egl_g3d.c revision f945cb651518025159499999527ff5d4536acaf8
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/*
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Mesa 3-D graphics library
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Version:  7.8
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * copy of this software and associated documentation files (the "Software"),
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * to deal in the Software without restriction, including without limitation
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Software is furnished to do so, subject to the following conditions:
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * The above copyright notice and this permission notice shall be included
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * in all copies or substantial portions of the Software.
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * DEALINGS IN THE SOFTWARE.
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "egldriver.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "eglcurrent.h"
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "egllog.h"
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "pipe/p_screen.h"
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "util/u_memory.h"
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "util/u_format.h"
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "util/u_string.h"
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "egl_g3d.h"
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "egl_g3d_api.h"
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "egl_g3d_st.h"
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "egl_g3d_loader.h"
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "native.h"
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/**
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Get the native platform.
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic const struct native_platform *
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochegl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch{
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   if (!gdrv->platforms[plat]) {
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const char *plat_name = NULL;
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const struct native_platform *nplat = NULL;
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      switch (plat) {
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      case _EGL_PLATFORM_WINDOWS:
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch         plat_name = "Windows";
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#ifdef HAVE_GDI_BACKEND
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch         nplat = native_get_gdi_platform();
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
59         break;
60      case _EGL_PLATFORM_X11:
61         plat_name = "X11";
62#ifdef HAVE_X11_BACKEND
63         nplat = native_get_x11_platform();
64#endif
65         break;
66      case _EGL_PLATFORM_DRM:
67         plat_name = "DRM";
68#ifdef HAVE_KMS_BACKEND
69         nplat = native_get_kms_platform();
70#endif
71         break;
72      case _EGL_PLATFORM_FBDEV:
73         plat_name = "FBDEV";
74#ifdef HAVE_FBDEV_BACKEND
75         nplat = native_get_fbdev_platform();
76#endif
77         break;
78      default:
79         break;
80      }
81
82      if (!nplat)
83         _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
84
85      gdrv->platforms[plat] = nplat;
86   }
87
88   return gdrv->platforms[plat];
89}
90
91#ifdef EGL_MESA_screen_surface
92
93static void
94egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
95{
96   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
97   const struct native_connector **native_connectors;
98   EGLint num_connectors, i;
99
100   native_connectors =
101      gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
102   if (!num_connectors) {
103      if (native_connectors)
104         FREE(native_connectors);
105      return;
106   }
107
108   for (i = 0; i < num_connectors; i++) {
109      const struct native_connector *nconn = native_connectors[i];
110      struct egl_g3d_screen *gscr;
111      const struct native_mode **native_modes;
112      EGLint num_modes, j;
113
114      /* TODO support for hotplug */
115      native_modes =
116         gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
117      if (!num_modes) {
118         if (native_modes)
119            FREE(native_modes);
120         continue;
121      }
122
123      gscr = CALLOC_STRUCT(egl_g3d_screen);
124      if (!gscr) {
125         FREE(native_modes);
126         continue;
127      }
128
129      _eglInitScreen(&gscr->base);
130
131      for (j = 0; j < num_modes; j++) {
132         const struct native_mode *nmode = native_modes[j];
133         _EGLMode *mode;
134
135         mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
136               nmode->refresh_rate, nmode->desc);
137         if (!mode)
138            break;
139         /* gscr->native_modes and gscr->base.Modes should be consistent */
140         assert(mode == &gscr->base.Modes[j]);
141      }
142
143      gscr->native = nconn;
144      gscr->native_modes = native_modes;
145
146      _eglAddScreen(dpy, &gscr->base);
147   }
148
149   FREE(native_connectors);
150}
151
152#endif /* EGL_MESA_screen_surface */
153
154/**
155 * Initialize and validate the EGL config attributes.
156 */
157static EGLBoolean
158init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
159                       EGLint api_mask, enum pipe_format depth_stencil_format)
160{
161   uint rgba[4], depth_stencil[2], buffer_size;
162   EGLint surface_type;
163   EGLint i;
164
165   /* get the color and depth/stencil component sizes */
166   assert(nconf->color_format != PIPE_FORMAT_NONE);
167   buffer_size = 0;
168   for (i = 0; i < 4; i++) {
169      rgba[i] = util_format_get_component_bits(nconf->color_format,
170            UTIL_FORMAT_COLORSPACE_RGB, i);
171      buffer_size += rgba[i];
172   }
173   for (i = 0; i < 2; i++) {
174      if (depth_stencil_format != PIPE_FORMAT_NONE) {
175         depth_stencil[i] =
176            util_format_get_component_bits(depth_stencil_format,
177               UTIL_FORMAT_COLORSPACE_ZS, i);
178      }
179      else {
180         depth_stencil[i] = 0;
181      }
182   }
183
184   surface_type = 0x0;
185   if (nconf->window_bit)
186      surface_type |= EGL_WINDOW_BIT;
187   if (nconf->pixmap_bit)
188      surface_type |= EGL_PIXMAP_BIT;
189#ifdef EGL_MESA_screen_surface
190   if (nconf->scanout_bit)
191      surface_type |= EGL_SCREEN_BIT_MESA;
192#endif
193
194   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
195      surface_type |= EGL_PBUFFER_BIT;
196
197   SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask);
198   SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask);
199
200   SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]);
201   SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]);
202   SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]);
203   SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]);
204   SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size);
205
206   SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]);
207   SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]);
208
209   SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
210
211   SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE);
212   if (surface_type & EGL_WINDOW_BIT) {
213      SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id);
214      SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE,
215            nconf->native_visual_type);
216   }
217
218   if (surface_type & EGL_PBUFFER_BIT) {
219      SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
220      if (rgba[3])
221         SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
222
223      SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096);
224      SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096);
225      SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096);
226   }
227
228   SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level);
229   SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples);
230   SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1);
231
232   if (nconf->slow_config)
233      SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
234
235   if (nconf->transparent_rgb) {
236      rgba[0] = nconf->transparent_rgb_values[0];
237      rgba[1] = nconf->transparent_rgb_values[1];
238      rgba[2] = nconf->transparent_rgb_values[2];
239
240      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
241      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]);
242      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]);
243      SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]);
244   }
245
246   return _eglValidateConfig(conf, EGL_FALSE);
247}
248
249/**
250 * Initialize an EGL config from the native config.
251 */
252static EGLBoolean
253egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
254                    _EGLConfig *conf, const struct native_config *nconf,
255                    enum pipe_format depth_stencil_format)
256{
257   struct egl_g3d_config *gconf = egl_g3d_config(conf);
258   EGLint buffer_mask, api_mask;
259   EGLBoolean valid;
260
261   buffer_mask = 0x0;
262   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
263      buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
264   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
265      buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
266   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
267      buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
268   if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
269      buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
270
271   gconf->stvis.buffer_mask = buffer_mask;
272   gconf->stvis.color_format = nconf->color_format;
273   gconf->stvis.depth_stencil_format = depth_stencil_format;
274   gconf->stvis.accum_format = PIPE_FORMAT_NONE;
275   gconf->stvis.samples = nconf->samples;
276
277   gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
278      ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
279
280   api_mask = dpy->ClientAPIsMask;
281   /* this is required by EGL, not by OpenGL ES */
282   if (nconf->window_bit &&
283       gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
284      api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
285
286   if (!api_mask) {
287      _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
288            nconf->native_visual_id);
289   }
290
291   valid = init_config_attributes(&gconf->base,
292         nconf, api_mask, depth_stencil_format);
293   if (!valid) {
294      _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
295      return EGL_FALSE;
296   }
297
298   gconf->native = nconf;
299
300   return EGL_TRUE;
301}
302
303/**
304 * Get all interested depth/stencil formats of a display.
305 */
306static EGLint
307egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
308                                   enum pipe_format formats[8])
309{
310   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
311   struct pipe_screen *screen = gdpy->native->screen;
312   const EGLint candidates[] = {
313      1, PIPE_FORMAT_Z16_UNORM,
314      1, PIPE_FORMAT_Z32_UNORM,
315      2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
316      2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
317      0
318   };
319   const EGLint *fmt = candidates;
320   EGLint count;
321
322   count = 0;
323   formats[count++] = PIPE_FORMAT_NONE;
324
325   while (*fmt) {
326      EGLint i, n = *fmt++;
327
328      /* pick the first supported format */
329      for (i = 0; i < n; i++) {
330         if (screen->is_format_supported(screen, fmt[i],
331                  PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) {
332            formats[count++] = fmt[i];
333            break;
334         }
335      }
336
337      fmt += n;
338   }
339
340   return count;
341}
342
343/**
344 * Add configs to display and return the next config ID.
345 */
346static EGLint
347egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
348{
349   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
350   const struct native_config **native_configs;
351   enum pipe_format depth_stencil_formats[8];
352   int num_formats, num_configs, i, j;
353
354   native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
355   if (!num_configs) {
356      if (native_configs)
357         FREE(native_configs);
358      return id;
359   }
360
361   num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
362         depth_stencil_formats);
363
364   for (i = 0; i < num_configs; i++) {
365      for (j = 0; j < num_formats; j++) {
366         struct egl_g3d_config *gconf;
367
368         gconf = CALLOC_STRUCT(egl_g3d_config);
369         if (gconf) {
370            _eglInitConfig(&gconf->base, dpy, id);
371            if (!egl_g3d_init_config(drv, dpy, &gconf->base,
372                     native_configs[i], depth_stencil_formats[j])) {
373               FREE(gconf);
374               break;
375            }
376
377            _eglAddConfig(dpy, &gconf->base);
378            id++;
379         }
380      }
381   }
382
383   FREE(native_configs);
384   return id;
385}
386
387static void
388egl_g3d_invalid_surface(struct native_display *ndpy,
389                        struct native_surface *nsurf,
390                        unsigned int seq_num)
391{
392   /* XXX not thread safe? */
393   struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
394   struct egl_g3d_context *gctx;
395
396   /*
397    * Some functions such as egl_g3d_copy_buffers create a temporary native
398    * surface.  There is no gsurf associated with it.
399    */
400   gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
401   if (gctx)
402      gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
403}
404
405static struct pipe_screen *
406egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
407{
408   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
409   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
410   return gdpy->loader->create_drm_screen(name, fd);
411}
412
413static struct pipe_screen *
414egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
415{
416   _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
417   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
418   return gdpy->loader->create_sw_screen(ws);
419}
420
421static struct native_event_handler egl_g3d_native_event_handler = {
422   egl_g3d_invalid_surface,
423   egl_g3d_new_drm_screen,
424   egl_g3d_new_sw_screen
425};
426
427static void
428egl_g3d_free_config(void *conf)
429{
430   struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
431   FREE(gconf);
432}
433
434static void
435egl_g3d_free_screen(void *scr)
436{
437#ifdef EGL_MESA_screen_surface
438   struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
439   FREE(gscr->native_modes);
440   FREE(gscr);
441#endif
442}
443
444static EGLBoolean
445egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
446{
447   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
448
449   _eglReleaseDisplayResources(drv, dpy);
450
451   if (gdpy->pipe)
452      gdpy->pipe->destroy(gdpy->pipe);
453
454   if (dpy->Configs) {
455      _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
456      dpy->Configs = NULL;
457   }
458   if (dpy->Screens) {
459      _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
460      dpy->Screens = NULL;
461   }
462
463   _eglCleanupDisplay(dpy);
464
465   if (gdpy->smapi)
466      egl_g3d_destroy_st_manager(gdpy->smapi);
467
468   if (gdpy->native)
469      gdpy->native->destroy(gdpy->native);
470
471   FREE(gdpy);
472   dpy->DriverData = NULL;
473
474   return EGL_TRUE;
475}
476
477static EGLBoolean
478egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
479                   EGLint *major, EGLint *minor)
480{
481   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
482   struct egl_g3d_display *gdpy;
483   const struct native_platform *nplat;
484
485   nplat = egl_g3d_get_platform(drv, dpy->Platform);
486   if (!nplat)
487      return EGL_FALSE;
488
489   gdpy = CALLOC_STRUCT(egl_g3d_display);
490   if (!gdpy) {
491      _eglError(EGL_BAD_ALLOC, "eglInitialize");
492      goto fail;
493   }
494   gdpy->loader = gdrv->loader;
495   dpy->DriverData = gdpy;
496
497   _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay);
498   gdpy->native = nplat->create_display(dpy->PlatformDisplay,
499         &egl_g3d_native_event_handler, (void *) dpy);
500   if (!gdpy->native) {
501      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
502      goto fail;
503   }
504
505   if (gdpy->loader->api_mask & (1 << ST_API_OPENGL))
506      dpy->ClientAPIsMask |= EGL_OPENGL_BIT;
507   if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES1))
508      dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
509   if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES2))
510      dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
511   if (gdpy->loader->api_mask & (1 << ST_API_OPENVG))
512      dpy->ClientAPIsMask |= EGL_OPENVG_BIT;
513
514   gdpy->smapi = egl_g3d_create_st_manager(dpy);
515   if (!gdpy->smapi) {
516      _eglError(EGL_NOT_INITIALIZED,
517            "eglInitialize(failed to create st manager)");
518      goto fail;
519   }
520
521#ifdef EGL_MESA_screen_surface
522   /* enable MESA_screen_surface before adding (and validating) configs */
523   if (gdpy->native->modeset) {
524      dpy->Extensions.MESA_screen_surface = EGL_TRUE;
525      egl_g3d_add_screens(drv, dpy);
526   }
527#endif
528
529   dpy->Extensions.KHR_image_base = EGL_TRUE;
530   if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
531      dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
532
533   dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
534   dpy->Extensions.KHR_fence_sync = EGL_TRUE;
535
536   if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
537      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
538      goto fail;
539   }
540
541   *major = 1;
542   *minor = 4;
543
544   return EGL_TRUE;
545
546fail:
547   if (gdpy)
548      egl_g3d_terminate(drv, dpy);
549   return EGL_FALSE;
550}
551
552static _EGLProc
553egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
554{
555   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
556   struct st_api *stapi = NULL;
557
558   if (procname && procname[0] == 'v' && procname[1] == 'g')
559      stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
560   else if (procname && procname[0] == 'g' && procname[1] == 'l')
561      stapi = gdrv->loader->guess_gl_api();
562
563   return (_EGLProc) ((stapi) ?
564         stapi->get_proc_address(stapi, procname) : NULL);
565}
566
567static EGLint
568egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
569{
570   return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0;
571}
572
573_EGLDriver *
574egl_g3d_create_driver(const struct egl_g3d_loader *loader)
575{
576   struct egl_g3d_driver *gdrv;
577
578   gdrv = CALLOC_STRUCT(egl_g3d_driver);
579   if (!gdrv)
580      return NULL;
581
582   gdrv->loader = loader;
583
584   egl_g3d_init_driver_api(&gdrv->base);
585   gdrv->base.API.Initialize = egl_g3d_initialize;
586   gdrv->base.API.Terminate = egl_g3d_terminate;
587   gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
588
589   gdrv->base.Probe = egl_g3d_probe;
590
591   /* to be filled by the caller */
592   gdrv->base.Name = NULL;
593   gdrv->base.Unload = NULL;
594
595   return &gdrv->base;
596}
597
598void
599egl_g3d_destroy_driver(_EGLDriver *drv)
600{
601   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
602   FREE(gdrv);
603}
604