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