blob: 5f1278010d6578b610a414fe6636d9b4fc0f9516 [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"
James Clarkeb8c0dab2021-02-09 06:22:41 -08009#if defined(SK_BUILD_FOR_WIN) && !defined(_M_ARM64) && !defined(WINUWP)
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"
John Stiles6e9ead92020-07-14 00:13:51 +000016#include "src/core/SkTSort.h"
bsalomon@google.com8a189b02012-04-17 12:43:00 +000017
bsalomon@google.combd7c6412011-12-01 16:34:28 +000018bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
halcanary96fcdcc2015-08-27 07:41:13 -070019 if (nullptr == this->fGetExtensionsString) {
bsalomon@google.combd7c6412011-12-01 16:34:28 +000020 return false;
21 }
22 if (!strcmp("WGL_ARB_extensions_string", ext)) {
23 return true;
24 }
25 const char* extensionString = this->getExtensionsString(dc);
robertphillips@google.comadacc702013-10-14 21:53:24 +000026 size_t extLength = strlen(ext);
bsalomon@google.combd7c6412011-12-01 16:34:28 +000027
28 while (true) {
robertphillips@google.comadacc702013-10-14 21:53:24 +000029 size_t n = strcspn(extensionString, " ");
bsalomon@google.combd7c6412011-12-01 16:34:28 +000030 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
31 return true;
32 }
33 if (0 == extensionString[n]) {
34 return false;
35 }
36 extensionString += n+1;
37 }
38
39 return false;
40}
41
42const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
43 return fGetExtensionsString(hdc);
44}
45
46BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
47 const int* piAttribIList,
48 const FLOAT* pfAttribFList,
49 UINT nMaxFormats,
50 int* piFormats,
51 UINT* nNumFormats) const {
52 return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
53 nMaxFormats, piFormats, nNumFormats);
54}
55
56BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
57 int iPixelFormat,
58 int iLayerPlane,
59 UINT nAttributes,
60 const int *piAttributes,
61 int *piValues) const {
62 return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
63 nAttributes, piAttributes, piValues);
64}
65
66BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
67 int iPixelFormat,
68 int iLayerPlane,
69 UINT nAttributes,
70 const int *piAttributes,
71 float *pfValues) const {
72 return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
73 nAttributes, piAttributes, pfValues);
74}
75HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
76 HGLRC hShareContext,
77 const int *attribList) const {
78 return fCreateContextAttribs(hDC, hShareContext, attribList);
79}
80
bsalomon9245b7e2014-07-01 07:20:11 -070081BOOL SkWGLExtensions::swapInterval(int interval) const {
82 return fSwapInterval(interval);
83}
84
85HPBUFFER SkWGLExtensions::createPbuffer(HDC hDC,
86 int iPixelFormat,
87 int iWidth,
88 int iHeight,
89 const int *piAttribList) const {
90 return fCreatePbuffer(hDC, iPixelFormat, iWidth, iHeight, piAttribList);
91}
92
93HDC SkWGLExtensions::getPbufferDC(HPBUFFER hPbuffer) const {
94 return fGetPbufferDC(hPbuffer);
95}
96
97int SkWGLExtensions::releasePbufferDC(HPBUFFER hPbuffer, HDC hDC) const {
98 return fReleasePbufferDC(hPbuffer, hDC);
99}
100
101BOOL SkWGLExtensions::destroyPbuffer(HPBUFFER hPbuffer) const {
102 return fDestroyPbuffer(hPbuffer);
103}
104
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000105namespace {
106
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000107struct PixelFormat {
108 int fFormat;
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000109 int fSampleCnt;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000110 int fChoosePixelFormatRank;
111};
112
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000113bool pf_less(const PixelFormat& a, const PixelFormat& b) {
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000114 if (a.fSampleCnt < b.fSampleCnt) {
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000115 return true;
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000116 } else if (b.fSampleCnt < a.fSampleCnt) {
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000117 return false;
118 } else if (a.fChoosePixelFormatRank < b.fChoosePixelFormatRank) {
119 return true;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000120 }
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000121 return false;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000122}
123}
124
125int SkWGLExtensions::selectFormat(const int formats[],
126 int formatCount,
127 HDC dc,
bsalomon9245b7e2014-07-01 07:20:11 -0700128 int desiredSampleCount) const {
Brian Salomonbdecacf2018-02-02 20:32:49 -0500129 SkASSERT(desiredSampleCount >= 1);
aleksandar.stojiljkovic2944fbb2015-11-05 07:48:12 -0800130 if (formatCount <= 0) {
131 return -1;
132 }
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000133 PixelFormat desiredFormat = {
134 0,
135 desiredSampleCount,
136 0,
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000137 };
138 SkTDArray<PixelFormat> rankedFormats;
139 rankedFormats.setCount(formatCount);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000140 for (int i = 0; i < formatCount; ++i) {
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000141 static const int kQueryAttr = SK_WGL_SAMPLES;
142 int numSamples;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000143 this->getPixelFormatAttribiv(dc,
144 formats[i],
145 0,
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000146 1,
147 &kQueryAttr,
148 &numSamples);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000149 rankedFormats[i].fFormat = formats[i];
Brian Osman788b9162020-02-07 10:36:46 -0500150 rankedFormats[i].fSampleCnt = std::max(1, numSamples);
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000151 rankedFormats[i].fChoosePixelFormatRank = i;
152 }
John Stiles886a9042020-07-14 16:28:33 -0400153 SkTQSort(rankedFormats.begin(), rankedFormats.end(), pf_less);
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000154 int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(),
155 rankedFormats.count(),
156 desiredFormat,
157 sizeof(PixelFormat));
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000158 if (idx < 0) {
159 idx = ~idx;
160 }
Brian Salomonbdecacf2018-02-02 20:32:49 -0500161 // If the caller asked for non-MSAA fail if the closest format has MSAA.
162 if (desiredSampleCount == 1 && rankedFormats[idx].fSampleCnt != 1) {
163 return -1;
164 }
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000165 return rankedFormats[idx].fFormat;
166}
167
168
169namespace {
170
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000171#if defined(UNICODE)
172 #define STR_LIT(X) L## #X
173#else
174 #define STR_LIT(X) #X
175#endif
176
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400177#define TEMP_CLASS STR_LIT("TempClass")
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000178
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400179HWND create_temp_window() {
halcanary96fcdcc2015-08-27 07:41:13 -0700180 HMODULE module = GetModuleHandle(nullptr);
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400181 HWND wnd;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000182 RECT windowRect;
183 windowRect.left = 0;
184 windowRect.right = 8;
185 windowRect.top = 0;
186 windowRect.bottom = 8;
187
188 WNDCLASS wc;
189
190 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
191 wc.lpfnWndProc = (WNDPROC) DefWindowProc;
192 wc.cbClsExtra = 0;
193 wc.cbWndExtra = 0;
194 wc.hInstance = module;
halcanary96fcdcc2015-08-27 07:41:13 -0700195 wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
196 wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
197 wc.hbrBackground = nullptr;
198 wc.lpszMenuName = nullptr;
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400199 wc.lpszClassName = TEMP_CLASS;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000200
201 if(!RegisterClass(&wc)) {
202 return 0;
203 }
204
205 DWORD style, exStyle;
206 exStyle = WS_EX_CLIENTEDGE;
207 style = WS_SYSMENU;
208
209 AdjustWindowRectEx(&windowRect, style, false, exStyle);
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400210 if(!(wnd = CreateWindowEx(exStyle,
211 TEMP_CLASS,
212 STR_LIT("PlaceholderWindow"),
213 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
214 0, 0,
215 windowRect.right-windowRect.left,
216 windowRect.bottom-windowRect.top,
217 nullptr, nullptr,
218 module,
219 nullptr))) {
220 UnregisterClass(TEMP_CLASS, module);
halcanary96fcdcc2015-08-27 07:41:13 -0700221 return nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000222 }
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400223 ShowWindow(wnd, SW_HIDE);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000224
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400225 return wnd;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000226}
227
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400228void destroy_temp_window(HWND wnd) {
229 DestroyWindow(wnd);
halcanary96fcdcc2015-08-27 07:41:13 -0700230 HMODULE module = GetModuleHandle(nullptr);
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400231 UnregisterClass(TEMP_CLASS, module);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000232}
233}
234
235#define GET_PROC(NAME, SUFFIX) f##NAME = \
Mike Kleinc722f792017-07-31 11:57:21 -0400236 (NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000237
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000238
Brian Osman6269f712017-08-16 15:14:59 -0400239SkWGLExtensions::GetExtensionsStringProc SkWGLExtensions::fGetExtensionsString = nullptr;
240SkWGLExtensions::ChoosePixelFormatProc SkWGLExtensions::fChoosePixelFormat = nullptr;
241SkWGLExtensions::GetPixelFormatAttribfvProc SkWGLExtensions::fGetPixelFormatAttribfv = nullptr;
242SkWGLExtensions::GetPixelFormatAttribivProc SkWGLExtensions::fGetPixelFormatAttribiv = nullptr;
243SkWGLExtensions::CreateContextAttribsProc SkWGLExtensions::fCreateContextAttribs = nullptr;
244SkWGLExtensions::SwapIntervalProc SkWGLExtensions::fSwapInterval = nullptr;
245SkWGLExtensions::CreatePbufferProc SkWGLExtensions::fCreatePbuffer = nullptr;
246SkWGLExtensions::GetPbufferDCProc SkWGLExtensions::fGetPbufferDC = nullptr;
247SkWGLExtensions::ReleasePbufferDCProc SkWGLExtensions::fReleasePbufferDC = nullptr;
248SkWGLExtensions::DestroyPbufferProc SkWGLExtensions::fDestroyPbuffer = nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000249
Brian Osman6269f712017-08-16 15:14:59 -0400250SkWGLExtensions::SkWGLExtensions() {
251 // We cache these function pointers once, and then reuse them. That's possibly incorrect if
252 // there are multiple GPUs, or if we intend to use these for rendering contexts of different
253 // pixel formats (where wglGetProcAddress is not guaranteed to return the same pointer).
254 static SkOnce once;
255 once([] {
256 HDC prevDC = wglGetCurrentDC();
257 HGLRC prevGLRC = wglGetCurrentContext();
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000258
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400259 PIXELFORMATDESCRIPTOR tempPFD;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000260
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400261 ZeroMemory(&tempPFD, sizeof(tempPFD));
262 tempPFD.nSize = sizeof(tempPFD);
263 tempPFD.nVersion = 1;
264 tempPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
265 tempPFD.iPixelType = PFD_TYPE_RGBA;
266 tempPFD.cColorBits = 32;
267 tempPFD.cDepthBits = 0;
268 tempPFD.cStencilBits = 8;
269 tempPFD.iLayerType = PFD_MAIN_PLANE;
270 HWND tempWND = create_temp_window();
271 if (tempWND) {
272 HDC tempDC = GetDC(tempWND);
273 int tempFormat = ChoosePixelFormat(tempDC, &tempPFD);
274 SetPixelFormat(tempDC, tempFormat, &tempPFD);
275 HGLRC tempGLRC = wglCreateContext(tempDC);
276 SkASSERT(tempGLRC);
277 wglMakeCurrent(tempDC, tempGLRC);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000278
Brian Osman759802f2021-06-15 13:19:08 -0400279 #if defined(__clang__)
280 #pragma clang diagnostic push
281 #pragma clang diagnostic ignored "-Wcast-function-type"
282 #endif
283
Brian Osman6269f712017-08-16 15:14:59 -0400284 GET_PROC(GetExtensionsString, ARB);
285 GET_PROC(ChoosePixelFormat, ARB);
286 GET_PROC(GetPixelFormatAttribiv, ARB);
287 GET_PROC(GetPixelFormatAttribfv, ARB);
288 GET_PROC(CreateContextAttribs, ARB);
289 GET_PROC(SwapInterval, EXT);
290 GET_PROC(CreatePbuffer, ARB);
291 GET_PROC(GetPbufferDC, ARB);
292 GET_PROC(ReleasePbufferDC, ARB);
293 GET_PROC(DestroyPbuffer, ARB);
294
Brian Osman759802f2021-06-15 13:19:08 -0400295 #if defined(__clang__)
296 #pragma clang diagnostic pop
297 #endif
298
Kevin Lubickbe03ef12021-06-16 15:28:00 -0400299 wglMakeCurrent(tempDC, nullptr);
300 wglDeleteContext(tempGLRC);
301 destroy_temp_window(tempWND);
Brian Osman6269f712017-08-16 15:14:59 -0400302 }
303
304 wglMakeCurrent(prevDC, prevGLRC);
305 });
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000306}
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000307
bsalomon9245b7e2014-07-01 07:20:11 -0700308///////////////////////////////////////////////////////////////////////////////
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000309
bsalomon9245b7e2014-07-01 07:20:11 -0700310static void get_pixel_formats_to_try(HDC dc, const SkWGLExtensions& extensions,
brianosman2d1ee792016-05-05 12:24:31 -0700311 bool doubleBuffered, int msaaSampleCount, bool deepColor,
bsalomon9245b7e2014-07-01 07:20:11 -0700312 int formatsToTry[2]) {
brianosman2d1ee792016-05-05 12:24:31 -0700313 auto appendAttr = [](SkTDArray<int>& attrs, int attr, int value) {
Mike Reedb5475792018-08-08 16:17:42 -0400314 attrs.push_back(attr);
315 attrs.push_back(value);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000316 };
317
brianosman2d1ee792016-05-05 12:24:31 -0700318 SkTDArray<int> iAttrs;
319 appendAttr(iAttrs, SK_WGL_DRAW_TO_WINDOW, TRUE);
320 appendAttr(iAttrs, SK_WGL_DOUBLE_BUFFER, (doubleBuffered ? TRUE : FALSE));
321 appendAttr(iAttrs, SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION);
322 appendAttr(iAttrs, SK_WGL_SUPPORT_OPENGL, TRUE);
323 if (deepColor) {
324 appendAttr(iAttrs, SK_WGL_RED_BITS, 10);
325 appendAttr(iAttrs, SK_WGL_GREEN_BITS, 10);
326 appendAttr(iAttrs, SK_WGL_BLUE_BITS, 10);
327 appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 2);
328 } else {
329 appendAttr(iAttrs, SK_WGL_COLOR_BITS, 24);
330 appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 8);
331 }
332 appendAttr(iAttrs, SK_WGL_STENCIL_BITS, 8);
333
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000334 float fAttrs[] = {0, 0};
335
bsalomon9245b7e2014-07-01 07:20:11 -0700336 // Get a MSAA format if requested and possible.
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000337 if (msaaSampleCount > 0 &&
338 extensions.hasExtension(dc, "WGL_ARB_multisample")) {
brianosman2d1ee792016-05-05 12:24:31 -0700339 SkTDArray<int> msaaIAttrs = iAttrs;
340 appendAttr(msaaIAttrs, SK_WGL_SAMPLE_BUFFERS, TRUE);
341 appendAttr(msaaIAttrs, SK_WGL_SAMPLES, msaaSampleCount);
342 appendAttr(msaaIAttrs, 0, 0);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000343 unsigned int num;
344 int formats[64];
brianosman2d1ee792016-05-05 12:24:31 -0700345 extensions.choosePixelFormat(dc, msaaIAttrs.begin(), fAttrs, 64, formats, &num);
Brian Osman788b9162020-02-07 10:36:46 -0500346 num = std::min(num, 64U);
bsalomon9245b7e2014-07-01 07:20:11 -0700347 formatsToTry[0] = extensions.selectFormat(formats, num, dc, msaaSampleCount);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000348 }
349
bsalomon9245b7e2014-07-01 07:20:11 -0700350 // Get a non-MSAA format
351 int* format = -1 == formatsToTry[0] ? &formatsToTry[0] : &formatsToTry[1];
352 unsigned int num;
brianosman2d1ee792016-05-05 12:24:31 -0700353 appendAttr(iAttrs, 0, 0);
354 extensions.choosePixelFormat(dc, iAttrs.begin(), fAttrs, 1, format, &num);
bsalomon9245b7e2014-07-01 07:20:11 -0700355}
356
Brian Osman6269f712017-08-16 15:14:59 -0400357static HGLRC create_gl_context(HDC dc, const SkWGLExtensions& extensions,
358 SkWGLContextRequest contextType, HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700359 HDC prevDC = wglGetCurrentDC();
360 HGLRC prevGLRC = wglGetCurrentContext();
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000361
halcanary96fcdcc2015-08-27 07:41:13 -0700362 HGLRC glrc = nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700363 if (kGLES_SkWGLContextRequest == contextType) {
364 if (!extensions.hasExtension(dc, "WGL_EXT_create_context_es2_profile")) {
bsalomon9245b7e2014-07-01 07:20:11 -0700365 wglMakeCurrent(prevDC, prevGLRC);
halcanary96fcdcc2015-08-27 07:41:13 -0700366 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700367 }
368 static const int glesAttribs[] = {
369 SK_WGL_CONTEXT_MAJOR_VERSION, 3,
370 SK_WGL_CONTEXT_MINOR_VERSION, 0,
371 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_ES2_PROFILE_BIT,
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000372 0,
373 };
Brian Osman60c774d2017-02-21 16:58:08 -0500374 glrc = extensions.createContextAttribs(dc, shareContext, glesAttribs);
halcanary96fcdcc2015-08-27 07:41:13 -0700375 if (nullptr == glrc) {
bsalomon9245b7e2014-07-01 07:20:11 -0700376 wglMakeCurrent(prevDC, prevGLRC);
halcanary96fcdcc2015-08-27 07:41:13 -0700377 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700378 }
379 } else {
380 if (kGLPreferCoreProfile_SkWGLContextRequest == contextType &&
381 extensions.hasExtension(dc, "WGL_ARB_create_context")) {
382 static const int kCoreGLVersions[] = {
383 4, 3,
384 4, 2,
385 4, 1,
386 4, 0,
387 3, 3,
388 3, 2,
389 };
390 int coreProfileAttribs[] = {
391 SK_WGL_CONTEXT_MAJOR_VERSION, -1,
392 SK_WGL_CONTEXT_MINOR_VERSION, -1,
393 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT,
394 0,
395 };
Chris Dalton1ef80942017-12-04 12:01:30 -0700396 for (size_t v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) {
kkinnunen80549fc2014-06-30 06:36:31 -0700397 coreProfileAttribs[1] = kCoreGLVersions[2 * v];
398 coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1];
Brian Osman60c774d2017-02-21 16:58:08 -0500399 glrc = extensions.createContextAttribs(dc, shareContext, coreProfileAttribs);
bsalomon49f085d2014-09-05 13:34:00 -0700400 if (glrc) {
kkinnunen80549fc2014-06-30 06:36:31 -0700401 break;
402 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000403 }
404 }
405 }
406
halcanary96fcdcc2015-08-27 07:41:13 -0700407 if (nullptr == glrc) {
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000408 glrc = wglCreateContext(dc);
Brian Osman60c774d2017-02-21 16:58:08 -0500409 if (shareContext) {
410 if (!wglShareLists(shareContext, glrc)) {
411 wglDeleteContext(glrc);
412 return nullptr;
413 }
414 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000415 }
416 SkASSERT(glrc);
417
418 wglMakeCurrent(prevDC, prevGLRC);
bsalomon9245b7e2014-07-01 07:20:11 -0700419
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000420 return glrc;
421}
bsalomon9245b7e2014-07-01 07:20:11 -0700422
brianosman2d1ee792016-05-05 12:24:31 -0700423HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool deepColor,
Brian Osman60c774d2017-02-21 16:58:08 -0500424 SkWGLContextRequest contextType, HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700425 SkWGLExtensions extensions;
426 if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
halcanary96fcdcc2015-08-27 07:41:13 -0700427 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700428 }
429
430 BOOL set = FALSE;
431
432 int pixelFormatsToTry[] = { -1, -1 };
brianosman2d1ee792016-05-05 12:24:31 -0700433 get_pixel_formats_to_try(dc, extensions, true, msaaSampleCount, deepColor, pixelFormatsToTry);
Chris Dalton1ef80942017-12-04 12:01:30 -0700434 for (size_t f = 0;
bsalomon9245b7e2014-07-01 07:20:11 -0700435 !set && -1 != pixelFormatsToTry[f] && f < SK_ARRAY_COUNT(pixelFormatsToTry);
436 ++f) {
437 PIXELFORMATDESCRIPTOR pfd;
438 DescribePixelFormat(dc, pixelFormatsToTry[f], sizeof(pfd), &pfd);
439 set = SetPixelFormat(dc, pixelFormatsToTry[f], &pfd);
440 }
441
442 if (!set) {
halcanary96fcdcc2015-08-27 07:41:13 -0700443 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700444 }
445
Brian Osman60c774d2017-02-21 16:58:08 -0500446 return create_gl_context(dc, extensions, contextType, shareContext);
447}
bsalomon9245b7e2014-07-01 07:20:11 -0700448
Ben Wagner9ec70c62018-07-12 13:30:47 -0400449sk_sp<SkWGLPbufferContext> SkWGLPbufferContext::Create(HDC parentDC,
450 SkWGLContextRequest contextType,
451 HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700452 SkWGLExtensions extensions;
453 if (!extensions.hasExtension(parentDC, "WGL_ARB_pixel_format") ||
454 !extensions.hasExtension(parentDC, "WGL_ARB_pbuffer")) {
halcanary96fcdcc2015-08-27 07:41:13 -0700455 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700456 }
457
Brian Osmande3b7102017-08-17 12:58:28 -0400458 // We cache the pixel formats once, and then reuse them. That's possibly incorrect if
459 // there are multiple GPUs, but this function is always called with a freshly made,
460 // identically constructed HDC (see WinGLTestContext).
461 //
462 // We only store two potential pixel formats, one for single buffer, one for double buffer.
463 // We never ask for MSAA, so we don't need the second pixel format for each buffering state.
464 static int gPixelFormats[2] = { -1, -1 };
465 static SkOnce once;
466 once([=] {
467 {
468 // Single buffer
469 int pixelFormatsToTry[2] = { -1, -1 };
470 get_pixel_formats_to_try(parentDC, extensions, false, 0, false, pixelFormatsToTry);
471 gPixelFormats[0] = pixelFormatsToTry[0];
472 }
473 {
474 // Double buffer
475 int pixelFormatsToTry[2] = { -1, -1 };
476 get_pixel_formats_to_try(parentDC, extensions, true, 0, false, pixelFormatsToTry);
477 gPixelFormats[1] = pixelFormatsToTry[0];
478 }
479 });
480
bsalomon9245b7e2014-07-01 07:20:11 -0700481 // try for single buffer first
Brian Osmande3b7102017-08-17 12:58:28 -0400482 for (int pixelFormat : gPixelFormats) {
483 if (-1 == pixelFormat) {
484 continue;
485 }
486 HPBUFFER pbuf = extensions.createPbuffer(parentDC, pixelFormat, 1, 1, nullptr);
487 if (0 != pbuf) {
488 HDC dc = extensions.getPbufferDC(pbuf);
489 if (dc) {
490 HGLRC glrc = create_gl_context(dc, extensions, contextType, shareContext);
491 if (glrc) {
Ben Wagner9ec70c62018-07-12 13:30:47 -0400492 return sk_sp<SkWGLPbufferContext>(new SkWGLPbufferContext(pbuf, dc, glrc));
bsalomon9245b7e2014-07-01 07:20:11 -0700493 }
Brian Osmande3b7102017-08-17 12:58:28 -0400494 extensions.releasePbufferDC(pbuf, dc);
bsalomon9245b7e2014-07-01 07:20:11 -0700495 }
Brian Osmande3b7102017-08-17 12:58:28 -0400496 extensions.destroyPbuffer(pbuf);
bsalomon9245b7e2014-07-01 07:20:11 -0700497 }
498 }
halcanary96fcdcc2015-08-27 07:41:13 -0700499 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700500}
501
502SkWGLPbufferContext::~SkWGLPbufferContext() {
503 SkASSERT(fExtensions.hasExtension(fDC, "WGL_ARB_pbuffer"));
504 wglDeleteContext(fGLRC);
505 fExtensions.releasePbufferDC(fPbuffer, fDC);
506 fExtensions.destroyPbuffer(fPbuffer);
507}
508
509SkWGLPbufferContext::SkWGLPbufferContext(HPBUFFER pbuffer, HDC dc, HGLRC glrc)
510 : fPbuffer(pbuffer)
511 , fDC(dc)
512 , fGLRC(glrc) {
513}
mtklein1ee76512015-11-02 10:20:27 -0800514
Mike Klein8f11d4d2018-01-24 12:42:55 -0500515#endif//defined(SK_BUILD_FOR_WIN)