从GraphicBuffer读取时出现意外的像素数据布局

时间:2014-06-27 09:54:53

标签: android c++ opengl-es android-source

我目前正在使用原生Android框架中的平台,我使用GraphicBuffer分配内存,然后从中创建EGLImage。然后将其用作OpenGL中的纹理(我使用简单的全屏四边形)。

问题是当我从GraphicBuffer读取渲染的像素数据时,我希望它在内存中采用线性RGBA格式,但结果是一个纹理,其中包含三个平行的较小的图像克隆和重叠的像素。也许这个描述并没有多说,但关键是实际的像素数据是有意义的,但内存布局似乎不是线性RGBA。我认为这是因为图形驱动程序将像素存储为线性RGBA以外的内部格式。

如果我渲染到标准的OpenGL纹理并使用glReadPixels读取一切正常,那么我认为问题在于使用GraphicBuffer进行自定义内存分配。

如果原因是司机'内部存储器布局,是否有任何方法可以将布局强制为线性RGBA?我已经尝试了提供给GraphicBuffer构造函数的大多数用法标志,但没有成功。如果没有,有没有办法在着色器中以不同的方式输出数据到"取消"内存布局?

我正在为Nexus 5构建Android 4.4.3。

//Allocate graphicbuffer
outputBuffer = new GraphicBuffer(outputFormat.width, outputFormat.height, outputFormat.bufferFormat,
        GraphicBuffer::USAGE_SW_READ_OFTEN |
        GraphicBuffer::USAGE_HW_RENDER |
        GraphicBuffer::USAGE_HW_TEXTURE);

/* ... */

//Create EGLImage from graphicbuffer
EGLint eglImageAttributes[] = {EGL_WIDTH, outputFormat.width, EGL_HEIGHT, outputFormat.height, EGL_MATCH_FORMAT_KHR,
        outputFormat.eglFormat, EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, EGL_NONE};

EGLClientBuffer nativeBuffer = outputBuffer->getNativeBuffer();

eglImage = _eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, nativeBuffer, eglImageAttributes);

/* ... */

//Create output texture
glGenTextures(1, &outputTexture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
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, eglImage);

/* ... */

//Create target fbo
glGenFramebuffers(1, &targetFBO);
glBindFramebuffer(GL_FRAMEBUFFER, targetFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, outputTexture, 0);

glBindFramebuffer(GL_FRAMEBUFFER, 0);
/* ... */
//Read from graphicbuffer
const Rect lockBoundsOutput(quadRenderer->outputFormat.width, quadRenderer->outputFormat.height);

status_t statusgb = quadRenderer->getOutputBuffer()->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &result);

1 个答案:

答案 0 :(得分:0)

我自己找到了答案,一直都是错的。原因很简单,虽然我渲染的​​是480x1080纹理,但是分配的内存被填充到640x1080,所以我只需要在每行之后删除填充,输出纹理就有意义。