【问题标题】:Unexpected pixel data layout when reading from GraphicBuffer从 GraphicBuffer 读取时出现意外的像素数据布局
【发布时间】:2014-07-08 23:09:48
【问题描述】:

我目前正在原生 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);

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 嘿,我正在尝试实现完全相同的东西,但根据这个article,应该不可能从GraphicBuffer 对象中读取纹理。可以分享一下代码吗?
    • 什么意思?如果渲染到基于GraphicBuffer的纹理,只需要同步渲染,通过lock()函数获取指向GraphicBuffer的指针,就可以读取纹理了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 2017-01-17
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多