Skip to content

Commit 4f5058b

Browse files
committed
rendering: separate primitive triangle handling from shape GL gating
Keep the installed shouldGLRender() contract and preserve the historical LegacyGL order. Source-private begin/sort/finish helpers let direct-rendered SoText2 skip only primitive-cache triangle sorting while retaining common transparency and late BIGIMAGE, bump-map, and vertex-array handling.
1 parent 75a020f commit 4f5058b

6 files changed

Lines changed: 449 additions & 73 deletions

File tree

include/Inventor/nodes/SoShape.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class COIN_DLL_API SoShape : public SoNode {
166166
void rayPickBoundingBox(SoRayPickAction * action);
167167
friend class soshape_primdata; // internal class
168168
friend class so_generate_prim_private; // a very private class
169+
friend class SoShapeGLRender;
169170
};
170171

171172
#endif // !COIN_SOSHAPE_H

src/shapenodes/SoShape.cpp

Lines changed: 110 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class SoVBO;
5151
#include <Inventor/elements/SoVertexAttributeElement.h>
5252

5353
#include "elements/SoLazyElementP.h"
54+
#include "shapenodes/SoShapeGLRenderP.h"
5455

5556
#include <cstring>
5657
#include <cstdlib>
@@ -883,76 +884,112 @@ SoShape::getComplexityValue(SoAction * action)
883884
*/
884885
SbBool
885886
SoShape::shouldGLRender(SoGLRenderAction * action)
887+
{
888+
SoShapeGLRenderContext context;
889+
const SoShapeGLRenderDecision decision =
890+
SoShapeGLRender::begin(this, action, context);
891+
if (decision == SoShapeGLRenderDecision::RenderShape) return TRUE;
892+
if (decision == SoShapeGLRenderDecision::Stop) return FALSE;
893+
if (!SoShapeGLRender::sortTriangles(this, action, context)) return FALSE;
894+
return SoShapeGLRender::finish(this, action, context);
895+
}
896+
897+
SoShapeGLRenderDecision
898+
SoShapeGLRender::begin(SoShape * shape, SoGLRenderAction * action,
899+
SoShapeGLRenderContext & context)
886900
{
887901
SoState * state = action->getState();
888902

889903
const SoShapeStyleElement * shapestyle = SoShapeStyleElement::get(state);
890-
unsigned int shapestyleflags = shapestyle->getFlags();
904+
const unsigned int shapestyleflags = shapestyle->getFlags();
905+
context.shapeStyleFlags = shapestyleflags;
906+
context.transparent = (shapestyleflags &
907+
(SoShapeStyleElement::TRANSP_TEXTURE |
908+
SoShapeStyleElement::TRANSP_MATERIAL)) != 0;
891909

892910
if (shapestyleflags & SoShapeStyleElement::INVISIBLE)
893-
return FALSE;
894-
895-
if (PRIVATE(this)->bboxcache && !state->isCacheOpen() && !SoCullElement::completelyInside(state)) {
896-
if (PRIVATE(this)->bboxcache->isValid(state)) {
897-
if (SoCullElement::cullTest(state, PRIVATE(this)->bboxcache->getProjectedBox())) {
898-
return FALSE;
911+
return SoShapeGLRenderDecision::Stop;
912+
913+
if (PRIVATE(shape)->bboxcache && !state->isCacheOpen() &&
914+
!SoCullElement::completelyInside(state)) {
915+
if (PRIVATE(shape)->bboxcache->isValid(state)) {
916+
if (SoCullElement::cullTest(state,
917+
PRIVATE(shape)->bboxcache->getProjectedBox())) {
918+
return SoShapeGLRenderDecision::Stop;
899919
}
900920
}
901921
}
902922

903-
SbBool transparent = (shapestyleflags & (SoShapeStyleElement::TRANSP_TEXTURE|
904-
SoShapeStyleElement::TRANSP_MATERIAL)) != 0;
905-
906923
if (shapestyleflags & SoShapeStyleElement::SHADOWMAP) {
907-
if (transparent) return FALSE;
924+
if (context.transparent) return SoShapeGLRenderDecision::Stop;
908925
int style = SoShadowStyleElement::get(state);
909-
if (style & SoShadowStyleElement::CASTS_SHADOW) return TRUE;
910-
return FALSE;
926+
if (style & SoShadowStyleElement::CASTS_SHADOW) {
927+
return SoShapeGLRenderDecision::RenderShape;
928+
}
929+
return SoShapeGLRenderDecision::Stop;
911930
}
912931

913-
if (action->handleTransparency(transparent))
914-
return FALSE;
932+
if (action->handleTransparency(context.transparent))
933+
return SoShapeGLRenderDecision::Stop;
915934

916935
if (shapestyleflags & SoShapeStyleElement::BBOXCMPLX) {
917-
this->GLRenderBoundingBox(action);
918-
return FALSE;
936+
shape->GLRenderBoundingBox(action);
937+
return SoShapeGLRenderDecision::Stop;
919938
}
920939

921-
// test if we should sort triangles before rendering
922-
if (transparent && (shapestyleflags & SoShapeStyleElement::TRANSP_SORTED_TRIANGLES)) {
923-
// lock since pvcache is shared among all threads
924-
PRIVATE(this)->lock();
925-
this->validatePVCache(action);
940+
return SoShapeGLRenderDecision::Continue;
941+
}
926942

927-
int arrays = SoPrimitiveVertexCache::NORMAL|SoPrimitiveVertexCache::COLOR;
928-
SoGLMultiTextureImageElement::Model model;
929-
SbColor blendcolor;
930-
SoGLImage * glimage = SoGLMultiTextureImageElement::get(state, 0, model, blendcolor);
931-
if (glimage) arrays |= SoPrimitiveVertexCache::TEXCOORD;
943+
SbBool
944+
SoShapeGLRender::sortTriangles(SoShape * shape, SoGLRenderAction * action,
945+
const SoShapeGLRenderContext & context)
946+
{
947+
if (!context.transparent ||
948+
!(context.shapeStyleFlags & SoShapeStyleElement::TRANSP_SORTED_TRIANGLES)) {
949+
return TRUE;
950+
}
932951

933-
SoMaterialBundle mb(action);
934-
mb.sendFirst();
935-
PRIVATE(this)->setupShapeHints(this, state);
936-
PRIVATE(this)->pvcache->depthSortTriangles(state);
937-
PRIVATE(this)->pvcache->renderTriangles(state, arrays);
938-
if (PRIVATE(this)->pvcache->getNumLineIndices() ||
939-
PRIVATE(this)->pvcache->getNumPointIndices()) {
940-
const SoNormalElement * nelem = SoNormalElement::getInstance(state);
941-
if (nelem->getNum() == 0) {
942-
glPushAttrib(GL_LIGHTING_BIT);
943-
glDisable(GL_LIGHTING);
944-
arrays &= SoPrimitiveVertexCache::NORMAL;
945-
}
946-
PRIVATE(this)->pvcache->renderLines(state, arrays);
947-
PRIVATE(this)->pvcache->renderPoints(state, arrays);
952+
SoState * state = action->getState();
953+
// lock since pvcache is shared among all threads
954+
PRIVATE(shape)->lock();
955+
shape->validatePVCache(action);
948956

949-
if (nelem->getNum() == 0) {
950-
glPopAttrib();
951-
}
957+
int arrays = SoPrimitiveVertexCache::NORMAL|SoPrimitiveVertexCache::COLOR;
958+
SoGLMultiTextureImageElement::Model model;
959+
SbColor blendcolor;
960+
SoGLImage * glimage = SoGLMultiTextureImageElement::get(state, 0, model, blendcolor);
961+
if (glimage) arrays |= SoPrimitiveVertexCache::TEXCOORD;
962+
963+
SoMaterialBundle mb(action);
964+
mb.sendFirst();
965+
PRIVATE(shape)->setupShapeHints(shape, state);
966+
PRIVATE(shape)->pvcache->depthSortTriangles(state);
967+
PRIVATE(shape)->pvcache->renderTriangles(state, arrays);
968+
if (PRIVATE(shape)->pvcache->getNumLineIndices() ||
969+
PRIVATE(shape)->pvcache->getNumPointIndices()) {
970+
const SoNormalElement * nelem = SoNormalElement::getInstance(state);
971+
if (nelem->getNum() == 0) {
972+
glPushAttrib(GL_LIGHTING_BIT);
973+
glDisable(GL_LIGHTING);
974+
arrays &= SoPrimitiveVertexCache::NORMAL;
975+
}
976+
PRIVATE(shape)->pvcache->renderLines(state, arrays);
977+
PRIVATE(shape)->pvcache->renderPoints(state, arrays);
978+
979+
if (nelem->getNum() == 0) {
980+
glPopAttrib();
952981
}
953-
PRIVATE(this)->unlock();
954-
return FALSE; // tell shape _not_ to render
955982
}
983+
PRIVATE(shape)->unlock();
984+
return FALSE;
985+
}
986+
987+
SbBool
988+
SoShapeGLRender::finish(SoShape * shape, SoGLRenderAction * action,
989+
const SoShapeGLRenderContext & context)
990+
{
991+
SoState * state = action->getState();
992+
const unsigned int shapestyleflags = context.shapeStyleFlags;
956993

957994
if (shapestyleflags & SoShapeStyleElement::BIGIMAGE) {
958995
SoGLMultiTextureImageElement::Model model;
@@ -984,10 +1021,10 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
9841021
soshape_bigtexture * bigtex = soshape_get_bigtexture(shapedata, action->getCacheContext());
9851022
shapedata->currentbigtexture = bigtex;
9861023
bigtex->beginShape(big, SoTextureQualityElement::get(state));
987-
this->generatePrimitives(action);
1024+
shape->generatePrimitives(action);
9881025
// endShape() returns whether more/less detailed textures need to be
9891026
// fetched. We force a redraw if this is needed.
990-
if (bigtex->endShape(state, this, mb) == FALSE) {
1027+
if (bigtex->endShape(state, shape, mb) == FALSE) {
9911028
action->getCurPath()->getHead()->touch();
9921029
}
9931030
shapedata->rendermode = NORMAL;
@@ -1002,13 +1039,13 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
10021039
const SoNodeList & lights = SoLightElement::getLights(state);
10031040
if (lights.getLength()) {
10041041
// lock since bumprender and pvcache is shared among all threads
1005-
PRIVATE(this)->lock();
1006-
if (PRIVATE(this)->bumprender == NULL) {
1007-
PRIVATE(this)->bumprender = new soshape_bumprender;
1042+
PRIVATE(shape)->lock();
1043+
if (PRIVATE(shape)->bumprender == NULL) {
1044+
PRIVATE(shape)->bumprender = new soshape_bumprender;
10081045
}
1009-
this->validatePVCache(action);
1010-
if (PRIVATE(this)->pvcache->getNumTriangleIndices() == 0) {
1011-
PRIVATE(this)->unlock();
1046+
shape->validatePVCache(action);
1047+
if (PRIVATE(shape)->pvcache->getNumTriangleIndices() == 0) {
1048+
PRIVATE(shape)->unlock();
10121049
return TRUE;
10131050
}
10141051
SoGLLazyElement::getInstance(state)->send(state, SoLazyElement::ALL_MASK);
@@ -1018,7 +1055,7 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
10181055
glDisable(GL_LIGHTING);
10191056

10201057
glColor3f(1.0f, 1.0f, 1.0f);
1021-
PRIVATE(this)->setupShapeHints(this, state);
1058+
PRIVATE(shape)->setupShapeHints(shape, state);
10221059
const int numlights = lights.getLength();
10231060
for (int i = 0; i < numlights; i++) {
10241061
// fetch matrix that convert the light from its object space
@@ -1038,7 +1075,7 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
10381075
//
10391076
// FIXME: about the above comment; i don't see any locking...?
10401077
// -mortene.
1041-
PRIVATE(this)->bumprender->renderBump(state, PRIVATE(this)->pvcache,
1078+
PRIVATE(shape)->bumprender->renderBump(state, PRIVATE(shape)->pvcache,
10421079
(SoLight*) lights[i], m);
10431080

10441081
if (i == 0) glEnable(GL_BLEND);
@@ -1055,8 +1092,8 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
10551092
SoLazyElement::DIFFUSE_MASK);
10561093
SoMaterialBundle mb(action);
10571094
mb.sendFirst();
1058-
PRIVATE(this)->setupShapeHints(this, state);
1059-
PRIVATE(this)->bumprender->renderNormal(state, PRIVATE(this)->pvcache);
1095+
PRIVATE(shape)->setupShapeHints(shape, state);
1096+
PRIVATE(shape)->bumprender->renderNormal(state, PRIVATE(shape)->pvcache);
10601097

10611098
const SbColor spec = SoLazyElement::getSpecular(state);
10621099
if (spec[0] != 0 || spec[1] != 0 || spec[2] != 0) { // Is the spec. color black?
@@ -1076,15 +1113,15 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
10761113
SoViewingMatrixElement::get(state);
10771114
m = m.inverse();
10781115
m.multLeft(lm);
1079-
PRIVATE(this)->bumprender->renderBumpSpecular(state, PRIVATE(this)->pvcache,
1116+
PRIVATE(shape)->bumprender->renderBumpSpecular(state, PRIVATE(shape)->pvcache,
10801117
(SoLight*) lights[i], m);
10811118
}
10821119
}
10831120

10841121
}
10851122

10861123

1087-
PRIVATE(this)->unlock();
1124+
PRIVATE(shape)->unlock();
10881125

10891126
glPopAttrib();
10901127
// we used two units in the bumpmap code
@@ -1101,9 +1138,9 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
11011138

11021139
if (shapestyleflags & SoShapeStyleElement::VERTEXARRAY) {
11031140
// lock since pvcache is shared among all threads
1104-
PRIVATE(this)->lock();
1105-
this->validatePVCache(action);
1106-
PRIVATE(this)->unlock();
1141+
PRIVATE(shape)->lock();
1142+
shape->validatePVCache(action);
1143+
PRIVATE(shape)->unlock();
11071144

11081145
SoGLCacheContextElement::shouldAutoCache(state,
11091146
SoGLCacheContextElement::DONT_AUTO_CACHE);
@@ -1114,18 +1151,18 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
11141151
if (glimage) arrays |= SoPrimitiveVertexCache::TEXCOORD;
11151152
SoMaterialBundle mb(action);
11161153
mb.sendFirst();
1117-
PRIVATE(this)->setupShapeHints(this, state);
1118-
PRIVATE(this)->pvcache->renderTriangles(state, arrays);
1119-
if (PRIVATE(this)->pvcache->getNumLineIndices() ||
1120-
PRIVATE(this)->pvcache->getNumPointIndices()) {
1154+
PRIVATE(shape)->setupShapeHints(shape, state);
1155+
PRIVATE(shape)->pvcache->renderTriangles(state, arrays);
1156+
if (PRIVATE(shape)->pvcache->getNumLineIndices() ||
1157+
PRIVATE(shape)->pvcache->getNumPointIndices()) {
11211158
const SoNormalElement * nelem = SoNormalElement::getInstance(state);
11221159
if (nelem->getNum() == 0) {
11231160
glPushAttrib(GL_LIGHTING_BIT);
11241161
glDisable(GL_LIGHTING);
11251162
arrays &= SoPrimitiveVertexCache::NORMAL;
11261163
}
1127-
PRIVATE(this)->pvcache->renderLines(state, arrays);
1128-
PRIVATE(this)->pvcache->renderPoints(state, arrays);
1164+
PRIVATE(shape)->pvcache->renderLines(state, arrays);
1165+
PRIVATE(shape)->pvcache->renderPoints(state, arrays);
11291166

11301167
if (nelem->getNum() == 0) {
11311168
glPopAttrib();
@@ -1139,11 +1176,11 @@ SoShape::shouldGLRender(SoGLRenderAction * action)
11391176
SoMaterialBundle mb(action);
11401177
mb.sendFirst();
11411178
soshape_get_staticdata()->currentbundle = &mb; // needed in the primitive callbacks
1142-
this->generatePrimitives(action);
1179+
shape->generatePrimitives(action);
11431180
return FALSE;
11441181
#else // generatePrimitives() rendering
1145-
if (PRIVATE(this)->rendercnt < ((1<<SoShapeP::RENDERCNT_BITS)-1)) {
1146-
PRIVATE(this)->rendercnt++;
1182+
if (PRIVATE(shape)->rendercnt < ((1<<SoShapeP::RENDERCNT_BITS)-1)) {
1183+
PRIVATE(shape)->rendercnt++;
11471184
}
11481185
return TRUE; // let the shape node render the geometry using OpenGL
11491186
#endif // ! generatePrimitives() rendering

src/shapenodes/SoShapeGLRenderP.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// src/shapenodes/SoShapeGLRenderP.h
2+
3+
#ifndef COIN_SOSHAPEGLRENDERP_H
4+
#define COIN_SOSHAPEGLRENDERP_H
5+
6+
#include <Inventor/SbBasic.h>
7+
8+
class SoGLRenderAction;
9+
class SoShape;
10+
11+
// This is deliberately source-private. It separates the historical
12+
// SoShape GL-render control flow without adding another installed rendering
13+
// policy API for direct-rendered subclasses.
14+
struct SoShapeGLRenderContext {
15+
unsigned int shapeStyleFlags = 0;
16+
SbBool transparent = FALSE;
17+
};
18+
19+
enum class SoShapeGLRenderDecision {
20+
Continue,
21+
RenderShape,
22+
Stop
23+
};
24+
25+
class SoShapeGLRender {
26+
public:
27+
static SoShapeGLRenderDecision begin(
28+
SoShape * shape, SoGLRenderAction * action,
29+
SoShapeGLRenderContext & context);
30+
static SbBool sortTriangles(SoShape * shape, SoGLRenderAction * action,
31+
const SoShapeGLRenderContext & context);
32+
static SbBool finish(SoShape * shape, SoGLRenderAction * action,
33+
const SoShapeGLRenderContext & context);
34+
};
35+
36+
#endif // COIN_SOSHAPEGLRENDERP_H

testsuite/CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,33 @@ target_include_directories(LegacyBlendingTest PRIVATE
136136
)
137137
add_test(NAME LegacyBlendingTest COMMAND LegacyBlendingTest)
138138

139+
if(COIN_BUILD_LEGACY_GL_RENDERER AND HAVE_EGL)
140+
add_executable(LegacyDirectRasterTransparencyTest
141+
legacy-direct-raster-transparency-test.cpp)
142+
target_link_libraries(LegacyDirectRasterTransparencyTest Coin
143+
${COIN_TARGET_LINK_LIBRARIES})
144+
target_include_directories(LegacyDirectRasterTransparencyTest PRIVATE
145+
${PROJECT_SOURCE_DIR}/include
146+
${PROJECT_BINARY_DIR}/include
147+
${COIN_TARGET_INCLUDE_DIRECTORIES})
148+
add_test(NAME LegacyDirectRasterTransparencyTest
149+
COMMAND LegacyDirectRasterTransparencyTest)
150+
set_tests_properties(LegacyDirectRasterTransparencyTest
151+
PROPERTIES SKIP_RETURN_CODE 77)
152+
add_executable(LegacyShapeGatingOrderTest
153+
legacy-shape-gating-order-test.cpp)
154+
target_link_libraries(LegacyShapeGatingOrderTest Coin
155+
${COIN_TARGET_LINK_LIBRARIES})
156+
target_include_directories(LegacyShapeGatingOrderTest PRIVATE
157+
${PROJECT_SOURCE_DIR}/include
158+
${PROJECT_BINARY_DIR}/include
159+
${COIN_TARGET_INCLUDE_DIRECTORIES})
160+
add_test(NAME LegacyShapeGatingOrderTest
161+
COMMAND LegacyShapeGatingOrderTest)
162+
set_tests_properties(LegacyShapeGatingOrderTest
163+
PROPERTIES SKIP_RETURN_CODE 77)
164+
endif()
165+
139166
add_executable(RetainedIRTest retained-ir-test.cpp)
140167
target_link_libraries(RetainedIRTest Coin ${COIN_TARGET_LINK_LIBRARIES})
141168
target_include_directories(RetainedIRTest PRIVATE

0 commit comments

Comments
 (0)