Android OpenGL GLES20中使用glTexImage2D的内存违规

时间:2016-02-22 22:31:51

标签: android opengl-es bitmap bytearray bytebuffer

我有一个位图(可以转换为ByteBuffer)。我希望通过偏移将所有6个面部上传到OpenGL中的GPU。当我执行以下操作时,应用程序会因OpenGL崩溃而导致内存违规。

此处bitmap是字节数组byte[]

for (int i=0 ; i<6 ; i++) {
      GLES20.glTexImage2D(
          GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
          0,
          GLES20.GL_RGBA,
          side,
          side,
          0,
          GLES20.GL_RGBA,
          GLES20.GL_UNSIGNED_BYTE,
          ByteBuffer.wrap(bitmap, length / 6 * i, side * side * 4));
    }

但是当我复制数组然后像这样上传到GPU时(bitmap类型为Bitmap):

int numBytes = bitmap.getByteCount();
 ByteBuffer pixels = ByteBuffer.allocate(numBytes);
 bitmap.copyPixelsToBuffer(pixels);
 for (int i=0 ; i<6 ; i++) {
   Log.d("aakash", String.valueOf(numBytes / 6 * i));
   byte[] arr = Arrays.copyOfRange(pixels.array(), numBytes / 6 * i, numBytes / 6 * (i+1));
   GLES20.glTexImage2D(
       GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
       0,
       GLES20.GL_RGBA,
       bitmap.getWidth(),
       bitmap.getHeight() / 6,
       0,
       GLES20.GL_RGBA,
       GLES20.GL_UNSIGNED_BYTE,
       ByteBuffer.wrap(arr));
 }

我正确渲染了立方体贴图。

第一个我做错了什么?我想避免复制数组以将其部分上传到GPU。

我可以保证尺寸和数学计算是正确的。

1 个答案:

答案 0 :(得分:0)

为避免内存冲突,请更换

ByteBuffer pixels = ByteBuffer.allocate(numBytes);

ByteBuffer pixels = ByteBuffer.allocateDirect(numBytes);

但是你不需要ByteBuffer来进行简单的侧面纹理加载

loadSideTexture(context, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X, R.raw.lake2_rt);
loadSideTexture(context, GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_X, R.raw.lake2_lf);

loadSideTexture(context, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Y, R.raw.lake2_up);
loadSideTexture(context, GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, R.raw.lake2_dn);

loadSideTexture(context, GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Z, R.raw.lake2_bk);
loadSideTexture(context, GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, R.raw.lake2_ft);

private void loadSideTexture(Context context, int target, @RawRes int resID) {
    final Bitmap bitmap = BitmapFactory.decodeStream(context.getResources().openRawResource(resID));
    GLUtils.texImage2D(target, 0, bitmap, 0);
    bitmap.recycle();
}