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 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 57 ANGLEGLWindowContext_win::ANGLEGLWindowContext_win(HWND wnd, const DisplayParams& params) 58 : INHERITED(params), fHWND(wnd) { 59 this->initializeContext(); 60 } 61 62 ANGLEGLWindowContext_win::~ANGLEGLWindowContext_win() { this->destroyContext(); } 63 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 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 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 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