Subversion Repositories seema-scanner

Rev

Rev 16 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
16 jakw 1
#include "OpenGLContext.h"
2
 
3
#include <GL/gl.h>
4
#include <GL/glx.h>
5
#include <X11/Xlib.h>
6
#include <X11/Xcursor/Xcursor.h>
7
 
8
#include <stdio.h>
9
#include <string.h>
10
 
11
#include <unistd.h>
12
 
13
// vmode extension for mode settings, gamma control, etc.
14
#include <X11/extensions/xf86vmode.h>
15
 
16
// XRandR extension for virtual screens, mode setting, etc.
17
#include <X11/extensions/Xrandr.h>
18
 
19
struct OpenGLContext::OpenGLContextInfo{
20
    Display *display;
21
    Window window;
22
    GLXContext context;
23
    OpenGLContextInfo() : display(NULL), window(0), context(NULL){}
24
};
25
 
26
std::vector<ScreenInfo> OpenGLContext::GetScreenInfo(){
27
    std::vector<ScreenInfo> ret;
28
 
29
    // Connection to default X Server
30
    Display *display = XOpenDisplay(NULL);
31
 
32
    RROutput primaryOutput = XRRGetOutputPrimary(display, RootWindow(display, 0));
33
    XRRScreenResources* sr = XRRGetScreenResources(display, RootWindow(display, 0));
34
 
35
    // number of virtual (XRandr screens)
36
    unsigned int nVirtualScreens = sr->ncrtc;
37
 
38
    for (unsigned int j = 0;  j < nVirtualScreens;  j++){
39
        XRROutputInfo* oi;
40
        XRRCrtcInfo* ci;
41
        RROutput output;
42
 
43
        // check if the crt has outputs
44
        ci = XRRGetCrtcInfo(display, sr, sr->crtcs[j]);
45
        if (ci->noutput == 0){
46
            XRRFreeCrtcInfo(ci);
47
            continue;
48
        }
49
 
50
        output = ci->outputs[0];
51
 
52
        // if primaryoutput is among outputs, use that instead of the first
53
        for (int k = 0;  k < ci->noutput;  k++){
54
            if (ci->outputs[k] == primaryOutput){
55
                output = primaryOutput;
56
                break;
57
            }
58
        }
59
 
60
        // check that the output is connected
61
        oi = XRRGetOutputInfo(display, sr, output);
62
        if(oi->connection != RR_Connected){
63
            XRRFreeOutputInfo(oi);
64
            XRRFreeCrtcInfo(ci);
65
            continue;
66
        }
67
 
68
        ScreenInfo info;
69
        info.name = oi->name;
70
 
71
        // get current mode
72
        XRRModeInfo *modeInfo;
73
        for (int k = 0;  k < sr->nmode;  k++){
74
            if (sr->modes[k].id == ci->mode){
75
                modeInfo = sr->modes + k;
76
                break;
77
            }
78
        }
79
 
80
        info.resX = modeInfo->width;
81
        info.resY = modeInfo->height;
82
 
83
        info.posX = ci->x;
84
        info.posY = ci->y;
85
 
86
        ret.push_back(info);
87
    }
88
    XRRFreeScreenResources(sr);
89
 
90
    XCloseDisplay(display);
91
 
92
    return ret;
93
}
94
 
95
 
