在Android/Java上安全使用glMapBufferRange()

rha*_*oto 18 java android opengl-es opengl-es-3.0

我使用glMapBufferRange()Android上的OpenGL-ES 3.0 使用的代码如下所示:

  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);
Run Code Online (Sandbox Code Playgroud)

我的问题是关于向下转换的结果glMapBufferRange(),以ByteBuffer在第三行.glMapBufferRange()声明为返回一个Buffer:

public static Buffer glMapBufferRange (int target, int offset, int length, int access)

在我的测试平台上,该函数返回一个子类,ByteBuffer因此转换工作正常,但对支持OpenGL-ES 3+的所有平台或Android版本进行此假设似乎不太安全.虽然看起来很合理,但我没有找到任何保证它的文档,如果保证它似乎应该声明函数返回ByteBuffer.

使用Buffer返回的正确方法(最好是文档支持)是glMapBufferRange()什么?

Ret*_*adi 6

正如您已经发现的那样,缺少文档.但仍然有一个相当确定的参考:OpenGL Java绑定的实现是公共Android源代码的一部分.

如果你看一下jNI包装器的实现glMapBufferRange(),它位于文件glMapBufferRange.cpp中,你可以看到通过调用一个名为的函数来分配缓冲区NewDirectByteBuffer().基于此,似乎可以安全地假设缓冲区确实是一个ByteBuffer.

虽然供应商可以更改Android代码,但似乎任何人都不太可能改变Java绑定的行为(除了可能修复错误).如果您担心在以后的Android版本中实现可能会发生变化,您当然可以使用标准的Java类型检查:

Buffer buf = glMapBufferRange(...);
ByteBuffer byteBuf = null;
if (buf instanceof ByteBuffer) {
    byteBuf = (ByteBuffer)buf;
}
Run Code Online (Sandbox Code Playgroud)

或者你可以使用更精细的反射,从调用getClass()返回的缓冲区开始.接下来的问题当然是如果返回的缓冲区不是a,你会怎么做ByteBuffer.它真的是唯一对我有意义的类型.

  • 你可能想设置`byteBuf.order(ByteOrder.nativeOrder())`,我花了一段时间才弄明白。 (2认同)