• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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