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 CDLockedReader cdata(_cycler); 00092 for (size_t i = 0; i != cdata->_textures.size(); ++i) { 00093 const RenderTexture &rt = cdata->_textures[i]; 00094 RenderTextureMode rtm_mode = rt._rtm_mode; 00095 if (rtm_mode == RTM_bind_or_copy) { 00096 CDWriter cdataw(_cycler, cdata, false); 00097 nassertr(cdata->_textures.size() == cdataw->_textures.size(), false); 00098 cdataw->_textures[i]._rtm_mode = RTM_copy_texture; 00099 } 00100 } 00101 clear_cube_map_selection(); 00102 } 00103 00104 _gsg->set_current_properties(&get_fb_properties()); 00105 return _gsg->begin_frame(current_thread); 00106 } 00107 00108 //////////////////////////////////////////////////////////////////// 00109 // Function: glxGraphicsBuffer::end_frame 00110 // Access: Public, Virtual 00111 // Description: This function will be called within the draw thread 00112 // after rendering is completed for a given frame. It 00113 // should do whatever finalization is required. 00114 //////////////////////////////////////////////////////////////////// 00115 void glxGraphicsBuffer:: 00116 end_frame(FrameMode mode, Thread *current_thread) { 00117 end_frame_spam(mode); 00118 nassertv(_gsg != (GraphicsStateGuardian *)NULL); 00119 00120 if (mode == FM_render) { 00121 copy_to_textures(); 00122 } 00123 00124 _gsg->end_frame(current_thread); 00125 00126 if (mode == FM_render) { 00127 trigger_flip(); 00128 clear_cube_map_selection(); 00129 } 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: glxGraphicsBuffer::close_buffer 00134 // Access: Protected, Virtual 00135 // Description: Closes the buffer right now. Called from the window 00136 // thread. 00137 //////////////////////////////////////////////////////////////////// 00138 void glxGraphicsBuffer:: 00139 close_buffer() { 00140 if (_gsg != (GraphicsStateGuardian *)NULL) { 00141 glXMakeCurrent(_display, None, NULL); 00142 00143 if (_pbuffer != None) { 00144 glxGraphicsStateGuardian *glxgsg; 00145 DCAST_INTO_V(glxgsg, _gsg); 00146 glxgsg->_glXDestroyPbuffer(_display, _pbuffer); 00147 _pbuffer = None; 00148 } 00149 00150 _gsg.clear(); 00151 } 00152 00153 _pbuffer = None; 00154 _is_valid = false; 00155 } 00156 00157 //////////////////////////////////////////////////////////////////// 00158 // Function: glxGraphicsBuffer::open_buffer 00159 // Access: Protected, Virtual 00160 // Description: Opens the buffer right now. Called from the window 00161 // thread. Returns true if the buffer is successfully 00162 // opened, or false if there was a problem. 00163 //////////////////////////////////////////////////////////////////// 00164 bool glxGraphicsBuffer:: 00165 open_buffer() { 00166 glxGraphicsPipe *glx_pipe; 00167 DCAST_INTO_R(glx_pipe, _pipe, false); 00168 00169 // GSG Creation/Initialization 00170 glxGraphicsStateGuardian *glxgsg; 00171 if (_gsg == 0) { 00172 // There is no old gsg. Create a new one. 00173 glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL); 00174 glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false); 00175 _gsg = glxgsg; 00176 } else { 00177 // If the old gsg has the wrong pixel format, create a 00178 // new one that shares with the old gsg. 00179 DCAST_INTO_R(glxgsg, _gsg, false); 00180 00181 if (!glxgsg->_context_has_pbuffer || 00182 !glxgsg->get_fb_properties().subsumes(_fb_properties)) { 00183 // We need a new pixel format, and hence a new GSG. 00184 glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg); 00185 glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false); 00186 _gsg = glxgsg; 00187 } 00188 } 00189 00190 if (glxgsg->_fbconfig == None || glxgsg->_context_has_pbuffer) { 00191 // If we didn't use an fbconfig to create the GSG, or it doesn't 00192 // support buffers, we can't create a PBuffer. 00193 return false; 00194 } 00195 00196 nassertr(glxgsg->_supports_pbuffer, false); 00197 00198 static const int max_attrib_list = 32; 00199 int attrib_list[max_attrib_list]; 00200 int n = 0; 00201 00202 if (glxgsg->_uses_sgix_pbuffer) { 00203 // The SGI version passed in the size in the parameter list. 00204 nassertr(n < max_attrib_list, false); 00205 attrib_list[n] = (int)None; 00206 _pbuffer = glxgsg->_glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig, 00207 _x_size, _y_size, attrib_list); 00208 } else { 00209 // The official GLX 1.3 version passes in the size in the attrib 00210 // list. 00211 attrib_list[n++] = GLX_PBUFFER_WIDTH; 00212 attrib_list[n++] = _x_size; 00213 attrib_list[n++] = GLX_PBUFFER_HEIGHT; 00214 attrib_list[n++] = _y_size; 00215 00216 nassertr(n < max_attrib_list, false); 00217 attrib_list[n] = (int)None; 00218 _pbuffer = glxgsg->_glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig, 00219 attrib_list); 00220 } 00221 00222 if (_pbuffer == None) { 00223 glxdisplay_cat.error() 00224 << "failed to create GLX pbuffer.\n"; 00225 return false; 00226 } 00227 00228 glXMakeCurrent(_display, _pbuffer, glxgsg->_context); 00229 glxgsg->reset_if_new(); 00230 if (!glxgsg->is_valid()) { 00231 close_buffer(); 00232 return false; 00233 } 00234 if (!glxgsg->get_fb_properties().verify_hardware_software 00235 (_fb_properties, glxgsg->get_gl_renderer())) { 00236 close_buffer(); 00237 return false; 00238 } 00239 _fb_properties = glxgsg->get_fb_properties(); 00240 00241 _is_valid = true; 00242 return true; 00243 }