dnalomaz
dnalomaz

Reputation: 61

Use glEGLImageTargetTexture2DOES to replace glReadPixels on Android

Given a textureId, I need to extract pixel data from the texture.

glReadPixels works, but it is extremely slow on some devices, even with FBO/PBO. (On Xiaomi MI 5, it is 65 ms, and even slower with PBO). So I decided to use Hardwarebuffer and eglImageKHR, which should be much faster. However, I cannot get it to work. The screen goes black, and nothing is read into the data.

 //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);

This is my code with glReadPixels, and it just can get the pixels after attaching the texture to framebuffer.

 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)

Please tell me where I did wrong :(

Upvotes: 1

Views: 7048

Answers (1)

solidpixel
solidpixel

Reputation: 12069

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

This doesn't do any reading of data. This is just setting up the texture to refer to the EGLImage. If you want data to be copied into it you need to either do glCopyTexImage2D() or bind it to a framebuffer and render in to it.

Upvotes: 2

Related Questions