egl_g3d.c revision 75772842133d101223ca31400e100b83476f327b
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.8
4 *
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@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
42static void
43egl_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
54static struct pipe_screen *
55egl_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
62static struct pipe_screen *
63egl_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
70static struct pipe_resource *
71egl_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
85static 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 */
95static const struct native_platform *
96egl_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
162static void
163egl_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 */
226static EGLBoolean
227init_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 */
333static EGLBoolean
334egl_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 */
380static EGLint
381egl_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 */
420static EGLint
421egl_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
471static void
472egl_g3d_free_config(void *conf)
473{
474   struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
475   FREE(gconf);
476}
477
478static void
479egl_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
488static EGLBoolean
489egl_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
518static EGLBoolean
519egl_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_gles1 = EGL_TRUE;
587   dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
588   dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
589
590   if (dpy->Platform == _EGL_PLATFORM_DRM) {
591      dpy->Extensions.MESA_drm_display = EGL_TRUE;
592      if (gdpy->native->buffer)
593         dpy->Extensions.MESA_drm_image = EGL_TRUE;
594   }
595
596   if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
597      dpy->Extensions.MESA_drm_image = EGL_TRUE;
598
599#ifdef EGL_ANDROID_image_native_buffer
600   if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer)
601      dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
602#endif
603
604#ifdef EGL_WL_bind_wayland_display
605   if (gdpy->native->wayland_bufmgr)
606      dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
607#endif
608
609   if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) &&
610       gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) {
611#ifdef EGL_NOK_swap_region
612      dpy->Extensions.NOK_swap_region = EGL_TRUE;
613#endif
614      dpy->Extensions.NV_post_sub_buffer = EGL_TRUE;
615   }
616
617   if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
618      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
619      goto fail;
620   }
621
622   dpy->VersionMajor = 1;
623   dpy->VersionMinor = 4;
624
625   return EGL_TRUE;
626
627fail:
628   if (gdpy)
629      egl_g3d_terminate(drv, dpy);
630   return EGL_FALSE;
631}
632
633static _EGLProc
634egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
635{
636   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
637   struct st_api *stapi = NULL;
638
639   if (procname && procname[0] == 'v' && procname[1] == 'g')
640      stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
641   else if (procname && procname[0] == 'g' && procname[1] == 'l')
642      stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
643
644   return (_EGLProc) ((stapi) ?
645         stapi->get_proc_address(stapi, procname) : NULL);
646}
647
648_EGLDriver *
649egl_g3d_create_driver(const struct egl_g3d_loader *loader)
650{
651   struct egl_g3d_driver *gdrv;
652
653   gdrv = CALLOC_STRUCT(egl_g3d_driver);
654   if (!gdrv)
655      return NULL;
656
657   gdrv->loader = loader;
658
659   egl_g3d_init_driver_api(&gdrv->base);
660   gdrv->base.API.Initialize = egl_g3d_initialize;
661   gdrv->base.API.Terminate = egl_g3d_terminate;
662   gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
663
664   /* to be filled by the caller */
665   gdrv->base.Name = NULL;
666   gdrv->base.Unload = NULL;
667
668   return &gdrv->base;
669}
670
671void
672egl_g3d_destroy_driver(_EGLDriver *drv)
673{
674   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
675   FREE(gdrv);
676}
677