2 * Mesa 3-D graphics library
4 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 #include "egldriver.h"
26 #include "eglcurrent.h"
29 #include "pipe/p_screen.h"
30 #include "util/u_memory.h"
31 #include "util/u_inlines.h"
32 #include "util/u_box.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"
42 * Return the state tracker for the given context.
44 static struct st_api
*
45 egl_g3d_choose_st(_EGLDriver
*drv
, _EGLContext
*ctx
,
46 enum st_profile_type
*profile
)
51 *profile
= ST_PROFILE_DEFAULT
;
53 switch (ctx
->ClientAPI
) {
54 case EGL_OPENGL_ES_API
:
55 switch (ctx
->ClientMajorVersion
) {
58 *profile
= ST_PROFILE_OPENGL_ES1
;
62 *profile
= ST_PROFILE_OPENGL_ES2
;
65 _eglLog(_EGL_WARNING
, "unknown client major version %d",
66 ctx
->ClientMajorVersion
);
77 _eglLog(_EGL_WARNING
, "unknown client API 0x%04x", ctx
->ClientAPI
);
81 stapi
= egl_g3d_get_st_api(drv
, api
);
82 if (stapi
&& !(stapi
->profile_mask
& (1 << *profile
)))
88 struct egl_g3d_choose_config_data
{
90 enum pipe_format format
;
94 egl_g3d_compare_config(const _EGLConfig
*conf1
, const _EGLConfig
*conf2
,
97 struct egl_g3d_choose_config_data
*data
=
98 (struct egl_g3d_choose_config_data
*) priv_data
;
99 const _EGLConfig
*criteria
= &data
->criteria
;;
101 /* EGL_NATIVE_VISUAL_TYPE ignored? */
102 return _eglCompareConfigs(conf1
, conf2
, criteria
, EGL_TRUE
);
106 egl_g3d_match_config(const _EGLConfig
*conf
, void *priv_data
)
108 struct egl_g3d_choose_config_data
*data
=
109 (struct egl_g3d_choose_config_data
*) priv_data
;
110 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
112 if (data
->format
!= PIPE_FORMAT_NONE
&&
113 data
->format
!= gconf
->native
->color_format
)
116 return _eglMatchConfig(conf
, &data
->criteria
);
120 egl_g3d_choose_config(_EGLDriver
*drv
, _EGLDisplay
*dpy
, const EGLint
*attribs
,
121 EGLConfig
*configs
, EGLint size
, EGLint
*num_configs
)
123 struct egl_g3d_choose_config_data data
;
125 if (!_eglParseConfigAttribList(&data
.criteria
, dpy
, attribs
))
126 return _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseConfig");
128 data
.format
= PIPE_FORMAT_NONE
;
129 if (data
.criteria
.MatchNativePixmap
!= EGL_NONE
&&
130 data
.criteria
.MatchNativePixmap
!= EGL_DONT_CARE
) {
131 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
133 if (!gdpy
->native
->get_pixmap_format(gdpy
->native
,
134 (EGLNativePixmapType
) data
.criteria
.MatchNativePixmap
,
136 return _eglError(EGL_BAD_NATIVE_PIXMAP
, "eglChooseConfig");
139 return _eglFilterConfigArray(dpy
->Configs
, configs
, size
, num_configs
,
140 egl_g3d_match_config
, egl_g3d_compare_config
, &data
);
144 egl_g3d_create_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
145 _EGLContext
*share
, const EGLint
*attribs
)
147 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
148 struct egl_g3d_context
*gshare
= egl_g3d_context(share
);
149 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
150 struct egl_g3d_context
*gctx
;
151 struct st_context_attribs stattribs
;
152 enum st_context_error ctx_err
= 0;
154 gctx
= CALLOC_STRUCT(egl_g3d_context
);
156 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
160 if (!_eglInitContext(&gctx
->base
, dpy
, conf
, attribs
)) {
165 memset(&stattribs
, 0, sizeof(stattribs
));
167 stattribs
.visual
= gconf
->stvis
;
169 gctx
->stapi
= egl_g3d_choose_st(drv
, &gctx
->base
, &stattribs
.profile
);
175 gctx
->stctxi
= gctx
->stapi
->create_context(gctx
->stapi
, gdpy
->smapi
,
176 &stattribs
, &ctx_err
, (gshare
) ? gshare
->stctxi
: NULL
);
182 gctx
->stctxi
->st_manager_private
= (void *) &gctx
->base
;
191 destroy_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
193 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
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");
199 gctx
->stctxi
->destroy(gctx
->stctxi
);
205 egl_g3d_destroy_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
207 if (_eglPutContext(ctx
))
208 destroy_context(dpy
, ctx
);
212 struct egl_g3d_create_surface_arg
{
215 EGLNativeWindowType win
;
216 EGLNativePixmapType pix
;
221 egl_g3d_create_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
222 struct egl_g3d_create_surface_arg
*arg
,
223 const EGLint
*attribs
)
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
;
233 err
= "eglCreateWindowSurface";
236 err
= "eglCreatePixmapSurface";
238 #ifdef EGL_MESA_screen_surface
239 case EGL_SCREEN_BIT_MESA
:
240 err
= "eglCreateScreenSurface";
244 err
= "eglCreateUnknownSurface";
248 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
250 _eglError(EGL_BAD_ALLOC
, err
);
254 if (!_eglInitSurface(&gsurf
->base
, dpy
, arg
->type
, conf
, attribs
)) {
259 /* create the native surface */
262 nsurf
= gdpy
->native
->create_window_surface(gdpy
->native
,
263 arg
->u
.win
, gconf
->native
);
266 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
,
267 arg
->u
.pix
, gconf
->native
);
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
);
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
);
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
;
299 /* surfaces can always be posted when the display supports it */
300 if (dpy
->Extensions
.NV_post_sub_buffer
)
301 gsurf
->base
.PostSubBufferSupportedNV
= EGL_TRUE
;
303 gsurf
->stfbi
= egl_g3d_create_st_framebuffer(&gsurf
->base
);
305 nsurf
->destroy(nsurf
);
310 nsurf
->user_data
= &gsurf
->base
;
311 gsurf
->native
= nsurf
;
317 egl_g3d_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
318 _EGLConfig
*conf
, void *native_window
,
319 const EGLint
*attribs
)
321 EGLNativeWindowType win
;
322 struct egl_g3d_create_surface_arg arg
;
324 STATIC_ASSERT(sizeof(EGLNativeWindowType
) == sizeof(native_window
));
325 win
= (EGLNativeWindowType
) native_window
;
327 memset(&arg
, 0, sizeof(arg
));
328 arg
.type
= EGL_WINDOW_BIT
;
331 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
335 egl_g3d_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
336 _EGLConfig
*conf
, void *native_pixmap
,
337 const EGLint
*attribs
)
339 EGLNativePixmapType pix
;
340 struct egl_g3d_create_surface_arg arg
;
342 STATIC_ASSERT(sizeof(EGLNativePixmapType
) == sizeof(native_pixmap
));
343 pix
= (EGLNativePixmapType
) native_pixmap
;
345 memset(&arg
, 0, sizeof(arg
));
346 arg
.type
= EGL_PIXMAP_BIT
;
349 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
352 static struct egl_g3d_surface
*
353 create_pbuffer_surface(_EGLDisplay
*dpy
, _EGLConfig
*conf
,
354 const EGLint
*attribs
, const char *func
)
356 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
357 struct egl_g3d_surface
*gsurf
;
359 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
361 _eglError(EGL_BAD_ALLOC
, func
);
365 if (!_eglInitSurface(&gsurf
->base
, dpy
, EGL_PBUFFER_BIT
, conf
, attribs
)) {
370 gsurf
->stvis
= gconf
->stvis
;
372 gsurf
->stfbi
= egl_g3d_create_st_framebuffer(&gsurf
->base
);
382 egl_g3d_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
383 _EGLConfig
*conf
, const EGLint
*attribs
)
385 struct egl_g3d_surface
*gsurf
;
387 gsurf
= create_pbuffer_surface(dpy
, conf
, attribs
,
388 "eglCreatePbufferSurface");
392 gsurf
->client_buffer_type
= EGL_NONE
;
398 egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
400 EGLClientBuffer buffer
,
402 const EGLint
*attribs
)
404 struct egl_g3d_surface
*gsurf
;
405 struct pipe_resource
*ptex
= NULL
;
406 EGLint pbuffer_attribs
[32];
410 case EGL_OPENVG_IMAGE
:
413 _eglError(EGL_BAD_PARAMETER
, "eglCreatePbufferFromClientBuffer");
418 /* parse the attributes first */
420 for (i
= 0; attribs
&& attribs
[i
] != EGL_NONE
; i
++) {
421 EGLint attr
= attribs
[i
++];
422 EGLint val
= attribs
[i
];
423 EGLint err
= EGL_SUCCESS
;
426 case EGL_TEXTURE_FORMAT
:
427 case EGL_TEXTURE_TARGET
:
428 case EGL_MIPMAP_TEXTURE
:
429 pbuffer_attribs
[count
++] = attr
;
430 pbuffer_attribs
[count
++] = val
;
433 err
= EGL_BAD_ATTRIBUTE
;
437 if (err
!= EGL_SUCCESS
) {
438 _eglError(err
, "eglCreatePbufferFromClientBuffer");
443 pbuffer_attribs
[count
++] = EGL_NONE
;
445 gsurf
= create_pbuffer_surface(dpy
, conf
, pbuffer_attribs
,
446 "eglCreatePbufferFromClientBuffer");
450 gsurf
->client_buffer_type
= buftype
;
451 gsurf
->client_buffer
= buffer
;
453 /* validate now so that it fails if the client buffer is invalid */
454 if (!gsurf
->stfbi
->validate(NULL
, gsurf
->stfbi
,
455 &gsurf
->stvis
.render_buffer
, 1, &ptex
)) {
456 egl_g3d_destroy_st_framebuffer(gsurf
->stfbi
);
460 pipe_resource_reference(&ptex
, NULL
);
469 destroy_surface(_EGLDisplay
*dpy
, _EGLSurface
*surf
)
471 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
473 /* FIXME a surface might live longer than its display */
474 if (!dpy
->Initialized
)
475 _eglLog(_EGL_FATAL
, "destroy a surface with an unitialized display");
477 pipe_resource_reference(&gsurf
->render_texture
, NULL
);
478 egl_g3d_destroy_st_framebuffer(gsurf
->stfbi
);
480 gsurf
->native
->destroy(gsurf
->native
);
485 egl_g3d_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
487 if (_eglPutSurface(surf
))
488 destroy_surface(dpy
, surf
);
493 egl_g3d_make_current(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
494 _EGLSurface
*draw
, _EGLSurface
*read
, _EGLContext
*ctx
)
496 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
497 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(draw
);
498 struct egl_g3d_surface
*gread
= egl_g3d_surface(read
);
499 struct egl_g3d_context
*old_gctx
;
500 _EGLContext
*old_ctx
;
501 _EGLSurface
*old_draw
, *old_read
;
502 EGLBoolean ok
= EGL_TRUE
;
504 /* make new bindings */
505 if (!_eglBindContext(ctx
, draw
, read
, &old_ctx
, &old_draw
, &old_read
))
508 old_gctx
= egl_g3d_context(old_ctx
);
510 /* flush old context */
511 old_gctx
->stctxi
->flush(old_gctx
->stctxi
, ST_FLUSH_FRONT
, NULL
);
515 ok
= gctx
->stapi
->make_current(gctx
->stapi
, gctx
->stctxi
,
516 (gdraw
) ? gdraw
->stfbi
: NULL
, (gread
) ? gread
->stfbi
: NULL
);
519 if (gdraw
->base
.Type
== EGL_WINDOW_BIT
) {
520 gctx
->base
.WindowRenderBuffer
=
521 (gdraw
->stvis
.render_buffer
== ST_ATTACHMENT_FRONT_LEFT
) ?
522 EGL_SINGLE_BUFFER
: EGL_BACK_BUFFER
;
528 ok
= old_gctx
->stapi
->make_current(old_gctx
->stapi
, NULL
, NULL
, NULL
);
530 old_gctx
->base
.WindowRenderBuffer
= EGL_NONE
;
534 if (_eglPutContext(old_ctx
))
535 destroy_context(dpy
, old_ctx
);
536 if (_eglPutSurface(old_draw
))
537 destroy_surface(dpy
, old_draw
);
538 if (_eglPutSurface(old_read
))
539 destroy_surface(dpy
, old_read
);
542 /* undo the previous _eglBindContext */
543 _eglBindContext(old_ctx
, old_draw
, old_read
, &ctx
, &draw
, &read
);
544 assert(&gctx
->base
== ctx
&&
545 &gdraw
->base
== draw
&&
546 &gread
->base
== read
);
548 _eglPutSurface(draw
);
549 _eglPutSurface(read
);
552 _eglPutSurface(old_draw
);
553 _eglPutSurface(old_read
);
554 _eglPutContext(old_ctx
);
561 swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
562 EGLint num_rects
, const EGLint
*rects
, EGLBoolean preserve
)
564 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
565 _EGLContext
*ctx
= _eglGetCurrentContext();
566 struct egl_g3d_context
*gctx
= NULL
;
567 struct native_present_control ctrl
;
569 /* no-op for pixmap or pbuffer surface */
570 if (gsurf
->base
.Type
== EGL_PIXMAP_BIT
||
571 gsurf
->base
.Type
== EGL_PBUFFER_BIT
)
574 /* or when the surface is single-buffered */
575 if (gsurf
->stvis
.render_buffer
== ST_ATTACHMENT_FRONT_LEFT
)
578 if (ctx
&& ctx
->DrawSurface
== surf
)
579 gctx
= egl_g3d_context(ctx
);
581 /* flush if the surface is current */
583 gctx
->stctxi
->flush(gctx
->stctxi
, ST_FLUSH_FRONT
, NULL
);
586 memset(&ctrl
, 0, sizeof(ctrl
));
587 ctrl
.natt
= NATIVE_ATTACHMENT_BACK_LEFT
;
588 ctrl
.preserve
= preserve
;
589 ctrl
.swap_interval
= gsurf
->base
.SwapInterval
;
590 ctrl
.premultiplied_alpha
= (gsurf
->base
.VGAlphaFormat
== EGL_VG_ALPHA_FORMAT_PRE
);
591 ctrl
.num_rects
= num_rects
;
594 return gsurf
->native
->present(gsurf
->native
, &ctrl
);
598 egl_g3d_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
600 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
602 return swap_buffers(drv
, dpy
, surf
, 0, NULL
,
603 (gsurf
->base
.SwapBehavior
== EGL_BUFFER_PRESERVED
));
606 #ifdef EGL_NOK_swap_region
608 egl_g3d_swap_buffers_region(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
609 EGLint num_rects
, const EGLint
*rects
)
612 return swap_buffers(drv
, dpy
, surf
, num_rects
, rects
, EGL_TRUE
);
614 #endif /* EGL_NOK_swap_region */
617 egl_g3d_post_sub_buffer(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
618 EGLint x
, EGLint y
, EGLint width
, EGLint height
)
622 if (x
< 0 || y
< 0 || width
< 0 || height
< 0)
623 return _eglError(EGL_BAD_PARAMETER
, "eglPostSubBufferNV");
626 if (x
+ width
> surf
->Width
)
627 width
= surf
->Width
- x
;
628 if (y
+ height
> surf
->Height
)
629 height
= surf
->Height
- y
;
631 if (width
<= 0 || height
<= 0)
635 /* Note: y=0=bottom */
636 rect
[1] = surf
->Height
- y
- height
;
640 return swap_buffers(drv
, dpy
, surf
, 1, rect
, EGL_TRUE
);
644 egl_g3d_copy_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
645 void *native_pixmap_target
)
647 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
648 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
649 _EGLContext
*ctx
= _eglGetCurrentContext();
650 EGLNativePixmapType target
;
652 STATIC_ASSERT(sizeof(EGLNativePixmapType
) == sizeof(native_pixmap_target
));
653 target
= (EGLNativePixmapType
) native_pixmap_target
;
655 if (!gsurf
->render_texture
)
658 /* flush if the surface is current */
659 if (ctx
&& ctx
->DrawSurface
== &gsurf
->base
) {
660 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
661 gctx
->stctxi
->flush(gctx
->stctxi
, ST_FLUSH_FRONT
, NULL
);
664 return gdpy
->native
->copy_to_pixmap(gdpy
->native
,
665 target
, gsurf
->render_texture
);
669 egl_g3d_wait_client(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
671 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
672 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
673 struct pipe_screen
*screen
= gdpy
->native
->screen
;
674 struct pipe_fence_handle
*fence
= NULL
;
676 gctx
->stctxi
->flush(gctx
->stctxi
, ST_FLUSH_FRONT
, &fence
);
678 screen
->fence_finish(screen
, fence
, PIPE_TIMEOUT_INFINITE
);
679 screen
->fence_reference(screen
, &fence
, NULL
);
686 egl_g3d_wait_native(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
688 _EGLContext
*ctx
= _eglGetCurrentContext();
690 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
691 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
693 if (ctx
&& ctx
->DrawSurface
) {
694 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(ctx
->DrawSurface
);
697 gsurf
->native
->wait(gsurf
->native
);
704 egl_g3d_bind_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
705 _EGLSurface
*surf
, EGLint buffer
)
707 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
708 _EGLContext
*es1
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
709 struct egl_g3d_context
*gctx
;
710 enum pipe_format internal_format
;
711 enum st_texture_type target
;
713 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
)
714 return _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
715 if (buffer
!= EGL_BACK_BUFFER
)
716 return _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
717 if (gsurf
->base
.BoundToTexture
)
718 return _eglError(EGL_BAD_ACCESS
, "eglBindTexImage");
720 switch (gsurf
->base
.TextureFormat
) {
721 case EGL_TEXTURE_RGB
:
722 internal_format
= PIPE_FORMAT_R8G8B8_UNORM
;
724 case EGL_TEXTURE_RGBA
:
725 internal_format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
728 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
731 switch (gsurf
->base
.TextureTarget
) {
733 target
= ST_TEXTURE_2D
;
736 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
741 if (!gsurf
->render_texture
)
744 /* flush properly if the surface is bound */
745 if (gsurf
->base
.CurrentContext
) {
746 gctx
= egl_g3d_context(gsurf
->base
.CurrentContext
);
747 gctx
->stctxi
->flush(gctx
->stctxi
, ST_FLUSH_FRONT
, NULL
);
750 gctx
= egl_g3d_context(es1
);
751 if (gctx
->stctxi
->teximage
) {
752 if (!gctx
->stctxi
->teximage(gctx
->stctxi
, target
,
753 gsurf
->base
.MipmapLevel
, internal_format
,
754 gsurf
->render_texture
, gsurf
->base
.MipmapTexture
))
756 gsurf
->base
.BoundToTexture
= EGL_TRUE
;
763 egl_g3d_release_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
764 _EGLSurface
*surf
, EGLint buffer
)
766 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
768 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
||
769 !gsurf
->base
.BoundToTexture
)
770 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
771 if (buffer
!= EGL_BACK_BUFFER
)
772 return _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
774 if (gsurf
->render_texture
) {
775 _EGLContext
*ctx
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
776 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
778 /* what if the context the surface binds to is no longer current? */
780 gctx
->stctxi
->teximage(gctx
->stctxi
, ST_TEXTURE_2D
,
781 gsurf
->base
.MipmapLevel
, PIPE_FORMAT_NONE
, NULL
, FALSE
);
785 gsurf
->base
.BoundToTexture
= EGL_FALSE
;
790 #ifdef EGL_MESA_screen_surface
793 egl_g3d_create_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
794 _EGLConfig
*conf
, const EGLint
*attribs
)
796 struct egl_g3d_create_surface_arg arg
;
798 memset(&arg
, 0, sizeof(arg
));
799 arg
.type
= EGL_SCREEN_BIT_MESA
;
801 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
805 egl_g3d_show_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
806 _EGLScreen
*scr
, _EGLSurface
*surf
,
809 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
810 struct egl_g3d_screen
*gscr
= egl_g3d_screen(scr
);
811 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
812 struct native_surface
*nsurf
;
813 const struct native_mode
*nmode
;
820 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
821 if (gsurf
->base
.Type
!= EGL_SCREEN_BIT_MESA
)
822 return _eglError(EGL_BAD_SURFACE
, "eglShowScreenSurfaceMESA");
823 if (gsurf
->base
.Width
< mode
->Width
|| gsurf
->base
.Height
< mode
->Height
)
824 return _eglError(EGL_BAD_MATCH
,
825 "eglShowSurfaceMESA(surface smaller than mode size)");
827 /* find the index of the mode */
828 for (idx
= 0; idx
< gscr
->base
.NumModes
; idx
++)
829 if (mode
== &gscr
->base
.Modes
[idx
])
831 if (idx
>= gscr
->base
.NumModes
) {
832 return _eglError(EGL_BAD_MODE_MESA
,
833 "eglShowSurfaceMESA(unknown mode)");
836 nsurf
= gsurf
->native
;
837 nmode
= gscr
->native_modes
[idx
];
841 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
843 /* disable the screen */
848 /* TODO surface panning by CRTC choosing */
849 changed
= gdpy
->native
->modeset
->program(gdpy
->native
, 0, nsurf
,
850 gscr
->base
.OriginX
, gscr
->base
.OriginY
, &gscr
->native
, 1, nmode
);
852 gscr
->base
.CurrentSurface
= &gsurf
->base
;
853 gscr
->base
.CurrentMode
= mode
;
859 #endif /* EGL_MESA_screen_surface */
861 #ifdef EGL_WL_bind_wayland_display
864 egl_g3d_bind_wayland_display_wl(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
865 struct wl_display
*wl_dpy
)
867 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
869 if (!gdpy
->native
->wayland_bufmgr
)
872 return gdpy
->native
->wayland_bufmgr
->bind_display(gdpy
->native
, wl_dpy
);
876 egl_g3d_unbind_wayland_display_wl(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
877 struct wl_display
*wl_dpy
)
879 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
881 if (!gdpy
->native
->wayland_bufmgr
)
884 return gdpy
->native
->wayland_bufmgr
->unbind_display(gdpy
->native
, wl_dpy
);
888 egl_g3d_query_wayland_buffer_wl(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
889 struct wl_resource
*buffer
,
890 EGLint attribute
, EGLint
*value
)
892 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
894 if (!gdpy
->native
->wayland_bufmgr
)
897 return gdpy
->native
->wayland_bufmgr
->query_buffer(gdpy
->native
,
898 buffer
, attribute
, value
);
900 #endif /* EGL_WL_bind_wayland_display */
903 egl_g3d_init_driver_api(_EGLDriver
*drv
)
905 _eglInitDriverFallbacks(drv
);
907 drv
->API
.ChooseConfig
= egl_g3d_choose_config
;
909 drv
->API
.CreateContext
= egl_g3d_create_context
;
910 drv
->API
.DestroyContext
= egl_g3d_destroy_context
;
911 drv
->API
.CreateWindowSurface
= egl_g3d_create_window_surface
;
912 drv
->API
.CreatePixmapSurface
= egl_g3d_create_pixmap_surface
;
913 drv
->API
.CreatePbufferSurface
= egl_g3d_create_pbuffer_surface
;
914 drv
->API
.CreatePbufferFromClientBuffer
= egl_g3d_create_pbuffer_from_client_buffer
;
915 drv
->API
.DestroySurface
= egl_g3d_destroy_surface
;
916 drv
->API
.MakeCurrent
= egl_g3d_make_current
;
917 drv
->API
.SwapBuffers
= egl_g3d_swap_buffers
;
918 drv
->API
.CopyBuffers
= egl_g3d_copy_buffers
;
919 drv
->API
.WaitClient
= egl_g3d_wait_client
;
920 drv
->API
.WaitNative
= egl_g3d_wait_native
;
922 drv
->API
.BindTexImage
= egl_g3d_bind_tex_image
;
923 drv
->API
.ReleaseTexImage
= egl_g3d_release_tex_image
;
925 drv
->API
.CreateImageKHR
= egl_g3d_create_image
;
926 drv
->API
.DestroyImageKHR
= egl_g3d_destroy_image
;
927 #ifdef EGL_MESA_drm_image
928 drv
->API
.CreateDRMImageMESA
= egl_g3d_create_drm_image
;
929 drv
->API
.ExportDRMImageMESA
= egl_g3d_export_drm_image
;
931 #ifdef EGL_WL_bind_wayland_display
932 drv
->API
.BindWaylandDisplayWL
= egl_g3d_bind_wayland_display_wl
;
933 drv
->API
.UnbindWaylandDisplayWL
= egl_g3d_unbind_wayland_display_wl
;
934 drv
->API
.QueryWaylandBufferWL
= egl_g3d_query_wayland_buffer_wl
;
937 drv
->API
.CreateSyncKHR
= egl_g3d_create_sync
;
938 drv
->API
.DestroySyncKHR
= egl_g3d_destroy_sync
;
939 drv
->API
.ClientWaitSyncKHR
= egl_g3d_client_wait_sync
;
940 drv
->API
.SignalSyncKHR
= egl_g3d_signal_sync
;
942 #ifdef EGL_MESA_screen_surface
943 drv
->API
.CreateScreenSurfaceMESA
= egl_g3d_create_screen_surface
;
944 drv
->API
.ShowScreenSurfaceMESA
= egl_g3d_show_screen_surface
;
947 #ifdef EGL_NOK_swap_region
948 drv
->API
.SwapBuffersRegionNOK
= egl_g3d_swap_buffers_region
;
951 drv
->API
.PostSubBufferNV
= egl_g3d_post_sub_buffer
;