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 **************************************************************************/
35 static LRESULT CALLBACK
36 WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
40 case WM_GETMINMAXINFO:
41 // Allow to create a window bigger than the desktop
42 pMMI = (MINMAXINFO *)lParam;
43 pMMI->ptMaxSize.x = 60000;
44 pMMI->ptMaxSize.y = 60000;
45 pMMI->ptMaxTrackSize.x = 60000;
46 pMMI->ptMaxTrackSize.y = 60000;
52 return DefWindowProc(hWnd, uMsg, wParam, lParam);
56 class WglDrawable : public Drawable
63 PIXELFORMATDESCRIPTOR pfd;
66 WglDrawable(const Visual *vis, int width, int height) :
67 Drawable(vis, width, height)
69 static bool first = TRUE;
74 memset(&wc, 0, sizeof wc);
75 wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
76 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
77 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
78 wc.lpfnWndProc = WndProc;
79 wc.lpszClassName = "glretrace";
80 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
86 dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
92 rect.right = rect.left + width;
93 rect.bottom = rect.top + height;
95 AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
97 hWnd = CreateWindowEx(dwExStyle,
98 "glretrace", /* wc.lpszClassName */
103 rect.right - rect.left, /* width */
104 rect.bottom - rect.top, /* height */
111 memset(&pfd, 0, sizeof pfd);
118 pfd.cStencilBits = 1;
119 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
120 pfd.iLayerType = PFD_MAIN_PLANE;
121 pfd.iPixelType = PFD_TYPE_RGBA;
122 pfd.nSize = sizeof(pfd);
125 if (visual->doubleBuffer) {
126 pfd.dwFlags |= PFD_DOUBLEBUFFER;
129 iPixelFormat = ChoosePixelFormat(hDC, &pfd);
131 SetPixelFormat(hDC, iPixelFormat, &pfd);
135 ReleaseDC(hWnd, hDC);
140 resize(int w, int h) {
141 if (w == width && h == height) {
145 RECT rClient, rWindow;
146 GetClientRect(hWnd, &rClient);
147 GetWindowRect(hWnd, &rWindow);
148 w += (rWindow.right - rWindow.left) - rClient.right;
149 h += (rWindow.bottom - rWindow.top) - rClient.bottom;
150 SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, w, h, SWP_NOMOVE);
152 Drawable::resize(w, h);
160 ShowWindow(hWnd, SW_SHOW);
165 void swapBuffers(void) {
168 // Drain message queue to prevent window from being considered
171 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
172 TranslateMessage(&msg);
173 DispatchMessage(&msg);
179 class WglContext : public Context
183 WglContext *shareContext;
185 WglContext(const Visual *vis, Profile prof, WglContext *share) :
193 wglDeleteContext(hglrc);
202 * OpenGL library must be loaded by the time we call GDI.
205 const char * libgl_filename = getenv("TRACE_LIBGL");
207 if (!libgl_filename) {
208 libgl_filename = "OPENGL32";
211 __libGlHandle = LoadLibraryA(libgl_filename);
212 if (!__libGlHandle) {
213 std::cerr << "error: unable to open " << libgl_filename << "\n";
223 createVisual(bool doubleBuffer, Profile profile) {
224 if (profile != PROFILE_COMPAT) {
228 Visual *visual = new Visual();
230 visual->doubleBuffer = doubleBuffer;
236 createDrawable(const Visual *visual, int width, int height)
238 return new WglDrawable(visual, width, height);
242 createContext(const Visual *visual, Context *shareContext, Profile profile)
244 if (profile != PROFILE_COMPAT) {
248 return new WglContext(visual, profile, static_cast<WglContext *>(shareContext));
252 makeCurrent(Drawable *drawable, Context *context)
254 if (!drawable || !context) {
255 return wglMakeCurrent(NULL, NULL);
257 WglDrawable *wglDrawable = static_cast<WglDrawable *>(drawable);
258 WglContext *wglContext = static_cast<WglContext *>(context);
260 if (!wglContext->hglrc) {
261 wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
262 if (!wglContext->hglrc) {
265 if (wglContext->shareContext) {
266 wglShareLists(wglContext->shareContext->hglrc,
271 return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
276 processEvents(void) {
282 } /* namespace glws */