使用GTK将EGL图像渲染到帧缓冲区

7
我正在尝试渲染从NVIDIA解码器获取的EGLImageKHR,将其呈现到帧缓冲区中,以便我可以在屏幕上呈现此帧缓冲区。 我编写了以下代码:
创建两个纹理:frameBufferTextureexternalTexture。我们将EGLImage写入externalTexture,并从externalTexture绘制到frameBufferTexture。然后,我们使用glReadPixelsframeBufferTexture中读取:
    glGenFramebuffers(1, &frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    glGenTextures(1, &externalTexture);
    glGenTextures(1, &frameBufferTexture);
    glBindTexture(GL_TEXTURE_2D, frameBufferTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, decodedNvFrame->width, decodedNvFrame->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glUniform1i(texLocation, 0);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    glBindTexture(GL_TEXTURE_2D, frameBufferTexture);

    EGLImageKHR hEglImage;

    hEglImage = NvEGLImageFromFd(eglDisplay, decodedNvFrame->nvBuffer->planes[0].fd);
    if (!hEglImage)
        printf("Could not get EglImage from fd. Not rendering\n");
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameBufferTexture, 0);     
    glBindTexture(GL_TEXTURE_2D, externalTexture);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, hEglImage);
    glUniform1i(texLocation, 0);
    glBindVertexArray(vertexArrayObject);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glReadBuffer(GL_COLOR_ATTACHMENT0);

    GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (frameBufferStatus!=GL_FRAMEBUFFER_COMPLETE) {
        printf("frameBufferStatus problem!\n");
        abort();
    }
    glReadPixels(0, 0, 512, 512, GL_RGBA, GL_UNSIGNED_BYTE, r);

    for (int i = 0; i < 100; ++i)
    {
        printf("%i ", r[i]);
    }
    printf("\n");

    NvDestroyEGLImage(eglDisplay, hEglImage);

注意我使用 glReadPixels 只获取帧缓冲区的一部分,以便查看正在发生的情况。

这是输出结果:

0 0 0 255 0 0 0 255 0 0 0 255 ...

我猜这个问题源于用 glTexImage2D 函数传递的参数中使用了0。这意味着glEGLImageTargetTexture2DOES 没有将图像推送到 externalTexture 中。

下面是片段着色器的代码:

#version 330 core
out vec4 FragColor;

in vec2 TexCoord;
uniform sampler2D tex;

void main()
{
    FragColor = texture(tex, TexCoord);
}

如果我将这个着色器更改为 FragColor = vec4(1.0,texture(tex, TexCoord).r,0,1.0),那么输出结果如下:

255 0 0 255 255 0 0 255 255 0 0 255 ... 

这意味着着色器正在工作并写入帧缓冲区。如果我添加

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, d);

glBindTexture(GL_TEXTURE_2D,externalTexture)之后,我能看到d的内容,这意味着我的片段着色器正确地从纹理externalTexture中写入数据。
这将问题归结为glEGLImageTargetTexture2DOES。它没有用我的图像填充externalTexture!
为什么? 提示: 我怀疑是eglDisplay的问题。为什么我需要一个显示器来创建EGLImageKHR?我看过 NVIDIA 的代码,他们使用NvEGLImageFromFd并传递来自 X11 窗口的 eglDisplay。但我在 GTK 中,不明白为什么 egl 显示器很重要,首先因为我正在渲染到帧缓冲区,但其次,当我想要渲染图像时,我会渲染到 GTK 的帧缓冲区。

glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, ...); 是非法的。glEGLImageTargetTexture2DOES 仅能以 GL_TEXTURE_EXTERNAL_OES 作为目标。 - Nicol Bolas
@NicolBolas 这很奇怪,因为在这个调用之后没有出现错误,并且当我使用glReadPixels读取时,它显然是有效的。此外,我是从他说它有效的地方获取的:https://devtalk.nvidia.com/default/topic/1028811/export-gl-texture-as-dmabuf/?offset=8#5384937。如果不使用`glEGLImageTargetTexture2DOES`,您有其他建议吗? - PPP
1
@NicolBolas 这里也使用了 https://devtalk.nvidia.com/default/topic/1030669/jetson-tx1/trying-to-process-with-opengl-an-eglimage-created-from-a-dmabuf_fd-/ - PPP
1个回答

2

Check the example implementations in nvidia

tegra_multimedia_api\argus\samples\utils\PreviewConsumer.cpp
tegra_multimedia_api\samples\common\classes\NvEglRenderer.cpp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接