egl/gbm: Fix EGL_DEFAULT_DISPLAY
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d.c
index 361cc7960bdc5f3dcd762e7451dfefafed55a675..6649f02b244fa8e304aa9ae7103354e56f25323f 100644 (file)
 #include "util/u_memory.h"
 #include "util/u_format.h"
 #include "util/u_string.h"
+#include "util/u_atomic.h"
 
 #include "egl_g3d.h"
 #include "egl_g3d_api.h"
 #include "egl_g3d_st.h"
+#include "egl_g3d_loader.h"
 #include "native.h"
 
-/**
- * Initialize the state trackers.
- */
 static void
-egl_g3d_init_st(_EGLDriver *drv)
+egl_g3d_invalid_surface(struct native_display *ndpy,
+                        struct native_surface *nsurf,
+                        unsigned int seq_num)
 {
-   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-   EGLint i;
+   /* XXX not thread safe? */
+   struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
 
-   /* already initialized */
-   if (gdrv->api_mask)
-      return;
+   if (gsurf && gsurf->stfbi)
+      p_atomic_inc(&gsurf->stfbi->stamp);
+}
 
-   egl_g3d_init_st_apis(gdrv->stapis);
-   for (i = 0; i < ST_API_COUNT; i++) {
-      if (gdrv->stapis[i])
-         gdrv->api_mask |= egl_g3d_st_api_bit(i);
-   }
+static struct pipe_screen *
+egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
+{
+   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   return gdpy->loader->create_drm_screen(name, fd);
+}
 
-   if (gdrv->api_mask)
-      _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
-   else
-      _eglLog(_EGL_WARNING, "No supported client API");
+static struct pipe_screen *
+egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
+{
+   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   return gdpy->loader->create_sw_screen(ws);
 }
 
-/**
- * Get the probe object of the display.
- *
- * Note that this function may be called before the display is initialized.
- */
-static struct native_probe *
-egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy)
+static struct pipe_resource *
+egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image)
 {
-   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-   struct native_probe *nprobe;
-
-   nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
-   if (!nprobe || nprobe->display != dpy->NativeDisplay) {
-      if (nprobe)
-         nprobe->destroy(nprobe);
-      nprobe = native_create_probe(dpy->NativeDisplay);
-      _eglSetProbeCache(gdrv->probe_key, (void *) nprobe);
-   }
+   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   struct st_egl_image img;
+   struct pipe_resource *resource = NULL;
 
-   return nprobe;
+   memset(&img, 0, sizeof(img));
+   if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img))
+      resource = img.texture;
+
+   return resource;
 }
 
+static const struct native_event_handler egl_g3d_native_event_handler = {
+   egl_g3d_invalid_surface,
+   egl_g3d_new_drm_screen,
+   egl_g3d_new_sw_screen,
+   egl_g3d_lookup_egl_image
+};
+
 /**
- * Destroy the probe object of the display.  The display may be NULL.
- *
- * Note that this function may be called before the display is initialized.
+ * Get the native platform.
  */
-static void
-egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
+static const struct native_platform *
+egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
 {
    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-   struct native_probe *nprobe;
 
-   nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
-   if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) {
-      nprobe->destroy(nprobe);
-      _eglSetProbeCache(gdrv->probe_key, NULL);
+   if (!gdrv->platforms[plat]) {
+      const char *plat_name = NULL;
+      const struct native_platform *nplat = NULL;
+
+      switch (plat) {
+      case _EGL_PLATFORM_WINDOWS:
+         plat_name = "Windows";
+#ifdef HAVE_GDI_BACKEND
+         nplat = native_get_gdi_platform(&egl_g3d_native_event_handler);
+#endif
+         break;
+      case _EGL_PLATFORM_X11:
+         plat_name = "X11";
+#ifdef HAVE_X11_BACKEND
+         nplat = native_get_x11_platform(&egl_g3d_native_event_handler);
+#endif
+        break;
+      case _EGL_PLATFORM_WAYLAND:
+         plat_name = "wayland";
+#ifdef HAVE_WAYLAND_BACKEND
+         nplat = native_get_wayland_platform(&egl_g3d_native_event_handler);
+#endif
+         break;
+      case _EGL_PLATFORM_DRM:
+         plat_name = "DRM";
+#ifdef HAVE_DRM_BACKEND
+         nplat = native_get_drm_platform(&egl_g3d_native_event_handler);
+#endif
+         break;
+      case _EGL_PLATFORM_FBDEV:
+         plat_name = "FBDEV";
+#ifdef HAVE_FBDEV_BACKEND
+         nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler);
+#endif
+         break;
+      default:
+         break;
+      }
+
+      if (!nplat)
+         _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
+
+      gdrv->platforms[plat] = nplat;
    }
