1 /**************************************************************************
3 * Copyright 2011 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
42 * Several WGL functions come in two flavors:
43 * - GDI (ChoosePixelFormat, SetPixelFormat, SwapBuffers, etc)
44 * - WGL (wglChoosePixelFormat, wglSetPixelFormat, wglSwapBuffers, etc)
46 * The GDI entrypoints will inevitably dispatch to the first module named
47 * "OPENGL32", loading "C:\Windows\System32\opengl32.dll" if none was loaded so
50 * In order to use a implementation other than the one installed in the system
51 * (when specified via the TRACE_LIBGL environment variable), we need to use
55 * - http://www.opengl.org/archives/resources/faq/technical/mswindows.htm
57 static __PFNWGLCHOOSEPIXELFORMAT pfnChoosePixelFormat = &ChoosePixelFormat;
58 static __PFNWGLSETPIXELFORMAT pfnSetPixelFormat = &SetPixelFormat;
59 static __PFNWGLSWAPBUFFERS pfnSwapBuffers = &SwapBuffers;
62 static LRESULT CALLBACK
63 WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
67 case WM_GETMINMAXINFO:
68 // Allow to create a window bigger than the desktop
69 pMMI = (MINMAXINFO *)lParam;
70 pMMI->ptMaxSize.x = 60000;
71 pMMI->ptMaxSize.y = 60000;
72 pMMI->ptMaxTrackSize.x = 60000;
73 pMMI->ptMaxTrackSize.y = 60000;
79 return DefWindowProc(hWnd, uMsg, wParam, lParam);
83 class WglDrawable : public Drawable
90 PIXELFORMATDESCRIPTOR pfd;
93 WglDrawable(const Visual *vis, int width, int height) :
94 Drawable(vis, width, height)
96 static bool first = TRUE;
102 memset(&wc, 0, sizeof wc);
103 wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
104 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
105 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
106 wc.lpfnWndProc = WndProc;
107 wc.lpszClassName = "glretrace";
108 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
114 dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
120 rect.right = rect.left + width;
121 rect.bottom = rect.top + height;
123 AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
125 hWnd = CreateWindowEx(dwExStyle,
126 "glretrace", /* wc.lpszClassName */
131 rect.right - rect.left, /* width */
132 rect.bottom - rect.top, /* height */
139 memset(&pfd, 0, sizeof pfd);
146 pfd.cStencilBits = 1;
147 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
148 pfd.iLayerType = PFD_MAIN_PLANE;
149 pfd.iPixelType = PFD_TYPE_RGBA;
150 pfd.nSize = sizeof(pfd);
153 if (visual->doubleBuffer) {
154 pfd.dwFlags |= PFD_DOUBLEBUFFER;
157 iPixelFormat = pfnChoosePixelFormat(hDC, &pfd);
158 if (iPixelFormat <= 0) {
159 std::cerr << "error: ChoosePixelFormat failed\n";
163 bRet = pfnSetPixelFormat(hDC, iPixelFormat, &pfd);
165 std::cerr << "error: SetPixelFormat failed\n";
171 ReleaseDC(hWnd, hDC);
176 resize(int w, int h) {
177 if (w == width && h == height) {
181 RECT rClient, rWindow;
182 GetClientRect(hWnd, &rClient);
183 GetWindowRect(hWnd, &rWindow);
184 w += (rWindow.right - rWindow.left) - rClient.right;
185 h += (rWindow.bottom - rWindow.top) - rClient.bottom;
186 SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, w, h, SWP_NOMOVE);
188 Drawable::resize(w, h);
196 ShowWindow(hWnd, SW_SHOW);
201 void swapBuffers(void) {
203 bRet = pfnSwapBuffers(hDC);
205 std::cerr << "warning: SwapBuffers failed\n";
208 // Drain message queue to prevent window from being considered
211 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
212 TranslateMessage(&msg);
213 DispatchMessage(&msg);
219 class WglContext : public Context
223 WglContext *shareContext;
225 WglContext(const Visual *vis, Profile prof, WglContext *share) :
233 wglDeleteContext(hglrc);
242 * OpenGL library must be loaded by the time we call GDI.
245 const char * libgl_filename = getenv("TRACE_LIBGL");
247 if (libgl_filename) {
248 pfnChoosePixelFormat = &wglChoosePixelFormat;
249 pfnSetPixelFormat = &wglSetPixelFormat;
250 pfnSwapBuffers = &wglSwapBuffers;
252 libgl_filename = "OPENGL32";
255 __libGlHandle = LoadLibraryA(libgl_filename);
256 if (!__libGlHandle) {
257 std::cerr << "error: unable to open " << libgl_filename << "\n";
267 createVisual(bool doubleBuffer, Profile profile) {
268 if (profile != PROFILE_COMPAT) {
272 Visual *visual = new Visual();
274 visual->doubleBuffer = doubleBuffer;
280 createDrawable(const Visual *visual, int width, int height)
282 return new WglDrawable(visual, width, height);
286 createContext(const Visual *visual, Context *shareContext, Profile profile)
288 if (profile != PROFILE_COMPAT) {
292 return new WglContext(visual, profile, static_cast<WglContext *>(shareContext));
296 makeCurrent(Drawable *drawable, Context *context)
298 if (!drawable || !context) {
299 return wglMakeCurrent(NULL, NULL);
301 WglDrawable *wglDrawable = static_cast<WglDrawable *>(drawable);
302 WglContext *wglContext = static_cast<WglContext *>(context);
304 if (!wglContext->hglrc) {
305 wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
306 if (!wglContext->hglrc) {
307 std::cerr << "error: wglCreateContext failed\n";
311 if (wglContext->shareContext) {
313 bRet = wglShareLists(wglContext->shareContext->hglrc,
316 std::cerr << "warning: wglShareLists failed\n";
321 return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
326 processEvents(void) {
332 } /* namespace glws */