从GraphicBuffer读取时意外的像素数据布局 [英] Unexpected pixel data layout when reading from GraphicBuffer

查看:1279
本文介绍了从GraphicBuffer读取时意外的像素数据布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前工作在原生的Andr​​oid框架,我用GraphicBuffer分配内存,然后从它创建一个EGLImage的平台。这然后用作在OpenGL纹理我渲染到(用一个简单的全屏四)。

现在的问题是,当我读到从GraphicBuffer呈现的像素数据,我希望它是在内存中的线性RGBA格式,但结果却是它包含的图像和重叠像素3 parallell小克隆纹理。也许这样的描述并没有说太多,但问题是实际像素数据是有意义的,但在内存布局似乎有什么东西比线性RGBA等。我想这是因为显卡驱动程序存储像素的内部格式比线性RGBA等。

如果我渲染一个标准的OpenGL纹理和阅读glReadPixels一切正常,所以我认为问题在于我与GraphicBuffer定制的内存分配。

如果原因是司机的内存布局,有没有办法迫使布局线性RGBA的?我已经尝试大部分供给到GraphicBuffer构造没有成功的使用标志。如果没有,有没有办法输出着色器中的数据不同,以抵消的内存布局?

我建立的Andr​​oid 4.4.3的Nexus 5。

  //分配graphicbuffer
OUTPUTBUFFER =新GraphicBuffer(outputFormat.width,outputFormat.height,outputFormat.bufferFormat,
        GraphicBuffer :: USAGE_SW_READ_OFTEN |
        GraphicBuffer :: USAGE_HW_RENDER |
        GraphicBuffer :: USAGE_HW_TEXTURE);

/ * ... * /

//从graphicbuffer创建EGLImage
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(显示器,EGL_NO_CONTEXT,EGL_NATIVE_BUFFER_ANDROID,nativeBuffer,eglImageAttributes);

/ * ... * /

//创建输出质感
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);

/ * ... * /

//创建目标FBO
glGenFramebuffers(1,&安培; targetFBO);
glBindFramebuffer(GL_FRAMEBUFFER,targetFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,outputTexture,0);

glBindFramebuffer(GL_FRAMEBUFFER,0);
/ * ... * /
//读取从graphicbuffer
常量矩形lockBoundsOutput(quadRenderer-> outputFormat.width,quadRenderer-> outputFormat.height);

status_t statusgb = quadRenderer-> getOutputBuffer() - >锁(GraphicBuffer :: USAGE_SW_READ_OFTEN,和放大器;结果);
 

解决方案

我设法找到了自己的答案,我错了一直。简单的原因是,尽管我被渲染​​480x1080纹理分配的内存被填充到640x1080,所以我只需要每一行和每一输出质感有道理后删除填充。

I am currently working on a platform in the native Android framework where I use GraphicBuffer to allocate memory and then create an EGLImage from it. This is then used as a texture in OpenGL which I render to (with a simple fullscreen quad).

The problem is when I read the rendered pixel data from the GraphicBuffer, I expect it to be in a linear RGBA format in memory but the result is a texture which contains three parallell smaller clones of the image and with overlapping pixels. Maybe that description doesn't say much but the point is the actual pixel data makes sense but the memory layout seems to be something other than linear RGBA. I assume this is because the graphics drivers store the pixels in an internal format other than linear RGBA.

If I render to a standard OpenGL texture and read with glReadPixels everything works fine, so I assume the problem lies with my custom memory allocation with GraphicBuffer.

If the reason is the drivers' internal memory layout, is there any way of forcing the layout to linear RGBA? I have tried most of the usage flags supplied to the GraphicBuffer constructor with no success. If not, is there a way to output the data differently in the shader to "cancel out" the memory layout?

I am building Android 4.4.3 for Nexus 5.

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

解决方案

I managed to find the answer myself and I was wrong all along. The simple reason was that although I was rendering a 480x1080 texture the memory allocated was padded to 640x1080 so I just needed to remove the padding after each row and the output texture made sense.

这篇关于从GraphicBuffer读取时意外的像素数据布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