Panda3D
|
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 }