• 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 <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