+
+   return gdrv->platforms[plat];
 }
 
 #ifdef EGL_MESA_screen_surface
@@ -140,24 +183,24 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
          continue;
       }
 
-      _eglInitScreen(&gscr->base);
-
-      for (j = 0; j < num_modes; j++) {
+      _eglInitScreen(&gscr->base, dpy, num_modes);
+      for (j = 0; j < gscr->base.NumModes; j++) {
          const struct native_mode *nmode = native_modes[j];
-         _EGLMode *mode;
-
-         mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
-               nmode->refresh_rate, nmode->desc);
-         if (!mode)
-            break;
-         /* gscr->native_modes and gscr->base.Modes should be consistent */
-         assert(mode == &gscr->base.Modes[j]);
+         _EGLMode *mode = &gscr->base.Modes[j];
+
+         mode->Width = nmode->width;
+         mode->Height = nmode->height;
+         mode->RefreshRate = nmode->refresh_rate;
+         mode->Optimal = EGL_FALSE;
+         mode->Interlaced = EGL_FALSE;
+         /* no need to strdup() */
+         mode->Name = nmode->desc;
       }
 
       gscr->native = nconn;
       gscr->native_modes = native_modes;
 
-      _eglAddScreen(dpy, &gscr->base);
+      _eglLinkScreen(&gscr->base);
    }
 
    FREE(native_connectors);
@@ -170,7 +213,8 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
  */
 static EGLBoolean
 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
-                       EGLint api_mask, enum pipe_format depth_stencil_format)
+                       EGLint api_mask, enum pipe_format depth_stencil_format,
+                       EGLBoolean preserve_buffer, EGLint max_swap_interval)
 {
    uint rgba[4], depth_stencil[2], buffer_size;
    EGLint surface_type;
@@ -196,67 +240,70 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
    }
 
    surface_type = 0x0;
-   if (nconf->window_bit)
-      surface_type |= EGL_WINDOW_BIT;
-   if (nconf->pixmap_bit)
-      surface_type |= EGL_PIXMAP_BIT;
+   /* pixmap surfaces should be EGL_SINGLE_BUFFER */
+   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) {
+      if (nconf->pixmap_bit)
+         surface_type |= EGL_PIXMAP_BIT;
+   }
+   /* the others surfaces should be EGL_BACK_BUFFER (or settable) */
+   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) {
+      if (nconf->window_bit)
+         surface_type |= EGL_WINDOW_BIT;
 #ifdef EGL_MESA_screen_surface
-   if (nconf->scanout_bit)
-      surface_type |= EGL_SCREEN_BIT_MESA;
+      if (nconf->scanout_bit)
+         surface_type |= EGL_SCREEN_BIT_MESA;
 #endif
-
-   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
       surface_type |= EGL_PBUFFER_BIT;
+   }
+
+   conf->Conformant = api_mask;
+   conf->RenderableType = api_mask;
 
-   SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask);
-   SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask);
+   conf->RedSize = rgba[0];
+   conf->GreenSize = rgba[1];
+   conf->BlueSize = rgba[2];
+   conf->AlphaSize = rgba[3];
+   conf->BufferSize = buffer_size;
 
-   SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]);
-   SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]);
-   SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]);
-   SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]);
-   SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size);
+   conf->DepthSize = depth_stencil[0];
+   conf->StencilSize = depth_stencil[1];
 
-   SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]);
-   SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]);
+   /* st/vega will allocate the mask on demand */
+   if (api_mask & EGL_OPENVG_BIT)
+      conf->AlphaMaskSize = 8;
 
-   SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
+   conf->SurfaceType = surface_type;
 
