00001 // Filename: videoTexture.cxx 00002 // Created by: drose (21Sep05) 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 "pandabase.h" 00016 00017 #include "videoTexture.h" 00018 #include "clockObject.h" 00019 #include "config_gobj.h" 00020 00021 TypeHandle VideoTexture::_type_handle; 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: VideoTexture::Constructor 00025 // Access: Protected 00026 // Description: 00027 //////////////////////////////////////////////////////////////////// 00028 VideoTexture:: 00029 VideoTexture(const string &name) : 00030 Texture(name) 00031 { 00032 // We don't want to try to compress each frame as it's loaded. 00033 Texture::CDWriter cdata(Texture::_cycler, true); 00034 cdata->_compression = CM_off; 00035 00036 _video_width = 0; 00037 _video_height = 0; 00038 00039 _last_frame_update = 0; 00040 _current_frame = -1; 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: VideoTexture::Copy Constructor 00045 // Access: Protected 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 VideoTexture:: 00049 VideoTexture(const VideoTexture ©) : 00050 Texture(copy), 00051 AnimInterface(copy), 00052 _video_width(copy._video_width), 00053 _video_height(copy._video_height), 00054 _last_frame_update(copy._last_frame_update), 00055 _current_frame(copy._current_frame) 00056 { 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: VideoTexture::get_keep_ram_image 00061 // Access: Published, Virtual 00062 // Description: Returns the flag that indicates whether this Texture 00063 // is eligible to have its main RAM copy of the texture 00064 // memory dumped when the texture is prepared for 00065 // rendering. See set_keep_ram_image(). 00066 //////////////////////////////////////////////////////////////////// 00067 bool VideoTexture:: 00068 get_keep_ram_image() const { 00069 // A VideoTexture should never dump its RAM image. 00070 return true; 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: VideoTexture::has_cull_callback 00075 // Access: Public, Virtual 00076 // Description: Should be overridden by derived classes to return 00077 // true if cull_callback() has been defined. Otherwise, 00078 // returns false to indicate cull_callback() does not 00079 // need to be called for this node during the cull 00080 // traversal. 00081 //////////////////////////////////////////////////////////////////// 00082 bool VideoTexture:: 00083 has_cull_callback() const { 00084 return true; 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: VideoTexture::cull_callback 00089 // Access: Public, Virtual 00090 // Description: If has_cull_callback() returns true, this function 00091 // will be called during the cull traversal to perform 00092 // any additional operations that should be performed at 00093 // cull time. 00094 // 00095 // This is called each time the Texture is discovered 00096 // applied to a Geom in the traversal. It should return 00097 // true if the Geom is visible, false if it should be 00098 // omitted. 00099 //////////////////////////////////////////////////////////////////// 00100 bool VideoTexture:: 00101 cull_callback(CullTraverser *, const CullTraverserData &) const { 00102 // Strictly speaking, the cull_callback() method isn't necessary for 00103 // VideoTexture, since the get_ram_image() function is already 00104 // overloaded to update itself if necessary. However, we define it 00105 // anyway, to move the update calculation into the cull traversal 00106 // rather than the draw traversal. 00107 ((VideoTexture *)this)->reconsider_dirty(); 00108 return true; 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: VideoTexture::set_video_size 00113 // Access: Protected 00114 // Description: Should be called by a derived class to set the size 00115 // of the video when it is loaded. Assumes the lock is 00116 // held. 00117 //////////////////////////////////////////////////////////////////// 00118 void VideoTexture:: 00119 set_video_size(int video_width, int video_height) { 00120 _video_width = video_width; 00121 _video_height = video_height; 00122 set_orig_file_size(video_width, video_height); 00123 00124 Texture::CDWriter cdata(Texture::_cycler, true); 00125 do_set_pad_size(cdata, 00126 max(cdata->_x_size - _video_width, 0), 00127 max(cdata->_y_size - _video_height, 0), 00128 0); 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: VideoTexture::do_has_ram_image 00133 // Access: Protected, Virtual 00134 // Description: Returns true if the Texture has its image contents 00135 // available in main RAM, false if it exists only in 00136 // texture memory or in the prepared GSG context. 00137 //////////////////////////////////////////////////////////////////// 00138 bool VideoTexture:: 00139 do_has_ram_image(const Texture::CData *cdata) const { 00140 int this_frame = ClockObject::get_global_clock()->get_frame_count(); 00141 if (this_frame != _last_frame_update) { 00142 return false; 00143 } 00144 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty(); 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: VideoTexture::reconsider_dirty 00149 // Access: Protected, Virtual 00150 // Description: Called by TextureContext to give the Texture a chance 00151 // to mark itself dirty before rendering, if necessary. 00152 //////////////////////////////////////////////////////////////////// 00153 void VideoTexture:: 00154 reconsider_dirty() { 00155 consider_update(); 00156 } 00157 00158 00159 //////////////////////////////////////////////////////////////////// 00160 // Function: VideoTexture::unlocked_ensure_ram_image 00161 // Access: Protected, Virtual 00162 // Description: If the texture has a ram image already, this acquires 00163 // the CData write lock and returns it. 00164 // 00165 // If the texture lacks a ram image, this performs 00166 // do_reload_ram_image(), but without holding the lock 00167 // on this particular Texture object, to avoid holding 00168 // the lock across what might be a slow operation. 00169 // Instead, the reload is performed in a copy of the 00170 // texture object, and then the lock is acquired and the 00171 // data is copied in. 00172 // 00173 // In any case, the return value is a locked CData 00174 // object, which must be released with an explicit call 00175 // to release_write(). The CData object will have a ram 00176 // image unless for some reason do_reload_ram_image() 00177 // fails. 00178 //////////////////////////////////////////////////////////////////// 00179 Texture::CData *VideoTexture:: 00180 unlocked_ensure_ram_image(bool allow_compression) { 00181 consider_update(); 00182 00183 Thread *current_thread = Thread::get_current_thread(); 00184 Texture::CData *cdata = Texture::_cycler.write_upstream(false, current_thread); 00185 return cdata; 00186 } 00187 00188 //////////////////////////////////////////////////////////////////// 00189 // Function: VideoTexture::do_reload_ram_image 00190 // Access: Protected, Virtual 00191 // Description: Called when the Texture image is required but the ram 00192 // image is not available, this will reload it from disk 00193 // or otherwise do whatever is required to make it 00194 // available, if possible. 00195 //////////////////////////////////////////////////////////////////// 00196 void VideoTexture:: 00197 do_reload_ram_image(Texture::CData *cdata, bool) { 00198 consider_update(); 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: VideoTexture::do_can_reload 00203 // Access: Protected, Virtual 00204 // Description: Returns true if we can safely call 00205 // do_unlock_and_reload_ram_image() in order to make the 00206 // image available, or false if we shouldn't do this 00207 // (because we know from a priori knowledge that it 00208 // wouldn't work anyway). 00209 //////////////////////////////////////////////////////////////////// 00210 bool VideoTexture:: 00211 do_can_reload(const Texture::CData *cdata) const { 00212 return true; 00213 } 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: VideoTexture::do_adjust_this_size 00217 // Access: Protected, Virtual 00218 // Description: Works like adjust_size, but also considers the 00219 // texture class. Movie textures, for instance, always 00220 // pad outwards, never scale down. 00221 //////////////////////////////////////////////////////////////////// 00222 bool VideoTexture:: 00223 do_adjust_this_size(const Texture::CData *cdata_tex, 00224 int &x_size, int &y_size, const string &name, 00225 bool for_padding) const { 00226 AutoTextureScale ats = do_get_auto_texture_scale(cdata_tex); 00227 if (ats != ATS_none) { 00228 ats = ATS_pad; 00229 } 00230 00231 return adjust_size(x_size, y_size, name, for_padding, ats); 00232 } 00233 00234 //////////////////////////////////////////////////////////////////// 00235 // Function: VideoTexture::consider_update 00236 // Access: Protected, Virtual 00237 // Description: Calls update_frame() if the current frame has 00238 // changed. 00239 //////////////////////////////////////////////////////////////////// 00240 void VideoTexture:: 00241 consider_update() { 00242 int this_frame = ClockObject::get_global_clock()->get_frame_count(); 00243 if (this_frame != _last_frame_update) { 00244 int frame = get_frame(); 00245 if (_current_frame != frame) { 00246 Texture::CDWriter cdata(Texture::_cycler, false); 00247 do_update_frame(cdata, frame); 00248 _current_frame = frame; 00249 } 00250 _last_frame_update = this_frame; 00251 } 00252 }