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