I encountered the following issue on imx6q (Android ICS): "GraphicBuffer memory attached as the texture to FBO not updated after rendering".
I'm trying to render into texture that is attached to the frame buffer object. However in order to avoid a lengthy glReadPixels operation from the GPU texture, I'm trying to do the following:
1) Create GraphicBuffer object:
GraphicBuffer *renderGraphicBuffer = new GraphicBuffer(imageWidth,
imageHeight,
PIXEL_FORMAT_RGBA_8888,
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
2) Create EGL Image from GraphicBuffer object:
const EGLint imageAttrs[] = {
EGL_WIDTH, displayWidth,
EGL_HEIGHT, displayHeight,
EGL_MATCH_FORMAT_KHR, EGL_FORMAT_RGBA_8888_KHR,
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_NONE
};
EGLImageKHR eglRenderImageHandle = eglCreateImageKHR(eglDisplay,
EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID,
renderGraphicBuffer->getNativeBuffer(),
imageAttrs);
3) Create a texture and attach the EGL Image to the same texture:
GLuint framebufferTexture;
glGenTextures(1, &framebufferTexture);
glBindTexture(GL_TEXTURE_2D, framebufferTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglRenderImageHandle);
4) Create FBO and attach texture as GL_COLOR_ATTACHMENT0:
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferTexture, 0);
5) I render some pixels into framebufferTexture:
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0, 0, imageWidth, imageHeight);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glFinish();
6) After I complete rendering, I copy the contest of renderGraphicBuffer into some temporary buffer destination that I transfer to my PC for inspection:
void *tex = 0;
renderGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &tex);
memcpy(destination, tex, imageWidth * imageHeight * 4);
renderGraphicBuffer->unlock();
The problem is that when I use the code from 6) I get black image. If I replace code from 6) with the following, picture looks good:
glReadPixels(0, 0, imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE, destination);
My question: Does imx6q GPU support attaching GraphicBuffer to the output texture and if it does, what I'm doing wrong?
Has anyone tried this? BTW, this approach is well documented on the Internet and people tried this before (not necessarily on imx6)
I attached complete test program with the makefile. The program works but to read pixels I use glReadPixels. If I replace glReadPixels with byte by byte copy from target texture buffer to the texture buffer I get black image as if target buffer doesn't reflect changes done to its texture during rendering pass. In the attached test code, lines 236-238 work. Lines 240-247 don't work.
Update:
After looking into ASOP code and reading some useful links I'm starting to understand Android mechanism to move graphic buffers through processing stages without using glReadPixels or memcpy. But the problem I encountered seems to be a supported feature on other GPUs so I was suprised that it didn't work as I expected. It could be still the case that there is an error in the code and if somebody knows the fix it would be good to know it because we could still use that method in some cases to simplify implementation.
If somebody is interested the following links are good to understand Android graphic buffers pipeline:
https://github.com/google/grafika
https://source.android.com/devices/graphics.html
https://source.android.com/devices/graphics/architecture.html
Original Attachment has been moved to: galileo_direct_texture_test.zip
Android Surfaceflinger mostly use GPU 2D to accelerate surface composition, the interface is Hwcomposer provided by Vivante.
According to the test, composition with GPU 2D has high efficiency and lower power consumption than GPU 3D.
Have a great day,
Victor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I'm having the exact same issue. The same code path works in every other GPU except Vivante. I'm wondering is there any other way to read data from a texture? I tried using glTexDirectVIV but that one is also always returning a null pointer to me.
I appear to have the exact same issue.
Using the IMX6 Quad, how do you copy a rendered image to another OpenGLES/EGL Context or CPU application?
Emphasis on the RENDERED. The image was made in OpenGLES and it's in an FBO.
glReadPixels() has utterly hideous performance, and context sharing doesn't seem to work at all.