blob: 7cf410a0037e1e047512b630386c772d2c4449ef [file] [log] [blame]
bsalomon@google.combd7c6412011-12-01 16:34:28 +00001
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
11bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
12 if (NULL == this->fGetExtensionsString) {
13 return false;
14 }
15 if (!strcmp("WGL_ARB_extensions_string", ext)) {
16 return true;
17 }
18 const char* extensionString = this->getExtensionsString(dc);
19 int extLength = strlen(ext);
20
21 while (true) {
22 int n = strcspn(extensionString, " ");
23 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
24 return true;
25 }
26 if (0 == extensionString[n]) {
27 return false;
28 }
29 extensionString += n+1;
30 }
31
32 return false;
33}
34
35const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
36 return fGetExtensionsString(hdc);
37}
38
39BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
40 const int* piAttribIList,
41 const FLOAT* pfAttribFList,
42 UINT nMaxFormats,
43 int* piFormats,
44 UINT* nNumFormats) const {
45 return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
46 nMaxFormats, piFormats, nNumFormats);
47}
48
49BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
50 int iPixelFormat,
51 int iLayerPlane,
52 UINT nAttributes,
53 const int *piAttributes,
54 int *piValues) const {
55 return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
56 nAttributes, piAttributes, piValues);
57}
58
59BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
60 int iPixelFormat,
61 int iLayerPlane,
62 UINT nAttributes,
63 const int *piAttributes,
64 float *pfValues) const {
65 return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
66 nAttributes, piAttributes, pfValues);
67}
68HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
69 HGLRC hShareContext,
70 const int *attribList) const {
71 return fCreateContextAttribs(hDC, hShareContext, attribList);
72}
73
74namespace {
75
76#if defined(UNICODE)
77 #define STR_LIT(X) L## #X
78#else
79 #define STR_LIT(X) #X
80#endif
81
82#define DUMMY_CLASS STR_LIT("DummyClass")
83
84HWND create_dummy_window() {
85 HMODULE module = GetModuleHandle(NULL);
86 HWND dummy;
87 RECT windowRect;
88 windowRect.left = 0;
89 windowRect.right = 8;
90 windowRect.top = 0;
91 windowRect.bottom = 8;
92
93 WNDCLASS wc;
94
95 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
96 wc.lpfnWndProc = (WNDPROC) DefWindowProc;
97 wc.cbClsExtra = 0;
98 wc.cbWndExtra = 0;
99 wc.hInstance = module;
100 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
101 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
102 wc.hbrBackground = NULL;
103 wc.lpszMenuName = NULL;
104 wc.lpszClassName = DUMMY_CLASS;
105
106 if(!RegisterClass(&wc)) {
107 return 0;
108 }
109
110 DWORD style, exStyle;
111 exStyle = WS_EX_CLIENTEDGE;
112 style = WS_SYSMENU;
113
114 AdjustWindowRectEx(&windowRect, style, false, exStyle);
115 if(!(dummy = CreateWindowEx(exStyle,
116 DUMMY_CLASS,
117 STR_LIT("DummyWindow"),
118 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
119 0, 0,
120 windowRect.right-windowRect.left,
121 windowRect.bottom-windowRect.top,
122 NULL, NULL,
123 module,
124 NULL))) {
125 UnregisterClass(DUMMY_CLASS, module);
126 return NULL;
127 }
128 ShowWindow(dummy, SW_HIDE);
129
130 return dummy;
131}
132
133void destroy_dummy_window(HWND dummy) {
134 DestroyWindow(dummy);
135 HMODULE module = GetModuleHandle(NULL);
136 UnregisterClass(DUMMY_CLASS, module);
137}
138}
139
140#define GET_PROC(NAME, SUFFIX) f##NAME = \
141 (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
142
143SkWGLExtensions::SkWGLExtensions()
144 : fGetExtensionsString(NULL)
145 , fChoosePixelFormat(NULL)
146 , fGetPixelFormatAttribfv(NULL)
147 , fGetPixelFormatAttribiv(NULL)
148 , fCreateContextAttribs(NULL) {
149 HDC prevDC = wglGetCurrentDC();
150 HGLRC prevGLRC = wglGetCurrentContext();
151
152 PIXELFORMATDESCRIPTOR dummyPFD;
153
154 ZeroMemory(&dummyPFD, sizeof(dummyPFD));
155 dummyPFD.nSize = sizeof(dummyPFD);
156 dummyPFD.nVersion = 1;
157 dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
158 dummyPFD.iPixelType = PFD_TYPE_RGBA;
159 dummyPFD.cColorBits = 32;
160 dummyPFD.cDepthBits = 0;
161 dummyPFD.cStencilBits = 8;
162 dummyPFD.iLayerType = PFD_MAIN_PLANE;
163 HWND dummyWND = create_dummy_window();
164 if (dummyWND) {
165 HDC dummyDC = GetDC(dummyWND);
166 int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
167 SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
168 HGLRC dummyGLRC = wglCreateContext(dummyDC);
169 SkASSERT(dummyGLRC);
170 wglMakeCurrent(dummyDC, dummyGLRC);
171
172 GET_PROC(GetExtensionsString, ARB);
173 GET_PROC(ChoosePixelFormat, ARB);
174 GET_PROC(GetPixelFormatAttribiv, ARB);
175 GET_PROC(GetPixelFormatAttribfv, ARB);
176 GET_PROC(CreateContextAttribs, ARB);
177
178 wglMakeCurrent(dummyDC, NULL);
179 wglDeleteContext(dummyGLRC);
180 destroy_dummy_window(dummyWND);
181 }
182
183 wglMakeCurrent(prevDC, prevGLRC);
184}