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