1cb93a386Sopenharmony_ci
2cb93a386Sopenharmony_ci/*
3cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
4cb93a386Sopenharmony_ci *
5cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
6cb93a386Sopenharmony_ci * found in the LICENSE file.
7cb93a386Sopenharmony_ci */
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#define EGL_EGL_PROTOTYPES 1
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include <EGL/egl.h>
12cb93a386Sopenharmony_ci#include <EGL/eglext.h>
13cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLAssembleInterface.h"
14cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLDefines.h"
15cb93a386Sopenharmony_ci#include "tools/sk_app/GLWindowContext.h"
16cb93a386Sopenharmony_ci#include "tools/sk_app/win/WindowContextFactory_win.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ciusing sk_app::GLWindowContext;
19cb93a386Sopenharmony_ciusing sk_app::DisplayParams;
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cinamespace {
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ciEGLDisplay get_angle_egl_display(HDC hdc) {
24cb93a386Sopenharmony_ci    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
25cb93a386Sopenharmony_ci    eglGetPlatformDisplayEXT =
26cb93a386Sopenharmony_ci            (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci    // We expect ANGLE to support this extension
29cb93a386Sopenharmony_ci    if (!eglGetPlatformDisplayEXT) {
30cb93a386Sopenharmony_ci        return EGL_NO_DISPLAY;
31cb93a386Sopenharmony_ci    }
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ci    // We currently only support D3D11 ANGLE.
34cb93a386Sopenharmony_ci    static constexpr EGLint kType = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
35cb93a386Sopenharmony_ci    static constexpr EGLint attribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, kType, EGL_NONE};
36cb93a386Sopenharmony_ci    return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, hdc, attribs);
37cb93a386Sopenharmony_ci}
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ciclass ANGLEGLWindowContext_win : public GLWindowContext {
40cb93a386Sopenharmony_cipublic:
41cb93a386Sopenharmony_ci    ANGLEGLWindowContext_win(HWND, const DisplayParams&);
42cb93a386Sopenharmony_ci    ~ANGLEGLWindowContext_win() override;
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ciprotected:
45cb93a386Sopenharmony_ci    void onSwapBuffers() override;
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    sk_sp<const GrGLInterface> onInitializeContext() override;
48cb93a386Sopenharmony_ci    void onDestroyContext() override;
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ciprivate:
51cb93a386Sopenharmony_ci    HWND fHWND;
52cb93a386Sopenharmony_ci    EGLDisplay fDisplay = EGL_NO_DISPLAY;
53cb93a386Sopenharmony_ci    EGLContext fEGLContext = EGL_NO_CONTEXT;
54cb93a386Sopenharmony_ci    EGLSurface fEGLSurface = EGL_NO_SURFACE;
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    using INHERITED = GLWindowContext;
57cb93a386Sopenharmony_ci};
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ciANGLEGLWindowContext_win::ANGLEGLWindowContext_win(HWND wnd, const DisplayParams& params)
60cb93a386Sopenharmony_ci        : INHERITED(params), fHWND(wnd) {
61cb93a386Sopenharmony_ci    this->initializeContext();
62cb93a386Sopenharmony_ci}
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ciANGLEGLWindowContext_win::~ANGLEGLWindowContext_win() { this->destroyContext(); }
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_cisk_sp<const GrGLInterface> ANGLEGLWindowContext_win::onInitializeContext() {
67cb93a386Sopenharmony_ci    HDC dc = GetDC(fHWND);
68cb93a386Sopenharmony_ci    fDisplay = get_angle_egl_display(dc);
69cb93a386Sopenharmony_ci    if (EGL_NO_DISPLAY == fDisplay) {
70cb93a386Sopenharmony_ci        return nullptr;
71cb93a386Sopenharmony_ci    }
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    EGLint majorVersion;
74cb93a386Sopenharmony_ci    EGLint minorVersion;
75cb93a386Sopenharmony_ci    if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
76cb93a386Sopenharmony_ci        SkDebugf("Could not initialize display!\n");
77cb93a386Sopenharmony_ci        return nullptr;
78cb93a386Sopenharmony_ci    }
79cb93a386Sopenharmony_ci    EGLint numConfigs;
80cb93a386Sopenharmony_ci    fSampleCount = this->getDisplayParams().fMSAASampleCount;
81cb93a386Sopenharmony_ci    const int sampleBuffers = fSampleCount > 1 ? 1 : 0;
82cb93a386Sopenharmony_ci    const int eglSampleCnt = fSampleCount > 1 ? fSampleCount : 0;
83cb93a386Sopenharmony_ci    const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE,
84cb93a386Sopenharmony_ci                                    // We currently only support ES3.
85cb93a386Sopenharmony_ci                                    EGL_OPENGL_ES3_BIT,
86cb93a386Sopenharmony_ci                                    EGL_RED_SIZE,
87cb93a386Sopenharmony_ci                                    8,
88cb93a386Sopenharmony_ci                                    EGL_GREEN_SIZE,
89cb93a386Sopenharmony_ci                                    8,
90cb93a386Sopenharmony_ci                                    EGL_BLUE_SIZE,
91cb93a386Sopenharmony_ci                                    8,
92cb93a386Sopenharmony_ci                                    EGL_ALPHA_SIZE,
93cb93a386Sopenharmony_ci                                    8,
94cb93a386Sopenharmony_ci                                    EGL_SAMPLE_BUFFERS,
95cb93a386Sopenharmony_ci                                    sampleBuffers,
96cb93a386Sopenharmony_ci                                    EGL_SAMPLES,
97cb93a386Sopenharmony_ci                                    eglSampleCnt,
98cb93a386Sopenharmony_ci                                    EGL_NONE};
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    EGLConfig surfaceConfig;
101cb93a386Sopenharmony_ci    if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
102cb93a386Sopenharmony_ci        SkDebugf("Could not create choose config!\n");
103cb93a386Sopenharmony_ci        return nullptr;
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci    // We currently only support ES3.
106cb93a386Sopenharmony_ci    const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
107cb93a386Sopenharmony_ci    fEGLContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
108cb93a386Sopenharmony_ci    if (EGL_NO_CONTEXT == fEGLContext) {
109cb93a386Sopenharmony_ci        SkDebugf("Could not create context!\n");
110cb93a386Sopenharmony_ci        return nullptr;
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci    fEGLSurface = eglCreateWindowSurface(fDisplay, surfaceConfig, fHWND, nullptr);
113cb93a386Sopenharmony_ci    if (EGL_NO_SURFACE == fEGLSurface) {
114cb93a386Sopenharmony_ci        SkDebugf("Could not create surface!\n");
115cb93a386Sopenharmony_ci        return nullptr;
116cb93a386Sopenharmony_ci    }
117cb93a386Sopenharmony_ci    if (!eglMakeCurrent(fDisplay, fEGLSurface, fEGLSurface, fEGLContext)) {
118cb93a386Sopenharmony_ci        SkDebugf("Could not make contxt current!\n");
119cb93a386Sopenharmony_ci        return nullptr;
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    sk_sp<const GrGLInterface> interface(GrGLMakeAssembledInterface(
123cb93a386Sopenharmony_ci            nullptr,
124cb93a386Sopenharmony_ci            [](void* ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); }));
125cb93a386Sopenharmony_ci    if (interface) {
126cb93a386Sopenharmony_ci        interface->fFunctions.fClearStencil(0);
127cb93a386Sopenharmony_ci        interface->fFunctions.fClearColor(0, 0, 0, 0);
128cb93a386Sopenharmony_ci        interface->fFunctions.fStencilMask(0xffffffff);
129cb93a386Sopenharmony_ci        interface->fFunctions.fClear(GR_GL_STENCIL_BUFFER_BIT | GR_GL_COLOR_BUFFER_BIT);
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci        // use DescribePixelFormat to get the stencil depth.
132cb93a386Sopenharmony_ci        int pixelFormat = GetPixelFormat(dc);
133cb93a386Sopenharmony_ci        PIXELFORMATDESCRIPTOR pfd;
134cb93a386Sopenharmony_ci        DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
135cb93a386Sopenharmony_ci        fStencilBits = pfd.cStencilBits;
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci        RECT rect;
138cb93a386Sopenharmony_ci        GetClientRect(fHWND, &rect);
139cb93a386Sopenharmony_ci        fWidth = rect.right - rect.left;
140cb93a386Sopenharmony_ci        fHeight = rect.bottom - rect.top;
141cb93a386Sopenharmony_ci        interface->fFunctions.fViewport(0, 0, fWidth, fHeight);
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci    return interface;
144cb93a386Sopenharmony_ci}
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_civoid ANGLEGLWindowContext_win::onDestroyContext() {
147cb93a386Sopenharmony_ci    eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
148cb93a386Sopenharmony_ci    if (EGL_NO_CONTEXT != fEGLContext) {
149cb93a386Sopenharmony_ci        eglDestroyContext(fDisplay, fEGLContext);
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    if (EGL_NO_SURFACE != fEGLSurface) {
152cb93a386Sopenharmony_ci        eglDestroySurface(fDisplay, fEGLSurface);
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci    if (EGL_NO_DISPLAY != fDisplay) {
155cb93a386Sopenharmony_ci        eglTerminate(fDisplay);
156cb93a386Sopenharmony_ci    }
157cb93a386Sopenharmony_ci}
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_civoid ANGLEGLWindowContext_win::onSwapBuffers() {
160cb93a386Sopenharmony_ci    if (!eglSwapBuffers(fDisplay, fEGLSurface)) {
161cb93a386Sopenharmony_ci        SkDebugf("Could not complete eglSwapBuffers.\n");
162cb93a386Sopenharmony_ci    }
163cb93a386Sopenharmony_ci}
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci}  // anonymous namespace
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_cinamespace sk_app {
168cb93a386Sopenharmony_cinamespace window_context_factory {
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_cistd::unique_ptr<WindowContext> MakeANGLEForWin(HWND wnd, const DisplayParams& params) {
171cb93a386Sopenharmony_ci    std::unique_ptr<WindowContext> ctx(new ANGLEGLWindowContext_win(wnd, params));
172cb93a386Sopenharmony_ci    if (!ctx->isValid()) {
173cb93a386Sopenharmony_ci        return nullptr;
174cb93a386Sopenharmony_ci    }
175cb93a386Sopenharmony_ci    return ctx;
176cb93a386Sopenharmony_ci}
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci}  // namespace window_context_factory
179cb93a386Sopenharmony_ci}  // namespace sk_app
180