-   SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE);
+   conf->NativeRenderable = EGL_TRUE;
    if (surface_type & EGL_WINDOW_BIT) {
-      SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id);
-      SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE,
-            nconf->native_visual_type);
+      conf->NativeVisualID = nconf->native_visual_id;
+      conf->NativeVisualType = nconf->native_visual_type;
    }
 
    if (surface_type & EGL_PBUFFER_BIT) {
-      SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
+      conf->BindToTextureRGB = EGL_TRUE;
       if (rgba[3])
-         SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
+         conf->BindToTextureRGBA = EGL_TRUE;
 
-      SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096);
-      SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096);
-      SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096);
+      conf->MaxPbufferWidth = 4096;
+      conf->MaxPbufferHeight = 4096;
+      conf->MaxPbufferPixels = 4096 * 4096;
    }
 
-   SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level);
-   SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples);
-   SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1);
-
-   if (nconf->slow_config)
-      SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
+   conf->Level = nconf->level;
 
    if (nconf->transparent_rgb) {
-      rgba[0] = nconf->transparent_rgb_values[0];
-      rgba[1] = nconf->transparent_rgb_values[1];
-      rgba[2] = nconf->transparent_rgb_values[2];
-
-      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
-      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]);
-      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]);
-      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]);
+      conf->TransparentType = EGL_TRANSPARENT_RGB;
+      conf->TransparentRedValue = nconf->transparent_rgb_values[0];
+      conf->TransparentGreenValue = nconf->transparent_rgb_values[1];
+      conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
    }
 
+   conf->MinSwapInterval = 0;
+   conf->MaxSwapInterval = max_swap_interval;
+   if (preserve_buffer)
+      conf->SurfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+
    return _eglValidateConfig(conf, EGL_FALSE);
 }
 
@@ -266,13 +313,12 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
 static EGLBoolean
 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
                     _EGLConfig *conf, const struct native_config *nconf,
-                    enum pipe_format depth_stencil_format)
+                    enum pipe_format depth_stencil_format,
+                    int preserve_buffer, int max_swap_interval)
 {
-   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
    struct egl_g3d_config *gconf = egl_g3d_config(conf);
-   EGLint buffer_mask, api_mask;
+   EGLint buffer_mask;
    EGLBoolean valid;
-   EGLint i;
 
    buffer_mask = 0x0;
    if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
@@ -288,31 +334,15 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
    gconf->stvis.color_format = nconf->color_format;
    gconf->stvis.depth_stencil_format = depth_stencil_format;
    gconf->stvis.accum_format = PIPE_FORMAT_NONE;
-   gconf->stvis.samples = nconf->samples;
+   gconf->stvis.samples = 0;
 
+   /* will be overridden per surface */
    gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
       ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
 
-   api_mask = 0;
-   for (i = 0; i < ST_API_COUNT; i++) {
-      struct st_api *stapi = gdrv->stapis[i];
-      if (stapi) {
-         if (stapi->is_visual_supported(stapi, &gconf->stvis))
-            api_mask |= egl_g3d_st_api_bit(i);
-      }
-   }
-   /* this is required by EGL, not by OpenGL ES */
-   if (nconf->window_bit &&
-       gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
-      api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
-
-   if (!api_mask) {
-      _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
-            nconf->native_visual_id);
-   }
-
    valid = init_config_attributes(&gconf->base,
-         nconf, api_mask, depth_stencil_format);
+         nconf, dpy->ClientAPIs, depth_stencil_format,
+         preserve_buffer, max_swap_interval);
    if (!valid) {
       _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
       return EGL_FALSE;
@@ -351,7 +381,7 @@ egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
       /* pick the first supported format */
       for (i = 0; i < n; i++) {
          if (screen->is_format_supported(screen, fmt[i],
-                  PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) {
+                  PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) {
             formats[count++] = fmt[i];
             break;
          }
@@ -373,6 +403,7 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
    const struct native_config **native_configs;
    enum pipe_format depth_stencil_formats[8];
    int num_formats, num_configs, i, j;
+   int preserve_buffer, max_swap_interval;
 
    native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
    if (!num_configs) {
@@ -381,6 +412,11 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
       return id;
    }
 
+   preserve_buffer =
+      gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
+   max_swap_interval =
+      gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
+
    num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
          depth_stencil_formats);
 
@@ -392,12 +428,13 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
          if (gconf) {
             _eglInitConfig(&gconf->base, dpy, id);
             if (!egl_g3d_init_config(drv, dpy, &gconf->base,
-                     native_configs[i], depth_stencil_formats[j])) {
+                     native_configs[i], depth_stencil_formats[j],
+                     preserve_buffer, max_swap_interval)) {
                FREE(gconf);
                break;
             }
 
-            _eglAddConfig(dpy, &gconf->base);
+            _eglLinkConfig(&gconf->base);
             id++;
          }
       }
