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
17 namespace {
18
context_restorer()19 std::function<void()> context_restorer() {
20 auto glrc = wglGetCurrentContext();
21 auto dc = wglGetCurrentDC();
22 return [glrc, dc] { wglMakeCurrent(dc, glrc); };
23 }
24
25 class WinGLTestContext : public sk_gpu_test::GLTestContext {
26 public:
27 WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
28 ~WinGLTestContext() override;
29
30 private:
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
45 ATOM WinGLTestContext::gWC = 0;
46
WinGLTestContext(GrGLStandard forcedGpuAPI,WinGLTestContext * shareContext)47 WinGLTestContext::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
~WinGLTestContext()145 WinGLTestContext::~WinGLTestContext() {
146 this->teardown();
147 this->destroyGLContext();
148 }
149
destroyGLContext()150 void 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
onPlatformMakeCurrent() const167 void 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
onPlatformGetAutoContextRestore() const184 std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
185 if (wglGetCurrentContext() == fGlRenderContext) {
186 return nullptr;
187 }
188 return context_restorer();
189 }
190
onPlatformSwapBuffers() const191 void 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
onPlatformGetProcAddress(const char * name) const204 GrGLFuncPtr WinGLTestContext::onPlatformGetProcAddress(const char* name) const {
205 return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name));
206 }
207
208 } // anonymous namespace
209
210 namespace sk_gpu_test {
CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,GLTestContext * shareContext)211 GLTestContext* 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