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