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