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