1 2 /* 3 * Copyright 2011 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 "gl/GLTestContext.h" 10 11 #if defined(_M_ARM64) 12 13 namespace sk_gpu_test { 14 15 GLTestContext* CreatePlatformGLTestContext(GrGLStandard, GLTestContext*) { return nullptr; } 16 17 } // namespace sk_gpu_test 18 19 #else 20 21 #include <windows.h> 22 #include <GL/GL.h> 23 #include "win/SkWGL.h" 24 25 #include <windows.h> 26 27 namespace { 28 29 std::function<void()> context_restorer() { 30 auto glrc = wglGetCurrentContext(); 31 auto dc = wglGetCurrentDC(); 32 return [glrc, dc] { wglMakeCurrent(dc, glrc); }; 33 } 34 35 class WinGLTestContext : public sk_gpu_test::GLTestContext { 36 public: 37 WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext); 38 ~WinGLTestContext() override; 39 40 private: 41 void destroyGLContext(); 42 43 void onPlatformMakeCurrent() const override; 44 std::function<void()> onPlatformGetAutoContextRestore() const override; 45 void onPlatformSwapBuffers() const override; 46 GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override; 47 48 HWND fWindow; 49 HDC fDeviceContext; 50 HGLRC fGlRenderContext; 51 static ATOM gWC; 52 sk_sp<SkWGLPbufferContext> fPbufferContext; 53 }; 54 55 ATOM WinGLTestContext::gWC = 0; 56 57 WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext) 58 : fWindow(nullptr) 59 , fDeviceContext(nullptr) 60 , fGlRenderContext(0) 61 , fPbufferContext(nullptr) { 62 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(nullptr); 63 64 if (!gWC) { 65 WNDCLASS wc; 66 wc.cbClsExtra = 0; 67 wc.cbWndExtra = 0; 68 wc.hbrBackground = nullptr; 69 wc.hCursor = LoadCursor(nullptr, IDC_ARROW); 70 wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION); 71 wc.hInstance = hInstance; 72 wc.lpfnWndProc = (WNDPROC) DefWindowProc; 73 wc.lpszClassName = TEXT("Griffin"); 74 wc.lpszMenuName = nullptr; 75 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 76 77 gWC = RegisterClass(&wc); 78 if (!gWC) { 79 SkDebugf("Could not register window class.\n"); 80 return; 81 } 82 } 83 84 if (!(fWindow = CreateWindow(TEXT("Griffin"), 85 TEXT("The Invisible Man"), 86 WS_OVERLAPPEDWINDOW, 87 0, 0, 1, 1, 88 nullptr, nullptr, 89 hInstance, nullptr))) { 90 SkDebugf("Could not create window.\n"); 91 return; 92 } 93 94 if (!(fDeviceContext = GetDC(fWindow))) { 95 SkDebugf("Could not get device context.\n"); 96 this->destroyGLContext(); 97 return; 98 } 99 // Requesting a Core profile would bar us from using NVPR. So we request 100 // compatibility profile or GL ES. 101 SkWGLContextRequest contextType = 102 kGLES_GrGLStandard == forcedGpuAPI ? 103 kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest; 104 105 HGLRC winShareContext = nullptr; 106 if (shareContext) { 107 winShareContext = shareContext->fPbufferContext ? shareContext->fPbufferContext->getGLRC() 108 : shareContext->fGlRenderContext; 109 } 110 fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, contextType, winShareContext); 111 112 HDC dc; 113 HGLRC glrc; 114 if (nullptr == fPbufferContext) { 115 if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false, contextType, 116 winShareContext))) { 117 SkDebugf("Could not create rendering context.\n"); 118 this->destroyGLContext(); 119 return; 120 } 121 dc = fDeviceContext; 122 glrc = fGlRenderContext; 123 } else { 124 ReleaseDC(fWindow, fDeviceContext); 125 fDeviceContext = 0; 126 DestroyWindow(fWindow); 127 fWindow = 0; 128 129 dc = fPbufferContext->getDC(); 130 glrc = fPbufferContext->getGLRC(); 131 } 132 133 SkScopeExit restorer(context_restorer()); 134 if (!(wglMakeCurrent(dc, glrc))) { 135 SkDebugf("Could not set the context.\n"); 136 this->destroyGLContext(); 137 return; 138 } 139 140 auto gl = GrGLMakeNativeInterface(); 141 if (!gl) { 142 SkDebugf("Could not create GL interface.\n"); 143 this->destroyGLContext(); 144 return; 145 } 146 if (!gl->validate()) { 147 SkDebugf("Could not validate GL interface.\n"); 148 this->destroyGLContext(); 149 return; 150 } 151 152 this->init(std::move(gl)); 153 } 154 155 WinGLTestContext::~WinGLTestContext() { 156 this->teardown(); 157 this->destroyGLContext(); 158 } 159 160 void WinGLTestContext::destroyGLContext() { 161 fPbufferContext = nullptr; 162 if (fGlRenderContext) { 163 // This deletes the context immediately even if it is current. 164 wglDeleteContext(fGlRenderContext); 165 fGlRenderContext = 0; 166 } 167 if (fWindow && fDeviceContext) { 168 ReleaseDC(fWindow, fDeviceContext); 169 fDeviceContext = 0; 170 } 171 if (fWindow) { 172 DestroyWindow(fWindow); 173 fWindow = 0; 174 } 175 } 176 177 void WinGLTestContext::onPlatformMakeCurrent() const { 178 HDC dc; 179 HGLRC glrc; 180 181 if (nullptr == fPbufferContext) { 182 dc = fDeviceContext; 183 glrc = fGlRenderContext; 184 } else { 185 dc = fPbufferContext->getDC(); 186 glrc = fPbufferContext->getGLRC(); 187 } 188 189 if (!wglMakeCurrent(dc, glrc)) { 190 SkDebugf("Could not create rendering context.\n"); 191 } 192 } 193 194 std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const { 195 if (wglGetCurrentContext() == fGlRenderContext) { 196 return nullptr; 197 } 198 return context_restorer(); 199 } 200 201 void WinGLTestContext::onPlatformSwapBuffers() const { 202 HDC dc; 203 204 if (nullptr == fPbufferContext) { 205 dc = fDeviceContext; 206 } else { 207 dc = fPbufferContext->getDC(); 208 } 209 if (!SwapBuffers(dc)) { 210 SkDebugf("Could not complete SwapBuffers.\n"); 211 } 212 } 213 214 GrGLFuncPtr WinGLTestContext::onPlatformGetProcAddress(const char* name) const { 215 return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name)); 216 } 217 218 } // anonymous namespace 219 220 namespace sk_gpu_test { 221 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, 222 GLTestContext *shareContext) { 223 WinGLTestContext* winShareContext = reinterpret_cast<WinGLTestContext*>(shareContext); 224 WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI, winShareContext); 225 if (!ctx->isValid()) { 226 delete ctx; 227 return nullptr; 228 } 229 return ctx; 230 } 231 } // namespace sk_gpu_test 232 233 #endif 234