Added OpenGl_Context::GetBufferSubData() implementing getBufferSubData() based on capabilities of various APIs.
Added OpenGl_VertexBuffer::GetSubData() similar to OpenGl_VertexBuffer::SubData().
#endif
#ifdef __EMSCRIPTEN__
+ #include <emscripten.h>
#include <emscripten/html5.h>
//! Check if WebGL extension is available and activate it
core45 (NULL),
core45back (NULL),
caps (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
+ hasGetBufferData (Standard_False),
#if defined(GL_ES_VERSION_2_0)
hasHighp (Standard_False),
hasUintIndex(Standard_False),
{
core30 = (OpenGl_GlCore30* )(&(*myFuncs));
core30fwd = (OpenGl_GlCore30Fwd* )(&(*myFuncs));
+ hasGetBufferData = true;
}
// load OpenGL ES 3.1 new functions
core15 = (OpenGl_GlCore15* )(&(*myFuncs));
}
core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs));
+ hasGetBufferData = true;
}
else
{
return anOldValue;
}
+// =======================================================================
+// function : GetBufferSubData
+// purpose :
+// =======================================================================
+bool OpenGl_Context::GetBufferSubData (GLenum theTarget, GLintptr theOffset, GLsizeiptr theSize, void* theData)
+{
+ if (!hasGetBufferData)
+ {
+ return false;
+ }
+#ifdef __EMSCRIPTEN__
+ EM_ASM_(
+ {
+ Module.ctx.getBufferSubData($0, $1, HEAPU8.subarray($2, $2 + $3));
+ }, theTarget, theOffset, theData, theSize);
+ return true;
+#elif defined(GL_ES_VERSION_2_0)
+ if (void* aData = core30fwd->glMapBufferRange (theTarget, theOffset, theSize, GL_MAP_READ_BIT))
+ {
+ memcpy (theData, aData, theSize);
+ core30fwd->glUnmapBuffer (theTarget);
+ return true;
+ }
+ return false;
+#else
+ core15fwd->glGetBufferSubData (theTarget, theOffset, theSize, theData);
+ return true;
+#endif
+}
+
// =======================================================================
// function : DumpJson
// purpose :
//! Set line feater width.
void SetLineFeather(Standard_ShortReal theValue) { myLineFeather = theValue; }
+ //! Wrapper over glGetBufferSubData(), implemented as:
+ //! - OpenGL 1.5+ (desktop) via glGetBufferSubData();
+ //! - OpenGL ES 3.0+ via glMapBufferRange();
+ //! - WebGL 2.0+ via gl.getBufferSubData().
+ //! @param theTarget [in] target buffer to map
+ //! @param theOffset [in] offset to the beginning of sub-data
+ //! @param theSize [in] number of bytes to read
+ //! @param theData [out] destination pointer to fill
+ //! @return FALSE if functionality is unavailable
+ Standard_EXPORT bool GetBufferSubData (GLenum theTarget, GLintptr theOffset, GLsizeiptr theSize, void* theData);
+
//! Return Graphics Driver's vendor.
const TCollection_AsciiString& Vendor() const { return myVendor; }
public: //! @name extensions
+ Standard_Boolean hasGetBufferData; //!< flag indicating if GetBufferSubData() is supported
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
using theBaseClass_t::glVertexAttribI4ubv;
using theBaseClass_t::glVertexAttribI4usv;
#endif
+
+#if defined(GL_ES_VERSION_2_0)
+ // the following functions from OpenGL 1.5 have been added only in OpenGL ES 3.0
+ using theBaseClass_t::glGenQueries;
+ using theBaseClass_t::glDeleteQueries;
+ using theBaseClass_t::glIsQuery;
+ using theBaseClass_t::glBeginQuery;
+ using theBaseClass_t::glEndQuery;
+ using theBaseClass_t::glGetQueryiv;
+ using theBaseClass_t::glGetQueryObjectuiv;
+ using theBaseClass_t::glUnmapBuffer;
+#endif
};
//! OpenGL 3.0 core based on 2.1 version.
return isDone;
}
+// =======================================================================
+// function : getSubData
+// purpose :
+// =======================================================================
+bool OpenGl_VertexBuffer::getSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ void* theData,
+ const GLenum theDataType)
+{
+ if (!IsValid() || myDataType != theDataType
+ || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb)
+ || !theGlCtx->hasGetBufferData)
+ {
+ return false;
+ }
+
+ Bind (theGlCtx);
+ const size_t aDataSize = sizeOfGlType (theDataType);
+ const GLintptr anOffset = GLintptr (theElemFrom) * GLintptr (myComponentsNb) * aDataSize;
+ const GLsizeiptr aSize = GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize;
+ bool isDone = theGlCtx->GetBufferSubData (GetTarget(), anOffset, aSize, theData);
+ isDone = isDone && (glGetError() == GL_NO_ERROR);
+ Unbind (theGlCtx);
+ return isDone;
+}
+
// =======================================================================
// function : BindVertexAttrib
// purpose :
return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
}
+ //! Read back buffer sub-range.
+ //! Notice that VBO will be unbound after this call.
+ //! Function reads portion of data from this VBO using glGetBufferSubData().
+ //! @param theElemFrom [in] element id from which replace buffer data (>=0);
+ //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
+ //! @param theData [out] destination pointer to GLfloat data.
+ bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ GLfloat* theData)
+ {
+ return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
+ }
+
//! Notice that VBO will be unbound after this call.
//! Function replaces portion of data within this VBO using glBufferSubData().
//! The VBO should be initialized before call.
return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
}
+ //! Read back buffer sub-range.
+ //! Notice that VBO will be unbound after this call.
+ //! Function reads portion of data from this VBO using glGetBufferSubData().
+ //! @param theElemFrom [in] element id from which replace buffer data (>=0);
+ //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
+ //! @param theData [out] destination pointer to GLuint data.
+ bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ GLuint* theData)
+ {
+ return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
+ }
+
//! Notice that VBO will be unbound after this call.
//! Function replaces portion of data within this VBO using glBufferSubData().
//! The VBO should be initialized before call.
return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
}
+ //! Read back buffer sub-range.
+ //! Notice that VBO will be unbound after this call.
+ //! Function reads portion of data from this VBO using glGetBufferSubData().
+ //! @param theElemFrom [in] element id from which replace buffer data (>=0);
+ //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
+ //! @param theData [out] destination pointer to GLushort data.
+ bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ GLushort* theData)
+ {
+ return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
+ }
+
//! Notice that VBO will be unbound after this call.
//! Function replaces portion of data within this VBO using glBufferSubData().
//! The VBO should be initialized before call.
return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
}
+ //! Read back buffer sub-range.
+ //! Notice that VBO will be unbound after this call.
+ //! Function reads portion of data from this VBO using glGetBufferSubData().
+ //! @param theElemFrom [in] element id from which replace buffer data (>=0);
+ //! @param theElemsNb [in] elements count (theElemFrom + theElemsNb <= GetElemsNb());
+ //! @param theData [out] destination pointer to GLubyte data.
+ bool GetSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ GLubyte* theData)
+ {
+ return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
+ }
+
//! Bind this VBO to active GLSL program.
Standard_EXPORT void BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
const GLuint theAttribLoc) const;
const void* theData,
const GLenum theDataType);
+ //! Read back buffer sub-range.
+ Standard_EXPORT virtual bool getSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ void* theData,
+ const GLenum theDataType);
+
//! Setup array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
//! or for FFP using bindFixed() when no program bound.
static void bindAttribute (const Handle(OpenGl_Context)& theGlCtx,
memcpy (myData->ChangeData() + anOffset, theData, aNbBytes);
return true;
}
+
+// =======================================================================
+// function : getSubData
+// purpose :
+// =======================================================================
+bool OpenGl_VertexBufferCompat::getSubData (const Handle(OpenGl_Context)& ,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ void* theData,
+ const GLenum theDataType)
+{
+ if (!IsValid() || myDataType != theDataType
+ || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb)
+ || theData == NULL)
+ {
+ return false;
+ }
+
+ const size_t aDataSize = sizeOfGlType (theDataType);
+ const size_t anOffset = size_t(theElemFrom) * size_t(myComponentsNb) * aDataSize;
+ const size_t aNbBytes = size_t(theElemsNb) * size_t(myComponentsNb) * aDataSize;
+ memcpy (theData, myData->Data() + anOffset, aNbBytes);
+ return true;
+}
const void* theData,
const GLenum theDataType) Standard_OVERRIDE;
+ //! Read back buffer sub-range.
+ Standard_EXPORT virtual bool getSubData (const Handle(OpenGl_Context)& theGlCtx,
+ const GLsizei theElemFrom,
+ const GLsizei theElemsNb,
+ void* theData,
+ const GLenum theDataType) Standard_OVERRIDE;
+
protected:
Handle(NCollection_Buffer) myData; //!< buffer data