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 GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
47
48 HWND fWindow;
49 HDC fDeviceContext;
50 HGLRC fGlRenderContext;
51 static ATOM gWC;
52 sk_sp<SkWGLPbufferContext> fPbufferContext;
53 };
54
55 ATOM WinGLTestContext::gWC = 0;
56
WinGLTestContext(GrGLStandard forcedGpuAPI,WinGLTestContext * shareContext)57 WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext)
58 : fWindow(nullptr)
59 , fDeviceContext(nullptr)
60 , fGlRenderContext(nullptr)
61 , fPbufferContext(nullptr) {
62 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(nullptr);
63
64 if (!gWC) {
65 WNDCLASS wc;
66 wc.cbClsExtra = 0;
67 wc.cbWndExtra = 0;
68 wc.hbrBackground = nullptr;
69 wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
70 wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
71 wc.hInstance = hInstance;
72 wc.lpfnWndProc = (WNDPROC) DefWindowProc;
73 wc.lpszClassName = TEXT("Griffin");
74 wc.lpszMenuName = nullptr;
75 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
76
77 gWC = RegisterClass(&wc);
78 if (!gWC) {
79 SkDebugf("Could not register window class.\n");
80 return;
81 }
82 }
83
84 if (!(fWindow = CreateWindow(TEXT("Griffin"),
85 TEXT("The Invisible Man"),
86 WS_OVERLAPPEDWINDOW,
87 0, 0, 1, 1,
88 nullptr, nullptr,
89 hInstance, nullptr))) {
90 SkDebugf("Could not create window.\n");
91 return;
92 }
93
94 if (!(fDeviceContext = GetDC(fWindow))) {
95 SkDebugf("Could not get device context.\n");
96 this->destroyGLContext();
97 return;
98 }
99
100 // We request a compatibility context since glMultiDrawArraysIndirect, apparently, doesn't
101 // work correctly on Intel Iris GPUs with the core profile (skbug.com/11787).
102 SkWGLContextRequest contextType =
103 kGLES_GrGLStandard == forcedGpuAPI ? kGLES_SkWGLContextRequest
104 : 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 = nullptr;
127 DestroyWindow(fWindow);
128 fWindow = nullptr;
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 #ifdef SK_GL
142 auto gl = GrGLMakeNativeInterface();
143 if (!gl) {
144 SkDebugf("Could not create GL interface.\n");
145 this->destroyGLContext();
146 return;
147 }
148 if (!gl->validate()) {
149 SkDebugf("Could not validate GL interface.\n");
150 this->destroyGLContext();
151 return;
152 }
153
154 this->init(std::move(gl));
155 #else
156 // Allow the GLTestContext creation to succeed without a GrGLInterface to support
157 // GrContextFactory's persistent GL context workaround for Vulkan. We won't need the
158 // GrGLInterface since we're not running the GL backend.
159 this->init(nullptr);
160 #endif
161 }
162
~WinGLTestContext()163 WinGLTestContext::~WinGLTestContext() {
164 this->teardown();
165 this->destroyGLContext();
166 }
167
destroyGLContext()168 void WinGLTestContext::destroyGLContext() {
169 fPbufferContext = nullptr;
170 if (fGlRenderContext) {
171 // This deletes the context immediately even if it is current.
172 wglDeleteContext(fGlRenderContext);
173 fGlRenderContext = nullptr;
174 }
175 if (fWindow && fDeviceContext) {
176 ReleaseDC(fWindow, fDeviceContext);
177 fDeviceContext = nullptr;
178 }
179 if (fWindow) {
180 DestroyWindow(fWindow);
181 fWindow = nullptr;
182 }
183 }
184
onPlatformMakeNotCurrent() const185 void WinGLTestContext::onPlatformMakeNotCurrent() const {
186 if (!wglMakeCurrent(nullptr, nullptr)) {
187 SkDebugf("Could not null out the rendering context.\n");
188 }
189 }
190
onPlatformMakeCurrent() const191 void WinGLTestContext::onPlatformMakeCurrent() const {
192 HDC dc;
193 HGLRC glrc;
194
195 if (nullptr == fPbufferContext) {
196 dc = fDeviceContext;
197 glrc = fGlRenderContext;
198 } else {
199 dc = fPbufferContext->getDC();
200 glrc = fPbufferContext->getGLRC();
201 }
202
203 if (!wglMakeCurrent(dc, glrc)) {
204 SkDebugf("Could not make current.\n");
205 }
206 }
207
onPlatformGetAutoContextRestore() const208 std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
209 if (wglGetCurrentContext() == fGlRenderContext) {
210 return nullptr;
211 }
212 return context_restorer();
213 }
214
onPlatformGetProcAddress(const char * name) const215 GrGLFuncPtr WinGLTestContext::onPlatformGetProcAddress(const char* name) const {
216 return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name));
217 }
218
219 } // anonymous namespace
220
221 namespace sk_gpu_test {
CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,GLTestContext * shareContext)222 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
223 GLTestContext *shareContext) {
224 WinGLTestContext* winShareContext = reinterpret_cast<WinGLTestContext*>(shareContext);
225 WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI, winShareContext);
226 if (!ctx->isValid()) {
227 delete ctx;
228 return nullptr;
229 }
230 return ctx;
231 }
232 } // namespace sk_gpu_test
233
234 #endif
235