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