Home | History | Annotate | Download | only in common
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.8
      4  *
      5  * Copyright (C) 2009-2010 Chia-I Wu <olv (at) 0xlab.org>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 #include "egldriver.h"
     27 #include "eglcurrent.h"
     28 #include "egllog.h"
     29 
     30 #include "pipe/p_screen.h"
     31 #include "util/u_memory.h"
     32 #include "util/u_format.h"
     33 #include "util/u_string.h"
     34 #include "util/u_atomic.h"
     35 
     36 #include "egl_g3d.h"
     37 #include "egl_g3d_api.h"
     38 #include "egl_g3d_st.h"
     39 #include "egl_g3d_loader.h"
     40 #include "native.h"
     41 
     42 static void
     43 egl_g3d_invalid_surface(struct native_display *ndpy,
     44                         struct native_surface *nsurf,
     45                         unsigned int seq_num)
     46 {
     47    /* XXX not thread safe? */
     48    struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
     49 
     50    if (gsurf && gsurf->stfbi)
     51       p_atomic_inc(&gsurf->stfbi->stamp);
     52 }
     53 
     54 static struct pipe_screen *
     55 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
     56 {
     57    _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
     58    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
     59    return gdpy->loader->create_drm_screen(name, fd);
     60 }
     61 
     62 static struct pipe_screen *
     63 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
     64 {
     65    _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
     66    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
     67    return gdpy->loader->create_sw_screen(ws);
     68 }
     69 
     70 static struct pipe_resource *
     71 egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image)
     72 {
     73    _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
     74    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
     75    struct st_egl_image img;
     76    struct pipe_resource *resource = NULL;
     77 
     78    memset(&img, 0, sizeof(img));
     79    if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img))
     80       resource = img.texture;
     81 
     82    return resource;
     83 }
     84 
     85 static const struct native_event_handler egl_g3d_native_event_handler = {
     86    egl_g3d_invalid_surface,
     87    egl_g3d_new_drm_screen,
     88    egl_g3d_new_sw_screen,
     89    egl_g3d_lookup_egl_image
     90 };
     91 
     92 /**
     93  * Get the native platform.
     94  */
     95 static const struct native_platform *
     96 egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
     97 {
     98    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
     99 
    100    if (!gdrv->platforms[plat]) {
    101       const char *plat_name = NULL;
    102       const struct native_platform *nplat = NULL;
    103 
    104       switch (plat) {
    105       case _EGL_PLATFORM_WINDOWS:
    106          plat_name = "Windows";
    107 #ifdef HAVE_GDI_BACKEND
    108          nplat = native_get_gdi_platform(&egl_g3d_native_event_handler);
    109 #endif
    110          break;
    111       case _EGL_PLATFORM_X11:
    112          plat_name = "X11";
    113 #ifdef HAVE_X11_BACKEND
    114          nplat = native_get_x11_platform(&egl_g3d_native_event_handler);
    115 #endif
    116 	 break;
    117       case _EGL_PLATFORM_WAYLAND:
    118          plat_name = "wayland";
    119 #ifdef HAVE_WAYLAND_BACKEND
    120          nplat = native_get_wayland_platform(&egl_g3d_native_event_handler);
    121 #endif
    122          break;
    123       case _EGL_PLATFORM_DRM:
    124          plat_name = "DRM";
    125 #ifdef HAVE_DRM_BACKEND
    126          nplat = native_get_drm_platform(&egl_g3d_native_event_handler);
    127 #endif
    128          break;
    129       case _EGL_PLATFORM_FBDEV:
    130          plat_name = "FBDEV";
    131 #ifdef HAVE_FBDEV_BACKEND
    132          nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler);
    133 #endif
    134          break;
    135       case _EGL_PLATFORM_NULL:
    136          plat_name = "NULL";
    137 #ifdef HAVE_NULL_BACKEND
    138          nplat = native_get_null_platform(&egl_g3d_native_event_handler);
    139 #endif
    140          break;
    141       case _EGL_PLATFORM_ANDROID:
    142          plat_name = "Android";
    143 #ifdef HAVE_ANDROID_BACKEND
    144          nplat = native_get_android_platform(&egl_g3d_native_event_handler);
    145 #endif
    146          break;
    147       default:
    148          break;
    149       }
    150 
    151       if (!nplat)
    152          _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
    153 
    154       gdrv->platforms[plat] = nplat;
    155    }
    156 
    157    return gdrv->platforms[plat];
    158 }
    159 
    160 #ifdef EGL_MESA_screen_surface
    161 
    162 static void
    163 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
    164 {
    165    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
    166    const struct native_connector **native_connectors;
    167    EGLint num_connectors, i;
    168 
    169    native_connectors =
    170       gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
    171    if (!num_connectors) {
    172       if (native_connectors)
    173          FREE(native_connectors);
    174       return;
    175    }
    176 
    177    for (i = 0; i < num_connectors; i++) {
    178       const struct native_connector *nconn = native_connectors[i];
    179       struct egl_g3d_screen *gscr;
    180       const struct native_mode **native_modes;
    181       EGLint num_modes, j;
    182 
    183       /* TODO support for hotplug */
    184       native_modes =
    185          gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
    186       if (!num_modes) {
    187          if (native_modes)
    188             FREE(native_modes);
    189          continue;
    190       }
    191 
    192       gscr = CALLOC_STRUCT(egl_g3d_screen);
    193       if (!gscr) {
    194          FREE(native_modes);
    195          continue;
    196       }
    197 
    198       _eglInitScreen(&gscr->base, dpy, num_modes);
    199       for (j = 0; j < gscr->base.NumModes; j++) {
    200          const struct native_mode *nmode = native_modes[j];
    201          _EGLMode *mode = &gscr->base.Modes[j];
    202 
    203          mode->Width = nmode->width;
    204          mode->Height = nmode->height;
    205          mode->RefreshRate = nmode->refresh_rate;
    206          mode->Optimal = EGL_FALSE;
    207          mode->Interlaced = EGL_FALSE;
    208          /* no need to strdup() */
    209          mode->Name = nmode->desc;
    210       }
    211 
    212       gscr->native = nconn;
    213       gscr->native_modes = native_modes;
    214 
    215       _eglLinkScreen(&gscr->base);
    216    }
    217 
    218    FREE(native_connectors);
    219 }
    220 
    221 #endif /* EGL_MESA_screen_surface */
    222 
    223 /**
    224  * Initialize and validate the EGL config attributes.
    225  */
    226 static EGLBoolean
    227 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
    228                        EGLint api_mask, enum pipe_format depth_stencil_format,
    229                        EGLint preserve_buffer, EGLint max_swap_interval,
    230                        EGLBoolean pre_alpha)
    231 {
    232    uint rgba[4], depth_stencil[2], buffer_size;
    233    EGLint surface_type;
    234    EGLint i;
    235 
    236    /* get the color and depth/stencil component sizes */
    237    assert(nconf->color_format != PIPE_FORMAT_NONE);
    238    buffer_size = 0;
    239    for (i = 0; i < 4; i++) {
    240       rgba[i] = util_format_get_component_bits(nconf->color_format,
    241             UTIL_FORMAT_COLORSPACE_RGB, i);
    242       buffer_size += rgba[i];
    243    }
    244    for (i = 0; i < 2; i++) {
    245       if (depth_stencil_format != PIPE_FORMAT_NONE) {
    246          depth_stencil[i] =
    247             util_format_get_component_bits(depth_stencil_format,
    248                UTIL_FORMAT_COLORSPACE_ZS, i);
    249       }
    250       else {
    251          depth_stencil[i] = 0;
    252       }
    253    }
    254 
    255    surface_type = 0x0;
    256    /* pixmap surfaces should be EGL_SINGLE_BUFFER */
    257    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) {
    258       if (nconf->pixmap_bit)
    259          surface_type |= EGL_PIXMAP_BIT;
    260    }
    261    /* the others surfaces should be EGL_BACK_BUFFER (or settable) */
    262    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) {
    263       if (nconf->window_bit)
    264          surface_type |= EGL_WINDOW_BIT;
    265 #ifdef EGL_MESA_screen_surface
    266       if (nconf->scanout_bit)
    267          surface_type |= EGL_SCREEN_BIT_MESA;
    268 #endif
    269       surface_type |= EGL_PBUFFER_BIT;
    270    }
    271 
    272    if (preserve_buffer)
    273       surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
    274 
    275    if (pre_alpha && rgba[3]) {
    276       surface_type |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
    277       /* st/vega does not support premultiplied alpha yet */
    278       api_mask &= ~EGL_OPENVG_BIT;
    279    }
    280 
    281    conf->Conformant = api_mask;
    282    conf->RenderableType = api_mask;
    283 
    284    conf->RedSize = rgba[0];
    285    conf->GreenSize = rgba[1];
    286    conf->BlueSize = rgba[2];
    287    conf->AlphaSize = rgba[3];
    288    conf->BufferSize = buffer_size;
    289 
    290    conf->DepthSize = depth_stencil[0];
    291    conf->StencilSize = depth_stencil[1];
    292 
    293    /* st/vega will allocate the mask on demand */
    294    if (api_mask & EGL_OPENVG_BIT)
    295       conf->AlphaMaskSize = 8;
    296 
    297    conf->SurfaceType = surface_type;
    298 
    299    conf->NativeRenderable = EGL_TRUE;
    300    if (surface_type & EGL_WINDOW_BIT) {
    301       conf->NativeVisualID = nconf->native_visual_id;
    302       conf->NativeVisualType = nconf->native_visual_type;
    303    }
    304 
    305    if (surface_type & EGL_PBUFFER_BIT) {
    306       conf->BindToTextureRGB = EGL_TRUE;
    307       if (rgba[3])
    308          conf->BindToTextureRGBA = EGL_TRUE;
    309 
    310       conf->MaxPbufferWidth = 4096;
    311       conf->MaxPbufferHeight = 4096;
    312       conf->MaxPbufferPixels = 4096 * 4096;
    313    }
    314 
    315    conf->Level = nconf->level;
    316 
    317    if (nconf->transparent_rgb) {
    318       conf->TransparentType = EGL_TRANSPARENT_RGB;
    319       conf->TransparentRedValue = nconf->transparent_rgb_values[0];
    320       conf->TransparentGreenValue = nconf->transparent_rgb_values[1];
    321       conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
    322    }
    323 
    324    conf->MinSwapInterval = 0;
    325    conf->MaxSwapInterval = max_swap_interval;
    326 
    327    return _eglValidateConfig(conf, EGL_FALSE);
    328 }
    329 
    330 /**
    331  * Initialize an EGL config from the native config.
    332  */
    333 static EGLBoolean
    334 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
    335                     _EGLConfig *conf, const struct native_config *nconf,
    336                     enum pipe_format depth_stencil_format,
    337                     int preserve_buffer, int max_swap_interval,
    338                     int pre_alpha)
    339 {
    340    struct egl_g3d_config *gconf = egl_g3d_config(conf);
    341    EGLint buffer_mask;
    342    EGLBoolean valid;
    343 
    344    buffer_mask = 0x0;
    345    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
    346       buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
    347    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
    348       buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
    349    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
    350       buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
    351    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
    352       buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
    353 
    354    gconf->stvis.buffer_mask = buffer_mask;
    355    gconf->stvis.color_format = nconf->color_format;
    356    gconf->stvis.depth_stencil_format = depth_stencil_format;
    357    gconf->stvis.accum_format = PIPE_FORMAT_NONE;
    358    gconf->stvis.samples = 0;
    359 
    360    /* will be overridden per surface */
    361    gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
    362       ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
    363 
    364    valid = init_config_attributes(&gconf->base,
    365          nconf, dpy->ClientAPIs, depth_stencil_format,
    366          preserve_buffer, max_swap_interval, pre_alpha);
    367    if (!valid) {
    368       _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
    369       return EGL_FALSE;
    370    }
    371 
    372    gconf->native = nconf;
    373 
    374    return EGL_TRUE;
    375 }
    376 
    377 /**
    378  * Get all interested depth/stencil formats of a display.
    379  */
    380 static EGLint
    381 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
    382                                    enum pipe_format formats[8])
    383 {
    384    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
    385    struct pipe_screen *screen = gdpy->native->screen;
    386    const EGLint candidates[] = {
    387       1, PIPE_FORMAT_Z16_UNORM,
    388       1, PIPE_FORMAT_Z32_UNORM,
    389       2, PIPE_FORMAT_Z24_UNORM_S8_UINT, PIPE_FORMAT_S8_UINT_Z24_UNORM,
    390       2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
    391       0
    392    };
    393    const EGLint *fmt = candidates;
    394    EGLint count;
    395 
    396    count = 0;
    397    formats[count++] = PIPE_FORMAT_NONE;
    398 
    399    while (*fmt) {
    400       EGLint i, n = *fmt++;
    401 
    402       /* pick the first supported format */
    403       for (i = 0; i < n; i++) {
    404          if (screen->is_format_supported(screen, fmt[i],
    405                   PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) {
    406             formats[count++] = fmt[i];
    407             break;
    408          }
    409       }
    410 
    411       fmt += n;
    412    }
    413 
    414    return count;
    415 }
    416 
    417 /**
    418  * Add configs to display and return the next config ID.
    419  */
    420 static EGLint
    421 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
    422 {
    423    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
    424    const struct native_config **native_configs;
    425    enum pipe_format depth_stencil_formats[8];
    426    int num_formats, num_configs, i, j;
    427    int preserve_buffer, max_swap_interval, premultiplied_alpha;
    428 
    429    native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
    430    if (!num_configs) {
    431       if (native_configs)
    432          FREE(native_configs);
    433       return id;
    434    }
    435 
    436    preserve_buffer =
    437       gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
    438    max_swap_interval =
    439       gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
    440    premultiplied_alpha =
    441       gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PREMULTIPLIED_ALPHA);
    442 
    443    num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
    444          depth_stencil_formats);
    445 
    446    for (i = 0; i < num_configs; i++) {
    447       for (j = 0; j < num_formats; j++) {
    448          struct egl_g3d_config *gconf;
    449 
    450          gconf = CALLOC_STRUCT(egl_g3d_config);
    451          if (gconf) {
    452             _eglInitConfig(&gconf->base, dpy, id);
    453             if (!egl_g3d_init_config(drv, dpy, &gconf->base,
    454                      native_configs[i], depth_stencil_formats[j],
    455                      preserve_buffer, max_swap_interval,
    456                      premultiplied_alpha)) {
    457                FREE(gconf);
    458                break;
    459             }
    460 
    461             _eglLinkConfig(&gconf->base);
    462             id++;
    463          }
    464       }
    465    }
    466 
    467    FREE(native_configs);
    468    return id;
    469 }
    470 
    471 static void
    472 egl_g3d_free_config(void *conf)
    473 {
    474    struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
    475    FREE(gconf);
    476 }
    477 
    478 static void
    479 egl_g3d_free_screen(void *scr)
    480 {
    481 #ifdef EGL_MESA_screen_surface
    482    struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
    483    FREE(gscr->native_modes);
    484    FREE(gscr);
    485 #endif
    486 }
    487 
    488 static EGLBoolean
    489 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
    490 {
    491    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
    492 
    493    _eglReleaseDisplayResources(drv, dpy);
    494 
    495    if (dpy->Configs) {
    496       _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
    497       dpy->Configs = NULL;
    498    }
    499    if (dpy->Screens) {
    500       _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
    501       dpy->Screens = NULL;
    502    }
    503 
    504    _eglCleanupDisplay(dpy);
    505 
    506    if (gdpy->smapi)
    507       egl_g3d_destroy_st_manager(gdpy->smapi);
    508 
    509    if (gdpy->native)
    510       gdpy->native->destroy(gdpy->native);
    511 
    512    FREE(gdpy);
    513    dpy->DriverData = NULL;
    514 
    515    return EGL_TRUE;
    516 }
    517 
    518 static EGLBoolean
    519 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
    520 {
    521    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
    522    struct egl_g3d_display *gdpy;
    523    const struct native_platform *nplat;
    524 
    525    nplat = egl_g3d_get_platform(drv, dpy->Platform);
    526    if (!nplat)
    527       return EGL_FALSE;
    528 
    529    if (dpy->Options.TestOnly)
    530       return EGL_TRUE;
    531 
    532    gdpy = CALLOC_STRUCT(egl_g3d_display);
    533    if (!gdpy) {
    534       _eglError(EGL_BAD_ALLOC, "eglInitialize");
    535       goto fail;
    536    }
    537    gdpy->loader = gdrv->loader;
    538    dpy->DriverData = gdpy;
    539 
    540    _eglLog(_EGL_INFO, "use %s for display %p",
    541          nplat->name, dpy->PlatformDisplay);
    542    gdpy->native =
    543       nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback);
    544    if (!gdpy->native) {
    545       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
    546       goto fail;
    547    }
    548    gdpy->native->user_data = (void *) dpy;
    549    if (!gdpy->native->init_screen(gdpy->native)) {
    550       _eglError(EGL_NOT_INITIALIZED,
    551             "eglInitialize(failed to initialize screen)");
    552       goto fail;
    553    }
    554 
    555    if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK)
    556       dpy->ClientAPIs |= EGL_OPENGL_BIT;
    557    if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK)
    558       dpy->ClientAPIs |= EGL_OPENGL_ES_BIT;
    559    if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK)
    560       dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT;
    561    if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK)
    562       dpy->ClientAPIs |= EGL_OPENVG_BIT;
    563 
    564    gdpy->smapi = egl_g3d_create_st_manager(dpy);
    565    if (!gdpy->smapi) {
    566       _eglError(EGL_NOT_INITIALIZED,
    567             "eglInitialize(failed to create st manager)");
    568       goto fail;
    569    }
    570 
    571 #ifdef EGL_MESA_screen_surface
    572    /* enable MESA_screen_surface before adding (and validating) configs */
    573    if (gdpy->native->modeset) {
    574       dpy->Extensions.MESA_screen_surface = EGL_TRUE;
    575       egl_g3d_add_screens(drv, dpy);
    576    }
    577 #endif
    578 
    579    dpy->Extensions.KHR_image_base = EGL_TRUE;
    580    if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
    581       dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
    582 
    583    dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
    584    dpy->Extensions.KHR_fence_sync = EGL_TRUE;
    585 
    586    dpy->Extensions.KHR_surfaceless_context = EGL_TRUE;
    587 
    588    if (dpy->Platform == _EGL_PLATFORM_DRM) {
    589       dpy->Extensions.MESA_drm_display = EGL_TRUE;
    590       if (gdpy->native->buffer)
    591          dpy->Extensions.MESA_drm_image = EGL_TRUE;
    592    }
    593 
    594    if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
    595       dpy->Extensions.MESA_drm_image = EGL_TRUE;
    596 
    597 #ifdef EGL_ANDROID_image_native_buffer
    598    if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer)
    599       dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
    600 #endif
    601 
    602 #ifdef EGL_WL_bind_wayland_display
    603    if (gdpy->native->wayland_bufmgr)
    604       dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
    605 #endif
    606 
    607    if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) &&
    608        gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) {
    609 #ifdef EGL_NOK_swap_region
    610       dpy->Extensions.NOK_swap_region = EGL_TRUE;
    611 #endif
    612       dpy->Extensions.NV_post_sub_buffer = EGL_TRUE;
    613    }
    614 
    615    if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
    616       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
    617       goto fail;
    618    }
    619 
    620    dpy->VersionMajor = 1;
    621    dpy->VersionMinor = 4;
    622 
    623    return EGL_TRUE;
    624 
    625 fail:
    626    if (gdpy)
    627       egl_g3d_terminate(drv, dpy);
    628    return EGL_FALSE;
    629 }
    630 
    631 static _EGLProc
    632 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
    633 {
    634    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
    635    struct st_api *stapi = NULL;
    636 
    637    if (procname && procname[0] == 'v' && procname[1] == 'g')
    638       stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
    639    else if (procname && procname[0] == 'g' && procname[1] == 'l')
    640       stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
    641 
    642    return (_EGLProc) ((stapi) ?
    643          stapi->get_proc_address(stapi, procname) : NULL);
    644 }
    645 
    646 _EGLDriver *
    647 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
    648 {
    649    struct egl_g3d_driver *gdrv;
    650 
    651    gdrv = CALLOC_STRUCT(egl_g3d_driver);
    652    if (!gdrv)
    653       return NULL;
    654 
    655    gdrv->loader = loader;
    656 
    657    egl_g3d_init_driver_api(&gdrv->base);
    658    gdrv->base.API.Initialize = egl_g3d_initialize;
    659    gdrv->base.API.Terminate = egl_g3d_terminate;
    660    gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
    661 
    662    /* to be filled by the caller */
    663    gdrv->base.Name = NULL;
    664    gdrv->base.Unload = NULL;
    665 
    666    return &gdrv->base;
    667 }
    668 
    669 void
    670 egl_g3d_destroy_driver(_EGLDriver *drv)
    671 {
    672    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
    673    FREE(gdrv);
    674 }
    675