2 * The whole interface between GLWindow and the configuration stuff is rather
3 * icky, and _should_ be rewritten. It appears to work somehow, though ;-)
15 #include <X11/extensions/xf86vmode.h>
16 #include <X11/keysym.h>
25 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
27 /* this is ugly, but so is Win32 ;-) */
31 #define DEMOLIB_XASPECT 4.0
32 #define DEMOLIB_YASPECT 3.0
34 void GLWindow::resize(int x, int y, int w, int h)
36 /* Prevent division by zero */
41 float aspect = (float)w / (float)h;
42 if (aspect > DEMOLIB_XASPECT / DEMOLIB_YASPECT) {
43 int new_w = (int)((float)h * DEMOLIB_XASPECT / DEMOLIB_YASPECT);
46 } else if (aspect < DEMOLIB_XASPECT / DEMOLIB_YASPECT) {
47 int new_h = (int)((float)w * DEMOLIB_YASPECT / DEMOLIB_XASPECT);
52 glViewport(x, y, w, h);
54 glMatrixMode(GL_PROJECTION);
56 gluPerspective(53.0f, (GLfloat)w / (GLfloat)h, 1.0f, 500.0f);
57 glMatrixMode(GL_MODELVIEW);
61 // XClearWindow(this->dpy, this->win);
65 GLWindow::GLWindow(const char *title, int width, int height, int bpp, bool fullscreen, int zbuffer, int visual_id)
72 DEVMODE dmScreenSettings;
74 if (visual_id != -1) {
75 EnumDisplaySettings(NULL, visual_id, &dmScreenSettings);
76 width = dmScreenSettings.dmPelsWidth;
77 height = dmScreenSettings.dmPelsHeight;
78 bpp = dmScreenSettings.dmBitsPerPel;
80 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
81 dmScreenSettings.dmSize = sizeof(dmScreenSettings);
82 dmScreenSettings.dmPelsWidth = width;
83 dmScreenSettings.dmPelsHeight = height;
84 dmScreenSettings.dmBitsPerPel = bpp;
85 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
90 WindowRect.left = (long)0;
91 WindowRect.right = (long)width;
92 WindowRect.top = (long)0;
93 WindowRect.bottom = (long)height;
98 int dpyWidth = 0, dpyHeight = 0;
100 XF86VidModeModeInfo **modes;
105 unsigned int borderDummy;
107 static int attrList[] = {
113 GLX_DEPTH_SIZE, zbuffer,
117 #endif /* __linux__ */
122 this->height = height;
124 this->fullscreen = fullscreen;
125 this->zbuffer = zbuffer;
129 this->hInstance = GetModuleHandle(NULL);
130 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
131 wc.lpfnWndProc = WndProc;
134 wc.hInstance = this->hInstance;
137 wc.hbrBackground = NULL;
138 wc.lpszMenuName = NULL;
139 wc.lpszClassName = "Excess-OGL";
141 if( !RegisterClass(&wc) ) throw "Couldn't register Window Class";
145 /* set best mode to current */
148 /* get a connection */
149 this->dpy = XOpenDisplay(0);
150 this->screen = DefaultScreen(this->dpy);
153 XF86VidModeGetAllModeLines(this->dpy, this->screen, &modeNum, &modes);
155 /* save desktop-resolution before switching modes */
156 this->deskMode = *modes[0];
158 /* look for mode with requested resolution */
159 for (i = 0; i < modeNum; i++) {
160 if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height)) {
165 /* if we don't have it, bomb out */
166 if (bestMode == 0 && (modes[0]->hdisplay != width || modes[0]->vdisplay != height)) {
167 throw "Couldn't set requested screen mode.";
171 if (visual_id != -1) {
175 tmplate.visualid = visual_id;
176 vi = XGetVisualInfo(this->dpy, VisualIDMask, &tmplate, &nret);
178 throw "Couldn't get selected visual!";
181 /* get an appropriate visual */
182 vi = glXChooseVisual(this->dpy, this->screen, attrList);
184 throw "Couldn't get double-buffered visual";
188 /* create a GLX context */
189 this->ctx = glXCreateContext(this->dpy, vi, NULL, GL_TRUE);
191 /* create a color map (umm, needed?) */
192 Colormap cmap = XCreateColormap(this->dpy, RootWindow(this->dpy, vi->screen),
193 vi->visual, AllocNone);
194 this->attr.colormap = cmap;
196 /* make a blank cursor */
198 static char data[1] = {0};
203 blank = XCreateBitmapFromData(this->dpy, RootWindow(this->dpy, vi->screen), data, 1, 1);
205 throw "Out of memory!";
206 cursor = XCreatePixmapCursor(this->dpy, blank, blank, &dummy, &dummy, 0, 0);
207 XFreePixmap(this->dpy, blank);
208 this->attr.cursor = cursor;
211 this->attr.border_pixel = 0;
212 #endif /* __linux__ */
214 /* change screen mode */
217 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
218 throw "Couldn't set requested screen mode.";
222 XF86VidModeSwitchToMode(this->dpy, this->screen, modes[bestMode]);
223 XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0);
224 dpyWidth = modes[bestMode]->hdisplay;
225 dpyHeight = modes[bestMode]->vdisplay;
227 #endif /* __linux__ */
230 /* create the window */
233 dwExStyle = WS_EX_APPWINDOW;
237 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
238 dwStyle = WS_OVERLAPPEDWINDOW;
241 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
243 if (!(hWnd = CreateWindowEx(dwExStyle,
246 dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
248 WindowRect.right - WindowRect.left,
249 WindowRect.bottom - WindowRect.top,
255 throw "Could not change screenmode";
259 this->attr.background_pixel = 0;
262 /* create a fullscreen window */
263 this->attr.override_redirect = True;
264 this->attr.event_mask = KeyPressMask | ButtonPressMask |
267 this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen),
268 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
269 CWColormap | CWCursor | CWEventMask | CWOverrideRedirect,
271 XWarpPointer(this->dpy, None, this->win, 0, 0, 0, 0, 0, 0);
272 XMapRaised(this->dpy, this->win);
273 XGrabKeyboard(this->dpy, this->win, True, GrabModeAsync,
274 GrabModeAsync, CurrentTime);
275 XGrabPointer(this->dpy, this->win, True, ButtonPressMask,
276 GrabModeAsync, GrabModeAsync, this->win, None, CurrentTime);
278 /* create a window in window mode*/
279 this->attr.event_mask = KeyPressMask | ButtonPressMask |
281 this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen),
282 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
283 CWColormap | CWBorderPixel | CWEventMask, &this->attr);
285 /* only set window title and handle wm_delete_events if in windowed mode */
286 wmDelete = XInternAtom(this->dpy, "WM_DELETE_WINDOW", True);
287 XSetWMProtocols(this->dpy, this->win, &wmDelete, 1);
288 XSetStandardProperties(this->dpy, this->win, title,
289 title, None, NULL, 0, NULL);
290 XMapRaised(this->dpy, this->win);
292 #endif /* __linux__ */
295 static PIXELFORMATDESCRIPTOR pfd = {
296 sizeof(PIXELFORMATDESCRIPTOR),
298 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
315 PixelFormat = ChoosePixelFormat(hDC, &pfd);
316 if (PixelFormat == 0) {
317 throw "Could not find a usable pixelformat";
319 SetPixelFormat(hDC, PixelFormat, &pfd);
320 hRC = wglCreateContext(hDC);
321 wglMakeCurrent(hDC, hRC);
322 ShowWindow(hWnd, SW_SHOW);
323 SetForegroundWindow(hWnd);
326 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
329 /* connect the glx-context to the window */
330 glXMakeCurrent(this->dpy, this->win, this->ctx);
331 XClearWindow(this->dpy, this->win);
332 XGetGeometry(this->dpy, this->win, &winDummy, &this->x, &this->y,
333 &this->width, &this->height, &borderDummy, &this->bpp);
334 if (!glXIsDirect(this->dpy, this->ctx)) {
335 throw "No direct rendering (hardware acceleration) available!";
339 #endif /* __linux__ */
341 this->resize(0, 0, this->width, this->height);
344 GLWindow::~GLWindow()
348 if (!glXMakeCurrent(this->dpy, None, NULL)) {
349 throw "Could not release drawing context.";
351 glXDestroyContext(this->dpy, this->ctx);
358 XF86VidModeSwitchToMode(this->dpy, this->screen, &this->deskMode);
359 XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0);
362 ChangeDisplaySettings(NULL,0);
368 XCloseDisplay(this->dpy);
373 wglMakeCurrent(NULL, NULL);
374 wglDeleteContext(hRC);
378 if (hDC != NULL && ReleaseDC(hWnd, hDC)) hDC = NULL;
379 if (hWnd != NULL && DestroyWindow(hWnd)) hWnd = NULL;
380 UnregisterClass("Excess-OGL", hInstance);
384 void GLWindow::flip()
388 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
389 if (msg.message == WM_QUIT) {
392 TranslateMessage(&msg);
393 DispatchMessage(&msg);
396 SwapBuffers(this->hDC);
399 glXSwapBuffers(this->dpy, this->win);
403 bool GLWindow::is_done()
409 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
415 case SC_MONITORPOWER:
425 if (wParam == VK_ESCAPE)
430 win->resize(0, 0, LOWORD(lParam), HIWORD(lParam));
434 return DefWindowProc(hWnd, uMsg, wParam, lParam);