]> git.cworth.org Git - apitrace/blob - glws_wgl.cpp
Merge branch 'master' into d3dretrace
[apitrace] / glws_wgl.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 #include <iostream>
27
28 #include "glproc.hpp"
29 #include "glws.hpp"
30
31
32 namespace glws {
33
34
35 static LRESULT CALLBACK
36 WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
37 {
38     MINMAXINFO *pMMI;
39     switch (uMsg) {
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;
47         break;
48     default:
49         break;
50     }
51
52     return DefWindowProc(hWnd, uMsg, wParam, lParam);
53 }
54
55
56 class WglDrawable : public Drawable
57 {
58 public:
59     DWORD dwExStyle;
60     DWORD dwStyle;
61     HWND hWnd;
62     HDC hDC;
63     PIXELFORMATDESCRIPTOR pfd;
64     int iPixelFormat;
65
66     WglDrawable(const Visual *vis, int width, int height) :
67         Drawable(vis, width, height)
68     {
69         static bool first = TRUE;
70         RECT rect;
71
72         if (first) {
73             WNDCLASS wc;
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;
81             RegisterClass(&wc);
82             first = FALSE;
83         }
84
85         dwExStyle = 0;
86         dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
87
88         int x = 0, y = 0;
89
90         rect.left = x;
91         rect.top = y;
92         rect.right = rect.left + width;
93         rect.bottom = rect.top + height;
94
95         AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
96
97         hWnd = CreateWindowEx(dwExStyle,
98                               "glretrace", /* wc.lpszClassName */
99                               NULL,
100                               dwStyle,
101                               0, /* x */
102                               0, /* y */
103                               rect.right - rect.left, /* width */
104                               rect.bottom - rect.top, /* height */
105                               NULL,
106                               NULL,
107                               NULL,
108                               NULL);
109         hDC = GetDC(hWnd);
110    
111         memset(&pfd, 0, sizeof pfd);
112         pfd.cColorBits = 4;
113         pfd.cRedBits = 1;
114         pfd.cGreenBits = 1;
115         pfd.cBlueBits = 1;
116         pfd.cAlphaBits = 1;
117         pfd.cDepthBits = 1;
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);
123         pfd.nVersion = 1;
124
125         if (visual->doubleBuffer) {
126            pfd.dwFlags |= PFD_DOUBLEBUFFER;
127         }
128
129         iPixelFormat = ChoosePixelFormat(hDC, &pfd);
130
131         SetPixelFormat(hDC, iPixelFormat, &pfd);
132     }
133
134     ~WglDrawable() {
135         ReleaseDC(hWnd, hDC);
136         DestroyWindow(hWnd);
137     }
138     
139     void
140     resize(int w, int h) {
141         if (w == width && h == height) {
142             return;
143         }
144
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);
151
152         Drawable::resize(w, h);
153     }
154
155     void show(void) {
156         if (visible) {
157             return;
158         }
159
160         ShowWindow(hWnd, SW_SHOW);
161
162         Drawable::show();
163     }
164
165     void swapBuffers(void) {
166         SwapBuffers(hDC);
167
168         // Drain message queue to prevent window from being considered
169         // non-responsive
170         MSG msg;
171         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
172             TranslateMessage(&msg);
173             DispatchMessage(&msg);
174         }
175     }
176 };
177
178
179 class WglContext : public Context
180 {
181 public:
182     HGLRC hglrc;
183     WglContext *shareContext;
184
185     WglContext(const Visual *vis, Profile prof, WglContext *share) :
186         Context(vis, prof),
187         hglrc(0),
188         shareContext(share)
189     {}
190
191     ~WglContext() {
192         if (hglrc) {
193             wglDeleteContext(hglrc);
194         }
195     }
196 };
197
198
199 void
200 init(void) {
201     /*
202      * OpenGL library must be loaded by the time we call GDI.
203      */
204
205     const char * libgl_filename = getenv("TRACE_LIBGL");
206
207     if (!libgl_filename) {
208         libgl_filename = "OPENGL32";
209     }
210
211     __libGlHandle = LoadLibraryA(libgl_filename);
212     if (!__libGlHandle) {
213         std::cerr << "error: unable to open " << libgl_filename << "\n";
214         exit(1);
215     }
216 }
217
218 void
219 cleanup(void) {
220 }
221
222 Visual *
223 createVisual(bool doubleBuffer, Profile profile) {
224     if (profile != PROFILE_COMPAT) {
225         return NULL;
226     }
227
228     Visual *visual = new Visual();
229
230     visual->doubleBuffer = doubleBuffer;
231
232     return visual;
233 }
234
235 Drawable *
236 createDrawable(const Visual *visual, int width, int height)
237 {
238     return new WglDrawable(visual, width, height);
239 }
240
241 Context *
242 createContext(const Visual *visual, Context *shareContext, Profile profile)
243 {
244     if (profile != PROFILE_COMPAT) {
245         return NULL;
246     }
247
248     return new WglContext(visual, profile, static_cast<WglContext *>(shareContext));
249 }
250
251 bool
252 makeCurrent(Drawable *drawable, Context *context)
253 {
254     if (!drawable || !context) {
255         return wglMakeCurrent(NULL, NULL);
256     } else {
257         WglDrawable *wglDrawable = static_cast<WglDrawable *>(drawable);
258         WglContext *wglContext = static_cast<WglContext *>(context);
259
260         if (!wglContext->hglrc) {
261             wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
262             if (!wglContext->hglrc) {
263                 return false;
264             }
265             if (wglContext->shareContext) {
266                 wglShareLists(wglContext->shareContext->hglrc,
267                               wglContext->hglrc);
268             }
269         }
270
271         return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
272     }
273 }
274
275 bool
276 processEvents(void) {
277     // TODO
278     return true;
279 }
280
281
282 } /* namespace glws */