Panda3D
 All Classes Functions Variables Enumerations
preparedGraphicsObjects.cxx
1 // Filename: preparedGraphicsObjects.cxx
2 // Created by: drose (19Feb04)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "preparedGraphicsObjects.h"
16 #include "textureContext.h"
17 #include "vertexBufferContext.h"
18 #include "indexBufferContext.h"
19 #include "texture.h"
20 #include "geom.h"
21 #include "geomVertexArrayData.h"
22 #include "geomPrimitive.h"
23 #include "samplerContext.h"
24 #include "shader.h"
25 #include "reMutexHolder.h"
26 #include "geomContext.h"
27 #include "shaderContext.h"
28 #include "config_gobj.h"
29 #include "throw_event.h"
30 
31 int PreparedGraphicsObjects::_name_index = 0;
32 
33 ////////////////////////////////////////////////////////////////////
34 // Function: PreparedGraphicsObjects::Constructor
35 // Access: Public
36 // Description:
37 ////////////////////////////////////////////////////////////////////
38 PreparedGraphicsObjects::
39 PreparedGraphicsObjects() :
40  _lock("PreparedGraphicsObjects::_lock"),
41  _name(init_name()),
42  _vertex_buffer_cache_size(0),
43  _index_buffer_cache_size(0),
44  _texture_residency(_name, "texture"),
45  _vbuffer_residency(_name, "vbuffer"),
46  _ibuffer_residency(_name, "ibuffer"),
47  _graphics_memory_lru("graphics_memory_lru", graphics_memory_limit),
48  _sampler_object_lru("sampler_object_lru", sampler_object_limit)
49 {
50  // GLGSG will turn this flag on. This is a temporary hack to
51  // disable this feature for DX8/DX9 for now, until we work out the
52  // fine points of updating the fvf properly.
53  _support_released_buffer_cache = false;
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: PreparedGraphicsObjects::Destructor
58 // Access: Public
59 // Description:
60 ////////////////////////////////////////////////////////////////////
61 PreparedGraphicsObjects::
62 ~PreparedGraphicsObjects() {
63  // There may be objects that are still prepared when we destruct.
64  // If this is so, then all of the GSG's that own them have already
65  // destructed, so we can assume their resources were internally
66  // cleaned up. Quietly erase these remaining objects.
67  ReMutexHolder holder(_lock);
68 
70  Textures::iterator tci;
71  for (tci = _released_textures.begin();
72  tci != _released_textures.end();
73  ++tci) {
74  TextureContext *tc = (*tci);
75  tc->set_owning_chain(NULL);
76  }
77  // Is this a leak? Should we delete these TextureContexts?
78  _released_textures.clear();
79 
81  _released_samplers.clear();
82 
84  _released_geoms.clear();
85 
87  _released_shaders.clear();
88 
90  Buffers::iterator vbci;
91  for (vbci = _released_vertex_buffers.begin();
92  vbci != _released_vertex_buffers.end();
93  ++vbci) {
94  VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
95  vbc->set_owning_chain(NULL);
96  }
97  _released_vertex_buffers.clear();
98 
100  Buffers::iterator ibci;
101  for (ibci = _released_index_buffers.begin();
102  ibci != _released_index_buffers.end();
103  ++ibci) {
104  IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
105  ibc->set_owning_chain(NULL);
106  }
107  _released_index_buffers.clear();
108 }
109 
110 ////////////////////////////////////////////////////////////////////
111 // Function: PreparedGraphicsObjects::set_graphics_memory_limit
112 // Access: Public
113 // Description: Sets an artificial cap on graphics memory that
114 // will be imposed on this GSG.
115 //
116 // This limits the total amount of graphics memory,
117 // including texture memory and vertex buffer memory,
118 // that will be consumed by the GSG, regardless of
119 // whether the hardware claims to provide more graphics
120 // memory than this. It is useful to put a ceiling on
121 // graphics memory consumed, since some drivers seem to
122 // allow the application to consume more memory than the
123 // hardware can realistically support.
124 ////////////////////////////////////////////////////////////////////
127  if (limit != _graphics_memory_lru.get_max_size()) {
128  _graphics_memory_lru.set_max_size(limit);
129 
130  // We throw an event here so global objects (particularly the
131  // TexMemWatcher) can automatically respond to this change.
132  throw_event("graphics_memory_limit_changed");
133  }
134 }
135 
136 ////////////////////////////////////////////////////////////////////
137 // Function: PreparedGraphicsObjects::show_graphics_memory_lru
138 // Access: Public
139 // Description: Writes to the indicated ostream a report of how the
140 // various textures and vertex buffers are allocated in
141 // the LRU.
142 ////////////////////////////////////////////////////////////////////
144 show_graphics_memory_lru(ostream &out) const {
145  _graphics_memory_lru.write(out, 0);
146 }
147 
148 ////////////////////////////////////////////////////////////////////
149 // Function: PreparedGraphicsObjects::show_residency_trackers
150 // Access: Public
151 // Description: Writes to the indicated ostream a report of how the
152 // various textures and vertex buffers are allocated in
153 // the LRU.
154 ////////////////////////////////////////////////////////////////////
156 show_residency_trackers(ostream &out) const {
157  out << "Textures:\n";
158  _texture_residency.write(out, 2);
159 
160  out << "\nVertex buffers:\n";
161  _vbuffer_residency.write(out, 2);
162 
163  out << "\nIndex buffers:\n";
164  _ibuffer_residency.write(out, 2);
165 }
166 
167 ////////////////////////////////////////////////////////////////////
168 // Function: PreparedGraphicsObjects::enqueue_texture
169 // Access: Public
170 // Description: Indicates that a texture would like to be put on the
171 // list to be prepared when the GSG is next ready to
172 // do this (presumably at the next frame).
173 ////////////////////////////////////////////////////////////////////
176  ReMutexHolder holder(_lock);
177 
178  _enqueued_textures.insert(tex);
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: PreparedGraphicsObjects::is_texture_queued
183 // Access: Public
184 // Description: Returns true if the texture has been queued on this
185 // GSG, false otherwise.
186 ////////////////////////////////////////////////////////////////////
188 is_texture_queued(const Texture *tex) const {
189  ReMutexHolder holder(_lock);
190 
191  EnqueuedTextures::const_iterator qi = _enqueued_textures.find((Texture *)tex);
192  return (qi != _enqueued_textures.end());
193 }
194 
195 ////////////////////////////////////////////////////////////////////
196 // Function: PreparedGraphicsObjects::dequeue_texture
197 // Access: Public
198 // Description: Removes a texture from the queued list of textures to
199 // be prepared. Normally it is not necessary to call
200 // this, unless you change your mind about preparing it
201 // at the last minute, since the texture will
202 // automatically be dequeued and prepared at the next
203 // frame.
204 //
205 // The return value is true if the texture is
206 // successfully dequeued, false if it had not been
207 // queued.
208 ////////////////////////////////////////////////////////////////////
211  ReMutexHolder holder(_lock);
212 
213  EnqueuedTextures::iterator qi = _enqueued_textures.find(tex);
214  if (qi != _enqueued_textures.end()) {
215  _enqueued_textures.erase(qi);
216  return true;
217  }
218  return false;
219 }
220 
221 ////////////////////////////////////////////////////////////////////
222 // Function: PreparedGraphicsObjects::is_texture_prepared
223 // Access: Public
224 // Description: Returns true if the texture has been prepared on
225 // this GSG, false otherwise.
226 ////////////////////////////////////////////////////////////////////
228 is_texture_prepared(const Texture *tex) const {
229  return tex->is_prepared((PreparedGraphicsObjects *)this);
230 }
231 
232 ////////////////////////////////////////////////////////////////////
233 // Function: PreparedGraphicsObjects::release_texture
234 // Access: Public
235 // Description: Indicates that a texture context, created by a
236 // previous call to prepare_texture(), is no longer
237 // needed. The driver resources will not be freed until
238 // some GSG calls update(), indicating it is at a
239 // stage where it is ready to release textures--this
240 // prevents conflicts from threading or multiple GSG's
241 // sharing textures (we have no way of knowing which
242 // graphics context is currently active, or what state
243 // it's in, at the time release_texture is called).
244 ////////////////////////////////////////////////////////////////////
247  ReMutexHolder holder(_lock);
248 
249  tc->_texture->clear_prepared(tc->get_view(), this);
250 
251  // We have to set the Texture pointer to NULL at this point, since
252  // the Texture itself might destruct at any time after it has been
253  // released.
254  tc->_texture = (Texture *)NULL;
255 
256  bool removed = (_prepared_textures.erase(tc) != 0);
257  nassertv(removed);
258 
259  _released_textures.insert(tc);
260 }
261 
262 ////////////////////////////////////////////////////////////////////
263 // Function: PreparedGraphicsObjects::release_texture
264 // Access: Public
265 // Description: Releases a texture if it has already been prepared,
266 // or removes it from the preparation queue.
267 ////////////////////////////////////////////////////////////////////
270  tex->release(this);
271 }
272 
273 ////////////////////////////////////////////////////////////////////
274 // Function: PreparedGraphicsObjects::release_all_textures
275 // Access: Public
276 // Description: Releases all textures at once. This will force them
277 // to be reloaded into texture memory for all GSG's that
278 // share this object. Returns the number of textures
279 // released.
280 ////////////////////////////////////////////////////////////////////
283  ReMutexHolder holder(_lock);
284 
285  int num_textures = (int)_prepared_textures.size() + (int)_enqueued_textures.size();
286 
287  Textures::iterator tci;
288  for (tci = _prepared_textures.begin();
289  tci != _prepared_textures.end();
290  ++tci) {
291  TextureContext *tc = (*tci);
292  tc->_texture->clear_prepared(tc->get_view(), this);
293  tc->_texture = (Texture *)NULL;
294 
295  _released_textures.insert(tc);
296  }
297 
298  _prepared_textures.clear();
299  _enqueued_textures.clear();
300 
301  return num_textures;
302 }
303 
304 ////////////////////////////////////////////////////////////////////
305 // Function: PreparedGraphicsObjects::get_num_queued_textures
306 // Access: Public
307 // Description: Returns the number of textures that have been
308 // enqueued to be prepared on this GSG.
309 ////////////////////////////////////////////////////////////////////
312  return _enqueued_textures.size();
313 }
314 
315 ////////////////////////////////////////////////////////////////////
316 // Function: PreparedGraphicsObjects::get_num_prepared_textures
317 // Access: Public
318 // Description: Returns the number of textures that have already been
319 // prepared on this GSG.
320 ////////////////////////////////////////////////////////////////////
323  return _prepared_textures.size();
324 }
325 
326 ////////////////////////////////////////////////////////////////////
327 // Function: PreparedGraphicsObjects::prepare_texture_now
328 // Access: Public
329 // Description: Immediately creates a new TextureContext for the
330 // indicated texture and returns it. This assumes that
331 // the GraphicsStateGuardian is the currently active
332 // rendering context and that it is ready to accept new
333 // textures. If this is not necessarily the case, you
334 // should use enqueue_texture() instead.
335 //
336 // Normally, this function is not called directly. Call
337 // Texture::prepare_now() instead.
338 //
339 // The TextureContext contains all of the pertinent
340 // information needed by the GSG to keep track of this
341 // one particular texture, and will exist as long as the
342 // texture is ready to be rendered.
343 //
344 // When either the Texture or the
345 // PreparedGraphicsObjects object destructs, the
346 // TextureContext will be deleted.
347 ////////////////////////////////////////////////////////////////////
350  ReMutexHolder holder(_lock);
351 
352  // Ask the GSG to create a brand new TextureContext. There might
353  // be several GSG's sharing the same set of textures; if so, it
354  // doesn't matter which of them creates the context (since they're
355  // all shared anyway).
356  TextureContext *tc = gsg->prepare_texture(tex, view);
357 
358  if (tc != (TextureContext *)NULL) {
359  bool prepared = _prepared_textures.insert(tc).second;
360  nassertr(prepared, tc);
361  }
362 
363  return tc;
364 }
365 
366 ////////////////////////////////////////////////////////////////////
367 // Function: PreparedGraphicsObjects::enqueue_sampler
368 // Access: Public
369 // Description: Indicates that a sampler would like to be put on the
370 // list to be prepared when the GSG is next ready to
371 // do this (presumably at the next frame).
372 ////////////////////////////////////////////////////////////////////
374 enqueue_sampler(const SamplerState &sampler) {
375  ReMutexHolder holder(_lock);
376 
377  _enqueued_samplers.insert(sampler);
378 }
379 
380 ////////////////////////////////////////////////////////////////////
381 // Function: PreparedGraphicsObjects::is_sampler_queued
382 // Access: Public
383 // Description: Returns true if the sampler has been queued on this
384 // GSG, false otherwise.
385 ////////////////////////////////////////////////////////////////////
387 is_sampler_queued(const SamplerState &sampler) const {
388  ReMutexHolder holder(_lock);
389 
390  EnqueuedSamplers::const_iterator qi = _enqueued_samplers.find(sampler);
391  return (qi != _enqueued_samplers.end());
392 }
393 
394 ////////////////////////////////////////////////////////////////////
395 // Function: PreparedGraphicsObjects::dequeue_sampler
396 // Access: Public
397 // Description: Removes a sampler from the queued list of samplers to
398 // be prepared. Normally it is not necessary to call
399 // this, unless you change your mind about preparing it
400 // at the last minute, since the sampler will
401 // automatically be dequeued and prepared at the next
402 // frame.
403 //
404 // The return value is true if the sampler is
405 // successfully dequeued, false if it had not been
406 // queued.
407 ////////////////////////////////////////////////////////////////////
409 dequeue_sampler(const SamplerState &sampler) {
410  ReMutexHolder holder(_lock);
411 
412  EnqueuedSamplers::iterator qi = _enqueued_samplers.find(sampler);
413  if (qi != _enqueued_samplers.end()) {
414  _enqueued_samplers.erase(qi);
415  return true;
416  }
417  return false;
418 }
419 
420 ////////////////////////////////////////////////////////////////////
421 // Function: PreparedGraphicsObjects::is_sampler_prepared
422 // Access: Public
423 // Description: Returns true if the sampler has been prepared on
424 // this GSG, false otherwise.
425 ////////////////////////////////////////////////////////////////////
427 is_sampler_prepared(const SamplerState &sampler) const {
428  ReMutexHolder holder(_lock);
429 
430  PreparedSamplers::const_iterator it = _prepared_samplers.find(sampler);
431  return (it != _prepared_samplers.end());
432 }
433 
434 ////////////////////////////////////////////////////////////////////
435 // Function: PreparedGraphicsObjects::release_sampler
436 // Access: Public
437 // Description: Indicates that a sampler context, created by a
438 // previous call to prepare_sampler(), is no longer
439 // needed. The driver resources will not be freed until
440 // some GSG calls update(), indicating it is at a
441 // stage where it is ready to release samplers.
442 ////////////////////////////////////////////////////////////////////
445  ReMutexHolder holder(_lock);
446 
447  _released_samplers.insert(sc);
448 }
449 
450 ////////////////////////////////////////////////////////////////////
451 // Function: PreparedGraphicsObjects::release_sampler
452 // Access: Public
453 // Description: Releases a sampler if it has already been prepared,
454 // or removes it from the preparation queue.
455 ////////////////////////////////////////////////////////////////////
457 release_sampler(const SamplerState &sampler) {
458  ReMutexHolder holder(_lock);
459 
460  PreparedSamplers::iterator it = _prepared_samplers.find(sampler);
461  if (it != _prepared_samplers.end()) {
462  _released_samplers.insert(it->second);
463  _prepared_samplers.erase(it);
464  }
465 
466  _enqueued_samplers.erase(sampler);
467 }
468 
469 ////////////////////////////////////////////////////////////////////
470 // Function: PreparedGraphicsObjects::release_all_samplers
471 // Access: Public
472 // Description: Releases all samplers at once. This will force them
473 // to be reloaded for all GSG's that share this object.
474 // Returns the number of samplers released.
475 ////////////////////////////////////////////////////////////////////
478  ReMutexHolder holder(_lock);
479 
480  int num_samplers = (int)_prepared_samplers.size() + (int)_enqueued_samplers.size();
481 
482  PreparedSamplers::iterator sci;
483  for (sci = _prepared_samplers.begin();
484  sci != _prepared_samplers.end();
485  ++sci) {
486  _released_samplers.insert(sci->second);
487  }
488 
489  _prepared_samplers.clear();
490  _enqueued_samplers.clear();
491 
492  return num_samplers;
493 }
494 
495 ////////////////////////////////////////////////////////////////////
496 // Function: PreparedGraphicsObjects::get_num_queued_samplers
497 // Access: Public
498 // Description: Returns the number of samplers that have been
499 // enqueued to be prepared on this GSG.
500 ////////////////////////////////////////////////////////////////////
503  return _enqueued_samplers.size();
504 }
505 
506 ////////////////////////////////////////////////////////////////////
507 // Function: PreparedGraphicsObjects::get_num_prepared_samplers
508 // Access: Public
509 // Description: Returns the number of samplers that have already been
510 // prepared on this GSG.
511 ////////////////////////////////////////////////////////////////////
514  return _prepared_samplers.size();
515 }
516 
517 ////////////////////////////////////////////////////////////////////
518 // Function: PreparedGraphicsObjects::prepare_sampler_now
519 // Access: Public
520 // Description: Immediately creates a new SamplerContext for the
521 // indicated sampler and returns it. This assumes that
522 // the GraphicsStateGuardian is the currently active
523 // rendering context and that it is ready to accept new
524 // samplers. If this is not necessarily the case, you
525 // should use enqueue_sampler() instead.
526 //
527 // Normally, this function is not called directly.
528 // Call Sampler::prepare_now() instead.
529 //
530 // The SamplerContext contains all of the pertinent
531 // information needed by the GSG to keep track of this
532 // one particular sampler, and will exist as long as the
533 // sampler is ready to be rendered.
534 //
535 // When either the Sampler or the
536 // PreparedGraphicsObjects object destructs, the
537 // SamplerContext will be deleted.
538 ////////////////////////////////////////////////////////////////////
541  ReMutexHolder holder(_lock);
542 
543  PreparedSamplers::const_iterator it = _prepared_samplers.find(sampler);
544  if (it != _prepared_samplers.end()) {
545  return it->second;
546  }
547 
548  // Ask the GSG to create a brand new SamplerContext.
549  SamplerContext *sc = gsg->prepare_sampler(sampler);
550 
551  if (sc != (SamplerContext *)NULL) {
552  _prepared_samplers[sampler] = sc;
553  }
554 
555  return sc;
556 }
557 
558 ////////////////////////////////////////////////////////////////////
559 // Function: PreparedGraphicsObjects::enqueue_geom
560 // Access: Public
561 // Description: Indicates that a geom would like to be put on the
562 // list to be prepared when the GSG is next ready to
563 // do this (presumably at the next frame).
564 ////////////////////////////////////////////////////////////////////
567  ReMutexHolder holder(_lock);
568 
569  _enqueued_geoms.insert(geom);
570 }
571 
572 ////////////////////////////////////////////////////////////////////
573 // Function: PreparedGraphicsObjects::is_geom_queued
574 // Access: Public
575 // Description: Returns true if the geom has been queued on this
576 // GSG, false otherwise.
577 ////////////////////////////////////////////////////////////////////
579 is_geom_queued(const Geom *geom) const {
580  ReMutexHolder holder(_lock);
581 
582  EnqueuedGeoms::const_iterator qi = _enqueued_geoms.find((Geom *)geom);
583  return (qi != _enqueued_geoms.end());
584 }
585 
586 ////////////////////////////////////////////////////////////////////
587 // Function: PreparedGraphicsObjects::dequeue_geom
588 // Access: Public
589 // Description: Removes a geom from the queued list of geoms to
590 // be prepared. Normally it is not necessary to call
591 // this, unless you change your mind about preparing it
592 // at the last minute, since the geom will
593 // automatically be dequeued and prepared at the next
594 // frame.
595 //
596 // The return value is true if the geom is
597 // successfully dequeued, false if it had not been
598 // queued.
599 ////////////////////////////////////////////////////////////////////
602  ReMutexHolder holder(_lock);
603 
604  EnqueuedGeoms::iterator qi = _enqueued_geoms.find(geom);
605  if (qi != _enqueued_geoms.end()) {
606  _enqueued_geoms.erase(qi);
607  return true;
608  }
609  return false;
610 }
611 
612 ////////////////////////////////////////////////////////////////////
613 // Function: PreparedGraphicsObjects::is_geom_prepared
614 // Access: Public
615 // Description: Returns true if the vertex buffer has been prepared on
616 // this GSG, false otherwise.
617 ////////////////////////////////////////////////////////////////////
619 is_geom_prepared(const Geom *geom) const {
620  return geom->is_prepared((PreparedGraphicsObjects *)this);
621 }
622 
623 ////////////////////////////////////////////////////////////////////
624 // Function: PreparedGraphicsObjects::release_geom
625 // Access: Public
626 // Description: Indicates that a geom context, created by a
627 // previous call to prepare_geom(), is no longer
628 // needed. The driver resources will not be freed until
629 // some GSG calls update(), indicating it is at a
630 // stage where it is ready to release geoms--this
631 // prevents conflicts from threading or multiple GSG's
632 // sharing geoms (we have no way of knowing which
633 // graphics context is currently active, or what state
634 // it's in, at the time release_geom is called).
635 ////////////////////////////////////////////////////////////////////
638  ReMutexHolder holder(_lock);
639 
640  gc->_geom->clear_prepared(this);
641 
642  // We have to set the Geom pointer to NULL at this point, since
643  // the Geom itself might destruct at any time after it has been
644  // released.
645  gc->_geom = (Geom *)NULL;
646 
647  bool removed = (_prepared_geoms.erase(gc) != 0);
648  nassertv(removed);
649 
650  _released_geoms.insert(gc);
651 }
652 
653 ////////////////////////////////////////////////////////////////////
654 // Function: PreparedGraphicsObjects::release_all_geoms
655 // Access: Public
656 // Description: Releases all geoms at once. This will force them
657 // to be reloaded into geom memory for all GSG's that
658 // share this object. Returns the number of geoms
659 // released.
660 ////////////////////////////////////////////////////////////////////
663  ReMutexHolder holder(_lock);
664 
665  int num_geoms = (int)_prepared_geoms.size() + (int)_enqueued_geoms.size();
666 
667  Geoms::iterator gci;
668  for (gci = _prepared_geoms.begin();
669  gci != _prepared_geoms.end();
670  ++gci) {
671  GeomContext *gc = (*gci);
672  gc->_geom->clear_prepared(this);
673  gc->_geom = (Geom *)NULL;
674 
675  _released_geoms.insert(gc);
676  }
677 
678  _prepared_geoms.clear();
679  _enqueued_geoms.clear();
680 
681  return num_geoms;
682 }
683 
684 ////////////////////////////////////////////////////////////////////
685 // Function: PreparedGraphicsObjects::get_num_queued_geoms
686 // Access: Public
687 // Description: Returns the number of geoms that have been
688 // enqueued to be prepared on this GSG.
689 ////////////////////////////////////////////////////////////////////
692  return _enqueued_geoms.size();
693 }
694 
695 ////////////////////////////////////////////////////////////////////
696 // Function: PreparedGraphicsObjects::get_num_prepared_geoms
697 // Access: Public
698 // Description: Returns the number of geoms that have already been
699 // prepared on this GSG.
700 ////////////////////////////////////////////////////////////////////
703  return _prepared_geoms.size();
704 }
705 
706 ////////////////////////////////////////////////////////////////////
707 // Function: PreparedGraphicsObjects::prepare_geom_now
708 // Access: Public
709 // Description: Immediately creates a new GeomContext for the
710 // indicated geom and returns it. This assumes that
711 // the GraphicsStateGuardian is the currently active
712 // rendering context and that it is ready to accept new
713 // geoms. If this is not necessarily the case, you
714 // should use enqueue_geom() instead.
715 //
716 // Normally, this function is not called directly. Call
717 // Geom::prepare_now() instead.
718 //
719 // The GeomContext contains all of the pertinent
720 // information needed by the GSG to keep track of this
721 // one particular geom, and will exist as long as the
722 // geom is ready to be rendered.
723 //
724 // When either the Geom or the
725 // PreparedGraphicsObjects object destructs, the
726 // GeomContext will be deleted.
727 ////////////////////////////////////////////////////////////////////
730  ReMutexHolder holder(_lock);
731 
732  // Ask the GSG to create a brand new GeomContext. There might
733  // be several GSG's sharing the same set of geoms; if so, it
734  // doesn't matter which of them creates the context (since they're
735  // all shared anyway).
736  GeomContext *gc = gsg->prepare_geom(geom);
737 
738  if (gc != (GeomContext *)NULL) {
739  bool prepared = _prepared_geoms.insert(gc).second;
740  nassertr(prepared, gc);
741  }
742 
743  return gc;
744 }
745 
746 ////////////////////////////////////////////////////////////////////
747 // Function: PreparedGraphicsObjects::enqueue_shader
748 // Access: Public
749 // Description: Indicates that a shader would like to be put on the
750 // list to be prepared when the GSG is next ready to
751 // do this (presumably at the next frame).
752 ////////////////////////////////////////////////////////////////////
755  ReMutexHolder holder(_lock);
756 
757  _enqueued_shaders.insert(se);
758 }
759 
760 ////////////////////////////////////////////////////////////////////
761 // Function: PreparedGraphicsObjects::is_shader_queued
762 // Access: Public
763 // Description: Returns true if the shader has been queued on this
764 // GSG, false otherwise.
765 ////////////////////////////////////////////////////////////////////
767 is_shader_queued(const Shader *shader) const {
768  ReMutexHolder holder(_lock);
769 
770  EnqueuedShaders::const_iterator qi = _enqueued_shaders.find((Shader *)shader);
771  return (qi != _enqueued_shaders.end());
772 }
773 
774 ////////////////////////////////////////////////////////////////////
775 // Function: PreparedGraphicsObjects::dequeue_shader
776 // Access: Public
777 // Description: Removes a shader from the queued list of shaders to
778 // be prepared. Normally it is not necessary to call
779 // this, unless you change your mind about preparing it
780 // at the last minute, since the shader will
781 // automatically be dequeued and prepared at the next
782 // frame.
783 //
784 // The return value is true if the shader is
785 // successfully dequeued, false if it had not been
786 // queued.
787 ////////////////////////////////////////////////////////////////////
790  ReMutexHolder holder(_lock);
791 
792  EnqueuedShaders::iterator qi = _enqueued_shaders.find(se);
793  if (qi != _enqueued_shaders.end()) {
794  _enqueued_shaders.erase(qi);
795  return true;
796  }
797  return false;
798 }
799 
800 ////////////////////////////////////////////////////////////////////
801 // Function: PreparedGraphicsObjects::is_shader_prepared
802 // Access: Public
803 // Description: Returns true if the shader has been prepared on
804 // this GSG, false otherwise.
805 ////////////////////////////////////////////////////////////////////
807 is_shader_prepared(const Shader *shader) const {
808  return shader->is_prepared((PreparedGraphicsObjects *)this);
809 }
810 
811 ////////////////////////////////////////////////////////////////////
812 // Function: PreparedGraphicsObjects::release_shader
813 // Access: Public
814 // Description: Indicates that a shader context, created by a
815 // previous call to prepare_shader(), is no longer
816 // needed. The driver resources will not be freed until
817 // some GSG calls update(), indicating it is at a
818 // stage where it is ready to release shaders--this
819 // prevents conflicts from threading or multiple GSG's
820 // sharing shaders (we have no way of knowing which
821 // graphics context is currently active, or what state
822 // it's in, at the time release_shader is called).
823 ////////////////////////////////////////////////////////////////////
826  ReMutexHolder holder(_lock);
827 
828  sc->_shader->clear_prepared(this);
829 
830  // We have to set the Shader pointer to NULL at this point, since
831  // the Shader itself might destruct at any time after it has been
832  // released.
833  sc->_shader = (Shader *)NULL;
834 
835  bool removed = (_prepared_shaders.erase(sc) != 0);
836  nassertv(removed);
837 
838  _released_shaders.insert(sc);
839 }
840 
841 ////////////////////////////////////////////////////////////////////
842 // Function: PreparedGraphicsObjects::release_all_shaders
843 // Access: Public
844 // Description: Releases all shaders at once. This will force them
845 // to be reloaded into shader memory for all GSG's that
846 // share this object. Returns the number of shaders
847 // released.
848 ////////////////////////////////////////////////////////////////////
851  ReMutexHolder holder(_lock);
852 
853  int num_shaders = (int)_prepared_shaders.size() + (int)_enqueued_shaders.size();
854 
855  Shaders::iterator sci;
856  for (sci = _prepared_shaders.begin();
857  sci != _prepared_shaders.end();
858  ++sci) {
859  ShaderContext *sc = (*sci);
860  sc->_shader->clear_prepared(this);
861  sc->_shader = (Shader *)NULL;
862 
863  _released_shaders.insert(sc);
864  }
865 
866  _prepared_shaders.clear();
867  _enqueued_shaders.clear();
868 
869  return num_shaders;
870 }
871 
872 ////////////////////////////////////////////////////////////////////
873 // Function: PreparedGraphicsObjects::get_num_queued_shaders
874 // Access: Public
875 // Description: Returns the number of shaders that have been
876 // enqueued to be prepared on this GSG.
877 ////////////////////////////////////////////////////////////////////
880  return _enqueued_shaders.size();
881 }
882 
883 ////////////////////////////////////////////////////////////////////
884 // Function: PreparedGraphicsObjects::get_num_prepared_shaders
885 // Access: Public
886 // Description: Returns the number of shaders that have already been
887 // prepared on this GSG.
888 ////////////////////////////////////////////////////////////////////
891  return _prepared_shaders.size();
892 }
893 
894 ////////////////////////////////////////////////////////////////////
895 // Function: PreparedGraphicsObjects::prepare_shader_now
896 // Access: Public
897 // Description: Immediately creates a new ShaderContext for the
898 // indicated shader and returns it. This assumes that
899 // the GraphicsStateGuardian is the currently active
900 // rendering context and that it is ready to accept new
901 // shaders. If this is not necessarily the case, you
902 // should use enqueue_shader() instead.
903 //
904 // Normally, this function is not called directly. Call
905 // Shader::prepare_now() instead.
906 //
907 // The ShaderContext contains all of the pertinent
908 // information needed by the GSG to keep track of this
909 // one particular shader, and will exist as long as the
910 // shader is ready to be rendered.
911 //
912 // When either the Shader or the
913 // PreparedGraphicsObjects object destructs, the
914 // ShaderContext will be deleted.
915 ////////////////////////////////////////////////////////////////////
918  ReMutexHolder holder(_lock);
919 
920  // Ask the GSG to create a brand new ShaderContext. There might
921  // be several GSG's sharing the same set of shaders; if so, it
922  // doesn't matter which of them creates the context (since they're
923  // all shared anyway).
924  ShaderContext *sc = gsg->prepare_shader(se);
925 
926  if (sc != (ShaderContext *)NULL) {
927  bool prepared = _prepared_shaders.insert(sc).second;
928  nassertr(prepared, sc);
929  }
930 
931  return sc;
932 }
933 
934 ////////////////////////////////////////////////////////////////////
935 // Function: PreparedGraphicsObjects::enqueue_vertex_buffer
936 // Access: Public
937 // Description: Indicates that a buffer would like to be put on the
938 // list to be prepared when the GSG is next ready to
939 // do this (presumably at the next frame).
940 ////////////////////////////////////////////////////////////////////
943  ReMutexHolder holder(_lock);
944 
945  _enqueued_vertex_buffers.insert(data);
946 }
947 
948 ////////////////////////////////////////////////////////////////////
949 // Function: PreparedGraphicsObjects::is_vertex_buffer_queued
950 // Access: Public
951 // Description: Returns true if the vertex buffer has been queued on
952 // this GSG, false otherwise.
953 ////////////////////////////////////////////////////////////////////
956  ReMutexHolder holder(_lock);
957 
958  EnqueuedVertexBuffers::const_iterator qi = _enqueued_vertex_buffers.find((GeomVertexArrayData *)data);
959  return (qi != _enqueued_vertex_buffers.end());
960 }
961 
962 ////////////////////////////////////////////////////////////////////
963 // Function: PreparedGraphicsObjects::dequeue_vertex_buffer
964 // Access: Public
965 // Description: Removes a buffer from the queued list of data
966 // arrays to be prepared. Normally it is not necessary
967 // to call this, unless you change your mind about
968 // preparing it at the last minute, since the data will
969 // automatically be dequeued and prepared at the next
970 // frame.
971 //
972 // The return value is true if the buffer is
973 // successfully dequeued, false if it had not been
974 // queued.
975 ////////////////////////////////////////////////////////////////////
978  ReMutexHolder holder(_lock);
979 
980  EnqueuedVertexBuffers::iterator qi = _enqueued_vertex_buffers.find(data);
981  if (qi != _enqueued_vertex_buffers.end()) {
982  _enqueued_vertex_buffers.erase(qi);
983  return true;
984  }
985  return false;
986 }
987 
988 ////////////////////////////////////////////////////////////////////
989 // Function: PreparedGraphicsObjects::is_vertex_buffer_prepared
990 // Access: Public
991 // Description: Returns true if the vertex buffer has been prepared on
992 // this GSG, false otherwise.
993 ////////////////////////////////////////////////////////////////////
996  return data->is_prepared((PreparedGraphicsObjects *)this);
997 }
998 
999 ////////////////////////////////////////////////////////////////////
1000 // Function: PreparedGraphicsObjects::release_vertex_buffer
1001 // Access: Public
1002 // Description: Indicates that a data context, created by a
1003 // previous call to prepare_vertex_buffer(), is no longer
1004 // needed. The driver resources will not be freed until
1005 // some GSG calls update(), indicating it is at a
1006 // stage where it is ready to release datas--this
1007 // prevents conflicts from threading or multiple GSG's
1008 // sharing datas (we have no way of knowing which
1009 // graphics context is currently active, or what state
1010 // it's in, at the time release_vertex_buffer is called).
1011 ////////////////////////////////////////////////////////////////////
1014  ReMutexHolder holder(_lock);
1015 
1016  vbc->_data->clear_prepared(this);
1017 
1018  size_t data_size_bytes = vbc->_data->get_data_size_bytes();
1019  GeomEnums::UsageHint usage_hint = vbc->_data->get_usage_hint();
1020 
1021  // We have to set the Data pointer to NULL at this point, since
1022  // the Data itself might destruct at any time after it has been
1023  // released.
1024  vbc->_data = (GeomVertexArrayData *)NULL;
1025 
1026  bool removed = (_prepared_vertex_buffers.erase(vbc) != 0);
1027  nassertv(removed);
1028 
1029  if (_support_released_buffer_cache) {
1030  cache_unprepared_buffer(vbc, data_size_bytes, usage_hint,
1031  _vertex_buffer_cache,
1032  _vertex_buffer_cache_lru, _vertex_buffer_cache_size,
1033  released_vbuffer_cache_size,
1034  _released_vertex_buffers);
1035  } else {
1036  _released_vertex_buffers.insert(vbc);
1037  }
1038 }
1039 
1040 ////////////////////////////////////////////////////////////////////
1041 // Function: PreparedGraphicsObjects::release_all_vertex_buffers
1042 // Access: Public
1043 // Description: Releases all datas at once. This will force them
1044 // to be reloaded into data memory for all GSG's that
1045 // share this object. Returns the number of datas
1046 // released.
1047 ////////////////////////////////////////////////////////////////////
1050  ReMutexHolder holder(_lock);
1051 
1052  int num_vertex_buffers = (int)_prepared_vertex_buffers.size() + (int)_enqueued_vertex_buffers.size();
1053 
1054  Buffers::iterator vbci;
1055  for (vbci = _prepared_vertex_buffers.begin();
1056  vbci != _prepared_vertex_buffers.end();
1057  ++vbci) {
1058  VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
1059  vbc->_data->clear_prepared(this);
1060  vbc->_data = (GeomVertexArrayData *)NULL;
1061 
1062  _released_vertex_buffers.insert(vbc);
1063  }
1064 
1065  _prepared_vertex_buffers.clear();
1066  _enqueued_vertex_buffers.clear();
1067 
1068  // Also clear the cache of recently-unprepared vertex buffers.
1069  BufferCache::iterator bci;
1070  for (bci = _vertex_buffer_cache.begin();
1071  bci != _vertex_buffer_cache.end();
1072  ++bci) {
1073  BufferList &buffer_list = (*bci).second;
1074  nassertr(!buffer_list.empty(), num_vertex_buffers);
1075  BufferList::iterator li;
1076  for (li = buffer_list.begin(); li != buffer_list.end(); ++li) {
1077  VertexBufferContext *vbc = (VertexBufferContext *)(*li);
1078  _released_vertex_buffers.insert(vbc);
1079  }
1080  }
1081  _vertex_buffer_cache.clear();
1082  _vertex_buffer_cache_lru.clear();
1083  _vertex_buffer_cache_size = 0;
1084 
1085  return num_vertex_buffers;
1086 }
1087 
1088 ////////////////////////////////////////////////////////////////////
1089 // Function: PreparedGraphicsObjects::get_num_queued_vertex_buffers
1090 // Access: Public
1091 // Description: Returns the number of vertex buffers that have been
1092 // enqueued to be prepared on this GSG.
1093 ////////////////////////////////////////////////////////////////////
1096  return _enqueued_vertex_buffers.size();
1097 }
1098 
1099 ////////////////////////////////////////////////////////////////////
1100 // Function: PreparedGraphicsObjects::get_num_prepared_vertex_buffers
1101 // Access: Public
1102 // Description: Returns the number of vertex buffers that have
1103 // already been prepared on this GSG.
1104 ////////////////////////////////////////////////////////////////////
1107  return _prepared_vertex_buffers.size();
1108 }
1109 
1110 ////////////////////////////////////////////////////////////////////
1111 // Function: PreparedGraphicsObjects::prepare_vertex_buffer_now
1112 // Access: Public
1113 // Description: Immediately creates a new VertexBufferContext for the
1114 // indicated data and returns it. This assumes that
1115 // the GraphicsStateGuardian is the currently active
1116 // rendering context and that it is ready to accept new
1117 // datas. If this is not necessarily the case, you
1118 // should use enqueue_vertex_buffer() instead.
1119 //
1120 // Normally, this function is not called directly. Call
1121 // Data::prepare_now() instead.
1122 //
1123 // The VertexBufferContext contains all of the pertinent
1124 // information needed by the GSG to keep track of this
1125 // one particular data, and will exist as long as the
1126 // data is ready to be rendered.
1127 //
1128 // When either the Data or the
1129 // PreparedGraphicsObjects object destructs, the
1130 // VertexBufferContext will be deleted.
1131 ////////////////////////////////////////////////////////////////////
1134  ReMutexHolder holder(_lock);
1135 
1136  // First, see if there might be a cached context of the appropriate
1137  // size.
1138  size_t data_size_bytes = data->get_data_size_bytes();
1139  GeomEnums::UsageHint usage_hint = data->get_usage_hint();
1141  get_cached_buffer(data_size_bytes, usage_hint,
1142  _vertex_buffer_cache, _vertex_buffer_cache_lru,
1143  _vertex_buffer_cache_size);
1144  if (vbc != (VertexBufferContext *)NULL) {
1145  vbc->_data = data;
1146 
1147  } else {
1148  // Ask the GSG to create a brand new VertexBufferContext. There
1149  // might be several GSG's sharing the same set of datas; if so, it
1150  // doesn't matter which of them creates the context (since they're
1151  // all shared anyway).
1152  vbc = gsg->prepare_vertex_buffer(data);
1153  }
1154 
1155  if (vbc != (VertexBufferContext *)NULL) {
1156  bool prepared = _prepared_vertex_buffers.insert(vbc).second;
1157  nassertr(prepared, vbc);
1158  }
1159 
1160  return vbc;
1161 }
1162 
1163 ////////////////////////////////////////////////////////////////////
1164 // Function: PreparedGraphicsObjects::enqueue_index_buffer
1165 // Access: Public
1166 // Description: Indicates that a buffer would like to be put on the
1167 // list to be prepared when the GSG is next ready to
1168 // do this (presumably at the next frame).
1169 ////////////////////////////////////////////////////////////////////
1172  ReMutexHolder holder(_lock);
1173 
1174  _enqueued_index_buffers.insert(data);
1175 }
1176 
1177 ////////////////////////////////////////////////////////////////////
1178 // Function: PreparedGraphicsObjects::is_index_buffer_queued
1179 // Access: Public
1180 // Description: Returns true if the index buffer has been queued on
1181 // this GSG, false otherwise.
1182 ////////////////////////////////////////////////////////////////////
1185  ReMutexHolder holder(_lock);
1186 
1187  EnqueuedIndexBuffers::const_iterator qi = _enqueued_index_buffers.find((GeomPrimitive *)data);
1188  return (qi != _enqueued_index_buffers.end());
1189 }
1190 
1191 ////////////////////////////////////////////////////////////////////
1192 // Function: PreparedGraphicsObjects::dequeue_index_buffer
1193 // Access: Public
1194 // Description: Removes a buffer from the queued list of data
1195 // arrays to be prepared. Normally it is not necessary
1196 // to call this, unless you change your mind about
1197 // preparing it at the last minute, since the data will
1198 // automatically be dequeued and prepared at the next
1199 // frame.
1200 //
1201 // The return value is true if the buffer is
1202 // successfully dequeued, false if it had not been
1203 // queued.
1204 ////////////////////////////////////////////////////////////////////
1207  ReMutexHolder holder(_lock);
1208 
1209  EnqueuedIndexBuffers::iterator qi = _enqueued_index_buffers.find(data);
1210  if (qi != _enqueued_index_buffers.end()) {
1211  _enqueued_index_buffers.erase(qi);
1212  return true;
1213  }
1214  return false;
1215 }
1216 
1217 ////////////////////////////////////////////////////////////////////
1218 // Function: PreparedGraphicsObjects::is_index_buffer_prepared
1219 // Access: Public
1220 // Description: Returns true if the index buffer has been prepared on
1221 // this GSG, false otherwise.
1222 ////////////////////////////////////////////////////////////////////
1225  return data->is_prepared((PreparedGraphicsObjects *)this);
1226 }
1227 
1228 ////////////////////////////////////////////////////////////////////
1229 // Function: PreparedGraphicsObjects::release_index_buffer
1230 // Access: Public
1231 // Description: Indicates that a data context, created by a
1232 // previous call to prepare_index_buffer(), is no longer
1233 // needed. The driver resources will not be freed until
1234 // some GSG calls update(), indicating it is at a
1235 // stage where it is ready to release datas--this
1236 // prevents conflicts from threading or multiple GSG's
1237 // sharing datas (we have no way of knowing which
1238 // graphics context is currently active, or what state
1239 // it's in, at the time release_index_buffer is called).
1240 ////////////////////////////////////////////////////////////////////
1243  ReMutexHolder holder(_lock);
1244 
1245  ibc->_data->clear_prepared(this);
1246 
1247  size_t data_size_bytes = ibc->_data->get_data_size_bytes();
1248  GeomEnums::UsageHint usage_hint = ibc->_data->get_usage_hint();
1249 
1250  // We have to set the Data pointer to NULL at this point, since
1251  // the Data itself might destruct at any time after it has been
1252  // released.
1253  ibc->_data = (GeomPrimitive *)NULL;
1254 
1255  bool removed = (_prepared_index_buffers.erase(ibc) != 0);
1256  nassertv(removed);
1257 
1258  if (_support_released_buffer_cache) {
1259  cache_unprepared_buffer(ibc, data_size_bytes, usage_hint,
1260  _index_buffer_cache,
1261  _index_buffer_cache_lru, _index_buffer_cache_size,
1262  released_ibuffer_cache_size,
1263  _released_index_buffers);
1264  } else {
1265  _released_index_buffers.insert(ibc);
1266  }
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////
1270 // Function: PreparedGraphicsObjects::release_all_index_buffers
1271 // Access: Public
1272 // Description: Releases all datas at once. This will force them
1273 // to be reloaded into data memory for all GSG's that
1274 // share this object. Returns the number of datas
1275 // released.
1276 ////////////////////////////////////////////////////////////////////
1279  ReMutexHolder holder(_lock);
1280 
1281  int num_index_buffers = (int)_prepared_index_buffers.size() + (int)_enqueued_index_buffers.size();
1282 
1283  Buffers::iterator ibci;
1284  for (ibci = _prepared_index_buffers.begin();
1285  ibci != _prepared_index_buffers.end();
1286  ++ibci) {
1287  IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
1288  ibc->_data->clear_prepared(this);
1289  ibc->_data = (GeomPrimitive *)NULL;
1290 
1291  _released_index_buffers.insert(ibc);
1292  }
1293 
1294  _prepared_index_buffers.clear();
1295  _enqueued_index_buffers.clear();
1296 
1297  // Also clear the cache of recently-unprepared index buffers.
1298  BufferCache::iterator bci;
1299  for (bci = _index_buffer_cache.begin();
1300  bci != _index_buffer_cache.end();
1301  ++bci) {
1302  BufferList &buffer_list = (*bci).second;
1303  nassertr(!buffer_list.empty(), num_index_buffers);
1304  BufferList::iterator li;
1305  for (li = buffer_list.begin(); li != buffer_list.end(); ++li) {
1306  IndexBufferContext *vbc = (IndexBufferContext *)(*li);
1307  _released_index_buffers.insert(vbc);
1308  }
1309  }
1310  _index_buffer_cache.clear();
1311  _index_buffer_cache_lru.clear();
1312  _index_buffer_cache_size = 0;
1313 
1314  return num_index_buffers;
1315 }
1316 
1317 ////////////////////////////////////////////////////////////////////
1318 // Function: PreparedGraphicsObjects::get_num_queued_index_buffers
1319 // Access: Public
1320 // Description: Returns the number of index buffers that have been
1321 // enqueued to be prepared on this GSG.
1322 ////////////////////////////////////////////////////////////////////
1325  return _enqueued_index_buffers.size();
1326 }
1327 
1328 ////////////////////////////////////////////////////////////////////
1329 // Function: PreparedGraphicsObjects::get_num_prepared_index_buffers
1330 // Access: Public
1331 // Description: Returns the number of index buffers that have
1332 // already been prepared on this GSG.
1333 ////////////////////////////////////////////////////////////////////
1336  return _prepared_index_buffers.size();
1337 }
1338 
1339 ////////////////////////////////////////////////////////////////////
1340 // Function: PreparedGraphicsObjects::prepare_index_buffer_now
1341 // Access: Public
1342 // Description: Immediately creates a new IndexBufferContext for the
1343 // indicated data and returns it. This assumes that
1344 // the GraphicsStateGuardian is the currently active
1345 // rendering context and that it is ready to accept new
1346 // datas. If this is not necessarily the case, you
1347 // should use enqueue_index_buffer() instead.
1348 //
1349 // Normally, this function is not called directly. Call
1350 // Data::prepare_now() instead.
1351 //
1352 // The IndexBufferContext contains all of the pertinent
1353 // information needed by the GSG to keep track of this
1354 // one particular data, and will exist as long as the
1355 // data is ready to be rendered.
1356 //
1357 // When either the Data or the
1358 // PreparedGraphicsObjects object destructs, the
1359 // IndexBufferContext will be deleted.
1360 ////////////////////////////////////////////////////////////////////
1363  ReMutexHolder holder(_lock);
1364 
1365  // First, see if there might be a cached context of the appropriate
1366  // size.
1367  size_t data_size_bytes = data->get_data_size_bytes();
1368  GeomEnums::UsageHint usage_hint = data->get_usage_hint();
1370  get_cached_buffer(data_size_bytes, usage_hint,
1371  _index_buffer_cache, _index_buffer_cache_lru,
1372  _index_buffer_cache_size);
1373  if (ibc != (IndexBufferContext *)NULL) {
1374  ibc->_data = data;
1375 
1376  } else {
1377  // Ask the GSG to create a brand new IndexBufferContext. There
1378  // might be several GSG's sharing the same set of datas; if so, it
1379  // doesn't matter which of them creates the context (since they're
1380  // all shared anyway).
1381  ibc = gsg->prepare_index_buffer(data);
1382  }
1383 
1384  if (ibc != (IndexBufferContext *)NULL) {
1385  bool prepared = _prepared_index_buffers.insert(ibc).second;
1386  nassertr(prepared, ibc);
1387  }
1388 
1389  return ibc;
1390 }
1391 
1392 ////////////////////////////////////////////////////////////////////
1393 // Function: PreparedGraphicsObjects::begin_frame
1394 // Access: Public
1395 // Description: This is called by the GraphicsStateGuardian to
1396 // indicate that it is about to begin processing of the
1397 // frame.
1398 //
1399 // Any texture contexts that were previously passed to
1400 // release_texture() are actually passed to the GSG to
1401 // be freed at this point; textures that were previously
1402 // passed to prepare_texture are actually loaded.
1403 ////////////////////////////////////////////////////////////////////
1406  ReMutexHolder holder(_lock, current_thread);
1407 
1408  // First, release all the textures, geoms, and buffers awaiting
1409  // release.
1410  if (!_released_textures.empty()) {
1411  Textures::iterator tci;
1412  for (tci = _released_textures.begin();
1413  tci != _released_textures.end();
1414  ++tci) {
1415  TextureContext *tc = (*tci);
1416  gsg->release_texture(tc);
1417  }
1418 
1419  _released_textures.clear();
1420  }
1421 
1422  if (!_released_samplers.empty()) {
1423  ReleasedSamplers::iterator sci;
1424  for (sci = _released_samplers.begin();
1425  sci != _released_samplers.end();
1426  ++sci) {
1427  SamplerContext *sc = (*sci);
1428  gsg->release_sampler(sc);
1429  }
1430 
1431  _released_samplers.clear();
1432  }
1433 
1434  Geoms::iterator gci;
1435  for (gci = _released_geoms.begin();
1436  gci != _released_geoms.end();
1437  ++gci) {
1438  GeomContext *gc = (*gci);
1439  gsg->release_geom(gc);
1440  }
1441 
1442  _released_geoms.clear();
1443 
1444  Shaders::iterator sci;
1445  for (sci = _released_shaders.begin();
1446  sci != _released_shaders.end();
1447  ++sci) {
1448  ShaderContext *sc = (*sci);
1449  gsg->release_shader(sc);
1450  }
1451 
1452  _released_shaders.clear();
1453 
1454  Buffers::iterator vbci;
1455  for (vbci = _released_vertex_buffers.begin();
1456  vbci != _released_vertex_buffers.end();
1457  ++vbci) {
1458  VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
1459  gsg->release_vertex_buffer(vbc);
1460  }
1461 
1462  _released_vertex_buffers.clear();
1463 
1464  Buffers::iterator ibci;
1465  for (ibci = _released_index_buffers.begin();
1466  ibci != _released_index_buffers.end();
1467  ++ibci) {
1468  IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
1469  gsg->release_index_buffer(ibc);
1470  }
1471 
1472  _released_index_buffers.clear();
1473 
1474  // Reset the residency trackers.
1475  _texture_residency.begin_frame(current_thread);
1476  _vbuffer_residency.begin_frame(current_thread);
1477  _ibuffer_residency.begin_frame(current_thread);
1478 
1479  // Now prepare all the textures, geoms, and buffers awaiting
1480  // preparation.
1481  EnqueuedTextures::iterator qti;
1482  for (qti = _enqueued_textures.begin();
1483  qti != _enqueued_textures.end();
1484  ++qti) {
1485  Texture *tex = (*qti);
1486  for (int view = 0; view < tex->get_num_views(); ++view) {
1487  TextureContext *tc = tex->prepare_now(view, this, gsg);
1488  if (tc != (TextureContext *)NULL) {
1489  gsg->update_texture(tc, true);
1490  }
1491  }
1492  }
1493 
1494  _enqueued_textures.clear();
1495 
1496  EnqueuedSamplers::iterator qsmi;
1497  for (qsmi = _enqueued_samplers.begin();
1498  qsmi != _enqueued_samplers.end();
1499  ++qsmi) {
1500  const SamplerState &sampler = (*qsmi);
1501  sampler.prepare_now(this, gsg);
1502  }
1503 
1504  _enqueued_samplers.clear();
1505 
1506  EnqueuedGeoms::iterator qgi;
1507  for (qgi = _enqueued_geoms.begin();
1508  qgi != _enqueued_geoms.end();
1509  ++qgi) {
1510  Geom *geom = (*qgi);
1511  geom->prepare_now(this, gsg);
1512  }
1513 
1514  _enqueued_geoms.clear();
1515 
1516  EnqueuedShaders::iterator qsi;
1517  for (qsi = _enqueued_shaders.begin();
1518  qsi != _enqueued_shaders.end();
1519  ++qsi) {
1520  Shader *shader = (*qsi);
1521  shader->prepare_now(this, gsg);
1522  }
1523 
1524  _enqueued_shaders.clear();
1525 
1526  EnqueuedVertexBuffers::iterator qvbi;
1527  for (qvbi = _enqueued_vertex_buffers.begin();
1528  qvbi != _enqueued_vertex_buffers.end();
1529  ++qvbi) {
1530  GeomVertexArrayData *data = (*qvbi);
1531  data->prepare_now(this, gsg);
1532  }
1533 
1534  _enqueued_vertex_buffers.clear();
1535 
1536  EnqueuedIndexBuffers::iterator qibi;
1537  for (qibi = _enqueued_index_buffers.begin();
1538  qibi != _enqueued_index_buffers.end();
1539  ++qibi) {
1540  GeomPrimitive *data = (*qibi);
1541  // We need this check because the actual index data may
1542  // not actually have propagated to the draw thread yet.
1543  if (data->is_indexed()) {
1544  data->prepare_now(this, gsg);
1545  }
1546  }
1547 
1548  _enqueued_index_buffers.clear();
1549 }
1550 
1551 ////////////////////////////////////////////////////////////////////
1552 // Function: PreparedGraphicsObjects::end_frame
1553 // Access: Public
1554 // Description: This is called by the GraphicsStateGuardian to
1555 // indicate that it has finished processing of the
1556 // frame.
1557 ////////////////////////////////////////////////////////////////////
1559 end_frame(Thread *current_thread) {
1560  ReMutexHolder holder(_lock, current_thread);
1561 
1562  _texture_residency.end_frame(current_thread);
1563  _vbuffer_residency.end_frame(current_thread);
1564  _ibuffer_residency.end_frame(current_thread);
1565 }
1566 
1567 ////////////////////////////////////////////////////////////////////
1568 // Function: PreparedGraphicsObjects::init_name
1569 // Access: Private, Static
1570 // Description: Returns a new, unique name for a newly-constructed
1571 // object.
1572 ////////////////////////////////////////////////////////////////////
1573 string PreparedGraphicsObjects::
1574 init_name() {
1575  ++_name_index;
1576  ostringstream strm;
1577  strm << "context" << _name_index;
1578  return strm.str();
1579 }
1580 
1581 ////////////////////////////////////////////////////////////////////
1582 // Function: PreparedGraphicsObjects::cache_unprepared_buffer
1583 // Access: Private
1584 // Description: Called when a vertex or index buffer is no longer
1585 // officially "prepared". However, we still have the
1586 // context on the graphics card, and we might be able to
1587 // reuse that context if we're about to re-prepare a
1588 // different buffer, especially one exactly the same
1589 // size. So instead of immediately enqueuing the vertex
1590 // buffer for release, we cache it.
1591 ////////////////////////////////////////////////////////////////////
1592 void PreparedGraphicsObjects::
1593 cache_unprepared_buffer(BufferContext *buffer, size_t data_size_bytes,
1594  GeomEnums::UsageHint usage_hint,
1596  PreparedGraphicsObjects::BufferCacheLRU &buffer_cache_lru,
1597  size_t &buffer_cache_size,
1598  int released_buffer_cache_size,
1599  PreparedGraphicsObjects::Buffers &released_buffers) {
1600  BufferCacheKey key;
1601  key._data_size_bytes = data_size_bytes;
1602  key._usage_hint = usage_hint;
1603 
1604  buffer_cache[key].push_back(buffer);
1605  buffer_cache_size += data_size_bytes;
1606 
1607  // Move the key to the head of the LRU.
1608  BufferCacheLRU::iterator li =
1609  find(buffer_cache_lru.begin(), buffer_cache_lru.end(), key);
1610  if (li != buffer_cache_lru.end()) {
1611  buffer_cache_lru.erase(li);
1612  }
1613  buffer_cache_lru.insert(buffer_cache_lru.begin(), key);
1614 
1615  // Now release not-recently-used buffers until we fit within the
1616  // constrained size.
1617  while ((int)buffer_cache_size > released_buffer_cache_size) {
1618  nassertv(!buffer_cache_lru.empty());
1619  const BufferCacheKey &release_key = *buffer_cache_lru.rbegin();
1620  BufferList &buffer_list = buffer_cache[release_key];
1621  while (!buffer_list.empty() &&
1622  (int)buffer_cache_size > released_buffer_cache_size) {
1623  BufferContext *released_buffer = buffer_list.back();
1624  buffer_list.pop_back();
1625  released_buffers.insert(released_buffer);
1626  buffer_cache_size -= release_key._data_size_bytes;
1627  }
1628 
1629  if (buffer_list.empty()) {
1630  buffer_cache.erase(release_key);
1631  buffer_cache_lru.pop_back();
1632  }
1633  }
1634 }
1635 
1636 ////////////////////////////////////////////////////////////////////
1637 // Function: PreparedGraphicsObjects::get_cached_buffer
1638 // Access: Private
1639 // Description: Returns a previously-cached buffer from the cache, or
1640 // NULL if there is no such buffer.
1641 ////////////////////////////////////////////////////////////////////
1642 BufferContext *PreparedGraphicsObjects::
1643 get_cached_buffer(size_t data_size_bytes, GeomEnums::UsageHint usage_hint,
1645  PreparedGraphicsObjects::BufferCacheLRU &buffer_cache_lru,
1646  size_t &buffer_cache_size) {
1647  BufferCacheKey key;
1648  key._data_size_bytes = data_size_bytes;
1649  key._usage_hint = usage_hint;
1650 
1651  BufferCache::iterator bci = buffer_cache.find(key);
1652  if (bci == buffer_cache.end()) {
1653  return NULL;
1654  }
1655 
1656  BufferList &buffer_list = (*bci).second;
1657  nassertr(!buffer_list.empty(), NULL);
1658 
1659  BufferContext *buffer = buffer_list.back();
1660  buffer_list.pop_back();
1661  if (buffer_list.empty()) {
1662  buffer_cache.erase(bci);
1663  BufferCacheLRU::iterator li =
1664  find(buffer_cache_lru.begin(), buffer_cache_lru.end(), key);
1665  if (li != buffer_cache_lru.end()) {
1666  buffer_cache_lru.erase(li);
1667  }
1668  }
1669 
1670  buffer_cache_size -= data_size_bytes;
1671  return buffer;
1672 }
IndexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
int release_all_shaders()
Releases all shaders at once.
VertexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
bool is_sampler_queued(const SamplerState &sampler) const
Returns true if the sampler has been queued on this GSG, false otherwise.
bool is_shader_prepared(const Shader *shader) const
Returns true if the shader has been prepared on this GSG, false otherwise.
int get_num_queued_samplers() const
Returns the number of samplers that have been enqueued to be prepared on this GSG.
int get_num_prepared_shaders() const
Returns the number of shaders that have already been prepared on this GSG.
int get_num_queued_textures() const
Returns the number of textures that have been enqueued to be prepared on this GSG.
bool is_texture_queued(const Texture *tex) const
Returns true if the texture has been queued on this GSG, false otherwise.
void release_shader(ShaderContext *sc)
Indicates that a shader context, created by a previous call to prepare_shader(), is no longer needed...
void enqueue_texture(Texture *tex)
Indicates that a texture would like to be put on the list to be prepared when the GSG is next ready t...
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: geomContext.h:39
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG...
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the shader has already been prepared or enqueued for preparation on the indicated GSG...
Definition: shader.cxx:2905
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
UsageHint get_usage_hint() const
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
void release_geom(GeomContext *gc)
Indicates that a geom context, created by a previous call to prepare_geom(), is no longer needed...
GeomContext * prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg)
Immediately creates a new GeomContext for the indicated geom and returns it.
void release_texture(TextureContext *tc)
Indicates that a texture context, created by a previous call to prepare_texture(), is no longer needed.
int release_all_vertex_buffers()
Releases all datas at once.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the geom has already been prepared or enqueued for preparation on the indicated GSG...
Definition: geom.cxx:1192
UsageHint get_usage_hint() const
Returns the usage hint for this primitive.
Definition: geomPrimitive.I:67
bool dequeue_texture(Texture *tex)
Removes a texture from the queued list of textures to be prepared.
bool dequeue_index_buffer(GeomPrimitive *data)
Removes a buffer from the queued list of data arrays to be prepared.
This is a special class object that holds all the information returned by a particular GSG to indicat...
This is a base class for those kinds of SavedContexts that occupy an easily-measured (and substantial...
Definition: bufferContext.h:41
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
void set_max_size(size_t max_size)
Changes the max size of all objects that are allowed to be active on the LRU.
Definition: adaptiveLru.I:49
bool dequeue_sampler(const SamplerState &sampler)
Removes a sampler from the queued list of samplers to be prepared.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:63
IndexBufferContext * prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new IndexBufferContext for the indicated data and returns it.
bool is_index_buffer_prepared(const GeomPrimitive *data) const
Returns true if the index buffer has been prepared on this GSG, false otherwise.
Definition: shader.h:50
void show_residency_trackers(ostream &out) const
Writes to the indicated ostream a report of how the various textures and vertex buffers are allocated...
void enqueue_shader(Shader *shader)
Indicates that a shader would like to be put on the list to be prepared when the GSG is next ready to...
This is a special class object that holds all the information returned by a particular GSG to indicat...
int get_data_size_bytes() const
Returns the number of bytes stored in the array.
void enqueue_index_buffer(GeomPrimitive *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
void release_vertex_buffer(VertexBufferContext *vbc)
Indicates that a data context, created by a previous call to prepare_vertex_buffer(), is no longer needed.
bool is_vertex_buffer_prepared(const GeomVertexArrayData *data) const
Returns true if the vertex buffer has been prepared on this GSG, false otherwise. ...
void show_graphics_memory_lru(ostream &out) const
Writes to the indicated ostream a report of how the various textures and vertex buffers are allocated...
int get_data_size_bytes() const
Returns the number of bytes stored in the vertices array.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture has already been prepared or enqueued for preparation on the indicated GS...
Definition: texture.cxx:1294
void enqueue_sampler(const SamplerState &sampler)
Indicates that a sampler would like to be put on the list to be prepared when the GSG is next ready t...
VertexBufferContext * prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new VertexBufferContext for the indicated data and returns it.
SamplerContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg) const
Creates a context for the sampler on the particular GSG, if it does not already exist.
A table of objects that are saved within the graphics context for reference by handle later...
bool is_index_buffer_queued(const GeomPrimitive *data) const
Returns true if the index buffer has been queued on this GSG, false otherwise.
The ShaderContext is meant to contain the compiled version of a shader string.
Definition: shaderContext.h:35
bool is_geom_prepared(const Geom *geom) const
Returns true if the vertex buffer has been prepared on this GSG, false otherwise. ...
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG...
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the texture context only on the indicated object, if it exists there.
Definition: texture.cxx:1438
ShaderContext * prepare_shader_now(Shader *shader, GraphicsStateGuardianBase *gsg)
Immediately creates a new ShaderContext for the indicated shader and returns it.
void release_index_buffer(IndexBufferContext *ibc)
Indicates that a data context, created by a previous call to prepare_index_buffer(), is no longer needed.
bool is_vertex_buffer_queued(const GeomVertexArrayData *data) const
Returns true if the vertex buffer has been queued on this GSG, false otherwise.
int get_num_views() const
Returns the number of &quot;views&quot; in the texture.
Definition: texture.I:683
int get_num_prepared_samplers() const
Returns the number of samplers that have already been prepared on this GSG.
int get_num_queued_geoms() const
Returns the number of geoms that have been enqueued to be prepared on this GSG.
int get_num_queued_shaders() const
Returns the number of shaders that have been enqueued to be prepared on this GSG. ...
A container for geometry primitives.
Definition: geom.h:58
GeomContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the geom on the particular GSG, if it does not already exist.
Definition: geom.cxx:1269
bool dequeue_vertex_buffer(GeomVertexArrayData *data)
Removes a buffer from the queued list of data arrays to be prepared.
SamplerContext * prepare_sampler_now(const SamplerState &sampler, GraphicsStateGuardianBase *gsg)
Immediately creates a new SamplerContext for the indicated sampler and returns it.
void enqueue_vertex_buffer(GeomVertexArrayData *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:27
int release_all_textures()
Releases all textures at once.
int get_num_prepared_vertex_buffers() const
Returns the number of vertex buffers that have already been prepared on this GSG. ...
bool dequeue_shader(Shader *shader)
Removes a shader from the queued list of shaders to be prepared.
int release_all_geoms()
Releases all geoms at once.
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:39
TextureContext * prepare_now(int view, PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the texture on the particular GSG, if it does not already exist.
Definition: texture.cxx:1808
void end_frame(Thread *current_thread)
This is called by the GraphicsStateGuardian to indicate that it has finished processing of the frame...
This is a special class object that holds a handle to the sampler state object given by the graphics ...
bool is_sampler_prepared(const SamplerState &sampler) const
Returns true if the sampler has been prepared on this GSG, false otherwise.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
int get_num_prepared_textures() const
Returns the number of textures that have already been prepared on this GSG.
A thread; that is, a lightweight process.
Definition: thread.h:51
TextureContext * prepare_texture_now(Texture *tex, int view, GraphicsStateGuardianBase *gsg)
Immediately creates a new TextureContext for the indicated texture and returns it.
This is a special class object that holds all the information returned by a particular GSG to indicat...
void begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread)
This is called by the GraphicsStateGuardian to indicate that it is about to begin processing of the f...
int get_view() const
Returns the specific view of a multiview texture this context represents.
void enqueue_geom(Geom *geom)
Indicates that a geom would like to be put on the list to be prepared when the GSG is next ready to d...
int get_num_prepared_index_buffers() const
Returns the number of index buffers that have already been prepared on this GSG.
void release_sampler(SamplerContext *sc)
Indicates that a sampler context, created by a previous call to prepare_sampler(), is no longer needed.
bool is_texture_prepared(const Texture *tex) const
Returns true if the texture has been prepared on this GSG, false otherwise.
int get_num_queued_index_buffers() const
Returns the number of index buffers that have been enqueued to be prepared on this GSG...
int get_num_prepared_geoms() const
Returns the number of geoms that have already been prepared on this GSG.
void begin_frame(Thread *current_thread)
To be called at the beginning of a frame, this initializes the active/inactive status.
void set_graphics_memory_limit(size_t limit)
Sets an artificial cap on graphics memory that will be imposed on this GSG.
void end_frame(Thread *current_thread)
To be called at the end of a frame, this updates the PStatCollectors appropriately.
int release_all_samplers()
Releases all samplers at once.
ShaderContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the shader on the particular GSG, if it does not already exist.
Definition: shader.cxx:2956
bool is_geom_queued(const Geom *geom) const
Returns true if the geom has been queued on this GSG, false otherwise.
int get_num_queued_vertex_buffers() const
Returns the number of vertex buffers that have been enqueued to be prepared on this GSG...
size_t get_max_size() const
Returns the max size of all objects that are allowed to be active on the LRU.
Definition: adaptiveLru.I:35
bool is_shader_queued(const Shader *shader) const
Returns true if the shader has been queued on this GSG, false otherwise.
bool dequeue_geom(Geom *geom)
Removes a geom from the queued list of geoms to be prepared.
This is the data for one array of a GeomVertexData structure.
int release_all_index_buffers()
Releases all datas at once.