1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SoGLLazyElement Inventor/elements/SoGLLazyElement.h
35 \brief The SoGLLazyElement class is meant to optimize GL rendering.
36
37 \ingroup elements
38
39 This is just a wrap-around implementation for compatibility. It should
40 (hopefully) work in the same way as the Inventor class though.
41 */
42
43 // FIXME: is the above class doc comment still correct? Or do we have
44 // an implementation of this class in the same manner as the other
45 // Inventors now? 20040702 mortene.
46
47 // *************************************************************************
48
49 #include <Inventor/elements/SoGLLazyElement.h>
50
51 #include <cassert>
52
53 #include <Inventor/C/glue/gl.h>
54 #include <Inventor/SbImage.h>
55 #include <Inventor/SoFullPath.h>
56 #include <Inventor/actions/SoGLRenderAction.h>
57 #include <Inventor/bundles/SoMaterialBundle.h>
58 #include <Inventor/elements/SoGLCacheContextElement.h>
59 #include <Inventor/elements/SoGLDisplayList.h>
60 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
61 #include <Inventor/elements/SoGLMultiTextureImageElement.h>
62 #include <Inventor/elements/SoShapeStyleElement.h>
63 #include <Inventor/elements/SoTextureCombineElement.h>
64 #include <Inventor/elements/SoGLShaderProgramElement.h>
65 #include <Inventor/errors/SoDebugError.h>
66 #include <Inventor/errors/SoDebugError.h>
67 #include <Inventor/misc/SoState.h>
68 #include <Inventor/nodes/SoNode.h>
69 #include <Inventor/C/tidbits.h>
70 #include "../../rendering/SoVBO.h"
71 #include <coindefs.h> // COIN_OBSOLETED
72
73 #include "../../shaders/SoGLShaderProgram.h"
74
75 // *************************************************************************
76
77 #define FLAG_FORCE_DIFFUSE 0x0001
78 #define FLAG_DIFFUSE_DEPENDENCY 0x0002
79
80 #if COIN_DEBUG
81 // #define GLLAZY_DEBUG(_x_) (SoDebugError::postInfo(COIN_STUB_FUNC, _x_))
82 #define GLLAZY_DEBUG(x)
83 #else
84 #define GLLAZY_DEBUG(x)
85 #endif
86
87 #ifdef HAVE_CONFIG_H
88 #include <config.h>
89 #endif // HAVE_CONFIG_H
90
91 // Some data and functions to create Bayer dither matrices (used for
92 // screen door transparency)
93 static unsigned char stipple_patterns[64 + 1][32 * 4];
94 static uint32_t two_by_two[] = {0, 2, 3, 1};
95
96 //
97 // Used to generate a matrix twice the size of the input
98 //
99 static void
generate_next_matrix(uint32_t * old,int oldsize,uint32_t * matrix)100 generate_next_matrix(uint32_t * old, int oldsize,
101 uint32_t * matrix)
102 {
103 int i,j;
104 int newsize = oldsize << 1;
105 for (i = 0; i < newsize; i++) {
106 for (j = 0; j < newsize; j++) {
107 matrix[i*newsize+j] = 4 * old[(i%oldsize)*oldsize + (j%oldsize)];
108 matrix[i*newsize+j] += two_by_two[(i/oldsize)*2 + (j/oldsize)];
109 }
110 }
111 }
112
113 //
114 // Creates a matrix by starting with a 2x2 and doubling until size
115 //
116 static void
make_dither_matrix(uint32_t * ptr,int size)117 make_dither_matrix(uint32_t * ptr, int size)
118 {
119 int currsize = 2;
120
121 uint32_t * currmatrix = two_by_two;
122 uint32_t * nextmatrix = NULL;
123 int nextsize;
124
125 while (currsize < size) {
126 nextsize = currsize << 1;
127 nextmatrix = new uint32_t[nextsize*nextsize];
128 generate_next_matrix(currmatrix, currsize, nextmatrix);
129 if (currmatrix != two_by_two) delete[] currmatrix;
130 currmatrix = nextmatrix;
131 currsize = nextsize;
132 }
133 // copy matrix
134 int i;
135 for (i = 0; i < size*size; i++)
136 ptr[i] = currmatrix[i];
137
138 if (currmatrix != two_by_two) delete[] currmatrix;
139 }
140
141 //
142 // Sets a bit bitnr bits from ptr
143 //
144 static void
set_bit(int bitnr,unsigned char * ptr)145 set_bit(int bitnr, unsigned char * ptr)
146 {
147 int byte = bitnr / 8;
148 int bit = bitnr % 8;
149
150 unsigned char mask = (unsigned char) (0x80 >> bit);
151
152 ptr[byte] |= mask;
153 }
154
155 //
156 // Create a bitmap from a 32x32 matrix
157 //
158 static void
create_matrix_bitmap(int intensity,unsigned char * bitmap,uint32_t * matrix,int size)159 create_matrix_bitmap(int intensity, unsigned char * bitmap,
160 uint32_t * matrix, int size)
161 {
162 int cnt = 0;
163 int i,j;
164 for (i = 0; i < 32*4; i++) bitmap[i] = 0;
165 for (i = 0; i < size; i++) {
166 for (j = 0; j < size; j++) {
167 if (matrix[i*size+j] > (uint32_t) intensity) {
168 set_bit(i*32+j, bitmap);
169 cnt++;
170 }
171 }
172 }
173 }
174
175
176 SO_ELEMENT_SOURCE(SoGLLazyElement);
177
178 /*!
179 This static method initializes static data for the
180 SoDiffuseColorElement class.
181 */
182
183 void
initClass()184 SoGLLazyElement::initClass()
185 {
186 SO_ELEMENT_INIT_CLASS(SoGLLazyElement, inherited);
187
188 // create stipple patterns
189 int i;
190 uint32_t matrix[32*32];
191 make_dither_matrix((uint32_t*)matrix, 32);
192 for (i = 0; i <= 64; i++) {
193 int intensity = (32 * 32 * i) / 64 - 1;
194 create_matrix_bitmap((intensity >= 0) ? intensity : 0,
195 stipple_patterns[i], (uint32_t*) matrix, 32);
196 }
197 }
198
199 // ! FIXME: write doc
200
~SoGLLazyElement()201 SoGLLazyElement::~SoGLLazyElement()
202 {
203 }
204
205 //! FIXME: write doc
206 SoGLLazyElement *
getInstance(const SoState * state)207 SoGLLazyElement::getInstance(const SoState *state)
208 {
209 return (SoGLLazyElement*)
210 state->getConstElement(classStackIndex);
211 }
212
213 inline void
sendPackedDiffuse(const uint32_t col) const214 SoGLLazyElement::sendPackedDiffuse(const uint32_t col) const
215 {
216 glColor4ub((unsigned char)((col>>24)&0xff),
217 (unsigned char)((col>>16)&0xff),
218 (unsigned char)((col>>8)&0xff),
219 (unsigned char)(col&0xff));
220 this->glstate.diffuse = col;
221 this->cachebitmask |= DIFFUSE_MASK;
222 }
223
224 inline void
sendLightModel(const int32_t model) const225 SoGLLazyElement::sendLightModel(const int32_t model) const
226 {
227 if (model == PHONG) glEnable(GL_LIGHTING);
228 else glDisable(GL_LIGHTING);
229 this->glstate.lightmodel = model;
230 this->cachebitmask |= LIGHT_MODEL_MASK;
231 }
232
233 inline void
sendFlatshading(const SbBool onoff) const234 SoGLLazyElement::sendFlatshading(const SbBool onoff) const
235 {
236 if (onoff) glShadeModel(GL_FLAT);
237 else glShadeModel(GL_SMOOTH);
238 this->glstate.flatshading = (int32_t) onoff;
239 this->cachebitmask |= SHADE_MODEL_MASK;
240 }
241
242 inline void
sendAlphaTest(int func,float value) const243 SoGLLazyElement::sendAlphaTest(int func, float value) const
244 {
245 if (func) {
246 glAlphaFunc((GLenum) func, value);
247 glEnable(GL_ALPHA_TEST);
248 }
249 else {
250 glDisable(GL_ALPHA_TEST);
251 }
252 this->cachebitmask |= ALPHATEST_MASK;
253 this->glstate.alphatestfunc = func;
254 this->glstate.alphatestvalue = value;
255 }
256
257
258 inline void
sendVertexOrdering(const VertexOrdering ordering) const259 SoGLLazyElement::sendVertexOrdering(const VertexOrdering ordering) const
260 {
261 glFrontFace(ordering == CW ? GL_CW : GL_CCW);
262 this->glstate.vertexordering = (int32_t) ordering;
263 this->cachebitmask |= VERTEXORDERING_MASK;
264 }
265
266 inline void
sendTwosideLighting(const SbBool onoff) const267 SoGLLazyElement::sendTwosideLighting(const SbBool onoff) const
268 {
269 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, onoff ? GL_TRUE : GL_FALSE);
270 this->glstate.twoside = (int32_t) onoff;
271 this->cachebitmask |= TWOSIDE_MASK;
272 }
273
274 inline void
sendBackfaceCulling(const SbBool onoff) const275 SoGLLazyElement::sendBackfaceCulling(const SbBool onoff) const
276 {
277 if (onoff) glEnable(GL_CULL_FACE);
278 else glDisable(GL_CULL_FACE);
279 this->glstate.culling = onoff;
280 this->cachebitmask |= CULLING_MASK;
281 }
282
283 static inline void
send_gl_material(GLenum pname,const SbColor & color)284 send_gl_material(GLenum pname, const SbColor & color)
285 {
286 GLfloat col[4];
287 color.getValue(col[0], col[1], col[2]);
288 col[3] = 1.0f;
289 glMaterialfv(GL_FRONT_AND_BACK, pname, col);
290 }
291
292
293 inline void
sendAmbient(const SbColor & color) const294 SoGLLazyElement::sendAmbient(const SbColor & color) const
295 {
296 send_gl_material(GL_AMBIENT, color);
297 this->glstate.ambient = color;
298 this->cachebitmask |= AMBIENT_MASK;
299 }
300
301 inline void
sendEmissive(const SbColor & color) const302 SoGLLazyElement::sendEmissive(const SbColor & color) const
303 {
304 send_gl_material(GL_EMISSION, color);
305 this->glstate.emissive = color;
306 this->cachebitmask |= EMISSIVE_MASK;
307 }
308
309 inline void
sendSpecular(const SbColor & color) const310 SoGLLazyElement::sendSpecular(const SbColor & color) const
311 {
312 send_gl_material(GL_SPECULAR, color);
313 this->glstate.specular = color;
314 this->cachebitmask |= SPECULAR_MASK;
315 }
316
317 inline void
sendShininess(const float shine) const318 SoGLLazyElement::sendShininess(const float shine) const
319 {
320 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shine*128.0f);
321 this->glstate.shininess = shine;
322 this->cachebitmask |= SHININESS_MASK;
323 }
324
325 inline void
sendTransparency(const int stipplenum) const326 SoGLLazyElement::sendTransparency(const int stipplenum) const
327 {
328 if (stipplenum == 0) {
329 glDisable(GL_POLYGON_STIPPLE);
330 }
331 else {
332 if (this->glstate.stipplenum <= 0) glEnable(GL_POLYGON_STIPPLE);
333 glPolygonStipple(stipple_patterns[stipplenum]);
334 }
335 this->glstate.stipplenum = stipplenum;
336 this->cachebitmask |= TRANSPARENCY_MASK;
337 }
338
339 inline void
enableBlending(const int sfactor,const int dfactor) const340 SoGLLazyElement::enableBlending(const int sfactor, const int dfactor) const
341 {
342 glEnable(GL_BLEND);
343 glBlendFunc((GLenum) sfactor, (GLenum) dfactor);
344 this->glstate.blending = TRUE;
345 this->glstate.blend_sfactor = sfactor;
346 this->glstate.blend_dfactor = dfactor;
347 this->glstate.alpha_blend_sfactor = 0;
348 this->glstate.alpha_blend_dfactor = 0;
349 this->cachebitmask |= BLENDING_MASK;
350 }
351
352 inline void
enableSeparateBlending(const cc_glglue * glue,const int sfactor,const int dfactor,const int alpha_sfactor,const int alpha_dfactor) const353 SoGLLazyElement::enableSeparateBlending(const cc_glglue * glue,
354 const int sfactor,
355 const int dfactor,
356 const int alpha_sfactor,
357 const int alpha_dfactor) const
358 {
359 glEnable(GL_BLEND);
360
361 if (cc_glglue_has_blendfuncseparate(glue)) {
362 cc_glglue_glBlendFuncSeparate(glue, sfactor, dfactor, alpha_sfactor, alpha_dfactor);
363 }
364 else {
365 // fall back to normal blending
366 glBlendFunc((GLenum) sfactor, (GLenum) dfactor);
367 }
368 this->glstate.blending = TRUE;
369 this->glstate.blend_sfactor = sfactor;
370 this->glstate.blend_dfactor = dfactor;
371 this->glstate.alpha_blend_sfactor = alpha_sfactor;
372 this->glstate.alpha_blend_dfactor = alpha_dfactor;
373 this->cachebitmask |= BLENDING_MASK;
374 }
375
376 inline void
disableBlending(void) const377 SoGLLazyElement::disableBlending(void) const
378 {
379 glDisable(GL_BLEND);
380 this->glstate.blending = FALSE;
381 this->cachebitmask |= BLENDING_MASK;
382 }
383
384 void
init(SoState * stateptr)385 SoGLLazyElement::init(SoState * stateptr)
386 {
387 inherited::init(stateptr);
388 this->state = stateptr; // needed to send GL texture
389 this->colorindex = FALSE;
390 this->glstate.ambient.setValue(-1.0f, -1.0f, -1.0f);
391 this->glstate.emissive.setValue(-1.0f, -1.0f, -1.0f);
392 this->glstate.specular.setValue(-1.0f, -1.0f, -1.0f);
393 this->glstate.shininess = -1.0f;
394 this->glstate.lightmodel = -1;
395 this->glstate.blending = -1;
396 this->glstate.blend_sfactor = -1;
397 this->glstate.blend_dfactor = -1;
398 this->glstate.alpha_blend_sfactor = -1;
399 this->glstate.alpha_blend_dfactor = -1;
400 this->glstate.stipplenum = -1;
401 this->glstate.vertexordering = -1;
402 this->glstate.twoside = -1;
403 this->glstate.culling = -1;
404 this->glstate.flatshading = -1;
405 this->glstate.alphatestfunc = -1;
406 this->glstate.alphatestvalue = -1.0f;
407 this->glstate.diffuse = 0xccccccff;
408 this->glstate.diffusenodeid = 0;
409 this->glstate.transpnodeid = 0;
410 this->packedpointer = NULL;
411 // when doing screen door rendering, we need to always supply 0xff as alpha.
412 this->transpmask = (this->coinstate.transptype == SoGLRenderAction::SCREEN_DOOR) ? 0xff : 0x00;
413 this->colorpacker = NULL;
414 this->precachestate = NULL;
415 this->postcachestate = NULL;
416 this->opencacheflags = 0;
417
418 // initialize this here to avoid UMR reports from
419 // Purify. cachebitmask is updated even when there are no open
420 // caches. It is only used (and properly initialized) when recording
421 // a cache though.
422 this->cachebitmask = 0;
423
424 glDisable(GL_POLYGON_STIPPLE);
425
426 GLboolean rgba;
427 glGetBooleanv(GL_RGBA_MODE, &rgba);
428 if (!rgba) this->colorindex = TRUE;
429 else {
430 this->sendPackedDiffuse(0xccccccff);
431 }
432 }
433
434 void
push(SoState * stateptr)435 SoGLLazyElement::push(SoState * stateptr)
436 {
437 inherited::push(stateptr);
438 SoGLLazyElement * prev = (SoGLLazyElement*) this->getNextInStack();
439 this->state = stateptr; // needed to send GL texture
440 this->glstate = prev->glstate;
441 this->colorindex = prev->colorindex;
442 this->transpmask = prev->transpmask;
443 this->colorpacker = prev->colorpacker;
444 this->precachestate = prev->precachestate;
445 this->postcachestate = prev->postcachestate;
446 this->didsetbitmask = prev->didsetbitmask;
447 this->didntsetbitmask = prev->didntsetbitmask;
448 this->cachebitmask = prev->cachebitmask;
449 this->opencacheflags = prev->opencacheflags;
450 }
451
452 void
pop(SoState * stateptr,const SoElement * prevtopelement)453 SoGLLazyElement::pop(SoState *stateptr, const SoElement * prevtopelement)
454 {
455 inherited::pop(stateptr, prevtopelement);
456 SoGLLazyElement * prev = (SoGLLazyElement*) prevtopelement;
457 this->glstate = prev->glstate;
458 this->colorindex = prev->colorindex;
459 this->didsetbitmask = prev->didsetbitmask;
460 this->didntsetbitmask = prev->didntsetbitmask;
461 this->cachebitmask = prev->cachebitmask;
462 this->opencacheflags = prev->opencacheflags;
463 }
464
465 //! FIXME: write doc
466
467 void
sendAllMaterial(SoState * state)468 SoGLLazyElement::sendAllMaterial(SoState * state)
469 {
470 SoGLLazyElement * elem = getInstance(state);
471 elem->send(state, ALL_MASK);
472 }
473
474 //! FIXME: write doc
475
476 void
sendNoMaterial(SoState * state)477 SoGLLazyElement::sendNoMaterial(SoState * state)
478 {
479 SoGLLazyElement * elem = getInstance(state);
480 elem->send(state, NO_COLOR_MASK);
481 }
482
483 //! FIXME: write doc
484
485 void
sendOnlyDiffuseColor(SoState * state)486 SoGLLazyElement::sendOnlyDiffuseColor(SoState * state)
487 {
488 SoGLLazyElement * elem = getInstance(state);
489 elem->send(state, DIFFUSE_ONLY_MASK);
490 }
491
492 //! FIXME: write doc
493
494 void
sendDiffuseByIndex(const int index) const495 SoGLLazyElement::sendDiffuseByIndex(const int index) const
496 {
497 int safeindex = index;
498 #if COIN_DEBUG
499 if (index < 0 || index >= this->coinstate.numdiffuse) {
500 static int first = 1;
501 if (first) {
502 SoFullPath * path = (SoFullPath*) this->state->getAction()->getCurPath();
503 SoNode * tail = path->getTail();
504 SbName name = tail->getName();
505 SoDebugError::postWarning("SoGLLazyElement::sendDiffuseByIndex",
506 "index %d out of bounds [0, %d] in node %p: %s "
507 "(this warning will only be printed once, but there "
508 "might be more errors)",
509 index,
510 this->coinstate.numdiffuse-1,
511 tail, name != SbName::empty() ? name.getString() : "<noname>");
512 first = 0;
513 }
514
515 safeindex = SbClamp((long) index, (long) 0, (long) (this->coinstate.numdiffuse-1));
516 }
517 #endif // COIN_DEBUG
518
519 if (this->colorindex) {
520 glIndexi((GLint)this->coinstate.colorindexarray[safeindex]);
521 }
522 else {
523 uint32_t col = this->packedpointer[safeindex] | this->transpmask;
524 // this test is really not necessary. SoMaterialBundle does the
525 // same test. We also need to send the color here to work around
526 // an nVIDIA bug
527 // if (col != this->glstate.diffuse)
528 this->sendPackedDiffuse(col);
529 }
530 }
531
532 //! FIXME: write doc
533
534 SbBool
isColorIndex(SoState * state)535 SoGLLazyElement::isColorIndex(SoState * state)
536 {
537 SoGLLazyElement * elem = getInstance(state);
538 return elem->colorindex;
539 }
540
541 //! FIXME: write doc
542
543 void
send(const SoState * stateptr,uint32_t mask) const544 SoGLLazyElement::send(const SoState * stateptr, uint32_t mask) const
545 {
546 if (this->colorpacker) {
547 if (!this->colorpacker->diffuseMatch(this->coinstate.diffusenodeid) ||
548 !this->colorpacker->transpMatch(this->coinstate.transpnodeid)) {
549 this->packColors(this->colorpacker);
550 }
551 this->packedpointer = this->colorpacker->getPackedColors();
552 }
553 else this->packedpointer = this->coinstate.packedarray;
554
555 assert(this->packedpointer);
556
557 int stipplenum;
558
559 for (int i = 0; (i < LAZYCASES_LAST)&&mask; i++, mask>>=1) {
560 if (mask&1) {
561 switch (i) {
562 case LIGHT_MODEL_CASE:
563 if (this->coinstate.lightmodel != this->glstate.lightmodel) {
564 SoGLShaderProgram * prog = SoGLShaderProgramElement::get((SoState*) stateptr);
565 if (prog) prog->updateCoinParameter((SoState*)stateptr, SbName("coin_light_model"), this->coinstate.lightmodel);
566 this->sendLightModel(this->coinstate.lightmodel);
567 }
568 break;
569 case DIFFUSE_CASE:
570 if (this->precachestate) {
571 // we are currently building a cache. Check if we're using
572 // colors from a material node outside the cache.
573 if ((this->precachestate->diffusenodeid == this->coinstate.diffusenodeid) ||
574 (this->precachestate->transpnodeid == this->coinstate.transpnodeid)) {
575 this->opencacheflags |= FLAG_DIFFUSE_DEPENDENCY;
576 }
577 }
578 if (this->opencacheflags & FLAG_FORCE_DIFFUSE) {
579 // we always send the first diffuse color for the first
580 // material in an open cache
581 if (this->colorindex) {
582 glIndexi((GLint)this->coinstate.colorindexarray[0]);
583 }
584 else {
585 this->sendPackedDiffuse(this->packedpointer[0]|this->transpmask);
586 }
587 this->opencacheflags &= ~FLAG_FORCE_DIFFUSE;
588 }
589 else {
590 this->sendDiffuseByIndex(0);
591 }
592 break;
593 case AMBIENT_CASE:
594 if (this->coinstate.ambient != this->glstate.ambient) {
595 this->sendAmbient(this->coinstate.ambient);
596 }
597 break;
598 case SPECULAR_CASE:
599 if (this->coinstate.specular != this->glstate.specular) {
600 this->sendSpecular(this->coinstate.specular);
601 }
602 break;
603 case EMISSIVE_CASE:
604 if (this->coinstate.emissive != this->glstate.emissive) {
605 this->sendEmissive(this->coinstate.emissive);
606 }
607 break;
608 case SHININESS_CASE:
609 if (this->coinstate.shininess != this->glstate.shininess) {
610 this->sendShininess(this->coinstate.shininess);
611 }
612 break;
613 case BLENDING_CASE:
614 if (this->coinstate.blending) {
615 if (this->glstate.blending != this->coinstate.blending ||
616 this->coinstate.blend_sfactor != this->glstate.blend_sfactor ||
617 this->coinstate.blend_dfactor != this->glstate.blend_dfactor ||
618 this->coinstate.alpha_blend_sfactor != this->glstate.alpha_blend_sfactor ||
619 this->coinstate.alpha_blend_dfactor != this->glstate.alpha_blend_dfactor) {
620 if ((this->coinstate.alpha_blend_sfactor != 0) &&
621 (this->coinstate.alpha_blend_dfactor != 0)) {
622 this->enableSeparateBlending(cc_glglue_instance(SoGLCacheContextElement::get((SoState*)stateptr)),
623 this->coinstate.blend_sfactor,
624 this->coinstate.blend_dfactor,
625 this->coinstate.alpha_blend_sfactor,
626 this->coinstate.alpha_blend_dfactor);
627 }
628 else {
629 this->enableBlending(this->coinstate.blend_sfactor, this->coinstate.blend_dfactor);
630 }
631 }
632 }
633 else {
634 if (this->coinstate.blending != this->glstate.blending) {
635 this->disableBlending();
636 }
637 }
638 break;
639 case TRANSPARENCY_CASE:
640 stipplenum =
641 this->coinstate.transptype == SoGLRenderAction::SCREEN_DOOR ?
642 this->coinstate.stipplenum : 0;
643
644 if (stipplenum != this->glstate.stipplenum) {
645 this->sendTransparency(stipplenum);
646 }
647 break;
648 case VERTEXORDERING_CASE:
649 if (this->glstate.vertexordering != this->coinstate.vertexordering) {
650 this->sendVertexOrdering(this->coinstate.vertexordering);
651 }
652 break;
653 case CULLING_CASE:
654 if (this->glstate.culling != this->coinstate.culling) {
655 this->sendBackfaceCulling(this->coinstate.culling);
656 }
657 break;
658 case TWOSIDE_CASE:
659 if (this->glstate.twoside != this->coinstate.twoside) {
660 SoGLShaderProgram * prog = SoGLShaderProgramElement::get((SoState*) stateptr);
661 if (prog) prog->updateCoinParameter((SoState*)stateptr, SbName("coin_two_sided_lighting"), this->coinstate.twoside);
662 this->sendTwosideLighting(this->coinstate.twoside);
663 }
664 break;
665 case SHADE_MODEL_CASE:
666 if (this->glstate.flatshading != this->coinstate.flatshading) {
667 this->sendFlatshading(this->coinstate.flatshading);
668 }
669 break;
670 case ALPHATEST_CASE:
671 if (this->glstate.alphatestfunc != (int32_t) this->coinstate.alphatestfunc ||
672 this->glstate.alphatestvalue != this->coinstate.alphatestvalue) {
673 this->sendAlphaTest(this->coinstate.alphatestfunc, this->coinstate.alphatestvalue);
674 }
675 break;
676 }
677
678 }
679 }
680 }
681
682 //! FIXME: write doc
683
684 void
sendVPPacked(SoState * COIN_UNUSED_ARG (stateptr),const unsigned char * COIN_UNUSED_ARG (pcolor))685 SoGLLazyElement::sendVPPacked(SoState* COIN_UNUSED_ARG(stateptr), const unsigned char* COIN_UNUSED_ARG(pcolor))
686 {
687 assert(0 && "Not implemented yet. Provided for API compatibility.");
688 }
689
690 /*!
691 Reset element GL state (set state to invalid). Use this method to
692 notify this element when you use your own GL code that changes the
693 OpenGL state.
694 */
695 void
reset(SoState * stateptr,uint32_t mask) const696 SoGLLazyElement::reset(SoState * stateptr, uint32_t mask) const
697 {
698 SoGLLazyElement * elem = getInstance(stateptr);
699
700 if (stateptr->isCacheOpen()) {
701 elem->cachebitmask |= mask;
702 }
703
704 for (int i = 0; (i < LAZYCASES_LAST)&&mask; i++, mask>>=1) {
705 if (mask&1) {
706 switch (i) {
707 case LIGHT_MODEL_CASE:
708 elem->glstate.lightmodel = -1;
709 break;
710 case DIFFUSE_CASE:
711 elem->sendPackedDiffuse(0xccccccff);
712 break;
713 case AMBIENT_CASE:
714 elem->glstate.ambient = SbColor(-1.f, -1.0f, -1.0f);
715 break;
716 case SPECULAR_CASE:
717 elem->glstate.specular = SbColor(-1.0f, -1.0f, -1.0f);
718 break;
719 case EMISSIVE_CASE:
720 elem->glstate.emissive = SbColor(-1.0f, -1.0f, -1.0f);
721 break;
722 case SHININESS_CASE:
723 elem->glstate.shininess = -1.0f;
724 break;
725 case BLENDING_CASE:
726 elem->glstate.blending = -1;
727 elem->glstate.blend_sfactor = -1;
728 elem->glstate.blend_dfactor = -1;
729 elem->glstate.alpha_blend_sfactor = -1;
730 elem->glstate.alpha_blend_dfactor = -1;
731 break;
732 case TRANSPARENCY_CASE:
733 elem->glstate.stipplenum = -1;
734 break;
735 case VERTEXORDERING_CASE:
736 elem->glstate.vertexordering = -1;
737 break;
738 case CULLING_CASE:
739 elem->glstate.culling = -1;
740 break;
741 case TWOSIDE_CASE:
742 elem->glstate.twoside = -1;
743 break;
744 case SHADE_MODEL_CASE:
745 elem->glstate.flatshading = -1;
746 break;
747 case ALPHATEST_CASE:
748 elem->glstate.alphatestfunc = -1;
749 elem->glstate.alphatestvalue = -1.0f;
750 break;
751 }
752 }
753 }
754 }
755
756 void
sendPackedDiffuse(SoState * state,const uint32_t diffuse)757 SoGLLazyElement::sendPackedDiffuse(SoState * state, const uint32_t diffuse)
758 {
759 SbBool cacheopen = state->isCacheOpen();
760 SoGLLazyElement * elem = getInstance(state);
761 if (elem->glstate.diffuse != diffuse) {
762 elem->sendPackedDiffuse(diffuse);
763 if (cacheopen) elem->lazyDidSet(DIFFUSE_MASK|TRANSPARENCY_MASK);
764 }
765 else if (cacheopen) {
766 elem->lazyDidntSet(DIFFUSE_MASK|TRANSPARENCY_MASK);
767 }
768 }
769
770 void
sendLightModel(SoState * state,const int32_t model)771 SoGLLazyElement::sendLightModel(SoState * state, const int32_t model)
772 {
773 SbBool cacheopen = state->isCacheOpen();
774 SoGLLazyElement * elem = getInstance(state);
775 if (elem->glstate.lightmodel != model) {
776 elem->sendLightModel(model);
777 if (cacheopen) elem->lazyDidSet(LIGHT_MODEL_MASK);
778 }
779 else if (cacheopen) {
780 elem->lazyDidntSet(LIGHT_MODEL_MASK);
781 }
782 }
783
784 void
sendFlatshading(SoState * state,const SbBool onoff)785 SoGLLazyElement::sendFlatshading(SoState * state, const SbBool onoff)
786 {
787 SbBool cacheopen = state->isCacheOpen();
788 SoGLLazyElement * elem = getInstance(state);
789 if (elem->glstate.flatshading != onoff) {
790 elem->sendFlatshading(onoff);
791 if (cacheopen) elem->lazyDidSet(SHADE_MODEL_MASK);
792 }
793 else if (cacheopen) {
794 elem->lazyDidntSet(SHADE_MODEL_MASK);
795 }
796 }
797
798 void
sendVertexOrdering(SoState * state,const VertexOrdering ordering)799 SoGLLazyElement::sendVertexOrdering(SoState * state, const VertexOrdering ordering)
800 {
801 SbBool cacheopen = state->isCacheOpen();
802 SoGLLazyElement * elem = getInstance(state);
803 if (elem->glstate.vertexordering != (int32_t) ordering) {
804 elem->sendVertexOrdering(ordering);
805 if (cacheopen) elem->lazyDidSet(VERTEXORDERING_MASK);
806 }
807 else if (cacheopen) {
808 elem->lazyDidntSet(VERTEXORDERING_MASK);
809 }
810 }
811
812 void
sendTwosideLighting(SoState * state,const SbBool onoff)813 SoGLLazyElement::sendTwosideLighting(SoState * state, const SbBool onoff)
814 {
815 SbBool cacheopen = state->isCacheOpen();
816 SoGLLazyElement * elem = getInstance(state);
817 if (elem->glstate.twoside != (int32_t) onoff) {
818 elem->sendTwosideLighting(onoff);
819 if (cacheopen) elem->lazyDidSet(TWOSIDE_MASK);
820 }
821 else if (cacheopen) {
822 elem->lazyDidntSet(TWOSIDE_MASK);
823 }
824 }
825
826 void
sendBackfaceCulling(SoState * state,const SbBool onoff)827 SoGLLazyElement::sendBackfaceCulling(SoState * state, const SbBool onoff)
828 {
829 SbBool cacheopen = state->isCacheOpen();
830 SoGLLazyElement * elem = getInstance(state);
831 if (elem->glstate.culling != (int32_t) onoff) {
832 elem->sendBackfaceCulling(onoff);
833 if (cacheopen) elem->lazyDidSet(CULLING_MASK);
834 }
835 else if (cacheopen) {
836 elem->lazyDidntSet(CULLING_MASK);
837 }
838 }
839
840 void
setDiffuseElt(SoNode * node,int32_t numcolors,const SbColor * colors,SoColorPacker * packer)841 SoGLLazyElement::setDiffuseElt(SoNode * node, int32_t numcolors,
842 const SbColor * colors, SoColorPacker * packer)
843 {
844 inherited::setDiffuseElt(node, numcolors, colors, packer);
845 this->colorpacker = packer;
846 }
847
848 void
setPackedElt(SoNode * node,int32_t numcolors,const uint32_t * colors,const SbBool packedtransparency)849 SoGLLazyElement::setPackedElt(SoNode * node, int32_t numcolors,
850 const uint32_t * colors, const SbBool packedtransparency)
851 {
852 inherited::setPackedElt(node, numcolors, colors, packedtransparency);
853 this->colorpacker = NULL;
854 this->packedpointer = colors;
855 }
856
857 void
setColorIndexElt(SoNode * node,int32_t numindices,const int32_t * indices)858 SoGLLazyElement::setColorIndexElt(SoNode * node, int32_t numindices,
859 const int32_t * indices)
860 {
861 inherited::setColorIndexElt(node, numindices, indices);
862 }
863
864 void
setTranspElt(SoNode * node,int32_t numtransp,const float * transp,SoColorPacker * packer)865 SoGLLazyElement::setTranspElt(SoNode * node, int32_t numtransp,
866 const float * transp, SoColorPacker * packer)
867 {
868 inherited::setTranspElt(node, numtransp, transp, packer);
869 this->colorpacker = packer;
870 }
871
872
873 void
setTranspTypeElt(int32_t type)874 SoGLLazyElement::setTranspTypeElt(int32_t type)
875 {
876 inherited::setTranspTypeElt(type);
877 this->transpmask = type == SoGLRenderAction::SCREEN_DOOR ? 0xff : 0x00;
878 }
879
880 void
setAmbientElt(const SbColor * color)881 SoGLLazyElement::setAmbientElt(const SbColor* color)
882 {
883 inherited::setAmbientElt(color);
884 }
885
886 void
setEmissiveElt(const SbColor * color)887 SoGLLazyElement::setEmissiveElt(const SbColor* color)
888 {
889 inherited::setEmissiveElt(color);
890 }
891
892 void
setSpecularElt(const SbColor * color)893 SoGLLazyElement::setSpecularElt(const SbColor* color)
894 {
895 inherited::setSpecularElt(color);
896 }
897
898 void
setShininessElt(float value)899 SoGLLazyElement::setShininessElt(float value)
900 {
901 inherited::setShininessElt(value);
902 }
903
904 void
setColorMaterialElt(SbBool value)905 SoGLLazyElement::setColorMaterialElt(SbBool value)
906 {
907 inherited::setColorMaterialElt(value);
908 }
909
910 void
enableBlendingElt(int sfactor,int dfactor,int alpha_sfactor,int alpha_dfactor)911 SoGLLazyElement::enableBlendingElt(int sfactor, int dfactor, int alpha_sfactor, int alpha_dfactor)
912 {
913 inherited::enableBlendingElt(sfactor, dfactor, alpha_sfactor, alpha_dfactor);
914 }
915
916 void
disableBlendingElt(void)917 SoGLLazyElement::disableBlendingElt(void)
918 {
919 inherited::disableBlendingElt();
920 }
921
922 void
setLightModelElt(SoState * stateptr,int32_t model)923 SoGLLazyElement::setLightModelElt(SoState * stateptr, int32_t model)
924 {
925 inherited::setLightModelElt(stateptr, model);
926 }
927
928 void
setMaterialElt(SoNode * node,uint32_t bitmask,SoColorPacker * packer,const SbColor * diffuse,const int numdiffuse,const float * transp,const int numtransp,const SbColor & ambient,const SbColor & emissive,const SbColor & specular,const float shininess,const SbBool istransparent)929 SoGLLazyElement::setMaterialElt(SoNode * node, uint32_t bitmask,
930 SoColorPacker * packer,
931 const SbColor * diffuse, const int numdiffuse,
932 const float * transp, const int numtransp,
933 const SbColor & ambient,
934 const SbColor & emissive,
935 const SbColor & specular,
936 const float shininess,
937 const SbBool istransparent)
938 {
939 inherited::setMaterialElt(node, bitmask,
940 packer, diffuse, numdiffuse,
941 transp, numtransp, ambient,
942 emissive, specular, shininess, istransparent);
943 this->colorpacker = packer;
944 }
945
946 void
setVertexOrderingElt(VertexOrdering ordering)947 SoGLLazyElement::setVertexOrderingElt(VertexOrdering ordering)
948 {
949 inherited::setVertexOrderingElt(ordering);
950 }
951
952 void
setBackfaceCullingElt(SbBool onoff)953 SoGLLazyElement::setBackfaceCullingElt(SbBool onoff)
954 {
955 inherited::setBackfaceCullingElt(onoff);
956 }
957
958 void
setTwosideLightingElt(SbBool onoff)959 SoGLLazyElement::setTwosideLightingElt(SbBool onoff)
960 {
961 inherited::setTwosideLightingElt(onoff);
962 }
963
964 void
setShadeModelElt(SbBool flatshading)965 SoGLLazyElement::setShadeModelElt(SbBool flatshading)
966 {
967 inherited::setShadeModelElt(flatshading);
968 }
969
970 void
setAlphaTestElt(int func,float value)971 SoGLLazyElement::setAlphaTestElt(int func, float value)
972 {
973 inherited::setAlphaTestElt(func, value);
974 }
975
976 void
packColors(SoColorPacker * packer) const977 SoGLLazyElement::packColors(SoColorPacker * packer) const
978 {
979 const int n = this->coinstate.numdiffuse;
980 const SbColor * diffuse = this->coinstate.diffusearray;
981 const int numtransp = this->coinstate.numtransp;
982 const float * transp = this->coinstate.transparray;
983
984 if (packer->getSize() < n) packer->reallocate(n);
985 uint32_t * ptr = packer->getPackedColors();
986
987 int ti = 0;
988
989 for (int i = 0; i < n; i++) {
990 ptr[i] = diffuse[i].getPackedValue(transp[ti]);
991 if (ti < numtransp-1) ti++;
992 }
993
994 packer->setNodeIds(this->coinstate.diffusenodeid,
995 this->coinstate.transpnodeid);
996 }
997
998 void
beginCaching(SoState * state,GLState * prestate,GLState * poststate)999 SoGLLazyElement::beginCaching(SoState * state, GLState * prestate,
1000 GLState * poststate)
1001 {
1002 SoGLLazyElement * elem = getInstance(state);
1003 elem->send(state, ALL_MASK); // send lazy state before starting to build cache
1004 *prestate = elem->glstate; // copy current GL state
1005 prestate->diffusenodeid = elem->coinstate.diffusenodeid;
1006 prestate->transpnodeid = elem->coinstate.transpnodeid;
1007 elem->precachestate = prestate;
1008 elem->postcachestate = poststate;
1009 elem->precachestate->cachebitmask = 0;
1010 elem->postcachestate->cachebitmask = 0;
1011 elem->didsetbitmask = 0;
1012 elem->didntsetbitmask = 0;
1013 elem->cachebitmask = 0;
1014 elem->opencacheflags = 0;
1015 }
1016
1017 void
endCaching(SoState * state)1018 SoGLLazyElement::endCaching(SoState * state)
1019 {
1020 SoGLLazyElement * elem = getInstance(state);
1021
1022 *elem->postcachestate = elem->glstate;
1023 elem->postcachestate->cachebitmask = elem->cachebitmask;
1024 elem->precachestate->cachebitmask = elem->didntsetbitmask;
1025
1026 // unset diffuse mask since it's used by the dependency test
1027 elem->precachestate->cachebitmask &= ~DIFFUSE_MASK;
1028
1029 // set diffuse mask if this cache depends on a material outside the
1030 // cache.
1031 if (elem->opencacheflags & FLAG_DIFFUSE_DEPENDENCY) {
1032 elem->precachestate->cachebitmask |= DIFFUSE_MASK;
1033 }
1034
1035 elem->precachestate = NULL;
1036 elem->postcachestate = NULL;
1037 elem->opencacheflags = 0;
1038 }
1039
1040 void
postCacheCall(const SoState * state,const GLState * poststate)1041 SoGLLazyElement::postCacheCall(const SoState * state, const GLState * poststate)
1042 {
1043 SoGLLazyElement * elem = getInstance(state);
1044 uint32_t mask = poststate->cachebitmask;
1045
1046 for (int i = 0; (i < LAZYCASES_LAST)&&mask; i++, mask>>=1) {
1047 if (mask&1) {
1048 switch (i) {
1049 case LIGHT_MODEL_CASE:
1050 elem->glstate.lightmodel = poststate->lightmodel;
1051 break;
1052 case DIFFUSE_CASE:
1053 elem->glstate.diffuse = poststate->diffuse;
1054 break;
1055 case AMBIENT_CASE:
1056 elem->glstate.ambient = poststate->ambient;
1057 break;
1058 case SPECULAR_CASE:
1059 elem->glstate.specular = poststate->specular;
1060 break;
1061 case EMISSIVE_CASE:
1062 elem->glstate.emissive = poststate->emissive;
1063 break;
1064 case SHININESS_CASE:
1065 elem->glstate.shininess = poststate->shininess;
1066 break;
1067 case BLENDING_CASE:
1068 elem->glstate.blending = poststate->blending;
1069 elem->glstate.blend_sfactor = poststate->blend_sfactor;
1070 elem->glstate.blend_dfactor = poststate->blend_dfactor;
1071 elem->glstate.alpha_blend_sfactor = poststate->alpha_blend_sfactor;
1072 elem->glstate.alpha_blend_dfactor = poststate->alpha_blend_dfactor;
1073 break;
1074 case TRANSPARENCY_CASE:
1075 elem->glstate.stipplenum = poststate->stipplenum;
1076 break;
1077 case VERTEXORDERING_CASE:
1078 elem->glstate.vertexordering = poststate->vertexordering;
1079 break;
1080 case CULLING_CASE:
1081 elem->glstate.culling = poststate->culling;
1082 break;
1083 case TWOSIDE_CASE:
1084 elem->glstate.twoside = poststate->twoside;
1085 break;
1086 case SHADE_MODEL_CASE:
1087 elem->glstate.flatshading = poststate->flatshading;
1088 break;
1089 case ALPHATEST_CASE:
1090 elem->glstate.alphatestfunc = poststate->alphatestfunc;
1091 elem->glstate.alphatestvalue = poststate->alphatestvalue;
1092 break;
1093 }
1094 }
1095 }
1096 }
1097
1098 SbBool
preCacheCall(const SoState * state,const GLState * prestate)1099 SoGLLazyElement::preCacheCall(const SoState * state, const GLState * prestate)
1100 {
1101 SoGLLazyElement * elem = getInstance(state);
1102
1103 struct CoinState & curr = elem->coinstate;
1104 uint32_t mask = prestate->cachebitmask;
1105
1106 for (int i = 0; (i < LAZYCASES_LAST)&&mask; i++, mask>>=1) {
1107 if (mask&1) {
1108 switch (i) {
1109 case LIGHT_MODEL_CASE:
1110 if (curr.lightmodel != prestate->lightmodel) {
1111 GLLAZY_DEBUG("light model failed");
1112 return FALSE;
1113 }
1114 break;
1115 case DIFFUSE_CASE:
1116 // this is a special case, since we can have multiple diffuse
1117 // and transparency values. Check the node ids.
1118 if ((prestate->diffusenodeid != curr.diffusenodeid) ||
1119 (prestate->transpnodeid != curr.transpnodeid)) {
1120 GLLAZY_DEBUG("material dependency failed");
1121 return FALSE;
1122 }
1123 break;
1124 case AMBIENT_CASE:
1125 if (curr.ambient != prestate->ambient) {
1126 GLLAZY_DEBUG("ambient failed");
1127 return FALSE;
1128 }
1129 break;
1130 case SPECULAR_CASE:
1131 if (curr.specular != prestate->specular) {
1132 GLLAZY_DEBUG("specular failed");
1133 return FALSE;
1134 }
1135 break;
1136 case EMISSIVE_CASE:
1137 if (curr.emissive != prestate->emissive) {
1138 GLLAZY_DEBUG("emissive failed");
1139 return FALSE;
1140 }
1141 break;
1142 case SHININESS_CASE:
1143 if (curr.shininess != prestate->shininess) {
1144 GLLAZY_DEBUG("shininess failed");
1145 return FALSE;
1146 }
1147 break;
1148 case BLENDING_CASE:
1149 if (curr.blending != prestate->blending) {
1150 GLLAZY_DEBUG("blending failed");
1151 return FALSE;
1152 }
1153 if (prestate->blending) {
1154 if (curr.blend_sfactor != prestate->blend_sfactor ||
1155 curr.blend_dfactor != prestate->blend_dfactor ||
1156 curr.alpha_blend_sfactor != prestate->alpha_blend_sfactor ||
1157 curr.alpha_blend_dfactor != prestate->alpha_blend_dfactor) {
1158 GLLAZY_DEBUG("blending failed");
1159 return FALSE;
1160 }
1161 }
1162 break;
1163 case TRANSPARENCY_CASE:
1164 if (curr.stipplenum != prestate->stipplenum) {
1165 GLLAZY_DEBUG("transparency failed");
1166 return FALSE;
1167 }
1168 break;
1169 case VERTEXORDERING_CASE:
1170 if (curr.vertexordering != prestate->vertexordering) {
1171 GLLAZY_DEBUG("vertexordering failed");
1172 return FALSE;
1173 }
1174 break;
1175 case CULLING_CASE:
1176 if (curr.culling != prestate->culling) {
1177 GLLAZY_DEBUG("culling failed");
1178 return FALSE;
1179 }
1180 break;
1181 case TWOSIDE_CASE:
1182 if (curr.twoside != prestate->twoside) {
1183 GLLAZY_DEBUG("twoside failed");
1184 return FALSE;
1185 }
1186 break;
1187 case SHADE_MODEL_CASE:
1188 if (curr.flatshading != prestate->flatshading) {
1189 GLLAZY_DEBUG("shade model failed");
1190 return FALSE;
1191 }
1192 break;
1193 case ALPHATEST_CASE:
1194 if (curr.alphatestfunc != prestate->alphatestfunc ||
1195 curr.alphatestvalue != prestate->alphatestvalue) {
1196 GLLAZY_DEBUG("alphatest failed");
1197 return FALSE;
1198 }
1199 break;
1200 }
1201 }
1202 }
1203 return TRUE;
1204 }
1205
1206
1207 void
lazyDidSet(uint32_t mask)1208 SoGLLazyElement::lazyDidSet(uint32_t mask)
1209 {
1210 if (mask & DIFFUSE_MASK) {
1211 if (!(this->didsetbitmask & DIFFUSE_MASK)) {
1212 // to be safe, always send first diffuse when a cache is open
1213 this->opencacheflags |= FLAG_FORCE_DIFFUSE;
1214 }
1215 }
1216 this->didsetbitmask |= mask;
1217 }
1218
1219 void
lazyDidntSet(uint32_t mask)1220 SoGLLazyElement::lazyDidntSet(uint32_t mask)
1221 {
1222 if (mask & DIFFUSE_MASK) {
1223 if (!(this->didsetbitmask & DIFFUSE_MASK)) {
1224 // to be safe, always send first diffuse when a cache is open
1225 this->didsetbitmask |= DIFFUSE_MASK;
1226 this->opencacheflags = FLAG_FORCE_DIFFUSE;
1227 }
1228 }
1229 this->didntsetbitmask |= mask&(~this->didsetbitmask);
1230 }
1231
1232 void
updateColorVBO(SoVBO * vbo)1233 SoGLLazyElement::updateColorVBO(SoVBO * vbo)
1234 {
1235 if (this->colorpacker) {
1236 SbUniqueId maxid = this->colorpacker->getDiffuseId();
1237 SbUniqueId tid = this->colorpacker->getTranspId();
1238 if (tid > maxid) {
1239 maxid = tid;
1240 }
1241 SbUniqueId vboid = vbo->getBufferDataId();
1242 if (vboid != maxid) {
1243 const int n = this->coinstate.numdiffuse;
1244 // need to update the VBO
1245 const uint32_t * src = this->colorpacker->getPackedColors();
1246 if (coin_host_get_endianness() == COIN_HOST_IS_BIGENDIAN) {
1247 vbo->setBufferData(src, n * sizeof(uint32_t),
1248 maxid);
1249 }
1250 else {
1251 uint32_t * dst = (uint32_t*)
1252 vbo->allocBufferData(n * sizeof(uint32_t),
1253 maxid);
1254 for (int i = 0; i < n; i++) {
1255 uint32_t tmp = src[i];
1256 dst[i] =
1257 (tmp << 24) |
1258 ((tmp & 0xff00) << 8) |
1259 ((tmp & 0xff0000) >> 8) |
1260 (tmp >> 24);
1261 }
1262 }
1263 }
1264 }
1265 }
1266
1267 /*!
1268 Merge cache info from a child cache (when doing nested caching)
1269 into the current cache.
1270 */
1271 void
mergeCacheInfo(SoState * state,SoGLLazyElement::GLState * childprestate,SoGLLazyElement::GLState * childpoststate)1272 SoGLLazyElement::mergeCacheInfo(SoState * state,
1273 SoGLLazyElement::GLState * childprestate,
1274 SoGLLazyElement::GLState * childpoststate)
1275 {
1276 SoGLLazyElement * elt = SoGLLazyElement::getInstance(state);
1277
1278 // just add pre-dependencies from child cache
1279 elt->lazyDidntSet(childprestate->cachebitmask);
1280
1281 // update current element's didsetbitmask
1282 elt->lazyDidSet(childpoststate->cachebitmask);
1283
1284 // also update cachebitmask so that the current cache knows about the changes
1285 // done by the child cache
1286 elt->cachebitmask |= childpoststate->cachebitmask;
1287 }
1288
1289 #undef FLAG_FORCE_DIFFUSE
1290 #undef FLAG_DIFFUSE_DEPENDENCY
1291 #undef GLLAZY_DEBUG
1292