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