00001
00002
00003
00004 #include "video_X.h"
00005 #include <iostream>
00006
00007
00008 #ifdef GLX_SGIX_fbconfig
00009 const int video_X::VISUAL_ATTRIBUTES_8BPP[] = {
00010 GLX_DRAWABLE_TYPE_SGIX, GLX_WINDOW_BIT_SGIX,
00011 GLX_RENDER_TYPE_SGIX, GLX_RGBA_BIT_SGIX,
00012 GLX_DOUBLEBUFFER, GL_TRUE,
00013 GLX_RED_SIZE, 2,
00014 GLX_GREEN_SIZE, 2,
00015 GLX_BLUE_SIZE, 2,
00016 GLX_ALPHA_SIZE, 2,
00017 None
00018 };
00019
00020 const int video_X::VISUAL_ATTRIBUTES_16BPP[] = {
00021 GLX_DRAWABLE_TYPE_SGIX, GLX_WINDOW_BIT_SGIX,
00022 GLX_RENDER_TYPE_SGIX, GLX_RGBA_BIT_SGIX,
00023 GLX_DOUBLEBUFFER, GL_TRUE,
00024 GLX_RED_SIZE, 4,
00025 GLX_GREEN_SIZE, 4,
00026 GLX_BLUE_SIZE, 4,
00027 GLX_ALPHA_SIZE, 4,
00028 None
00029 };
00030
00031 const int video_X::VISUAL_ATTRIBUTES_24BPP[] = {
00032 GLX_DRAWABLE_TYPE_SGIX, GLX_WINDOW_BIT_SGIX,
00033 GLX_RENDER_TYPE_SGIX, GLX_RGBA_BIT_SGIX,
00034 GLX_DOUBLEBUFFER, GL_TRUE,
00035 GLX_RED_SIZE, 6,
00036 GLX_GREEN_SIZE, 6,
00037 GLX_BLUE_SIZE, 6,
00038 GLX_ALPHA_SIZE, 6,
00039 None
00040 };
00041
00042 const int video_X::VISUAL_ATTRIBUTES_32BPP[] = {
00043 GLX_DRAWABLE_TYPE_SGIX, GLX_WINDOW_BIT_SGIX,
00044 GLX_RENDER_TYPE_SGIX, GLX_RGBA_BIT_SGIX,
00045 GLX_DOUBLEBUFFER, GL_TRUE,
00046 GLX_RED_SIZE, 8,
00047 GLX_GREEN_SIZE, 8,
00048 GLX_BLUE_SIZE, 8,
00049 GLX_ALPHA_SIZE, 8,
00050 None
00051 };
00052 #else
00053 const int video_X::VISUAL_ATTRIBUTES_8BPP[] = {
00054 GLX_DOUBLEBUFFER, GL_TRUE,
00055 GLX_RED_SIZE, 2,
00056 GLX_GREEN_SIZE, 2,
00057 GLX_BLUE_SIZE, 2,
00058 GLX_ALPHA_SIZE, 2,
00059 None
00060 };
00061
00062 const int video_X::VISUAL_ATTRIBUTES_16BPP[] = {
00063 GLX_DOUBLEBUFFER, GL_TRUE,
00064 GLX_RED_SIZE, 4,
00065 GLX_GREEN_SIZE, 4,
00066 GLX_BLUE_SIZE, 4,
00067 GLX_ALPHA_SIZE, 4,
00068 None
00069 };
00070
00071 const int video_X::VISUAL_ATTRIBUTES_24BPP[] = {
00072 GLX_DOUBLEBUFFER, GL_TRUE,
00073 GLX_RED_SIZE, 6,
00074 GLX_GREEN_SIZE, 6,
00075 GLX_BLUE_SIZE, 6,
00076 GLX_ALPHA_SIZE, 6,
00077 None
00078 };
00079
00080 const int video_X::VISUAL_ATTRIBUTES_32BPP[] = {
00081 GLX_DOUBLEBUFFER, GL_TRUE,
00082 GLX_RED_SIZE, 8,
00083 GLX_GREEN_SIZE, 8,
00084 GLX_BLUE_SIZE, 8,
00085 GLX_ALPHA_SIZE, 8,
00086 None
00087 };
00088 #endif
00089 const int video_X::LARGE = 10000;
00090
00091
00092
00093 video_X::video_X(void){
00094 m_window_title = std::string("Uber");
00095 m_display = NULL;
00096 m_selected_visual = NULL;
00097 m_GL_attributes = NULL;
00098 #ifdef GLX_SGIX_fbconfig
00099 m_available_configs = NULL;
00100 m_num_available_configs = 0;
00101 #endif
00102 }
00103
00104
00105
00106 video_X::~video_X(void){
00107 #ifdef GLX_SGIX_fbconfig
00108 if (m_available_configs != NULL){
00109 delete(m_available_configs);
00110 m_available_configs = NULL;
00111 }
00112 #endif
00113 if (m_selected_visual != NULL){
00114 delete(m_selected_visual);
00115 m_selected_visual = NULL;
00116 }
00117 if (m_GL_attributes != NULL){
00118 delete(m_GL_attributes);
00119 m_GL_attributes = NULL;
00120 }
00121 }
00122
00123
00124
00125 bool video_X::init(unsigned int w, unsigned int h, unsigned int bpp, bool fs){
00126 int screen, num_modes, best_mode_width = LARGE, best_mode_height = LARGE,
00127 best_mode, i, attributes_size;
00128 int *attributes, *ptr;
00129 Window root_window;
00130 XSetWindowAttributes window_attributes;
00131 XColor white;
00132 XF86VidModeModeInfo **modes;
00133 Atom wm_delete;
00134
00135
00136 if (w < 1)
00137 w = 1;
00138 if (h < 1)
00139 h = 1;
00140 if (bpp < 8)
00141 bpp = 8;
00142
00143
00144 if ((m_display = XOpenDisplay(NULL)) == NULL){
00145 set_error("Unable to open the X display.");
00146 return false;
00147 }
00148 screen = DefaultScreen(m_display);
00149 root_window = RootWindow(m_display, screen);
00150
00151
00152 if (!(XF86VidModeGetAllModeLines(m_display, screen, &num_modes, &modes))){
00153 set_error("Unable to obtain the X video modes.");
00154 return false;
00155 }
00156 m_desktop_mode = (*modes)[0];
00157 best_mode = -1;
00158 for (i=0; i<num_modes; i++){
00159 if ((modes[i]->hdisplay >= w) && (modes[i]->vdisplay >= h) &&
00160 (modes[i]->hdisplay <= best_mode_width) && (modes[i]->vdisplay <= best_mode_height)){
00161 best_mode = i;
00162 best_mode_width = modes[i]->hdisplay;
00163 best_mode_height = modes[i]->vdisplay;
00164 }
00165 }
00166
00167
00168 if (bpp < 16)
00169 attributes = (int*)VISUAL_ATTRIBUTES_8BPP;
00170 else if (bpp < 24)
00171 attributes = (int*)VISUAL_ATTRIBUTES_16BPP;
00172 else if (bpp < 32)
00173 attributes = (int*)VISUAL_ATTRIBUTES_24BPP;
00174 else
00175 attributes = (int*)VISUAL_ATTRIBUTES_32BPP;
00176
00177 #ifdef GLX_SGIX_fbconfig
00178
00179 m_num_available_configs = 0;
00180 m_available_configs = glXChooseFBConfigSGIX(m_display, screen, attributes, &m_num_available_configs);
00181 if (m_num_available_configs == 0){
00182 set_error("A framebuffer configuration with the chosen bit depth could not be found.");
00183 return false;
00184 }
00185
00186
00187 if (m_num_available_configs > 0)
00188 m_selected_visual = glXGetVisualFromFBConfigSGIX(m_display, m_available_configs[0]);
00189 else{
00190 set_error("Unable to find an appropriate X visual.");
00191 return false;
00192 }
00193 #else
00194
00195 m_selected_visual = glXChooseVisual(m_display, screen, attributes);
00196 if (m_selected_visual == NULL){
00197 set_error("Unable to find an appropriate X visual.");
00198 return false;
00199 }
00200 #endif
00201
00202
00203 window_attributes.colormap = XCreateColormap(m_display, root_window,
00204 m_selected_visual->visual, AllocNone);
00205 white.red = white.green = white.blue = 0xffff;
00206 XAllocColor(m_display, window_attributes.colormap, &white);
00207 window_attributes.border_pixel = white.pixel;
00208
00209
00210 m_window_context = glXCreateContext(m_display, m_selected_visual, NULL, True);
00211
00212
00213 if (fs){
00214
00215
00216 if(!(XF86VidModeSwitchToMode(m_display, screen, modes[best_mode]))){
00217 set_error("Unable to switch the X video mode.");
00218 return false;
00219 }
00220 XF86VidModeSetViewPort(m_display, screen, 0, 0);
00221 w = modes[best_mode]->hdisplay;
00222 h = modes[best_mode]->vdisplay;
00223 XFree(modes);
00224
00225
00226 window_attributes.override_redirect = True;
00227 window_attributes.event_mask = ExposureMask;
00228 m_window = XCreateWindow(m_display, root_window, 0, 0, w, h, 0,
00229 m_selected_visual->depth, InputOutput, m_selected_visual->visual,
00230 CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &window_attributes);
00231 XWarpPointer(m_display, None, m_window, 0, 0, 0, 0, 0, 0);
00232
00233
00234 XMapRaised(m_display, m_window);
00235
00236
00237 XGrabKeyboard(m_display, m_window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
00238 XGrabPointer(m_display, m_window, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
00239 GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
00240 }
00241 else {
00242
00243
00244 window_attributes.event_mask = ExposureMask;
00245 m_window = XCreateWindow(m_display, root_window, 0, 0, w, h, 0,
00246 m_selected_visual->depth, InputOutput, m_selected_visual->visual,
00247 CWBorderPixel|CWColormap|CWEventMask, &window_attributes);
00248
00249
00250 wm_delete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
00251 XSetWMProtocols(m_display, m_window, &wm_delete, 1);
00252 XSetStandardProperties(m_display, m_window, m_window_title.c_str(), m_window_title.c_str(), None, NULL, 0, NULL);
00253
00254
00255 XMapRaised(m_display, m_window);
00256 }
00257
00258
00259 glXMakeContextCurrent(m_display, m_window, m_window, m_window_context);
00260 gl::init(w, h);
00261
00262
00263 m_clock.reset();
00264
00265
00266 attributes_size = 0;
00267 ptr = attributes;
00268 while (*ptr != None){
00269 attributes_size++;
00270 ptr++;
00271 }
00272 attributes_size++;
00273
00274
00275 m_width = w;
00276 m_height = h;
00277 m_bpp = bpp;
00278 m_fullscreen = fs;
00279 m_GL_attributes = new int(attributes_size);
00280 memcpy(m_GL_attributes, attributes, attributes_size);
00281 return true;
00282 }
00283
00284
00285
00286 bool video_X::init(unsigned int w, unsigned int h, unsigned int bpp, const int attributes[], bool fs){
00287 int screen, num_modes, best_mode_width = LARGE, best_mode_height = LARGE,
00288 best_mode, i, attributes_size;
00289 int *ptr;
00290 Window root_window;
00291 XSetWindowAttributes window_attributes;
00292 XColor white;
00293 XF86VidModeModeInfo **modes;
00294 Atom wm_delete;
00295
00296
00297 if (w < 1)
00298 w = 1;
00299 if (h < 1)
00300 h = 1;
00301 if (bpp < 8)
00302 bpp = 8;
00303
00304
00305 if ((m_display = XOpenDisplay(NULL)) == NULL){
00306 set_error("Unable to open the X display.");
00307 return false;
00308 }
00309 screen = DefaultScreen(m_display);
00310 root_window = RootWindow(m_display, screen);
00311
00312
00313 if (!(XF86VidModeGetAllModeLines(m_display, screen, &num_modes, &modes))){
00314 set_error("Unable to obtain the X video modes.");
00315 return false;
00316 }
00317 m_desktop_mode = (*modes)[0];
00318
00319 #ifdef GLX_SGIX_fbconfig
00320
00321 m_num_available_configs = 0;
00322 m_available_configs = glXChooseFBConfigSGIX(m_display, screen, attributes, &m_num_available_configs);
00323 if (m_num_available_configs == 0){
00324 set_error("A framebuffer configuration with the chosen bit depth could not be found.");
00325 return false;
00326 }
00327
00328
00329 if (m_num_available_configs > 0)
00330 m_selected_visual = glXGetVisualFromFBConfigSGIX(m_display, m_available_configs[0]);
00331 else{
00332 set_error("Unable to find an appropriate X visual.");
00333 return false;
00334 }
00335 #else
00336
00337 m_selected_visual = glXChooseVisual(m_display, screen, attributes);
00338 if (m_selected_visual == NULL){
00339 set_error("Unable to find an appropriate X visual.");
00340 return false;
00341 }
00342 #endif
00343
00344
00345 window_attributes.colormap = XCreateColormap(m_display, root_window,
00346 m_selected_visual->visual, AllocNone);
00347 white.red = white.green = white.blue = 0xffff;
00348 XAllocColor(m_display, window_attributes.colormap, &white);
00349 window_attributes.border_pixel = white.pixel;
00350
00351
00352 m_window_context = glXCreateContext(m_display, m_selected_visual, NULL, True);
00353
00354
00355 if (fs){
00356
00357
00358 best_mode = -1;
00359 for (i=0; i<num_modes; i++){
00360 if ((modes[i]->hdisplay >= w) && (modes[i]->vdisplay >= h) &&
00361 (modes[i]->hdisplay <= best_mode_width) && (modes[i]->vdisplay <= best_mode_height)){
00362 best_mode = i;
00363 best_mode_width = modes[i]->hdisplay;
00364 best_mode_height = modes[i]->vdisplay;
00365 }
00366 }
00367 if (best_mode == -1){
00368 set_error("A suitable video mode could not be found for X.");
00369 return false;
00370 }
00371
00372
00373 if(!(XF86VidModeSwitchToMode(m_display, screen, modes[best_mode]))){
00374 set_error("Unable to switch the X video mode.");
00375 return false;
00376 }
00377 XF86VidModeSetViewPort(m_display, screen, 0, 0);
00378 w = modes[best_mode]->hdisplay;
00379 h = modes[best_mode]->vdisplay;
00380 XFree(modes);
00381
00382
00383 window_attributes.override_redirect = True;
00384 window_attributes.event_mask = ExposureMask;
00385 m_window = XCreateWindow(m_display, root_window, 0, 0, w, h, 0,
00386 m_selected_visual->depth, InputOutput, m_selected_visual->visual,
00387 CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &window_attributes);
00388 XWarpPointer(m_display, None, m_window, 0, 0, 0, 0, 0, 0);
00389
00390
00391 XMapRaised(m_display, m_window);
00392
00393
00394 XGrabKeyboard(m_display, m_window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
00395 XGrabPointer(m_display, m_window, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
00396 GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
00397 }
00398 else {
00399
00400
00401 window_attributes.event_mask = ExposureMask;
00402 m_window = XCreateWindow(m_display, root_window, 0, 0, w, h, 0,
00403 m_selected_visual->depth, InputOutput, m_selected_visual->visual,
00404 CWBorderPixel|CWColormap|CWEventMask, &window_attributes);
00405
00406
00407 wm_delete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
00408 XSetWMProtocols(m_display, m_window, &wm_delete, 1);
00409 XSetStandardProperties(m_display, m_window, m_window_title.c_str(), m_window_title.c_str(), None, NULL, 0, NULL);
00410
00411
00412 XMapRaised(m_display, m_window);
00413 }
00414
00415
00416 glXMakeContextCurrent(m_display, m_window, m_window, m_window_context);
00417 gl::init(w, h);
00418
00419
00420 m_clock.reset();
00421 m_clock.reset();
00422
00423
00424 attributes_size = 0;
00425 ptr = (int*)attributes;
00426 while (*ptr != None){
00427 attributes_size++;
00428 ptr++;
00429 }
00430 attributes_size++;
00431
00432
00433 m_width = w;
00434 m_height = h;
00435 m_bpp = bpp;
00436 m_fullscreen = fs;
00437 m_GL_attributes = new int(attributes_size);
00438 memcpy(m_GL_attributes, attributes, attributes_size);
00439 return true;
00440 }
00441
00442
00443
00444 void video_X::set_title(const std::string& title){
00445 if (!m_fullscreen){
00446
00447
00448 XStoreName(m_display, m_window, title.c_str());
00449
00450
00451 XSetIconName(m_display, m_window, title.c_str());
00452 }
00453
00454
00455 m_window_title = title;
00456 }
00457
00458
00459
00460 void video_X::resize(unsigned int w, unsigned int h){
00461 if (!m_fullscreen){
00462
00463
00464 XResizeWindow(m_display, m_window, w, h);
00465
00466
00467 m_width = w;
00468 m_height = h;
00469 }
00470 }
00471
00472
00473
00474 void video_X::start_frame(void){
00475
00476
00477 m_clock.update();
00478
00479
00480 m_fps = 1.0/m_clock.elapsed();
00481
00482
00483 ++m_frame_count;
00484
00485
00486 m_fps_sum += m_clock.elapsed();
00487 if (m_fps_sum > 1.0){
00488 m_avg_fps = m_fps_sum * static_cast<double>(m_frame_count);
00489 m_fps_sum = 0.0;
00490 m_frame_count = 0;
00491 }
00492 }
00493
00494
00495
00496 void video_X::end_frame(void){
00497
00498
00499 activate();
00500 glXSwapBuffers(m_display, m_window);
00501 }
00502
00503
00504
00505 void video_X::toggle_fullscreen(void){
00506 int screen = DefaultScreen(m_display), i, best_mode, best_mode_width = LARGE,
00507 best_mode_height = LARGE, num_modes;
00508 XSetWindowAttributes window_attributes;
00509 XF86VidModeModeInfo **modes;
00510 Atom wm_delete;
00511
00512
00513 if (m_fullscreen){
00514
00515
00516 XUngrabKeyboard(m_display, CurrentTime);
00517 XUngrabPointer(m_display, CurrentTime);
00518
00519
00520 XUnmapWindow(m_display, m_window);
00521
00522
00523 XF86VidModeSwitchToMode(m_display, screen, &m_desktop_mode);
00524 XF86VidModeSetViewPort(m_display, screen, 0, 0);
00525
00526
00527 wm_delete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
00528 XSetWMProtocols(m_display, m_window, &wm_delete, 1);
00529 XSetStandardProperties(m_display, m_window, m_window_title.c_str(), m_window_title.c_str(), None, NULL, 0, NULL);
00530
00531
00532 window_attributes.override_redirect = False;
00533 XChangeWindowAttributes(m_display, m_window, CWOverrideRedirect, &window_attributes);
00534
00535
00536 XMapRaised(m_display, m_window);
00537 m_fullscreen = false;
00538 }
00539
00540
00541 else{
00542
00543
00544 XF86VidModeGetAllModeLines(m_display, screen, &num_modes, &modes);
00545
00546
00547 best_mode = -1;
00548 for (i=0; i<num_modes; i++){
00549 if ((modes[i]->hdisplay >= m_width) && (modes[i]->vdisplay >= m_height) &&
00550 (modes[i]->hdisplay <= best_mode_width) && (modes[i]->vdisplay <= best_mode_height)){
00551 best_mode = i;
00552 best_mode_width = modes[i]->hdisplay;
00553 best_mode_height = modes[i]->vdisplay;
00554 }
00555 }
00556 if (best_mode == -1){
00557 set_error("A suitable video mode could not be found for X.");
00558 return;
00559 }
00560
00561
00562 XUnmapWindow(m_display, m_window);
00563
00564
00565 if(!(XF86VidModeSwitchToMode(m_display, screen, modes[best_mode]))){
00566 set_error("Unable to switch the X video mode.");
00567 return;
00568 }
00569 XF86VidModeSetViewPort(m_display, screen, 0, 0);
00570 m_width = modes[best_mode]->hdisplay;
00571 m_height = modes[best_mode]->vdisplay;
00572 XFree(modes);
00573 XResizeWindow(m_display, m_window, m_width, m_height);
00574
00575
00576 window_attributes.override_redirect = True;
00577 XChangeWindowAttributes(m_display, m_window, CWOverrideRedirect, &window_attributes);
00578 XWarpPointer(m_display, None, m_window, 0, 0, 0, 0 ,0 ,0);
00579
00580
00581 XMapRaised(m_display, m_window);
00582 XMoveWindow(m_display, m_window, 0, 0);
00583
00584
00585 XGrabKeyboard(m_display, m_window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
00586 XGrabPointer(m_display, m_window, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
00587 GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
00588 m_fullscreen = true;
00589 }
00590 }
00591
00592
00593
00594 void video_X::activate(void){
00595
00596
00597 glXMakeContextCurrent(m_display, m_window, m_window, m_window_context);
00598 }
00599
00600
00601
00602 void video_X::shutdown(void){
00603 int screen = DefaultScreen(m_display);
00604
00605
00606 glXDestroyContext(m_display, m_window_context);
00607 m_window_context = NULL;
00608
00609
00610 if (m_fullscreen){
00611 XF86VidModeSwitchToMode(m_display, screen, &m_desktop_mode);
00612 XF86VidModeSetViewPort(m_display, screen, 0, 0);
00613 }
00614 XCloseDisplay(m_display);
00615 m_display = NULL;
00616 }
00617
00618
00619
00620 void video_X::set_eventmask(long eventmask){
00621
00622
00623 XSelectInput(m_display, m_window, eventmask);
00624 }
00625
00626
00627
00628 void video_X::move_pointer(int x, int y){
00629
00630
00631 XWarpPointer(m_display, None, m_window, 0, 0, 0, 0, x, y);
00632 }
00633
00634
00635
00636 bool video_X::get_pointer(int *x, int *y){
00637 int root_x, root_y;
00638 unsigned int mask;
00639 bool result;
00640 Window result_window, result_root;
00641
00642
00643 result = XQueryPointer(m_display, m_window, &result_root, &result_window,
00644 &root_x, &root_y, x, y, &mask);
00645 return result;
00646 }