Rev 36 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "OpenGLContext.h"
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// vmode extension for mode settings, gamma control, etc.
#include <X11/extensions/xf86vmode.h>
struct OpenGLContext::OpenGLContextInfo{
Display *display;
Window window;
GLXContext context;
OpenGLContextInfo() : display(NULL), window(0), context(NULL){}
};
std::vector<ScreenInfo> OpenGLContext::GetScreenInfo(){
std::vector<ScreenInfo> ret;
// Connection to default X Server
Display *display = XOpenDisplay(NULL);
unsigned int nScreens = ScreenCount(display);
for(unsigned int i=0; i<nScreens; i++){
Screen *XScreen = ScreenOfDisplay(display, i);
ScreenInfo screen;
screen.resX = XScreen->width;
screen.resY = XScreen->height;
char buff[100];
sprintf(buff, "XScreen no. %d", i);
screen.name = buff;
ret.push_back(screen);
}
XCloseDisplay(display);
return ret;
}
OpenGLContext::OpenGLContext(uint _screenNum) : screenNum(_screenNum){
contextInfo = new OpenGLContextInfo();
contextInfo->display = XOpenDisplay(NULL);
if((int)screenNum+1 > ScreenCount(contextInfo->display))
throw "Could not create OpenGLContext. Screen not available!";
Screen *xScreen = ScreenOfDisplay(contextInfo->display, screenNum);
screenResX = xScreen->width;
screenResY = xScreen->height;
// Create a OpenGL OpenGLContext on the specified X screen
contextInfo->window = RootWindow(contextInfo->display, screenNum);
int attrListDbl[] = {
GLX_RGBA, GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
None
};
XVisualInfo *visualInfo = glXChooseVisual(contextInfo->display, screenNum, attrListDbl);
int glxMajor, glxMinor = 0;
glXQueryVersion(contextInfo->display, &glxMajor, &glxMinor);
std::cout << "GLX-Version " << glxMajor << "." << glxMinor << std::endl;
// Create a GLX OpenGLContext
bool directRendering = True;
contextInfo->context = glXCreateContext(contextInfo->display, visualInfo, NULL, directRendering);
// Create colormap
Colormap colormap = XCreateColormap(contextInfo->display,contextInfo->window,visualInfo->visual,AllocNone);
// Create the actual window
unsigned long wamask = CWColormap;
XSetWindowAttributes wa;
wa.colormap = colormap;
wa.border_pixel = 0;
wa.event_mask = 0;
// bypass window manager
wa.override_redirect = False;
// show no cursor
wa.cursor = 0;
contextInfo->window = XCreateWindow(contextInfo->display, contextInfo->window, 0, 0, screenResX, screenResY, 0, visualInfo->depth, InputOutput, visualInfo->visual, wamask, &wa);
if(!contextInfo->window)
std::cerr << "Failed to create X window!" << std::endl;
// Raise window (necessary)
XMapRaised(contextInfo->display, contextInfo->window);
// Connect the glx-OpenGLContext to the window
glXMakeCurrent(contextInfo->display, contextInfo->window, contextInfo->context);
//XSaveOpenGLContext
XFlush(contextInfo->display);
// Check if OpenGLContext is direct
if (glXIsDirect(contextInfo->display, contextInfo->context))
std::cout << "OpenGLContext is direct\n";
else
std::cout << "OpenGLContext is not direct\n";
// Set swap interval to 1 for standard vsync
typedef GLvoid (*glXSwapIntervalSGIFunc) (GLint);
const char *glx_extensions = glXQueryExtensionsString(contextInfo->display, screenNum);
if (strstr(glx_extensions, "GLX_SGI_swap_control")) {
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalSGI");
SwapIntervalSGI(1);
} else if (strstr(glx_extensions, "GLX_EXT_swap_control")) {
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
SwapIntervalEXT(contextInfo->display, contextInfo->window, 1);
} else {
std::cerr << "OpenGLContext.Unix Error: Could not access swap interval extension!" << std::endl;
}
// Match projector gamma
setGamma(1.9);
}
void OpenGLContext::setGamma(float gamma){
// Adjust gamma
XF86VidModeGamma xf86Gamma = {gamma, gamma, gamma};
XF86VidModeSetGamma(contextInfo->display, screenNum, &xf86Gamma);
}
void OpenGLContext::makeContextCurrent(){
glXMakeCurrent(contextInfo->display, contextInfo->window, contextInfo->context);
}
void OpenGLContext::flush(){
// Swap buffers
glXSwapBuffers(contextInfo->display, contextInfo->window);
// Synchronize CPU with vsync buffer swap
//glFinish();
//glXWaitGL();
}
OpenGLContext::~OpenGLContext(){
std::cout<<"Releasing OpenGL Context\n"<<std::flush;
if(contextInfo->context){
// Release context (None, NULL)
if(!glXMakeCurrent(contextInfo->display, None, NULL))
std::cerr << "Error. Could not release drawing OpenGLContext." << std::endl;
glXDestroyContext(contextInfo->display, contextInfo->context);
XCloseDisplay(contextInfo->display);
delete contextInfo;
}
}