egl_g3d.c revision 0b99303d1c6244094c24844f86f4e7677ee69f18
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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <assert.h>
26#include <stdio.h>
27#include <string.h>
28#include "pipe/p_screen.h"
29#include "util/u_memory.h"
30#include "util/u_rect.h"
31#include "util/u_inlines.h"
32#include "egldriver.h"
33#include "eglcurrent.h"
34#include "eglconfigutil.h"
35#include "egllog.h"
36
37#include "native.h"
38#include "egl_g3d.h"
39#include "egl_st.h"
40
41/**
42 * Validate the draw/read surfaces of the context.
43 */
44static void
45egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
46{
47   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
48   struct pipe_screen *screen = gdpy->native->screen;
49   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
50   const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
51      ST_SURFACE_FRONT_LEFT,
52      ST_SURFACE_BACK_LEFT,
53      ST_SURFACE_FRONT_RIGHT,
54      ST_SURFACE_BACK_RIGHT,
55   };
56   EGLint num_surfaces, s;
57
58   /* validate draw and/or read buffers */
59   num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
60   for (s = 0; s < num_surfaces; s++) {
61      struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
62      struct egl_g3d_surface *gsurf;
63      struct egl_g3d_buffer *gbuf;
64      EGLint att;
65
66      if (s == 0) {
67         gsurf = egl_g3d_surface(gctx->base.DrawSurface);
68         gbuf = &gctx->draw;
69      }
70      else {
71         gsurf = egl_g3d_surface(gctx->base.ReadSurface);
72         gbuf = &gctx->read;
73      }
74
75      if (!gctx->force_validate) {
76         unsigned int seq_num;
77
78         gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
79               &seq_num, NULL, NULL, NULL);
80         /* skip validation */
81         if (gsurf->sequence_number == seq_num)
82            continue;
83      }
84
85      pipe_surface_reference(&gsurf->render_surface, NULL);
86      memset(textures, 0, sizeof(textures));
87
88      gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
89            &gsurf->sequence_number, textures,
90            &gsurf->base.Width, &gsurf->base.Height);
91      for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
92         struct pipe_texture *pt = textures[att];
93         struct pipe_surface *ps;
94
95         if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
96            ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
97                  PIPE_BUFFER_USAGE_GPU_READ |
98                  PIPE_BUFFER_USAGE_GPU_WRITE);
99            gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
100                  st_att_map[att], ps);
101
102            if (gsurf->render_att == att)
103               pipe_surface_reference(&gsurf->render_surface, ps);
104
105            pipe_surface_reference(&ps, NULL);
106            pipe_texture_reference(&pt, NULL);
107         }
108      }
109
110      gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
111            gsurf->base.Width, gsurf->base.Height);
112   }
113
114   gctx->force_validate = EGL_FALSE;
115
116}
117
118/**
119 * Create a st_framebuffer.
120 */
121static struct st_framebuffer *
122create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
123{
124   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
125   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
126   struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
127
128   return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
129         gconf->native->color_format, gconf->native->depth_format,
130         gconf->native->stencil_format,
131         gsurf->base.Width, gsurf->base.Height, &gsurf->base);
132}
133
134/**
135 * Update the attachments of draw/read surfaces.
136 */
137static void
138egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
139{
140   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
141   EGLint s;
142
143   /* route draw and read buffers' attachments */
144   for (s = 0; s < 2; s++) {
145      struct egl_g3d_surface *gsurf;
146      struct egl_g3d_buffer *gbuf;
147
148      if (s == 0) {
149         gsurf = egl_g3d_surface(gctx->base.DrawSurface);
150         gbuf = &gctx->draw;
151      }
152      else {
153         gsurf = egl_g3d_surface(gctx->base.ReadSurface);
154         gbuf = &gctx->read;
155      }
156
157      gbuf->attachment_mask = (1 << gsurf->render_att);
158
159      /* FIXME OpenGL defaults to draw the front or back buffer when the
160       * context is single-buffered or double-buffered respectively.  In EGL,
161       * however, the buffer to be drawn is determined by the surface, instead
162       * of the context.  As a result, rendering to a pixmap surface with a
163       * double-buffered context does not work as expected.
164       *
165       * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
166       *    NATIVE_ATTACHMENT_FRONT_LEFT);
167       */
168
169      /*
170       * FIXME If the back buffer is asked for here, and the front buffer is
171       * later needed by the client API (e.g. glDrawBuffer is called to draw
172       * the front buffer), it will create a new pipe texture and draw there.
173       * One fix is to ask for both buffers here, but it would be a waste if
174       * the front buffer is never used.  A better fix is to add a callback to
175       * the pipe screen with context private (just like flush_frontbuffer).
176       */
177   }
178}
179
180/**
181 * Reallocate the context's framebuffers after draw/read surfaces change.
182 */
183static EGLBoolean
184egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
185{
186   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
187   struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
188   struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
189
190   /* unreference the old framebuffers */
191   if (gctx->draw.st_fb) {
192      EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
193      void *priv;
194
195      priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
196      if (!gdraw || priv != (void *) &gdraw->base) {
197         gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
198         gctx->draw.st_fb = NULL;
199         gctx->draw.attachment_mask = 0x0;
200      }
201
202      if (is_equal) {
203         gctx->read.st_fb = NULL;
204         gctx->draw.attachment_mask = 0x0;
205      }
206      else {
207         priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
208         if (!gread || priv != (void *) &gread->base) {
209            gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
210            gctx->read.st_fb = NULL;
211            gctx->draw.attachment_mask = 0x0;
212         }
213      }
214   }
215
216   if (!gdraw)
217      return EGL_TRUE;
218
219   /* create the draw fb */
220   if (!gctx->draw.st_fb) {
221      gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
222      if (!gctx->draw.st_fb)
223         return EGL_FALSE;
224   }
225
226   /* create the read fb */
227   if (!gctx->read.st_fb) {
228      if (gread != gdraw) {
229         gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
230         if (!gctx->read.st_fb) {
231            gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
232            gctx->draw.st_fb = NULL;
233            return EGL_FALSE;
234         }
235      }
236      else {
237         /* there is no st_reference_framebuffer... */
238         gctx->read.st_fb = gctx->draw.st_fb;
239      }
240   }
241
242   egl_g3d_route_context(dpy, &gctx->base);
243   gctx->force_validate = EGL_TRUE;
244
245   return EGL_TRUE;
246}
247
248/**
249 * Return the state tracker for the given context.
250 */
251static const struct egl_g3d_st *
252egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
253{
254   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
255   const struct egl_g3d_st *stapi;
256   EGLint idx = -1;
257
258   switch (ctx->ClientAPI) {
259   case EGL_OPENGL_ES_API:
260      switch (ctx->ClientVersion) {
261      case 1:
262         idx = EGL_G3D_ST_OPENGL_ES;
263         break;
264      case 2:
265         idx = EGL_G3D_ST_OPENGL_ES2;
266         break;
267      default:
268         _eglLog(_EGL_WARNING, "unknown client version %d",
269               ctx->ClientVersion);
270         break;
271      }
272      break;
273   case EGL_OPENVG_API:
274      idx = EGL_G3D_ST_OPENVG;
275      break;
276   case EGL_OPENGL_API:
277      idx = EGL_G3D_ST_OPENGL;
278      break;
279   default:
280      _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
281      break;
282   }
283
284   stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
285   return stapi;
286}
287
288/**
289 * Initialize the state trackers.
290 */
291static void
292egl_g3d_init_st(_EGLDriver *drv)
293{
294   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
295   EGLint i;
296
297   /* already initialized */
298   if (gdrv->api_mask)
299      return;
300
301   for (i = 0; i < NUM_EGL_G3D_STS; i++) {
302      gdrv->stapis[i] = egl_g3d_get_st(i);
303      if (gdrv->stapis[i])
304         gdrv->api_mask |= gdrv->stapis[i]->api_bit;
305   }
306
307   if (gdrv->api_mask)
308      _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
309   else
310      _eglLog(_EGL_WARNING, "No supported client API");
311}
312
313/**
314 * Get the probe object of the display.
315 *
316 * Note that this function may be called before the display is initialized.
317 */
318static struct native_probe *
319egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy)
320{
321   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
322   struct native_probe *nprobe;
323
324   nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
325   if (!nprobe || nprobe->display != dpy->NativeDisplay) {
326      if (nprobe)
327         nprobe->destroy(nprobe);
328      nprobe = native_create_probe(dpy->NativeDisplay);
329      _eglSetProbeCache(gdrv->probe_key, (void *) nprobe);
330   }
331
332   return nprobe;
333}
334
335/**
336 * Destroy the probe object of the display.  The display may be NULL.
337 *
338 * Note that this function may be called before the display is initialized.
339 */
340static void
341egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
342{
343   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
344   struct native_probe *nprobe;
345
346   nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
347   if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) {
348      nprobe->destroy(nprobe);
349      _eglSetProbeCache(gdrv->probe_key, NULL);
350   }
351}
352
353/**
354 * Return an API mask that consists of the state trackers that supports the
355 * given mode.
356 *
357 * FIXME add st_is_mode_supported()?
358 */
359static EGLint
360get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
361{
362   EGLint check;
363
364   /* OpenGL ES 1.x and 2.x are checked together */
365   check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
366   if (api_mask & check) {
367      /* this is required by EGL, not by OpenGL ES */
368      if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
369         api_mask &= ~check;
370   }
371
372   check = EGL_OPENVG_BIT;
373   if (api_mask & check) {
374      /* vega st needs the depth/stencil rb */
375      if (!mode->depthBits && !mode->stencilBits)
376         api_mask &= ~check;
377   }
378
379   return api_mask;
380}
381
382#ifdef EGL_MESA_screen_surface
383
384static void
385egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
386{
387   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
388   const struct native_connector **native_connectors;
389   EGLint num_connectors, i;
390
391   native_connectors =
392      gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
393   if (!num_connectors) {
394      if (native_connectors)
395         free(native_connectors);
396      return;
397   }
398
399   for (i = 0; i < num_connectors; i++) {
400      const struct native_connector *nconn = native_connectors[i];
401      struct egl_g3d_screen *gscr;
402      const struct native_mode **native_modes;
403      EGLint num_modes, j;
404
405      /* TODO support for hotplug */
406      native_modes =
407         gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
408      if (!num_modes) {
409         if (native_modes)
410            free(native_modes);
411         continue;
412      }
413
414      gscr = CALLOC_STRUCT(egl_g3d_screen);
415      if (!gscr) {
416         free(native_modes);
417         continue;
418      }
419
420      _eglInitScreen(&gscr->base);
421
422      for (j = 0; j < num_modes; j++) {
423         const struct native_mode *nmode = native_modes[j];
424         _EGLMode *mode;
425
426         mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
427               nmode->refresh_rate, nmode->desc);
428         if (!mode)
429            break;
430         /* gscr->native_modes and gscr->base.Modes should be consistent */
431         assert(mode == &gscr->base.Modes[j]);
432      }
433
434      gscr->native = nconn;
435      gscr->native_modes = native_modes;
436
437      _eglAddScreen(dpy, &gscr->base);
438   }
439
440   free(native_connectors);
441}
442
443#endif /* EGL_MESA_screen_surface */
444
445/**
446 * Add configs to display and return the next config ID.
447 */
448static EGLint
449egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
450{
451   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
452   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
453   const struct native_config **native_configs;
454   int num_configs, i;
455
456   native_configs = gdpy->native->get_configs(gdpy->native,
457         &num_configs);
458   if (!num_configs) {
459      if (native_configs)
460         free(native_configs);
461      return id;
462   }
463
464   for (i = 0; i < num_configs; i++) {
465      EGLint api_mask;
466      struct egl_g3d_config *gconf;
467      EGLBoolean valid;
468
469      gconf = CALLOC_STRUCT(egl_g3d_config);
470      if (!gconf)
471         continue;
472
473      _eglInitConfig(&gconf->base, dpy, id);
474
475      api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
476      if (!api_mask) {
477         _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
478               native_configs[i]->mode.visualID);
479      }
480
481      valid = _eglConfigFromContextModesRec(&gconf->base,
482            &native_configs[i]->mode, api_mask, api_mask);
483      if (valid) {
484#ifdef EGL_MESA_screen_surface
485         /* check if scanout surface bit is set */
486         if (native_configs[i]->scanout_bit) {
487            EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
488            val |= EGL_SCREEN_BIT_MESA;
489            SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
490         }
491#endif
492         valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
493      }
494      if (!valid) {
495         _eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
496               native_configs[i]->mode.visualID);
497         free(gconf);
498         continue;
499      }
500
501      gconf->native = native_configs[i];
502      _eglAddConfig(dpy, &gconf->base);
503      id++;
504   }
505
506   free(native_configs);
507   return id;
508}
509
510/**
511 * Flush the front buffer of the context's draw surface.
512 */
513static void
514egl_g3d_flush_frontbuffer(struct pipe_screen *screen,
515                          struct pipe_surface *surf, void *context_private)
516{
517   struct egl_g3d_context *gctx = egl_g3d_context(context_private);
518   struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface);
519
520   if (gsurf)
521      gsurf->native->flush_frontbuffer(gsurf->native);
522}
523
524/**
525 * Re-validate the context.
526 */
527static void
528egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
529{
530   struct egl_g3d_context *gctx = egl_g3d_context(context_private);
531
532   /**
533    * It is likely that the surface has changed when this function is called.
534    * Set force_validate to skip an unnecessary check.
535    */
536   gctx->force_validate = EGL_TRUE;
537   egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
538}
539
540static EGLBoolean
541egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
542{
543   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
544   EGLint i;
545
546   _eglReleaseDisplayResources(drv, dpy);
547   _eglCleanupDisplay(dpy);
548
549   if (dpy->Screens) {
550      for (i = 0; i < dpy->NumScreens; i++) {
551         struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
552         free(gscr->native_modes);
553         free(gscr);
554      }
555      free(dpy->Screens);
556   }
557
558   if (gdpy->native)
559      gdpy->native->destroy(gdpy->native);
560
561   free(gdpy);
562   dpy->DriverData = NULL;
563
564   return EGL_TRUE;
565}
566
567static EGLBoolean
568egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
569                   EGLint *major, EGLint *minor)
570{
571   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
572   struct egl_g3d_display *gdpy;
573
574   /* the probe object is unlikely to be needed again */
575   egl_g3d_destroy_probe(drv, dpy);
576
577   gdpy = CALLOC_STRUCT(egl_g3d_display);
578   if (!gdpy) {
579      _eglError(EGL_BAD_ALLOC, "eglInitialize");
580      goto fail;
581   }
582   dpy->DriverData = gdpy;
583
584   gdpy->native = native_create_display(dpy->NativeDisplay);
585   if (!gdpy->native) {
586      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
587      goto fail;
588   }
589
590   gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
591   gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
592
593   egl_g3d_init_st(&gdrv->base);
594   dpy->ClientAPIsMask = gdrv->api_mask;
595
596   if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
597      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
598      goto fail;
599   }
600
601#ifdef EGL_MESA_screen_surface
602   /* enable MESA_screen_surface */
603   if (gdpy->native->modeset) {
604      dpy->Extensions.MESA_screen_surface = EGL_TRUE;
605      egl_g3d_add_screens(drv, dpy);
606   }
607#endif
608
609   *major = 1;
610   *minor = 4;
611
612   return EGL_TRUE;
613
614fail:
615   if (gdpy)
616      egl_g3d_terminate(drv, dpy);
617   return EGL_FALSE;
618}
619
620static _EGLContext *
621egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
622                       _EGLContext *share, const EGLint *attribs)
623{
624   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
625   struct egl_g3d_context *gshare = egl_g3d_context(share);
626   struct egl_g3d_config *gconf = egl_g3d_config(conf);
627   struct egl_g3d_context *gctx;
628   const __GLcontextModes *mode;
629
630   gctx = CALLOC_STRUCT(egl_g3d_context);
631   if (!gctx) {
632      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
633      return NULL;
634   }
635
636   if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) {
637      free(gctx);
638      return NULL;
639   }
640
641   gctx->stapi = egl_g3d_choose_st(drv, &gctx->base);
642   if (!gctx->stapi) {
643      free(gctx);
644      return NULL;
645   }
646
647   mode = &gconf->native->mode;
648
649   gctx->pipe = gdpy->native->screen->context_create(
650      gdpy->native->screen,
651      (void *) &gctx->base);
652
653   if (!gctx->pipe) {
654      free(gctx);
655      return NULL;
656   }
657
658   gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
659                        (gshare) ? gshare->st_ctx : NULL);
660   if (!gctx->st_ctx) {
661      gctx->pipe->destroy(gctx->pipe);
662      free(gctx);
663      return NULL;
664   }
665
666   return &gctx->base;
667}
668
669/**
670 * Destroy a context.
671 */
672static void
673destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
674{
675   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
676
677   /* FIXME a context might live longer than its display */
678   if (!dpy->Initialized)
679      _eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
680
681   egl_g3d_realloc_context(dpy, &gctx->base);
682   /* it will destroy the associated pipe context */
683   gctx->stapi->st_destroy_context(gctx->st_ctx);
684
685   free(gctx);
686}
687
688static EGLBoolean
689egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
690{
691   if (!_eglIsContextBound(ctx))
692      destroy_context(dpy, ctx);
693   return EGL_TRUE;
694}
695
696static EGLBoolean
697init_surface_geometry(_EGLSurface *surf)
698{
699   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
700
701   return gsurf->native->validate(gsurf->native, 0x0,
702         &gsurf->sequence_number, NULL,
703         &gsurf->base.Width, &gsurf->base.Height);
704}
705
706static _EGLSurface *
707egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
708                              _EGLConfig *conf, EGLNativeWindowType win,
709                              const EGLint *attribs)
710{
711   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
712   struct egl_g3d_config *gconf = egl_g3d_config(conf);
713   struct egl_g3d_surface *gsurf;
714
715   gsurf = CALLOC_STRUCT(egl_g3d_surface);
716   if (!gsurf) {
717      _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
718      return NULL;
719   }
720
721   if (!_eglInitSurface(&gsurf->base, dpy, EGL_WINDOW_BIT, conf, attribs)) {
722      free(gsurf);
723      return NULL;
724   }
725
726   gsurf->native =
727      gdpy->native->create_window_surface(gdpy->native, win, gconf->native);
728   if (!gsurf->native) {
729      free(gsurf);
730      return NULL;
731   }
732
733   if (!init_surface_geometry(&gsurf->base)) {
734      gsurf->native->destroy(gsurf->native);
735      free(gsurf);
736      return NULL;
737   }
738
739   gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
740                        !gconf->native->mode.doubleBufferMode) ?
741      NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
742
743   return &gsurf->base;
744}
745
746static _EGLSurface *
747egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
748                              _EGLConfig *conf, EGLNativePixmapType pix,
749                              const EGLint *attribs)
750{
751   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
752   struct egl_g3d_config *gconf = egl_g3d_config(conf);
753   struct egl_g3d_surface *gsurf;
754
755   gsurf = CALLOC_STRUCT(egl_g3d_surface);
756   if (!gsurf) {
757      _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
758      return NULL;
759   }
760
761   if (!_eglInitSurface(&gsurf->base, dpy, EGL_PIXMAP_BIT, conf, attribs)) {
762      free(gsurf);
763      return NULL;
764   }
765
766   gsurf->native =
767      gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native);
768   if (!gsurf->native) {
769      free(gsurf);
770      return NULL;
771   }
772
773   if (!init_surface_geometry(&gsurf->base)) {
774      gsurf->native->destroy(gsurf->native);
775      free(gsurf);
776      return NULL;
777   }
778
779   gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
780
781   return &gsurf->base;
782}
783
784static _EGLSurface *
785egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
786                               _EGLConfig *conf, const EGLint *attribs)
787{
788   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
789   struct egl_g3d_config *gconf = egl_g3d_config(conf);
790   struct egl_g3d_surface *gsurf;
791
792   gsurf = CALLOC_STRUCT(egl_g3d_surface);
793   if (!gsurf) {
794      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
795      return NULL;
796   }
797
798   if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) {
799      free(gsurf);
800      return NULL;
801   }
802
803   gsurf->native =
804      gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native,
805            gsurf->base.Width, gsurf->base.Height);
806   if (!gsurf->native) {
807      free(gsurf);
808      return NULL;
809   }
810
811   if (!init_surface_geometry(&gsurf->base)) {
812      gsurf->native->destroy(gsurf->native);
813      free(gsurf);
814      return NULL;
815   }
816
817   gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
818      NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
819
820   return &gsurf->base;
821}
822
823/**
824 * Destroy a surface.
825 */
826static void
827destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
828{
829   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
830
831   /* FIXME a surface might live longer than its display */
832   if (!dpy->Initialized)
833      _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
834
835   pipe_surface_reference(&gsurf->render_surface, NULL);
836   gsurf->native->destroy(gsurf->native);
837   free(gsurf);
838}
839
840static EGLBoolean
841egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
842{
843   if (!_eglIsSurfaceBound(surf))
844      destroy_surface(dpy, surf);
845   return EGL_TRUE;
846}
847
848static EGLBoolean
849egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
850                     _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
851{
852   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
853   struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
854   struct egl_g3d_context *old_gctx;
855   EGLBoolean ok = EGL_TRUE;
856
857   /* bind the new context and return the "orphaned" one */
858   if (!_eglBindContext(&ctx, &draw, &read))
859      return EGL_FALSE;
860   old_gctx = egl_g3d_context(ctx);
861
862   if (old_gctx) {
863      /* flush old context */
864      old_gctx->stapi->st_flush(old_gctx->st_ctx,
865            PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
866
867      /*
868       * The old context is no longer current, and egl_g3d_realloc_context()
869       * should be called to destroy the framebuffers.  However, it is possible
870       * that it will be made current again with the same draw/read surfaces.
871       * It might be better to keep it around.
872       */
873   }
874
875   if (gctx) {
876      ok = egl_g3d_realloc_context(dpy, &gctx->base);
877      if (ok) {
878         ok = gctx->stapi->st_make_current(gctx->st_ctx,
879               gctx->draw.st_fb, gctx->read.st_fb);
880         if (ok) {
881            egl_g3d_validate_context(dpy, &gctx->base);
882            if (gdraw->base.Type == EGL_WINDOW_BIT) {
883               gctx->base.WindowRenderBuffer =
884                  (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
885                  EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
886            }
887         }
888      }
889   }
890   else if (old_gctx) {
891      ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
892      old_gctx->base.WindowRenderBuffer = EGL_NONE;
893   }
894
895   if (ctx && !_eglIsContextLinked(ctx))
896      destroy_context(dpy, ctx);
897   if (draw && !_eglIsSurfaceLinked(draw))
898      destroy_surface(dpy, draw);
899   if (read && read != draw && !_eglIsSurfaceLinked(read))
900      destroy_surface(dpy, read);
901
902   return ok;
903}
904
905static EGLBoolean
906egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
907{
908   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
909   _EGLContext *ctx = _eglGetCurrentContext();
910   struct egl_g3d_context *gctx = NULL;
911
912   /* no-op for pixmap or pbuffer surface */
913   if (gsurf->base.Type == EGL_PIXMAP_BIT ||
914       gsurf->base.Type == EGL_PBUFFER_BIT)
915      return EGL_TRUE;
916
917   /* or when the surface is single-buffered */
918   if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
919      return EGL_TRUE;
920
921   if (ctx && ctx->DrawSurface == surf)
922      gctx = egl_g3d_context(ctx);
923
924   /* flush if the surface is current */
925   if (gctx)
926      gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
927
928   /*
929    * We drew on the back buffer, unless there was no back buffer.
930    * In that case, we drew on the front buffer.  Either case, we call
931    * swap_buffers.
932    */
933   if (!gsurf->native->swap_buffers(gsurf->native))
934      return EGL_FALSE;
935
936   if (gctx) {
937      struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
938
939      /* force validation if the swap method is not copy */
940      if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
941         gctx->force_validate = EGL_TRUE;
942         egl_g3d_validate_context(dpy, &gctx->base);
943      }
944   }
945
946   return EGL_TRUE;
947}
948
949/**
950 * Find a config that supports the pixmap.
951 */
952static _EGLConfig *
953find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix)
954{
955   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
956   struct egl_g3d_config *gconf;
957   EGLint i;
958
959   for (i = 0; i < dpy->NumConfigs; i++) {
960      gconf = egl_g3d_config(dpy->Configs[i]);
961      if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native))
962         break;
963   }
964
965   return (i < dpy->NumConfigs) ? &gconf->base : NULL;
966}
967
968/**
969 * Get the pipe surface of the given attachment of the native surface.
970 */
971static struct pipe_surface *
972get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
973                 enum native_attachment natt)
974{
975   struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
976   struct pipe_surface *psurf;
977
978   textures[natt] = NULL;
979   nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL);
980   if (!textures[natt])
981      return NULL;
982
983   psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
984         0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE);
985   pipe_texture_reference(&textures[natt], NULL);
986
987   return psurf;
988}
989
990static EGLBoolean
991egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
992                     EGLNativePixmapType target)
993{
994   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
995   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
996   _EGLContext *ctx = _eglGetCurrentContext();
997   struct egl_g3d_config *gconf;
998   struct native_surface *nsurf;
999   struct pipe_screen *screen = gdpy->native->screen;
1000   struct pipe_surface *psurf;
1001
1002   if (!gsurf->render_surface)
1003      return EGL_TRUE;
1004
1005   gconf = egl_g3d_config(find_pixmap_config(dpy, target));
1006   if (!gconf)
1007      return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
1008
1009   nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
1010         target, gconf->native);
1011   if (!nsurf)
1012      return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
1013
1014   /* flush if the surface is current */
1015   if (ctx && ctx->DrawSurface == &gsurf->base) {
1016      struct egl_g3d_context *gctx = egl_g3d_context(ctx);
1017      gctx->stapi->st_flush(gctx->st_ctx,
1018            PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
1019   }
1020
1021   psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
1022   if (psurf) {
1023      struct pipe_context pipe;
1024
1025      /**
1026       * XXX This is hacky.  If we might allow the EGLDisplay to create a pipe
1027       * context of its own and use the blitter context for this.
1028       */
1029      memset(&pipe, 0, sizeof(pipe));
1030      pipe.screen = screen;
1031
1032      util_surface_copy(&pipe, FALSE, psurf, 0, 0,
1033            gsurf->render_surface, 0, 0, psurf->width, psurf->height);
1034
1035      pipe_surface_reference(&psurf, NULL);
1036      nsurf->flush_frontbuffer(nsurf);
1037   }
1038
1039   nsurf->destroy(nsurf);
1040
1041   return EGL_TRUE;
1042}
1043
1044static EGLBoolean
1045egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
1046{
1047   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
1048   gctx->stapi->st_finish(gctx->st_ctx);
1049   return EGL_TRUE;
1050}
1051
1052static EGLBoolean
1053egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
1054{
1055   _EGLContext *ctx = _eglGetCurrentContext();
1056
1057   if (engine != EGL_CORE_NATIVE_ENGINE)
1058      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
1059
1060   if (ctx && ctx->DrawSurface) {
1061      struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface);
1062      gsurf->native->wait(gsurf->native);
1063   }
1064
1065   return EGL_TRUE;
1066}
1067
1068static _EGLProc
1069egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
1070{
1071   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
1072   _EGLProc proc;
1073   EGLint i;
1074
1075   /* in case this is called before a display is initialized */
1076   egl_g3d_init_st(&gdrv->base);
1077
1078   for (i = 0; i < NUM_EGL_G3D_STS; i++) {
1079      const struct egl_g3d_st *stapi = gdrv->stapis[i];
1080      if (stapi) {
1081         proc = (_EGLProc) stapi->st_get_proc_address(procname);
1082         if (proc)
1083            return proc;
1084      }
1085   }
1086
1087   return (_EGLProc) NULL;
1088}
1089
1090static EGLBoolean
1091egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
1092                       _EGLSurface *surf, EGLint buffer)
1093{
1094   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1095   _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
1096   struct egl_g3d_context *gctx;
1097   enum pipe_format target_format;
1098   int target;
1099
1100   if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
1101      return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
1102   if (buffer != EGL_BACK_BUFFER)
1103      return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
1104   if (gsurf->base.BoundToTexture)
1105      return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
1106
1107   switch (gsurf->base.TextureFormat) {
1108   case EGL_TEXTURE_RGB:
1109      target_format = PIPE_FORMAT_R8G8B8_UNORM;
1110      break;
1111   case EGL_TEXTURE_RGBA:
1112      target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
1113      break;
1114   default:
1115      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
1116   }
1117
1118   switch (gsurf->base.TextureTarget) {
1119   case EGL_TEXTURE_2D:
1120      target = ST_TEXTURE_2D;
1121      break;
1122   default:
1123      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
1124   }
1125
1126   if (!es1)
1127      return EGL_TRUE;
1128   if (!gsurf->render_surface)
1129      return EGL_FALSE;
1130
1131   /* flush properly if the surface is bound */
1132   if (gsurf->base.CurrentContext) {
1133      gctx = egl_g3d_context(gsurf->base.CurrentContext);
1134      gctx->stapi->st_flush(gctx->st_ctx,
1135            PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
1136   }
1137
1138   gctx = egl_g3d_context(es1);
1139   gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
1140         target, gsurf->base.MipmapLevel, target_format);
1141
1142   gsurf->base.BoundToTexture = EGL_TRUE;
1143
1144   return EGL_TRUE;
1145}
1146
1147static EGLBoolean
1148egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
1149                          _EGLSurface *surf, EGLint buffer)
1150{
1151   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1152
1153   if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
1154       !gsurf->base.BoundToTexture)
1155      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
1156   if (buffer != EGL_BACK_BUFFER)
1157      return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
1158
1159   if (gsurf->render_surface) {
1160      _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
1161      struct egl_g3d_context *gctx = egl_g3d_context(ctx);
1162
1163      /* what if the context the surface binds to is no longer current? */
1164      if (gctx)
1165         gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
1166               ST_TEXTURE_2D, gsurf->base.MipmapLevel);
1167   }
1168
1169   gsurf->base.BoundToTexture = EGL_FALSE;
1170
1171   return EGL_TRUE;
1172}
1173
1174#ifdef EGL_MESA_screen_surface
1175
1176static _EGLSurface *
1177egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1178                              _EGLConfig *conf, const EGLint *attribs)
1179{
1180   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
1181   struct egl_g3d_config *gconf = egl_g3d_config(conf);
1182   struct egl_g3d_surface *gsurf;
1183
1184   gsurf = CALLOC_STRUCT(egl_g3d_surface);
1185   if (!gsurf) {
1186      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
1187      return NULL;
1188   }
1189
1190   if (!_eglInitSurface(&gsurf->base, dpy,
1191            EGL_SCREEN_BIT_MESA, conf, attribs)) {
1192      free(gsurf);
1193      return NULL;
1194   }
1195
1196   gsurf->native =
1197      gdpy->native->modeset->create_scanout_surface(gdpy->native,
1198            gconf->native, gsurf->base.Width, gsurf->base.Height);
1199   if (!gsurf->native) {
1200      free(gsurf);
1201      return NULL;
1202   }
1203
1204   gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
1205      NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
1206
1207   return &gsurf->base;
1208}
1209
1210static EGLBoolean
1211egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1212                            _EGLScreen *scr, _EGLSurface *surf,
1213                            _EGLMode *mode)
1214{
1215   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
1216   struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
1217   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1218   struct native_surface *nsurf;
1219   const struct native_mode *nmode;
1220   EGLBoolean changed;
1221
1222   if (gsurf) {
1223      EGLint idx;
1224
1225      if (!mode)
1226         return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
1227      if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
1228         return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
1229      if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
1230         return _eglError(EGL_BAD_MATCH,
1231               "eglShowSurfaceMESA(surface smaller than mode size)");
1232
1233      /* find the index of the mode */
1234      for (idx = 0; idx < gscr->base.NumModes; idx++)
1235         if (mode == &gscr->base.Modes[idx])
1236            break;
1237      if (idx >= gscr->base.NumModes) {
1238         return _eglError(EGL_BAD_MODE_MESA,
1239               "eglShowSurfaceMESA(unknown mode)");
1240      }
1241
1242      nsurf = gsurf->native;
1243      nmode = gscr->native_modes[idx];
1244   }
1245   else {
1246      if (mode)
1247         return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
1248
1249      /* disable the screen */
1250      nsurf = NULL;
1251      nmode = NULL;
1252   }
1253
1254   /* TODO surface panning by CRTC choosing */
1255   changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
1256         gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
1257   if (changed) {
1258      gscr->base.CurrentSurface = &gsurf->base;
1259      gscr->base.CurrentMode = mode;
1260   }
1261
1262   return changed;
1263}
1264
1265#endif /* EGL_MESA_screen_surface */
1266
1267static EGLint
1268egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
1269{
1270   struct native_probe *nprobe;
1271   enum native_probe_result res;
1272   EGLint score;
1273
1274   nprobe = egl_g3d_get_probe(drv, dpy);
1275   res = native_get_probe_result(nprobe);
1276
1277   switch (res) {
1278   case NATIVE_PROBE_UNKNOWN:
1279   default:
1280      score = 0;
1281      break;
1282   case NATIVE_PROBE_FALLBACK:
1283      score = 40;
1284      break;
1285   case NATIVE_PROBE_SUPPORTED:
1286      score = 50;
1287      break;
1288   case NATIVE_PROBE_EXACT:
1289      score = 100;
1290      break;
1291   }
1292
1293   return score;
1294}
1295
1296static void
1297egl_g3d_unload(_EGLDriver *drv)
1298{
1299   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
1300
1301   egl_g3d_destroy_probe(drv, NULL);
1302   free(gdrv);
1303}
1304
1305_EGLDriver *
1306_eglMain(const char *args)
1307{
1308   static char driver_name[64];
1309   struct egl_g3d_driver *gdrv;
1310
1311   snprintf(driver_name, sizeof(driver_name),
1312         "Gallium/%s", native_get_name());
1313
1314   gdrv = CALLOC_STRUCT(egl_g3d_driver);
1315   if (!gdrv)
1316      return NULL;
1317
1318   _eglInitDriverFallbacks(&gdrv->base);
1319
1320   gdrv->base.API.Initialize = egl_g3d_initialize;
1321   gdrv->base.API.Terminate = egl_g3d_terminate;
1322   gdrv->base.API.CreateContext = egl_g3d_create_context;
1323   gdrv->base.API.DestroyContext = egl_g3d_destroy_context;
1324   gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface;
1325   gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
1326   gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
1327   gdrv->base.API.DestroySurface = egl_g3d_destroy_surface;
1328   gdrv->base.API.MakeCurrent = egl_g3d_make_current;
1329   gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers;
1330   gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers;
1331   gdrv->base.API.WaitClient = egl_g3d_wait_client;
1332   gdrv->base.API.WaitNative = egl_g3d_wait_native;
1333   gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
1334
1335   gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
1336   gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
1337
1338#ifdef EGL_MESA_screen_surface
1339   gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
1340   gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
1341#endif
1342
1343   gdrv->base.Name = driver_name;
1344   gdrv->base.Probe = egl_g3d_probe;
1345   gdrv->base.Unload = egl_g3d_unload;
1346
1347   /* the key is " EGL G3D" */
1348   gdrv->probe_key = 0x0E61063D;
1349
1350   return &gdrv->base;
1351}
1352