Details
Description
When calling glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices) with 'indices' being an offset in a bound buffer, the binding code fails.
In current state, the binding only accepts a pointer to an array of indices, for instance an array.array('I', ...). This is fine for direct rendering.
However, when an index buffer is bound to the opengl context with QOpenGLBuffer.bind() with the buffer type being QOpenGLBuffer.IndexBuffer, the OpenGL semantic is that 'indices' become a byte offset into the bound buffer.
Unfortunately, it is not possible to pass such an offset to the binding:
- glDrawElements(GL.GL_POINTS, 10, GL.GL_UNSIGNED_INT, 0): this fails (or any other numeric input) because the binding expect a pointer
- glDrawElements(GL.GL_POINTS, 10, GL.GL_UNSIGNED_INT, None): this fails too
- glDrawElements(GL.GL_POINTS, 10, GL.GL_UNSIGNED_INT, ctypes.c_void_p(...)): this fails also because it's not possible to pass a null pointer or a pointer to an invalid memory address (such as 0 or 1000).
I did a quick hack as follow (adding a new function variant to accept numbers instead of array pointers), and it works in both cases now:
<object-type name="QOpenGLFunctions" since="5.0"> <add-function signature="glDrawElements(int,unsigned int,int,unsigned int)"> <inject-code class="target" position="beginning"> %BEGIN_ALLOW_THREADS %CPPSELF.%FUNCTION_NAME(%1, %2, %3, (const GLvoid*)((size_t)%4)); %END_ALLOW_THREADS </inject-code> </add-function> </object-type>
The catch is that it's unsafe to pass a number if no opengl index buffer is bound to the context. Maybe that should be checked?
This kind of logic is also necessary for (non exhaustive):
- glDrawElementsBaseVertex
- glDrawElementsInstanced
- glDrawElementsInstancedBaseInstance
- glDrawElementsInstancedBaseVertex
- glDrawElementsInstancedBaseVertexBaseInstance
- glDrawRangeElements
- glDrawRangeElementsBaseVertex