Panda3D
graphicsStateGuardianBase.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file graphicsStateGuardianBase.cxx
10  * @author drose
11  * @date 1999-10-06
12  */
13 
15 #include "lightMutexHolder.h"
16 #include <algorithm>
17 
18 AtomicAdjust::Pointer GraphicsStateGuardianBase::_gsg_list;
19 UpdateSeq GraphicsStateGuardianBase::_generated_shader_seq;
20 TypeHandle GraphicsStateGuardianBase::_type_handle;
21 
22 /**
23  * Returns a pointer to the "default" GSG. This is typically the first GSG
24  * created in an application; in a single-window application, it will be the
25  * only GSG. This GSG is used to determine default optimization choices for
26  * loaded geometry.
27  *
28  * The return value may be NULL if a GSG has not been created.
29  */
32  GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
33  if (gsg_list == nullptr) {
34  // Nobody created a GSG list, so we won't have any GSGs either.
35  return nullptr;
36  }
37  LightMutexHolder holder(gsg_list->_lock);
38  return gsg_list->_default_gsg;
39 }
40 
41 /**
42  * Specifies a particular GSG to use as the "default" GSG. See
43  * get_default_gsg().
44  */
47  GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
48  if (gsg_list == nullptr) {
49  // Nobody ever created a GSG list. How could we have a GSG?
50  nassertv(false);
51  return;
52  }
53 
54  LightMutexHolder holder(gsg_list->_lock);
55  if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), default_gsg) == gsg_list->_gsgs.end()) {
56  // The specified GSG doesn't exist or it has already destructed.
57  nassert_raise("GSG not found or already destructed");
58  return;
59  }
60 
61  gsg_list->_default_gsg = default_gsg;
62 }
63 
64 /**
65  * Returns the total number of GSG's in the universe.
66  */
67 size_t GraphicsStateGuardianBase::
68 get_num_gsgs() {
69  GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
70  if (gsg_list == nullptr) {
71  // Nobody created a GSG list, so we won't have any GSGs either.
72  return 0;
73  }
74  LightMutexHolder holder(gsg_list->_lock);
75  return gsg_list->_gsgs.size();
76 }
77 
78 /**
79  * Returns the nth GSG in the universe. GSG's automatically add themselves
80  * and remove themselves from this list as they are created and destroyed.
81  */
83 get_gsg(size_t n) {
84  GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
85  nassertr(gsg_list != nullptr, nullptr);
86 
87  LightMutexHolder holder(gsg_list->_lock);
88  nassertr(n < gsg_list->_gsgs.size(), nullptr);
89  return gsg_list->_gsgs[n];
90 }
91 
92 /**
93  * Called by a GSG after it has been initialized, to add a new GSG to the
94  * available list.
95  */
98  GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
99  if (gsg_list == nullptr) {
100  gsg_list = new GSGList;
101  gsg_list->_default_gsg = nullptr;
102 
103  GSGList *orig_gsg_list = (GSGList *)
104  AtomicAdjust::compare_and_exchange_ptr(_gsg_list, nullptr, gsg_list);
105 
106  if (orig_gsg_list != nullptr) {
107  // Another thread beat us to it. No problem, we'll use that.
108  delete gsg_list;
109  gsg_list = orig_gsg_list;
110  }
111  }
112 
113  LightMutexHolder holder(gsg_list->_lock);
114 
115  if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg) != gsg_list->_gsgs.end()) {
116  // Already on the list.
117  return;
118  }
119 
120  gsg_list->_gsgs.push_back(gsg);
121 
122  if (gsg_list->_default_gsg == nullptr) {
123  gsg_list->_default_gsg = gsg;
124  }
125 }
126 
127 /**
128  * Called by a GSG destructor to remove a GSG from the available list.
129  */
132  GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
133  if (gsg_list == nullptr) {
134  // No GSGs were added yet, or the program is destructing anyway.
135  return;
136  }
137 
138  LightMutexHolder holder(gsg_list->_lock);
139 
140  GSGList::GSGs::iterator gi;
141  gi = find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg);
142  if (gi == gsg_list->_gsgs.end()) {
143  // Already removed, or never added.
144  return;
145  }
146 
147  gsg_list->_gsgs.erase(gi);
148 
149  if (gsg_list->_default_gsg == gsg) {
150  if (!gsg_list->_gsgs.empty()) {
151  gsg_list->_default_gsg = *gsg_list->_gsgs.begin();
152  } else {
153  gsg_list->_default_gsg = nullptr;
154  }
155  }
156 }
static Pointer get_ptr(const Pointer &var)
Atomically retrieves the snapshot value of the indicated variable.
get_gsg
Returns the nth GSG in the universe.
static void remove_gsg(GraphicsStateGuardianBase *gsg)
Called by a GSG destructor to remove a GSG from the available list.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Similar to MutexHolder, but for a light mutex.
static GraphicsStateGuardianBase * get_default_gsg()
Returns a pointer to the "default" GSG.
static void set_default_gsg(GraphicsStateGuardianBase *default_gsg)
Specifies a particular GSG to use as the "default" GSG.
static void add_gsg(GraphicsStateGuardianBase *gsg)
Called by a GSG after it has been initialized, to add a new GSG to the available list.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
static Pointer compare_and_exchange_ptr(Pointer &mem, Pointer old_value, Pointer new_value)
Atomic compare and exchange.