@@ -408,48 +445,40 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
 }
 
 static void
-egl_g3d_invalid_surface(struct native_display *ndpy,
-                        struct native_surface *nsurf,
-                        unsigned int seq_num)
+egl_g3d_free_config(void *conf)
 {
-   /* XXX not thread safe? */
-   struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
-   struct egl_g3d_context *gctx;
-   
-   /*
-    * Some functions such as egl_g3d_copy_buffers create a temporary native
-    * surface.  There is no gsurf associated with it.
-    */
-   gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
-   if (gctx)
-      gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
+   struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
+   FREE(gconf);
 }
 
-static struct native_event_handler egl_g3d_native_event_handler = {
-   egl_g3d_invalid_surface
-};
+static void
+egl_g3d_free_screen(void *scr)
+{
+#ifdef EGL_MESA_screen_surface
+   struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
+   FREE(gscr->native_modes);
+   FREE(gscr);
+#endif
+}
 
 static EGLBoolean
 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
 {
    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
-   EGLint i;
 
    _eglReleaseDisplayResources(drv, dpy);
-   _eglCleanupDisplay(dpy);
-
-   if (gdpy->pipe)
-      gdpy->pipe->destroy(gdpy->pipe);
 
+   if (dpy->Configs) {
+      _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
+      dpy->Configs = NULL;
+   }
    if (dpy->Screens) {
-      for (i = 0; i < dpy->NumScreens; i++) {
-         struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
-         FREE(gscr->native_modes);
-         FREE(gscr);
-      }
-      FREE(dpy->Screens);
+      _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
+      dpy->Screens = NULL;
    }
 
+   _eglCleanupDisplay(dpy);
+
    if (gdpy->smapi)
       egl_g3d_destroy_st_manager(gdpy->smapi);
 
@@ -463,33 +492,50 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
 }
 
 static EGLBoolean
-egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
-                   EGLint *major, EGLint *minor)
+egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
 {
    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
    struct egl_g3d_display *gdpy;
+   const struct native_platform *nplat;
 
-   /* the probe object is unlikely to be needed again */
-   egl_g3d_destroy_probe(drv, dpy);
+   nplat = egl_g3d_get_platform(drv, dpy->Platform);
+   if (!nplat)
+      return EGL_FALSE;
+
+   if (dpy->Options.TestOnly)
+      return EGL_TRUE;
 
    gdpy = CALLOC_STRUCT(egl_g3d_display);
    if (!gdpy) {
       _eglError(EGL_BAD_ALLOC, "eglInitialize");
       goto fail;
    }
+   gdpy->loader = gdrv->loader;
    dpy->DriverData = gdpy;
 
-   gdpy->native = native_create_display(dpy->NativeDisplay,
-         &egl_g3d_native_event_handler);
+   _eglLog(_EGL_INFO, "use %s for display %p",
+         nplat->name, dpy->PlatformDisplay);
+   gdpy->native =
+      nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback);
    if (!gdpy->native) {
       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
       goto fail;
    }
-
    gdpy->native->user_data = (void *) dpy;
+   if (!gdpy->native->init_screen(gdpy->native)) {
+      _eglError(EGL_NOT_INITIALIZED,
+            "eglInitialize(failed to initialize screen)");
+      goto fail;
+   }
 
