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 :(

1 Answer

 //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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest