1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/win/SkWGL_win.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,342 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 +#include "SkWGL.h" 1.13 + 1.14 +#include "SkTDArray.h" 1.15 +#include "SkTSearch.h" 1.16 +#include "SkTSort.h" 1.17 + 1.18 +bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const { 1.19 + if (NULL == this->fGetExtensionsString) { 1.20 + return false; 1.21 + } 1.22 + if (!strcmp("WGL_ARB_extensions_string", ext)) { 1.23 + return true; 1.24 + } 1.25 + const char* extensionString = this->getExtensionsString(dc); 1.26 + size_t extLength = strlen(ext); 1.27 + 1.28 + while (true) { 1.29 + size_t n = strcspn(extensionString, " "); 1.30 + if (n == extLength && 0 == strncmp(ext, extensionString, n)) { 1.31 + return true; 1.32 + } 1.33 + if (0 == extensionString[n]) { 1.34 + return false; 1.35 + } 1.36 + extensionString += n+1; 1.37 + } 1.38 + 1.39 + return false; 1.40 +} 1.41 + 1.42 +const char* SkWGLExtensions::getExtensionsString(HDC hdc) const { 1.43 + return fGetExtensionsString(hdc); 1.44 +} 1.45 + 1.46 +BOOL SkWGLExtensions::choosePixelFormat(HDC hdc, 1.47 + const int* piAttribIList, 1.48 + const FLOAT* pfAttribFList, 1.49 + UINT nMaxFormats, 1.50 + int* piFormats, 1.51 + UINT* nNumFormats) const { 1.52 + return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList, 1.53 + nMaxFormats, piFormats, nNumFormats); 1.54 +} 1.55 + 1.56 +BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc, 1.57 + int iPixelFormat, 1.58 + int iLayerPlane, 1.59 + UINT nAttributes, 1.60 + const int *piAttributes, 1.61 + int *piValues) const { 1.62 + return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane, 1.63 + nAttributes, piAttributes, piValues); 1.64 +} 1.65 + 1.66 +BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc, 1.67 + int iPixelFormat, 1.68 + int iLayerPlane, 1.69 + UINT nAttributes, 1.70 + const int *piAttributes, 1.71 + float *pfValues) const { 1.72 + return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane, 1.73 + nAttributes, piAttributes, pfValues); 1.74 +} 1.75 +HGLRC SkWGLExtensions::createContextAttribs(HDC hDC, 1.76 + HGLRC hShareContext, 1.77 + const int *attribList) const { 1.78 + return fCreateContextAttribs(hDC, hShareContext, attribList); 1.79 +} 1.80 + 1.81 +namespace { 1.82 + 1.83 +struct PixelFormat { 1.84 + int fFormat; 1.85 + int fSampleCnt; 1.86 + int fChoosePixelFormatRank; 1.87 +}; 1.88 + 1.89 +bool pf_less(const PixelFormat& a, const PixelFormat& b) { 1.90 + if (a.fSampleCnt < b.fSampleCnt) { 1.91 + return true; 1.92 + } else if (b.fSampleCnt < a.fSampleCnt) { 1.93 + return false; 1.94 + } else if (a.fChoosePixelFormatRank < b.fChoosePixelFormatRank) { 1.95 + return true; 1.96 + } 1.97 + return false; 1.98 +} 1.99 +} 1.100 + 1.101 +int SkWGLExtensions::selectFormat(const int formats[], 1.102 + int formatCount, 1.103 + HDC dc, 1.104 + int desiredSampleCount) { 1.105 + PixelFormat desiredFormat = { 1.106 + 0, 1.107 + desiredSampleCount, 1.108 + 0, 1.109 + }; 1.110 + SkTDArray<PixelFormat> rankedFormats; 1.111 + rankedFormats.setCount(formatCount); 1.112 + for (int i = 0; i < formatCount; ++i) { 1.113 + static const int kQueryAttr = SK_WGL_SAMPLES; 1.114 + int numSamples; 1.115 + this->getPixelFormatAttribiv(dc, 1.116 + formats[i], 1.117 + 0, 1.118 + 1, 1.119 + &kQueryAttr, 1.120 + &numSamples); 1.121 + rankedFormats[i].fFormat = formats[i]; 1.122 + rankedFormats[i].fSampleCnt = numSamples; 1.123 + rankedFormats[i].fChoosePixelFormatRank = i; 1.124 + } 1.125 + SkTQSort(rankedFormats.begin(), 1.126 + rankedFormats.begin() + rankedFormats.count() - 1, 1.127 + SkTLessFunctionToFunctorAdaptor<PixelFormat, pf_less>()); 1.128 + int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(), 1.129 + rankedFormats.count(), 1.130 + desiredFormat, 1.131 + sizeof(PixelFormat)); 1.132 + if (idx < 0) { 1.133 + idx = ~idx; 1.134 + } 1.135 + return rankedFormats[idx].fFormat; 1.136 +} 1.137 + 1.138 + 1.139 +namespace { 1.140 + 1.141 +#if defined(UNICODE) 1.142 + #define STR_LIT(X) L## #X 1.143 +#else 1.144 + #define STR_LIT(X) #X 1.145 +#endif 1.146 + 1.147 +#define DUMMY_CLASS STR_LIT("DummyClass") 1.148 + 1.149 +HWND create_dummy_window() { 1.150 + HMODULE module = GetModuleHandle(NULL); 1.151 + HWND dummy; 1.152 + RECT windowRect; 1.153 + windowRect.left = 0; 1.154 + windowRect.right = 8; 1.155 + windowRect.top = 0; 1.156 + windowRect.bottom = 8; 1.157 + 1.158 + WNDCLASS wc; 1.159 + 1.160 + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 1.161 + wc.lpfnWndProc = (WNDPROC) DefWindowProc; 1.162 + wc.cbClsExtra = 0; 1.163 + wc.cbWndExtra = 0; 1.164 + wc.hInstance = module; 1.165 + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); 1.166 + wc.hCursor = LoadCursor(NULL, IDC_ARROW); 1.167 + wc.hbrBackground = NULL; 1.168 + wc.lpszMenuName = NULL; 1.169 + wc.lpszClassName = DUMMY_CLASS; 1.170 + 1.171 + if(!RegisterClass(&wc)) { 1.172 + return 0; 1.173 + } 1.174 + 1.175 + DWORD style, exStyle; 1.176 + exStyle = WS_EX_CLIENTEDGE; 1.177 + style = WS_SYSMENU; 1.178 + 1.179 + AdjustWindowRectEx(&windowRect, style, false, exStyle); 1.180 + if(!(dummy = CreateWindowEx(exStyle, 1.181 + DUMMY_CLASS, 1.182 + STR_LIT("DummyWindow"), 1.183 + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style, 1.184 + 0, 0, 1.185 + windowRect.right-windowRect.left, 1.186 + windowRect.bottom-windowRect.top, 1.187 + NULL, NULL, 1.188 + module, 1.189 + NULL))) { 1.190 + UnregisterClass(DUMMY_CLASS, module); 1.191 + return NULL; 1.192 + } 1.193 + ShowWindow(dummy, SW_HIDE); 1.194 + 1.195 + return dummy; 1.196 +} 1.197 + 1.198 +void destroy_dummy_window(HWND dummy) { 1.199 + DestroyWindow(dummy); 1.200 + HMODULE module = GetModuleHandle(NULL); 1.201 + UnregisterClass(DUMMY_CLASS, module); 1.202 +} 1.203 +} 1.204 + 1.205 +#define GET_PROC(NAME, SUFFIX) f##NAME = \ 1.206 + (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX) 1.207 + 1.208 +SkWGLExtensions::SkWGLExtensions() 1.209 + : fGetExtensionsString(NULL) 1.210 + , fChoosePixelFormat(NULL) 1.211 + , fGetPixelFormatAttribfv(NULL) 1.212 + , fGetPixelFormatAttribiv(NULL) 1.213 + , fCreateContextAttribs(NULL) { 1.214 + HDC prevDC = wglGetCurrentDC(); 1.215 + HGLRC prevGLRC = wglGetCurrentContext(); 1.216 + 1.217 + PIXELFORMATDESCRIPTOR dummyPFD; 1.218 + 1.219 + ZeroMemory(&dummyPFD, sizeof(dummyPFD)); 1.220 + dummyPFD.nSize = sizeof(dummyPFD); 1.221 + dummyPFD.nVersion = 1; 1.222 + dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; 1.223 + dummyPFD.iPixelType = PFD_TYPE_RGBA; 1.224 + dummyPFD.cColorBits = 32; 1.225 + dummyPFD.cDepthBits = 0; 1.226 + dummyPFD.cStencilBits = 8; 1.227 + dummyPFD.iLayerType = PFD_MAIN_PLANE; 1.228 + HWND dummyWND = create_dummy_window(); 1.229 + if (dummyWND) { 1.230 + HDC dummyDC = GetDC(dummyWND); 1.231 + int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD); 1.232 + SetPixelFormat(dummyDC, dummyFormat, &dummyPFD); 1.233 + HGLRC dummyGLRC = wglCreateContext(dummyDC); 1.234 + SkASSERT(dummyGLRC); 1.235 + wglMakeCurrent(dummyDC, dummyGLRC); 1.236 + 1.237 + GET_PROC(GetExtensionsString, ARB); 1.238 + GET_PROC(ChoosePixelFormat, ARB); 1.239 + GET_PROC(GetPixelFormatAttribiv, ARB); 1.240 + GET_PROC(GetPixelFormatAttribfv, ARB); 1.241 + GET_PROC(CreateContextAttribs, ARB); 1.242 + 1.243 + wglMakeCurrent(dummyDC, NULL); 1.244 + wglDeleteContext(dummyGLRC); 1.245 + destroy_dummy_window(dummyWND); 1.246 + } 1.247 + 1.248 + wglMakeCurrent(prevDC, prevGLRC); 1.249 +} 1.250 + 1.251 +HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile) { 1.252 + SkWGLExtensions extensions; 1.253 + if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) { 1.254 + return NULL; 1.255 + } 1.256 + 1.257 + HDC prevDC = wglGetCurrentDC(); 1.258 + HGLRC prevGLRC = wglGetCurrentContext(); 1.259 + PIXELFORMATDESCRIPTOR pfd; 1.260 + 1.261 + int format = 0; 1.262 + 1.263 + static const int iAttrs[] = { 1.264 + SK_WGL_DRAW_TO_WINDOW, TRUE, 1.265 + SK_WGL_DOUBLE_BUFFER, TRUE, 1.266 + SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION, 1.267 + SK_WGL_SUPPORT_OPENGL, TRUE, 1.268 + SK_WGL_COLOR_BITS, 24, 1.269 + SK_WGL_ALPHA_BITS, 8, 1.270 + SK_WGL_STENCIL_BITS, 8, 1.271 + 0, 0 1.272 + }; 1.273 + 1.274 + float fAttrs[] = {0, 0}; 1.275 + 1.276 + if (msaaSampleCount > 0 && 1.277 + extensions.hasExtension(dc, "WGL_ARB_multisample")) { 1.278 + static const int kIAttrsCount = SK_ARRAY_COUNT(iAttrs); 1.279 + int msaaIAttrs[kIAttrsCount + 4]; 1.280 + memcpy(msaaIAttrs, iAttrs, sizeof(int) * kIAttrsCount); 1.281 + SkASSERT(0 == msaaIAttrs[kIAttrsCount - 2] && 1.282 + 0 == msaaIAttrs[kIAttrsCount - 1]); 1.283 + msaaIAttrs[kIAttrsCount - 2] = SK_WGL_SAMPLE_BUFFERS; 1.284 + msaaIAttrs[kIAttrsCount - 1] = TRUE; 1.285 + msaaIAttrs[kIAttrsCount + 0] = SK_WGL_SAMPLES; 1.286 + msaaIAttrs[kIAttrsCount + 1] = msaaSampleCount; 1.287 + msaaIAttrs[kIAttrsCount + 2] = 0; 1.288 + msaaIAttrs[kIAttrsCount + 3] = 0; 1.289 + unsigned int num; 1.290 + int formats[64]; 1.291 + extensions.choosePixelFormat(dc, msaaIAttrs, fAttrs, 64, formats, &num); 1.292 + num = SkTMin(num, 64U); 1.293 + int formatToTry = extensions.selectFormat(formats, 1.294 + num, 1.295 + dc, 1.296 + msaaSampleCount); 1.297 + DescribePixelFormat(dc, formatToTry, sizeof(pfd), &pfd); 1.298 + if (SetPixelFormat(dc, formatToTry, &pfd)) { 1.299 + format = formatToTry; 1.300 + } 1.301 + } 1.302 + 1.303 + if (0 == format) { 1.304 + // Either MSAA wasn't requested or creation failed 1.305 + unsigned int num; 1.306 + extensions.choosePixelFormat(dc, iAttrs, fAttrs, 1, &format, &num); 1.307 + DescribePixelFormat(dc, format, sizeof(pfd), &pfd); 1.308 + SkDEBUGCODE(BOOL set =) SetPixelFormat(dc, format, &pfd); 1.309 + SkASSERT(TRUE == set); 1.310 + } 1.311 + 1.312 + HGLRC glrc = NULL; 1.313 + if (preferCoreProfile && extensions.hasExtension(dc, "WGL_ARB_create_context")) { 1.314 + static const int kCoreGLVersions[] = { 1.315 + 4, 3, 1.316 + 4, 2, 1.317 + 4, 1, 1.318 + 4, 0, 1.319 + 3, 3, 1.320 + 3, 2, 1.321 + }; 1.322 + int coreProfileAttribs[] = { 1.323 + SK_WGL_CONTEXT_MAJOR_VERSION, -1, 1.324 + SK_WGL_CONTEXT_MINOR_VERSION, -1, 1.325 + SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT, 1.326 + 0, 1.327 + }; 1.328 + for (int v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) { 1.329 + coreProfileAttribs[1] = kCoreGLVersions[2 * v]; 1.330 + coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1]; 1.331 + glrc = extensions.createContextAttribs(dc, NULL, coreProfileAttribs); 1.332 + if (NULL != glrc) { 1.333 + break; 1.334 + } 1.335 + } 1.336 + } 1.337 + 1.338 + if (NULL == glrc) { 1.339 + glrc = wglCreateContext(dc); 1.340 + } 1.341 + SkASSERT(glrc); 1.342 + 1.343 + wglMakeCurrent(prevDC, prevGLRC); 1.344 + return glrc; 1.345 +}