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