From a53c9432609090a8430d2d4f18d32df98455850c Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 13 Feb 2005 02:35:02 +0000 Subject: [PATCH] Initial commit. Import glwindow.{cpp,h} from the demolib, and make a simple Makefile etc. --- Makefile | 14 ++ ccbs_bigscreen.cpp | 10 ++ glwindow.cpp | 425 +++++++++++++++++++++++++++++++++++++++++++++ glwindow.h | 55 ++++++ 4 files changed, 504 insertions(+) create mode 100644 Makefile create mode 100644 ccbs_bigscreen.cpp create mode 100644 glwindow.cpp create mode 100644 glwindow.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f430885 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CC=gcc +CXX=g++ +LIBS=-lGL -lX11 -lXext -lXxf86vm +CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o glwindow.o + +all: ccbs-bigscreen + +ccbs-bigscreen: $(CCBS_BIGSCREEN_OBJS) + $(CXX) -o ccbs-bigscreen $(CCBS_BIGSCREEN_OBJS) $(LDFLAGS) $(LIBS) + +clean: + $(RM) $(CCBS_BIGSCREEN_OBJS) ccbs-bigscreen + +.PHONY: clean diff --git a/ccbs_bigscreen.cpp b/ccbs_bigscreen.cpp new file mode 100644 index 0000000..778720f --- /dev/null +++ b/ccbs_bigscreen.cpp @@ -0,0 +1,10 @@ +#include +#include +#include "glwindow.h" + +int main(int argc, char **argv) +{ + GLWindow glw("CCBS bigscreen", 800, 600, 32, false, 16, -1); + sleep(5); + return 0; +} diff --git a/glwindow.cpp b/glwindow.cpp new file mode 100644 index 0000000..45d46b5 --- /dev/null +++ b/glwindow.cpp @@ -0,0 +1,425 @@ +#include + +#ifdef WIN32 +#include +#endif + +#ifdef __linux__ +#include +#include +#include +#include +#endif + +#include +#include + +#include "glwindow.h" + +#ifdef WIN32 +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); + +/* this is ugly, but so is Win32 ;-) */ +GLWindow *win; +#endif + +#define DEMOLIB_XASPECT 4.0f +#define DEMOLIB_YASPECT 3.0f + +void GLWindow::resize(int x, int y, int w, int h) +{ + /* Prevent division by zero */ + if (h == 0) { + h = 1; + } + + float aspect = (float)w / (float)h; + if (aspect > DEMOLIB_XASPECT / DEMOLIB_YASPECT) { + int new_w = (int)((float)h * DEMOLIB_XASPECT / DEMOLIB_YASPECT); + x += (w - new_w) / 2; + w = new_w; + } else if (aspect < DEMOLIB_XASPECT / DEMOLIB_YASPECT) { + int new_h = (int)((float)w * DEMOLIB_YASPECT / DEMOLIB_XASPECT); + y += (h - new_h) / 2; + h = new_h; + } + + glViewport(x, y, w, h); + +#ifdef __linux__ +// XClearWindow(this->dpy, this->win); +#endif +} + +GLWindow::GLWindow(char *title, int width, int height, int bpp, bool fullscreen, int zbuffer, int visual_id) +{ +#ifdef WIN32 + GLuint PixelFormat; + WNDCLASS wc; + DWORD dwExStyle; + DWORD dwStyle; + DEVMODE dmScreenSettings; + + if (visual_id != -1) { + EnumDisplaySettings(NULL, visual_id, &dmScreenSettings); + width = dmScreenSettings.dmPelsWidth; + height = dmScreenSettings.dmPelsHeight; + bpp = dmScreenSettings.dmBitsPerPel; + } else { + memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); + dmScreenSettings.dmSize = sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = width; + dmScreenSettings.dmPelsHeight = height; + dmScreenSettings.dmBitsPerPel = bpp; + dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + } + win = this; + + RECT WindowRect; + WindowRect.left = (long)0; + WindowRect.right = (long)width; + WindowRect.top = (long)0; + WindowRect.bottom = (long)height; + +#endif /* WIN32 */ +#ifdef __linux__ + XVisualInfo *vi; + int dpyWidth = 0, dpyHeight = 0; + int i; + XF86VidModeModeInfo **modes; + int modeNum; + int bestMode; + Atom wmDelete; + Window winDummy; + unsigned int borderDummy; + + static int attrList[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, zbuffer, + GLX_STENCIL_SIZE, 4, + None + }; +#endif /* __linux__ */ + + this->x = 0; + this->y = 0; + this->width = width; + this->height = height; + this->bpp = bpp; + this->fullscreen = fullscreen; + this->zbuffer = zbuffer; + this->done = 0; + +#ifdef WIN32 + this->hInstance = GetModuleHandle(NULL); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = this->hInstance; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = "Excess-OGL"; + + if( !RegisterClass(&wc) ) throw "Couldn't register Window Class"; + +#endif /* WIN32 */ +#ifdef __linux__ + /* set best mode to current */ + bestMode = 0; + + /* get a connection */ + this->dpy = XOpenDisplay(0); + this->screen = DefaultScreen(this->dpy); + + if (fullscreen) { + XF86VidModeGetAllModeLines(this->dpy, this->screen, &modeNum, &modes); + + /* save desktop-resolution before switching modes */ + this->deskMode = *modes[0]; + + /* look for mode with requested resolution */ + for (i = 0; i < modeNum; i++) { + if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height)) { + bestMode = i; + } + } + + /* if we don't have it, bomb out */ + if (bestMode == 0 && (modes[0]->hdisplay != width || modes[0]->vdisplay != height)) { + throw "Couldn't set requested screen mode."; + } + } + + if (visual_id != -1) { + XVisualInfo tmplate; + int nret; + + tmplate.visualid = visual_id; + vi = XGetVisualInfo(this->dpy, VisualIDMask, &tmplate, &nret); + if (vi == NULL) { + throw "Couldn't get selected visual!"; + } + } else { + /* get an appropriate visual */ + vi = glXChooseVisual(this->dpy, this->screen, attrList); + if (vi == NULL) { + throw "Couldn't get double-buffered visual"; + } + } + + /* create a GLX context */ + this->ctx = glXCreateContext(this->dpy, vi, NULL, GL_TRUE); + + /* create a color map (umm, needed?) */ + Colormap cmap = XCreateColormap(this->dpy, RootWindow(this->dpy, vi->screen), + vi->visual, AllocNone); + this->attr.colormap = cmap; + + /* make a blank cursor */ + { + static char data[1] = {0}; + Cursor cursor; + Pixmap blank; + XColor dummy; + + blank = XCreateBitmapFromData(this->dpy, RootWindow(this->dpy, vi->screen), data, 1, 1); + if (blank == None) + throw "Out of memory!"; + cursor = XCreatePixmapCursor(this->dpy, blank, blank, &dummy, &dummy, 0, 0); + XFreePixmap(this->dpy, blank); + this->attr.cursor = cursor; + } + + this->attr.border_pixel = 0; +#endif /* __linux__ */ + + /* change screen mode */ + if (fullscreen) { +#ifdef WIN32 + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { + throw "Couldn't set requested screen mode."; + } +#endif /* WIN32 */ +#ifdef __linux__ + XF86VidModeSwitchToMode(this->dpy, this->screen, modes[bestMode]); + XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0); + dpyWidth = modes[bestMode]->hdisplay; + dpyHeight = modes[bestMode]->vdisplay; + XFree(modes); +#endif /* __linux__ */ + } + + /* create the window */ +#ifdef WIN32 + if (fullscreen) { + dwExStyle = WS_EX_APPWINDOW; + dwStyle = WS_POPUP; + ShowCursor(FALSE); + } else { + dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle = WS_OVERLAPPEDWINDOW; + } + + AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); + + if (!(hWnd = CreateWindowEx(dwExStyle, + "Excess-OGL", + title, + dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, + NULL, + this->hInstance, + NULL))) { + delete this; + throw "Could not change screenmode"; + } +#endif +#ifdef __linux__ + this->attr.background_pixel = 0; + + if (fullscreen) { + /* create a fullscreen window */ + this->attr.override_redirect = True; + this->attr.event_mask = KeyPressMask | ButtonPressMask | + StructureNotifyMask; + + this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen), + 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, + CWColormap | CWCursor | CWEventMask | CWOverrideRedirect, + &this->attr); + XWarpPointer(this->dpy, None, this->win, 0, 0, 0, 0, 0, 0); + XMapRaised(this->dpy, this->win); + XGrabKeyboard(this->dpy, this->win, True, GrabModeAsync, + GrabModeAsync, CurrentTime); + XGrabPointer(this->dpy, this->win, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, this->win, None, CurrentTime); + } else { + /* create a window in window mode*/ + this->attr.event_mask = KeyPressMask | ButtonPressMask | + StructureNotifyMask; + this->win = XCreateWindow(this->dpy, RootWindow(this->dpy, vi->screen), + 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, + CWColormap | CWBorderPixel | CWEventMask, &this->attr); + + /* only set window title and handle wm_delete_events if in windowed mode */ + wmDelete = XInternAtom(this->dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(this->dpy, this->win, &wmDelete, 1); + XSetStandardProperties(this->dpy, this->win, title, + title, None, NULL, 0, NULL); + XMapRaised(this->dpy, this->win); + } +#endif /* __linux__ */ + +#ifdef WIN32 + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + bpp, + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + zbuffer, + 8, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + hDC = GetDC(hWnd); + PixelFormat = ChoosePixelFormat(hDC, &pfd); + if (PixelFormat == 0) { + throw "Could not find a usable pixelformat"; + } + SetPixelFormat(hDC, PixelFormat, &pfd); + hRC = wglCreateContext(hDC); + wglMakeCurrent(hDC, hRC); + ShowWindow(hWnd, SW_SHOW); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); +#endif /* WIN32 */ +#ifdef __linux__ + /* connect the glx-context to the window */ + glXMakeCurrent(this->dpy, this->win, this->ctx); + XClearWindow(this->dpy, this->win); + XGetGeometry(this->dpy, this->win, &winDummy, &this->x, &this->y, + &this->width, &this->height, &borderDummy, &this->bpp); + if (!glXIsDirect(this->dpy, this->ctx)) { + throw "No direct rendering (hardware acceleration) available!"; + } + + nice(-7); +#endif /* __linux__ */ + + this->resize(0, 0, this->width, this->height); +} + +GLWindow::~GLWindow() +{ +#ifdef __linux__ + if (this->ctx) { + if (!glXMakeCurrent(this->dpy, None, NULL)) { + throw "Could not release drawing context."; + } + glXDestroyContext(this->dpy, this->ctx); + this->ctx = NULL; + } +#endif + + if (fullscreen) { +#ifdef __linux__ + XF86VidModeSwitchToMode(this->dpy, this->screen, &this->deskMode); + XF86VidModeSetViewPort(this->dpy, this->screen, 0, 0); +#endif +#ifdef WIN32 + ChangeDisplaySettings(NULL,0); + ShowCursor(TRUE); +#endif + } + +#ifdef __linux__ + XCloseDisplay(this->dpy); +#endif + +#ifdef WIN32 + if (hRC) { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hRC); + hRC = NULL; + } + + if (hDC != NULL && ReleaseDC(hWnd, hDC)) hDC = NULL; + if (hWnd != NULL && DestroyWindow(hWnd)) hWnd = NULL; + UnregisterClass("Excess-OGL", hInstance); +#endif +} + +void GLWindow::flip() +{ +#ifdef WIN32 + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + this->done = TRUE; + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + SwapBuffers(this->hDC); +#endif +#ifdef __linux__ + glXSwapBuffers(this->dpy, this->win); +#endif +} + +bool GLWindow::is_done() +{ + return this->done; +} + +#ifdef WIN32 +LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_SYSCOMMAND: + switch (wParam) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_KEYUP: + if (wParam == VK_ESCAPE) + PostQuitMessage(0); + return 0; + + case WM_SIZE: + win->resize(0, 0, LOWORD(lParam), HIWORD(lParam)); + return 0; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} +#endif //WIN32 diff --git a/glwindow.h b/glwindow.h new file mode 100644 index 0000000..a2a8e32 --- /dev/null +++ b/glwindow.h @@ -0,0 +1,55 @@ +#ifndef _GLWINDOW_H +#define _GLWINDOW_H + +#ifdef WIN32 +#include +#endif + +#ifdef __linux__ +#include +#include +#include +#endif + +#include +#include + +class GLWindow { +public: + GLWindow(char *title, int width, int height, int bpp, bool fullscreen, int zbuffer, int visual_id); + ~GLWindow(); + void resize(int x, int y, int w, int h); + void flip(); + bool is_done(); + + friend class DemoHandler; + friend class DirectSoundAudioDriver; + +protected: +#ifdef WIN32 + HDC hDC; + HGLRC hRC; + HWND hWnd; + HINSTANCE hInstance; +#endif +#ifdef __linux__ + Display *dpy; + int screen; + Window win; + GLXContext ctx; + XSetWindowAttributes attr; + Bool fs; + XF86VidModeModeInfo deskMode; +#endif + + char *title; + bool fullscreen; + int x, y; + unsigned int width, height; + unsigned int bpp; + int zbuffer; + bool done; + void initGL(); +}; + +#endif -- 2.39.2