How to render an EGLImageKHR without EGL display?

I’m looking at the following code from NVIDIA that renders an image from a file descriptor called render_fd

    EGLImageKHR hEglImage;
    bool frame_is_late = false;

    EGLSyncKHR egl_sync;
    int iErr;
    hEglImage = NvEGLImageFromFd(egl_display, render_fd);
    if (!hEglImage)
    {
        COMP_ERROR_MSG("Could not get EglImage from fd. Not rendering");
        return -1;
    }

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, hEglImage);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    iErr = glGetError();
    if (iErr != GL_NO_ERROR)
    {
        COMP_ERROR_MSG("glDrawArrays arrays failed:" << iErr);
        return -1;
    }
    egl_sync = eglCreateSyncKHR(egl_display, EGL_SYNC_FENCE_KHR, NULL);
    if (egl_sync == EGL_NO_SYNC_KHR)
    {
        COMP_ERROR_MSG("eglCreateSyncKHR() failed");
        return -1;
    }
    eglSwapBuffers(egl_display, egl_surface);
    if (eglGetError() != EGL_SUCCESS)
    {
        COMP_ERROR_MSG("Got Error in eglSwapBuffers " << eglGetError());
        return -1;
    }
    if (eglClientWaitSyncKHR (egl_display, egl_sync,
                EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR) == EGL_FALSE)
    {
        COMP_ERROR_MSG("eglClientWaitSyncKHR failed!");
    }

    if (eglDestroySyncKHR(egl_display, egl_sync) != EGL_TRUE)
    {
        COMP_ERROR_MSG("eglDestroySyncKHR failed!");
    }
    NvDestroyEGLImage(egl_display, hEglImage);

Here is the fragment shader:

    #extension GL_OES_EGL_image_external : require
    precision mediump float;
    varying vec2 interp_tc; 
    uniform samplerExternalOES tex;
    void main() {
        gl_FragColor = texture2D(tex, interp_tc);
    };

The problem is that I want to render independently from an display (or should I sar EGL display?). I might want to display it now but in the future I want to not use a display at all. I want to render to something and plug this something to another opengl program that renders it.

I found the documentation of NvEGLImageFromFd:

    EGLImageKHR NvEGLImageFromFd(EGLDisplay display, int dmabuf_fd) 		

Creates an EGLImage instance from dmabuf-fd.

Parameters
    [in]	display	EGLDisplay object used during the creation of EGLImage. If NULL, the nvbuf_utils API uses its own EGLDisplay instance.
    [in]	dmabuf_fd	DMABUF FD of buffer from which EGLImage to be created.

It looks like I can pass NULL to it, so I tried the following code:

                EGLImageKHR hEglImage;

		int iErr;
		hEglImage = NvEGLImageFromFd(NULL, decodedNvFrame->nvBuffer->planes[0].fd);
		if (!hEglImage)
			printf("Could not get EglImage from fd. Not rendering\n");
		
		glBindVertexArray(vertexArrayObject);
                glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
		glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, hEglImage);
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		iErr = glGetError();
		if (iErr != GL_NO_ERROR)
			printf("glDrawArrays arrays failed:%i\n", iErr);

		NvDestroyEGLImage(NULL, hEglImage);

Even though I see no errors, I also see no output in the screen. Is there something I’m missing? Are those eglConfig, eglSurfaces, etc, needed to render to a screen? If so, how to render to a buffer and then render to a screen?

For offscreen-only rendering, you have several options. Here are a few:

First, instead of creating and rendering to a window EGLSurface, you could instead create and render to offscreen EGLSurfaces such as pbuffers and pixmaps. See the latest EGL Spec for details.

Another approach that uses less EGL and more GLES/GL is to create a window surface, don’t map it, and then do all of your rendering offscreen in GLES via Framebuffer Objects (FBOs). In fact, you may not even need to create the window surface. See egl_offscreen_opengl and EGL_KHR_surfaceless_context, for instance.

Well if you really mean independent from an EGLDisplay rather than just independent from a physical display, then that’s a bit different. EGLDisplay is roughly your connection to a graphics driver.

There are EGL/OpenGL ES implementations that support rendering on the CPU rather than via physical GPUs (such as Mesa3D). If you wanted to render offscreen without making use of the native GPU or display drivers (I’m inferring that might be your goal), you could target your rendering to one of those libraries. This would let you use the same EGL/OpenGL ES interface for rendering, but without requiring access to and making use of the native GPU and graphics drivers.

Code from NVIDIA does the following

    EGLImageKHR hEglImage;
    hEglImage = NvEGLImageFromFd(eglDisplay, decodedNvFrame->nvBuffer->planes[0].fd);

NvEGLImageFromFd takes an eglDisplay but I can pass NULL to it, so it uses the default display.

Then their rendering code calls

    eglSync = eglCreateSyncKHR(eglDisplay, EGL_SYNC_FENCE_KHR, NULL);
    if (eglSync == EGL_NO_SYNC_KHR)
    {
        printf("eglCreateSyncKHR() failed\n");
    }
    eglSwapBuffers(eglDisplay, eglSurface);

So I can create a ‘fake’ eglSurface and render to it?

I’m having problems opening an eglDisplay with GTK3 (gtkmm) (eglMakeCurrent gives X error) and I’d like to try to render without eglDisplays. Both because I’ll need in the future and also to avoid having to use GTK+EGL because it’s hard to get it working

I tried to use frame buffers, which is exactly what I need. However, I can’t make glDrawArrays draw to a frameBuffer because the texture I’m using is GL_TEXTURE_EXTERNAL_OES and I can’t bind to that, glFramebufferTexture2D gives me error. Do you know how to render to a framebuffer from a GL_TEXTURE_EXTERNAL_OES?

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.