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