Merge commit 'origin/perrtblend'
[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 current context of the given API.
248 */
249 static struct egl_g3d_context *
250 egl_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 */
260 static const struct egl_g3d_st *
261 egl_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 */
300 static void
301 egl_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 */
327 static struct native_probe *
328 egl_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 */
349 static void
350 egl_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 */
368 static EGLint
369 get_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
393 static void
394 egl_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 */
457 static EGLint
458 egl_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 */
522 static void
523 egl_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 */
536 static void
537 egl_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
549 static EGLBoolean
550 egl_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
576 static EGLBoolean
577 egl_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
623 fail:
624 if (gdpy)
625 egl_g3d_terminate(drv, dpy);
626 return EGL_FALSE;
627 }
628
629 static _EGLContext *
630 egl_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 */
678 static void
679 destroy_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
694 static EGLBoolean
695 egl_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
702 static EGLBoolean
703 init_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
712 static _EGLSurface *
713 egl_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
752 static _EGLSurface *
753 egl_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
790 static _EGLSurface *
791 egl_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 */
832 static void
833 destroy_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
846 static EGLBoolean
847 egl_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
854 static EGLBoolean
855 egl_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
911 static EGLBoolean
912 egl_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 */
958 static _EGLConfig *
959 find_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 */
977 static struct pipe_surface *
978 get_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
996 static EGLBoolean
997 egl_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
1050 static EGLBoolean
1051 egl_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
1058 static EGLBoolean
1059 egl_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
1074 static _EGLProc
1075 egl_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
1096 static EGLBoolean
1097 egl_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
1152 static EGLBoolean
1153 egl_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
1183 static _EGLSurface *
1184 egl_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
1217 static EGLBoolean
1218 egl_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
1274 static EGLint
1275 egl_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
1303 static void
1304 egl_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 }