Uso seguro de glMapBufferRange() en Android/Java
opengl-es opengl-es-3.0 (1)
Tengo un código de trabajo que utiliza glMapBufferRange()
de OpenGL-ES 3.0 en Android que se ve así:
glBindBuffer(GL_ARRAY_BUFFER, myVertexBufferName);
glBufferData(GL_ARRAY_BUFFER, myVertexBufferSize, null, GL_STATIC_DRAW);
ByteBuffer mappedBuffer = (ByteBuffer)glMapBufferRange(
GL_ARRAY_BUFFER,
0, myVertexBufferSize,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
// [fill buffer...]
glUnmapBuffer(GL_ARRAY_BUFFER);
Mi pregunta es acerca de glMapBufferRange()
el resultado de glMapBufferRange()
a ByteBuffer
en la tercera línea. glMapBufferRange()
se declara para devolver un Buffer
:
public static Buffer glMapBufferRange (int target, int offset, int length, int access)
En mi plataforma de prueba, la función devuelve una subclase de ByteBuffer
para que el reparto funcione, pero esta suposición para todas las plataformas o versiones de Android que admiten OpenGL-ES 3+ no parece muy segura. Aunque parece razonable, no he encontrado ninguna documentación que lo garantice, y si estuviera garantizado, parece que la función debería declararse como ByteBuffer
devolución.
¿Cuál es la forma correcta (preferiblemente respaldada por la documentación) de usar el Buffer
devuelto por glMapBufferRange()
?
Como ya se ha encontrado, falta la documentación. Pero todavía hay una referencia bastante concluyente: la implementación de los enlaces OpenGL Java es parte del código fuente público de Android.
Si observa la implementación del contenedor JNI para glMapBufferRange()
, que se encuentra en el archivo glMapBufferRange.cpp , puede ver que el búfer se asigna llamando a una función llamada NewDirectByteBuffer()
. En base a esto, parece seguro asumir que el búfer es de hecho un ByteBuffer
.
Si bien los proveedores pueden cambiar el código de Android, parece muy poco probable que alguien cambie el comportamiento de los enlaces de Java (excepto tal vez para corregir errores). Si le preocupa que la implementación pueda cambiar en versiones posteriores de Android, puede utilizar una comprobación de tipo Java estándar:
Buffer buf = glMapBufferRange(...);
ByteBuffer byteBuf = null;
if (buf instanceof ByteBuffer) {
byteBuf = (ByteBuffer)buf;
}
O podría usar una reflexión más elaborada, empezando por llamar a getClass()
en el búfer devuelto. La siguiente pregunta es, por supuesto, qué hacer si el búfer devuelto no es un ByteBuffer
. Es realmente el único tipo que tiene sentido para mí.