EGLDisplay on GBM

2019-06-17 06:49发布

问题:

I want to create an OpenGL context through EGL. As I won't actually draw, I want to use Pbuffers in conjunction with the GBM platform. This is the code (C99):

#include <stdlib.h>
#include <assert.h>

#include <fcntl.h>
#include <unistd.h>

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <gbm.h>


int main( void )
{
    assert( eglBindAPI( EGL_OPENGL_API ) == EGL_TRUE );

    int fd = open("/dev/dri/card0", O_RDWR);
    struct gbm_device * gbm = gbm_create_device( fd );

    EGLDisplay dpy = eglGetDisplay( gbm );
    eglInitialize( dpy , NULL , NULL );

    EGLConfig config;
    EGLint n_of_configs;
    assert( eglGetConfigs( dpy , &config , 1 , &n_of_configs ) == EGL_TRUE );

    EGLSurface srf = eglCreatePbufferSurface( dpy , config , NULL );
    assert( srf != EGL_NO_SURFACE );

    EGLContext ctx = eglCreateContext( dpy , config , EGL_NO_CONTEXT , NULL );
    assert( ctx != EGL_NO_CONTEXT );

    assert( eglMakeCurrent( dpy , srf , srf , ctx ) == EGL_TRUE );

    eglDestroySurface( dpy , srf );
    eglDestroyContext( dpy , ctx );
    eglTerminate( dpy );

    gbm_device_destroy( gbm );
    close( fd );

    return EXIT_SUCCESS;
}

It fails with the following error:

test.c: In function ‘main’:
test.c:20:2: error: passing argument 1 of ‘eglGetDisplay’ from incompatible pointer type [-Werror]
  EGLDisplay dpy = eglGetDisplay( gbm );
  ^
In file included from test.c:7:0:
/usr/include/EGL/egl.h:251:31: note: expected ‘EGLNativeDisplayType’ but argument is of type ‘struct gbm_device *’
 EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);

This is the page I took as example.

I'm surprised, because I built Mesa with --with-egl-platforms=drm,wayland,x11, and, even though it is stated here that EGL_DEFAULT_DISPLAY maps to the first platform specified, it is an alias for _XDisplay * on my system.

--with-egl-platforms
List the platforms (window systems) to support. Its argument is a comma seprated string such as --with-egl-platforms=x11,drm. It decides the platforms a driver may support. The first listed platform is also used by the main library to decide the native platform: the platform the EGL native types such as EGLNativeDisplayType or EGLNativeWindowType defined for.

AFAIK, Weston creates an EGLDisplay on top of GBM for drawing on bare KMS. I've looked at its code, and I've grepped the pertinent system headers looking for a solution, but it seems to not be there.

FWIW, I'm using Mesa 10.0 on a Radeon HD 3200, Linux 3.12.6, GCC 4.8.2.

回答1:

You say

I want to use Pbuffers in conjunction with the GBM platform.

EGL/GBM does not support Pbuffers. It doesn't support Pixmaps either.

To create an offscreen surface with EGL/GBM, you must pass a gbm_surface to eglCreateWindowSurface. "Window" is a misnomer. No real "window" gets created. The resultant buffer will remain offscreen unless you use the kernel's KMS APIs to post it to the display.

But... that's not why your program fails to compile. When calling eglGetDisplay and eglCreateWindowSurface, you must cast like this:

eglGetDisplay((EGLNativeDisplayType)my_gbm_device);
eglCreateWindowSurface(egl_dpy, egl_config,
                       (EGLNativeWindowType)my_gbm_surface, NULL);

If you are using a Mesa that contains commit 468cc86, then you may avoid the casting by instead using eglGetPlatformDisplayEXT and eglCreatePlatformWindowSurface like this:

eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, my_gbm_device, NULL);
eglCreatePlatformWindowSurfaceEXT(egl_dpy, egl_config, my_gbm_surface, NULL);

Whether you choose to use the vanilla EGL functions or the newer platform EGL functions, you should refer to the example code in the EGL_MESA_platform_gbm spec as a guide.



标签: c egl mesa