00001 // Filename: parasiteBuffer.cxx 00002 // Created by: drose (27Feb04) 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 "parasiteBuffer.h" 00016 #include "texture.h" 00017 00018 TypeHandle ParasiteBuffer::_type_handle; 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: ParasiteBuffer::Constructor 00022 // Access: Public 00023 // Description: Normally, the ParasiteBuffer constructor is not 00024 // called directly; these are created instead via the 00025 // GraphicsEngine::make_parasite() function. 00026 //////////////////////////////////////////////////////////////////// 00027 ParasiteBuffer:: 00028 ParasiteBuffer(GraphicsOutput *host, const string &name, 00029 int x_size, int y_size, int flags) : 00030 GraphicsOutput(host->get_engine(), host->get_pipe(), 00031 name, host->get_fb_properties(), 00032 WindowProperties::size(x_size, y_size), flags, 00033 host->get_gsg(), host, false) 00034 { 00035 #ifdef DO_MEMORY_USAGE 00036 MemoryUsage::update_type(this, this); 00037 #endif 00038 00039 if (display_cat.is_debug()) { 00040 display_cat.debug() 00041 << "Creating new parasite buffer " << get_name() 00042 << " on " << _host->get_name() << "\n"; 00043 } 00044 00045 _creation_flags = flags; 00046 00047 if (flags & GraphicsPipe::BF_size_track_host) { 00048 x_size = host->get_x_size(); 00049 y_size = host->get_y_size(); 00050 } 00051 00052 _x_size = x_size; 00053 _y_size = y_size; 00054 _has_size = true; 00055 _overlay_display_region->compute_pixels(_x_size, _y_size); 00056 _is_valid = true; 00057 00058 set_inverted(host->get_gsg()->get_copy_texture_inverted()); 00059 } 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Function: ParasiteBuffer::Destructor 00063 // Access: Published, Virtual 00064 // Description: 00065 //////////////////////////////////////////////////////////////////// 00066 ParasiteBuffer:: 00067 ~ParasiteBuffer() { 00068 _is_valid = false; 00069 } 00070 00071 //////////////////////////////////////////////////////////////////// 00072 // Function: ParasiteBuffer::is_active 00073 // Access: Published, Virtual 00074 // Description: Returns true if the window is ready to be rendered 00075 // into, false otherwise. 00076 //////////////////////////////////////////////////////////////////// 00077 bool ParasiteBuffer:: 00078 is_active() const { 00079 return GraphicsOutput::is_active() && _host->is_active(); 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: ParasiteBuffer::set_size 00084 // Access: Public, Virtual 00085 // Description: This is called by the GraphicsEngine to request that 00086 // the buffer resize itself. Although calls to get the 00087 // size will return the new value, much of the actual 00088 // resizing work doesn't take place until the next 00089 // begin_frame. Not all buffers are resizeable. 00090 //////////////////////////////////////////////////////////////////// 00091 void ParasiteBuffer:: 00092 set_size(int x, int y) { 00093 if ((_creation_flags & GraphicsPipe::BF_resizeable) == 0) { 00094 nassert_raise("Cannot resize buffer unless it is created with BF_resizeable flag"); 00095 return; 00096 } 00097 set_size_and_recalc(x, y); 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 // Function: ParasiteBuffer::set_size_and_recalc 00102 // Access: Public 00103 // Description: 00104 //////////////////////////////////////////////////////////////////// 00105 void ParasiteBuffer:: 00106 set_size_and_recalc(int x, int y) { 00107 if (!(_creation_flags & GraphicsPipe::BF_size_track_host)) { 00108 if (_creation_flags & GraphicsPipe::BF_size_power_2) { 00109 x = Texture::down_to_power_2(x); 00110 y = Texture::down_to_power_2(y); 00111 } 00112 if (_creation_flags & GraphicsPipe::BF_size_square) { 00113 x = y = min(x, y); 00114 } 00115 } 00116 00117 GraphicsOutput::set_size_and_recalc(x, y); 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: ParasiteBuffer::flip_ready 00122 // Access: Public, Virtual 00123 // Description: Returns true if a frame has been rendered and needs 00124 // to be flipped, false otherwise. 00125 //////////////////////////////////////////////////////////////////// 00126 bool ParasiteBuffer:: 00127 flip_ready() const { 00128 nassertr(_host != NULL, false); 00129 return _host->flip_ready(); 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: ParasiteBuffer::begin_flip 00134 // Access: Public, Virtual 00135 // Description: This function will be called within the draw thread 00136 // after end_frame() has been called on all windows, to 00137 // initiate the exchange of the front and back buffers. 00138 // 00139 // This should instruct the window to prepare for the 00140 // flip at the next video sync, but it should not wait. 00141 // 00142 // We have the two separate functions, begin_flip() and 00143 // end_flip(), to make it easier to flip all of the 00144 // windows at the same time. 00145 //////////////////////////////////////////////////////////////////// 00146 void ParasiteBuffer:: 00147 begin_flip() { 00148 nassertv(_host != NULL); 00149 _host->begin_flip(); 00150 } 00151 00152 //////////////////////////////////////////////////////////////////// 00153 // Function: ParasiteBuffer::ready_flip 00154 // Access: Public, Virtual 00155 // Description: This function will be called within the draw thread 00156 // after end_frame() has been called on all windows, to 00157 // initiate the exchange of the front and back buffers. 00158 // 00159 // This should instruct the window to prepare for the 00160 // flip when it is command but not actually flip 00161 // 00162 //////////////////////////////////////////////////////////////////// 00163 void ParasiteBuffer:: 00164 ready_flip() { 00165 nassertv(_host != NULL); 00166 _host->ready_flip(); 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: ParasiteBuffer::end_flip 00171 // Access: Public, Virtual 00172 // Description: This function will be called within the draw thread 00173 // after begin_flip() has been called on all windows, to 00174 // finish the exchange of the front and back buffers. 00175 // 00176 // This should cause the window to wait for the flip, if 00177 // necessary. 00178 //////////////////////////////////////////////////////////////////// 00179 void ParasiteBuffer:: 00180 end_flip() { 00181 nassertv(_host != NULL); 00182 _host->end_flip(); 00183 _flip_ready = false; 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: ParasiteBuffer::begin_frame 00188 // Access: Public, Virtual 00189 // Description: This function will be called within the draw thread 00190 // before beginning rendering for a given frame. It 00191 // should do whatever setup is required, and return true 00192 // if the frame should be rendered, or false if it 00193 // should be skipped. 00194 //////////////////////////////////////////////////////////////////// 00195 bool ParasiteBuffer:: 00196 begin_frame(FrameMode mode, Thread *current_thread) { 00197 begin_frame_spam(mode); 00198 00199 if (!_host->begin_frame(FM_parasite, current_thread)) { 00200 return false; 00201 } 00202 00203 if (_creation_flags & GraphicsPipe::BF_size_track_host) { 00204 if ((_host->get_x_size() != _x_size)|| 00205 (_host->get_y_size() != _y_size)) { 00206 set_size_and_recalc(_host->get_x_size(), 00207 _host->get_y_size()); 00208 } 00209 } else { 00210 if (_host->get_x_size() < _x_size || 00211 _host->get_y_size() < _y_size) { 00212 set_size_and_recalc(min(_x_size, _host->get_x_size()), 00213 min(_y_size, _host->get_y_size())); 00214 } 00215 } 00216 00217 clear_cube_map_selection(); 00218 return true; 00219 } 00220 00221 //////////////////////////////////////////////////////////////////// 00222 // Function: ParasiteBuffer::end_frame 00223 // Access: Public, Virtual 00224 // Description: This function will be called within the draw thread 00225 // after rendering is completed for a given frame. It 00226 // should do whatever finalization is required. 00227 //////////////////////////////////////////////////////////////////// 00228 void ParasiteBuffer:: 00229 end_frame(FrameMode mode, Thread *current_thread) { 00230 end_frame_spam(mode); 00231 00232 nassertv(_gsg != (GraphicsStateGuardian *)NULL); 00233 00234 _host->end_frame(FM_parasite, current_thread); 00235 00236 if (mode == FM_refresh) { 00237 return; 00238 } 00239 00240 if (mode == FM_render) { 00241 promote_to_copy_texture(); 00242 copy_to_textures(); 00243 clear_cube_map_selection(); 00244 } 00245 } 00246 00247 //////////////////////////////////////////////////////////////////// 00248 // Function: ParasiteBuffer::get_host 00249 // Access: Public, Virtual 00250 // Description: This is normally called only from within 00251 // make_texture_buffer(). When called on a 00252 // ParasiteBuffer, it returns the host of that buffer; 00253 // but when called on some other buffer, it returns the 00254 // buffer itself. 00255 //////////////////////////////////////////////////////////////////// 00256 GraphicsOutput *ParasiteBuffer:: 00257 get_host() { 00258 return _host; 00259 } 00260