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