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