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
13 namespace sk_gpu_test {
14
CreatePlatformGLTestContext(GrGLStandard,GLTestContext *)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 "src/utils/win/SkWGL.h"
24
25 #include <windows.h>
26
27 namespace {
28
context_restorer()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 onPlatformMakeNotCurrent() const override;
44 void onPlatformMakeCurrent() const override;
45 std::function<void()> onPlatformGetAutoContextRestore() const override;
46 void onPlatformSwapBuffers() 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
56 ATOM WinGLTestContext::gWC = 0;
57
WinGLTestContext(GrGLStandard forcedGpuAPI,WinGLTestContext * shareContext)58 WinGLTestContext::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 // Requesting a Core profile would bar us from using NVPR. So we request
101 // compatibility profile or GL ES.
102 SkWGLContextRequest contextType =
103 kGLES_GrGLStandard == forcedGpuAPI ?
104 kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest;
105
106 HGLRC winShareContext = nullptr;
107 if (shareContext) {
108 winShareContext = shareContext->fPbufferContext ? shareContext->fPbufferContext->getGLRC()
109 : shareContext->fGlRenderContext;
110 }
111 fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, contextType, winShareContext);
112
113 HDC dc;
114 HGLRC glrc;
115 if (nullptr == fPbufferContext) {
116 if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false, contextType,
117 winShareContext))) {
118 SkDebugf("Could not create rendering context.\n");
119 this->destroyGLContext();
120 return;
121 }
122 dc = fDeviceContext;
123 glrc = fGlRenderContext;
124 } else {
125 ReleaseDC(fWindow, fDeviceContext);
126 fDeviceContext = 0;
127 DestroyWindow(fWindow);
128 fWindow = 0;
129
130 dc = fPbufferContext->getDC();
131 glrc = fPbufferContext->getGLRC();
132 }
133
134 SkScopeExit restorer(context_restorer());
135 if (!(wglMakeCurrent(dc, glrc))) {
136 SkDebugf("Could not set the context.\n");
137 this->destroyGLContext();
138 return;
139 }
140
141 auto gl = GrGLMakeNativeInterface();
142 if (!gl) {
143 SkDebugf("Could not create GL interface.\n");
144 this->destroyGLContext();
145 return;
146 }
147 if (!gl->validate()) {
148 SkDebugf("Could not validate GL interface.\n");
149 this->destroyGLContext();
150 return;
151 }
152
153 this->init(std::move(gl));
154 }
155
~WinGLTestContext()156 WinGLTestContext::~WinGLTestContext() {
157 this->teardown();
158 this->destroyGLContext();
159 }
160
destroyGLContext()161 void WinGLTestContext::destroyGLContext() {
162 fPbufferContext = nullptr;
163 if (fGlRenderContext) {
164 // This deletes the context immediately even if it is current.
165 wglDeleteContext(fGlRenderContext);
166 fGlRenderContext = 0;
167 }
168 if (fWindow && fDeviceContext) {
169 ReleaseDC(fWindow, fDeviceContext);
170 fDeviceContext = 0;
171 }
172 if (fWindow) {
173 DestroyWindow(fWindow);
174 fWindow = 0;
175 }
176 }
177
onPlatformMakeNotCurrent() const178 void WinGLTestContext::onPlatformMakeNotCurrent() const {
179 if (!wglMakeCurrent(NULL, NULL)) {
180 SkDebugf("Could not null out the rendering context.\n");
181 }
182 }
183
onPlatformMakeCurrent() const184 void WinGLTestContext::onPlatformMakeCurrent() const {
185 HDC dc;
186 HGLRC glrc;
187
188 if (nullptr == fPbufferContext) {
189 dc = fDeviceContext;
190 glrc = fGlRenderContext;
191 } else {
192 dc = fPbufferContext->getDC();
193 glrc = fPbufferContext->getGLRC();
194 }
195
196 if (!wglMakeCurrent(dc, glrc)) {
197 SkDebugf("Could not create rendering context.\n");
198 }
199 }
200
onPlatformGetAutoContextRestore() const201 std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
202 if (wglGetCurrentContext() == fGlRenderContext) {
203 return nullptr;
204 }
205 return context_restorer();
206 }
207
onPlatformSwapBuffers() const208 void WinGLTestContext::onPlatformSwapBuffers() const {
209 HDC dc;
210
211 if (nullptr == fPbufferContext) {
212 dc = fDeviceContext;
213 } else {
214 dc = fPbufferContext->getDC();
215 }
216 if (!SwapBuffers(dc)) {
217 SkDebugf("Could not complete SwapBuffers.\n");
218 }
219 }
220
onPlatformGetProcAddress(const char * name) const221 GrGLFuncPtr WinGLTestContext::onPlatformGetProcAddress(const char* name) const {
222 return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name));
223 }
224
225 } // anonymous namespace
226
227 namespace sk_gpu_test {
CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,GLTestContext * shareContext)228 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
229 GLTestContext *shareContext) {
230 WinGLTestContext* winShareContext = reinterpret_cast<WinGLTestContext*>(shareContext);
231 WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI, winShareContext);
232 if (!ctx->isValid()) {
233 delete ctx;
234 return nullptr;
235 }
236 return ctx;
237 }
238 } // namespace sk_gpu_test
239
240 #endif
241