egl_g3d.c revision 719c4b0fc2672adcaacd81877db9901ff5cd1d7c
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   egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
532}
533
534static EGLBoolean
535egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
536{
537   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
538   EGLint i;
539
540   _eglReleaseDisplayResources(drv, dpy);
541   _eglCleanupDisplay(dpy);
542
543   if (dpy->Screens) {
544      for (i = 0; i < dpy->NumScreens; i++) {
545         struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
546         free(gscr->native_modes);
547         free(gscr);
548      }
549      free(dpy->Screens);
550   }
551
552   if (gdpy->native)
553      gdpy->native->destroy(gdpy->native);
554
555   free(gdpy);
556   dpy->DriverData = NULL;
557
558   return EGL_TRUE;
559}
560
561static EGLBoolean
562egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
563                   EGLint *major, EGLint *minor)
564{
565   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
566   struct egl_g3d_display *gdpy;
567
568   /* the probe object is unlikely to be needed again */
569   egl_g3d_destroy_probe(drv, dpy);
570
571   gdpy = CALLOC_STRUCT(egl_g3d_display);
572   if (!gdpy) {
573      _eglError(EGL_BAD_ALLOC, "eglInitialize");
574      goto fail;
575   }
576   dpy->DriverData = gdpy;
577
578   gdpy->native = native_create_display(dpy->NativeDisplay);
579   if (!gdpy->native) {
580      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
581      goto fail;
582   }
583
584   gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
585   gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
586
587   egl_g3d_init_st(&gdrv->base);
588   dpy->ClientAPIsMask = gdrv->api_mask;
589
590   if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
591      _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
592      goto fail;
593   }
594
595#ifdef EGL_MESA_screen_surface
596   /* enable MESA_screen_surface */
597   if (gdpy->native->modeset) {
598      dpy->Extensions.MESA_screen_surface = EGL_TRUE;
599      egl_g3d_add_screens(drv, dpy);
600   }
601#endif
602
603   *major = 1;
604   *minor = 4;
605
606   return EGL_TRUE;
607
608fail:
609   if (gdpy)
610      egl_g3d_terminate(drv, dpy);
611   return EGL_FALSE;
612}
613
614static _EGLContext *
615egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
616                       _EGLContext *share, const EGLint *attribs)
617{
618   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
619   struct egl_g3d_context *gshare = egl_g3d_context(share);
620   struct egl_g3d_config *gconf = egl_g3d_config(conf);
621   struct egl_g3d_context *gctx;
622   const __GLcontextModes *mode;
623
624   gctx = CALLOC_STRUCT(egl_g3d_context);
625   if (!gctx) {
626      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
627      return NULL;
628   }
629
630   if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) {
631      free(gctx);
632      return NULL;
633   }
634
635   gctx->stapi = egl_g3d_choose_st(drv, &gctx->base);
636   if (!gctx->stapi) {
637      free(gctx);
638      return NULL;
639   }
640
641   mode = &gconf->native->mode;
642
643   gctx->pipe = gdpy->native->screen->context_create(
644      gdpy->native->screen,
645      (void *) &gctx->base);
646
647   if (!gctx->pipe) {
648      free(gctx);
649      return NULL;
650   }
651
652   gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
653                        (gshare) ? gshare->st_ctx : NULL);
654   if (!gctx->st_ctx) {
655      gctx->pipe->destroy(gctx->pipe);
656      free(gctx);
657      return NULL;
658   }
659
660   return &gctx->base;
661}
662
663/**
664 * Destroy a context.
665 */
666static void
667destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
668{
669   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
670
671   /* FIXME a context might live longer than its display */
672   if (!dpy->Initialized)
673      _eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
674
675   egl_g3d_realloc_context(dpy, &gctx->base);
676   /* it will destroy the associated pipe context */
677   gctx->stapi->st_destroy_context(gctx->st_ctx);
678
679   free(gctx);
680}
681
682static EGLBoolean
683egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
684{
685   if (!_eglIsContextBound(ctx))
686      destroy_context(dpy, ctx);
687   return EGL_TRUE;
688}
689
690static EGLBoolean
691init_surface_geometry(_EGLSurface *surf)
692{
693   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
694
695   return gsurf->native->validate(gsurf->native, 0x0,
696         &gsurf->sequence_number, NULL,
697         &gsurf->base.Width, &gsurf->base.Height);
698}
699
700static _EGLSurface *
701egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
702                              _EGLConfig *conf, EGLNativeWindowType win,
703                              const EGLint *attribs)
704{
705   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
706   struct egl_g3d_config *gconf = egl_g3d_config(conf);
707   struct egl_g3d_surface *gsurf;
708
709   gsurf = CALLOC_STRUCT(egl_g3d_surface);
710   if (!gsurf) {
711      _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
712      return NULL;
713   }
714
715   if (!_eglInitSurface(&gsurf->base, dpy, EGL_WINDOW_BIT, conf, attribs)) {
716      free(gsurf);
717      return NULL;
718   }
719
720   gsurf->native =
721      gdpy->native->create_window_surface(gdpy->native, win, gconf->native);
722   if (!gsurf->native) {
723      free(gsurf);
724      return NULL;
725   }
726
727   if (!init_surface_geometry(&gsurf->base)) {
728      gsurf->native->destroy(gsurf->native);
729      free(gsurf);
730      return NULL;
731   }
732
733   gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
734                        !gconf->native->mode.doubleBufferMode) ?
735      NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
736
737   return &gsurf->base;
738}
739
740static _EGLSurface *
741egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
742                              _EGLConfig *conf, EGLNativePixmapType pix,
743                              const EGLint *attribs)
744{
745   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
746   struct egl_g3d_config *gconf = egl_g3d_config(conf);
747   struct egl_g3d_surface *gsurf;
748
749   gsurf = CALLOC_STRUCT(egl_g3d_surface);
750   if (!gsurf) {
751      _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
752      return NULL;
753   }
754
755   if (!_eglInitSurface(&gsurf->base, dpy, EGL_PIXMAP_BIT, conf, attribs)) {
756      free(gsurf);
757      return NULL;
758   }
759
760   gsurf->native =
761      gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native);
762   if (!gsurf->native) {
763      free(gsurf);
764      return NULL;
765   }
766
767   if (!init_surface_geometry(&gsurf->base)) {
768      gsurf->native->destroy(gsurf->native);
769      free(gsurf);
770      return NULL;
771   }
772
773   gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
774
775   return &gsurf->base;
776}
777
778static _EGLSurface *
779egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
780                               _EGLConfig *conf, const EGLint *attribs)
781{
782   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
783   struct egl_g3d_config *gconf = egl_g3d_config(conf);
784   struct egl_g3d_surface *gsurf;
785
786   gsurf = CALLOC_STRUCT(egl_g3d_surface);
787   if (!gsurf) {
788      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
789      return NULL;
790   }
791
792   if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) {
793      free(gsurf);
794      return NULL;
795   }
796
797   gsurf->native =
798      gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native,
799            gsurf->base.Width, gsurf->base.Height);
800   if (!gsurf->native) {
801      free(gsurf);
802      return NULL;
803   }
804
805   if (!init_surface_geometry(&gsurf->base)) {
806      gsurf->native->destroy(gsurf->native);
807      free(gsurf);
808      return NULL;
809   }
810
811   gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
812      NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
813
814   return &gsurf->base;
815}
816
817/**
818 * Destroy a surface.
819 */
820static void
821destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
822{
823   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
824
825   /* FIXME a surface might live longer than its display */
826   if (!dpy->Initialized)
827      _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
828
829   pipe_surface_reference(&gsurf->render_surface, NULL);
830   gsurf->native->destroy(gsurf->native);
831   free(gsurf);
832}
833
834static EGLBoolean
835egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
836{
837   if (!_eglIsSurfaceBound(surf))
838      destroy_surface(dpy, surf);
839   return EGL_TRUE;
840}
841
842static EGLBoolean
843egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
844                     _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
845{
846   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
847   struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
848   struct egl_g3d_context *old_gctx;
849   EGLBoolean ok = EGL_TRUE;
850
851   /* bind the new context and return the "orphaned" one */
852   if (!_eglBindContext(&ctx, &draw, &read))
853      return EGL_FALSE;
854   old_gctx = egl_g3d_context(ctx);
855
856   if (old_gctx) {
857      /* flush old context */
858      old_gctx->stapi->st_flush(old_gctx->st_ctx,
859            PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
860
861      /*
862       * The old context is no longer current, and egl_g3d_realloc_context()
863       * should be called to destroy the framebuffers.  However, it is possible
864       * that it will be made current again with the same draw/read surfaces.
865       * It might be better to keep it around.
866       */
867   }
868
869   if (gctx) {
870      ok = egl_g3d_realloc_context(dpy, &gctx->base);
871      if (ok) {
872         ok = gctx->stapi->st_make_current(gctx->st_ctx,
873               gctx->draw.st_fb, gctx->read.st_fb);
874         if (ok) {
875            egl_g3d_validate_context(dpy, &gctx->base);
876            if (gdraw->base.Type == EGL_WINDOW_BIT) {
877               gctx->base.WindowRenderBuffer =
878                  (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
879                  EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
880            }
881         }
882      }
883   }
884   else if (old_gctx) {
885      ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
886      old_gctx->base.WindowRenderBuffer = EGL_NONE;
887   }
888
889   if (ctx && !_eglIsContextLinked(ctx))
890      destroy_context(dpy, ctx);
891   if (draw && !_eglIsSurfaceLinked(draw))
892      destroy_surface(dpy, draw);
893   if (read && read != draw && !_eglIsSurfaceLinked(read))
894      destroy_surface(dpy, read);
895
896   return ok;
897}
898
899static EGLBoolean
900egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
901{
902   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
903   _EGLContext *ctx = _eglGetCurrentContext();
904   struct egl_g3d_context *gctx = NULL;
905
906   /* no-op for pixmap or pbuffer surface */
907   if (gsurf->base.Type == EGL_PIXMAP_BIT ||
908       gsurf->base.Type == EGL_PBUFFER_BIT)
909      return EGL_TRUE;
910
911   /* or when the surface is single-buffered */
912   if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
913      return EGL_TRUE;
914
915   if (ctx && ctx->DrawSurface == surf)
916      gctx = egl_g3d_context(ctx);
917
918   /* flush if the surface is current */
919   if (gctx)
920      gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
921
922   /*
923    * We drew on the back buffer, unless there was no back buffer.
924    * In that case, we drew on the front buffer.  Either case, we call
925    * swap_buffers.
926    */
927   if (!gsurf->native->swap_buffers(gsurf->native))
928      return EGL_FALSE;
929
930   if (gctx) {
931      struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
932
933      /* force validation if the swap method is not copy */
934      if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
935         gctx->force_validate = EGL_TRUE;
936         egl_g3d_validate_context(dpy, &gctx->base);
937      }
938   }
939
940   return EGL_TRUE;
941}
942
943/**
944 * Find a config that supports the pixmap.
945 */
946static _EGLConfig *
947find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix)
948{
949   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
950   struct egl_g3d_config *gconf;
951   EGLint i;
952
953   for (i = 0; i < dpy->NumConfigs; i++) {
954      gconf = egl_g3d_config(dpy->Configs[i]);
955      if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native))
956         break;
957   }
958
959   return (i < dpy->NumConfigs) ? &gconf->base : NULL;
960}
961
962/**
963 * Get the pipe surface of the given attachment of the native surface.
964 */
965static struct pipe_surface *
966get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf,
967                 enum native_attachment natt)
968{
969   struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
970   struct pipe_surface *psurf;
971
972   textures[natt] = NULL;
973   nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL);
974   if (!textures[natt])
975      return NULL;
976
977   psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt],
978         0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE);
979   pipe_texture_reference(&textures[natt], NULL);
980
981   return psurf;
982}
983
984static EGLBoolean
985egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
986                     EGLNativePixmapType target)
987{
988   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
989   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
990   _EGLContext *ctx = _eglGetCurrentContext();
991   struct egl_g3d_config *gconf;
992   struct native_surface *nsurf;
993   struct pipe_screen *screen = gdpy->native->screen;
994   struct pipe_surface *psurf;
995
996   if (!gsurf->render_surface)
997      return EGL_TRUE;
998
999   gconf = egl_g3d_config(find_pixmap_config(dpy, target));
1000   if (!gconf)
1001      return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
1002
1003   nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
1004         target, gconf->native);
1005   if (!nsurf)
1006      return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers");
1007
1008   /* flush if the surface is current */
1009   if (ctx && ctx->DrawSurface == &gsurf->base) {
1010      struct egl_g3d_context *gctx = egl_g3d_context(ctx);
1011      gctx->stapi->st_flush(gctx->st_ctx,
1012            PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
1013   }
1014
1015   psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
1016   if (psurf) {
1017      struct pipe_context pipe;
1018
1019      /**
1020       * XXX This is hacky.  If we might allow the EGLDisplay to create a pipe
1021       * context of its own and use the blitter context for this.
1022       */
1023      memset(&pipe, 0, sizeof(pipe));
1024      pipe.screen = screen;
1025
1026      util_surface_copy(&pipe, FALSE, psurf, 0, 0,
1027            gsurf->render_surface, 0, 0, psurf->width, psurf->height);
1028
1029      pipe_surface_reference(&psurf, NULL);
1030      nsurf->flush_frontbuffer(nsurf);
1031   }
1032
1033   nsurf->destroy(nsurf);
1034
1035   return EGL_TRUE;
1036}
1037
1038static EGLBoolean
1039egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
1040{
1041   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
1042   gctx->stapi->st_finish(gctx->st_ctx);
1043   return EGL_TRUE;
1044}
1045
1046static EGLBoolean
1047egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
1048{
1049   _EGLContext *ctx = _eglGetCurrentContext();
1050
1051   if (engine != EGL_CORE_NATIVE_ENGINE)
1052      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
1053
1054   if (ctx && ctx->DrawSurface) {
1055      struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface);
1056      gsurf->native->wait(gsurf->native);
1057   }
1058
1059   return EGL_TRUE;
1060}
1061
1062static _EGLProc
1063egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
1064{
1065   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
1066   _EGLProc proc;
1067   EGLint i;
1068
1069   /* in case this is called before a display is initialized */
1070   egl_g3d_init_st(&gdrv->base);
1071
1072   for (i = 0; i < NUM_EGL_G3D_STS; i++) {
1073      const struct egl_g3d_st *stapi = gdrv->stapis[i];
1074      if (stapi) {
1075         proc = (_EGLProc) stapi->st_get_proc_address(procname);
1076         if (proc)
1077            return proc;
1078      }
1079   }
1080
1081   return (_EGLProc) NULL;
1082}
1083
1084static EGLBoolean
1085egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
1086                       _EGLSurface *surf, EGLint buffer)
1087{
1088   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1089   _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
1090   struct egl_g3d_context *gctx;
1091   enum pipe_format target_format;
1092   int target;
1093
1094   if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
1095      return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
1096   if (buffer != EGL_BACK_BUFFER)
1097      return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
1098   if (gsurf->base.BoundToTexture)
1099      return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
1100
1101   switch (gsurf->base.TextureFormat) {
1102   case EGL_TEXTURE_RGB:
1103      target_format = PIPE_FORMAT_R8G8B8_UNORM;
1104      break;
1105   case EGL_TEXTURE_RGBA:
1106      target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
1107      break;
1108   default:
1109      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
1110   }
1111
1112   switch (gsurf->base.TextureTarget) {
1113   case EGL_TEXTURE_2D:
1114      target = ST_TEXTURE_2D;
1115      break;
1116   default:
1117      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
1118   }
1119
1120   if (!es1)
1121      return EGL_TRUE;
1122   if (!gsurf->render_surface)
1123      return EGL_FALSE;
1124
1125   /* flush properly if the surface is bound */
1126   if (gsurf->base.CurrentContext) {
1127      gctx = egl_g3d_context(gsurf->base.CurrentContext);
1128      gctx->stapi->st_flush(gctx->st_ctx,
1129            PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
1130   }
1131
1132   gctx = egl_g3d_context(es1);
1133   gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
1134         target, gsurf->base.MipmapLevel, target_format);
1135
1136   gsurf->base.BoundToTexture = EGL_TRUE;
1137
1138   return EGL_TRUE;
1139}
1140
1141static EGLBoolean
1142egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
1143                          _EGLSurface *surf, EGLint buffer)
1144{
1145   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1146
1147   if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
1148       !gsurf->base.BoundToTexture)
1149      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
1150   if (buffer != EGL_BACK_BUFFER)
1151      return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
1152
1153   if (gsurf->render_surface) {
1154      _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
1155      struct egl_g3d_context *gctx = egl_g3d_context(ctx);
1156
1157      /* what if the context the surface binds to is no longer current? */
1158      if (gctx)
1159         gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
1160               ST_TEXTURE_2D, gsurf->base.MipmapLevel);
1161   }
1162
1163   gsurf->base.BoundToTexture = EGL_FALSE;
1164
1165   return EGL_TRUE;
1166}
1167
1168#ifdef EGL_MESA_screen_surface
1169
1170static _EGLSurface *
1171egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1172                              _EGLConfig *conf, const EGLint *attribs)
1173{
1174   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
1175   struct egl_g3d_config *gconf = egl_g3d_config(conf);
1176   struct egl_g3d_surface *gsurf;
1177
1178   gsurf = CALLOC_STRUCT(egl_g3d_surface);
1179   if (!gsurf) {
1180      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
1181      return NULL;
1182   }
1183
1184   if (!_eglInitSurface(&gsurf->base, dpy,
1185            EGL_SCREEN_BIT_MESA, conf, attribs)) {
1186      free(gsurf);
1187      return NULL;
1188   }
1189
1190   gsurf->native =
1191      gdpy->native->modeset->create_scanout_surface(gdpy->native,
1192            gconf->native, gsurf->base.Width, gsurf->base.Height);
1193   if (!gsurf->native) {
1194      free(gsurf);
1195      return NULL;
1196   }
1197
1198   gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
1199      NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
1200
1201   return &gsurf->base;
1202}
1203
1204static EGLBoolean
1205egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
1206                            _EGLScreen *scr, _EGLSurface *surf,
1207                            _EGLMode *mode)
1208{
1209   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
1210   struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
1211   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1212   struct native_surface *nsurf;
1213   const struct native_mode *nmode;
1214   EGLBoolean changed;
1215
1216   if (gsurf) {
1217      EGLint idx;
1218
1219      if (!mode)
1220         return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
1221      if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
1222         return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
1223      if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
1224         return _eglError(EGL_BAD_MATCH,
1225               "eglShowSurfaceMESA(surface smaller than mode size)");
1226
1227      /* find the index of the mode */
1228      for (idx = 0; idx < gscr->base.NumModes; idx++)
1229         if (mode == &gscr->base.Modes[idx])
1230            break;
1231      if (idx >= gscr->base.NumModes) {
1232         return _eglError(EGL_BAD_MODE_MESA,
1233               "eglShowSurfaceMESA(unknown mode)");
1234      }
1235
1236      nsurf = gsurf->native;
1237      nmode = gscr->native_modes[idx];
1238   }
1239   else {
1240      if (mode)
1241         return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
1242
1243      /* disable the screen */
1244      nsurf = NULL;
1245      nmode = NULL;
1246   }
1247
1248   /* TODO surface panning by CRTC choosing */
1249   changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
1250         gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
1251   if (changed) {
1252      gscr->base.CurrentSurface = &gsurf->base;
1253      gscr->base.CurrentMode = mode;
1254   }
1255
1256   return changed;
1257}
1258
1259#endif /* EGL_MESA_screen_surface */
1260
1261static EGLint
1262egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
1263{
1264   struct native_probe *nprobe;
1265   enum native_probe_result res;
1266   EGLint score;
1267
1268   nprobe = egl_g3d_get_probe(drv, dpy);
1269   res = native_get_probe_result(nprobe);
1270
1271   switch (res) {
1272   case NATIVE_PROBE_UNKNOWN:
1273   default:
1274      score = 0;
1275      break;
1276   case NATIVE_PROBE_FALLBACK:
1277      score = 40;
1278      break;
1279   case NATIVE_PROBE_SUPPORTED:
1280      score = 50;
1281      break;
1282   case NATIVE_PROBE_EXACT:
1283      score = 100;
1284      break;
1285   }
1286
1287   return score;
1288}
1289
1290static void
1291egl_g3d_unload(_EGLDriver *drv)
1292{
1293   struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
1294
1295   egl_g3d_destroy_probe(drv, NULL);
1296   free(gdrv);
1297}
1298
1299_EGLDriver *
1300_eglMain(const char *args)
1301{
1302   static char driver_name[64];
1303   struct egl_g3d_driver *gdrv;
1304
1305   snprintf(driver_name, sizeof(driver_name),
1306         "Gallium/%s", native_get_name());
1307
1308   gdrv = CALLOC_STRUCT(egl_g3d_driver);
1309   if (!gdrv)
1310      return NULL;
1311
1312   _eglInitDriverFallbacks(&gdrv->base);
1313
1314   gdrv->base.API.Initialize = egl_g3d_initialize;
1315   gdrv->base.API.Terminate = egl_g3d_terminate;
1316   gdrv->base.API.CreateContext = egl_g3d_create_context;
1317   gdrv->base.API.DestroyContext = egl_g3d_destroy_context;
1318   gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface;
1319   gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
1320   gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
1321   gdrv->base.API.DestroySurface = egl_g3d_destroy_surface;
1322   gdrv->base.API.MakeCurrent = egl_g3d_make_current;
1323   gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers;
1324   gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers;
1325   gdrv->base.API.WaitClient = egl_g3d_wait_client;
1326   gdrv->base.API.WaitNative = egl_g3d_wait_native;
1327   gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
1328
1329   gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
1330   gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
1331
1332#ifdef EGL_MESA_screen_surface
1333   gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
1334   gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
1335#endif
1336
1337   gdrv->base.Name = driver_name;
1338   gdrv->base.Probe = egl_g3d_probe;
1339   gdrv->base.Unload = egl_g3d_unload;
1340
1341   /* the key is " EGL G3D" */
1342   gdrv->probe_key = 0x0E61063D;
1343
1344   return &gdrv->base;
1345}
1346