]> git.cworth.org Git - apitrace/blob - glws_wgl.cpp
Merge branch 'master' into d2d
[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 "glproc.hpp"
27 #include "glws.hpp"
28
29
30 namespace glws {
31
32
33 static LRESULT CALLBACK
34 WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
35 {
36     MINMAXINFO *pMMI;
37     switch (uMsg) {
38     case WM_GETMINMAXINFO:
39         // Allow to create a window bigger than the desktop
40         pMMI = (MINMAXINFO *)lParam;
41         pMMI->ptMaxSize.x = 60000;
42         pMMI->ptMaxSize.y = 60000;
43         pMMI->ptMaxTrackSize.x = 60000;
44         pMMI->ptMaxTrackSize.y = 60000;
45         break;
46     default:
47         break;
48     }
49
50     return DefWindowProc(hWnd, uMsg, wParam, lParam);
51 }
52
53
54 class WglDrawable : public Drawable
55 {
56 public:
57     DWORD dwExStyle;
58     DWORD dwStyle;
59     HWND hWnd;
60     HDC hDC;
61     PIXELFORMATDESCRIPTOR pfd;
62     int iPixelFormat;
63
64     WglDrawable(const Visual *vis, int width, int height) :
65         Drawable(vis, width, height)
66     {
67         static bool first = TRUE;
68         RECT rect;
69
70         if (first) {
71             WNDCLASS wc;
72             memset(&wc, 0, sizeof wc);
73             wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
74             wc.hCursor = LoadCursor(NULL, IDC_ARROW);
75             wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
76             wc.lpfnWndProc = WndProc;
77             wc.lpszClassName = "glretrace";
78             wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
79             RegisterClass(&wc);
80             first = FALSE;
81         }
82
83         dwExStyle = 0;
84         dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
85
86         int x = 0, y = 0;
87
88         rect.left = x;
89         rect.top = y;
90         rect.right = rect.left + width;
91         rect.bottom = rect.top + height;
92
93         AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
94
95         hWnd = CreateWindowEx(dwExStyle,
96                               "glretrace", /* wc.lpszClassName */
97                               NULL,
98                               dwStyle,
99                               0, /* x */
100                               0, /* y */
101                               rect.right - rect.left, /* width */
102                               rect.bottom - rect.top, /* height */
103                               NULL,
104                               NULL,
105                               NULL,
106                               NULL);
107         hDC = GetDC(hWnd);
108    
109         memset(&pfd, 0, sizeof pfd);
110         pfd.cColorBits = 4;
111         pfd.cRedBits = 1;
112         pfd.cGreenBits = 1;
113         pfd.cBlueBits = 1;
114         pfd.cAlphaBits = 1;
115         pfd.cDepthBits = 1;
116         pfd.cStencilBits = 1;
117         pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
118         pfd.iLayerType = PFD_MAIN_PLANE;
119         pfd.iPixelType = PFD_TYPE_RGBA;
120         pfd.nSize = sizeof(pfd);
121         pfd.nVersion = 1;
122
123         if (visual->doubleBuffer) {
124            pfd.dwFlags |= PFD_DOUBLEBUFFER;
125         }
126
127         iPixelFormat = ChoosePixelFormat(hDC, &pfd);
128
129         SetPixelFormat(hDC, iPixelFormat, &pfd);
130     }
131
132     ~WglDrawable() {
133         ReleaseDC(hWnd, hDC);
134         DestroyWindow(hWnd);
135     }
136     
137     void
138     resize(int w, int h) {
139         if (w == width && h == height) {
140             return;
141         }
142
143         RECT rClient, rWindow;
144         GetClientRect(hWnd, &rClient);
145         GetWindowRect(hWnd, &rWindow);
146         w += (rWindow.right  - rWindow.left) - rClient.right;
147         h += (rWindow.bottom - rWindow.top)  - rClient.bottom;
148         SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, w, h, SWP_NOMOVE);
149
150         Drawable::resize(w, h);
151     }
152
153     void show(void) {
154         if (visible) {
155             return;
156         }
157
158         ShowWindow(hWnd, SW_SHOW);
159
160         Drawable::show();
161     }
162
163     void swapBuffers(void) {
164         SwapBuffers(hDC);
165
166         // Drain message queue to prevent window from being considered
167         // non-responsive
168         MSG msg;
169         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
170             TranslateMessage(&msg);
171             DispatchMessage(&msg);
172         }
173     }
174 };
175
176
177 class WglContext : public Context
178 {
179 public:
180     HGLRC hglrc;
181     WglContext *shareContext;
182
183     WglContext(const Visual *vis, Profile prof, WglContext *share) :
184         Context(vis, prof),
185         hglrc(0),
186         shareContext(share)
187     {}
188
189     ~WglContext() {
190         if (hglrc) {
191             wglDeleteContext(hglrc);
192         }
193     }
194 };
195
196
197 void
198 init(void) {
199     /*
200      * OpenGL library must be loaded by the time we call GDI.
201      */
202     __libGlHandle = LoadLibraryA("OPENGL32");
203 }
204
205 void
206 cleanup(void) {
207 }
208
209 Visual *
210 createVisual(bool doubleBuffer, Profile profile) {
211     if (profile != PROFILE_COMPAT) {
212         return NULL;
213     }
214
215     Visual *visual = new Visual();
216
217     visual->doubleBuffer = doubleBuffer;
218
219     return visual;
220 }
221
222 Drawable *
223 createDrawable(const Visual *visual, int width, int height)
224 {
225     return new WglDrawable(visual, width, height);
226 }
227
228 Context *
229 createContext(const Visual *visual, Context *shareContext, Profile profile)
230 {
231     if (profile != PROFILE_COMPAT) {
232         return NULL;
233     }
234
235     return new WglContext(visual, profile, static_cast<WglContext *>(shareContext));
236 }
237
238 bool
239 makeCurrent(Drawable *drawable, Context *context)
240 {
241     if (!drawable || !context) {
242         return wglMakeCurrent(NULL, NULL);
243     } else {
244         WglDrawable *wglDrawable = static_cast<WglDrawable *>(drawable);
245         WglContext *wglContext = static_cast<WglContext *>(context);
246
247         if (!wglContext->hglrc) {
248             wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
249             if (!wglContext->hglrc) {
250                 return false;
251             }
252             if (wglContext->shareContext) {
253                 wglShareLists(wglContext->shareContext->hglrc,
254                               wglContext->hglrc);
255             }
256         }
257
258         return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
259     }
260 }
261
262 bool
263 processEvents(void) {
264     // TODO
265     return true;
266 }
267
268
269 } /* namespace glws */