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