blob: 8cc889215f1a3798612622bf71063bb045d1aec0 [file] [log] [blame]
bsalomon@google.combd7c6412011-12-01 16:34:28 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkTypes.h"
Brian Osman0c757272018-12-10 10:27:26 -05009#if defined(SK_BUILD_FOR_WIN) && !defined(_M_ARM64)
mtklein1ee76512015-11-02 10:20:27 -080010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/utils/win/SkWGL.h"
bsalomon@google.combd7c6412011-12-01 16:34:28 +000012
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/private/SkOnce.h"
14#include "include/private/SkTDArray.h"
Ben Wagner8bd6e8f2019-05-15 09:28:52 -040015#include "src/core/SkTSearch.h"
bsalomon@google.com8a189b02012-04-17 12:43:00 +000016
bsalomon@google.combd7c6412011-12-01 16:34:28 +000017bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
halcanary96fcdcc2015-08-27 07:41:13 -070018 if (nullptr == this->fGetExtensionsString) {
bsalomon@google.combd7c6412011-12-01 16:34:28 +000019 return false;
20 }
21 if (!strcmp("WGL_ARB_extensions_string", ext)) {
22 return true;
23 }
24 const char* extensionString = this->getExtensionsString(dc);
robertphillips@google.comadacc702013-10-14 21:53:24 +000025 size_t extLength = strlen(ext);
bsalomon@google.combd7c6412011-12-01 16:34:28 +000026
27 while (true) {
robertphillips@google.comadacc702013-10-14 21:53:24 +000028 size_t n = strcspn(extensionString, " ");
bsalomon@google.combd7c6412011-12-01 16:34:28 +000029 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
30 return true;
31 }
32 if (0 == extensionString[n]) {
33 return false;
34 }
35 extensionString += n+1;
36 }
37
38 return false;
39}
40
41const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
42 return fGetExtensionsString(hdc);
43}
44
45BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
46 const int* piAttribIList,
47 const FLOAT* pfAttribFList,
48 UINT nMaxFormats,
49 int* piFormats,
50 UINT* nNumFormats) const {
51 return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
52 nMaxFormats, piFormats, nNumFormats);
53}
54
55BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
56 int iPixelFormat,
57 int iLayerPlane,
58 UINT nAttributes,
59 const int *piAttributes,
60 int *piValues) const {
61 return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
62 nAttributes, piAttributes, piValues);
63}
64
65BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
66 int iPixelFormat,
67 int iLayerPlane,
68 UINT nAttributes,
69 const int *piAttributes,
70 float *pfValues) const {
71 return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
72 nAttributes, piAttributes, pfValues);
73}
74HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
75 HGLRC hShareContext,
76 const int *attribList) const {
77 return fCreateContextAttribs(hDC, hShareContext, attribList);
78}
79
bsalomon9245b7e2014-07-01 07:20:11 -070080BOOL SkWGLExtensions::swapInterval(int interval) const {
81 return fSwapInterval(interval);
82}
83
84HPBUFFER SkWGLExtensions::createPbuffer(HDC hDC,
85 int iPixelFormat,
86 int iWidth,
87 int iHeight,
88 const int *piAttribList) const {
89 return fCreatePbuffer(hDC, iPixelFormat, iWidth, iHeight, piAttribList);
90}
91
92HDC SkWGLExtensions::getPbufferDC(HPBUFFER hPbuffer) const {
93 return fGetPbufferDC(hPbuffer);
94}
95
96int SkWGLExtensions::releasePbufferDC(HPBUFFER hPbuffer, HDC hDC) const {
97 return fReleasePbufferDC(hPbuffer, hDC);
98}
99
100BOOL SkWGLExtensions::destroyPbuffer(HPBUFFER hPbuffer) const {
101 return fDestroyPbuffer(hPbuffer);
102}
103
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000104namespace {
105
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000106struct PixelFormat {
107 int fFormat;
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000108 int fSampleCnt;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000109 int fChoosePixelFormatRank;
110};
111
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000112bool pf_less(const PixelFormat& a, const PixelFormat& b) {
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000113 if (a.fSampleCnt < b.fSampleCnt) {
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000114 return true;
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000115 } else if (b.fSampleCnt < a.fSampleCnt) {
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000116 return false;
117 } else if (a.fChoosePixelFormatRank < b.fChoosePixelFormatRank) {
118 return true;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000119 }
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000120 return false;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000121}
122}
123
124int SkWGLExtensions::selectFormat(const int formats[],
125 int formatCount,
126 HDC dc,
bsalomon9245b7e2014-07-01 07:20:11 -0700127 int desiredSampleCount) const {
Brian Salomonbdecacf2018-02-02 20:32:49 -0500128 SkASSERT(desiredSampleCount >= 1);
aleksandar.stojiljkovic2944fbb2015-11-05 07:48:12 -0800129 if (formatCount <= 0) {
130 return -1;
131 }
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000132 PixelFormat desiredFormat = {
133 0,
134 desiredSampleCount,
135 0,
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000136 };
137 SkTDArray<PixelFormat> rankedFormats;
138 rankedFormats.setCount(formatCount);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000139 for (int i = 0; i < formatCount; ++i) {
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000140 static const int kQueryAttr = SK_WGL_SAMPLES;
141 int numSamples;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000142 this->getPixelFormatAttribiv(dc,
143 formats[i],
144 0,
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000145 1,
146 &kQueryAttr,
147 &numSamples);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000148 rankedFormats[i].fFormat = formats[i];
Brian Osman788b9162020-02-07 10:36:46 -0500149 rankedFormats[i].fSampleCnt = std::max(1, numSamples);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000150 rankedFormats[i].fChoosePixelFormatRank = i;
151 }
John Stiles70474c12020-07-13 18:09:07 -0400152 std::sort(rankedFormats.begin(), rankedFormats.end(), pf_less);
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000153 int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(),
154 rankedFormats.count(),
155 desiredFormat,
156 sizeof(PixelFormat));
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000157 if (idx < 0) {
158 idx = ~idx;
159 }
Brian Salomonbdecacf2018-02-02 20:32:49 -0500160 // If the caller asked for non-MSAA fail if the closest format has MSAA.
161 if (desiredSampleCount == 1 && rankedFormats[idx].fSampleCnt != 1) {
162 return -1;
163 }
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000164 return rankedFormats[idx].fFormat;
165}
166
167
168namespace {
169
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000170#if defined(UNICODE)
171 #define STR_LIT(X) L## #X
172#else
173 #define STR_LIT(X) #X
174#endif
175
176#define DUMMY_CLASS STR_LIT("DummyClass")
177
178HWND create_dummy_window() {
halcanary96fcdcc2015-08-27 07:41:13 -0700179 HMODULE module = GetModuleHandle(nullptr);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000180 HWND dummy;
181 RECT windowRect;
182 windowRect.left = 0;
183 windowRect.right = 8;
184 windowRect.top = 0;
185 windowRect.bottom = 8;
186
187 WNDCLASS wc;
188
189 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
190 wc.lpfnWndProc = (WNDPROC) DefWindowProc;
191 wc.cbClsExtra = 0;
192 wc.cbWndExtra = 0;
193 wc.hInstance = module;
halcanary96fcdcc2015-08-27 07:41:13 -0700194 wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
195 wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
196 wc.hbrBackground = nullptr;
197 wc.lpszMenuName = nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000198 wc.lpszClassName = DUMMY_CLASS;
199
200 if(!RegisterClass(&wc)) {
201 return 0;
202 }
203
204 DWORD style, exStyle;
205 exStyle = WS_EX_CLIENTEDGE;
206 style = WS_SYSMENU;
207
208 AdjustWindowRectEx(&windowRect, style, false, exStyle);
209 if(!(dummy = CreateWindowEx(exStyle,
210 DUMMY_CLASS,
211 STR_LIT("DummyWindow"),
212 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
213 0, 0,
214 windowRect.right-windowRect.left,
215 windowRect.bottom-windowRect.top,
halcanary96fcdcc2015-08-27 07:41:13 -0700216 nullptr, nullptr,
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000217 module,
halcanary96fcdcc2015-08-27 07:41:13 -0700218 nullptr))) {
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000219 UnregisterClass(DUMMY_CLASS, module);
halcanary96fcdcc2015-08-27 07:41:13 -0700220 return nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000221 }
222 ShowWindow(dummy, SW_HIDE);
223
224 return dummy;
225}
226
227void destroy_dummy_window(HWND dummy) {
228 DestroyWindow(dummy);
halcanary96fcdcc2015-08-27 07:41:13 -0700229 HMODULE module = GetModuleHandle(nullptr);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000230 UnregisterClass(DUMMY_CLASS, module);
231}
232}
233
234#define GET_PROC(NAME, SUFFIX) f##NAME = \
Mike Kleinc722f792017-07-31 11:57:21 -0400235 (NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000236
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000237
Brian Osman6269f712017-08-16 15:14:59 -0400238SkWGLExtensions::GetExtensionsStringProc SkWGLExtensions::fGetExtensionsString = nullptr;
239SkWGLExtensions::ChoosePixelFormatProc SkWGLExtensions::fChoosePixelFormat = nullptr;
240SkWGLExtensions::GetPixelFormatAttribfvProc SkWGLExtensions::fGetPixelFormatAttribfv = nullptr;
241SkWGLExtensions::GetPixelFormatAttribivProc SkWGLExtensions::fGetPixelFormatAttribiv = nullptr;
242SkWGLExtensions::CreateContextAttribsProc SkWGLExtensions::fCreateContextAttribs = nullptr;
243SkWGLExtensions::SwapIntervalProc SkWGLExtensions::fSwapInterval = nullptr;
244SkWGLExtensions::CreatePbufferProc SkWGLExtensions::fCreatePbuffer = nullptr;
245SkWGLExtensions::GetPbufferDCProc SkWGLExtensions::fGetPbufferDC = nullptr;
246SkWGLExtensions::ReleasePbufferDCProc SkWGLExtensions::fReleasePbufferDC = nullptr;
247SkWGLExtensions::DestroyPbufferProc SkWGLExtensions::fDestroyPbuffer = nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000248
Brian Osman6269f712017-08-16 15:14:59 -0400249SkWGLExtensions::SkWGLExtensions() {
250 // We cache these function pointers once, and then reuse them. That's possibly incorrect if
251 // there are multiple GPUs, or if we intend to use these for rendering contexts of different
252 // pixel formats (where wglGetProcAddress is not guaranteed to return the same pointer).
253 static SkOnce once;
254 once([] {
255 HDC prevDC = wglGetCurrentDC();
256 HGLRC prevGLRC = wglGetCurrentContext();
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000257
Brian Osman6269f712017-08-16 15:14:59 -0400258 PIXELFORMATDESCRIPTOR dummyPFD;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000259
Brian Osman6269f712017-08-16 15:14:59 -0400260 ZeroMemory(&dummyPFD, sizeof(dummyPFD));
261 dummyPFD.nSize = sizeof(dummyPFD);
262 dummyPFD.nVersion = 1;
263 dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
264 dummyPFD.iPixelType = PFD_TYPE_RGBA;
265 dummyPFD.cColorBits = 32;
266 dummyPFD.cDepthBits = 0;
267 dummyPFD.cStencilBits = 8;
268 dummyPFD.iLayerType = PFD_MAIN_PLANE;
269 HWND dummyWND = create_dummy_window();
270 if (dummyWND) {
271 HDC dummyDC = GetDC(dummyWND);
272 int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
273 SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
274 HGLRC dummyGLRC = wglCreateContext(dummyDC);
275 SkASSERT(dummyGLRC);
276 wglMakeCurrent(dummyDC, dummyGLRC);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000277
Brian Osman6269f712017-08-16 15:14:59 -0400278 GET_PROC(GetExtensionsString, ARB);
279 GET_PROC(ChoosePixelFormat, ARB);
280 GET_PROC(GetPixelFormatAttribiv, ARB);
281 GET_PROC(GetPixelFormatAttribfv, ARB);
282 GET_PROC(CreateContextAttribs, ARB);
283 GET_PROC(SwapInterval, EXT);
284 GET_PROC(CreatePbuffer, ARB);
285 GET_PROC(GetPbufferDC, ARB);
286 GET_PROC(ReleasePbufferDC, ARB);
287 GET_PROC(DestroyPbuffer, ARB);
288
289 wglMakeCurrent(dummyDC, nullptr);
290 wglDeleteContext(dummyGLRC);
291 destroy_dummy_window(dummyWND);
292 }
293
294 wglMakeCurrent(prevDC, prevGLRC);
295 });
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000296}
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000297
bsalomon9245b7e2014-07-01 07:20:11 -0700298///////////////////////////////////////////////////////////////////////////////
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000299
bsalomon9245b7e2014-07-01 07:20:11 -0700300static void get_pixel_formats_to_try(HDC dc, const SkWGLExtensions& extensions,
brianosman2d1ee792016-05-05 12:24:31 -0700301 bool doubleBuffered, int msaaSampleCount, bool deepColor,
bsalomon9245b7e2014-07-01 07:20:11 -0700302 int formatsToTry[2]) {
brianosman2d1ee792016-05-05 12:24:31 -0700303 auto appendAttr = [](SkTDArray<int>& attrs, int attr, int value) {
Mike Reedb5475792018-08-08 16:17:42 -0400304 attrs.push_back(attr);
305 attrs.push_back(value);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000306 };
307
brianosman2d1ee792016-05-05 12:24:31 -0700308 SkTDArray<int> iAttrs;
309 appendAttr(iAttrs, SK_WGL_DRAW_TO_WINDOW, TRUE);
310 appendAttr(iAttrs, SK_WGL_DOUBLE_BUFFER, (doubleBuffered ? TRUE : FALSE));
311 appendAttr(iAttrs, SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION);
312 appendAttr(iAttrs, SK_WGL_SUPPORT_OPENGL, TRUE);
313 if (deepColor) {
314 appendAttr(iAttrs, SK_WGL_RED_BITS, 10);
315 appendAttr(iAttrs, SK_WGL_GREEN_BITS, 10);
316 appendAttr(iAttrs, SK_WGL_BLUE_BITS, 10);
317 appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 2);
318 } else {
319 appendAttr(iAttrs, SK_WGL_COLOR_BITS, 24);
320 appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 8);
321 }
322 appendAttr(iAttrs, SK_WGL_STENCIL_BITS, 8);
323
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000324 float fAttrs[] = {0, 0};
325
bsalomon9245b7e2014-07-01 07:20:11 -0700326 // Get a MSAA format if requested and possible.
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000327 if (msaaSampleCount > 0 &&
328 extensions.hasExtension(dc, "WGL_ARB_multisample")) {
brianosman2d1ee792016-05-05 12:24:31 -0700329 SkTDArray<int> msaaIAttrs = iAttrs;
330 appendAttr(msaaIAttrs, SK_WGL_SAMPLE_BUFFERS, TRUE);
331 appendAttr(msaaIAttrs, SK_WGL_SAMPLES, msaaSampleCount);
332 appendAttr(msaaIAttrs, 0, 0);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000333 unsigned int num;
334 int formats[64];
brianosman2d1ee792016-05-05 12:24:31 -0700335 extensions.choosePixelFormat(dc, msaaIAttrs.begin(), fAttrs, 64, formats, &num);
Brian Osman788b9162020-02-07 10:36:46 -0500336 num = std::min(num, 64U);
bsalomon9245b7e2014-07-01 07:20:11 -0700337 formatsToTry[0] = extensions.selectFormat(formats, num, dc, msaaSampleCount);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000338 }
339
bsalomon9245b7e2014-07-01 07:20:11 -0700340 // Get a non-MSAA format
341 int* format = -1 == formatsToTry[0] ? &formatsToTry[0] : &formatsToTry[1];
342 unsigned int num;
brianosman2d1ee792016-05-05 12:24:31 -0700343 appendAttr(iAttrs, 0, 0);
344 extensions.choosePixelFormat(dc, iAttrs.begin(), fAttrs, 1, format, &num);
bsalomon9245b7e2014-07-01 07:20:11 -0700345}
346
Brian Osman6269f712017-08-16 15:14:59 -0400347static HGLRC create_gl_context(HDC dc, const SkWGLExtensions& extensions,
348 SkWGLContextRequest contextType, HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700349 HDC prevDC = wglGetCurrentDC();
350 HGLRC prevGLRC = wglGetCurrentContext();
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000351
halcanary96fcdcc2015-08-27 07:41:13 -0700352 HGLRC glrc = nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700353 if (kGLES_SkWGLContextRequest == contextType) {
354 if (!extensions.hasExtension(dc, "WGL_EXT_create_context_es2_profile")) {
bsalomon9245b7e2014-07-01 07:20:11 -0700355 wglMakeCurrent(prevDC, prevGLRC);
halcanary96fcdcc2015-08-27 07:41:13 -0700356 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700357 }
358 static const int glesAttribs[] = {
359 SK_WGL_CONTEXT_MAJOR_VERSION, 3,
360 SK_WGL_CONTEXT_MINOR_VERSION, 0,
361 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_ES2_PROFILE_BIT,
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000362 0,
363 };
Brian Osman60c774d2017-02-21 16:58:08 -0500364 glrc = extensions.createContextAttribs(dc, shareContext, glesAttribs);
halcanary96fcdcc2015-08-27 07:41:13 -0700365 if (nullptr == glrc) {
bsalomon9245b7e2014-07-01 07:20:11 -0700366 wglMakeCurrent(prevDC, prevGLRC);
halcanary96fcdcc2015-08-27 07:41:13 -0700367 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700368 }
369 } else {
370 if (kGLPreferCoreProfile_SkWGLContextRequest == contextType &&
371 extensions.hasExtension(dc, "WGL_ARB_create_context")) {
372 static const int kCoreGLVersions[] = {
373 4, 3,
374 4, 2,
375 4, 1,
376 4, 0,
377 3, 3,
378 3, 2,
379 };
380 int coreProfileAttribs[] = {
381 SK_WGL_CONTEXT_MAJOR_VERSION, -1,
382 SK_WGL_CONTEXT_MINOR_VERSION, -1,
383 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT,
384 0,
385 };
Chris Dalton1ef80942017-12-04 12:01:30 -0700386 for (size_t v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) {
kkinnunen80549fc2014-06-30 06:36:31 -0700387 coreProfileAttribs[1] = kCoreGLVersions[2 * v];
388 coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1];
Brian Osman60c774d2017-02-21 16:58:08 -0500389 glrc = extensions.createContextAttribs(dc, shareContext, coreProfileAttribs);
bsalomon49f085d2014-09-05 13:34:00 -0700390 if (glrc) {
kkinnunen80549fc2014-06-30 06:36:31 -0700391 break;
392 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000393 }
394 }
395 }
396
halcanary96fcdcc2015-08-27 07:41:13 -0700397 if (nullptr == glrc) {
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000398 glrc = wglCreateContext(dc);
Brian Osman60c774d2017-02-21 16:58:08 -0500399 if (shareContext) {
400 if (!wglShareLists(shareContext, glrc)) {
401 wglDeleteContext(glrc);
402 return nullptr;
403 }
404 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000405 }
406 SkASSERT(glrc);
407
408 wglMakeCurrent(prevDC, prevGLRC);
bsalomon9245b7e2014-07-01 07:20:11 -0700409
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000410 return glrc;
411}
bsalomon9245b7e2014-07-01 07:20:11 -0700412
brianosman2d1ee792016-05-05 12:24:31 -0700413HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool deepColor,
Brian Osman60c774d2017-02-21 16:58:08 -0500414 SkWGLContextRequest contextType, HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700415 SkWGLExtensions extensions;
416 if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
halcanary96fcdcc2015-08-27 07:41:13 -0700417 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700418 }
419
420 BOOL set = FALSE;
421
422 int pixelFormatsToTry[] = { -1, -1 };
brianosman2d1ee792016-05-05 12:24:31 -0700423 get_pixel_formats_to_try(dc, extensions, true, msaaSampleCount, deepColor, pixelFormatsToTry);
Chris Dalton1ef80942017-12-04 12:01:30 -0700424 for (size_t f = 0;
bsalomon9245b7e2014-07-01 07:20:11 -0700425 !set && -1 != pixelFormatsToTry[f] && f < SK_ARRAY_COUNT(pixelFormatsToTry);
426 ++f) {
427 PIXELFORMATDESCRIPTOR pfd;
428 DescribePixelFormat(dc, pixelFormatsToTry[f], sizeof(pfd), &pfd);
429 set = SetPixelFormat(dc, pixelFormatsToTry[f], &pfd);
430 }
431
432 if (!set) {
halcanary96fcdcc2015-08-27 07:41:13 -0700433 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700434 }
435
Brian Osman60c774d2017-02-21 16:58:08 -0500436 return create_gl_context(dc, extensions, contextType, shareContext);
437}
bsalomon9245b7e2014-07-01 07:20:11 -0700438
Ben Wagner9ec70c62018-07-12 13:30:47 -0400439sk_sp<SkWGLPbufferContext> SkWGLPbufferContext::Create(HDC parentDC,
440 SkWGLContextRequest contextType,
441 HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700442 SkWGLExtensions extensions;
443 if (!extensions.hasExtension(parentDC, "WGL_ARB_pixel_format") ||
444 !extensions.hasExtension(parentDC, "WGL_ARB_pbuffer")) {
halcanary96fcdcc2015-08-27 07:41:13 -0700445 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700446 }
447
Brian Osmande3b7102017-08-17 12:58:28 -0400448 // We cache the pixel formats once, and then reuse them. That's possibly incorrect if
449 // there are multiple GPUs, but this function is always called with a freshly made,
450 // identically constructed HDC (see WinGLTestContext).
451 //
452 // We only store two potential pixel formats, one for single buffer, one for double buffer.
453 // We never ask for MSAA, so we don't need the second pixel format for each buffering state.
454 static int gPixelFormats[2] = { -1, -1 };
455 static SkOnce once;
456 once([=] {
457 {
458 // Single buffer
459 int pixelFormatsToTry[2] = { -1, -1 };
460 get_pixel_formats_to_try(parentDC, extensions, false, 0, false, pixelFormatsToTry);
461 gPixelFormats[0] = pixelFormatsToTry[0];
462 }
463 {
464 // Double buffer
465 int pixelFormatsToTry[2] = { -1, -1 };
466 get_pixel_formats_to_try(parentDC, extensions, true, 0, false, pixelFormatsToTry);
467 gPixelFormats[1] = pixelFormatsToTry[0];
468 }
469 });
470
bsalomon9245b7e2014-07-01 07:20:11 -0700471 // try for single buffer first
Brian Osmande3b7102017-08-17 12:58:28 -0400472 for (int pixelFormat : gPixelFormats) {
473 if (-1 == pixelFormat) {
474 continue;
475 }
476 HPBUFFER pbuf = extensions.createPbuffer(parentDC, pixelFormat, 1, 1, nullptr);
477 if (0 != pbuf) {
478 HDC dc = extensions.getPbufferDC(pbuf);
479 if (dc) {
480 HGLRC glrc = create_gl_context(dc, extensions, contextType, shareContext);
481 if (glrc) {
Ben Wagner9ec70c62018-07-12 13:30:47 -0400482 return sk_sp<SkWGLPbufferContext>(new SkWGLPbufferContext(pbuf, dc, glrc));
bsalomon9245b7e2014-07-01 07:20:11 -0700483 }
Brian Osmande3b7102017-08-17 12:58:28 -0400484 extensions.releasePbufferDC(pbuf, dc);
bsalomon9245b7e2014-07-01 07:20:11 -0700485 }
Brian Osmande3b7102017-08-17 12:58:28 -0400486 extensions.destroyPbuffer(pbuf);
bsalomon9245b7e2014-07-01 07:20:11 -0700487 }
488 }
halcanary96fcdcc2015-08-27 07:41:13 -0700489 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700490}
491
492SkWGLPbufferContext::~SkWGLPbufferContext() {
493 SkASSERT(fExtensions.hasExtension(fDC, "WGL_ARB_pbuffer"));
494 wglDeleteContext(fGLRC);
495 fExtensions.releasePbufferDC(fPbuffer, fDC);
496 fExtensions.destroyPbuffer(fPbuffer);
497}
498
499SkWGLPbufferContext::SkWGLPbufferContext(HPBUFFER pbuffer, HDC dc, HGLRC glrc)
500 : fPbuffer(pbuffer)
501 , fDC(dc)
502 , fGLRC(glrc) {
503}
mtklein1ee76512015-11-02 10:20:27 -0800504
Mike Klein8f11d4d2018-01-24 12:42:55 -0500505#endif//defined(SK_BUILD_FOR_WIN)