Panda3D
 All Classes Functions Variables Enumerations
glxGraphicsWindow.cxx
00001 // Filename: glxGraphicsWindow.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "glxGraphicsWindow.h"
00016 #include "glxGraphicsStateGuardian.h"
00017 #include "config_glxdisplay.h"
00018 #include "glxGraphicsPipe.h"
00019 
00020 #include "graphicsPipe.h"
00021 #include "keyboardButton.h"
00022 #include "mouseButton.h"
00023 #include "glgsg.h"
00024 #include "clockObject.h"
00025 #include "pStatTimer.h"
00026 #include "textEncoder.h"
00027 #include "throw_event.h"
00028 #include "lightReMutexHolder.h"
00029 
00030 #include <errno.h>
00031 #include <sys/time.h>
00032 
00033 TypeHandle glxGraphicsWindow::_type_handle;
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: glxGraphicsWindow::Constructor
00037 //       Access: Public
00038 //  Description:
00039 ////////////////////////////////////////////////////////////////////
00040 glxGraphicsWindow::
00041 glxGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, 
00042                   const string &name,
00043                   const FrameBufferProperties &fb_prop,
00044                   const WindowProperties &win_prop,
00045                   int flags,
00046                   GraphicsStateGuardian *gsg,
00047                   GraphicsOutput *host) :
00048   x11GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00049 {
00050 }
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: glxGraphicsWindow::begin_frame
00054 //       Access: Public, Virtual
00055 //  Description: This function will be called within the draw thread
00056 //               before beginning rendering for a given frame.  It
00057 //               should do whatever setup is required, and return true
00058 //               if the frame should be rendered, or false if it
00059 //               should be skipped.
00060 ////////////////////////////////////////////////////////////////////
00061 bool glxGraphicsWindow::
00062 begin_frame(FrameMode mode, Thread *current_thread) {
00063   PStatTimer timer(_make_current_pcollector, current_thread);
00064 
00065   begin_frame_spam(mode);
00066   if (_gsg == (GraphicsStateGuardian *)NULL) {
00067     return false;
00068   }
00069   if (_awaiting_configure) {
00070     // Don't attempt to draw while we have just reconfigured the
00071     // window and we haven't got the notification back yet.
00072     return false;
00073   }
00074 
00075   glxGraphicsStateGuardian *glxgsg;
00076   DCAST_INTO_R(glxgsg, _gsg, false);
00077   {
00078     LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
00079 
00080     if (glXGetCurrentDisplay() == _display &&
00081         glXGetCurrentDrawable() == _xwindow &&
00082         glXGetCurrentContext() == glxgsg->_context) {
00083       // No need to make the context current again.  Short-circuit
00084       // this possibly-expensive call.
00085     } else {
00086       // Need to set the context.
00087       glXMakeCurrent(_display, _xwindow, glxgsg->_context);
00088     }
00089   }
00090   
00091   // Now that we have made the context current to a window, we can
00092   // reset the GSG state if this is the first time it has been used.
00093   // (We can't just call reset() when we construct the GSG, because
00094   // reset() requires having a current context.)
00095   glxgsg->reset_if_new();
00096   
00097   if (mode == FM_render) {
00098     // begin_render_texture();
00099     clear_cube_map_selection();
00100   }
00101   
00102   _gsg->set_current_properties(&get_fb_properties());
00103   return _gsg->begin_frame(current_thread);
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: glxGraphicsWindow::end_flip
00108 //       Access: Public, Virtual
00109 //  Description: This function will be called within the draw thread
00110 //               after begin_flip() has been called on all windows, to
00111 //               finish the exchange of the front and back buffers.
00112 //
00113 //               This should cause the window to wait for the flip, if
00114 //               necessary.
00115 ////////////////////////////////////////////////////////////////////
00116 void glxGraphicsWindow::
00117 end_flip() {
00118   if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
00119 
00120     // It doesn't appear to be necessary to ensure the graphics
00121     // context is current before flipping the windows, and insisting
00122     // on doing so can be a significant performance hit.
00123 
00124     //make_current();
00125 
00126     LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
00127     glXSwapBuffers(_display, _xwindow);
00128   }
00129   GraphicsWindow::end_flip();
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: glxGraphicsWindow::close_window
00134 //       Access: Protected, Virtual
00135 //  Description: Closes the window right now.  Called from the window
00136 //               thread.
00137 ////////////////////////////////////////////////////////////////////
00138 void glxGraphicsWindow::
00139 close_window() {
00140   if (_gsg != (GraphicsStateGuardian *)NULL) {
00141     glXMakeCurrent(_display, None, NULL);
00142     _gsg.clear();
00143   }
00144   
00145   x11GraphicsWindow::close_window();
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: glxGraphicsWindow::open_window
00150 //       Access: Protected, Virtual
00151 //  Description: Opens the window right now.  Called from the window
00152 //               thread.  Returns true if the window is successfully
00153 //               opened, or false if there was a problem.
00154 ////////////////////////////////////////////////////////////////////
00155 bool glxGraphicsWindow::
00156 open_window() {
00157   glxGraphicsPipe *glx_pipe;
00158   DCAST_INTO_R(glx_pipe, _pipe, false);
00159 
00160   // GSG Creation/Initialization
00161   glxGraphicsStateGuardian *glxgsg;
00162   if (_gsg == 0) {
00163     // There is no old gsg.  Create a new one.
00164     glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
00165     glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false, false);
00166     _gsg = glxgsg;
00167   } else {
00168     // If the old gsg has the wrong pixel format, create a
00169     // new one that shares with the old gsg.
00170     DCAST_INTO_R(glxgsg, _gsg, false);
00171     if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
00172       glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
00173       glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false, false);
00174       _gsg = glxgsg;
00175     }
00176   }
00177   
00178   if (glxgsg->_context == NULL) {
00179     // We're supposed to have a context at this point.
00180     glxdisplay_cat.error()
00181       << "No GLX context: cannot open window.\n";
00182     return false;
00183   }
00184   
00185   _visual_info = glxgsg->_visual;
00186   if (_visual_info == NULL) {
00187     // No X visual for this fbconfig; how can we open the window?
00188     glxdisplay_cat.error()
00189       << "No X visual: cannot open window.\n";
00190     return false;
00191   }
00192   Visual *visual = _visual_info->visual;
00193   
00194   if (glxgsg->_fbconfig != None) {
00195     setup_colormap(glxgsg->_fbconfig);
00196   } else {
00197     setup_colormap(_visual_info);
00198   }
00199 
00200   if (!x11GraphicsWindow::open_window()) {
00201     return false;
00202   }
00203 
00204   glXMakeCurrent(_display, _xwindow, glxgsg->_context);
00205   glxgsg->reset_if_new();
00206   if (!glxgsg->is_valid()) {
00207     close_window();
00208     return false;
00209   }
00210   if (!glxgsg->get_fb_properties().verify_hardware_software
00211       (_fb_properties, glxgsg->get_gl_renderer())) {
00212     close_window();
00213     return false;
00214   }
00215   _fb_properties = glxgsg->get_fb_properties();
00216 
00217   return true;
00218 }
00219 
00220 ////////////////////////////////////////////////////////////////////
00221 //     Function: glxGraphicsWindow::setup_colormap
00222 //       Access: Private
00223 //  Description: Allocates a colormap appropriate to the fbconfig and
00224 //               stores in in the _colormap method.
00225 ////////////////////////////////////////////////////////////////////
00226 void glxGraphicsWindow::
00227 setup_colormap(GLXFBConfig fbconfig) {
00228   glxGraphicsStateGuardian *glxgsg;
00229   DCAST_INTO_V(glxgsg, _gsg);
00230   nassertv(glxgsg->_supports_fbconfig);
00231 
00232   XVisualInfo *visual_info = glxgsg->_glXGetVisualFromFBConfig(_display, fbconfig);
00233   if (visual_info == NULL) {
00234     // No X visual; no need to set up a colormap.
00235     return;
00236   }
00237   int visual_class = visual_info->c_class;
00238   Visual *visual = visual_info->visual;
00239   XFree(visual_info);
00240 
00241   glxGraphicsPipe *glx_pipe;
00242   DCAST_INTO_V(glx_pipe, _pipe);
00243   X11_Window root_window = glx_pipe->get_root();
00244 
00245   int rc, is_rgb;
00246 
00247   switch (visual_class) {
00248     case PseudoColor:
00249       rc = glxgsg->_glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &is_rgb);
00250       if (rc == 0 && is_rgb) {
00251         glxdisplay_cat.warning()
00252           << "mesa pseudocolor not supported.\n";
00253         // this is a terrible terrible hack, but it seems to work
00254         _colormap = (Colormap)0;
00255 
00256       } else {
00257         _colormap = XCreateColormap(_display, root_window,
00258                                     visual, AllocAll);
00259       }
00260       break;
00261     case TrueColor:
00262     case DirectColor:
00263       _colormap = XCreateColormap(_display, root_window,
00264                                   visual, AllocNone);
00265       break;
00266     case StaticColor:
00267     case StaticGray:
00268     case GrayScale:
00269       _colormap = XCreateColormap(_display, root_window,
00270                                   visual, AllocNone);
00271       break;
00272     default:
00273       glxdisplay_cat.error()
00274         << "Could not allocate a colormap for visual class "
00275         << visual_class << ".\n";
00276       break;
00277   }
00278 }
00279 
00280 ////////////////////////////////////////////////////////////////////
00281 //     Function: glxGraphicsWindow::setup_colormap
00282 //       Access: Private, Virtual
00283 //  Description: Allocates a colormap appropriate to the visual and
00284 //               stores in in the _colormap method.
00285 ////////////////////////////////////////////////////////////////////
00286 void glxGraphicsWindow::
00287 setup_colormap(XVisualInfo *visual) {
00288   glxGraphicsPipe *glx_pipe;
00289   DCAST_INTO_V(glx_pipe, _pipe);
00290   X11_Window root_window = glx_pipe->get_root();
00291 
00292   int visual_class = visual->c_class;
00293   int rc, is_rgb;
00294 
00295   switch (visual_class) {
00296     case PseudoColor:
00297       rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb);
00298       if (rc == 0 && is_rgb) {
00299         glxdisplay_cat.warning()
00300           << "mesa pseudocolor not supported.\n";
00301         // this is a terrible terrible hack, but it seems to work
00302         _colormap = (Colormap)0;
00303 
00304       } else {
00305         _colormap = XCreateColormap(_display, root_window,
00306                                     visual->visual, AllocAll);
00307       }
00308       break;
00309     case TrueColor:
00310     case DirectColor:
00311       _colormap = XCreateColormap(_display, root_window,
00312                                   visual->visual, AllocNone);
00313       break;
00314     case StaticColor:
00315     case StaticGray:
00316     case GrayScale:
00317       _colormap = XCreateColormap(_display, root_window,
00318                                   visual->visual, AllocNone);
00319       break;
00320     default:
00321       glxdisplay_cat.error()
00322         << "Could not allocate a colormap for visual class "
00323         << visual_class << ".\n";
00324       break;
00325   }
00326 }
 All Classes Functions Variables Enumerations