GraphicsBuffer problem on Lenovo vibe X2 with PowerVR G600 with reading data from texture.

Hello,

My application needs to retrieve a lot of data from GPU. So, as once recommended here on ImgTec forums and on ARM dev forums, I use android GraphicBuffer for this purpose as glReadPixels slows down the process quite heavily. But, when I render something into it and then try to read it via GraphicBuffer, the memory pointed at the address I get with buffer->lock() contains only partially updated image data (e.g. some of the pixels contain the data from the last draw call, and another pixels contain the data which was in that texture before I made the draw call).

Here are the images of what I mean: http://1drv.ms/1Jua6lY http://1drv.ms/1Jua8u8

So, here is what I do:

  1. Create android graphics buffer
    int format = PIXEL_FORMAT_RGBA_8888;<br />
int usage = GraphicBuffer::USAGE_HW_TEXTURE |<br />
GRALLOC_USAGE_SW_READ_OFTEN |<br />
GRALLOC_USAGE_SW_WRITE_RARELY;<br />
EGLClientBuffer clientBuffer = nullptr;<br />
buffer = new android::GraphicBuffer(width, height, format, usage);<br />
clientBuffer = (EGLClientBuffer)buffer->getNativeBuffer();
```<br />
2) Create EglKHR image with this buffer attached to it<br />

EGLint eglImgAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE};

img = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,

EGL_NATIVE_BUFFER_ANDROID,

(EGLClientBuffer) clientBuffer,

eglImgAttrs);

3) Attach Egl KHR image to texture<br />

glGenTextures(1, &androidTextureId);



glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_2D, androidTextureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);



// Attach the EGLImage to whatever texture is bound to GL_TEXTURE_2D

glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img);

glBindTexture(GL_TEXTURE_2D, 0);

4) Then, I get frames from camera which are rendered into external texture, which I render into graphicsBuffer-backed texture<br />
    glBindFramebuffer(GL_FRAMEBUFFER, framebufferId);<br />

glViewport(0, 0, width, height);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, androidTextureId, 0);

glUseProgram(shDrawCameraExtTexture);

int textureLoc = glGetUniformLocation(shDrawCameraExtTexture, “sTexture”);

glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_2D, cameraTextureId);

glUniform1i(textureLoc, /GL_TEXTURE/0);



int atbCoordLocation = glGetAttribLocation(shDrawCameraExtTexture, “atbCoord”);

glEnableVertexAttribArray(atbCoordLocation);

glVertexAttribPointer(atbCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, vertCoords);

int atbTexCoordLocation = glGetAttribLocation(shDrawCameraExtTexture, “atbTextureCoord”);

glEnableVertexAttribArray(atbTexCoordLocation);

glVertexAttribPointer(atbTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texCoords);



glDrawArrays(GL_TRIANGLE_STRIP, 0, 4 );



glDisableVertexAttribArray(atbCoordLocation);

glDisableVertexAttribArray(atbTexCoordLocation);

glUseProgram(0);



glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 );

glBindFramebuffer(GL_FRAMEBUFFER, 0);

5) Then, I call glFinish(), lock the graphicsBuffer for reading and load it's data into another texture I'll write on the screen later.<br />
   glFinish();<br />

void *memPtr;

buffer->lock(mode, &memPtr);

glActiveTexture(GL_TEXTURE0);

glPixelStorei(GL_PACK_ALIGNMENT, 1);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glBindTexture(GL_TEXTURE_2D, textureToRenderId);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, buffer->stride, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, memPtr);

unlockGraphicsBuffer();



glUseProgram(shDrawAndroidTexture);

int textureLoc = glGetUniformLocation(shDrawAndroidTexture, “sTexture”);

glUniform1i(textureLoc, /GL_TEXTURE/0);



int atbCoordLocation = glGetAttribLocation(shDrawAndroidTexture, “atbCoord”);

glEnableVertexAttribArray(atbCoordLocation);

glVertexAttribPointer(atbCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, vertCoords);

int atbTexCoordLocation = glGetAttribLocation(shDrawAndroidTexture, “atbTextureCoord”);

glEnableVertexAttribArray(atbTexCoordLocation);

glVertexAttribPointer(atbTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texCoords);



glViewport(0, 0, screenWidth, screenHeight);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4 );



glDisableVertexAttribArray(atbCoordLocation);

glDisableVertexAttribArray(atbTexCoordLocation);

glBindTexture(GL_TEXTURE_2D, 0);

glUseProgram(0);

6) Then, I write zeros to graphicBuffer-backed texture so I'll clearly see the artifacts. If I skip this step, the artifacts are still present but harder to notice, because two sequential camera frames look similar unless you move the device quite quickly.<br />
<br />
This code works absolutely fine on ~10 another devices, with the only problematic device being Lenovo mentioned above. I haven't tested it on other devices with the same GPU, so I assume this may be gpu-specific bug.<br />
Could you please tell what can be wrong with this code?<br />
I can email you the sample project with this problem or provide any other additional info.<br />
Thank you.

Hello,



Could you create a support ticket here: https://pvrsupport.imgtec.com/new-ticket

The system is private so you can attach your source code there confidentially.



It may also be useful for us if you could list the devices you’ve tested against and their driver versions. We’ll see where it goes from there.



Thanks,

Paul.