首页 > 解决方案 > 在 Android 上使用 glEGLImageTargetTexture2DOES 替换 glReadPixels

问题描述

给定一个textureId,我需要从纹理中提取像素数据。

glReadPixels 可以工作,但在某些设备上非常慢,即使是 FBO/PBO。(在小米 5 上为 65 毫秒,使用 PBO 甚至更慢)。所以我决定使用Hardwarebufferand eglImageKHR,它应该更快。但是,我无法让它工作。屏幕变黑,没有任何内容被读入数据。

 //attach inputTexture to FBO
 glBindFrameBuffer(GL_FRAMEBUFFER, fbo)
 glFrameBufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0)
 
 //allocate hardware buffer
 AHardwareBuffer* buffer = nullptr;
 AHardwareBuffer_Desc desc = {};
 desc.width = width;
 desc.height = height;
 desc.layers = 1;
 desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER
            | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT ;
 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
 
//create eglImageKHR
 EGLint eglAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer);
 EGLImageKHR eglImageKhr = eglCreateImageKHR(eglDisplay, eglContext, 
 EGL_NATIVE_BUFFER_ANDROID, clientBuffer, eglAttributes);

 //read pixels to hardware buffer ????
 glBindTexture(GL_TEXTURE_2D, textureId);
 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImageKhr);

 //copy pixels into memory
 void *readPtr;
 AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, nullptr, (void**)&readPtr);
 memcpy(writePtr, readPtr, width * 4);
 AHardwareBuffer_unlock(buffer, nullptr);

这是我的代码glReadPixels,它可以在将纹理附加到帧缓冲区后获取像素。

 GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fboBuffer!![0])
 GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, 
        GLES30.GL_COLOR_ATTACHMENT0, 
        GLES30.GL_TEXTURE_2D, 
        inputTextureId, 
        0)
 GLES30.glReadPixels(0, 0, width, height, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, byteBuffer)

请告诉我哪里做错了:(

标签: androidopengl-eseglglreadpixels

解决方案


 //read pixels to hardware buffer ????
 glBindTexture(GL_TEXTURE_2D, textureId);
 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImageKhr);

这不会读取任何数据。这只是设置纹理以引用 EGLImage。如果您希望将数据复制到其中,您需要执行glCopyTexImage2D()或将其绑定到帧缓冲区并渲染到其中。


推荐阅读