-   egl_g3d_init_st(&gdrv->base);
-   dpy->ClientAPIsMask = gdrv->api_mask;
+   if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK)
+      dpy->ClientAPIs |= EGL_OPENGL_BIT;
+   if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK)
+      dpy->ClientAPIs |= EGL_OPENGL_ES_BIT;
+   if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK)
+      dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT;
+   if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK)
+      dpy->ClientAPIs |= EGL_OPENVG_BIT;
 
    gdpy->smapi = egl_g3d_create_st_manager(dpy);
    if (!gdpy->smapi) {
@@ -510,13 +556,34 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
    if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
       dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
 
+   dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
+   dpy->Extensions.KHR_fence_sync = EGL_TRUE;
+
+   dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+   dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+   dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+
+   if (dpy->Platform == _EGL_PLATFORM_DRM) {
+      dpy->Extensions.MESA_drm_display = EGL_TRUE;
+      if (gdpy->native->buffer)
+         dpy->Extensions.MESA_drm_image = EGL_TRUE;
+   }
+
+   if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
+      dpy->Extensions.MESA_drm_image = EGL_TRUE;
+
+#ifdef EGL_WL_bind_wayland_display
+   if (gdpy->native->wayland_bufmgr)
+      dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
+#endif
+
    if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
       goto fail;
    }
 
-   *major = 1;
-   *minor = 4;
+   dpy->VersionMajor = 1;
+   dpy->VersionMinor = 4;
 
    return EGL_TRUE;
 
@@ -530,87 +597,43 @@ static _EGLProc
 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
 {
    struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-   _EGLProc proc;
-   EGLint i;
-
-   /* in case this is called before a display is initialized */
-   egl_g3d_init_st(&gdrv->base);
-
-   for (i = 0; i < ST_API_COUNT; i++) {
-      struct st_api *stapi = gdrv->stapis[i];
-      if (stapi) {
-         proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
-         if (proc)
-            return proc;
-      }
-   }
+   struct st_api *stapi = NULL;
 
-   return (_EGLProc) NULL;
-}
+   if (procname && procname[0] == 'v' && procname[1] == 'g')
+      stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
+   else if (procname && procname[0] == 'g' && procname[1] == 'l')
+      stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
 
-static EGLint
-egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
-{
-   struct native_probe *nprobe;
-   enum native_probe_result res;
-   EGLint score;
-
-   nprobe = egl_g3d_get_probe(drv, dpy);
-   res = native_get_probe_result(nprobe);
-
-   switch (res) {
-   case NATIVE_PROBE_UNKNOWN:
-   default:
-      score = 0;
-      break;
-   case NATIVE_PROBE_FALLBACK:
-      score = 40;
-      break;
-   case NATIVE_PROBE_SUPPORTED:
-      score = 50;
-      break;
-   case NATIVE_PROBE_EXACT:
-      score = 100;
-      break;
-   }
-
-   return score;
-}
-
-static void
-egl_g3d_unload(_EGLDriver *drv)
-{
-   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-
-   egl_g3d_destroy_st_apis();
-   egl_g3d_destroy_probe(drv, NULL);
-   FREE(gdrv);
+   return (_EGLProc) ((stapi) ?
+         stapi->get_proc_address(stapi, procname) : NULL);
 }
 
 _EGLDriver *
-_eglMain(const char *args)
+egl_g3d_create_driver(const struct egl_g3d_loader *loader)
 {
-   static char driver_name[64];
    struct egl_g3d_driver *gdrv;
 
-   util_snprintf(driver_name, sizeof(driver_name),
-         "Gallium/%s", native_get_name());
-
    gdrv = CALLOC_STRUCT(egl_g3d_driver);
    if (!gdrv)
       return NULL;
 
+   gdrv->loader = loader;
+
    egl_g3d_init_driver_api(&gdrv->base);
    gdrv->base.API.Initialize = egl_g3d_initialize;
    gdrv->base.API.Terminate = egl_g3d_terminate;
    gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
 
-   gdrv->base.Name = driver_name;
-   gdrv->base.Probe = egl_g3d_probe;
-   gdrv->base.Unload = egl_g3d_unload;
-
-   /* the key is " EGL G3D" */
-   gdrv->probe_key = 0x0E61063D;
+   /* to be filled by the caller */
+   gdrv->base.Name = NULL;
+   gdrv->base.Unload = NULL;
 
    return &gdrv->base;
 }
+
+void
+egl_g3d_destroy_driver(_EGLDriver *drv)
+{
+   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+   FREE(gdrv);
+}