Panda3D

preparedGraphicsObjects.cxx

00001 // Filename: preparedGraphicsObjects.cxx
00002 // Created by:  drose (19Feb04)
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 "preparedGraphicsObjects.h"
00016 #include "textureContext.h"
00017 #include "vertexBufferContext.h"
00018 #include "indexBufferContext.h"
00019 #include "texture.h"
00020 #include "geom.h"
00021 #include "geomVertexArrayData.h"
00022 #include "geomPrimitive.h"
00023 #include "shader.h"
00024 #include "reMutexHolder.h"
00025 #include "geomContext.h"
00026 #include "shaderContext.h"
00027 #include "config_gobj.h"
00028 #include "throw_event.h"
00029 
00030 int PreparedGraphicsObjects::_name_index = 0;
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: PreparedGraphicsObjects::Constructor
00034 //       Access: Public
00035 //  Description: 
00036 ////////////////////////////////////////////////////////////////////
00037 PreparedGraphicsObjects::
00038 PreparedGraphicsObjects() : 
00039   _lock("PreparedGraphicsObjects::_lock"),
00040   _name(init_name()),
00041   _vertex_buffer_cache_size(0),
00042   _index_buffer_cache_size(0),
00043   _texture_residency(_name, "texture"),
00044   _vbuffer_residency(_name, "vbuffer"),
00045   _ibuffer_residency(_name, "ibuffer"),
00046   _graphics_memory_lru("graphics_memory_lru", graphics_memory_limit)
00047 {
00048   // GLGSG will turn this flag on.  This is a temporary hack to
00049   // disable this feature for DX8/DX9 for now, until we work out the
00050   // fine points of updating the fvf properly.
00051   _support_released_buffer_cache = false;
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: PreparedGraphicsObjects::Destructor
00056 //       Access: Public
00057 //  Description: 
00058 ////////////////////////////////////////////////////////////////////
00059 PreparedGraphicsObjects::
00060 ~PreparedGraphicsObjects() {
00061   // There may be objects that are still prepared when we destruct.
00062   // If this is so, then all of the GSG's that own them have already
00063   // destructed, so we can assume their resources were internally
00064   // cleaned up.  Quietly erase these remaining objects.
00065   ReMutexHolder holder(_lock);
00066 
00067   release_all_textures();
00068   Textures::iterator tci;
00069   for (tci = _released_textures.begin();
00070        tci != _released_textures.end();
00071        ++tci) {
00072     TextureContext *tc = (*tci);
00073     tc->set_owning_chain(NULL);
00074   }
00075   // Is this a leak?  Should we delete these TextureContexts?
00076   _released_textures.clear();
00077 
00078   release_all_geoms();
00079   _released_geoms.clear();
00080 
00081   release_all_shaders();
00082   _released_shaders.clear();
00083 
00084   release_all_vertex_buffers();
00085   Buffers::iterator vbci;
00086   for (vbci = _released_vertex_buffers.begin();
00087        vbci != _released_vertex_buffers.end();
00088        ++vbci) {
00089     VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
00090     vbc->set_owning_chain(NULL);
00091   }
00092   _released_vertex_buffers.clear();
00093 
00094   release_all_index_buffers();
00095   Buffers::iterator ibci;
00096   for (ibci = _released_index_buffers.begin();
00097        ibci != _released_index_buffers.end();
00098        ++ibci) {
00099     IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
00100     ibc->set_owning_chain(NULL);
00101   }
00102   _released_index_buffers.clear();
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: PreparedGraphicsObjects::set_graphics_memory_limit
00107 //       Access: Public
00108 //  Description: Sets an artificial cap on graphics memory that
00109 //               will be imposed on this GSG.
00110 //
00111 //               This limits the total amount of graphics memory,
00112 //               including texture memory and vertex buffer memory,
00113 //               that will be consumed by the GSG, regardless of
00114 //               whether the hardware claims to provide more graphics
00115 //               memory than this. It is useful to put a ceiling on
00116 //               graphics memory consumed, since some drivers seem to
00117 //               allow the application to consume more memory than the
00118 //               hardware can realistically support.
00119 ////////////////////////////////////////////////////////////////////
00120 void PreparedGraphicsObjects::
00121 set_graphics_memory_limit(size_t limit) {
00122   if (limit != _graphics_memory_lru.get_max_size()) {
00123     _graphics_memory_lru.set_max_size(limit);
00124   
00125     // We throw an event here so global objects (particularly the
00126     // TexMemWatcher) can automatically respond to this change.
00127     throw_event("graphics_memory_limit_changed");
00128   }
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: PreparedGraphicsObjects::show_graphics_memory_lru
00133 //       Access: Public
00134 //  Description: Writes to the indicated ostream a report of how the
00135 //               various textures and vertex buffers are allocated in
00136 //               the LRU.
00137 ////////////////////////////////////////////////////////////////////
00138 void PreparedGraphicsObjects::
00139 show_graphics_memory_lru(ostream &out) const {
00140   _graphics_memory_lru.write(out, 0);
00141 }
00142 
00143 ////////////////////////////////////////////////////////////////////
00144 //     Function: PreparedGraphicsObjects::show_residency_trackers
00145 //       Access: Public
00146 //  Description: Writes to the indicated ostream a report of how the
00147 //               various textures and vertex buffers are allocated in
00148 //               the LRU.
00149 ////////////////////////////////////////////////////////////////////
00150 void PreparedGraphicsObjects::
00151 show_residency_trackers(ostream &out) const {
00152   out << "Textures:\n";
00153   _texture_residency.write(out, 2);
00154 
00155   out << "\nVertex buffers:\n";
00156   _vbuffer_residency.write(out, 2);
00157 
00158   out << "\nIndex buffers:\n";
00159   _ibuffer_residency.write(out, 2);
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: PreparedGraphicsObjects::enqueue_texture
00164 //       Access: Public
00165 //  Description: Indicates that a texture would like to be put on the
00166 //               list to be prepared when the GSG is next ready to
00167 //               do this (presumably at the next frame).
00168 ////////////////////////////////////////////////////////////////////
00169 void PreparedGraphicsObjects::
00170 enqueue_texture(Texture *tex) {
00171   ReMutexHolder holder(_lock);
00172 
00173   _enqueued_textures.insert(tex);
00174 }
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: PreparedGraphicsObjects::is_texture_queued
00178 //       Access: Public
00179 //  Description: Returns true if the texture has been queued on this
00180 //               GSG, false otherwise.
00181 ////////////////////////////////////////////////////////////////////
00182 bool PreparedGraphicsObjects::
00183 is_texture_queued(const Texture *tex) const {
00184   ReMutexHolder holder(_lock);
00185 
00186   EnqueuedTextures::const_iterator qi = _enqueued_textures.find((Texture *)tex);
00187   return (qi != _enqueued_textures.end());
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: PreparedGraphicsObjects::dequeue_texture
00192 //       Access: Public
00193 //  Description: Removes a texture from the queued list of textures to
00194 //               be prepared.  Normally it is not necessary to call
00195 //               this, unless you change your mind about preparing it
00196 //               at the last minute, since the texture will
00197 //               automatically be dequeued and prepared at the next
00198 //               frame.
00199 //
00200 //               The return value is true if the texture is
00201 //               successfully dequeued, false if it had not been
00202 //               queued.
00203 ////////////////////////////////////////////////////////////////////
00204 bool PreparedGraphicsObjects::
00205 dequeue_texture(Texture *tex) {
00206   ReMutexHolder holder(_lock);
00207 
00208   EnqueuedTextures::iterator qi = _enqueued_textures.find(tex);
00209   if (qi != _enqueued_textures.end()) {
00210     _enqueued_textures.erase(qi);
00211     return true;
00212   }
00213   return false;
00214 }
00215 
00216 ////////////////////////////////////////////////////////////////////
00217 //     Function: PreparedGraphicsObjects::is_texture_prepared
00218 //       Access: Public
00219 //  Description: Returns true if the texture has been prepared on
00220 //               this GSG, false otherwise.
00221 ////////////////////////////////////////////////////////////////////
00222 bool PreparedGraphicsObjects::
00223 is_texture_prepared(const Texture *tex) const {
00224   return tex->is_prepared((PreparedGraphicsObjects *)this);
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: PreparedGraphicsObjects::release_texture
00229 //       Access: Public
00230 //  Description: Indicates that a texture context, created by a
00231 //               previous call to prepare_texture(), is no longer
00232 //               needed.  The driver resources will not be freed until
00233 //               some GSG calls update(), indicating it is at a
00234 //               stage where it is ready to release textures--this
00235 //               prevents conflicts from threading or multiple GSG's
00236 //               sharing textures (we have no way of knowing which
00237 //               graphics context is currently active, or what state
00238 //               it's in, at the time release_texture is called).
00239 ////////////////////////////////////////////////////////////////////
00240 void PreparedGraphicsObjects::
00241 release_texture(TextureContext *tc) {
00242   ReMutexHolder holder(_lock);
00243 
00244   tc->_texture->clear_prepared(tc->get_view(), this);
00245 
00246   // We have to set the Texture pointer to NULL at this point, since
00247   // the Texture itself might destruct at any time after it has been
00248   // released.
00249   tc->_texture = (Texture *)NULL;
00250 
00251   bool removed = (_prepared_textures.erase(tc) != 0);
00252   nassertv(removed);
00253 
00254   _released_textures.insert(tc);
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: PreparedGraphicsObjects::release_texture
00259 //       Access: Public
00260 //  Description: Releases a texture if it has already been prepared,
00261 //               or removes it from the preparation queue.
00262 ////////////////////////////////////////////////////////////////////
00263 void PreparedGraphicsObjects::
00264 release_texture(Texture *tex) {
00265   tex->release(this);
00266 }
00267 
00268 ////////////////////////////////////////////////////////////////////
00269 //     Function: PreparedGraphicsObjects::release_all_textures
00270 //       Access: Public
00271 //  Description: Releases all textures at once.  This will force them
00272 //               to be reloaded into texture memory for all GSG's that
00273 //               share this object.  Returns the number of textures
00274 //               released.
00275 ////////////////////////////////////////////////////////////////////
00276 int PreparedGraphicsObjects::
00277 release_all_textures() {
00278   ReMutexHolder holder(_lock);
00279 
00280   int num_textures = (int)_prepared_textures.size() + (int)_enqueued_textures.size();
00281 
00282   Textures::iterator tci;
00283   for (tci = _prepared_textures.begin();
00284        tci != _prepared_textures.end();
00285        ++tci) {
00286     TextureContext *tc = (*tci);
00287     tc->_texture->clear_prepared(tc->get_view(), this);
00288     tc->_texture = (Texture *)NULL;
00289 
00290     _released_textures.insert(tc);
00291   }
00292 
00293   _prepared_textures.clear();
00294   _enqueued_textures.clear();
00295 
00296   return num_textures;
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: PreparedGraphicsObjects::get_num_queued_textures
00301 //       Access: Public
00302 //  Description: Returns the number of textures that have been
00303 //               enqueued to be prepared on this GSG.
00304 ////////////////////////////////////////////////////////////////////
00305 int PreparedGraphicsObjects::
00306 get_num_queued_textures() const {
00307   return _enqueued_textures.size();
00308 }
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: PreparedGraphicsObjects::get_num_prepared_textures
00312 //       Access: Public
00313 //  Description: Returns the number of textures that have already been
00314 //               prepared on this GSG.
00315 ////////////////////////////////////////////////////////////////////
00316 int PreparedGraphicsObjects::
00317 get_num_prepared_textures() const {
00318   return _prepared_textures.size();
00319 }
00320 
00321 ////////////////////////////////////////////////////////////////////
00322 //     Function: PreparedGraphicsObjects::prepare_texture_now
00323 //       Access: Public
00324 //  Description: Immediately creates a new TextureContext for the
00325 //               indicated texture and returns it.  This assumes that
00326 //               the GraphicsStateGuardian is the currently active
00327 //               rendering context and that it is ready to accept new
00328 //               textures.  If this is not necessarily the case, you
00329 //               should use enqueue_texture() instead.
00330 //
00331 //               Normally, this function is not called directly.  Call
00332 //               Texture::prepare_now() instead.
00333 //
00334 //               The TextureContext contains all of the pertinent
00335 //               information needed by the GSG to keep track of this
00336 //               one particular texture, and will exist as long as the
00337 //               texture is ready to be rendered.
00338 //
00339 //               When either the Texture or the
00340 //               PreparedGraphicsObjects object destructs, the
00341 //               TextureContext will be deleted.
00342 ////////////////////////////////////////////////////////////////////
00343 TextureContext *PreparedGraphicsObjects::
00344 prepare_texture_now(Texture *tex, int view, GraphicsStateGuardianBase *gsg) {
00345   ReMutexHolder holder(_lock);
00346 
00347   // Ask the GSG to create a brand new TextureContext.  There might
00348   // be several GSG's sharing the same set of textures; if so, it
00349   // doesn't matter which of them creates the context (since they're
00350   // all shared anyway).
00351   TextureContext *tc = gsg->prepare_texture(tex, view);
00352 
00353   if (tc != (TextureContext *)NULL) {
00354     bool prepared = _prepared_textures.insert(tc).second;
00355     nassertr(prepared, tc);
00356   }
00357 
00358   return tc;
00359 }
00360 
00361 ////////////////////////////////////////////////////////////////////
00362 //     Function: PreparedGraphicsObjects::enqueue_geom
00363 //       Access: Public
00364 //  Description: Indicates that a geom would like to be put on the
00365 //               list to be prepared when the GSG is next ready to
00366 //               do this (presumably at the next frame).
00367 ////////////////////////////////////////////////////////////////////
00368 void PreparedGraphicsObjects::
00369 enqueue_geom(Geom *geom) {
00370   ReMutexHolder holder(_lock);
00371 
00372   _enqueued_geoms.insert(geom);
00373 }
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: PreparedGraphicsObjects::is_geom_queued
00377 //       Access: Public
00378 //  Description: Returns true if the geom has been queued on this
00379 //               GSG, false otherwise.
00380 ////////////////////////////////////////////////////////////////////
00381 bool PreparedGraphicsObjects::
00382 is_geom_queued(const Geom *geom) const {
00383   ReMutexHolder holder(_lock);
00384 
00385   EnqueuedGeoms::const_iterator qi = _enqueued_geoms.find((Geom *)geom);
00386   return (qi != _enqueued_geoms.end());
00387 }
00388 
00389 ////////////////////////////////////////////////////////////////////
00390 //     Function: PreparedGraphicsObjects::dequeue_geom
00391 //       Access: Public
00392 //  Description: Removes a geom from the queued list of geoms to
00393 //               be prepared.  Normally it is not necessary to call
00394 //               this, unless you change your mind about preparing it
00395 //               at the last minute, since the geom will
00396 //               automatically be dequeued and prepared at the next
00397 //               frame.
00398 //
00399 //               The return value is true if the geom is
00400 //               successfully dequeued, false if it had not been
00401 //               queued.
00402 ////////////////////////////////////////////////////////////////////
00403 bool PreparedGraphicsObjects::
00404 dequeue_geom(Geom *geom) {
00405   ReMutexHolder holder(_lock);
00406 
00407   EnqueuedGeoms::iterator qi = _enqueued_geoms.find(geom);
00408   if (qi != _enqueued_geoms.end()) {
00409     _enqueued_geoms.erase(qi);
00410     return true;
00411   }
00412   return false;
00413 }
00414 
00415 ////////////////////////////////////////////////////////////////////
00416 //     Function: PreparedGraphicsObjects::is_geom_prepared
00417 //       Access: Public
00418 //  Description: Returns true if the vertex buffer has been prepared on
00419 //               this GSG, false otherwise.
00420 ////////////////////////////////////////////////////////////////////
00421 bool PreparedGraphicsObjects::
00422 is_geom_prepared(const Geom *geom) const {
00423   return geom->is_prepared((PreparedGraphicsObjects *)this);
00424 }
00425 
00426 ////////////////////////////////////////////////////////////////////
00427 //     Function: PreparedGraphicsObjects::release_geom
00428 //       Access: Public
00429 //  Description: Indicates that a geom context, created by a
00430 //               previous call to prepare_geom(), is no longer
00431 //               needed.  The driver resources will not be freed until
00432 //               some GSG calls update(), indicating it is at a
00433 //               stage where it is ready to release geoms--this
00434 //               prevents conflicts from threading or multiple GSG's
00435 //               sharing geoms (we have no way of knowing which
00436 //               graphics context is currently active, or what state
00437 //               it's in, at the time release_geom is called).
00438 ////////////////////////////////////////////////////////////////////
00439 void PreparedGraphicsObjects::
00440 release_geom(GeomContext *gc) {
00441   ReMutexHolder holder(_lock);
00442 
00443   gc->_geom->clear_prepared(this);
00444 
00445   // We have to set the Geom pointer to NULL at this point, since
00446   // the Geom itself might destruct at any time after it has been
00447   // released.
00448   gc->_geom = (Geom *)NULL;
00449 
00450   bool removed = (_prepared_geoms.erase(gc) != 0);
00451   nassertv(removed);
00452 
00453   _released_geoms.insert(gc);
00454 }
00455 
00456 ////////////////////////////////////////////////////////////////////
00457 //     Function: PreparedGraphicsObjects::release_all_geoms
00458 //       Access: Public
00459 //  Description: Releases all geoms at once.  This will force them
00460 //               to be reloaded into geom memory for all GSG's that
00461 //               share this object.  Returns the number of geoms
00462 //               released.
00463 ////////////////////////////////////////////////////////////////////
00464 int PreparedGraphicsObjects::
00465 release_all_geoms() {
00466   ReMutexHolder holder(_lock);
00467 
00468   int num_geoms = (int)_prepared_geoms.size() + (int)_enqueued_geoms.size();
00469 
00470   Geoms::iterator gci;
00471   for (gci = _prepared_geoms.begin();
00472        gci != _prepared_geoms.end();
00473        ++gci) {
00474     GeomContext *gc = (*gci);
00475     gc->_geom->clear_prepared(this);
00476     gc->_geom = (Geom *)NULL;
00477 
00478     _released_geoms.insert(gc);
00479   }
00480 
00481   _prepared_geoms.clear();
00482   _enqueued_geoms.clear();
00483 
00484   return num_geoms;
00485 }
00486 
00487 ////////////////////////////////////////////////////////////////////
00488 //     Function: PreparedGraphicsObjects::get_num_queued_geoms
00489 //       Access: Public
00490 //  Description: Returns the number of geoms that have been
00491 //               enqueued to be prepared on this GSG.
00492 ////////////////////////////////////////////////////////////////////
00493 int PreparedGraphicsObjects::
00494 get_num_queued_geoms() const {
00495   return _enqueued_geoms.size();
00496 }
00497 
00498 ////////////////////////////////////////////////////////////////////
00499 //     Function: PreparedGraphicsObjects::get_num_prepared_geoms
00500 //       Access: Public
00501 //  Description: Returns the number of geoms that have already been
00502 //               prepared on this GSG.
00503 ////////////////////////////////////////////////////////////////////
00504 int PreparedGraphicsObjects::
00505 get_num_prepared_geoms() const {
00506   return _prepared_geoms.size();
00507 }
00508 
00509 ////////////////////////////////////////////////////////////////////
00510 //     Function: PreparedGraphicsObjects::prepare_geom_now
00511 //       Access: Public
00512 //  Description: Immediately creates a new GeomContext for the
00513 //               indicated geom and returns it.  This assumes that
00514 //               the GraphicsStateGuardian is the currently active
00515 //               rendering context and that it is ready to accept new
00516 //               geoms.  If this is not necessarily the case, you
00517 //               should use enqueue_geom() instead.
00518 //
00519 //               Normally, this function is not called directly.  Call
00520 //               Geom::prepare_now() instead.
00521 //
00522 //               The GeomContext contains all of the pertinent
00523 //               information needed by the GSG to keep track of this
00524 //               one particular geom, and will exist as long as the
00525 //               geom is ready to be rendered.
00526 //
00527 //               When either the Geom or the
00528 //               PreparedGraphicsObjects object destructs, the
00529 //               GeomContext will be deleted.
00530 ////////////////////////////////////////////////////////////////////
00531 GeomContext *PreparedGraphicsObjects::
00532 prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg) {
00533   ReMutexHolder holder(_lock);
00534 
00535   // Ask the GSG to create a brand new GeomContext.  There might
00536   // be several GSG's sharing the same set of geoms; if so, it
00537   // doesn't matter which of them creates the context (since they're
00538   // all shared anyway).
00539   GeomContext *gc = gsg->prepare_geom(geom);
00540 
00541   if (gc != (GeomContext *)NULL) {
00542     bool prepared = _prepared_geoms.insert(gc).second;
00543     nassertr(prepared, gc);
00544   }
00545 
00546   return gc;
00547 }
00548 
00549 ////////////////////////////////////////////////////////////////////
00550 //     Function: PreparedGraphicsObjects::enqueue_shader
00551 //       Access: Public
00552 //  Description: Indicates that a shader would like to be put on the
00553 //               list to be prepared when the GSG is next ready to
00554 //               do this (presumably at the next frame).
00555 ////////////////////////////////////////////////////////////////////
00556 void PreparedGraphicsObjects::
00557 enqueue_shader(Shader *se) {
00558   ReMutexHolder holder(_lock);
00559 
00560   _enqueued_shaders.insert(se);
00561 }
00562 
00563 ////////////////////////////////////////////////////////////////////
00564 //     Function: PreparedGraphicsObjects::is_shader_queued
00565 //       Access: Public
00566 //  Description: Returns true if the shader has been queued on this
00567 //               GSG, false otherwise.
00568 ////////////////////////////////////////////////////////////////////
00569 bool PreparedGraphicsObjects::
00570 is_shader_queued(const Shader *shader) const {
00571   ReMutexHolder holder(_lock);
00572 
00573   EnqueuedShaders::const_iterator qi = _enqueued_shaders.find((Shader *)shader);
00574   return (qi != _enqueued_shaders.end());
00575 }
00576 
00577 ////////////////////////////////////////////////////////////////////
00578 //     Function: PreparedGraphicsObjects::dequeue_shader
00579 //       Access: Public
00580 //  Description: Removes a shader from the queued list of shaders to
00581 //               be prepared.  Normally it is not necessary to call
00582 //               this, unless you change your mind about preparing it
00583 //               at the last minute, since the shader will
00584 //               automatically be dequeued and prepared at the next
00585 //               frame.
00586 //
00587 //               The return value is true if the shader is
00588 //               successfully dequeued, false if it had not been
00589 //               queued.
00590 ////////////////////////////////////////////////////////////////////
00591 bool PreparedGraphicsObjects::
00592 dequeue_shader(Shader *se) {
00593   ReMutexHolder holder(_lock);
00594 
00595   EnqueuedShaders::iterator qi = _enqueued_shaders.find(se);
00596   if (qi != _enqueued_shaders.end()) {
00597     _enqueued_shaders.erase(qi);
00598     return true;
00599   }
00600   return false;
00601 }
00602 
00603 ////////////////////////////////////////////////////////////////////
00604 //     Function: PreparedGraphicsObjects::is_shader_prepared
00605 //       Access: Public
00606 //  Description: Returns true if the shader has been prepared on
00607 //               this GSG, false otherwise.
00608 ////////////////////////////////////////////////////////////////////
00609 bool PreparedGraphicsObjects::
00610 is_shader_prepared(const Shader *shader) const {
00611   return shader->is_prepared((PreparedGraphicsObjects *)this);
00612 }
00613 
00614 ////////////////////////////////////////////////////////////////////
00615 //     Function: PreparedGraphicsObjects::release_shader
00616 //       Access: Public
00617 //  Description: Indicates that a shader context, created by a
00618 //               previous call to prepare_shader(), is no longer
00619 //               needed.  The driver resources will not be freed until
00620 //               some GSG calls update(), indicating it is at a
00621 //               stage where it is ready to release shaders--this
00622 //               prevents conflicts from threading or multiple GSG's
00623 //               sharing shaders (we have no way of knowing which
00624 //               graphics context is currently active, or what state
00625 //               it's in, at the time release_shader is called).
00626 ////////////////////////////////////////////////////////////////////
00627 void PreparedGraphicsObjects::
00628 release_shader(ShaderContext *sc) {
00629   ReMutexHolder holder(_lock);
00630 
00631   sc->_shader->clear_prepared(this);
00632 
00633   // We have to set the Shader pointer to NULL at this point, since
00634   // the Shader itself might destruct at any time after it has been
00635   // released.
00636   sc->_shader = (Shader *)NULL;
00637 
00638   bool removed = (_prepared_shaders.erase(sc) != 0);
00639   nassertv(removed);
00640 
00641   _released_shaders.insert(sc);
00642 }
00643 
00644 ////////////////////////////////////////////////////////////////////
00645 //     Function: PreparedGraphicsObjects::release_all_shaders
00646 //       Access: Public
00647 //  Description: Releases all shaders at once.  This will force them
00648 //               to be reloaded into shader memory for all GSG's that
00649 //               share this object.  Returns the number of shaders
00650 //               released.
00651 ////////////////////////////////////////////////////////////////////
00652 int PreparedGraphicsObjects::
00653 release_all_shaders() {
00654   ReMutexHolder holder(_lock);
00655 
00656   int num_shaders = (int)_prepared_shaders.size() + (int)_enqueued_shaders.size();
00657 
00658   Shaders::iterator sci;
00659   for (sci = _prepared_shaders.begin();
00660        sci != _prepared_shaders.end();
00661        ++sci) {
00662     ShaderContext *sc = (*sci);
00663     sc->_shader->clear_prepared(this);
00664     sc->_shader = (Shader *)NULL;
00665 
00666     _released_shaders.insert(sc);
00667   }
00668 
00669   _prepared_shaders.clear();
00670   _enqueued_shaders.clear();
00671 
00672   return num_shaders;
00673 }
00674 
00675 ////////////////////////////////////////////////////////////////////
00676 //     Function: PreparedGraphicsObjects::get_num_queued_shaders
00677 //       Access: Public
00678 //  Description: Returns the number of shaders that have been
00679 //               enqueued to be prepared on this GSG.
00680 ////////////////////////////////////////////////////////////////////
00681 int PreparedGraphicsObjects::
00682 get_num_queued_shaders() const {
00683   return _enqueued_shaders.size();
00684 }
00685 
00686 ////////////////////////////////////////////////////////////////////
00687 //     Function: PreparedGraphicsObjects::get_num_prepared_shaders
00688 //       Access: Public
00689 //  Description: Returns the number of shaders that have already been
00690 //               prepared on this GSG.
00691 ////////////////////////////////////////////////////////////////////
00692 int PreparedGraphicsObjects::
00693 get_num_prepared_shaders() const {
00694   return _prepared_shaders.size();
00695 }
00696 
00697 ////////////////////////////////////////////////////////////////////
00698 //     Function: PreparedGraphicsObjects::prepare_shader_now
00699 //       Access: Public
00700 //  Description: Immediately creates a new ShaderContext for the
00701 //               indicated shader and returns it.  This assumes that
00702 //               the GraphicsStateGuardian is the currently active
00703 //               rendering context and that it is ready to accept new
00704 //               shaders.  If this is not necessarily the case, you
00705 //               should use enqueue_shader() instead.
00706 //
00707 //               Normally, this function is not called directly.  Call
00708 //               Shader::prepare_now() instead.
00709 //
00710 //               The ShaderContext contains all of the pertinent
00711 //               information needed by the GSG to keep track of this
00712 //               one particular shader, and will exist as long as the
00713 //               shader is ready to be rendered.
00714 //
00715 //               When either the Shader or the
00716 //               PreparedGraphicsObjects object destructs, the
00717 //               ShaderContext will be deleted.
00718 ////////////////////////////////////////////////////////////////////
00719 ShaderContext *PreparedGraphicsObjects::
00720 prepare_shader_now(Shader *se, GraphicsStateGuardianBase *gsg) {
00721   ReMutexHolder holder(_lock);
00722 
00723   // Ask the GSG to create a brand new ShaderContext.  There might
00724   // be several GSG's sharing the same set of shaders; if so, it
00725   // doesn't matter which of them creates the context (since they're
00726   // all shared anyway).
00727   ShaderContext *sc = gsg->prepare_shader(se);
00728 
00729   if (sc != (ShaderContext *)NULL) {
00730     bool prepared = _prepared_shaders.insert(sc).second;
00731     nassertr(prepared, sc);
00732   }
00733 
00734   return sc;
00735 }
00736 
00737 ////////////////////////////////////////////////////////////////////
00738 //     Function: PreparedGraphicsObjects::enqueue_vertex_buffer
00739 //       Access: Public
00740 //  Description: Indicates that a buffer would like to be put on the
00741 //               list to be prepared when the GSG is next ready to
00742 //               do this (presumably at the next frame).
00743 ////////////////////////////////////////////////////////////////////
00744 void PreparedGraphicsObjects::
00745 enqueue_vertex_buffer(GeomVertexArrayData *data) {
00746   ReMutexHolder holder(_lock);
00747 
00748   _enqueued_vertex_buffers.insert(data);
00749 }
00750 
00751 ////////////////////////////////////////////////////////////////////
00752 //     Function: PreparedGraphicsObjects::is_vertex_buffer_queued
00753 //       Access: Public
00754 //  Description: Returns true if the vertex buffer has been queued on
00755 //               this GSG, false otherwise.
00756 ////////////////////////////////////////////////////////////////////
00757 bool PreparedGraphicsObjects::
00758 is_vertex_buffer_queued(const GeomVertexArrayData *data) const {
00759   ReMutexHolder holder(_lock);
00760 
00761   EnqueuedVertexBuffers::const_iterator qi = _enqueued_vertex_buffers.find((GeomVertexArrayData *)data);
00762   return (qi != _enqueued_vertex_buffers.end());
00763 }
00764 
00765 ////////////////////////////////////////////////////////////////////
00766 //     Function: PreparedGraphicsObjects::dequeue_vertex_buffer
00767 //       Access: Public
00768 //  Description: Removes a buffer from the queued list of data
00769 //               arrays to be prepared.  Normally it is not necessary
00770 //               to call this, unless you change your mind about
00771 //               preparing it at the last minute, since the data will
00772 //               automatically be dequeued and prepared at the next
00773 //               frame.
00774 //
00775 //               The return value is true if the buffer is
00776 //               successfully dequeued, false if it had not been
00777 //               queued.
00778 ////////////////////////////////////////////////////////////////////
00779 bool PreparedGraphicsObjects::
00780 dequeue_vertex_buffer(GeomVertexArrayData *data) {
00781   ReMutexHolder holder(_lock);
00782 
00783   EnqueuedVertexBuffers::iterator qi = _enqueued_vertex_buffers.find(data);
00784   if (qi != _enqueued_vertex_buffers.end()) {
00785     _enqueued_vertex_buffers.erase(qi);
00786     return true;
00787   }
00788   return false;
00789 }
00790 
00791 ////////////////////////////////////////////////////////////////////
00792 //     Function: PreparedGraphicsObjects::is_vertex_buffer_prepared
00793 //       Access: Public
00794 //  Description: Returns true if the vertex buffer has been prepared on
00795 //               this GSG, false otherwise.
00796 ////////////////////////////////////////////////////////////////////
00797 bool PreparedGraphicsObjects::
00798 is_vertex_buffer_prepared(const GeomVertexArrayData *data) const {
00799   return data->is_prepared((PreparedGraphicsObjects *)this);
00800 }
00801 
00802 ////////////////////////////////////////////////////////////////////
00803 //     Function: PreparedGraphicsObjects::release_vertex_buffer
00804 //       Access: Public
00805 //  Description: Indicates that a data context, created by a
00806 //               previous call to prepare_vertex_buffer(), is no longer
00807 //               needed.  The driver resources will not be freed until
00808 //               some GSG calls update(), indicating it is at a
00809 //               stage where it is ready to release datas--this
00810 //               prevents conflicts from threading or multiple GSG's
00811 //               sharing datas (we have no way of knowing which
00812 //               graphics context is currently active, or what state
00813 //               it's in, at the time release_vertex_buffer is called).
00814 ////////////////////////////////////////////////////////////////////
00815 void PreparedGraphicsObjects::
00816 release_vertex_buffer(VertexBufferContext *vbc) {
00817   ReMutexHolder holder(_lock);
00818 
00819   vbc->_data->clear_prepared(this);
00820 
00821   size_t data_size_bytes = vbc->_data->get_data_size_bytes();
00822   GeomEnums::UsageHint usage_hint = vbc->_data->get_usage_hint();
00823 
00824   // We have to set the Data pointer to NULL at this point, since
00825   // the Data itself might destruct at any time after it has been
00826   // released.
00827   vbc->_data = (GeomVertexArrayData *)NULL;
00828 
00829   bool removed = (_prepared_vertex_buffers.erase(vbc) != 0);
00830   nassertv(removed);
00831 
00832   if (_support_released_buffer_cache) {
00833     cache_unprepared_buffer(vbc, data_size_bytes, usage_hint,
00834                             _vertex_buffer_cache,
00835                             _vertex_buffer_cache_lru, _vertex_buffer_cache_size,
00836                             released_vbuffer_cache_size,
00837                             _released_vertex_buffers);
00838   } else {
00839     _released_vertex_buffers.insert(vbc);
00840   }
00841 }
00842 
00843 ////////////////////////////////////////////////////////////////////
00844 //     Function: PreparedGraphicsObjects::release_all_vertex_buffers
00845 //       Access: Public
00846 //  Description: Releases all datas at once.  This will force them
00847 //               to be reloaded into data memory for all GSG's that
00848 //               share this object.  Returns the number of datas
00849 //               released.
00850 ////////////////////////////////////////////////////////////////////
00851 int PreparedGraphicsObjects::
00852 release_all_vertex_buffers() {
00853   ReMutexHolder holder(_lock);
00854 
00855   int num_vertex_buffers = (int)_prepared_vertex_buffers.size() + (int)_enqueued_vertex_buffers.size();
00856 
00857   Buffers::iterator vbci;
00858   for (vbci = _prepared_vertex_buffers.begin();
00859        vbci != _prepared_vertex_buffers.end();
00860        ++vbci) {
00861     VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
00862     vbc->_data->clear_prepared(this);
00863     vbc->_data = (GeomVertexArrayData *)NULL;
00864 
00865     _released_vertex_buffers.insert(vbc);
00866   }
00867 
00868   _prepared_vertex_buffers.clear();
00869   _enqueued_vertex_buffers.clear();
00870 
00871   // Also clear the cache of recently-unprepared vertex buffers.
00872   BufferCache::iterator bci;
00873   for (bci = _vertex_buffer_cache.begin(); 
00874        bci != _vertex_buffer_cache.end(); 
00875        ++bci) {
00876     BufferList &buffer_list = (*bci).second;
00877     nassertr(!buffer_list.empty(), num_vertex_buffers);
00878     BufferList::iterator li;
00879     for (li = buffer_list.begin(); li != buffer_list.end(); ++li) {
00880       VertexBufferContext *vbc = (VertexBufferContext *)(*li);
00881       _released_vertex_buffers.insert(vbc);
00882     }
00883   }
00884   _vertex_buffer_cache.clear();
00885   _vertex_buffer_cache_lru.clear();
00886   _vertex_buffer_cache_size = 0;
00887   
00888   return num_vertex_buffers;
00889 }
00890 
00891 ////////////////////////////////////////////////////////////////////
00892 //     Function: PreparedGraphicsObjects::get_num_queued_vertex_buffers
00893 //       Access: Public
00894 //  Description: Returns the number of vertex buffers that have been
00895 //               enqueued to be prepared on this GSG.
00896 ////////////////////////////////////////////////////////////////////
00897 int PreparedGraphicsObjects::
00898 get_num_queued_vertex_buffers() const {
00899   return _enqueued_vertex_buffers.size();
00900 }
00901 
00902 ////////////////////////////////////////////////////////////////////
00903 //     Function: PreparedGraphicsObjects::get_num_prepared_vertex_buffers
00904 //       Access: Public
00905 //  Description: Returns the number of vertex buffers that have
00906 //               already been prepared on this GSG.
00907 ////////////////////////////////////////////////////////////////////
00908 int PreparedGraphicsObjects::
00909 get_num_prepared_vertex_buffers() const {
00910   return _prepared_vertex_buffers.size();
00911 }
00912 
00913 ////////////////////////////////////////////////////////////////////
00914 //     Function: PreparedGraphicsObjects::prepare_vertex_buffer_now
00915 //       Access: Public
00916 //  Description: Immediately creates a new VertexBufferContext for the
00917 //               indicated data and returns it.  This assumes that
00918 //               the GraphicsStateGuardian is the currently active
00919 //               rendering context and that it is ready to accept new
00920 //               datas.  If this is not necessarily the case, you
00921 //               should use enqueue_vertex_buffer() instead.
00922 //
00923 //               Normally, this function is not called directly.  Call
00924 //               Data::prepare_now() instead.
00925 //
00926 //               The VertexBufferContext contains all of the pertinent
00927 //               information needed by the GSG to keep track of this
00928 //               one particular data, and will exist as long as the
00929 //               data is ready to be rendered.
00930 //
00931 //               When either the Data or the
00932 //               PreparedGraphicsObjects object destructs, the
00933 //               VertexBufferContext will be deleted.
00934 ////////////////////////////////////////////////////////////////////
00935 VertexBufferContext *PreparedGraphicsObjects::
00936 prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *gsg) {
00937   ReMutexHolder holder(_lock);
00938 
00939   // First, see if there might be a cached context of the appropriate
00940   // size.
00941   size_t data_size_bytes = data->get_data_size_bytes();
00942   GeomEnums::UsageHint usage_hint = data->get_usage_hint();
00943   VertexBufferContext *vbc = (VertexBufferContext *)
00944     get_cached_buffer(data_size_bytes, usage_hint,
00945                       _vertex_buffer_cache, _vertex_buffer_cache_lru,
00946                       _vertex_buffer_cache_size);
00947   if (vbc != (VertexBufferContext *)NULL) {
00948     vbc->_data = data;
00949 
00950   } else {
00951     // Ask the GSG to create a brand new VertexBufferContext.  There
00952     // might be several GSG's sharing the same set of datas; if so, it
00953     // doesn't matter which of them creates the context (since they're
00954     // all shared anyway).
00955     vbc = gsg->prepare_vertex_buffer(data);
00956   }
00957 
00958   if (vbc != (VertexBufferContext *)NULL) {
00959     bool prepared = _prepared_vertex_buffers.insert(vbc).second;
00960     nassertr(prepared, vbc);
00961   }
00962 
00963   return vbc;
00964 }
00965 
00966 ////////////////////////////////////////////////////////////////////
00967 //     Function: PreparedGraphicsObjects::enqueue_index_buffer
00968 //       Access: Public
00969 //  Description: Indicates that a buffer would like to be put on the
00970 //               list to be prepared when the GSG is next ready to
00971 //               do this (presumably at the next frame).
00972 ////////////////////////////////////////////////////////////////////
00973 void PreparedGraphicsObjects::
00974 enqueue_index_buffer(GeomPrimitive *data) {
00975   ReMutexHolder holder(_lock);
00976 
00977   _enqueued_index_buffers.insert(data);
00978 }
00979 
00980 ////////////////////////////////////////////////////////////////////
00981 //     Function: PreparedGraphicsObjects::is_index_buffer_queued
00982 //       Access: Public
00983 //  Description: Returns true if the index buffer has been queued on
00984 //               this GSG, false otherwise.
00985 ////////////////////////////////////////////////////////////////////
00986 bool PreparedGraphicsObjects::
00987 is_index_buffer_queued(const GeomPrimitive *data) const {
00988   ReMutexHolder holder(_lock);
00989 
00990   EnqueuedIndexBuffers::const_iterator qi = _enqueued_index_buffers.find((GeomPrimitive *)data);
00991   return (qi != _enqueued_index_buffers.end());
00992 }
00993 
00994 ////////////////////////////////////////////////////////////////////
00995 //     Function: PreparedGraphicsObjects::dequeue_index_buffer
00996 //       Access: Public
00997 //  Description: Removes a buffer from the queued list of data
00998 //               arrays to be prepared.  Normally it is not necessary
00999 //               to call this, unless you change your mind about
01000 //               preparing it at the last minute, since the data will
01001 //               automatically be dequeued and prepared at the next
01002 //               frame.
01003 //
01004 //               The return value is true if the buffer is
01005 //               successfully dequeued, false if it had not been
01006 //               queued.
01007 ////////////////////////////////////////////////////////////////////
01008 bool PreparedGraphicsObjects::
01009 dequeue_index_buffer(GeomPrimitive *data) {
01010   ReMutexHolder holder(_lock);
01011 
01012   EnqueuedIndexBuffers::iterator qi = _enqueued_index_buffers.find(data);
01013   if (qi != _enqueued_index_buffers.end()) {
01014     _enqueued_index_buffers.erase(qi);
01015     return true;
01016   }
01017   return false;
01018 }
01019 
01020 ////////////////////////////////////////////////////////////////////
01021 //     Function: PreparedGraphicsObjects::is_index_buffer_prepared
01022 //       Access: Public
01023 //  Description: Returns true if the index buffer has been prepared on
01024 //               this GSG, false otherwise.
01025 ////////////////////////////////////////////////////////////////////
01026 bool PreparedGraphicsObjects::
01027 is_index_buffer_prepared(const GeomPrimitive *data) const {
01028   return data->is_prepared((PreparedGraphicsObjects *)this);
01029 }
01030 
01031 ////////////////////////////////////////////////////////////////////
01032 //     Function: PreparedGraphicsObjects::release_index_buffer
01033 //       Access: Public
01034 //  Description: Indicates that a data context, created by a
01035 //               previous call to prepare_index_buffer(), is no longer
01036 //               needed.  The driver resources will not be freed until
01037 //               some GSG calls update(), indicating it is at a
01038 //               stage where it is ready to release datas--this
01039 //               prevents conflicts from threading or multiple GSG's
01040 //               sharing datas (we have no way of knowing which
01041 //               graphics context is currently active, or what state
01042 //               it's in, at the time release_index_buffer is called).
01043 ////////////////////////////////////////////////////////////////////
01044 void PreparedGraphicsObjects::
01045 release_index_buffer(IndexBufferContext *ibc) {
01046   ReMutexHolder holder(_lock);
01047 
01048   ibc->_data->clear_prepared(this);
01049 
01050   size_t data_size_bytes = ibc->_data->get_data_size_bytes();
01051   GeomEnums::UsageHint usage_hint = ibc->_data->get_usage_hint();
01052 
01053   // We have to set the Data pointer to NULL at this point, since
01054   // the Data itself might destruct at any time after it has been
01055   // released.
01056   ibc->_data = (GeomPrimitive *)NULL;
01057 
01058   bool removed = (_prepared_index_buffers.erase(ibc) != 0);
01059   nassertv(removed);
01060 
01061   if (_support_released_buffer_cache) {
01062     cache_unprepared_buffer(ibc, data_size_bytes, usage_hint,
01063                             _index_buffer_cache,
01064                             _index_buffer_cache_lru, _index_buffer_cache_size,
01065                             released_ibuffer_cache_size,
01066                             _released_index_buffers);
01067   } else {
01068     _released_index_buffers.insert(ibc);
01069   }
01070 }
01071 
01072 ////////////////////////////////////////////////////////////////////
01073 //     Function: PreparedGraphicsObjects::release_all_index_buffers
01074 //       Access: Public
01075 //  Description: Releases all datas at once.  This will force them
01076 //               to be reloaded into data memory for all GSG's that
01077 //               share this object.  Returns the number of datas
01078 //               released.
01079 ////////////////////////////////////////////////////////////////////
01080 int PreparedGraphicsObjects::
01081 release_all_index_buffers() {
01082   ReMutexHolder holder(_lock);
01083 
01084   int num_index_buffers = (int)_prepared_index_buffers.size() + (int)_enqueued_index_buffers.size();
01085 
01086   Buffers::iterator ibci;
01087   for (ibci = _prepared_index_buffers.begin();
01088        ibci != _prepared_index_buffers.end();
01089        ++ibci) {
01090     IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
01091     ibc->_data->clear_prepared(this);
01092     ibc->_data = (GeomPrimitive *)NULL;
01093 
01094     _released_index_buffers.insert(ibc);
01095   }
01096 
01097   _prepared_index_buffers.clear();
01098   _enqueued_index_buffers.clear();
01099 
01100   // Also clear the cache of recently-unprepared index buffers.
01101   BufferCache::iterator bci;
01102   for (bci = _index_buffer_cache.begin(); 
01103        bci != _index_buffer_cache.end(); 
01104        ++bci) {
01105     BufferList &buffer_list = (*bci).second;
01106     nassertr(!buffer_list.empty(), num_index_buffers);
01107     BufferList::iterator li;
01108     for (li = buffer_list.begin(); li != buffer_list.end(); ++li) {
01109       IndexBufferContext *vbc = (IndexBufferContext *)(*li);
01110       _released_index_buffers.insert(vbc);
01111     }
01112   }
01113   _index_buffer_cache.clear();
01114   _index_buffer_cache_lru.clear();
01115   _index_buffer_cache_size = 0;
01116 
01117   return num_index_buffers;
01118 }
01119 
01120 ////////////////////////////////////////////////////////////////////
01121 //     Function: PreparedGraphicsObjects::get_num_queued_index_buffers
01122 //       Access: Public
01123 //  Description: Returns the number of index buffers that have been
01124 //               enqueued to be prepared on this GSG.
01125 ////////////////////////////////////////////////////////////////////
01126 int PreparedGraphicsObjects::
01127 get_num_queued_index_buffers() const {
01128   return _enqueued_index_buffers.size();
01129 }
01130 
01131 ////////////////////////////////////////////////////////////////////
01132 //     Function: PreparedGraphicsObjects::get_num_prepared_index_buffers
01133 //       Access: Public
01134 //  Description: Returns the number of index buffers that have
01135 //               already been prepared on this GSG.
01136 ////////////////////////////////////////////////////////////////////
01137 int PreparedGraphicsObjects::
01138 get_num_prepared_index_buffers() const {
01139   return _prepared_index_buffers.size();
01140 }
01141 
01142 ////////////////////////////////////////////////////////////////////
01143 //     Function: PreparedGraphicsObjects::prepare_index_buffer_now
01144 //       Access: Public
01145 //  Description: Immediately creates a new IndexBufferContext for the
01146 //               indicated data and returns it.  This assumes that
01147 //               the GraphicsStateGuardian is the currently active
01148 //               rendering context and that it is ready to accept new
01149 //               datas.  If this is not necessarily the case, you
01150 //               should use enqueue_index_buffer() instead.
01151 //
01152 //               Normally, this function is not called directly.  Call
01153 //               Data::prepare_now() instead.
01154 //
01155 //               The IndexBufferContext contains all of the pertinent
01156 //               information needed by the GSG to keep track of this
01157 //               one particular data, and will exist as long as the
01158 //               data is ready to be rendered.
01159 //
01160 //               When either the Data or the
01161 //               PreparedGraphicsObjects object destructs, the
01162 //               IndexBufferContext will be deleted.
01163 ////////////////////////////////////////////////////////////////////
01164 IndexBufferContext *PreparedGraphicsObjects::
01165 prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
01166   ReMutexHolder holder(_lock);
01167 
01168   // First, see if there might be a cached context of the appropriate
01169   // size.
01170   size_t data_size_bytes = data->get_data_size_bytes();
01171   GeomEnums::UsageHint usage_hint = data->get_usage_hint();
01172   IndexBufferContext *ibc = (IndexBufferContext *)
01173     get_cached_buffer(data_size_bytes, usage_hint,
01174                       _index_buffer_cache, _index_buffer_cache_lru,
01175                       _index_buffer_cache_size);
01176   if (ibc != (IndexBufferContext *)NULL) {
01177     ibc->_data = data;
01178 
01179   } else {
01180     // Ask the GSG to create a brand new IndexBufferContext.  There
01181     // might be several GSG's sharing the same set of datas; if so, it
01182     // doesn't matter which of them creates the context (since they're
01183     // all shared anyway).
01184     ibc = gsg->prepare_index_buffer(data);
01185   }
01186 
01187   if (ibc != (IndexBufferContext *)NULL) {
01188     bool prepared = _prepared_index_buffers.insert(ibc).second;
01189     nassertr(prepared, ibc);
01190   }
01191 
01192   return ibc;
01193 }
01194 
01195 ////////////////////////////////////////////////////////////////////
01196 //     Function: PreparedGraphicsObjects::begin_frame
01197 //       Access: Public
01198 //  Description: This is called by the GraphicsStateGuardian to
01199 //               indicate that it is about to begin processing of the
01200 //               frame.
01201 //
01202 //               Any texture contexts that were previously passed to
01203 //               release_texture() are actually passed to the GSG to
01204 //               be freed at this point; textures that were previously
01205 //               passed to prepare_texture are actually loaded.
01206 ////////////////////////////////////////////////////////////////////
01207 void PreparedGraphicsObjects::
01208 begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
01209   ReMutexHolder holder(_lock, current_thread);
01210 
01211   // First, release all the textures, geoms, and buffers awaiting
01212   // release.
01213   if (!_released_textures.empty()) {
01214     Textures::iterator tci;
01215     for (tci = _released_textures.begin();
01216          tci != _released_textures.end();
01217          ++tci) {
01218       TextureContext *tc = (*tci);
01219       gsg->release_texture(tc);
01220     }
01221   }
01222 
01223   _released_textures.clear();
01224 
01225   Geoms::iterator gci;
01226   for (gci = _released_geoms.begin();
01227        gci != _released_geoms.end();
01228        ++gci) {
01229     GeomContext *gc = (*gci);
01230     gsg->release_geom(gc);
01231   }
01232 
01233   _released_geoms.clear();
01234 
01235   Shaders::iterator sci;
01236   for (sci = _released_shaders.begin();
01237        sci != _released_shaders.end();
01238        ++sci) {
01239     ShaderContext *sc = (*sci);
01240     gsg->release_shader(sc);
01241   }
01242 
01243   _released_shaders.clear();
01244 
01245   Buffers::iterator vbci;
01246   for (vbci = _released_vertex_buffers.begin();
01247        vbci != _released_vertex_buffers.end();
01248        ++vbci) {
01249     VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
01250     gsg->release_vertex_buffer(vbc);
01251   }
01252 
01253   _released_vertex_buffers.clear();
01254 
01255   Buffers::iterator ibci;
01256   for (ibci = _released_index_buffers.begin();
01257        ibci != _released_index_buffers.end();
01258        ++ibci) {
01259     IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
01260     gsg->release_index_buffer(ibc);
01261   }
01262 
01263   _released_index_buffers.clear();
01264 
01265   // Reset the residency trackers.
01266   _texture_residency.begin_frame(current_thread);
01267   _vbuffer_residency.begin_frame(current_thread);
01268   _ibuffer_residency.begin_frame(current_thread);
01269 
01270   // Now prepare all the textures, geoms, and buffers awaiting
01271   // preparation.
01272   EnqueuedTextures::iterator qti;
01273   for (qti = _enqueued_textures.begin();
01274        qti != _enqueued_textures.end();
01275        ++qti) {
01276     Texture *tex = (*qti);
01277     for (int view = 0; view < tex->get_num_views(); ++view) {
01278       TextureContext *tc = tex->prepare_now(view, this, gsg);
01279       if (tc != (TextureContext *)NULL) {
01280         gsg->update_texture(tc, true);
01281       }
01282     }
01283   }
01284 
01285   _enqueued_textures.clear();
01286 
01287   EnqueuedGeoms::iterator qgi;
01288   for (qgi = _enqueued_geoms.begin();
01289        qgi != _enqueued_geoms.end();
01290        ++qgi) {
01291     Geom *geom = (*qgi);
01292     geom->prepare_now(this, gsg);
01293   }
01294 
01295   _enqueued_geoms.clear();
01296 
01297   EnqueuedShaders::iterator qsi;
01298   for (qsi = _enqueued_shaders.begin();
01299        qsi != _enqueued_shaders.end();
01300        ++qsi) {
01301     Shader *shader = (*qsi);
01302     shader->prepare_now(this, gsg);
01303   }
01304 
01305   _enqueued_shaders.clear();
01306 
01307   EnqueuedVertexBuffers::iterator qvbi;
01308   for (qvbi = _enqueued_vertex_buffers.begin();
01309        qvbi != _enqueued_vertex_buffers.end();
01310        ++qvbi) {
01311     GeomVertexArrayData *data = (*qvbi);
01312     data->prepare_now(this, gsg);
01313   }
01314 
01315   _enqueued_vertex_buffers.clear();
01316 
01317   EnqueuedIndexBuffers::iterator qibi;
01318   for (qibi = _enqueued_index_buffers.begin();
01319        qibi != _enqueued_index_buffers.end();
01320        ++qibi) {
01321     GeomPrimitive *data = (*qibi);
01322     data->prepare_now(this, gsg);
01323   }
01324 
01325   _enqueued_index_buffers.clear();
01326 }
01327 
01328 ////////////////////////////////////////////////////////////////////
01329 //     Function: PreparedGraphicsObjects::end_frame
01330 //       Access: Public
01331 //  Description: This is called by the GraphicsStateGuardian to
01332 //               indicate that it has finished processing of the
01333 //               frame.
01334 ////////////////////////////////////////////////////////////////////
01335 void PreparedGraphicsObjects::
01336 end_frame(Thread *current_thread) {
01337   ReMutexHolder holder(_lock, current_thread);
01338 
01339   _texture_residency.end_frame(current_thread);
01340   _vbuffer_residency.end_frame(current_thread);
01341   _ibuffer_residency.end_frame(current_thread);
01342 }
01343 
01344 ////////////////////////////////////////////////////////////////////
01345 //     Function: PreparedGraphicsObjects::init_name
01346 //       Access: Private, Static
01347 //  Description: Returns a new, unique name for a newly-constructed
01348 //               object.
01349 ////////////////////////////////////////////////////////////////////
01350 string PreparedGraphicsObjects::
01351 init_name() {
01352   ++_name_index;
01353   ostringstream strm;
01354   strm << "context" << _name_index;
01355   return strm.str();
01356 }
01357 
01358 ////////////////////////////////////////////////////////////////////
01359 //     Function: PreparedGraphicsObjects::cache_unprepared_buffer
01360 //       Access: Private
01361 //  Description: Called when a vertex or index buffer is no longer
01362 //               officially "prepared".  However, we still have the
01363 //               context on the graphics card, and we might be able to
01364 //               reuse that context if we're about to re-prepare a
01365 //               different buffer, especially one exactly the same
01366 //               size.  So instead of immediately enqueuing the vertex
01367 //               buffer for release, we cache it.
01368 ////////////////////////////////////////////////////////////////////
01369 void PreparedGraphicsObjects::
01370 cache_unprepared_buffer(BufferContext *buffer, size_t data_size_bytes,
01371                         GeomEnums::UsageHint usage_hint,
01372                         PreparedGraphicsObjects::BufferCache &buffer_cache,
01373                         PreparedGraphicsObjects::BufferCacheLRU &buffer_cache_lru,
01374                         size_t &buffer_cache_size, 
01375                         int released_buffer_cache_size,
01376                         PreparedGraphicsObjects::Buffers &released_buffers) {
01377   BufferCacheKey key;
01378   key._data_size_bytes = data_size_bytes;
01379   key._usage_hint = usage_hint;
01380 
01381   buffer_cache[key].push_back(buffer);
01382   buffer_cache_size += data_size_bytes;
01383 
01384   // Move the key to the head of the LRU.
01385   BufferCacheLRU::iterator li =
01386     find(buffer_cache_lru.begin(), buffer_cache_lru.end(), key);
01387   if (li != buffer_cache_lru.end()) {
01388     buffer_cache_lru.erase(li);
01389   }
01390   buffer_cache_lru.insert(buffer_cache_lru.begin(), key);
01391 
01392   // Now release not-recently-used buffers until we fit within the
01393   // constrained size.
01394   while ((int)buffer_cache_size > released_buffer_cache_size) {
01395     nassertv(!buffer_cache_lru.empty());
01396     const BufferCacheKey &release_key = *buffer_cache_lru.rbegin();
01397     BufferList &buffer_list = buffer_cache[release_key];
01398     while (!buffer_list.empty() && 
01399            (int)buffer_cache_size > released_buffer_cache_size) {
01400       BufferContext *released_buffer = buffer_list.back();
01401       buffer_list.pop_back();
01402       released_buffers.insert(released_buffer);
01403       buffer_cache_size -= release_key._data_size_bytes;
01404     }
01405 
01406     if (buffer_list.empty()) {
01407       buffer_cache.erase(release_key);
01408       buffer_cache_lru.pop_back();
01409     }
01410   }
01411 }
01412 
01413 ////////////////////////////////////////////////////////////////////
01414 //     Function: PreparedGraphicsObjects::get_cached_buffer
01415 //       Access: Private
01416 //  Description: Returns a previously-cached buffer from the cache, or
01417 //               NULL if there is no such buffer.
01418 ////////////////////////////////////////////////////////////////////
01419 BufferContext *PreparedGraphicsObjects::
01420 get_cached_buffer(size_t data_size_bytes, GeomEnums::UsageHint usage_hint,
01421                   PreparedGraphicsObjects::BufferCache &buffer_cache,
01422                   PreparedGraphicsObjects::BufferCacheLRU &buffer_cache_lru,
01423                   size_t &buffer_cache_size) {
01424   BufferCacheKey key;
01425   key._data_size_bytes = data_size_bytes;
01426   key._usage_hint = usage_hint;
01427 
01428   BufferCache::iterator bci = buffer_cache.find(key);
01429   if (bci == buffer_cache.end()) {
01430     return NULL;
01431   }
01432 
01433   BufferList &buffer_list = (*bci).second;
01434   nassertr(!buffer_list.empty(), NULL);
01435 
01436   BufferContext *buffer = buffer_list.back();
01437   buffer_list.pop_back();
01438   if (buffer_list.empty()) {
01439     buffer_cache.erase(bci);
01440     BufferCacheLRU::iterator li =
01441       find(buffer_cache_lru.begin(), buffer_cache_lru.end(), key);
01442     if (li != buffer_cache_lru.end()) {
01443       buffer_cache_lru.erase(li);
01444     }
01445   }
01446 
01447   buffer_cache_size -= data_size_bytes;
01448   return buffer;
01449 }
 All Classes Functions Variables Enumerations