egl: Add _EGLDriver as the first argument to GetProcAddress.
[mesa.git] / src / gallium / state_trackers / egl_g3d / 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 "util/u_memory.h"
28 #include "egldriver.h"
29 #include "eglcurrent.h"
30 #include "eglconfigutil.h"
31 #include "egllog.h"
32
33 #include "native.h"
34 #include "egl_g3d.h"
35 #include "egl_st.h"
36
37 /**
38 * Validate the draw/read surfaces of the context.
39 */
40 static void
41 egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
42 {
43 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
44 struct pipe_screen *screen = gdpy->native->screen;
45 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
46 EGLint num_surfaces;
47 EGLint s, i;
48
49 /* validate draw and/or read buffers */
50 num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
51 for (s = 0; s < num_surfaces; s++) {
52 struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
53 struct egl_g3d_surface *gsurf;
54 struct egl_g3d_buffer *gbuf;
55
56 if (s == 0) {
57 gsurf = egl_g3d_surface(gctx->base.DrawSurface);
58 gbuf = &gctx->draw;
59 }
60 else {
61 gsurf = egl_g3d_surface(gctx->base.ReadSurface);
62 gbuf = &gctx->read;
63 }
64
65 if (!gctx->force_validate) {
66 EGLint cur_w, cur_h;
67
68 cur_w = gsurf->base.Width;
69 cur_h = gsurf->base.Height;
70 gsurf->native->validate(gsurf->native,
71 gbuf->native_atts, gbuf->num_atts,
72 NULL,
73 &gsurf->base.Width, &gsurf->base.Height);
74 /* validate only when the geometry changed */
75 if (gsurf->base.Width == cur_w && gsurf->base.Height == cur_h)
76 continue;
77 }
78
79 gsurf->native->validate(gsurf->native,
80 gbuf->native_atts, gbuf->num_atts,
81 (struct pipe_texture **) textures,
82 &gsurf->base.Width, &gsurf->base.Height);
83 for (i = 0; i < gbuf->num_atts; i++) {
84 struct pipe_texture *pt = textures[i];
85 struct pipe_surface *ps;
86
87 if (pt) {
88 ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
89 PIPE_BUFFER_USAGE_GPU_READ |
90 PIPE_BUFFER_USAGE_GPU_WRITE);
91 gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
92 gbuf->st_atts[i], ps);
93
94 if (gbuf->native_atts[i] == gsurf->render_att)
95 pipe_surface_reference(&gsurf->render_surface, ps);
96
97 pipe_surface_reference(&ps, NULL);
98 pipe_texture_reference(&pt, NULL);
99 }
100 }
101
102 gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
103 gsurf->base.Width, gsurf->base.Height);
104 }
105
106 gctx->force_validate = EGL_FALSE;
107
108 }
109
110 /**
111 * Create a st_framebuffer.
112 */
113 static struct st_framebuffer *
114 create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
115 {
116 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
117 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
118 struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
119
120 return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
121 gconf->native->color_format, gconf->native->depth_format,
122 gconf->native->stencil_format,
123 gsurf->base.Width, gsurf->base.Height, &gsurf->base);
124 }
125
126 /**
127 * Update the attachments of draw/read surfaces.
128 */
129 static void
130 egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
131 {
132 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
133 const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
134 ST_SURFACE_FRONT_LEFT,
135 ST_SURFACE_BACK_LEFT,
136 ST_SURFACE_FRONT_RIGHT,
137 ST_SURFACE_BACK_RIGHT,
138 };
139 EGLint s, i;
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->native_atts[0] = gsurf->render_att;
156 gbuf->num_atts = 1;
157
158 for (i = 0; i < gbuf->num_atts; i++)
159 gbuf->st_atts[i] = st_att_map[gbuf->native_atts[i]];
160
161 /* FIXME OpenGL defaults to draw the front or back buffer when the
162 * context is single-buffered or double-buffered respectively. In EGL,
163 * however, the buffer to be drawn is determined by the surface, instead
164 * of the context. As a result, rendering to a pixmap surface with a
165 * double-buffered context does not work as expected.
166 *
167 * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
168 * NATIVE_ATTACHMENT_FRONT_LEFT);
169 */
170
171 /*
172 * FIXME If the back buffer is asked for here, and the front buffer is
173 * later needed by the client API (e.g. glDrawBuffer is called to draw
174 * the front buffer), it will create a new pipe texture and draw there.
175 * One fix is to ask for both buffers here, but it would be a waste if
176 * the front buffer is never used. A better fix is to add a callback to
177 * the pipe screen with context private (just like flush_frontbuffer).
178 */
179 }
180 }
181
182 /**
183 * Reallocate the context's framebuffers after draw/read surfaces change.
184 */
185 static EGLBoolean
186 egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
187 {
188 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
189 struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
190 struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
191
192 /* unreference the old framebuffers */
193 if (gctx->draw.st_fb) {
194 EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
195 void *priv;
196
197 priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
198 if (!gdraw || priv != (void *) &gdraw->base) {
199 gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
200 gctx->draw.st_fb = NULL;
201 gctx->draw.num_atts = 0;
202 }
203
204 if (is_equal) {
205 gctx->read.st_fb = NULL;
206 gctx->draw.num_atts = 0;
207 }
208 else {
209 priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
210 if (!gread || priv != (void *) &gread->base) {
211 gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
212 gctx->read.st_fb = NULL;
213 gctx->draw.num_atts = 0;
214 }
215 }
216 }
217
218 if (!gdraw)
219 return EGL_TRUE;
220
221 /* create the draw fb */
222 if (!gctx->draw.st_fb) {
223 gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
224 if (!gctx->draw.st_fb)
225 return EGL_FALSE;
226 }
227
228 /* create the read fb */
229 if (!gctx->read.st_fb) {
230 if (gread != gdraw) {
231 gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
232 if (!gctx->read.st_fb) {
233 gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
234 gctx->draw.st_fb = NULL;
235 return EGL_FALSE;
236 }
237 }
238 else {
239 /* there is no st_reference_framebuffer... */
240 gctx->read.st_fb = gctx->draw.st_fb;
241 }
242 }
243
244 egl_g3d_route_context(dpy, &gctx->base);
245 gctx->force_validate = EGL_TRUE;
246
247 return EGL_TRUE;
248 }
249
250 /**
251 * Return the current context of the given API.
252 */
253 static struct egl_g3d_context *
254 egl_g3d_get_current_context(EGLint api)
255 {
256 _EGLThreadInfo *t = _eglGetCurrentThread();
257 EGLint api_index = _eglConvertApiToIndex(api);
258 return egl_g3d_context(t->CurrentContexts[api_index]);
259 }
260
261 /**
262 * Return the state tracker for the given context.
263 */
264 static const struct egl_g3d_st *
265 egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
266 {
267 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
268 const struct egl_g3d_st *stapi;
269 EGLint idx = -1;
270
271 switch (ctx->ClientAPI) {
272 case EGL_OPENGL_ES_API:
273 switch (ctx->ClientVersion) {
274 case 1:
275 idx = EGL_G3D_ST_OPENGL_ES;
276 break;
277 case 2:
278 idx = EGL_G3D_ST_OPENGL_ES2;
279 break;
280 default:
281 _eglLog(_EGL_WARNING, "unknown client version %d",
282 ctx->ClientVersion);
283 break;
284 }
285 break;
286 case EGL_OPENVG_API:
287 idx = EGL_G3D_ST_OPENVG;
288 break;
289 case EGL_OPENGL_API:
290 idx = EGL_G3D_ST_OPENGL;
291 break;
292 default:
293 _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
294 break;
295 }
296
297 stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
298 return stapi;
299 }
300
301 /**
302 * Return an API mask that consists of the state trackers that supports the
303 * given mode.
304 *
305 * FIXME add st_is_mode_supported()?
306 */
307 static EGLint
308 get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask)
309 {
310 EGLint check;
311
312 /* OpenGL ES 1.x and 2.x are checked together */
313 check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
314 if (api_mask & check) {
315 /* this is required by EGL, not by OpenGL ES */
316 if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode)
317 api_mask &= ~check;
318 }
319
320 check = EGL_OPENVG_BIT;
321 if (api_mask & check) {
322 /* vega st needs the depth/stencil rb */
323 if (!mode->depthBits && !mode->stencilBits)
324 api_mask &= ~check;
325 }
326
327 return api_mask;
328 }
329
330 #ifdef EGL_MESA_screen_surface
331
332 static void
333 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
334 {
335 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
336 const struct native_connector **native_connectors;
337 EGLint num_connectors, i;
338
339 native_connectors =
340 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
341 if (!num_connectors) {
342 if (native_connectors)
343 free(native_connectors);
344 return;
345 }
346
347 for (i = 0; i < num_connectors; i++) {
348 const struct native_connector *nconn = native_connectors[i];
349 struct egl_g3d_screen *gscr;
350 const struct native_mode **native_modes;
351 EGLint num_modes, j;
352
353 /* TODO support for hotplug */
354 native_modes =
355 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
356 if (!num_modes) {
357 if (native_modes)
358 free(native_modes);
359 continue;
360 }
361
362 gscr = CALLOC_STRUCT(egl_g3d_screen);
363 if (!gscr) {
364 free(native_modes);
365 continue;
366 }
367
368 _eglInitScreen(&gscr->base);
369
370 for (j = 0; j < num_modes; j++) {
371 const struct native_mode *nmode = native_modes[j];
372 _EGLMode *mode;
373
374 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
375 nmode->refresh_rate, nmode->desc);
376 if (!mode)
377 break;
378 /* gscr->native_modes and gscr->base.Modes should be consistent */
379 assert(mode == &gscr->base.Modes[j]);
380 }
381
382 gscr->native = nconn;
383 gscr->native_modes = native_modes;
384
385 _eglAddScreen(dpy, &gscr->base);
386 }
387
388 free(native_connectors);
389 }
390
391 #endif /* EGL_MESA_screen_surface */
392
393 /**
394 * Add configs to display and return the next config ID.
395 */
396 static EGLint
397 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
398 {
399 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
400 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
401 const struct native_config **native_configs;
402 int num_configs, i;
403
404 native_configs = gdpy->native->get_configs(gdpy->native,
405 &num_configs);
406 if (!num_configs) {
407 if (native_configs)
408 free(native_configs);
409 return id;
410 }
411
412 for (i = 0; i < num_configs; i++) {
413 EGLint api_mask;
414 struct egl_g3d_config *gconf;
415 EGLBoolean valid;
416
417 api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask);
418 if (!api_mask) {
419 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
420 native_configs[i]->mode.visualID);
421 continue;
422 }
423
424 gconf = CALLOC_STRUCT(egl_g3d_config);
425 if (!gconf)
426 continue;
427
428 _eglInitConfig(&gconf->base, id);
429 valid = _eglConfigFromContextModesRec(&gconf->base,
430 &native_configs[i]->mode, api_mask, api_mask);
431 if (valid) {
432 #ifdef EGL_MESA_screen_surface
433 /* check if scanout surface bit is set */
434 if (native_configs[i]->scanout_bit) {
435 EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE);
436 val |= EGL_SCREEN_BIT_MESA;
437 SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val);
438 }
439 #endif
440 valid = _eglValidateConfig(&gconf->base, EGL_FALSE);
441 }
442 if (!valid) {
443 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x",
444 native_configs[i]->mode.visualID);
445 free(gconf);
446 continue;
447 }
448
449 gconf->native = native_configs[i];
450 _eglAddConfig(dpy, &gconf->base);
451 id++;
452 }
453
454 free(native_configs);
455 return id;
456 }
457
458 /**
459 * Flush the front buffer of the context's draw surface.
460 */
461 static void
462 egl_g3d_flush_frontbuffer(void *dummy, struct pipe_surface *surf,
463 void *context_private)
464 {
465 struct egl_g3d_context *gctx = egl_g3d_context(context_private);
466 struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface);
467
468 if (gsurf) {
469 gsurf->native->flush_frontbuffer(gsurf->native);
470 egl_g3d_validate_context(gctx->base.Display, &gctx->base);
471 }
472 }
473
474 static EGLBoolean
475 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
476 {
477 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
478 EGLint i;
479
480 _eglReleaseDisplayResources(drv, dpy);
481 _eglCleanupDisplay(dpy);
482
483 if (dpy->Screens) {
484 for (i = 0; i < dpy->NumScreens; i++) {
485 struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
486 free(gscr->native_modes);
487 free(gscr);
488 }
489 free(dpy->Screens);
490 }
491
492 if (gdpy->native)
493 gdpy->native->destroy(gdpy->native);
494
495 free(gdpy);
496 dpy->DriverData = NULL;
497
498 return EGL_TRUE;
499 }
500
501 static EGLBoolean
502 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
503 EGLint *major, EGLint *minor)
504 {
505 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
506 struct egl_g3d_display *gdpy;
507
508 gdpy = CALLOC_STRUCT(egl_g3d_display);
509 if (!gdpy) {
510 _eglError(EGL_BAD_ALLOC, "eglInitialize");
511 goto fail;
512 }
513 dpy->DriverData = gdpy;
514
515 gdpy->native =
516 native_create_display(dpy->NativeDisplay, egl_g3d_flush_frontbuffer);
517 if (!gdpy->native) {
518 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
519 goto fail;
520 }
521
522 dpy->ClientAPIsMask = gdrv->api_mask;
523
524 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
525 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
526 goto fail;
527 }
528
529 #ifdef EGL_MESA_screen_surface
530 /* enable MESA_screen_surface */
531 if (gdpy->native->modeset) {
532 dpy->Extensions.MESA_screen_surface = EGL_TRUE;
533 egl_g3d_add_screens(drv, dpy);
534 }
535 #endif
536
537 *major = 1;
538 *minor = 4;
539
540 return EGL_TRUE;
541
542 fail:
543 if (gdpy)
544 egl_g3d_terminate(drv, dpy);
545 return EGL_FALSE;
546 }
547
548 static _EGLContext *
549 egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
550 _EGLContext *share, const EGLint *attribs)
551 {
552 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
553 struct egl_g3d_context *xshare = egl_g3d_context(share);
554 struct egl_g3d_config *gconf = egl_g3d_config(conf);
555 struct egl_g3d_context *gctx;
556 const __GLcontextModes *mode;
557
558 gctx = CALLOC_STRUCT(egl_g3d_context);
559 if (!gctx) {
560 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
561 return NULL;
562 }
563
564 if (!_eglInitContext(drv, &gctx->base, conf, attribs)) {
565 free(gctx);
566 return NULL;
567 }
568
569 gctx->stapi = egl_g3d_choose_st(drv, &gctx->base);
570 if (!gctx->stapi) {
571 free(gctx);
572 return NULL;
573 }
574
575 mode = &gconf->native->mode;
576 gctx->pipe =
577 gdpy->native->create_context(gdpy->native, (void *) &gctx->base);
578 gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
579 (xshare) ? xshare->st_ctx : NULL);
580
581 return &gctx->base;
582 }
583
584 static EGLBoolean
585 egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
586 {
587 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
588
589 if (_eglIsContextBound(&gctx->base))
590 return EGL_TRUE;
591
592 egl_g3d_realloc_context(dpy, &gctx->base);
593
594 /* it will destroy pipe context */
595 gctx->stapi->st_destroy_context(gctx->st_ctx);
596
597 free(gctx);
598
599 return EGL_TRUE;
600 }
601
602 static _EGLSurface *
603 egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
604 _EGLConfig *conf, EGLNativeWindowType win,
605 const EGLint *attribs)
606 {
607 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
608 struct egl_g3d_config *gconf = egl_g3d_config(conf);
609 struct egl_g3d_surface *gsurf;
610
611 gsurf = CALLOC_STRUCT(egl_g3d_surface);
612 if (!gsurf) {
613 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
614 return NULL;
615 }
616
617 if (!_eglInitSurface(drv, &gsurf->base, EGL_WINDOW_BIT, conf, attribs)) {
618 free(gsurf);
619 return NULL;
620 }
621
622 gsurf->native =
623 gdpy->native->create_window_surface(gdpy->native, win, gconf->native);
624 if (!gsurf->native) {
625 free(gsurf);
626 return NULL;
627 }
628
629 if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL,
630 &gsurf->base.Width, &gsurf->base.Height)) {
631 gsurf->native->destroy(gsurf->native);
632 free(gsurf);
633 return NULL;
634 }
635
636 gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
637 !gconf->native->mode.doubleBufferMode) ?
638 NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
639
640 return &gsurf->base;
641 }
642
643 static _EGLSurface *
644 egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
645 _EGLConfig *conf, EGLNativePixmapType pix,
646 const EGLint *attribs)
647 {
648 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
649 struct egl_g3d_config *gconf = egl_g3d_config(conf);
650 struct egl_g3d_surface *gsurf;
651
652 gsurf = CALLOC_STRUCT(egl_g3d_surface);
653 if (!gsurf) {
654 _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
655 return NULL;
656 }
657
658 if (!_eglInitSurface(drv, &gsurf->base, EGL_PIXMAP_BIT, conf, attribs)) {
659 free(gsurf);
660 return NULL;
661 }
662
663 gsurf->native =
664 gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native);
665 if (!gsurf->native) {
666 free(gsurf);
667 return NULL;
668 }
669
670 if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL,
671 &gsurf->base.Width, &gsurf->base.Height)) {
672 gsurf->native->destroy(gsurf->native);
673 free(gsurf);
674 return NULL;
675 }
676
677 gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
678
679 return &gsurf->base;
680 }
681
682 static _EGLSurface *
683 egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
684 _EGLConfig *conf, const EGLint *attribs)
685 {
686 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
687 struct egl_g3d_config *gconf = egl_g3d_config(conf);
688 struct egl_g3d_surface *gsurf;
689
690 gsurf = CALLOC_STRUCT(egl_g3d_surface);
691 if (!gsurf) {
692 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
693 return NULL;
694 }
695
696 if (!_eglInitSurface(drv, &gsurf->base, EGL_PBUFFER_BIT, conf, attribs)) {
697 free(gsurf);
698 return NULL;
699 }
700
701 gsurf->native =
702 gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native,
703 gsurf->base.Width, gsurf->base.Height);
704 if (!gsurf->native) {
705 free(gsurf);
706 return NULL;
707 }
708
709 gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
710 NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
711
712 return &gsurf->base;
713 }
714
715 static EGLBoolean
716 egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
717 {
718 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
719
720 if (_eglIsSurfaceBound(&gsurf->base))
721 return EGL_TRUE;
722
723 pipe_surface_reference(&gsurf->render_surface, NULL);
724 gsurf->native->destroy(gsurf->native);
725 free(gsurf);
726 return EGL_TRUE;
727 }
728
729 static EGLBoolean
730 egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
731 _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
732 {
733 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
734 struct egl_g3d_context *old_gctx;
735 EGLint api;
736 EGLBoolean ok = EGL_TRUE;
737
738 /* find the old context */
739 api = (gctx) ? gctx->base.ClientAPI : eglQueryAPI();
740 old_gctx = egl_g3d_get_current_context(api);
741 if (old_gctx && !_eglIsContextLinked(&old_gctx->base))
742 old_gctx = NULL;
743
744 if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
745 return EGL_FALSE;
746
747 if (old_gctx) {
748 /* flush old context */
749 old_gctx->stapi->st_flush(old_gctx->st_ctx,
750 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
751
752 /*
753 * The old context is no longer current, and egl_g3d_realloc_context()
754 * should be called to destroy the framebuffers. However, it is possible
755 * that it will be made current again with the same draw/read surfaces.
756 * It might be better to keep it around.
757 */
758 }
759
760 if (gctx) {
761 struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
762
763 ok = egl_g3d_realloc_context(dpy, &gctx->base);
764 if (ok) {
765 ok = gctx->stapi->st_make_current(gctx->st_ctx,
766 gctx->draw.st_fb, gctx->read.st_fb);
767 if (ok) {
768 egl_g3d_validate_context(dpy, &gctx->base);
769 if (gdraw->base.Type == EGL_WINDOW_BIT) {
770 gctx->base.WindowRenderBuffer =
771 (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
772 EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
773 }
774 }
775 }
776 }
777 else if (old_gctx) {
778 ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
779 old_gctx->base.WindowRenderBuffer = EGL_NONE;
780 }
781
782 return ok;
783 }
784
785 static EGLBoolean
786 egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
787 {
788 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
789 _EGLContext *ctx = _eglGetCurrentContext();
790 struct egl_g3d_context *gctx = NULL;
791
792 /* no-op for pixmap or pbuffer surface */
793 if (gsurf->base.Type == EGL_PIXMAP_BIT ||
794 gsurf->base.Type == EGL_PBUFFER_BIT)
795 return EGL_TRUE;
796
797 /* or when the surface is single-buffered */
798 if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
799 return EGL_TRUE;
800
801 if (ctx && ctx->DrawSurface == surf)
802 gctx = egl_g3d_context(ctx);
803
804 /* flush if the surface is current */
805 if (gctx)
806 gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
807
808 /*
809 * We drew on the back buffer, unless there was no back buffer.
810 * In that case, we drew on the front buffer. Either case, we call
811 * swap_buffers.
812 */
813 if (!gsurf->native->swap_buffers(gsurf->native))
814 return EGL_FALSE;
815
816 if (gctx) {
817 struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
818
819 /* force validation if the swap method is not copy */
820 if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML)
821 gctx->force_validate = EGL_TRUE;
822 egl_g3d_validate_context(dpy, &gctx->base);
823 }
824
825 return EGL_TRUE;
826 }
827
828 static EGLBoolean
829 egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
830 {
831 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
832 gctx->stapi->st_finish(gctx->st_ctx);
833 return EGL_TRUE;
834 }
835
836 static EGLBoolean
837 egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
838 {
839 _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
840 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
841
842 if (engine != EGL_CORE_NATIVE_ENGINE)
843 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
844
845 if (gsurf)
846 gsurf->native->wait(gsurf->native);
847
848 return EGL_TRUE;
849 }
850
851 static _EGLProc
852 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
853 {
854 /* FIXME how come _EGLDriver is not passed? */
855 const struct egl_g3d_st *stapi;
856 _EGLProc proc;
857 EGLint i;
858
859 for (i = 0; i < NUM_EGL_G3D_STS; i++) {
860 stapi = egl_g3d_get_st(i);
861 if (stapi) {
862 proc = (_EGLProc) stapi->st_get_proc_address(procname);
863 if (proc)
864 return proc;
865 }
866 }
867
868 return (_EGLProc) NULL;
869 }
870
871 static EGLBoolean
872 egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
873 _EGLSurface *surf, EGLint buffer)
874 {
875 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
876 struct egl_g3d_context *gctx;
877 enum pipe_format target_format;
878 int target;
879
880 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
881 return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
882 if (buffer != EGL_BACK_BUFFER)
883 return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
884 if (gsurf->base.BoundToTexture)
885 return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
886
887 switch (gsurf->base.TextureFormat) {
888 case EGL_TEXTURE_RGB:
889 target_format = PIPE_FORMAT_R8G8B8_UNORM;
890 break;
891 case EGL_TEXTURE_RGBA:
892 target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
893 break;
894 default:
895 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
896 }
897
898 switch (gsurf->base.TextureTarget) {
899 case EGL_TEXTURE_2D:
900 target = ST_TEXTURE_2D;
901 break;
902 default:
903 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
904 }
905
906 /* flush properly if the surface is bound */
907 if (gsurf->base.Binding) {
908 gctx = egl_g3d_context(gsurf->base.Binding);
909 gctx->stapi->st_flush(gctx->st_ctx,
910 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
911 }
912
913 /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
914 gctx = egl_g3d_get_current_context(EGL_OPENGL_API);
915 if (gctx) {
916 if (!gsurf->render_surface)
917 return EGL_FALSE;
918
919 gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
920 target, gsurf->base.MipmapLevel, target_format);
921 gsurf->base.BoundToTexture = EGL_TRUE;
922 }
923
924 return EGL_TRUE;
925 }
926
927 static EGLBoolean
928 egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
929 _EGLSurface *surf, EGLint buffer)
930 {
931 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
932
933 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
934 !gsurf->base.BoundToTexture)
935 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
936 if (buffer != EGL_BACK_BUFFER)
937 return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
938
939 if (gsurf->render_surface) {
940 _EGLThreadInfo *t = _eglGetCurrentThread();
941 /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
942 struct egl_g3d_context *gctx = egl_g3d_context(
943 t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]);
944
945 /* what if the context the surface binds to is no longer current? */
946 if (gctx)
947 gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
948 ST_TEXTURE_2D, gsurf->base.MipmapLevel);
949 }
950
951 gsurf->base.BoundToTexture = EGL_FALSE;
952
953 return EGL_TRUE;
954 }
955
956 #ifdef EGL_MESA_screen_surface
957
958 static _EGLSurface *
959 egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
960 _EGLConfig *conf, const EGLint *attribs)
961 {
962 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
963 struct egl_g3d_config *gconf = egl_g3d_config(conf);
964 struct egl_g3d_surface *gsurf;
965
966 gsurf = CALLOC_STRUCT(egl_g3d_surface);
967 if (!gsurf) {
968 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
969 return NULL;
970 }
971
972 if (!_eglInitSurface(drv, &gsurf->base,
973 EGL_SCREEN_BIT_MESA, conf, attribs)) {
974 free(gsurf);
975 return NULL;
976 }
977
978 gsurf->native =
979 gdpy->native->modeset->create_scanout_surface(gdpy->native,
980 gconf->native, gsurf->base.Width, gsurf->base.Height);
981 if (!gsurf->native) {
982 free(gsurf);
983 return NULL;
984 }
985
986 gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
987 NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
988
989 return &gsurf->base;
990 }
991
992 static EGLBoolean
993 egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
994 _EGLScreen *scr, _EGLSurface *surf,
995 _EGLMode *mode)
996 {
997 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
998 struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
999 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
1000 struct native_surface *nsurf;
1001 const struct native_mode *nmode;
1002 EGLBoolean changed;
1003
1004 if (gsurf) {
1005 EGLint idx;
1006
1007 if (!mode)
1008 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
1009 if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
1010 return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
1011 if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
1012 return _eglError(EGL_BAD_MATCH,
1013 "eglShowSurfaceMESA(surface smaller than mode size)");
1014
1015 /* find the index of the mode */
1016 for (idx = 0; idx < gscr->base.NumModes; idx++)
1017 if (mode == &gscr->base.Modes[idx])
1018 break;
1019 if (idx >= gscr->base.NumModes) {
1020 return _eglError(EGL_BAD_MODE_MESA,
1021 "eglShowSurfaceMESA(unknown mode)");
1022 }
1023
1024 nsurf = gsurf->native;
1025 nmode = gscr->native_modes[idx];
1026 }
1027 else {
1028 if (mode)
1029 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
1030
1031 /* disable the screen */
1032 nsurf = NULL;
1033 nmode = NULL;
1034 }
1035
1036 /* TODO surface panning by CRTC choosing */
1037 changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
1038 gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
1039 if (changed) {
1040 gscr->base.CurrentSurface = &gsurf->base;
1041 gscr->base.CurrentMode = mode;
1042 }
1043
1044 return changed;
1045 }
1046
1047 #endif /* EGL_MESA_screen_surface */
1048
1049 static void
1050 egl_g3d_unload(_EGLDriver *drv)
1051 {
1052 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
1053 free(gdrv);
1054 }
1055
1056 _EGLDriver *
1057 _eglMain(const char *args)
1058 {
1059 static char driver_name[64];
1060 struct egl_g3d_driver *gdrv;
1061 EGLint i;
1062
1063 snprintf(driver_name, sizeof(driver_name),
1064 "Gallium/%s", native_get_name());
1065
1066 gdrv = CALLOC_STRUCT(egl_g3d_driver);
1067 if (!gdrv)
1068 return NULL;
1069
1070 _eglInitDriverFallbacks(&gdrv->base);
1071
1072 gdrv->base.API.Initialize = egl_g3d_initialize;
1073 gdrv->base.API.Terminate = egl_g3d_terminate;
1074 gdrv->base.API.CreateContext = egl_g3d_create_context;
1075 gdrv->base.API.DestroyContext = egl_g3d_destroy_context;
1076 gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface;
1077 gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
1078 gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
1079 gdrv->base.API.DestroySurface = egl_g3d_destroy_surface;
1080 gdrv->base.API.MakeCurrent = egl_g3d_make_current;
1081 gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers;
1082 gdrv->base.API.WaitClient = egl_g3d_wait_client;
1083 gdrv->base.API.WaitNative = egl_g3d_wait_native;
1084 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
1085
1086 gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image;
1087 gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image;
1088
1089 #ifdef EGL_MESA_screen_surface
1090 gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
1091 gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
1092 #endif
1093
1094 gdrv->base.Name = driver_name;
1095 gdrv->base.Unload = egl_g3d_unload;
1096
1097 for (i = 0; i < NUM_EGL_G3D_STS; i++) {
1098 gdrv->stapis[i] = egl_g3d_get_st(i);
1099 if (gdrv->stapis[i])
1100 gdrv->api_mask |= gdrv->stapis[i]->api_bit;
1101 }
1102
1103 if (gdrv->api_mask)
1104 _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
1105 else
1106 _eglLog(_EGL_WARNING, "No supported client API");
1107
1108 return &gdrv->base;
1109 }