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 "SkWGL.h"
10
11 #include "SkTDArray.h"
12 #include "SkTSearch.h"
13
hasExtension(HDC dc,const char * ext) const14 bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
15 if (NULL == this->fGetExtensionsString) {
16 return false;
17 }
18 if (!strcmp("WGL_ARB_extensions_string", ext)) {
19 return true;
20 }
21 const char* extensionString = this->getExtensionsString(dc);
22 int extLength = strlen(ext);
23
24 while (true) {
25 int n = strcspn(extensionString, " ");
26 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
27 return true;
28 }
29 if (0 == extensionString[n]) {
30 return false;
31 }
32 extensionString += n+1;
33 }
34
35 return false;
36 }
37
getExtensionsString(HDC hdc) const38 const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
39 return fGetExtensionsString(hdc);
40 }
41
choosePixelFormat(HDC hdc,const int * piAttribIList,const FLOAT * pfAttribFList,UINT nMaxFormats,int * piFormats,UINT * nNumFormats) const42 BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
43 const int* piAttribIList,
44 const FLOAT* pfAttribFList,
45 UINT nMaxFormats,
46 int* piFormats,
47 UINT* nNumFormats) const {
48 return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
49 nMaxFormats, piFormats, nNumFormats);
50 }
51
getPixelFormatAttribiv(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,int * piValues) const52 BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
53 int iPixelFormat,
54 int iLayerPlane,
55 UINT nAttributes,
56 const int *piAttributes,
57 int *piValues) const {
58 return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
59 nAttributes, piAttributes, piValues);
60 }
61
getPixelFormatAttribfv(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,float * pfValues) const62 BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
63 int iPixelFormat,
64 int iLayerPlane,
65 UINT nAttributes,
66 const int *piAttributes,
67 float *pfValues) const {
68 return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
69 nAttributes, piAttributes, pfValues);
70 }
createContextAttribs(HDC hDC,HGLRC hShareContext,const int * attribList) const71 HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
72 HGLRC hShareContext,
73 const int *attribList) const {
74 return fCreateContextAttribs(hDC, hShareContext, attribList);
75 }
76
77 namespace {
78
79 struct PixelFormat {
80 int fFormat;
81 int fCoverageSamples;
82 int fColorSamples;
83 int fChoosePixelFormatRank;
84 };
85
compare_pf(const PixelFormat * a,const PixelFormat * b)86 int compare_pf(const PixelFormat* a, const PixelFormat* b) {
87 if (a->fCoverageSamples < b->fCoverageSamples) {
88 return -1;
89 } else if (b->fCoverageSamples < a->fCoverageSamples) {
90 return 1;
91 } else if (a->fColorSamples < b->fColorSamples) {
92 return -1;
93 } else if (b->fColorSamples < a->fColorSamples) {
94 return 1;
95 } else if (a->fChoosePixelFormatRank < b->fChoosePixelFormatRank) {
96 return -1;
97 } else if (b->fChoosePixelFormatRank < a->fChoosePixelFormatRank) {
98 return 1;
99 }
100 return 0;
101 }
102 }
103
selectFormat(const int formats[],int formatCount,HDC dc,int desiredSampleCount)104 int SkWGLExtensions::selectFormat(const int formats[],
105 int formatCount,
106 HDC dc,
107 int desiredSampleCount) {
108 PixelFormat desiredFormat = {
109 0,
110 desiredSampleCount,
111 0,
112 0,
113 };
114 SkTDArray<PixelFormat> rankedFormats;
115 rankedFormats.setCount(formatCount);
116 bool supportsCoverage = this->hasExtension(dc,
117 "WGL_NV_multisample_coverage");
118 for (int i = 0; i < formatCount; ++i) {
119 static const int queryAttrs[] = {
120 SK_WGL_COVERAGE_SAMPLES,
121 // Keep COLOR_SAMPLES at the end so it can be skipped
122 SK_WGL_COLOR_SAMPLES,
123 };
124 int answers[2];
125 int queryAttrCnt = supportsCoverage ?
126 SK_ARRAY_COUNT(queryAttrs) :
127 SK_ARRAY_COUNT(queryAttrs) - 1;
128 this->getPixelFormatAttribiv(dc,
129 formats[i],
130 0,
131 queryAttrCnt,
132 queryAttrs,
133 answers);
134 rankedFormats[i].fFormat = formats[i];
135 rankedFormats[i].fCoverageSamples = answers[0];
136 rankedFormats[i].fColorSamples = answers[supportsCoverage ? 1 : 0];
137 rankedFormats[i].fChoosePixelFormatRank = i;
138 }
139 qsort(rankedFormats.begin(),
140 rankedFormats.count(),
141 sizeof(PixelFormat),
142 SkCastForQSort(compare_pf));
143 int idx = SkTSearch<PixelFormat>(rankedFormats.begin(),
144 rankedFormats.count(),
145 desiredFormat,
146 sizeof(PixelFormat),
147 compare_pf);
148 if (idx < 0) {
149 idx = ~idx;
150 }
151 return rankedFormats[idx].fFormat;
152 }
153
154
155 namespace {
156
157 #if defined(UNICODE)
158 #define STR_LIT(X) L## #X
159 #else
160 #define STR_LIT(X) #X
161 #endif
162
163 #define DUMMY_CLASS STR_LIT("DummyClass")
164
create_dummy_window()165 HWND create_dummy_window() {
166 HMODULE module = GetModuleHandle(NULL);
167 HWND dummy;
168 RECT windowRect;
169 windowRect.left = 0;
170 windowRect.right = 8;
171 windowRect.top = 0;
172 windowRect.bottom = 8;
173
174 WNDCLASS wc;
175
176 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
177 wc.lpfnWndProc = (WNDPROC) DefWindowProc;
178 wc.cbClsExtra = 0;
179 wc.cbWndExtra = 0;
180 wc.hInstance = module;
181 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
182 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
183 wc.hbrBackground = NULL;
184 wc.lpszMenuName = NULL;
185 wc.lpszClassName = DUMMY_CLASS;
186
187 if(!RegisterClass(&wc)) {
188 return 0;
189 }
190
191 DWORD style, exStyle;
192 exStyle = WS_EX_CLIENTEDGE;
193 style = WS_SYSMENU;
194
195 AdjustWindowRectEx(&windowRect, style, false, exStyle);
196 if(!(dummy = CreateWindowEx(exStyle,
197 DUMMY_CLASS,
198 STR_LIT("DummyWindow"),
199 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
200 0, 0,
201 windowRect.right-windowRect.left,
202 windowRect.bottom-windowRect.top,
203 NULL, NULL,
204 module,
205 NULL))) {
206 UnregisterClass(DUMMY_CLASS, module);
207 return NULL;
208 }
209 ShowWindow(dummy, SW_HIDE);
210
211 return dummy;
212 }
213
destroy_dummy_window(HWND dummy)214 void destroy_dummy_window(HWND dummy) {
215 DestroyWindow(dummy);
216 HMODULE module = GetModuleHandle(NULL);
217 UnregisterClass(DUMMY_CLASS, module);
218 }
219 }
220
221 #define GET_PROC(NAME, SUFFIX) f##NAME = \
222 (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
223
SkWGLExtensions()224 SkWGLExtensions::SkWGLExtensions()
225 : fGetExtensionsString(NULL)
226 , fChoosePixelFormat(NULL)
227 , fGetPixelFormatAttribfv(NULL)
228 , fGetPixelFormatAttribiv(NULL)
229 , fCreateContextAttribs(NULL) {
230 HDC prevDC = wglGetCurrentDC();
231 HGLRC prevGLRC = wglGetCurrentContext();
232
233 PIXELFORMATDESCRIPTOR dummyPFD;
234
235 ZeroMemory(&dummyPFD, sizeof(dummyPFD));
236 dummyPFD.nSize = sizeof(dummyPFD);
237 dummyPFD.nVersion = 1;
238 dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
239 dummyPFD.iPixelType = PFD_TYPE_RGBA;
240 dummyPFD.cColorBits = 32;
241 dummyPFD.cDepthBits = 0;
242 dummyPFD.cStencilBits = 8;
243 dummyPFD.iLayerType = PFD_MAIN_PLANE;
244 HWND dummyWND = create_dummy_window();
245 if (dummyWND) {
246 HDC dummyDC = GetDC(dummyWND);
247 int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
248 SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
249 HGLRC dummyGLRC = wglCreateContext(dummyDC);
250 SkASSERT(dummyGLRC);
251 wglMakeCurrent(dummyDC, dummyGLRC);
252
253 GET_PROC(GetExtensionsString, ARB);
254 GET_PROC(ChoosePixelFormat, ARB);
255 GET_PROC(GetPixelFormatAttribiv, ARB);
256 GET_PROC(GetPixelFormatAttribfv, ARB);
257 GET_PROC(CreateContextAttribs, ARB);
258
259 wglMakeCurrent(dummyDC, NULL);
260 wglDeleteContext(dummyGLRC);
261 destroy_dummy_window(dummyWND);
262 }
263
264 wglMakeCurrent(prevDC, prevGLRC);
265 }
266