blob: 0c1752a06aba89217d7cd29bfa6232e9f19bd70f [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
mtklein1ee76512015-11-02 10:20:27 -08008#include "SkTypes.h"
9#if defined(SK_BUILD_FOR_WIN32)
10
bsalomon@google.combd7c6412011-12-01 16:34:28 +000011#include "SkWGL.h"
12
Brian Osman6269f712017-08-16 15:14:59 -040013#include "SkOnce.h"
bsalomon@google.com8a189b02012-04-17 12:43:00 +000014#include "SkTDArray.h"
15#include "SkTSearch.h"
bsalomon@google.com20f7f172013-05-17 19:05:03 +000016#include "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 {
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];
commit-bot@chromium.org040fd8f2013-09-06 20:00:41 +0000149 rankedFormats[i].fSampleCnt = numSamples;
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000150 rankedFormats[i].fChoosePixelFormatRank = i;
151 }
bsalomon@google.com20f7f172013-05-17 19:05:03 +0000152 SkTQSort(rankedFormats.begin(),
153 rankedFormats.begin() + rankedFormats.count() - 1,
154 SkTLessFunctionToFunctorAdaptor<PixelFormat, pf_less>());
155 int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(),
156 rankedFormats.count(),
157 desiredFormat,
158 sizeof(PixelFormat));
bsalomon@google.com8a189b02012-04-17 12:43:00 +0000159 if (idx < 0) {
160 idx = ~idx;
161 }
162 return rankedFormats[idx].fFormat;
163}
164
165
166namespace {
167
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000168#if defined(UNICODE)
169 #define STR_LIT(X) L## #X
170#else
171 #define STR_LIT(X) #X
172#endif
173
174#define DUMMY_CLASS STR_LIT("DummyClass")
175
176HWND create_dummy_window() {
halcanary96fcdcc2015-08-27 07:41:13 -0700177 HMODULE module = GetModuleHandle(nullptr);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000178 HWND dummy;
179 RECT windowRect;
180 windowRect.left = 0;
181 windowRect.right = 8;
182 windowRect.top = 0;
183 windowRect.bottom = 8;
184
185 WNDCLASS wc;
186
187 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
188 wc.lpfnWndProc = (WNDPROC) DefWindowProc;
189 wc.cbClsExtra = 0;
190 wc.cbWndExtra = 0;
191 wc.hInstance = module;
halcanary96fcdcc2015-08-27 07:41:13 -0700192 wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
193 wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
194 wc.hbrBackground = nullptr;
195 wc.lpszMenuName = nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000196 wc.lpszClassName = DUMMY_CLASS;
197
198 if(!RegisterClass(&wc)) {
199 return 0;
200 }
201
202 DWORD style, exStyle;
203 exStyle = WS_EX_CLIENTEDGE;
204 style = WS_SYSMENU;
205
206 AdjustWindowRectEx(&windowRect, style, false, exStyle);
207 if(!(dummy = CreateWindowEx(exStyle,
208 DUMMY_CLASS,
209 STR_LIT("DummyWindow"),
210 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
211 0, 0,
212 windowRect.right-windowRect.left,
213 windowRect.bottom-windowRect.top,
halcanary96fcdcc2015-08-27 07:41:13 -0700214 nullptr, nullptr,
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000215 module,
halcanary96fcdcc2015-08-27 07:41:13 -0700216 nullptr))) {
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000217 UnregisterClass(DUMMY_CLASS, module);
halcanary96fcdcc2015-08-27 07:41:13 -0700218 return nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000219 }
220 ShowWindow(dummy, SW_HIDE);
221
222 return dummy;
223}
224
225void destroy_dummy_window(HWND dummy) {
226 DestroyWindow(dummy);
halcanary96fcdcc2015-08-27 07:41:13 -0700227 HMODULE module = GetModuleHandle(nullptr);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000228 UnregisterClass(DUMMY_CLASS, module);
229}
230}
231
232#define GET_PROC(NAME, SUFFIX) f##NAME = \
Mike Kleinc722f792017-07-31 11:57:21 -0400233 (NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000234
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000235
Brian Osman6269f712017-08-16 15:14:59 -0400236SkWGLExtensions::GetExtensionsStringProc SkWGLExtensions::fGetExtensionsString = nullptr;
237SkWGLExtensions::ChoosePixelFormatProc SkWGLExtensions::fChoosePixelFormat = nullptr;
238SkWGLExtensions::GetPixelFormatAttribfvProc SkWGLExtensions::fGetPixelFormatAttribfv = nullptr;
239SkWGLExtensions::GetPixelFormatAttribivProc SkWGLExtensions::fGetPixelFormatAttribiv = nullptr;
240SkWGLExtensions::CreateContextAttribsProc SkWGLExtensions::fCreateContextAttribs = nullptr;
241SkWGLExtensions::SwapIntervalProc SkWGLExtensions::fSwapInterval = nullptr;
242SkWGLExtensions::CreatePbufferProc SkWGLExtensions::fCreatePbuffer = nullptr;
243SkWGLExtensions::GetPbufferDCProc SkWGLExtensions::fGetPbufferDC = nullptr;
244SkWGLExtensions::ReleasePbufferDCProc SkWGLExtensions::fReleasePbufferDC = nullptr;
245SkWGLExtensions::DestroyPbufferProc SkWGLExtensions::fDestroyPbuffer = nullptr;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000246
Brian Osman6269f712017-08-16 15:14:59 -0400247SkWGLExtensions::SkWGLExtensions() {
248 // We cache these function pointers once, and then reuse them. That's possibly incorrect if
249 // there are multiple GPUs, or if we intend to use these for rendering contexts of different
250 // pixel formats (where wglGetProcAddress is not guaranteed to return the same pointer).
251 static SkOnce once;
252 once([] {
253 HDC prevDC = wglGetCurrentDC();
254 HGLRC prevGLRC = wglGetCurrentContext();
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000255
Brian Osman6269f712017-08-16 15:14:59 -0400256 PIXELFORMATDESCRIPTOR dummyPFD;
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000257
Brian Osman6269f712017-08-16 15:14:59 -0400258 ZeroMemory(&dummyPFD, sizeof(dummyPFD));
259 dummyPFD.nSize = sizeof(dummyPFD);
260 dummyPFD.nVersion = 1;
261 dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
262 dummyPFD.iPixelType = PFD_TYPE_RGBA;
263 dummyPFD.cColorBits = 32;
264 dummyPFD.cDepthBits = 0;
265 dummyPFD.cStencilBits = 8;
266 dummyPFD.iLayerType = PFD_MAIN_PLANE;
267 HWND dummyWND = create_dummy_window();
268 if (dummyWND) {
269 HDC dummyDC = GetDC(dummyWND);
270 int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
271 SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
272 HGLRC dummyGLRC = wglCreateContext(dummyDC);
273 SkASSERT(dummyGLRC);
274 wglMakeCurrent(dummyDC, dummyGLRC);
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000275
Brian Osman6269f712017-08-16 15:14:59 -0400276 GET_PROC(GetExtensionsString, ARB);
277 GET_PROC(ChoosePixelFormat, ARB);
278 GET_PROC(GetPixelFormatAttribiv, ARB);
279 GET_PROC(GetPixelFormatAttribfv, ARB);
280 GET_PROC(CreateContextAttribs, ARB);
281 GET_PROC(SwapInterval, EXT);
282 GET_PROC(CreatePbuffer, ARB);
283 GET_PROC(GetPbufferDC, ARB);
284 GET_PROC(ReleasePbufferDC, ARB);
285 GET_PROC(DestroyPbuffer, ARB);
286
287 wglMakeCurrent(dummyDC, nullptr);
288 wglDeleteContext(dummyGLRC);
289 destroy_dummy_window(dummyWND);
290 }
291
292 wglMakeCurrent(prevDC, prevGLRC);
293 });
bsalomon@google.combd7c6412011-12-01 16:34:28 +0000294}
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000295
bsalomon9245b7e2014-07-01 07:20:11 -0700296///////////////////////////////////////////////////////////////////////////////
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000297
bsalomon9245b7e2014-07-01 07:20:11 -0700298static void get_pixel_formats_to_try(HDC dc, const SkWGLExtensions& extensions,
brianosman2d1ee792016-05-05 12:24:31 -0700299 bool doubleBuffered, int msaaSampleCount, bool deepColor,
bsalomon9245b7e2014-07-01 07:20:11 -0700300 int formatsToTry[2]) {
brianosman2d1ee792016-05-05 12:24:31 -0700301 auto appendAttr = [](SkTDArray<int>& attrs, int attr, int value) {
302 attrs.push(attr);
303 attrs.push(value);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000304 };
305
brianosman2d1ee792016-05-05 12:24:31 -0700306 SkTDArray<int> iAttrs;
307 appendAttr(iAttrs, SK_WGL_DRAW_TO_WINDOW, TRUE);
308 appendAttr(iAttrs, SK_WGL_DOUBLE_BUFFER, (doubleBuffered ? TRUE : FALSE));
309 appendAttr(iAttrs, SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION);
310 appendAttr(iAttrs, SK_WGL_SUPPORT_OPENGL, TRUE);
311 if (deepColor) {
312 appendAttr(iAttrs, SK_WGL_RED_BITS, 10);
313 appendAttr(iAttrs, SK_WGL_GREEN_BITS, 10);
314 appendAttr(iAttrs, SK_WGL_BLUE_BITS, 10);
315 appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 2);
316 } else {
317 appendAttr(iAttrs, SK_WGL_COLOR_BITS, 24);
318 appendAttr(iAttrs, SK_WGL_ALPHA_BITS, 8);
319 }
320 appendAttr(iAttrs, SK_WGL_STENCIL_BITS, 8);
321
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000322 float fAttrs[] = {0, 0};
323
bsalomon9245b7e2014-07-01 07:20:11 -0700324 // Get a MSAA format if requested and possible.
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000325 if (msaaSampleCount > 0 &&
326 extensions.hasExtension(dc, "WGL_ARB_multisample")) {
brianosman2d1ee792016-05-05 12:24:31 -0700327 SkTDArray<int> msaaIAttrs = iAttrs;
328 appendAttr(msaaIAttrs, SK_WGL_SAMPLE_BUFFERS, TRUE);
329 appendAttr(msaaIAttrs, SK_WGL_SAMPLES, msaaSampleCount);
330 appendAttr(msaaIAttrs, 0, 0);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000331 unsigned int num;
332 int formats[64];
brianosman2d1ee792016-05-05 12:24:31 -0700333 extensions.choosePixelFormat(dc, msaaIAttrs.begin(), fAttrs, 64, formats, &num);
bsalomon@google.comf3f2d162013-07-31 18:52:31 +0000334 num = SkTMin(num, 64U);
bsalomon9245b7e2014-07-01 07:20:11 -0700335 formatsToTry[0] = extensions.selectFormat(formats, num, dc, msaaSampleCount);
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000336 }
337
bsalomon9245b7e2014-07-01 07:20:11 -0700338 // Get a non-MSAA format
339 int* format = -1 == formatsToTry[0] ? &formatsToTry[0] : &formatsToTry[1];
340 unsigned int num;
brianosman2d1ee792016-05-05 12:24:31 -0700341 appendAttr(iAttrs, 0, 0);
342 extensions.choosePixelFormat(dc, iAttrs.begin(), fAttrs, 1, format, &num);
bsalomon9245b7e2014-07-01 07:20:11 -0700343}
344
Brian Osman6269f712017-08-16 15:14:59 -0400345static HGLRC create_gl_context(HDC dc, const SkWGLExtensions& extensions,
346 SkWGLContextRequest contextType, HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700347 HDC prevDC = wglGetCurrentDC();
348 HGLRC prevGLRC = wglGetCurrentContext();
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000349
halcanary96fcdcc2015-08-27 07:41:13 -0700350 HGLRC glrc = nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700351 if (kGLES_SkWGLContextRequest == contextType) {
352 if (!extensions.hasExtension(dc, "WGL_EXT_create_context_es2_profile")) {
bsalomon9245b7e2014-07-01 07:20:11 -0700353 wglMakeCurrent(prevDC, prevGLRC);
halcanary96fcdcc2015-08-27 07:41:13 -0700354 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700355 }
356 static const int glesAttribs[] = {
357 SK_WGL_CONTEXT_MAJOR_VERSION, 3,
358 SK_WGL_CONTEXT_MINOR_VERSION, 0,
359 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_ES2_PROFILE_BIT,
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000360 0,
361 };
Brian Osman60c774d2017-02-21 16:58:08 -0500362 glrc = extensions.createContextAttribs(dc, shareContext, glesAttribs);
halcanary96fcdcc2015-08-27 07:41:13 -0700363 if (nullptr == glrc) {
bsalomon9245b7e2014-07-01 07:20:11 -0700364 wglMakeCurrent(prevDC, prevGLRC);
halcanary96fcdcc2015-08-27 07:41:13 -0700365 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700366 }
367 } else {
368 if (kGLPreferCoreProfile_SkWGLContextRequest == contextType &&
369 extensions.hasExtension(dc, "WGL_ARB_create_context")) {
370 static const int kCoreGLVersions[] = {
371 4, 3,
372 4, 2,
373 4, 1,
374 4, 0,
375 3, 3,
376 3, 2,
377 };
378 int coreProfileAttribs[] = {
379 SK_WGL_CONTEXT_MAJOR_VERSION, -1,
380 SK_WGL_CONTEXT_MINOR_VERSION, -1,
381 SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT,
382 0,
383 };
Chris Dalton1ef80942017-12-04 12:01:30 -0700384 for (size_t v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) {
kkinnunen80549fc2014-06-30 06:36:31 -0700385 coreProfileAttribs[1] = kCoreGLVersions[2 * v];
386 coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1];
Brian Osman60c774d2017-02-21 16:58:08 -0500387 glrc = extensions.createContextAttribs(dc, shareContext, coreProfileAttribs);
bsalomon49f085d2014-09-05 13:34:00 -0700388 if (glrc) {
kkinnunen80549fc2014-06-30 06:36:31 -0700389 break;
390 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000391 }
392 }
393 }
394
halcanary96fcdcc2015-08-27 07:41:13 -0700395 if (nullptr == glrc) {
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000396 glrc = wglCreateContext(dc);
Brian Osman60c774d2017-02-21 16:58:08 -0500397 if (shareContext) {
398 if (!wglShareLists(shareContext, glrc)) {
399 wglDeleteContext(glrc);
400 return nullptr;
401 }
402 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000403 }
404 SkASSERT(glrc);
405
406 wglMakeCurrent(prevDC, prevGLRC);
bsalomon9245b7e2014-07-01 07:20:11 -0700407
408 // This might help make the context non-vsynced.
409 if (extensions.hasExtension(dc, "WGL_EXT_swap_control")) {
410 extensions.swapInterval(-1);
411 }
bsalomon@google.comb7f20f22013-03-05 19:13:09 +0000412 return glrc;
413}
bsalomon9245b7e2014-07-01 07:20:11 -0700414
brianosman2d1ee792016-05-05 12:24:31 -0700415HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool deepColor,
Brian Osman60c774d2017-02-21 16:58:08 -0500416 SkWGLContextRequest contextType, HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700417 SkWGLExtensions extensions;
418 if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
halcanary96fcdcc2015-08-27 07:41:13 -0700419 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700420 }
421
422 BOOL set = FALSE;
423
424 int pixelFormatsToTry[] = { -1, -1 };
brianosman2d1ee792016-05-05 12:24:31 -0700425 get_pixel_formats_to_try(dc, extensions, true, msaaSampleCount, deepColor, pixelFormatsToTry);
Chris Dalton1ef80942017-12-04 12:01:30 -0700426 for (size_t f = 0;
bsalomon9245b7e2014-07-01 07:20:11 -0700427 !set && -1 != pixelFormatsToTry[f] && f < SK_ARRAY_COUNT(pixelFormatsToTry);
428 ++f) {
429 PIXELFORMATDESCRIPTOR pfd;
430 DescribePixelFormat(dc, pixelFormatsToTry[f], sizeof(pfd), &pfd);
431 set = SetPixelFormat(dc, pixelFormatsToTry[f], &pfd);
432 }
433
434 if (!set) {
halcanary96fcdcc2015-08-27 07:41:13 -0700435 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700436 }
437
Brian Osman60c774d2017-02-21 16:58:08 -0500438 return create_gl_context(dc, extensions, contextType, shareContext);
439}
bsalomon9245b7e2014-07-01 07:20:11 -0700440
Brian Osmande3b7102017-08-17 12:58:28 -0400441SkWGLPbufferContext* SkWGLPbufferContext::Create(HDC parentDC, SkWGLContextRequest contextType,
Brian Osman60c774d2017-02-21 16:58:08 -0500442 HGLRC shareContext) {
bsalomon9245b7e2014-07-01 07:20:11 -0700443 SkWGLExtensions extensions;
444 if (!extensions.hasExtension(parentDC, "WGL_ARB_pixel_format") ||
445 !extensions.hasExtension(parentDC, "WGL_ARB_pbuffer")) {
halcanary96fcdcc2015-08-27 07:41:13 -0700446 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700447 }
448
Brian Osmande3b7102017-08-17 12:58:28 -0400449 // We cache the pixel formats once, and then reuse them. That's possibly incorrect if
450 // there are multiple GPUs, but this function is always called with a freshly made,
451 // identically constructed HDC (see WinGLTestContext).
452 //
453 // We only store two potential pixel formats, one for single buffer, one for double buffer.
454 // We never ask for MSAA, so we don't need the second pixel format for each buffering state.
455 static int gPixelFormats[2] = { -1, -1 };
456 static SkOnce once;
457 once([=] {
458 {
459 // Single buffer
460 int pixelFormatsToTry[2] = { -1, -1 };
461 get_pixel_formats_to_try(parentDC, extensions, false, 0, false, pixelFormatsToTry);
462 gPixelFormats[0] = pixelFormatsToTry[0];
463 }
464 {
465 // Double buffer
466 int pixelFormatsToTry[2] = { -1, -1 };
467 get_pixel_formats_to_try(parentDC, extensions, true, 0, false, pixelFormatsToTry);
468 gPixelFormats[1] = pixelFormatsToTry[0];
469 }
470 });
471
bsalomon9245b7e2014-07-01 07:20:11 -0700472 // try for single buffer first
Brian Osmande3b7102017-08-17 12:58:28 -0400473 for (int pixelFormat : gPixelFormats) {
474 if (-1 == pixelFormat) {
475 continue;
476 }
477 HPBUFFER pbuf = extensions.createPbuffer(parentDC, pixelFormat, 1, 1, nullptr);
478 if (0 != pbuf) {
479 HDC dc = extensions.getPbufferDC(pbuf);
480 if (dc) {
481 HGLRC glrc = create_gl_context(dc, extensions, contextType, shareContext);
482 if (glrc) {
483 return new SkWGLPbufferContext(pbuf, dc, glrc);
bsalomon9245b7e2014-07-01 07:20:11 -0700484 }
Brian Osmande3b7102017-08-17 12:58:28 -0400485 extensions.releasePbufferDC(pbuf, dc);
bsalomon9245b7e2014-07-01 07:20:11 -0700486 }
Brian Osmande3b7102017-08-17 12:58:28 -0400487 extensions.destroyPbuffer(pbuf);
bsalomon9245b7e2014-07-01 07:20:11 -0700488 }
489 }
halcanary96fcdcc2015-08-27 07:41:13 -0700490 return nullptr;
bsalomon9245b7e2014-07-01 07:20:11 -0700491}
492
493SkWGLPbufferContext::~SkWGLPbufferContext() {
494 SkASSERT(fExtensions.hasExtension(fDC, "WGL_ARB_pbuffer"));
495 wglDeleteContext(fGLRC);
496 fExtensions.releasePbufferDC(fPbuffer, fDC);
497 fExtensions.destroyPbuffer(fPbuffer);
498}
499
500SkWGLPbufferContext::SkWGLPbufferContext(HPBUFFER pbuffer, HDC dc, HGLRC glrc)
501 : fPbuffer(pbuffer)
502 , fDC(dc)
503 , fGLRC(glrc) {
504}
mtklein1ee76512015-11-02 10:20:27 -0800505
506#endif//defined(SK_BUILD_FOR_WIN32)