10 #include <X11/extensions/xf86vmode.h>
11 #include <X11/keysym.h>
20 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
22 /* this is ugly, but so is Win32 ;-) */
26 #define DEMOLIB_XASPECT 4.0f
27 #define DEMOLIB_YASPECT 3.0f
29 void GLWindow::resize(int x, int y, int w, int h)
31 /* Prevent division by zero */
36 float aspect = (float)w / (float)h;
37 if (aspect > DEMOLIB_XASPECT / DEMOLIB_YASPECT) {
38 int new_w = (int)((float)h * DEMOLIB_XASPECT / DEMOLIB_YASPECT);
41 } else if (aspect < DEMOLIB_XASPECT / DEMOLIB_YASPECT) {
42 int new_h = (int)((float)w * DEMOLIB_YASPECT / DEMOLIB_XASPECT);
47 glViewport(x, y, w, h);
50 // XClearWindow(this->dpy, this->win);
54 GLWindow::GLWindow(char *title, int width, int height, int bpp, bool fullscreen, int zbuffer, int visual_id)
61 DEVMODE dmScreenSettings;
63 if (visual_id != -1) {
64 EnumDisplaySettings(NULL, visual_id, &dmScreenSettings);
65 width = dmScreenSettings.dmPelsWidth;
66 height = dmScreenSettings.dmPelsHeight;
67 bpp = dmScreenSettings.dmBitsPerPel;
69 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
70 dmScreenSettings.dmSize = sizeof(dmScreenSettings);
71 dmScreenSettings.dmPelsWidth = width;
72 dmScreenSettings.dmPelsHeight = height;
73 dmScreenSettings.dmBitsPerPel = bpp;
74 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
79 WindowRect.left = (long)0;
80 WindowRect.right = (long)width;
81 WindowRect.top = (long)0;
82 WindowRect.bottom = (long)height;
87 int dpyWidth = 0, dpyHeight = 0;
89 XF86VidModeModeInfo **modes;
94 unsigned int borderDummy;
96 static int attrList[] = {
102 GLX_DEPTH_SIZE, zbuffer,
106 #endif /* __linux__ */
111 this->height = height;
113 this->fullscreen = fullscreen;
114 this->zbuffer = zbuffer;
118 this->hInstance = GetModuleHandle(NULL);
119 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
120 wc.lpfnWndProc = WndProc;
123 wc.hInstance = this->hInstance;
126 wc.hbrBackground = NULL;
127 wc.lpszMenuName = NULL;
128 wc.lpszClassName = "Excess-OGL";
130 if( !RegisterClass(&wc) ) throw "Couldn't register Window Class";
134 /* set best mode to current */
137 /* get a connection */
138 this->dpy = XOpenDisplay(0);
139 this->screen = DefaultScreen(this->dpy);
142 XF86VidModeGetAllModeLines(this->dpy, this->screen, &modeNum, &modes);
144 /* save desktop-resolution before switching modes */
145 this->deskMode = *modes[0];
147 /* look for mode with requested resolution */
148 for (i = 0; i < modeNum; i++) {
149 if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height)) {
154 /* if we don't have it, bomb out */
155 if (bestMode == 0 && (modes[0]->hdisplay != width || modes[0]->vdisplay != height)) {
156 throw "Couldn't set requested screen mode.";
160 if (visual_id != -1) {
164 tmplate.visualid = visual_id;
165 vi = XGetVisualInfo(this->dpy, VisualIDMask, &tmplate, &nret);
167 throw "Couldn't get selected visual!";
170 /* get an appropriate visual */
171 vi = glXChooseVisual(this->dpy, this->screen, attrList);
173 throw "Couldn't get double-buffered visual";
177 /* create a GLX context */
178 this->ctx = glXCreateContext(this->dpy, vi, NULL, GL_TRUE);
180 /* create a color map (umm, needed?) */
181 Colormap cmap = XCreateColormap(this->dpy, RootWindow(this->dpy, vi->screen),
182 vi->visual, AllocNone);
183 this->attr.colormap = cmap;
185 /* make a blank cursor */
187 static char data[1] = {0};
192 blank = XCreateBitmapFromData(this->dpy, RootWindow(this->dpy, vi->screen), data, 1, 1);
194 throw "Out of memory!";
195 cursor = XCreatePixmapCursor(this->dpy, blank, blank, &dummy, &dummy, 0, 0);
196 XFreePixmap(this->dpy, blank);
197 this->attr.cursor = cursor;
200 this->attr.border_pixel = 0;
201 #endif /* __linux__ */
203 /* change screen mode */
206 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
207 throw "Couldn't set requested screen mode.";
211 XF86VidModeSwitchToMode(this->dpy, this->screen, modes[bestMode]);
212 XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0);
213 dpyWidth = modes[bestMode]->hdisplay;
214 dpyHeight = modes[bestMode]->vdisplay;
216 #endif /* __linux__ */
219 /* create the window */
222 dwExStyle = WS_EX_APPWINDOW;
226 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
227 dwStyle = WS_OVERLAPPEDWINDOW;
230 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
232 if (!(hWnd = CreateWindowEx(dwExStyle,
235 dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
237 WindowRect.right - WindowRect.left,
238 WindowRect.bottom - WindowRect.top,
244 throw "Could not change screenmode";
248 this->attr.background_pixel = 0;
251 /* create a fullscreen window */
252 this->attr.override_redirect = True;
253 this->attr.event_mask = KeyPressMask | ButtonPressMask |
256 this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen),
257 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
258 CWColormap | CWCursor | CWEventMask | CWOverrideRedirect,
260 XWarpPointer(this->dpy, None, this->win, 0, 0, 0, 0, 0, 0);
261 XMapRaised(this->dpy, this->win);
262 XGrabKeyboard(this->dpy, this->win, True, GrabModeAsync,
263 GrabModeAsync, CurrentTime);
264 XGrabPointer(this->dpy, this->win, True, ButtonPressMask,
265 GrabModeAsync, GrabModeAsync, this->win, None, CurrentTime);
267 /* create a window in window mode*/
268 this->attr.event_mask = KeyPressMask | ButtonPressMask |
270 this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen),
271 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
272 CWColormap | CWBorderPixel | CWEventMask, &this->attr);
274 /* only set window title and handle wm_delete_events if in windowed mode */
275 wmDelete = XInternAtom(this->dpy, "WM_DELETE_WINDOW", True);
276 XSetWMProtocols(this->dpy, this->win, &wmDelete, 1);
277 XSetStandardProperties(this->dpy, this->win, title,
278 title, None, NULL, 0, NULL);
279 XMapRaised(this->dpy, this->win);
281 #endif /* __linux__ */
284 static PIXELFORMATDESCRIPTOR pfd = {
285 sizeof(PIXELFORMATDESCRIPTOR),
287 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
304 PixelFormat = ChoosePixelFormat(hDC, &pfd);
305 if (PixelFormat == 0) {
306 throw "Could not find a usable pixelformat";
308 SetPixelFormat(hDC, PixelFormat, &pfd);
309 hRC = wglCreateContext(hDC);
310 wglMakeCurrent(hDC, hRC);
311 ShowWindow(hWnd, SW_SHOW);
312 SetForegroundWindow(hWnd);
315 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
318 /* connect the glx-context to the window */
319 glXMakeCurrent(this->dpy, this->win, this->ctx);
320 XClearWindow(this->dpy, this->win);
321 XGetGeometry(this->dpy, this->win, &winDummy, &this->x, &this->y,
322 &this->width, &this->height, &borderDummy, &this->bpp);
323 if (!glXIsDirect(this->dpy, this->ctx)) {
324 throw "No direct rendering (hardware acceleration) available!";
328 #endif /* __linux__ */
330 this->resize(0, 0, this->width, this->height);
333 GLWindow::~GLWindow()
337 if (!glXMakeCurrent(this->dpy, None, NULL)) {
338 throw "Could not release drawing context.";
340 glXDestroyContext(this->dpy, this->ctx);
347 XF86VidModeSwitchToMode(this->dpy, this->screen, &this->deskMode);
348 XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0);
351 ChangeDisplaySettings(NULL,0);
357 XCloseDisplay(this->dpy);
362 wglMakeCurrent(NULL, NULL);
363 wglDeleteContext(hRC);
367 if (hDC != NULL && ReleaseDC(hWnd, hDC)) hDC = NULL;
368 if (hWnd != NULL && DestroyWindow(hWnd)) hWnd = NULL;
369 UnregisterClass("Excess-OGL", hInstance);
373 void GLWindow::flip()
377 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
378 if (msg.message == WM_QUIT) {
381 TranslateMessage(&msg);
382 DispatchMessage(&msg);
385 SwapBuffers(this->hDC);
388 glXSwapBuffers(this->dpy, this->win);
392 bool GLWindow::is_done()
398 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
404 case SC_MONITORPOWER:
414 if (wParam == VK_ESCAPE)
419 win->resize(0, 0, LOWORD(lParam), HIWORD(lParam));
423 return DefWindowProc(hWnd, uMsg, wParam, lParam);