egl: remove #ifdef's for official extensions
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
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 OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "egldriver.h"
27 #include "eglcurrent.h"
28 #include "egllog.h"
29
30 #include "pipe/p_screen.h"
31 #include "util/u_memory.h"
32 #include "util/u_inlines.h"
33 #include "util/u_box.h"
34
35 #include "egl_g3d.h"
36 #include "egl_g3d_api.h"
37 #include "egl_g3d_image.h"
38 #include "egl_g3d_sync.h"
39 #include "egl_g3d_st.h"
40 #include "native.h"
41
42 /**
43 * Return the state tracker for the given context.
44 */
45 static struct st_api *
46 egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx,
47 enum st_profile_type *profile)
48 {
49 struct st_api *stapi;
50 EGLint api = -1;
51
52 *profile = ST_PROFILE_DEFAULT;
53
54 switch (ctx->ClientAPI) {
55 case EGL_OPENGL_ES_API:
56 switch (ctx->ClientVersion) {
57 case 1:
58 api = ST_API_OPENGL;
59 *profile = ST_PROFILE_OPENGL_ES1;
60 break;
61 case 2:
62 api = ST_API_OPENGL;
63 *profile = ST_PROFILE_OPENGL_ES2;
64 break;
65 default:
66 _eglLog(_EGL_WARNING, "unknown client version %d",
67 ctx->ClientVersion);
68 break;
69 }
70 break;
71 case EGL_OPENVG_API:
72 api = ST_API_OPENVG;
73 break;
74 case EGL_OPENGL_API:
75 api = ST_API_OPENGL;
76 break;
77 default:
78 _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
79 break;
80 }
81
82 stapi = egl_g3d_get_st_api(drv, api);
83 if (stapi && !(stapi->profile_mask & (1 << *profile)))
84 stapi = NULL;
85
86 return stapi;
87 }
88
89 struct egl_g3d_choose_config_data {
90 _EGLConfig criteria;
91 enum pipe_format format;
92 };
93
94 static int
95 egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2,
96 void *priv_data)
97 {
98 struct egl_g3d_choose_config_data *data =
99 (struct egl_g3d_choose_config_data *) priv_data;
100 const _EGLConfig *criteria = &data->criteria;;
101
102 /* EGL_NATIVE_VISUAL_TYPE ignored? */
103 return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE);
104 }
105
106 static EGLBoolean
107 egl_g3d_match_config(const _EGLConfig *conf, void *priv_data)
108 {
109 struct egl_g3d_choose_config_data *data =
110 (struct egl_g3d_choose_config_data *) priv_data;
111 struct egl_g3d_config *gconf = egl_g3d_config(conf);
112
113 if (data->format != PIPE_FORMAT_NONE &&
114 data->format != gconf->native->color_format)
115 return EGL_FALSE;
116
117 return _eglMatchConfig(conf, &data->criteria);
118 }
119
120 static EGLBoolean
121 egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs,
122 EGLConfig *configs, EGLint size, EGLint *num_configs)
123 {
124 struct egl_g3d_choose_config_data data;
125
126 if (!_eglParseConfigAttribList(&data.criteria, dpy, attribs))
127 return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
128
129 data.format = PIPE_FORMAT_NONE;
130 if (data.criteria.MatchNativePixmap != EGL_NONE &&
131 data.criteria.MatchNativePixmap != EGL_DONT_CARE) {
132 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
133
134 if (!gdpy->native->get_pixmap_format(gdpy->native,
135 (EGLNativePixmapType) data.criteria.MatchNativePixmap,
136 &data.format))
137 return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglChooseConfig");
138 }
139
140 return _eglFilterConfigArray(dpy->Configs, configs, size, num_configs,
141 egl_g3d_match_config, egl_g3d_compare_config, &data);
142 }
143
144 static _EGLContext *
145 egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
146 _EGLContext *share, const EGLint *attribs)
147 {
148 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
149 struct egl_g3d_context *gshare = egl_g3d_context(share);
150 struct egl_g3d_config *gconf = egl_g3d_config(conf);
151 struct egl_g3d_context *gctx;
152 struct st_context_attribs stattribs;
153
154 gctx = CALLOC_STRUCT(egl_g3d_context);
155 if (!gctx) {
156 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
157 return NULL;
158 }
159
160 if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) {
161 FREE(gctx);
162 return NULL;
163 }
164
165 memset(&stattribs, 0, sizeof(stattribs));
166 if (gconf)
167 stattribs.visual = gconf->stvis;
168
169 gctx->stapi = egl_g3d_choose_st(drv, &gctx->base, &stattribs.profile);
170 if (!gctx->stapi) {
171 FREE(gctx);
172 return NULL;
173 }
174
175 gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
176 &stattribs, (gshare) ? gshare->stctxi : NULL);
177 if (!gctx->stctxi) {
178 FREE(gctx);
179 return NULL;
180 }
181
182 gctx->stctxi->st_manager_private = (void *) &gctx->base;
183
184 return &gctx->base;
185 }
186
187 /**
188 * Destroy a context.
189 */
190 static void
191 destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
192 {
193 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
194
195 /* FIXME a context might live longer than its display */
196 if (!dpy->Initialized)
197 _eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
198
199 gctx->stctxi->destroy(gctx->stctxi);
200
201 FREE(gctx);
202 }
203
204 static EGLBoolean
205 egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
206 {
207 if (_eglPutContext(ctx))
208 destroy_context(dpy, ctx);
209 return EGL_TRUE;
210 }
211
212 struct egl_g3d_create_surface_arg {
213 EGLint type;
214 union {
215 EGLNativeWindowType win;
216 EGLNativePixmapType pix;
217 } u;
218 };
219
220 static _EGLSurface *
221 egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
222 struct egl_g3d_create_surface_arg *arg,
223 const EGLint *attribs)
224 {
225 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
226 struct egl_g3d_config *gconf = egl_g3d_config(conf);
227 struct egl_g3d_surface *gsurf;
228 struct native_surface *nsurf;
229 const char *err;
230
231 switch (arg->type) {
232 case EGL_WINDOW_BIT:
233 err = "eglCreateWindowSurface";
234 break;
235 case EGL_PIXMAP_BIT:
236 err = "eglCreatePixmapSurface";
237 break;
238 #ifdef EGL_MESA_screen_surface
239 case EGL_SCREEN_BIT_MESA:
240 err = "eglCreateScreenSurface";
241 break;
242 #endif
243 default:
244 err = "eglCreateUnknownSurface";
245 break;
246 }
247
248 gsurf = CALLOC_STRUCT(egl_g3d_surface);
249 if (!gsurf) {
250 _eglError(EGL_BAD_ALLOC, err);
251 return NULL;
252 }
253
254 if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) {
255 FREE(gsurf);
256 return NULL;
257 }
258
259 /* create the native surface */
260 switch (arg->type) {
261 case EGL_WINDOW_BIT:
262 nsurf = gdpy->native->create_window_surface(gdpy->native,
263 arg->u.win, gconf->native);
264 break;
265 case EGL_PIXMAP_BIT:
266 nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
267 arg->u.pix, gconf->native);
268 break;
269 #ifdef EGL_MESA_screen_surface
270 case EGL_SCREEN_BIT_MESA:
271 /* prefer back buffer (move to _eglInitSurface?) */
272 gsurf->base.RenderBuffer = EGL_BACK_BUFFER;
273 nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native,
274 gconf->native, gsurf->base.Width, gsurf->base.Height);
275 break;
276 #endif
277 default:
278 nsurf = NULL;
279 break;
280 }
281
282 if (!nsurf) {
283 FREE(gsurf);
284 return NULL;
285 }
286 /* initialize the geometry */
287 if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL,
288 &gsurf->base.Width, &gsurf->base.Height)) {
289 nsurf->destroy(nsurf);
290 FREE(gsurf);
291 return NULL;
292 }
293
294 gsurf->stvis = gconf->stvis;
295 if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER &&
296 gconf->stvis.buffer_mask & ST_ATTACHMENT_FRONT_LEFT_MASK)
297 gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT;
298
299 gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
300 if (!gsurf->stfbi) {
301 nsurf->destroy(nsurf);
302 FREE(gsurf);
303 return NULL;
304 }
305
306 nsurf->user_data = &gsurf->base;
307 gsurf->native = nsurf;
308
309 return &gsurf->base;
310 }
311
312 static _EGLSurface *
313 egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
314 _EGLConfig *conf, EGLNativeWindowType win,
315 const EGLint *attribs)
316 {
317 struct egl_g3d_create_surface_arg arg;
318
319 memset(&arg, 0, sizeof(arg));
320 arg.type = EGL_WINDOW_BIT;
321 arg.u.win = win;
322
323 return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
324 }
325
326 static _EGLSurface *
327 egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
328 _EGLConfig *conf, EGLNativePixmapType pix,
329 const EGLint *attribs)
330 {
331 struct egl_g3d_create_surface_arg arg;
332
333 memset(&arg, 0, sizeof(arg));
334 arg.type = EGL_PIXMAP_BIT;
335 arg.u.pix = pix;
336
337 return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
338 }
339
340 static struct egl_g3d_surface *
341 create_pbuffer_surface(_EGLDisplay *dpy, _EGLConfig *conf,
342 const EGLint *attribs, const char *func)
343 {
344 struct egl_g3d_config *gconf = egl_g3d_config(conf);
345 struct egl_g3d_surface *gsurf;
346
347 gsurf = CALLOC_STRUCT(egl_g3d_surface);
348 if (!gsurf) {
349 _eglError(EGL_BAD_ALLOC, func);
350 return NULL;
351 }
352
353 if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) {
354 FREE(gsurf);
355 return NULL;
356 }
357
358 gsurf->stvis = gconf->stvis;
359
360 gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
361 if (!gsurf->stfbi) {
362 FREE(gsurf);
363 return NULL;
364 }
365
366 return gsurf;
367 }
368
369 static _EGLSurface *
370 egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
371 _EGLConfig *conf, const EGLint *attribs)
372 {
373 struct egl_g3d_surface *gsurf;
374
375 gsurf = create_pbuffer_surface(dpy, conf, attribs,
376 "eglCreatePbufferSurface");
377 if (!gsurf)
378 return NULL;
379
380 gsurf->client_buffer_type = EGL_NONE;
381
382 return &gsurf->base;
383 }
384
385 static _EGLSurface *
386 egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver *drv, _EGLDisplay *dpy,
387 EGLenum buftype,
388 EGLClientBuffer buffer,
389 _EGLConfig *conf,
390 const EGLint *attribs)
391 {
392 struct egl_g3d_surface *gsurf;
393 struct pipe_resource *ptex = NULL;
394 EGLint pbuffer_attribs[32];
395 EGLint count, i;
396
397 switch (buftype) {
398 case EGL_OPENVG_IMAGE:
399 break;
400 default:
401 _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
402 return NULL;
403 break;
404 }
405
406 /* parse the attributes first */
407 count = 0;
408 for (i = 0; attribs && attribs[i] != EGL_NONE; i++) {
409 EGLint attr = attribs[i++];
410 EGLint val = attribs[i];
411 EGLint err = EGL_SUCCESS;
412
413 switch (attr) {
414 case EGL_TEXTURE_FORMAT:
415 case EGL_TEXTURE_TARGET:
416 case EGL_MIPMAP_TEXTURE:
417 pbuffer_attribs[count++] = attr;
418 pbuffer_attribs[count++] = val;
419 break;
420 default:
421 err = EGL_BAD_ATTRIBUTE;
422 break;
423 }
424 /* bail out */
425 if (err != EGL_SUCCESS) {
426 _eglError(err, "eglCreatePbufferFromClientBuffer");
427 return NULL;
428 }
429 }
430
431 pbuffer_attribs[count++] = EGL_NONE;
432
433 gsurf = create_pbuffer_surface(dpy, conf, pbuffer_attribs,
434 "eglCreatePbufferFromClientBuffer");
435 if (!gsurf)
436 return NULL;
437
438 gsurf->client_buffer_type = buftype;
439 gsurf->client_buffer = buffer;
440
441 /* validate now so that it fails if the client buffer is invalid */
442 if (!gsurf->stfbi->validate(gsurf->stfbi,
443 &gsurf->stvis.render_buffer, 1, &ptex)) {
444 egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
445 FREE(gsurf);
446 return NULL;
447 }
448 pipe_resource_reference(&ptex, NULL);
449
450 return &gsurf->base;
451 }
452
453 /**
454 * Destroy a surface.
455 */
456 static void
457 destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
458 {
459 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
460
461 /* FIXME a surface might live longer than its display */
462 if (!dpy->Initialized)
463 _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
464
465 pipe_resource_reference(&gsurf->render_texture, NULL);
466 egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
467 if (gsurf->native)
468 gsurf->native->destroy(gsurf->native);
469 FREE(gsurf);
470 }
471
472 static EGLBoolean
473 egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
474 {
475 if (_eglPutSurface(surf))
476 destroy_surface(dpy, surf);
477 return EGL_TRUE;
478 }
479
480 static EGLBoolean
481 egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
482 _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
483 {
484 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
485 struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
486 struct egl_g3d_surface *gread = egl_g3d_surface(read);
487 struct egl_g3d_context *old_gctx;
488 _EGLContext *old_ctx;
489 _EGLSurface *old_draw, *old_read;
490 EGLBoolean ok = EGL_TRUE;
491
492 /* make new bindings */
493 if (!_eglBindContext(ctx, draw, read, &old_ctx, &old_draw, &old_read))
494 return EGL_FALSE;
495
496 old_gctx = egl_g3d_context(old_ctx);
497 if (old_gctx) {
498 /* flush old context */
499 old_gctx->stctxi->flush(old_gctx->stctxi, ST_FLUSH_FRONT, NULL);
500 }
501
502 if (gctx) {
503 ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
504 (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
505 if (ok) {
506 if (gdraw) {
507 if (gdraw->base.Type == EGL_WINDOW_BIT) {
508 gctx->base.WindowRenderBuffer =
509 (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
510 EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
511 }
512 }
513 }
514 }
515 else if (old_gctx) {
516 ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
517 if (ok)
518 old_gctx->base.WindowRenderBuffer = EGL_NONE;
519 }
520
521 if (ok) {
522 if (_eglPutContext(old_ctx))
523 destroy_context(dpy, old_ctx);
524 if (_eglPutSurface(old_draw))
525 destroy_surface(dpy, old_draw);
526 if (_eglPutSurface(old_read))
527 destroy_surface(dpy, old_read);
528 }
529 else {
530 /* undo the previous _eglBindContext */
531 _eglBindContext(old_ctx, old_draw, old_read, &ctx, &draw, &read);
532 assert(&gctx->base == ctx &&
533 &gdraw->base == draw &&
534 &gread->base == read);
535
536 _eglPutSurface(draw);
537 _eglPutSurface(read);
538 _eglPutContext(ctx);
539
540 _eglPutSurface(old_draw);
541 _eglPutSurface(old_read);
542 _eglPutContext(old_ctx);
543 }
544
545 return ok;
546 }
547
548 static EGLBoolean
549 swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
550 EGLint num_rects, const EGLint *rects, EGLBoolean preserve)
551 {
552 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
553 _EGLContext *ctx = _eglGetCurrentContext();
554 struct egl_g3d_context *gctx = NULL;
555 struct native_present_control ctrl;
556
557 /* no-op for pixmap or pbuffer surface */
558 if (gsurf->base.Type == EGL_PIXMAP_BIT ||
559 gsurf->base.Type == EGL_PBUFFER_BIT)
560 return EGL_TRUE;
561
562 /* or when the surface is single-buffered */
563 if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT)
564 return EGL_TRUE;
565
566 if (ctx && ctx->DrawSurface == surf)
567 gctx = egl_g3d_context(ctx);
568
569 /* flush if the surface is current */
570 if (gctx) {
571 gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
572 }
573
574 memset(&ctrl, 0, sizeof(ctrl));
575 ctrl.natt = NATIVE_ATTACHMENT_BACK_LEFT;
576 ctrl.preserve = preserve;
577 ctrl.swap_interval = gsurf->base.SwapInterval;
578 ctrl.premultiplied_alpha = (gsurf->base.VGAlphaFormat == EGL_VG_ALPHA_FORMAT_PRE);
579 ctrl.num_rects = num_rects;
580 ctrl.rects = rects;
581
582 return gsurf->native->present(gsurf->native, &ctrl);
583 }
584
585 static EGLBoolean
586 egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
587 {
588 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
589
590 return swap_buffers(drv, dpy, surf, 0, NULL,
591 (gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED));
592 }
593
594 #ifdef EGL_NOK_swap_region
595 static EGLBoolean
596 egl_g3d_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
597 EGLint num_rects, const EGLint *rects)
598 {
599 /* Note: y=0=top */
600 return swap_buffers(drv, dpy, surf, num_rects, rects, EGL_TRUE);
601 }
602 #endif /* EGL_NOK_swap_region */
603
604 static EGLBoolean
605 egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
606 EGLNativePixmapType target)
607 {
608 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
609 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
610 _EGLContext *ctx = _eglGetCurrentContext();
611
612 if (!gsurf->render_texture)
613 return EGL_TRUE;
614
615 /* flush if the surface is current */
616 if (ctx && ctx->DrawSurface == &gsurf->base) {
617 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
618 gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
619 }
620
621 return gdpy->native->copy_to_pixmap(gdpy->native,
622 target, gsurf->render_texture);
623 }
624
625 static EGLBoolean
626 egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
627 {
628 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
629 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
630 struct pipe_screen *screen = gdpy->native->screen;
631 struct pipe_fence_handle *fence = NULL;
632
633 gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, &fence);
634 if (fence) {
635 screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
636 screen->fence_reference(screen, &fence, NULL);
637 }
638
639 return EGL_TRUE;
640 }
641
642 static EGLBoolean
643 egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
644 {
645 _EGLContext *ctx = _eglGetCurrentContext();
646
647 if (engine != EGL_CORE_NATIVE_ENGINE)
648 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
649
650 if (ctx && ctx->DrawSurface) {
651 struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface);
652
653 if (gsurf->native)
654 gsurf->native->wait(gsurf->native);
655 }
656
657 return EGL_TRUE;
658 }
659
660 static EGLBoolean
661 egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
662 _EGLSurface *surf, EGLint buffer)
663 {
664 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
665 _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
666 struct egl_g3d_context *gctx;
667 enum pipe_format internal_format;
668 enum st_texture_type target;
669
670 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
671 return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
672 if (buffer != EGL_BACK_BUFFER)
673 return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
674 if (gsurf->base.BoundToTexture)
675 return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
676
677 switch (gsurf->base.TextureFormat) {
678 case EGL_TEXTURE_RGB:
679 internal_format = PIPE_FORMAT_R8G8B8_UNORM;
680 break;
681 case EGL_TEXTURE_RGBA:
682 internal_format = PIPE_FORMAT_B8G8R8A8_UNORM;
683 break;
684 default:
685 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
686 }
687
688 switch (gsurf->base.TextureTarget) {
689 case EGL_TEXTURE_2D:
690 target = ST_TEXTURE_2D;
691 break;
692 default:
693 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
694 }
695
696 if (!es1)
697 return EGL_TRUE;
698 if (!gsurf->render_texture)
699 return EGL_FALSE;
700
701 /* flush properly if the surface is bound */
702 if (gsurf->base.CurrentContext) {
703 gctx = egl_g3d_context(gsurf->base.CurrentContext);
704 gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
705 }
706
707 gctx = egl_g3d_context(es1);
708 if (gctx->stctxi->teximage) {
709 if (!gctx->stctxi->teximage(gctx->stctxi, target,
710 gsurf->base.MipmapLevel, internal_format,
711 gsurf->render_texture, gsurf->base.MipmapTexture))
712 return EGL_FALSE;
713 gsurf->base.BoundToTexture = EGL_TRUE;
714 }
715
716 return EGL_TRUE;
717 }
718
719 static EGLBoolean
720 egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
721 _EGLSurface *surf, EGLint buffer)
722 {
723 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
724
725 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
726 !gsurf->base.BoundToTexture)
727 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
728 if (buffer != EGL_BACK_BUFFER)
729 return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
730
731 if (gsurf->render_texture) {
732 _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
733 struct egl_g3d_context *gctx = egl_g3d_context(ctx);
734
735 /* what if the context the surface binds to is no longer current? */
736 if (gctx) {
737 gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
738 gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
739 }
740 }
741
742 gsurf->base.BoundToTexture = EGL_FALSE;
743
744 return EGL_TRUE;
745 }
746
747 #ifdef EGL_MESA_screen_surface
748
749 static _EGLSurface *
750 egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
751 _EGLConfig *conf, const EGLint *attribs)
752 {
753 struct egl_g3d_create_surface_arg arg;
754
755 memset(&arg, 0, sizeof(arg));
756 arg.type = EGL_SCREEN_BIT_MESA;
757
758 return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
759 }
760
761 static EGLBoolean
762 egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
763 _EGLScreen *scr, _EGLSurface *surf,
764 _EGLMode *mode)
765 {
766 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
767 struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
768 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
769 struct native_surface *nsurf;
770 const struct native_mode *nmode;
771 EGLBoolean changed;
772
773 if (gsurf) {
774 EGLint idx;
775
776 if (!mode)
777 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
778 if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
779 return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
780 if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
781 return _eglError(EGL_BAD_MATCH,
782 "eglShowSurfaceMESA(surface smaller than mode size)");
783
784 /* find the index of the mode */
785 for (idx = 0; idx < gscr->base.NumModes; idx++)
786 if (mode == &gscr->base.Modes[idx])
787 break;
788 if (idx >= gscr->base.NumModes) {
789 return _eglError(EGL_BAD_MODE_MESA,
790 "eglShowSurfaceMESA(unknown mode)");
791 }
792
793 nsurf = gsurf->native;
794 nmode = gscr->native_modes[idx];
795 }
796 else {
797 if (mode)
798 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
799
800 /* disable the screen */
801 nsurf = NULL;
802 nmode = NULL;
803 }
804
805 /* TODO surface panning by CRTC choosing */
806 changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
807 gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
808 if (changed) {
809 gscr->base.CurrentSurface = &gsurf->base;
810 gscr->base.CurrentMode = mode;
811 }
812
813 return changed;
814 }
815
816 #endif /* EGL_MESA_screen_surface */
817
818 #ifdef EGL_WL_bind_wayland_display
819
820 static EGLBoolean
821 egl_g3d_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy,
822 struct wl_display *wl_dpy)
823 {
824 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
825
826 if (!gdpy->native->wayland_bufmgr)
827 return EGL_FALSE;
828
829 return gdpy->native->wayland_bufmgr->bind_display(gdpy->native, wl_dpy);
830 }
831
832 static EGLBoolean
833 egl_g3d_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy,
834 struct wl_display *wl_dpy)
835 {
836 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
837
838 if (!gdpy->native->wayland_bufmgr)
839 return EGL_FALSE;
840
841 return gdpy->native->wayland_bufmgr->unbind_display(gdpy->native, wl_dpy);
842 }
843
844 #endif /* EGL_WL_bind_wayland_display */
845
846 void
847 egl_g3d_init_driver_api(_EGLDriver *drv)
848 {
849 _eglInitDriverFallbacks(drv);
850
851 drv->API.ChooseConfig = egl_g3d_choose_config;
852
853 drv->API.CreateContext = egl_g3d_create_context;
854 drv->API.DestroyContext = egl_g3d_destroy_context;
855 drv->API.CreateWindowSurface = egl_g3d_create_window_surface;
856 drv->API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
857 drv->API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
858 drv->API.CreatePbufferFromClientBuffer = egl_g3d_create_pbuffer_from_client_buffer;
859 drv->API.DestroySurface = egl_g3d_destroy_surface;
860 drv->API.MakeCurrent = egl_g3d_make_current;
861 drv->API.SwapBuffers = egl_g3d_swap_buffers;
862 drv->API.CopyBuffers = egl_g3d_copy_buffers;
863 drv->API.WaitClient = egl_g3d_wait_client;
864 drv->API.WaitNative = egl_g3d_wait_native;
865
866 drv->API.BindTexImage = egl_g3d_bind_tex_image;
867 drv->API.ReleaseTexImage = egl_g3d_release_tex_image;
868
869 drv->API.CreateImageKHR = egl_g3d_create_image;
870 drv->API.DestroyImageKHR = egl_g3d_destroy_image;
871 #ifdef EGL_MESA_drm_image
872 drv->API.CreateDRMImageMESA = egl_g3d_create_drm_image;
873 drv->API.ExportDRMImageMESA = egl_g3d_export_drm_image;
874 #endif
875 #ifdef EGL_WL_bind_wayland_display
876 drv->API.BindWaylandDisplayWL = egl_g3d_bind_wayland_display_wl;
877 drv->API.UnbindWaylandDisplayWL = egl_g3d_unbind_wayland_display_wl;
878
879 #endif
880
881 drv->API.CreateSyncKHR = egl_g3d_create_sync;
882 drv->API.DestroySyncKHR = egl_g3d_destroy_sync;
883 drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync;
884 drv->API.SignalSyncKHR = egl_g3d_signal_sync;
885
886 #ifdef EGL_MESA_screen_surface
887 drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
888 drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
889 #endif
890
891 #ifdef EGL_NOK_swap_region
892 drv->API.SwapBuffersRegionNOK = egl_g3d_swap_buffers_region;
893 #endif
894 }