fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / State / Base / OSGState.cpp
blob1b54945415a940dc3c61e1c74bb11478d3825fc2
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include "OSGGL.h"
50 #include "OSGStateChunk.h"
52 #include "OSGState.h"
54 #include "OSGTextureBaseChunk.h"
55 #include "OSGMaterialChunk.h"
56 #include "OSGShaderExecutableChunk.h"
57 #include "OSGShaderExecutableVarChunk.h"
58 #include "OSGLightChunk.h"
59 #include "OSGMaterial.h"
61 OSG_USING_NAMESPACE
63 // Documentation for this class is emited in the
64 // OSGStateBase.cpp file.
65 // To modify it, please change the .fcd file (OSGState.fcd) and
66 // regenerate the base file.
68 /***************************************************************************\
69 * Class variables *
70 \***************************************************************************/
72 /***************************************************************************\
73 * Class methods *
74 \***************************************************************************/
76 /*-------------------------------------------------------------------------*\
77 - private -
78 \*-------------------------------------------------------------------------*/
80 void State::initMethod(InitPhase ePhase)
82 Inherited::initMethod(ePhase);
85 /***************************************************************************\
86 * Instance methods *
87 \***************************************************************************/
89 /*-------------------------------------------------------------------------*\
90 - public -
91 \*-------------------------------------------------------------------------*/
93 void State::onCreateAspect(const State *createAspect,
94 const State *source )
96 Inherited::onCreateAspect(createAspect, source);
98 UInt32 uiTId = TextureBaseChunk ::getStaticClassId() & 0x000003FF;
99 UInt32 uiShId = ShaderExecutableChunk ::getStaticClassId() & 0x000003FF;
100 UInt32 uiMId = ShaderExecutableVarChunk::getStaticClassId() & 0x000003FF;
102 _uiKeyGen = ( (uiShId) | (uiTId << 10) | (uiMId << 20) );
105 fprintf(stderr, "CreateKeyGen (%p | %p | %p) from %d %d -> %08x\n",
106 this,
107 createAspect,
108 source,
109 TextureChunk ::getStaticClassId(),
110 MaterialChunk::getStaticClassId(),
111 _uiKeyGen);
115 /*------------- constructors & destructors --------------------------------*/
117 State::State(void) :
118 Inherited ( ),
119 _uiDefaultSortKey (0 ),
120 _uiSortKey (0 ),
121 _uiKeyGen (0 ),
122 #if defined(OSG_OGL_COREONLY)
123 _uiCoreGLChunkLimit(LightChunk::getStaticClassId())
124 #else
125 _uiCoreGLChunkLimit(4096 ) // Arbitrary high value
126 #endif
130 State::State(const State &source) :
131 Inherited ( source),
132 _uiDefaultSortKey ( 0),
133 _uiSortKey ( 0),
134 _uiKeyGen ( 0),
135 #if defined(OSG_OGL_COREONLY)
136 _uiCoreGLChunkLimit(LightChunk::getStaticClassId())
137 #else
138 _uiCoreGLChunkLimit(4096 ) // Arbitrary high value
139 #endif
143 State::~State(void)
147 void State::rebuildSortKey(void)
149 UInt32 uiKey1 = _uiKeyGen & Key1Mask;
150 UInt32 uiKey2 = (_uiKeyGen & Key2Mask) >> 10;
151 UInt32 uiKey3 = (_uiKeyGen & Key3Mask) >> 20;
153 UInt32 uiSizeChunks = _mfChunks.size32();
155 // fprintf(stderr, "Got Keys %d %d %d\n", uiKey1, uiKey2, uiKey3);
157 const State *pThis = this;
159 if(uiKey1 != InvalidKey && uiKey1 < uiSizeChunks)
161 uiKey1 =
162 (pThis->_mfChunks[uiKey1] != NULL &&
163 pThis->_mfChunks[uiKey1]->getIgnore() == false ) ?
165 pThis->_mfChunks[uiKey1]->getChunkId() : 0;
167 else
169 uiKey1 = 0x00000000;
172 if(uiKey2 != InvalidKey && uiKey2 < uiSizeChunks)
174 uiKey2 =
175 (pThis->_mfChunks[uiKey2] != NULL &&
176 pThis->_mfChunks[uiKey2]->getIgnore() == false ) ?
178 pThis->_mfChunks[uiKey2]->getChunkId() : 0;
180 else
182 uiKey2 = 0x00000000;
185 if(uiKey3 != InvalidKey && uiKey3 < uiSizeChunks)
187 uiKey3 =
188 (pThis->_mfChunks[uiKey3] != NULL &&
189 pThis->_mfChunks[uiKey3]->getIgnore() == false ) ?
191 pThis->_mfChunks[uiKey3]->getChunkId() : 0;
193 else
195 uiKey3 = 0x00000000;
198 _uiSortKey =
199 (uiKey1 & Key1Mask) |
200 ((uiKey2 & Key1Mask) << 10) |
201 ((uiKey3 & Key1Mask) << 20);
203 if(_uiSortKey == 0x00000000)
205 _uiSortKey = _uiDefaultSortKey;
209 fprintf(stderr, "Use Sort Key : %08x %08x %08x %08x -> %08x\n",
210 uiKey1,
211 uiKey2,
212 uiKey3,
213 _uiDefaultSortKey,
214 _uiSortKey);
218 void State::changed(ConstFieldMaskArg whichField,
219 UInt32 origin,
220 BitVector details)
222 Inherited::changed(whichField, origin, details);
224 rebuildSortKey();
227 /*------------------------------- dump ----------------------------------*/
229 void State::dump( UInt32 OSG_CHECK_ARG(uiIndent),
230 const BitVector OSG_CHECK_ARG(bvFlags)) const
232 std::cerr << "State at " << this << std::endl;
234 MFChunksType::const_iterator it;
235 UInt32 cind;
237 for(it = _mfChunks.begin(), cind = 0; it != _mfChunks.end(); ++it, ++cind)
239 std::cerr << "[" << cind << "]["
240 << StateChunkClass::getName(cind) << "]\t";
242 if(*it == NULL)
244 std::cerr << "NullChunk" << std::endl;
246 else
248 std::cerr << *it << std::endl;
253 /*-------------------- OpenGL State Management --------------------------*/
255 /*! Activate (i.e. call all their OpenGL commands) the current set of
256 StateChunks. Activate will simply overwrite whatever was set before.
259 void State::activate(DrawEnv *pEnv) const
261 MFChunksType::const_iterator cIt = _mfChunks.begin();
262 MFChunksType::const_iterator cEnd = _mfChunks.end ();
263 Int32 ind = 0;
264 UInt32 cind = osgMin(State::SkipNumChunks,
265 _mfChunks.size32() );
266 UInt32 const climit = _uiCoreGLChunkLimit;
268 OSG_SKIP_IT(cIt, cind);
270 for(; (cIt != cEnd) && (cind < climit); ++cIt, ++cind)
272 if(*cIt != NULL && (*cIt)->getIgnore() == false)
274 (*cIt)->activate(pEnv, UInt32(ind));
277 if(++ind >= StateChunkClass::getNumSlots(cind))
278 ind = 0;
283 /*! Switch to this state from the given old State. The chunks will try to
284 optimize the transition.
287 void State::changeFrom(DrawEnv *pEnv, State *pOld) const
289 MFChunksType::const_iterator cIt = _mfChunks.begin();
290 MFChunksType::const_iterator cEnd = _mfChunks.end ();
291 Int32 ind = 0;
292 UInt32 i;
293 UInt32 cind = osgMin(State::SkipNumChunks,
294 _mfChunks.size32() );
295 UInt32 const climit = _uiCoreGLChunkLimit;
297 OSG_SKIP_IT(cIt, cind);
299 for(; (cIt != cEnd) && (cind < climit); ++cIt, ++cind)
301 StateChunk *o = pOld->getChunk(cind);
302 StateChunk *n = *cIt;
304 if(n != NULL && n->getIgnore() == false)
306 if(o != NULL && o->getIgnore() == false)
308 n->changeFrom(pEnv, o, UInt32(ind));
310 else
312 n->activate(pEnv, UInt32(ind));
315 else if(o != NULL && o->getIgnore() == false)
317 o->deactivate(pEnv, UInt32(ind));
320 if(++ind >= StateChunkClass::getNumSlots(cind))
321 ind = 0;
324 if(ind >= StateChunkClass::getNumSlots(cind))
325 ind = 0;
327 for(i = cind; (i < pOld->getMFChunks()->size()) && (i < climit); ++i)
329 StateChunk *o = pOld->getChunk(i);
331 if(o != NULL && o->getIgnore() == false)
333 o->deactivate(pEnv, UInt32(ind));
336 if(++ind >= StateChunkClass::getNumSlots(i))
338 ind = 0;
344 /*! Deactivate the current set of StateChunks, i.e. switch everything back to
345 the default state for the OpenGL state covered by the given chunks.
348 void State::deactivate(DrawEnv *pEnv) const
350 MFChunksType::const_iterator cIt = _mfChunks.begin();
351 MFChunksType::const_iterator cEnd = _mfChunks.end ();
352 Int32 ind = 0;
353 UInt32 cind = osgMin(State::SkipNumChunks,
354 _mfChunks.size32() );
355 UInt32 const climit = _uiCoreGLChunkLimit;
357 OSG_SKIP_IT(cIt, cind);
359 for(; (cIt != cEnd) && (cind < climit); ++cIt, ++cind)
361 if(*cIt != NULL && (*cIt)->getIgnore() == false)
362 (*cIt)->deactivate(pEnv, UInt32(ind));
364 if(++ind >= StateChunkClass::getNumSlots(cind))
365 ind = 0;
369 /*---------------------------- Access -----------------------------------*/
371 /*! Add the given chunk to the State. The index defines the behaviour,
372 especially for multi-slot chunks.
374 If it is set to AutoSlotReplace (the default), addChunk will try to find an
375 empty slot for the chunk class, if it doesn't find one the last one will be
376 replaced with the new entry. This is also useful for chunk classes with
377 only a single slot, as it will override an old instance of the chunk class,
378 which is usually the desired behaviour.
380 If it is set to AutoSlot, the new chunk will only be added to the State if
381 there is a free slot. If there is no free slot true will be returned, in
382 all other cases it will be false.
384 If the index is explicitly given (i.e. it is >=0) the chunk will be set
385 into the given slot, possibly overwriting an old entry. If the index is
386 larger than the number of slots for the given chunck class true will be
387 returned.
390 bool State::addChunk(StateChunk *chunk, Int32 index)
392 if(index > 0 && index > chunk->getClass()->getNumSlots())
394 SWARNING << "addChunk: index "
395 << index
396 << " > Numslots "
397 << chunk->getClass()->getNumSlots()
398 << ", ignored!"
399 << std::endl;
400 return true;
403 UInt32 cindex = chunk->getClassId();
404 UInt32 csize = _mfChunks.size32();
406 const State *pThis = this;
408 // special case: find empty slot automatically
409 if(index == AutoSlot || index == AutoSlotReplace)
411 UInt8 nslots = chunk->getClass()->getNumSlots();
412 UInt8 ci;
414 for(ci = cindex; ci < cindex + nslots && ci < csize; ++ci)
416 if(pThis->_mfChunks[ci] == NULL)
418 break;
422 if(ci >= cindex + nslots) // no free slot found
424 if(index == AutoSlot)
426 SWARNING << "addChunk: no free slot found for "
427 << chunk->getClass()->getName()
428 << " class, ignored!" << std::endl;
429 return true;
431 // use last slot
432 --ci;
435 cindex = ci;
437 else
439 cindex += index;
442 editMField(ChunksFieldMask, _mfChunks);
444 // add the chunk to the state at cindex
445 if(cindex >= csize)
447 UInt32 oldsize = csize;
448 UInt32 newsize = cindex + 1;
450 _mfChunks.resize(newsize);
452 for(UInt32 i = oldsize; i < newsize; i++)
454 _mfChunks.replace(i, NULL);
458 _mfChunks.replace(cindex, chunk);
460 return false;
463 /*! Remove the given chunk from the State. Returns false if successful, true if
464 the chunk wasn't found.
467 bool State::subChunk(StateChunk *chunk)
469 if(chunk == NULL)
470 return true;
472 UInt32 cindex = chunk->getClassId();
473 UInt32 csize = _mfChunks.size32();
475 // special case: find it in the slots
476 UInt8 nslots = chunk->getClass()->getNumSlots();
477 UInt8 ci;
479 const State *pThis = this;
481 for(ci = cindex; ci < cindex + nslots && ci < csize; ci++)
483 if(pThis->_mfChunks[ci] == chunk)
485 break;
489 if(ci >= cindex + nslots) // chunk not found
491 SWARNING << "subChunk: chunk "
492 << chunk
493 << " of class "
494 << chunk->getClass()->getName()
495 << " not found!"
496 << std::endl;
497 return true;
500 editMField(ChunksFieldMask, _mfChunks);
502 // remove the chunk from the state
504 _mfChunks.replace(ci, NULL);
506 return false;
510 /*! Remove the chunk defined by the class id and the slot index from the State.
511 Returns false if successful, true if the chunk wasn't found.
514 bool State::subChunk(UInt32 classid, Int32 index)
516 if(index < 0 || index > StateChunkClass::getNumSlots(classid))
518 SWARNING << "subChunk: index " << index << " > Numslots "
519 << StateChunkClass::getNumSlots(classid)
520 << ", ignored!" << std::endl;
521 return true;
524 const State *pThis = this;
526 if(pThis->_mfChunks[classid + index] == NULL)
527 return true;
529 editMField(ChunksFieldMask, _mfChunks);
531 // remove the chunk from the state
533 _mfChunks.replace(classid + index, NULL);
535 return false;
538 /*! Remove all chunks from the state
541 void State::clearChunks(void)
543 editMField(ChunksFieldMask, _mfChunks);
545 MFChunksType::iterator chunksIt = _mfChunks.begin_nc();
546 MFChunksType::iterator chunksEnd = _mfChunks.end_nc ();
548 for(; chunksIt != chunksEnd; ++chunksIt)
550 _mfChunks.replace(chunksIt, NULL);
554 bool State::isTransparent(void) const
556 Int32 tm = getTransparencyMode();
558 if(tm != Material::TransparencyAutoDetection)
560 return (tm == Material::TransparencyForceTransparent);
563 bool returnValue = false;
565 MFChunksType::const_iterator chunksIt = _mfChunks.begin();
566 MFChunksType::const_iterator chunksEnd = _mfChunks.end();
568 for(; chunksIt != chunksEnd && returnValue == false; ++chunksIt)
570 if((*chunksIt) != NULL)
571 returnValue =(*chunksIt)->isTransparent();
574 return returnValue;
577 /*-------------------------- comparison -----------------------------------*/
580 /*! Calculate the switch cost for the whole state, which is the sum of the
581 switch cost of all its chunks. Right now it's always 0.
584 Real32 State::switchCost(State *OSG_CHECK_ARG(state))
586 return 0;
589 bool State::operator < (const State &other) const
591 return this < &other;
594 /*! Compare the two states. Not implemented yet, always false.
597 bool State::operator == (const State &OSG_CHECK_ARG(other)) const
599 return false;
602 bool State::operator != (const State &other) const
604 return ! (*this == other);
607 void State::resolveLinks(void)
609 clearChunks();
611 Inherited::resolveLinks();