From e99a2f7cae49c6777eebdb6e5401b1be87ec5b09 Mon Sep 17 00:00:00 2001 From: dbp Date: Thu, 16 Apr 2015 16:03:55 +0300 Subject: [PATCH] 0026081: Visualization, TKOpenGl - rebuild vertex attributes in order to not render large index arrays in OpenGL ES --- src/OpenGl/OpenGl_Context.cxx | 6 ++- src/OpenGl/OpenGl_Context.hxx | 1 + src/OpenGl/OpenGl_PrimitiveArray.cxx | 59 +++++++++++++++++++++++++--- src/OpenGl/OpenGl_PrimitiveArray.hxx | 3 ++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 7e53da093f..060576c110 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -83,9 +83,11 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) caps (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()), #if defined(GL_ES_VERSION_2_0) hasHighp (Standard_False), + hasUintIndex(Standard_False), hasTexRGBA8(Standard_False), #else hasHighp (Standard_True), + hasUintIndex(Standard_True), hasTexRGBA8(Standard_True), #endif arbNPTW (Standard_False), @@ -1057,7 +1059,9 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs)); } - hasHighp = CheckExtension ("GL_OES_fragment_precision_high"); + hasUintIndex = IsGlGreaterEqual (3, 0) + || CheckExtension ("GL_OES_element_index_uint"); + hasHighp = CheckExtension ("GL_OES_fragment_precision_high"); GLint aRange[2] = {0, 0}; GLint aPrec = 0; ::glGetShaderPrecisionFormat (GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, aRange, &aPrec); diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index ce67d6012a..47caab9b13 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -595,6 +595,7 @@ public: //! @name core profiles public: //! @name extensions Standard_Boolean hasHighp; //!< highp in GLSL ES fragment shader is supported + Standard_Boolean hasUintIndex; //!< GLuint for index buffer is supported (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_element_index_uint) Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8 Standard_Boolean arbNPTW; //!< GL_ARB_texture_non_power_of_two Standard_Boolean arbTexRG; //!< GL_ARB_texture_rg diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 4e8810ecab..6ee9083b01 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -25,6 +25,7 @@ #include #include #include +#include namespace { @@ -628,11 +629,6 @@ OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* myDrawMode (DRAW_MODE_NONE), myIsVboInit (Standard_False) { - if (theDriver != NULL) - { - myUID = theDriver->GetNextPrimitiveArrayUID(); - } - if (!myIndices.IsNull() && myIndices->NbElements < 1) { @@ -640,6 +636,18 @@ OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* myIndices.Nullify(); } + if (theDriver != NULL) + { + myUID = theDriver->GetNextPrimitiveArrayUID(); + #if defined (GL_ES_VERSION_2_0) + const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext(); + if (!aCtx.IsNull()) + { + processIndices (aCtx); + } + #endif + } + setDrawMode (theType); } @@ -700,6 +708,9 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace const Standard_Boolean toKeepData = myDrawMode == GL_POINTS && !anAspectMarker->SpriteRes (aCtx).IsNull() && anAspectMarker->SpriteRes (aCtx)->IsDisplayList(); + #if defined (GL_ES_VERSION_2_0) + processIndices (aCtx); + #endif buildVBO (aCtx, toKeepData); myIsVboInit = Standard_True; } @@ -871,6 +882,41 @@ void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray th } } +// ======================================================================= +// function : processIndices +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const +{ + if (myIndices.IsNull() + || theContext->hasUintIndex) + { + return Standard_True; + } + + if (myIndices->NbElements > std::numeric_limits::max()) + { + Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16)); + if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes)) + { + return Standard_False; // failed to initialize attribute array + } + + for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx) + { + const Standard_Integer anIndex = myIndices->Index (anIdxIdx); + memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx, + myAttribs->Data() + myAttribs->Stride * anIndex, + myAttribs->Stride); + } + + myIndices.Nullify(); + myAttribs = anAttribs; + } + + return Standard_True; +} + // ======================================================================= // function : InitBuffers // purpose : @@ -887,6 +933,9 @@ void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& th myIndices = theIndices; myAttribs = theAttribs; myBounds = theBounds; +#if defined(GL_ES_VERSION_2_0) + processIndices (theContext); +#endif setDrawMode (theType); } diff --git a/src/OpenGl/OpenGl_PrimitiveArray.hxx b/src/OpenGl/OpenGl_PrimitiveArray.hxx index c642f01dd3..261da15002 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.hxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.hxx @@ -122,6 +122,9 @@ private: //! @param theType type of primitive array. void setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType); + //! Rebuilds the array of vertex attributes so that it can be drawn without indices. + Standard_Boolean processIndices (const Handle(OpenGl_Context)& theContext) const; + protected: mutable Handle(OpenGl_VertexBuffer) myVboIndices;