Panda3D

glxGraphicsBuffer.cxx

00001 // Filename: glxGraphicsBuffer.cxx
00002 // Created by:  drose (09Feb04)
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 "glxGraphicsBuffer.h"
00016 #include "glxGraphicsStateGuardian.h"
00017 #include "config_glxdisplay.h"
00018 #include "glxGraphicsPipe.h"
00019 
00020 #include "graphicsPipe.h"
00021 #include "glgsg.h"
00022 #include "pStatTimer.h"
00023 
00024 TypeHandle glxGraphicsBuffer::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: glxGraphicsBuffer::Constructor
00028 //       Access: Public
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 glxGraphicsBuffer::
00032 glxGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe, 
00033                   const string &name,
00034                   const FrameBufferProperties &fb_prop,
00035                   const WindowProperties &win_prop,
00036                   int flags,
00037                   GraphicsStateGuardian *gsg,
00038                   GraphicsOutput *host) :
00039   GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00040 {
00041   glxGraphicsPipe *glx_pipe;
00042   DCAST_INTO_V(glx_pipe, _pipe);
00043   _display = glx_pipe->get_display();
00044   _pbuffer = None;
00045 
00046   // Since the pbuffer never gets flipped, we get screenshots from the
00047   // same buffer we draw into.
00048   _screenshot_buffer_type = _draw_buffer_type;
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: glxGraphicsBuffer::Destructor
00053 //       Access: Public, Virtual
00054 //  Description:
00055 ////////////////////////////////////////////////////////////////////
00056 glxGraphicsBuffer::
00057 ~glxGraphicsBuffer() {
00058   nassertv(_pbuffer == None);
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: glxGraphicsBuffer::begin_frame
00063 //       Access: Public, Virtual
00064 //  Description: This function will be called within the draw thread
00065 //               before beginning rendering for a given frame.  It
00066 //               should do whatever setup is required, and return true
00067 //               if the frame should be rendered, or false if it
00068 //               should be skipped.
00069 ////////////////////////////////////////////////////////////////////
00070 bool glxGraphicsBuffer::
00071 begin_frame(FrameMode mode, Thread *current_thread) {
00072   PStatTimer timer(_make_current_pcollector, current_thread);
00073 
00074   begin_frame_spam(mode);
00075   if (_gsg == (GraphicsStateGuardian *)NULL ||
00076       _pbuffer == None) {
00077     return false;
00078   }
00079 
00080   glxGraphicsStateGuardian *glxgsg;
00081   DCAST_INTO_R(glxgsg, _gsg, false);
00082   glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
00083 
00084   // Now that we have made the context current to a window, we can
00085   // reset the GSG state if this is the first time it has been used.
00086   // (We can't just call reset() when we construct the GSG, because
00087   // reset() requires having a current context.)
00088   glxgsg->reset_if_new();
00089 
00090   if (mode == FM_render) {
00091     for (int i=0; i<count_textures(); i++) {
00092       if (get_rtm_mode(i) == RTM_bind_or_copy) {
00093         _textures[i]._rtm_mode = RTM_copy_texture;
00094       }
00095     }
00096     clear_cube_map_selection();
00097   }
00098   
00099   _gsg->set_current_properties(&get_fb_properties());
00100   return _gsg->begin_frame(current_thread);
00101 }
00102 
00103 ////////////////////////////////////////////////////////////////////
00104 //     Function: glxGraphicsBuffer::end_frame
00105 //       Access: Public, Virtual
00106 //  Description: This function will be called within the draw thread
00107 //               after rendering is completed for a given frame.  It
00108 //               should do whatever finalization is required.
00109 ////////////////////////////////////////////////////////////////////
00110 void glxGraphicsBuffer::
00111 end_frame(FrameMode mode, Thread *current_thread) {
00112   end_frame_spam(mode);
00113   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00114 
00115   if (mode == FM_render) {
00116     copy_to_textures();
00117   }
00118 
00119   _gsg->end_frame(current_thread);
00120 
00121   if (mode == FM_render) {
00122     trigger_flip();
00123     if (_one_shot) {
00124       prepare_for_deletion();
00125     }
00126     clear_cube_map_selection();
00127   }
00128 }
00129 
00130 ////////////////////////////////////////////////////////////////////
00131 //     Function: glxGraphicsBuffer::close_buffer
00132 //       Access: Protected, Virtual
00133 //  Description: Closes the buffer right now.  Called from the window
00134 //               thread.
00135 ////////////////////////////////////////////////////////////////////
00136 void glxGraphicsBuffer::
00137 close_buffer() {
00138   if (_gsg != (GraphicsStateGuardian *)NULL) {
00139     glXMakeCurrent(_display, None, NULL);
00140 
00141     if (_pbuffer != None) {
00142       glxGraphicsStateGuardian *glxgsg;
00143       DCAST_INTO_V(glxgsg, _gsg);
00144       glxgsg->_glXDestroyPbuffer(_display, _pbuffer);
00145       _pbuffer = None;
00146     }
00147     
00148     _gsg.clear();
00149     _active = false;
00150   }
00151 
00152   _pbuffer = None;
00153   _is_valid = false;
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: glxGraphicsBuffer::open_buffer
00158 //       Access: Protected, Virtual
00159 //  Description: Opens the buffer right now.  Called from the window
00160 //               thread.  Returns true if the buffer is successfully
00161 //               opened, or false if there was a problem.
00162 ////////////////////////////////////////////////////////////////////
00163 bool glxGraphicsBuffer::
00164 open_buffer() {
00165   glxGraphicsPipe *glx_pipe;
00166   DCAST_INTO_R(glx_pipe, _pipe, false);
00167 
00168   // GSG Creation/Initialization
00169   glxGraphicsStateGuardian *glxgsg;
00170   if (_gsg == 0) {
00171     // There is no old gsg.  Create a new one.
00172     glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
00173     glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
00174     _gsg = glxgsg;
00175   } else {
00176     // If the old gsg has the wrong pixel format, create a
00177     // new one that shares with the old gsg.
00178     DCAST_INTO_R(glxgsg, _gsg, false);
00179 
00180     if (!glxgsg->_context_has_pbuffer || 
00181         !glxgsg->get_fb_properties().subsumes(_fb_properties)) {
00182       // We need a new pixel format, and hence a new GSG.
00183       glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
00184       glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
00185       _gsg = glxgsg;
00186     }
00187   }
00188   
00189   if (glxgsg->_fbconfig == None || glxgsg->_context_has_pbuffer) {
00190     // If we didn't use an fbconfig to create the GSG, or it doesn't
00191     // support buffers, we can't create a PBuffer.
00192     return false;
00193   }
00194 
00195   nassertr(glxgsg->_supports_pbuffer, false);
00196 
00197   static const int max_attrib_list = 32;
00198   int attrib_list[max_attrib_list];
00199   int n = 0;
00200 
00201   if (glxgsg->_uses_sgix_pbuffer) {
00202     // The SGI version passed in the size in the parameter list.
00203     nassertr(n < max_attrib_list, false);
00204     attrib_list[n] = (int)None;
00205     _pbuffer = glxgsg->_glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig,
00206                                                 _x_size, _y_size, attrib_list);
00207   } else {
00208     // The official GLX 1.3 version passes in the size in the attrib
00209     // list.
00210     attrib_list[n++] = GLX_PBUFFER_WIDTH;
00211     attrib_list[n++] = _x_size;
00212     attrib_list[n++] = GLX_PBUFFER_HEIGHT;
00213     attrib_list[n++] = _y_size;
00214     
00215     nassertr(n < max_attrib_list, false);
00216     attrib_list[n] = (int)None;
00217     _pbuffer = glxgsg->_glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig,
00218                                          attrib_list);
00219   }
00220 
00221   if (_pbuffer == None) {
00222     glxdisplay_cat.error()
00223       << "failed to create GLX pbuffer.\n";
00224     return false;
00225   }
00226 
00227   glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
00228   glxgsg->reset_if_new();
00229   if (!glxgsg->is_valid()) {
00230     close_buffer();
00231     return false;
00232   }
00233   if (!glxgsg->get_fb_properties().verify_hardware_software
00234       (_fb_properties, glxgsg->get_gl_renderer())) {
00235     close_buffer();
00236     return false;
00237   }
00238   _fb_properties = glxgsg->get_fb_properties();
00239   
00240   _is_valid = true;
00241   return true;
00242 }
 All Classes Functions Variables Enumerations