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