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 <GL/gl.h>
24 #include "src/utils/win/SkWGL.h"
25
26 #include <windows.h>
27
28 namespace {
29
context_restorer()30 std::function<void()> context_restorer() {
31 auto glrc = wglGetCurrentContext();
32 auto dc = wglGetCurrentDC();
33 return [glrc, dc] { wglMakeCurrent(dc, glrc); };
34 }
35
36 class WinGLTestContext : public sk_gpu_test::GLTestContext {
37 public:
38 WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
39 ~WinGLTestContext() override;
40
41 private:
42 void destroyGLContext();
43
44 void onPlatformMakeNotCurrent() const override;
45 void onPlatformMakeCurrent() const override;
46 std::function<void()> onPlatformGetAutoContextRestore() 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
101 // We request a compatibility context since glMultiDrawArraysIndirect, apparently, doesn't
102 // work correctly on Intel Iris GPUs with the core profile (skbug.com/11787).
103 SkWGLContextRequest contextType =
104 kGLES_GrGLStandard == forcedGpuAPI ? kGLES_SkWGLContextRequest
105 : kGLPreferCompatibilityProfile_SkWGLContextRequest;
106
107 HGLRC winShareContext = nullptr;
108 if (shareContext) {
109 winShareContext = shareContext->fPbufferContext ? shareContext->fPbufferContext->getGLRC()
110 : shareContext->fGlRenderContext;
111 }
112 fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, contextType, winShareContext);
113
114 HDC dc;
115 HGLRC glrc;
116 if (nullptr == fPbufferContext) {
117 if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false, contextType,
118 winShareContext))) {
119 SkDebugf("Could not create rendering context.\n");
120 this->destroyGLContext();
121 return;
122 }
123 dc = fDeviceContext;
124 glrc = fGlRenderContext;
125 } else {
126 ReleaseDC(fWindow, fDeviceContext);
127 fDeviceContext = 0;
128 DestroyWindow(fWindow);
129 fWindow = 0;
130
131 dc = fPbufferContext->getDC();
132 glrc = fPbufferContext->getGLRC();
133 }
134
135 SkScopeExit restorer(context_restorer());
136 if (!(wglMakeCurrent(dc, glrc))) {
137 SkDebugf("Could not set the context.\n");
138 this->destroyGLContext();
139 return;
140 }
141
142 #ifdef SK_GL
143 auto gl = GrGLMakeNativeInterface();
144 if (!gl) {
145 SkDebugf("Could not create GL interface.\n");
146 this->destroyGLContext();
147 return;
148 }
149 if (!gl->validate()) {
150 SkDebugf("Could not validate GL interface.\n");
151 this->destroyGLContext();
152 return;
153 }
154
155 this->init(std::move(gl));
156 #else
157 // Allow the GLTestContext creation to succeed without a GrGLInterface to support
158 // GrContextFactory's persistent GL context workaround for Vulkan. We won't need the
159 // GrGLInterface since we're not running the GL backend.
160 this->init(nullptr);
161 #endif
162 }
163
~WinGLTestContext()164 WinGLTestContext::~WinGLTestContext() {
165 this->teardown();
166 this->destroyGLContext();
167 }
168
destroyGLContext()169 void WinGLTestContext::destroyGLContext() {
170 fPbufferContext = nullptr;
171 if (fGlRenderContext) {
172 // This deletes the context immediately even if it is current.
173 wglDeleteContext(fGlRenderContext);
174 fGlRenderContext = 0;
175 }
176 if (fWindow && fDeviceContext) {
177 ReleaseDC(fWindow, fDeviceContext);
178 fDeviceContext = 0;
179 }
180 if (fWindow) {
181 DestroyWindow(fWindow);
182 fWindow = 0;
183 }
184 }
185
onPlatformMakeNotCurrent() const186 void WinGLTestContext::onPlatformMakeNotCurrent() const {
187 if (!wglMakeCurrent(NULL, NULL)) {
188 SkDebugf("Could not null out the rendering context.\n");
189 }
190 }
191
onPlatformMakeCurrent() const192 void WinGLTestContext::onPlatformMakeCurrent() const {
193 HDC dc;
194 HGLRC glrc;
195
196 if (nullptr == fPbufferContext) {
197 dc = fDeviceContext;
198 glrc = fGlRenderContext;
199 } else {
200 dc = fPbufferContext->getDC();
201 glrc = fPbufferContext->getGLRC();
202 }
203
204 if (!wglMakeCurrent(dc, glrc)) {
205 SkDebugf("Could not make current.\n");
206 }
207 }
208
onPlatformGetAutoContextRestore() const209 std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
210 if (wglGetCurrentContext() == fGlRenderContext) {
211 return nullptr;
212 }
213 return context_restorer();
214 }
215
onPlatformGetProcAddress(const char * name) const216 GrGLFuncPtr WinGLTestContext::onPlatformGetProcAddress(const char* name) const {
217 return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name));
218 }
219
220 } // anonymous namespace
221
222 namespace sk_gpu_test {
CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,GLTestContext * shareContext)223 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
224 GLTestContext *shareContext) {
225 WinGLTestContext* winShareContext = reinterpret_cast<WinGLTestContext*>(shareContext);
226 WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI, winShareContext);
227 if (!ctx->isValid()) {
228 delete ctx;
229 return nullptr;
230 }
231 return ctx;
232 }
233 } // namespace sk_gpu_test
234
235 #endif
236