Open Inventor Release 2024.1.3
 
Loading...
Searching...
No Matches
SoContextedObjectCacheList.h
1/*=======================================================================
2 *** THE CONTENT OF THIS WORK IS PROPRIETARY TO FEI S.A.S, (FEI S.A.S.), ***
3 *** AND IS DISTRIBUTED UNDER A LICENSE AGREEMENT. ***
4 *** ***
5 *** REPRODUCTION, DISCLOSURE, OR USE, IN WHOLE OR IN PART, OTHER THAN AS ***
6 *** SPECIFIED IN THE LICENSE ARE NOT TO BE UNDERTAKEN EXCEPT WITH PRIOR ***
7 *** WRITTEN AUTHORIZATION OF FEI S.A.S. ***
8 *** ***
9 *** RESTRICTED RIGHTS LEGEND ***
10 *** USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT OF THE CONTENT OF THIS ***
11 *** WORK OR RELATED DOCUMENTATION IS SUBJECT TO RESTRICTIONS AS SET FORTH IN ***
12 *** SUBPARAGRAPH (C)(1) OF THE COMMERCIAL COMPUTER SOFTWARE RESTRICTED RIGHT ***
13 *** CLAUSE AT FAR 52.227-19 OR SUBPARAGRAPH (C)(1)(II) OF THE RIGHTS IN ***
14 *** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 52.227-7013. ***
15 *** ***
16 *** COPYRIGHT (C) 1996-2014 BY FEI S.A.S, ***
17 *** BORDEAUX, FRANCE ***
18 *** ALL RIGHTS RESERVED ***
19**=======================================================================*/
20/*=======================================================================
21** Author : mmh * (MMM yyyy)
22**=======================================================================*/
23
24#ifndef _SO_CONTEXTED_OBJECT_CACHE_LIST_H_
25#define _SO_CONTEXTED_OBJECT_CACHE_LIST_H_
26
28//
29// SoContextedObjectCacheList
30// This class has some similarities to SoGLCacheList, which manages render
31// caches (OpenGL display lists), but is significantly different because:
32//
33// 1) Texture caches (OpenGL texture objects) only depend on the OpenGL render
34// context (identified by cachectxSharedId in Inventor) and texture quality.
35// Render caches depend on a large number of traversal state elements
36// (including cachectxSharedId). In fact SoGLCacheList is able to maintain
37// multiple render caches (with different attribute settings) for the same
38// cachectxSharedId. For texture caches we do not need this complexity, so
39// we only maintain a single texture cache for each cachectxSharedId.
40//
41// 2) Texture nodes already have a slightly complicated relationship with the
42// SoGLTextureImageElement, where the element creates the texture object,
43// but the node stores the address of the object for later re-use.
44// SoGLCacheList, on the other hand, is relatively self-contained. It is
45// responsible for creating, using and destroying render caches and looks
46// more like a "black box" to Separator (etc) nodes. SoContextedObjectCacheList is
47// more of a "helper" class that does some bookkeeping for the client node.
48// It will generally be safer and more efficient for the client node to
49// lock its own mutex, but we have provided an optional internal mutex.
50//
51// 3) Texture caches are used in a different way than render caches. A "call"
52// of a render cache (glCallList) is a somewhat atomic operation. We must
53// ensure the display list continues to exist until glCallList returns,
54// but after that it could be destroyed. A texture cache is put into the
55// traversal state and must continue to exist until its TextureImageElement
56// is popped off the stack. We don't know what other geometry the texture
57// might apply to. To ensure this happens safely with multiple threads we
58// modified TextureImageElement to ref and unref the texture object.
59//
60// The number of texture caches that are required depends on the number of
61// graphics pipes that the application will use. However, it specifically
62// depends on the number of different cachectxSharedIds. So if all the pipes
63// can share texture objects, they can (and should) all use the same
64// cachectxSharedId, and only one texture cache is required. If the pipes
65// cannot share texture objects (eg. on SGI hardware), then they should each
66// use a different cachectxSharedId and the number of texture caches should be
67// equal to or greater than the number of pipes. The number of caches can be
68// set for both render and texture caches using SoDB::setNumRenderCaches.
69//
70// There are two cases that should account for 99% of the usage:
71//
72// Case 1: Classic single pipe Open Inventor program
73//
74// The effective behavior in this case should be the same as before.
75// Typically the program will only have one cachectxSharedId value (even
76// if it uses multiple Open Inventor windows), so only one texture cache
77// is needed. If the texture quality changes, the texture node will create
78// a new texture object and call setCache, but the cachectxSharedId will be
79// the same so the existing entry will be re-used.
80//
81// Case 2: Multi-pipe Open Inventor program
82//
83// Typically each pipe will have a different cachectxSharedId, but once
84// the pipes are set up, the cachectxSharedIds will remain the same until
85// the program exits. There are should be as many texture caches as
86// there are pipes and each cachectxSharedId will have its own cache (and
87// its own texture object). If the texture quality changes, the texture
88// node will create a new texture object and call setCache in each render
89// thread, but the cachectxSharedId is the same for each thread, so the
90// existing entry will be re-used.
91//
92// In the unlikely, but possible, case that there are more cachectxSharedId
93// values than there are texture caches, the SoContextedObjectCacheList will choose
94// an existing cache entry to "clobber". This is based on a useCount to
95// encourage clobbering the least used cache entry. However it is likely
96// that in this case the cache list will be "thrashing", clobbering and
97// re-using the same cache entry over and over. This is not good, but no
98// worse than the behavior in the 3.0 (and older) code. :-)
99//
101
102#include <Inventor/SbBasic.h>
103#include <Inventor/helpers/SbGlContextHelper.h>
104#include <Inventor/caches/SoBaseContextCache.h>
105
106class SoState;
107class SoDeviceContext;
108// Base class that implements the common cache functions.
109
110
111{
112 private:
113 SoBaseContextedObjectCacheList(int numCaches = 1, bool sharable = true, SbBool useMutex = FALSE);
125
126 void *getCache( SoState *state, float quality );
127 void *getCache( SoDeviceContext* ctx, float quality );
128
129 void setCache( int sharedGroup, void *texObj,
130 float quality, SoState *state = NULL );
131
132 void setCache( int sharedGroup, void *texObj,
133 float quality, SoState *state, void*& oldTexObj );
134 public:
135 // Specifies that all texture caches are invalid.
136 // This method would be called, for example, if the texture quality
137 // or the wrap/repeat setting changes. Because there is a single
138 // texture cache for each context id, the change invalidates all
139 // the caches.
140 //
141 // NOTE: All texObj's will be unref'd. A valid SoState* should be
142 // passed if possible so texObjs can be destroyed immediately.
143 void invalidateAll( SoState *state = NULL ) const;
144
145 // Specifies that all texture caches are invalid for a specific context.
146 // This method would be called, for example, if the texture quality
147 // or the wrap/repeat setting changes. Because there is a single
148 // texture cache for each context id, the change invalidates all
149 // the caches.
150 //
151 // NOTE: All texObj's will be unref'd. A valid SoState* should be
152 // passed if possible so texObjs can be destroyed immediately.
153 bool invalidateContext( SoDeviceContextSharedGroup* ctx);
154
155 private:
156 // Get the cache for the specified context id.
157 // Returns NULL if there is no cache for the specified context id.
158 // If there is a cache, the current texObj may be NULL.
159 //
160 // NOTE: This method does not ref or unref the texObj.
161 // It does increment the useCount if a cache was found.
162 SoGLTexCacheEntry *getCache( SoState *state);
163
164 private:
165
172 virtual void release(SoDeviceContextSharedGroup *ctx);
173
174private:
175
177 virtual ~SoBaseContextedObjectCacheList();
178
184 virtual bool notifyDelete() const;
185
187 virtual void refObject(void *obj) const = 0;
188 virtual void unrefObject(void *obj) const = 0;
189
190 private:
191
192 SoGLTexCacheEntry* m_cacheList;
193 int m_numCaches;
194 SbThreadMutex* m_mutex;
195
197 bool m_sharable;
198
199 static int s_debugFlag;
200};
201
202template <typename TContextedObject>
203
204{
205 public:
206 // Constructor.
207 // Takes the maximum number of caches to build and an
208 // optional flag specifying to use internal mutex.
209 // It is more efficient, and safer, for the client code
210 // to lock its own mutex.
211 SoContextedObjectCacheList(int numCaches = 1, bool sharable = true, SbBool useMutex = FALSE)
212 : SoBaseContextedObjectCacheList(numCaches, sharable, useMutex)
213 {
214 }
215
216 // Get the texture object for the specified context id and quality.
217 //
218 // Returns NULL if there is no cache for the specified context id.
219 // Even if there is a cache, the current texObj may be NULL.
220 //
221 // NOTE: This method does not ref or unref the texObj.
222 // It does increment the useCount if a cache was found.
223 TContextedObject *getCache( SoState *state, float quality )
224 {
225 return static_cast<TContextedObject*>(SoBaseContextedObjectCacheList::getCache(state, quality));
226 }
227
228 TContextedObject *getCache( SoDeviceContext* ctx, float quality )
229 {
230 return static_cast<TContextedObject*>(SoBaseContextedObjectCacheList::getCache(ctx, quality));
231 }
232
233 // Get a texture object for the specified context id.
234 // Returns false if there is no cache for the specified context id.
235 // If there is a cache, the current texObj may be NULL.
236 //
237 // NOTE: This method does not ref or unref the texObj.
238 // It does increment the useCount if a cache was found.
239 bool getCache( SoState *state, TContextedObject*& texObj)
240 {
241 texObj = NULL;
242 SoGLTexCacheEntry *entry = SoBaseContextedObjectCacheList::getCache(state);
243 if (entry == NULL)
244 return false;
245 texObj = static_cast<TContextedObject*>(entry->texObj);
246 return true;
247 }
248
249 // Set the values in the cache for the specified context id.
250 // If there is a cache for this context id, its values are modified.
251 // Else if there is an unused cache entry, it becomes the cache for
252 // this context id and its values are modified. Else the least
253 // used cache entry (lowest useCount) is chosen and becomes the
254 // cache for this context id.
255 //
256 // NOTE: The specified texObj will be ref'd and the current texObj
257 // in the cache entry (if any) will be unref'd. A valid
258 // SoState* should be passed if possible so texObjs can be
259 // destroyed immediately (more efficient).
260 void setCache( int sharedGroup, TContextedObject *texObj,
261 float quality, SoState *state = NULL )
262 {
263 SoBaseContextedObjectCacheList::setCache(sharedGroup, texObj, quality, state);
264 }
265
266 void setCache( int sharedGroup, TContextedObject *texObj,
267 float quality, SoState *state, TContextedObject*& oldTexObj )
268 {
269 void* oldObj;
270 SoBaseContextedObjectCacheList::setCache(sharedGroup, texObj, quality, state, oldObj);
271 oldTexObj = static_cast<TContextedObject*>(oldObj);
272 }
273
274private:
275
277 virtual ~SoContextedObjectCacheList() { invalidateAll(); }
278
279 virtual void refObject(void *obj) const
280 {
281 if (obj)
282 static_cast<TContextedObject*>(obj)->ref();
283 }
284
285 virtual void unrefObject(void *obj) const
286 {
287 if (obj)
288 static_cast<TContextedObject*>(obj)->unref();
289 }
290};
291#endif //_SO_CONTEXTED_OBJECT_CACHE_LIST_H_
292
293
<a href="IconLegend.html"><img src="extTGS.gif" alt="VSG extension" border="0"></a> Portable mutex c...
<a href="IconLegend.html"><img src="extTGS.gif" alt="VSG extension" border="0"></a> Abstract base cl...
<a href="IconLegend.html"><img src="extTGS.gif" alt="VSG extension" border="0"></a> Shared context m...
Traversal state.
Definition SoState.h:74
int SbBool
Boolean type.
Definition SbBase.h:87
Stores info about a tex cache.
float quality
uint64_t lastUse
void * texObj
SoDeviceContextSharedGroup * contextSharedGroup