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 }