96
OpenGLContext::OpenGLContext(uint _screenNum) : screenNum(_screenNum){
97
 
98
    std::vector<ScreenInfo> virtualScreens = GetScreenInfo();
99
    if(screenNum > virtualScreens.size())
100
        std::cerr << "OpenGLContext: cannot open screen no. " << screenNum << "!" << std::endl;
101
 
102
    ScreenInfo screen = virtualScreens[screenNum];
103
    screenResX = screen.resX;
104
    screenResY = screen.resY;
105
 
106
    contextInfo = new OpenGLContextInfo();
107
    contextInfo->display = XOpenDisplay(NULL);
108
 
109
    int attrListDbl[] = {
110
        GLX_RGBA, GLX_DOUBLEBUFFER,
111
        GLX_RED_SIZE, 4,
112
        GLX_GREEN_SIZE, 4,
113
        GLX_BLUE_SIZE, 4,
114
        None
115
    };
116
 
117
    XVisualInfo *visualInfo = glXChooseVisual(contextInfo->display, 0, attrListDbl);
118
 
119
    int glxMajor, glxMinor = 0;
120
    glXQueryVersion(contextInfo->display, &glxMajor, &glxMinor);
121
    std::cout << "GLX-Version " << glxMajor << "." << glxMinor << std::endl;
122
 
123
    // Create a GLX OpenGLContext
124
    bool directRendering = True;
125
    contextInfo->context = glXCreateContext(contextInfo->display, visualInfo,  NULL, directRendering);
126
 
127
    // Check if OpenGLContext is direct
128
    if (glXIsDirect(contextInfo->display, contextInfo->context))
129
        std::cout << "OpenGLContext is direct." << std::endl;
130
    else
131
        std::cout << "OpenGLContext is not direct." << std::endl;
132
 
133
    // Create colormap
134
    Colormap colormap = XCreateColormap(contextInfo->display, RootWindow(contextInfo->display, 0), visualInfo->visual, AllocNone);
135
 
136
    // Create the actual window
137
    unsigned long wamask = CWColormap;
138
 
139
    XSetWindowAttributes wa;
140
    wa.colormap = colormap;
141
    wa.border_pixel = 0;
142
    wa.event_mask = 0;
143
 
144
    // bypass window manager (has no effect here)
17 jakw 145
    wa.override_redirect = True;
16 jakw 146
 
147
    // show no cursor
148
    wa.cursor = None;
149
 
150
    contextInfo->window = XCreateWindow(contextInfo->display, RootWindow(contextInfo->display, 0), screen.posX, screen.posY, screenResX, screenResY, 0, visualInfo->depth, InputOutput, visualInfo->visual, wamask, &wa);
151
 
152
    // move to correct position (necessary when not overriding redirect)
153
    XMoveWindow(contextInfo->display, contextInfo->window, screen.posX, screen.posY);
154
 
155
    if(!contextInfo->window)
156
        std::cerr << "Failed to create X window!" << std::endl;
157
 
158
    // bypass window manager (actually effects here)
159
    XSetWindowAttributes attributes;
17 jakw 160
    attributes.override_redirect = False;
16 jakw 161
    XChangeWindowAttributes(contextInfo->display, contextInfo->window, CWOverrideRedirect, &attributes);
162
 
163
    // Disable mouse cursor over window
164
    XcursorImage *cursorImage = XcursorImageCreate(1, 1);
165
    *cursorImage->pixels = 0;
166
    cursorImage->xhot = 0;
167
    cursorImage->yhot = 0;
168
    Cursor cursor = XcursorImageLoadCursor(contextInfo->display, cursorImage);
169
    XDefineCursor(contextInfo->display, contextInfo->window, cursor);
170
    XFreeCursor(contextInfo->display, cursor);
171
 
172
    // Connect the glx-OpenGLContext to the window
173
    glXMakeCurrent(contextInfo->display, contextInfo->window, contextInfo->context);
174
 
175
    // Window state
176
    Atom wmNetWmState = XInternAtom(contextInfo->display, "_NET_WM_STATE", 1);
177
    // raise window above most other windows
178
    Atom wmStateAbove = XInternAtom(contextInfo->display, "_NET_WM_STATE_ABOVE", 1);
179
    // define window as fullscreen
180
    Atom wmStateFullScreen = XInternAtom(contextInfo->display, "_NET_WM_STATE_FULLSCREEN", 1);
181
 
182
    XEvent event;
183
    memset(&event, 0, sizeof(event));
184
 
185
    event.type = ClientMessage;
186
    event.xclient.window = contextInfo->window;
187
    event.xclient.format = 32; // Data is 32-bit longs
188
    event.xclient.message_type = wmNetWmState;
189
    event.xclient.data.l[0] = 1; // Add the state
190
    event.xclient.data.l[2] = 0; // No secondary property
191
    event.xclient.data.l[3] = 1; // Sender is a normal application
192
 
193
    event.xclient.data.l[1] = wmStateAbove;
194
    XSendEvent(contextInfo->display, RootWindow(contextInfo->display, 0), False, SubstructureNotifyMask | SubstructureRedirectMask, &event);
195
 
196
    event.xclient.data.l[1] = wmStateFullScreen;
197
    XSendEvent(contextInfo->display, RootWindow(contextInfo->display, 0), False, SubstructureNotifyMask | SubstructureRedirectMask, &event);
198
 
199
//    // Set active window
200
//    Atom wmActiveWindow = XInternAtom(contextInfo->display, "_NET_WM_ACTIVE_WINDOW", 1);
201
 
202
//    event.xclient.message_type = wmActiveWindow;
203
//    event.xclient.data.l[0] = 1; // Sender is a normal application
204
//    event.xclient.data.l[1] = 0; // We don't really know the timestamp
205
 
206
//    XSendEvent(contextInfo->display, RootWindow(contextInfo->display, 0), False, SubstructureNotifyMask | SubstructureRedirectMask, &event);
207
 
208
 
209
    // Set swap interval to 1 for vsync
210
    const char *glx_extensions = glXQueryExtensionsString(contextInfo->display, 0);
211
    if (strstr(glx_extensions, "GLX_SGI_swap_control")) {
212
        PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalSGI");
213
        SwapIntervalSGI(1);
214
    } else if (strstr(glx_extensions, "GLX_EXT_swap_control")) {
215
        PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
216
        SwapIntervalEXT(contextInfo->display, contextInfo->window, 1);
217
    } else {
218
        std::cerr << "OpenGLContext Error: Could not access swap interval extension!" << std::endl;
219
    }
220
 
221
    // Raise window (necessary)
222
    XMapRaised(contextInfo->display, contextInfo->window);
223
 
224
    XFlush(contextInfo->display);
225
 
226
    // Adjust gamma to one
227
//    setGamma(1.9);
228
}
229
 
230
void OpenGLContext::setGamma(float gamma){
231
    // Adjust gamma
232
    XF86VidModeGamma xf86Gamma = {gamma, gamma, gamma};
233
    XF86VidModeSetGamma(contextInfo->display, screenNum, &xf86Gamma);
234
}
235
 
236
void OpenGLContext::makeContextCurrent(){
237
    glXMakeCurrent(contextInfo->display, contextInfo->window, contextInfo->context);
238
}
239
 
240
void OpenGLContext::flush(){
241
 
242
    // Swap buffers
243
    glXSwapBuffers(contextInfo->display, contextInfo->window);
244
 
245
    // Synchronize CPU with vsync buffer swap
246
    //glFinish();
247
    //glXWaitGL();
248
}
249
 
250
OpenGLContext::~OpenGLContext(){
251
    std::cout<<"Releasing OpenGL Context\n"<<std::flush;
252
    if(contextInfo->context){
253
        // Release context (None, NULL)
254
        if(!glXMakeCurrent(contextInfo->display, None, NULL))
255
            std::cerr << "Error. Could not release drawing OpenGLContext." << std::endl;
256
 
257
        glXDestroyContext(contextInfo->display, contextInfo->context);
258
        XCloseDisplay(contextInfo->display);
259
        delete contextInfo;
260
    }
261
}
262