From e0bd3c144674de331c622074c16aa9b3e9d47716 Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Wed, 29 Jul 2026 15:52:19 +0100 Subject: [PATCH 1/3] gl: compile fixed-function rendering helpers only in compatibility builds Shared rendering helpers still pulled fixed-function declarations into core-profile builds, coupling profile-neutral image, VBO, and shader support to the legacy renderer. Guard compatibility-only operations in offscreen setup, image and vertex-array helpers, and shader utilities while leaving profile-neutral work available to both paths. The two renderer paths can therefore coexist until retained traversal is complete. --- src/glue/gl.cpp | 38 +++++ src/rendering/CoinOffscreenGLCanvas.cpp | 196 ++++++++++++------------ src/rendering/SoGLImage.cpp | 62 +++++--- src/rendering/SoVertexArrayIndexer.cpp | 82 ++++++---- src/shaders/SoGLSLShaderObject.cpp | 91 ++++++++++- src/shaders/SoGLSLShaderObject.h | 1 + src/shaders/SoGLSLShaderParameter.cpp | 88 ++++++----- src/shaders/SoGLSLShaderProgram.cpp | 65 +++++++- src/shaders/SoGLSLShaderProgram.h | 1 + src/shaders/SoShaderObject.cpp | 17 +- 10 files changed, 436 insertions(+), 205 deletions(-) diff --git a/src/glue/gl.cpp b/src/glue/gl.cpp index dcba5bc408c..9739a28e752 100644 --- a/src/glue/gl.cpp +++ b/src/glue/gl.cpp @@ -2399,8 +2399,12 @@ cc_glglue_instance(int contextid) gi->max_texture_size = gltmp; if (gi->context_supports_legacy_rendering) { +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) glGetIntegerv(GL_MAX_LIGHTS, &gltmp); gi->max_lights = (int) gltmp; +#else + gi->max_lights = 0; +#endif } else { gi->max_lights = 0; @@ -5062,10 +5066,20 @@ cc_glglue_is_texture_size_legal(const cc_glglue * glw, switch (bytespertexel) { default: case 1: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = internalformat = GL_LUMINANCE; +#else + internalformat = GL_R8; + format = GL_RED; +#endif break; case 2: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = internalformat = GL_LUMINANCE_ALPHA; +#else + internalformat = GL_RG8; + format = GL_RG; +#endif break; case 3: format = internalformat = GL_RGB8; @@ -5143,10 +5157,18 @@ GLint coin_glglue_get_internal_texture_format(const cc_glglue * glw, if (compress) { switch (numcomponents) { case 1: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = GL_COMPRESSED_LUMINANCE_ARB; +#else + format = GL_COMPRESSED_RED; +#endif break; case 2: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = GL_COMPRESSED_LUMINANCE_ALPHA_ARB; +#else + format = GL_COMPRESSED_RG; +#endif break; case 3: format = GL_COMPRESSED_RGB_ARB; @@ -5161,10 +5183,18 @@ GLint coin_glglue_get_internal_texture_format(const cc_glglue * glw, SbBool usenewenums = glglue_allow_newer_opengl(glw) && cc_glglue_glversion_matches_at_least(glw,1,1,0); switch (numcomponents) { case 1: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = usenewenums ? GL_LUMINANCE8 : GL_LUMINANCE; +#else + format = GL_R8; +#endif break; case 2: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = usenewenums ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA; +#else + format = GL_RG8; +#endif break; case 3: format = usenewenums ? GL_RGB8 : GL_RGB; @@ -5187,10 +5217,18 @@ GLenum coin_glglue_get_texture_format(const cc_glglue * COIN_UNUSED_ARG(glw), in GLenum format; switch (numcomponents) { case 1: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = GL_LUMINANCE; +#else + format = GL_RED; +#endif break; case 2: +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) format = GL_LUMINANCE_ALPHA; +#else + format = GL_RG; +#endif break; case 3: format = GL_RGB; diff --git a/src/rendering/CoinOffscreenGLCanvas.cpp b/src/rendering/CoinOffscreenGLCanvas.cpp index 18f09378a65..9943fc32426 100644 --- a/src/rendering/CoinOffscreenGLCanvas.cpp +++ b/src/rendering/CoinOffscreenGLCanvas.cpp @@ -331,105 +331,111 @@ CoinOffscreenGLCanvas::readPixels(uint8_t * dst, unsigned int dstrowsize, unsigned int nrcomponents) const { - glPushAttrib(GL_ALL_ATTRIB_BITS); - - // First reset all settings that can influence the result of a - // glReadPixels() call, to make sure we get the actual contents of - // the buffer, unmodified. - // - // The values set up below matches the default settings of an - // OpenGL driver. - - glPixelStorei(GL_PACK_SWAP_BYTES, 0); - glPixelStorei(GL_PACK_LSB_FIRST, 0); - glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)dstrowsize); - glPixelStorei(GL_PACK_SKIP_ROWS, 0); - glPixelStorei(GL_PACK_SKIP_PIXELS, 0); - - // FIXME: should use best possible alignment, for speediest - // operation. 20050617 mortene. -// glPixelStorei(GL_PACK_ALIGNMENT, 4); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - glPixelTransferi(GL_MAP_COLOR, 0); - glPixelTransferi(GL_MAP_STENCIL, 0); - glPixelTransferi(GL_INDEX_SHIFT, 0); - glPixelTransferi(GL_INDEX_OFFSET, 0); - glPixelTransferf(GL_RED_SCALE, 1); - glPixelTransferf(GL_RED_BIAS, 0); - glPixelTransferf(GL_GREEN_SCALE, 1); - glPixelTransferf(GL_GREEN_BIAS, 0); - glPixelTransferf(GL_BLUE_SCALE, 1); - glPixelTransferf(GL_BLUE_BIAS, 0); - glPixelTransferf(GL_ALPHA_SCALE, 1); - glPixelTransferf(GL_ALPHA_BIAS, 0); - glPixelTransferf(GL_DEPTH_SCALE, 1); - glPixelTransferf(GL_DEPTH_BIAS, 0); - - GLuint i = 0; - GLfloat f = 0.0f; - glPixelMapfv(GL_PIXEL_MAP_I_TO_I, 1, &f); - glPixelMapuiv(GL_PIXEL_MAP_S_TO_S, 1, &i); - glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_R_TO_R, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_G_TO_G, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_B_TO_B, 1, &f); - glPixelMapfv(GL_PIXEL_MAP_A_TO_A, 1, &f); - - // The flushing of the OpenGL pipeline before and after the - // glReadPixels() call is done as a work-around for a reported - // OpenGL driver bug: on a Win2000 system with ATI Radeon graphics - // card, the system would hang hard if the flushing was not done. - // - // This is obviously an OpenGL driver bug, but the workaround of - // doing excessive flushing has no real ill effects, so we just do - // it unconditionally for all drivers. Note that it might not be - // necessary to flush both before and after glReadPixels() to work - // around the bug (this was not established with the external - // reporter), but again it shouldn't matter if we do. - // - // For reference, the specific driver which was reported to fail has - // the following characteristics: - // - // GL_VENDOR="ATI Technologies Inc." - // GL_RENDERER="Radeon 9000 DDR x86/SSE2" - // GL_VERSION="1.3.3446 Win2000 Release" - // - // mortene. - - glFlush(); glFinish(); - - assert((nrcomponents >= 1) && (nrcomponents <= 4)); - - if (nrcomponents < 3) { - unsigned char * tmp = new unsigned char[vpdims[0]*vpdims[1]*4]; - glReadPixels(0, 0, vpdims[0], vpdims[1], - nrcomponents == 1 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, tmp); - - const unsigned char * src = tmp; - // manually convert to grayscale - for (short y = 0; y < vpdims[1]; y++) { - for (short x = 0; x < vpdims[0]; x++) { - double v = src[0] * 0.3 + src[1] * 0.59 + src[2] * 0.11; - *dst++ = (unsigned char) v; - if (nrcomponents == 2) { - *dst++ = src[3]; +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + //if (sogl_context_supports_legacy_rendering(state)) { + glPushAttrib(GL_ALL_ATTRIB_BITS); + + // First reset all settings that can influence the result of a + // glReadPixels() call, to make sure we get the actual contents of + // the buffer, unmodified. + // + // The values set up below matches the default settings of an + // OpenGL driver. + + glPixelStorei(GL_PACK_SWAP_BYTES, 0); + glPixelStorei(GL_PACK_LSB_FIRST, 0); + glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)dstrowsize); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + + // FIXME: should use best possible alignment, for speediest + // operation. 20050617 mortene. + // glPixelStorei(GL_PACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + glPixelTransferi(GL_MAP_COLOR, 0); + glPixelTransferi(GL_MAP_STENCIL, 0); + glPixelTransferi(GL_INDEX_SHIFT, 0); + glPixelTransferi(GL_INDEX_OFFSET, 0); + glPixelTransferf(GL_RED_SCALE, 1); + glPixelTransferf(GL_RED_BIAS, 0); + glPixelTransferf(GL_GREEN_SCALE, 1); + glPixelTransferf(GL_GREEN_BIAS, 0); + glPixelTransferf(GL_BLUE_SCALE, 1); + glPixelTransferf(GL_BLUE_BIAS, 0); + glPixelTransferf(GL_ALPHA_SCALE, 1); + glPixelTransferf(GL_ALPHA_BIAS, 0); + glPixelTransferf(GL_DEPTH_SCALE, 1); + glPixelTransferf(GL_DEPTH_BIAS, 0); + + GLuint i = 0; + GLfloat f = 0.0f; + glPixelMapfv(GL_PIXEL_MAP_I_TO_I, 1, &f); + glPixelMapuiv(GL_PIXEL_MAP_S_TO_S, 1, &i); + glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_R_TO_R, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_G_TO_G, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_B_TO_B, 1, &f); + glPixelMapfv(GL_PIXEL_MAP_A_TO_A, 1, &f); + + // The flushing of the OpenGL pipeline before and after the + // glReadPixels() call is done as a work-around for a reported + // OpenGL driver bug: on a Win2000 system with ATI Radeon graphics + // card, the system would hang hard if the flushing was not done. + // + // This is obviously an OpenGL driver bug, but the workaround of + // doing excessive flushing has no real ill effects, so we just do + // it unconditionally for all drivers. Note that it might not be + // necessary to flush both before and after glReadPixels() to work + // around the bug (this was not established with the external + // reporter), but again it shouldn't matter if we do. + // + // For reference, the specific driver which was reported to fail has + // the following characteristics: + // + // GL_VENDOR="ATI Technologies Inc." + // GL_RENDERER="Radeon 9000 DDR x86/SSE2" + // GL_VERSION="1.3.3446 Win2000 Release" + // + // mortene. + + glFlush(); glFinish(); + + assert((nrcomponents >= 1) && (nrcomponents <= 4)); + + if (nrcomponents < 3) { + unsigned char * tmp = new unsigned char[vpdims[0]*vpdims[1]*4]; + glReadPixels(0, 0, vpdims[0], vpdims[1], + nrcomponents == 1 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, tmp); + + const unsigned char * src = tmp; + // manually convert to grayscale + for (short y = 0; y < vpdims[1]; y++) { + for (short x = 0; x < vpdims[0]; x++) { + double v = src[0] * 0.3 + src[1] * 0.59 + src[2] * 0.11; + *dst++ = (unsigned char) v; + if (nrcomponents == 2) { + *dst++ = src[3]; + } + src += nrcomponents == 1 ? 3 : 4; } - src += nrcomponents == 1 ? 3 : 4; } + delete[] tmp; } - delete[] tmp; - } - else { - glReadPixels(0, 0, vpdims[0], vpdims[1], - nrcomponents == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, dst); - } - glFlush(); glFinish(); + else { + glReadPixels(0, 0, vpdims[0], vpdims[1], + nrcomponents == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, dst); + } + glFlush(); glFinish(); - glPopAttrib(); + glPopAttrib(); + //} +#else + assert(0 && "Not implemented for non-compatibility GL renderer"); +#endif } // ************************************************************************* diff --git a/src/rendering/SoGLImage.cpp b/src/rendering/SoGLImage.cpp index 64094a68fb8..ad200bf62e3 100644 --- a/src/rendering/SoGLImage.cpp +++ b/src/rendering/SoGLImage.cpp @@ -248,6 +248,21 @@ static int COIN_TEX2_USE_GLTEXSUBIMAGE = -1; static int COIN_TEX2_USE_SGIS_GENERATE_MIPMAP = -1; static int COIN_ENABLE_CONFORMANT_GL_CLAMP = -1; +#if !defined(COIN_BUILD_LEGACY_GL_RENDERER) +static void +set_core_texture_swizzle(const GLenum target, const int numcomponents) +{ + if (numcomponents == 1) { + const GLint swizzle[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; + glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + } + else if (numcomponents == 2) { + const GLint swizzle[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; + glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + } +} +#endif + // ************************************************************************* // buffer used for creating mipmap images @@ -1816,6 +1831,9 @@ SoGLImageP::reallyCreateTexture(SoState *state, fast_mipmap(state, w, h, d, numComponents, texture, FALSE, compress); } +#if !defined(COIN_BUILD_LEGACY_GL_RENDERER) + set_core_texture_swizzle(GL_TEXTURE_3D, numComponents); +#endif } else { // 2D textures SbBool mipmapimage = mipmap; @@ -1830,26 +1848,31 @@ SoGLImageP::reallyCreateTexture(SoState *state, glTexParameteri(target, GL_TEXTURE_WRAP_T, translate_wrap(state, this->wrapt)); - if (mipmap && (this->flags & SoGLImage::RECTANGLE)) { - mipmapimage = FALSE; - if (SoGLDriverDatabase::isSupported(glw, "GL_SGIS_generate_mipmap")) { + if (sogl_context_supports_legacy_rendering(state)) + { + if (mipmap && (this->flags & SoGLImage::RECTANGLE)) { + mipmapimage = FALSE; + if (SoGLDriverDatabase::isSupported(glw, "GL_SGIS_generate_mipmap")) { + glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + } + else mipmapfilter = FALSE; + } + // prefer GL_SGIS_generate_mipmap to glGenerateMipmap. It seems to + // be better supported in drivers. + else if (mipmap && SoGLDriverDatabase::isSupported(glw, "GL_SGIS_generate_mipmap")) { glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + mipmapimage = FALSE; + } + } + if (mipmapimage) { + // using glGenerateMipmap() while creating a display list is not + // supported (even if the display list is never used). This is + // probably because the OpenGL driver creates each mipmap level by + // rendering it using normal OpenGL calls. + if (mipmap && SoGLDriverDatabase::isSupported(glw, SO_GL_GENERATE_MIPMAP) && !state->isCacheOpen()) { + mipmapimage = FALSE; + generatemipmap = TRUE; // delay until after the texture image is set up } - else mipmapfilter = FALSE; - } - // prefer GL_SGIS_generate_mipmap to glGenerateMipmap. It seems to - // be better supported in drivers. - else if (mipmap && SoGLDriverDatabase::isSupported(glw, "GL_SGIS_generate_mipmap")) { - glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); - mipmapimage = FALSE; - } - // using glGenerateMipmap() while creating a display list is not - // supported (even if the display list is never used). This is - // probably because the OpenGL driver creates each mipmap level by - // rendering it using normal OpenGL calls. - else if (mipmap && SoGLDriverDatabase::isSupported(glw, SO_GL_GENERATE_MIPMAP) && !state->isCacheOpen()) { - mipmapimage = FALSE; - generatemipmap = TRUE; // delay until after the texture image is set up } if ((this->quality > COIN_TEX2_ANISOTROPIC_LIMIT) && SoGLDriverDatabase::isSupported(glw, SO_GL_ANISOTROPIC_FILTERING)) { @@ -1886,6 +1909,9 @@ SoGLImageP::reallyCreateTexture(SoState *state, // GL_UNSIGNED_BYTE, texture); fast_mipmap(state, w, h, numComponents, texture, FALSE, compress); } +#if !defined(COIN_BUILD_LEGACY_GL_RENDERER) + set_core_texture_swizzle(target, numComponents); +#endif // apply the texture filters this->applyFilter(mipmapfilter); } diff --git a/src/rendering/SoVertexArrayIndexer.cpp b/src/rendering/SoVertexArrayIndexer.cpp index 4314f2947c8..20aa91720d0 100644 --- a/src/rendering/SoVertexArrayIndexer.cpp +++ b/src/rendering/SoVertexArrayIndexer.cpp @@ -47,6 +47,10 @@ #include #include +#include "Inventor/C/glue/gl.h" +#include "Inventor/elements/SoViewingMatrixElement.h" +#include "Inventor/elements/SoProjectionMatrixElement.h" + #include "tidbitsp.h" #include "rendering/SoVBO.h" #include "rendering/SoGL.h" @@ -273,40 +277,60 @@ SoVertexArrayIndexer::render(SoState * state, const SbBool renderasvbo, const ui } } this->vbo->bindBuffer(contextid); - cc_glglue_glDrawElements(glue, - this->target, - this->indexarray.getLength(), - this->use_shorts ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, NULL); - cc_glglue_glBindBuffer(glue, GL_ELEMENT_ARRAY_BUFFER, 0); - } - else { - const GLint * idxptr = this->indexarray.getArrayPtr(); - cc_glglue_glDrawElements(glue, - this->target, - this->indexarray.getLength(), - GL_UNSIGNED_INT, - idxptr); + +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (cc_glglue_context_supports_legacy_rendering(glue)) { + cc_glglue_glDrawElements(glue, + this->target, + this->indexarray.getLength(), + this->use_shorts ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, NULL); + cc_glglue_glBindBuffer(glue, GL_ELEMENT_ARRAY_BUFFER, 0); + } else +#endif + { + glDrawElements(this->target, + this->indexarray.getLength(), + this->use_shorts ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + } else { + const GLint * idxptr = this->indexarray.getArrayPtr(); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (cc_glglue_context_supports_legacy_rendering(glue)) { + cc_glglue_glDrawElements(glue, + this->target, + this->indexarray.getLength(), + GL_UNSIGNED_INT, + idxptr); + } else +#endif + { + glDrawElements(this->target, + this->indexarray.getLength(), + GL_UNSIGNED_INT, + idxptr); + } } break; default: if (SoGLDriverDatabase::isSupported(glue, SO_GL_MULTIDRAW_ELEMENTS)) { - cc_glglue_glMultiDrawElements(glue, - this->target, - (GLsizei*) this->countarray.getArrayPtr(), - GL_UNSIGNED_INT, - (const GLvoid**) this->ciarray.getArrayPtr(), - this->countarray.getLength()); - } - else { - for (int i = 0; i < this->countarray.getLength(); i++) { - const GLsizei * ptr = this->ciarray[i]; - GLsizei cnt = this->countarray[i]; - cc_glglue_glDrawElements(glue, - this->target, - cnt, - GL_UNSIGNED_INT, - (const GLvoid*) ptr); + cc_glglue_glMultiDrawElements(glue, + this->target, + (GLsizei*) this->countarray.getArrayPtr(), + GL_UNSIGNED_INT, + (const GLvoid**) this->ciarray.getArrayPtr(), + this->countarray.getLength()); } + else { + for (int i = 0; i < this->countarray.getLength(); i++) { + const GLsizei * ptr = this->ciarray[i]; + GLsizei cnt = this->countarray[i]; + cc_glglue_glDrawElements(glue, + this->target, + cnt, + GL_UNSIGNED_INT, + (const GLvoid*) ptr); + } } break; } diff --git a/src/shaders/SoGLSLShaderObject.cpp b/src/shaders/SoGLSLShaderObject.cpp index 57f431a17d7..4999c125113 100644 --- a/src/shaders/SoGLSLShaderObject.cpp +++ b/src/shaders/SoGLSLShaderObject.cpp @@ -31,8 +31,10 @@ \**************************************************************************/ #include "shaders/SoGLSLShaderObject.h" +#include "Inventor/C/glue/gl.h" #include "coindefs.h" +#include #include #include #include @@ -80,6 +82,59 @@ SoGLSLShaderObject::isLoaded(void) const void SoGLSLShaderObject::load(const char* srcStr) +{ + if (cc_glglue_context_supports_legacy_rendering(this->glctx)) { + loadARB(srcStr); + return; + } + + this->unload(); + this->setParametersDirty(TRUE); + + GLint flag; + GLenum sType; + + switch (this->getShaderType()) { + default: + assert(0 &&" unknown shader type"); + case VERTEX: + sType = GL_VERTEX_SHADER; + break; + case FRAGMENT: + sType = GL_FRAGMENT_SHADER; + break; + case GEOMETRY: + sType = GL_GEOMETRY_SHADER; + break; + } + + SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderObject::load() : previous errors"); + + this->shaderHandle = glCreateShader(sType); + this->programid = 0; + + if (this->shaderHandle == 0) return; + this->programid = soglshaderobject_idcounter++; + + glShaderSource(this->shaderHandle, 1, (const COIN_GLchar **)&srcStr, NULL); + glCompileShader(this->shaderHandle); + + if (SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderObject::load()")) { + this->shaderHandle = 0; + return; + } + + glGetShaderiv(this->shaderHandle, GL_COMPILE_STATUS, &flag); + SoGLSLShaderObject::printInfoLog(this->GLContext(), this->shaderHandle, + this->getShaderType()); + + if (!flag) { + this->shaderHandle = 0; + } +} + +void +SoGLSLShaderObject::loadARB(const char* srcStr) { this->unload(); this->setParametersDirty(TRUE); @@ -101,7 +156,7 @@ SoGLSLShaderObject::load(const char* srcStr) break; } - SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderObject::load() : previous errors"); + SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderObject::loadARB() : previous errors"); this->shaderHandle = this->glctx->glCreateShaderObjectARB(sType); this->programid = 0; @@ -153,7 +208,11 @@ SoGLSLShaderObject::attach(COIN_GLhandle programHandle) if (this->shaderHandle) { this->programHandle = programHandle; - this->glctx->glAttachObjectARB(this->programHandle, this->shaderHandle); + if (cc_glglue_context_supports_legacy_rendering(this->glctx)) { + this->glctx->glAttachObjectARB(this->programHandle, this->shaderHandle); + } else { + glAttachShader(this->programHandle, this->shaderHandle); + } this->isattached = TRUE; } } @@ -179,12 +238,20 @@ SoGLSLShaderObject::printInfoLog(const cc_glglue * g, COIN_GLhandle handle, int { GLint length = 0; - g->glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + if (cc_glglue_context_supports_legacy_rendering(g)) { + g->glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + } else { + glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &length); + } if (length > 1) { COIN_GLchar *infoLog = new COIN_GLchar[length]; GLsizei charsWritten = 0; - g->glGetInfoLogARB(handle, length, &charsWritten, infoLog); + if (cc_glglue_context_supports_legacy_rendering(g)) { + g->glGetInfoLogARB(handle, length, &charsWritten, infoLog); + } else { + glGetShaderInfoLog(handle, length, &charsWritten, infoLog); + } SbString s("GLSL"); switch (objType) { case 0: s += "vertexShader "; break; @@ -249,8 +316,14 @@ SoGLSLShaderObject::updateCoinParameter(SoState * COIN_UNUSED_ARG(state), const if (p->value.getValue() != value) p->value = value; } else { - GLint location = glue->glGetUniformLocationARB(pHandle, - (const COIN_GLchar *)name.getString()); + GLint location; + if (sogl_context_supports_legacy_rendering(state)) { + location = glue->glGetUniformLocationARB(pHandle, + (const COIN_GLchar *)name.getString()); + } else { + location = glGetUniformLocation(pHandle, + (const COIN_GLchar *)name.getString()); + } #if 0 fprintf(stderr,"action: %s, name: %s, loc: %d, handle: %p\n", @@ -258,7 +331,11 @@ SoGLSLShaderObject::updateCoinParameter(SoState * COIN_UNUSED_ARG(state), const name.getString(), location, pHandle); #endif if (location >= 0) { - glue->glUniform1iARB(location, value); + if (sogl_context_supports_legacy_rendering(state)) { + glue->glUniform1iARB(location, value); + } else { + glUniform1i(location, value); + } } } } diff --git a/src/shaders/SoGLSLShaderObject.h b/src/shaders/SoGLSLShaderObject.h index 435c1190bbd..c83a59012b9 100644 --- a/src/shaders/SoGLSLShaderObject.h +++ b/src/shaders/SoGLSLShaderObject.h @@ -60,6 +60,7 @@ class SoGLSLShaderObject : public SoGLShaderObject virtual SbBool isLoaded(void) const; virtual void load(const char * sourceString); + virtual void loadARB(const char * sourceString); virtual void unload(void); void attach(COIN_GLhandle programHandle); diff --git a/src/shaders/SoGLSLShaderParameter.cpp b/src/shaders/SoGLSLShaderParameter.cpp index 2094a224ffb..3299731da39 100644 --- a/src/shaders/SoGLSLShaderParameter.cpp +++ b/src/shaders/SoGLSLShaderParameter.cpp @@ -63,31 +63,31 @@ SoGLSLShaderParameter::set1f(const SoGLShaderObject * shader, const float value, const char *name, const int) { if (this->isValid(shader, name, GL_FLOAT)) - shader->GLContext()->glUniform1fARB(this->location, value); + glUniform1f(this->location, value); } void SoGLSLShaderParameter::set2f(const SoGLShaderObject * shader, const float * value, const char *name, const int) { - if (this->isValid(shader, name, GL_FLOAT_VEC2_ARB)) - shader->GLContext()->glUniform2fARB(this->location, value[0], value[1]); + if (this->isValid(shader, name, GL_FLOAT_VEC2)) + glUniform2f(this->location, value[0], value[1]); } void SoGLSLShaderParameter::set3f(const SoGLShaderObject * shader, const float * v, const char *name, const int) { - if (this->isValid(shader, name, GL_FLOAT_VEC3_ARB)) - shader->GLContext()->glUniform3fARB(this->location, v[0], v[1], v[2]); + if (this->isValid(shader, name, GL_FLOAT_VEC3)) + glUniform3f(this->location, v[0], v[1], v[2]); } void SoGLSLShaderParameter::set4f(const SoGLShaderObject * shader, const float * v, const char *name, const int) { - if (this->isValid(shader, name, GL_FLOAT_VEC4_ARB)) - shader->GLContext()->glUniform4fARB(this->location, v[0], v[1], v[2], v[3]); + if (this->isValid(shader, name, GL_FLOAT_VEC4)) + glUniform4f(this->location, v[0], v[1], v[2], v[3]); } @@ -97,7 +97,7 @@ SoGLSLShaderParameter::set1fv(const SoGLShaderObject * shader, const int num, { int cnt = num; if (this->isValid(shader, name, GL_FLOAT, &cnt)) - shader->GLContext()->glUniform1fvARB(this->location, cnt, value); + glUniform1fv(this->location, cnt, value); } void @@ -105,8 +105,8 @@ SoGLSLShaderParameter::set2fv(const SoGLShaderObject * shader, const int num, const float* value, const char* name, const int) { int cnt = num; - if (this->isValid(shader, name, GL_FLOAT_VEC2_ARB, &cnt)) - shader->GLContext()->glUniform2fvARB(this->location, cnt, value); + if (this->isValid(shader, name, GL_FLOAT_VEC2, &cnt)) + glUniform2fv(this->location, cnt, value); } void @@ -114,8 +114,8 @@ SoGLSLShaderParameter::set3fv(const SoGLShaderObject * shader, const int num, const float* value, const char * name, const int) { int cnt = num; - if (this->isValid(shader, name, GL_FLOAT_VEC3_ARB, &cnt)) - shader->GLContext()->glUniform3fvARB(this->location, cnt, value); + if (this->isValid(shader, name, GL_FLOAT_VEC3, &cnt)) + glUniform3fv(this->location, cnt, value); } void @@ -123,8 +123,8 @@ SoGLSLShaderParameter::set4fv(const SoGLShaderObject * shader, const int num, const float* value, const char * name, const int) { int cnt = num; - if (this->isValid(shader, name, GL_FLOAT_VEC4_ARB, &cnt)) - shader->GLContext()->glUniform4fvARB(this->location, cnt, value); + if (this->isValid(shader, name, GL_FLOAT_VEC4, &cnt)) + glUniform4fv(this->location, cnt, value); } void @@ -132,8 +132,8 @@ SoGLSLShaderParameter::setMatrix(const SoGLShaderObject *shader, const float * value, const char * name, const int) { - if (this->isValid(shader, name, GL_FLOAT_MAT4_ARB)) - shader->GLContext()->glUniformMatrix4fvARB(this->location,1,FALSE,value); + if (this->isValid(shader, name, GL_FLOAT_MAT4)) + glUniformMatrix4fv(this->location,1,FALSE,value); } @@ -143,8 +143,8 @@ SoGLSLShaderParameter::setMatrixArray(const SoGLShaderObject *shader, const char *name, const int) { int cnt = num; - if (this->isValid(shader, name, GL_FLOAT_MAT4_ARB, &cnt)) - shader->GLContext()->glUniformMatrix4fvARB(this->location,cnt,FALSE,value); + if (this->isValid(shader, name, GL_FLOAT_MAT4, &cnt)) + glUniformMatrix4fv(this->location,cnt,FALSE,value); } @@ -153,7 +153,7 @@ SoGLSLShaderParameter::set1i(const SoGLShaderObject * shader, const int32_t value, const char * name, const int) { if (this->isValid(shader, name, GL_INT)) - shader->GLContext()->glUniform1iARB(this->location, value); + glUniform1i(this->location, value); } void @@ -161,8 +161,8 @@ SoGLSLShaderParameter::set2i(const SoGLShaderObject * shader, const int32_t * value, const char * name, const int) { - if (this->isValid(shader, name, GL_INT_VEC2_ARB)) - shader->GLContext()->glUniform2iARB(this->location, value[0], value[1]); + if (this->isValid(shader, name, GL_INT_VEC2)) + glUniform2i(this->location, value[0], value[1]); } void @@ -170,8 +170,8 @@ SoGLSLShaderParameter::set3i(const SoGLShaderObject * shader, const int32_t * v, const char * name, const int) { - if (this->isValid(shader, name, GL_INT_VEC3_ARB)) - shader->GLContext()->glUniform3iARB(this->location, v[0], v[1], v[2]); + if (this->isValid(shader, name, GL_INT_VEC3)) + glUniform3i(this->location, v[0], v[1], v[2]); } void @@ -179,8 +179,8 @@ SoGLSLShaderParameter::set4i(const SoGLShaderObject * shader, const int32_t * v, const char * name, const int) { - if (this->isValid(shader, name, GL_INT_VEC4_ARB)) - shader->GLContext()->glUniform4iARB(this->location, v[0], v[1], v[2], v[3]); + if (this->isValid(shader, name, GL_INT_VEC4)) + glUniform4i(this->location, v[0], v[1], v[2], v[3]); } void @@ -190,7 +190,7 @@ SoGLSLShaderParameter::set1iv(const SoGLShaderObject * shader, const int) { if (this->isValid(shader, name, GL_INT)) - shader->GLContext()->glUniform1ivARB(this->location, num, (const GLint*) value); + glUniform1iv(this->location, num, (const GLint*) value); } void @@ -199,8 +199,8 @@ SoGLSLShaderParameter::set2iv(const SoGLShaderObject * shader, const int32_t * value, const char * name, const int) { - if (this->isValid(shader, name, GL_INT_VEC2_ARB)) - shader->GLContext()->glUniform2ivARB(this->location, num, (const GLint*)value); + if (this->isValid(shader, name, GL_INT_VEC2)) + glUniform2iv(this->location, num, (const GLint*)value); } void @@ -209,8 +209,8 @@ SoGLSLShaderParameter::set3iv(const SoGLShaderObject * shader, const int32_t * v, const char * name, const int) { - if (this->isValid(shader, name, GL_INT_VEC3_ARB)) - shader->GLContext()->glUniform3ivARB(this->location, num, (const GLint*)v); + if (this->isValid(shader, name, GL_INT_VEC3)) + glUniform3iv(this->location, num, (const GLint*)v); } void @@ -219,8 +219,8 @@ SoGLSLShaderParameter::set4iv(const SoGLShaderObject * shader, const int32_t * v, const char * name, const int) { - if (this->isValid(shader, name, GL_INT_VEC4_ARB)) - shader->GLContext()->glUniform4ivARB(this->location, num, (const GLint*)v); + if (this->isValid(shader, name, GL_INT_VEC4)) + glUniform4iv(this->location, num, (const GLint*)v); } SbBool @@ -232,14 +232,14 @@ SoGLSLShaderParameter::isEqual(GLenum type1, GLenum type2) if (type2 == GL_INT) { switch (type1) { case GL_INT: - case GL_SAMPLER_1D_ARB: - case GL_SAMPLER_2D_ARB: - case GL_SAMPLER_3D_ARB: - case GL_SAMPLER_CUBE_ARB: - case GL_SAMPLER_1D_SHADOW_ARB: - case GL_SAMPLER_2D_SHADOW_ARB: - case GL_SAMPLER_2D_RECT_ARB: - case GL_SAMPLER_2D_RECT_SHADOW_ARB: + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_RECT: + case GL_SAMPLER_2D_RECT_SHADOW: return TRUE; default: return FALSE; @@ -282,8 +282,7 @@ SoGLSLShaderParameter::isValid(const SoGLShaderObject * shader, const cc_glglue * g = shader->GLContext(); this->cacheSize = 0; - this->location = g->glGetUniformLocationARB(pHandle, - (const COIN_GLchar *)name); + this->location = glGetUniformLocation(pHandle, (const COIN_GLchar *)name); this->programid = pId; if (this->location == -1) { @@ -295,7 +294,7 @@ SoGLSLShaderParameter::isValid(const SoGLShaderObject * shader, return FALSE; } GLint activeUniforms = 0; - g->glGetObjectParameterivARB(pHandle, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeUniforms); + glGetProgramiv(pHandle, GL_ACTIVE_UNIFORMS, &activeUniforms); GLint i; GLint tmpSize = 0; @@ -309,8 +308,7 @@ SoGLSLShaderParameter::isValid(const SoGLShaderObject * shader, // this will only happen once after the variable has been added so // it's not a performance issue that we have to search for it here. for (i = 0; i < activeUniforms; i++) { - g->glGetActiveUniformARB(pHandle, i, 128, &length, &tmpSize, - &tmpType, myName); + glGetActiveUniform(pHandle, i, 128, &length, &tmpSize, &tmpType, myName); if (this->cacheName == myName) { this->cacheSize = tmpSize; this->cacheType = tmpType; diff --git a/src/shaders/SoGLSLShaderProgram.cpp b/src/shaders/SoGLSLShaderProgram.cpp index 3b9583aa400..57b088a6483 100644 --- a/src/shaders/SoGLSLShaderProgram.cpp +++ b/src/shaders/SoGLSLShaderProgram.cpp @@ -35,6 +35,7 @@ #include #include +#include "Inventor/C/glue/gl.h" #include "shaders/SoGLSLShaderObject.h" #include #include "glue/glp.h" @@ -113,7 +114,14 @@ SoGLSLShaderProgram::enable(const cc_glglue * g) if (this->isExecutable) { COIN_GLhandle programhandle = this->getProgramHandle(g, TRUE); - g->glUseProgramObjectARB(programhandle); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (cc_glglue_context_supports_legacy_rendering(g)) { + g->glUseProgramObjectARB(programhandle); + } else +#endif + { + glUseProgram(programhandle); + } if (SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderProgram::enable")) { SoGLSLShaderObject::printInfoLog(g, programhandle, 0); @@ -125,7 +133,14 @@ void SoGLSLShaderProgram::disable(const cc_glglue * g) { if (this->isExecutable) { - g->glUseProgramObjectARB(0); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (cc_glglue_context_supports_legacy_rendering(g)) { + g->glUseProgramObjectARB(0); + } else +#endif + { + glUseProgram(0); + } } } @@ -180,19 +195,49 @@ SoGLSLShaderProgram::ensureLinking(const cc_glglue * g) } - g->glLinkProgramARB(programHandle); + if (cc_glglue_context_supports_legacy_rendering(g)) { + g->glLinkProgramARB(programHandle); - if (SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderProgram::ensureLinking")) { - SoGLSLShaderObject::printInfoLog(g, programHandle, 0); + if (SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderProgram::ensureLinking")) { + SoGLSLShaderObject::printInfoLog(g, programHandle, 0); + } + + g->glGetObjectParameterivARB(programHandle, + GL_OBJECT_LINK_STATUS_ARB, &didLink); + } else { + glLinkProgram(programHandle); + glGetProgramiv(programHandle, GL_LINK_STATUS, &didLink); + + if (SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderProgram::ensureLinking") + || !didLink) { + printInfoLog(g, programHandle); + } } - g->glGetObjectParameterivARB(programHandle, - GL_OBJECT_LINK_STATUS_ARB,&didLink); this->isExecutable = didLink; this->neededlinking = TRUE; } } +void +SoGLSLShaderProgram::printInfoLog(const cc_glglue * g, COIN_GLhandle handle) +{ + GLint length = 0; + glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &length); + + if (length > 1) { + COIN_GLchar *infoLog = new COIN_GLchar[length]; + GLsizei charsWritten = 0; + glGetProgramInfoLog(handle, length, &charsWritten, infoLog); + + SoDebugError::postInfo("SoGLSLShaderProgram::printInfoLog", + "program log: '%s'", + infoLog); + delete [] infoLog; + } +} + + int SoGLSLShaderProgram::indexOfShaderObject(SoGLSLShaderObject *shaderObject) { @@ -216,7 +261,11 @@ SoGLSLShaderProgram::getProgramHandle(const cc_glglue * g, const SbBool create) { COIN_GLhandle handle = 0; if (!this->programHandles.get(g->contextid, handle) && create) { - handle = g->glCreateProgramObjectARB(); + if (cc_glglue_context_supports_legacy_rendering(g)) { + handle = g->glCreateProgramObjectARB(); + } else { + handle = glCreateProgram(); + } this->programHandles.put(g->contextid, handle); } return handle; diff --git a/src/shaders/SoGLSLShaderProgram.h b/src/shaders/SoGLSLShaderProgram.h index 144362c82d0..0cf189ea532 100644 --- a/src/shaders/SoGLSLShaderProgram.h +++ b/src/shaders/SoGLSLShaderProgram.h @@ -82,6 +82,7 @@ class SoGLSLShaderProgram SbBool isExecutable; SbBool neededlinking; + static void printInfoLog(const cc_glglue * g, COIN_GLhandle handle); int indexOfShaderObject(SoGLSLShaderObject * shaderObject); void ensureLinking(const cc_glglue * g); void ensureProgramHandle(const cc_glglue * g); diff --git a/src/shaders/SoShaderObject.cpp b/src/shaders/SoShaderObject.cpp index a95db9da715..62c8ed16eb4 100644 --- a/src/shaders/SoShaderObject.cpp +++ b/src/shaders/SoShaderObject.cpp @@ -606,7 +606,11 @@ SoShaderObjectP::isSupported(SoShaderObject::SourceType sourceType, const cc_glg return SoGLDriverDatabase::isSupported(glue, SO_GL_ARB_VERTEX_PROGRAM); } else if (sourceType == SoShaderObject::GLSL_PROGRAM) { +#if !defined(COIN_BUILD_LEGACY_GL_RENDERER) + return TRUE; +#else return SoGLDriverDatabase::isSupported(glue, SO_GL_ARB_SHADER_OBJECT); +#endif } // FIXME: Add support for detecting missing Cg support // (20050427 handegar) @@ -621,7 +625,11 @@ SoShaderObjectP::isSupported(SoShaderObject::SourceType sourceType, const cc_glg return SoGLDriverDatabase::isSupported(glue, SO_GL_ARB_FRAGMENT_PROGRAM); } else if (sourceType == SoShaderObject::GLSL_PROGRAM) { +#if !defined(COIN_BUILD_LEGACY_GL_RENDERER) + return TRUE; +#else return SoGLDriverDatabase::isSupported(glue, SO_GL_ARB_SHADER_OBJECT); +#endif } // FIXME: Add support for detecting missing Cg support (20050427 // handegar) @@ -631,9 +639,12 @@ SoShaderObjectP::isSupported(SoShaderObject::SourceType sourceType, const cc_glg else { assert(this->owner->isOfType(SoGeometryShader::getClassTypeId())); if (sourceType == SoShaderObject::GLSL_PROGRAM) { - return - SoGLDriverDatabase::isSupported(glue, "GL_EXT_geometry_shader4") && - SoGLDriverDatabase::isSupported(glue, SO_GL_ARB_SHADER_OBJECT); +#if !defined(COIN_BUILD_LEGACY_GL_RENDERER) + return TRUE; +#else + return SoGLDriverDatabase::isSupported(glue, "GL_EXT_geometry_shader4") + && SoGLDriverDatabase::isSupported(glue, SO_GL_ARB_SHADER_OBJECT); +#endif } return FALSE; } From b2ca1d91cc9b05eccebad62a53f8345cc40c63df Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Wed, 29 Jul 2026 11:04:01 +0100 Subject: [PATCH 2/3] gl: isolate ancillary compatibility-only helpers Material, texture-combine, and GLU helpers still pulled compatibility-only declarations into the core build after the main traversal paths were isolated. Guard those ancillary helpers and keep protocol definitions available through the profile-neutral glue. This removes the remaining compile-time dependencies without changing legacy behavior. --- src/bundles/SoMaterialBundle.cpp | 4 +++- src/elements/SoTextureCombineElement.cpp | 7 ++++++- src/fonts/freetype.cpp | 1 - src/glue/gl.cpp | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/bundles/SoMaterialBundle.cpp b/src/bundles/SoMaterialBundle.cpp index ead840a5f36..8458abd99fa 100644 --- a/src/bundles/SoMaterialBundle.cpp +++ b/src/bundles/SoMaterialBundle.cpp @@ -76,10 +76,12 @@ SoMaterialBundle::SoMaterialBundle(SoAction *action) if (SoLazyElement::getLightModel(this->state) == SoLazyElement::BASE_COLOR) this->coloronly |= FLAG_COLORONLY; +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) const cc_glglue * glue = sogl_glue_instance(this->state); - if (glue->nvidia_color_per_face_bug) { + if (glue && glue->nvidia_color_per_face_bug) { this->coloronly |= FLAG_NVIDIA_BUG; } +#endif } /*! diff --git a/src/elements/SoTextureCombineElement.cpp b/src/elements/SoTextureCombineElement.cpp index b869a9d9e8e..05ad739ddae 100644 --- a/src/elements/SoTextureCombineElement.cpp +++ b/src/elements/SoTextureCombineElement.cpp @@ -269,7 +269,7 @@ SoTextureCombineElement::apply(SoState * state, const int unit) assert(unit < PRIVATE(elem)->unitdata.getLength()); const UnitData & ud = PRIVATE(elem)->unitdata[unit]; - +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, static_cast(ud.rgboperation)); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, static_cast(ud.alphaoperation)); @@ -294,6 +294,11 @@ SoTextureCombineElement::apply(SoState * state, const int unit) ud.constantcolor.getValue()); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, ud.rgbscale); glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, ud.alphascale); +#else + (void) state; + (void) unit; + (void) ud; +#endif } SoTextureCombineElement::UnitData::UnitData() diff --git a/src/fonts/freetype.cpp b/src/fonts/freetype.cpp index 8337bc9a3b1..d395a1668c2 100644 --- a/src/fonts/freetype.cpp +++ b/src/fonts/freetype.cpp @@ -1111,7 +1111,6 @@ cc_flwft_get_vector_glyph(void * font, unsigned int glyphindex, float complexity cc_ftglue_FT_Done_Glyph((FT_Glyph) g); return new_vector_glyph; - } static void diff --git a/src/glue/gl.cpp b/src/glue/gl.cpp index 9739a28e752..5ab2bf69805 100644 --- a/src/glue/gl.cpp +++ b/src/glue/gl.cpp @@ -244,6 +244,8 @@ #include #include /* SHRT_MAX */ +#include + #ifdef HAVE_AGL #include #endif /* HAVE_AGL */ @@ -265,8 +267,6 @@ #include #endif /* HAVE_EGL */ -#include - #include #include #include From e3b2309ecdb94fc387d4361a93e36e073e99b81b Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Wed, 29 Jul 2026 15:52:20 +0100 Subject: [PATCH 3/3] gl: isolate compatibility-only display-list operations Display-list allocation, compilation, and teardown are compatibility-profile operations, but the element must remain safe to reference while retained rendering is active. Keep display-list lifetime management behind the compatibility boundary and preserve the logical element behavior for code that still traverses legacy nodes. Core-profile builds therefore retain the ABI without issuing display-list commands. --- src/elements/GL/SoGLDisplayList.cpp | 85 ++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/src/elements/GL/SoGLDisplayList.cpp b/src/elements/GL/SoGLDisplayList.cpp index 13af1383de6..50dd4193266 100644 --- a/src/elements/GL/SoGLDisplayList.cpp +++ b/src/elements/GL/SoGLDisplayList.cpp @@ -77,6 +77,7 @@ class SoGLDisplayListP { int openindex; SbBool mipmap; GLenum texturetarget; + SbBool hasGLCompatibilityProfile; }; #define PRIVATE(obj) obj->pimpl @@ -96,6 +97,7 @@ SoGLDisplayList::SoGLDisplayList(SoState * state, Type type, int allocnum, PRIVATE(this)->refcount = 0; PRIVATE(this)->mipmap = mipmaptexobj; PRIVATE(this)->texturetarget = 0; + PRIVATE(this)->hasGLCompatibilityProfile = sogl_context_supports_legacy_rendering(state); #if COIN_DEBUG && 0 // debug SoDebugError::postInfo("SoGLDisplayList::SoGLDisplayList", "%p", this); @@ -170,7 +172,13 @@ SoGLDisplayList::SoGLDisplayList(SoState * state, Type type, int allocnum, } if (PRIVATE(this)->type == DISPLAY_LIST) { - PRIVATE(this)->firstindex = (unsigned int) glGenLists(allocnum); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (sogl_context_supports_legacy_rendering(state)) { + PRIVATE(this)->firstindex = (unsigned int) glGenLists(allocnum); + } +#else + assert(0 && "Not implemented for non-compatibility GL renderer"); +#endif if (PRIVATE(this)->firstindex == 0) { SoDebugError::post("SoGLDisplayList::SoGLDisplayList", "Could not reserve %d displaylist%s. " @@ -193,21 +201,28 @@ SoGLDisplayList::~SoGLDisplayList() SoDebugError::postInfo("SoGLDisplayList::~SoGLDisplayList", "%p", this); #endif // debug - if (PRIVATE(this)->type == DISPLAY_LIST) { - glDeleteLists((GLuint) PRIVATE(this)->firstindex, PRIVATE(this)->numalloc); - } - else { - assert(PRIVATE(this)->type == TEXTURE_OBJECT); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (PRIVATE(this)->hasGLCompatibilityProfile) { + if (PRIVATE(this)->type == DISPLAY_LIST) { + glDeleteLists((GLuint) PRIVATE(this)->firstindex, PRIVATE(this)->numalloc); + } + else { + assert(PRIVATE(this)->type == TEXTURE_OBJECT); - const cc_glglue * glw = cc_glglue_instance(PRIVATE(this)->context); - assert(cc_glglue_has_texture_objects(glw)); + const cc_glglue * glw = cc_glglue_instance(PRIVATE(this)->context); + assert(cc_glglue_has_texture_objects(glw)); - // Use temporary variable in case GLUint != unsigned int. - GLuint tmpindex = (GLuint) PRIVATE(this)->firstindex; - // It is only possible to create one texture object at a time, so - // there's only one index to delete. - cc_glglue_glDeleteTextures(glw, 1, &tmpindex); + // Use temporary variable in case GLUint != unsigned int. + GLuint tmpindex = (GLuint) PRIVATE(this)->firstindex; + // It is only possible to create one texture object at a time, so + // there's only one index to delete. + cc_glglue_glDeleteTextures(glw, 1, &tmpindex); + } } +#else + assert(0 && "Not implemented for non-compatibility GL renderer"); +#endif + delete PRIVATE(this); } @@ -242,10 +257,16 @@ SoGLDisplayList::open(SoState * state, int index) { if (PRIVATE(this)->type == DISPLAY_LIST) { PRIVATE(this)->openindex = index; - // using GL_COMPILE here instead of GL_COMPILE_AND_EXECUTE will - // lead to much higher performance on nVidia cards, and doesn't - // hurt performance for other vendors. - glNewList((GLuint) (PRIVATE(this)->firstindex+PRIVATE(this)->openindex), GL_COMPILE); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (sogl_context_supports_legacy_rendering(state)) { + // using GL_COMPILE here instead of GL_COMPILE_AND_EXECUTE will + // lead to much higher performance on nVidia cards, and doesn't + // hurt performance for other vendors. + glNewList((GLuint) (PRIVATE(this)->firstindex+PRIVATE(this)->openindex), GL_COMPILE); + } +#else + assert(0 && "Not implemented for non-compatibility GL renderer"); +#endif } else { assert(PRIVATE(this)->type == TEXTURE_OBJECT); @@ -261,15 +282,21 @@ void SoGLDisplayList::close(SoState * COIN_UNUSED_ARG(state)) { if (PRIVATE(this)->type == DISPLAY_LIST) { - glEndList(); - GLenum err = sogl_glerror_debugging() ? glGetError() : GL_NO_ERROR; - if (err == GL_OUT_OF_MEMORY) { - SoDebugError::post("SoGLDisplayList::close", - "Not enough memory resources available on system " - "to store full display list. Expect flaws in " - "rendering."); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (sogl_context_supports_legacy_rendering(state)) { + glEndList(); + GLenum err = sogl_glerror_debugging() ? glGetError() : GL_NO_ERROR; + if (err == GL_OUT_OF_MEMORY) { + SoDebugError::post("SoGLDisplayList::close", + "Not enough memory resources available on system " + "to store full display list. Expect flaws in " + "rendering."); + } + glCallList((GLuint) (PRIVATE(this)->firstindex + PRIVATE(this)->openindex)); } - glCallList((GLuint) (PRIVATE(this)->firstindex + PRIVATE(this)->openindex)); +#else + assert(0 && "Not implemented for non-compatibility GL renderer"); +#endif } else { const cc_glglue * glw = cc_glglue_instance(PRIVATE(this)->context); @@ -291,7 +318,13 @@ void SoGLDisplayList::call(SoState * state, int index) { if (PRIVATE(this)->type == DISPLAY_LIST) { - glCallList((GLuint) (PRIVATE(this)->firstindex + index)); +#if defined(COIN_BUILD_LEGACY_GL_RENDERER) + if (sogl_context_supports_legacy_rendering(state)) { + glCallList((GLuint) (PRIVATE(this)->firstindex + index)); + } +#else + assert(0 && "Not implemented for non-compatibility GL renderer"); +#endif } else { assert(PRIVATE(this)->type == TEXTURE_OBJECT);