1 // wglext.cpp
2 //
3 // Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
4 //
5 // Set up pointers for WGL functions.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11
12 #include "celengine/gl.h"
13 //#define WGL_WGLEXT_PROTOTYPES 1
14 #include "wglext.h"
15 #include <windows.h>
16 #include <cstdio>
17 #include <vector>
18
19 using namespace std;
20
21 static vector<string> supportedExtensions;
22
23
24 extern "C"
25 {
26 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL;
27
28 // WGL_ARB_pixel_format functions
29 PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = NULL;
30 PFNWGLGETPIXELFORMATATTRIBFVARBPROC wglGetPixelFormatAttribfvARB = NULL;
31 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
32
33 // WGL_ARB_pbuffer functions
34 PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = NULL;
35 PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = NULL;
36 PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = NULL;
37 PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = NULL;
38 PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = NULL;
39 };
40
41
42 // Select a floating point pixel format
FindFormatFloat(HDC hDC)43 int FindFormatFloat(HDC hDC)
44 {
45 int ifmtList[] = {
46 WGL_DRAW_TO_PBUFFER_ARB, TRUE,
47 WGL_SUPPORT_OPENGL_ARB, TRUE,
48 //WGL_DOUBLE_BUFFER_ARB, TRUE,
49 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ATI,
50 WGL_DEPTH_BITS_ARB, 24,
51 WGL_COLOR_BITS_ARB, 0,
52 WGL_RED_BITS_ARB, 16,
53 WGL_GREEN_BITS_ARB, 16,
54 WGL_BLUE_BITS_ARB, 16,
55 WGL_ALPHA_BITS_ARB, 0,
56 WGL_ACCUM_BITS_ARB, 0,
57 WGL_STENCIL_BITS_ARB, 8,
58 WGL_BIND_TO_TEXTURE_RGB_ARB, TRUE,
59 0
60 };
61
62 int pixelFormatIndex = -1;
63 int pixFormats[256];
64 unsigned int numFormats;
65
66 wglChoosePixelFormatARB(hDC, ifmtList, NULL, 256, pixFormats, &numFormats);
67
68 if (numFormats != 0)
69 {
70 for (unsigned int i = 0; i < numFormats; i++)
71 {
72 int results[7];
73 int query[] = { WGL_COLOR_BITS_ARB,
74 WGL_DEPTH_BITS_ARB,
75 WGL_STENCIL_BITS_ARB,
76 WGL_RED_BITS_ARB,
77 WGL_GREEN_BITS_ARB,
78 WGL_BLUE_BITS_ARB,
79 WGL_ALPHA_BITS_ARB };
80
81 wglGetPixelFormatAttribivARB(hDC, pixFormats[i], 0,
82 7, query, results);
83
84 // Select an fp16 format. No existing hardware fully supports
85 // fp32 render targets (no alpha blending, etc.), and fp16 is
86 // probably good enough anyway.
87 if (results[0] == 64 && results[3] == 16)
88 return pixFormats[i];
89 }
90 }
91
92 return -1;
93 }
94
95
96 // Called when dummy window is opened. Its only job is to get hold
97 // of wgl extensions.
WGLCallback(HWND wnd)98 static void WGLCallback(HWND wnd)
99 {
100 if (wnd == NULL)
101 return;
102
103 HDC hdc = GetDC(wnd);
104
105 if (hdc == NULL)
106 return;
107
108 PIXELFORMATDESCRIPTOR pfd = {
109 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
110 1, // version number
111 PFD_DRAW_TO_WINDOW | // support window
112 PFD_SUPPORT_OPENGL | // support OpenGL
113 PFD_DOUBLEBUFFER, // double buffered
114 PFD_TYPE_RGBA, // RGBA type
115 24, // 24-bit color depth
116 0, 0, 0, 0, 0, 0, // color bits ignored
117 0, // no alpha buffer
118 0, // shift bit ignored
119 0, // no accumulation buffer
120 0, 0, 0, 0, // accum bits ignored
121 24, // 24-bit z-buffer
122 0, // no stencil buffer
123 0, // no auxiliary buffer
124 PFD_MAIN_PLANE, // main layer
125 0, // reserved
126 0, 0, 0 // layer masks ignored
127 };
128
129 unsigned int pixelFormat = ChoosePixelFormat(hdc, &pfd);
130
131 DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
132 if (!SetPixelFormat(hdc, pixelFormat, &pfd))
133 return;
134
135 HGLRC context = wglCreateContext(hdc);
136 if (context == NULL)
137 return;
138
139 wglMakeCurrent(hdc, context);
140
141 wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
142 if (wglGetExtensionsStringARB == NULL)
143 return;
144
145 const char *ext = wglGetExtensionsStringARB(hdc);
146 char buff[100];
147
148 if (ext == NULL)
149 return;
150
151 while (*ext != '\0')
152 {
153 // TODO: This is prone to buffer overflows if the driver reports a
154 // bad extension string.
155 sscanf(ext, "%s", buff);
156
157 // Check for required extension and fill in pointers
158 if (strcmp(buff, "WGL_ARB_pixel_format") == 0)
159 {
160 wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) wglGetProcAddress("wglGetPixelFormatAttribivARB");
161 wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC) wglGetProcAddress("wglGetPixelFormatAttribfvARB");
162 wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
163
164 if (wglChoosePixelFormatARB != NULL &&
165 wglGetPixelFormatAttribivARB != NULL &&
166 wglGetPixelFormatAttribfvARB != NULL)
167 {
168 supportedExtensions.push_back(buff);
169 }
170 }
171 else if (strcmp(buff, "WGL_ARB_pbuffer") == 0)
172 {
173 wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB");
174 wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB");
175 wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC) wglGetProcAddress("wglReleasePbufferDCARB");
176 wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC) wglGetProcAddress("wglDestroyPbufferARB");
177 wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC) wglGetProcAddress("wglQueryPbufferARB");
178 if (wglCreatePbufferARB != NULL &&
179 wglGetPbufferDCARB != NULL &&
180 wglReleasePbufferDCARB != NULL &&
181 wglDestroyPbufferARB != NULL &&
182 wglQueryPbufferARB != NULL)
183 {
184 supportedExtensions.push_back(buff);
185 }
186 }
187 else if (strcmp(buff, "WGL_ARB_multisample") == 0)
188 {
189 //wglSampleCoverageARB = (PFNWGLSAMPLECOVERAGEARBPROC) wglGetProcAddres("wglSampleCoverageARB");
190 supportedExtensions.push_back(buff);
191 }
192 else if (strcmp(buff, "WGL_ATI_pixel_format_float") == 0)
193 {
194 supportedExtensions.push_back(buff);
195 }
196 else if (strcmp(buff, "WGL_ARB_render_texture") == 0)
197 {
198 }
199
200 ext += strlen(buff) + 1;
201 }
202
203 // Close down this context
204 wglMakeCurrent(NULL, NULL);
205 wglDeleteContext(context);
206 ReleaseDC(wnd, hdc);
207 }
208
209
210 // This window exists only to call WGLCallback when its created
WGLWindProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)211 static LRESULT CALLBACK WGLWindProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
212 {
213 switch (uMsg)
214 {
215 case WM_CREATE:
216 {
217 CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
218 WGLCallback(hwnd);
219 return -1;
220 }
221
222 default:
223 return DefWindowProc(hwnd, uMsg, wParam, lParam);
224 }
225
226 return 0;
227 }
228
229
230 // Create a dummy window to initialise WGL extensions.
InitWGLExtensions(HINSTANCE appInstance)231 void InitWGLExtensions(HINSTANCE appInstance)
232 {
233 WNDCLASS wglClass = {
234 0, WGLWindProc, 0, 0, appInstance, NULL, NULL, NULL, NULL, "InitWGL"
235 };
236 ATOM classId = RegisterClass(&wglClass);
237 HWND hwnd = CreateWindow("InitWGL", "",
238 0, 0, 0, 0, 0,
239 (HWND) NULL,
240 (HMENU) NULL,
241 appInstance,
242 NULL);
243 }
244
245
WGLExtensionSupported(const string & extName)246 bool WGLExtensionSupported(const string& extName)
247 {
248 for (unsigned int i = 0; i < supportedExtensions.size(); i++)
249 {
250 if (supportedExtensions[i] == extName)
251 return true;
252 }
253
254 return false;
255 }
256