2 * Mesa 3-D graphics library
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 #include "egldriver.h"
27 #include "eglcurrent.h"
30 #include "pipe/p_screen.h"
31 #include "util/u_memory.h"
32 #include "util/u_inlines.h"
33 #include "util/u_box.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 "egl_g3d_loader.h"
44 * Return the state tracker for the given context.
46 static struct st_api
*
47 egl_g3d_choose_st(_EGLDriver
*drv
, _EGLContext
*ctx
,
48 enum st_profile_type
*profile
)
50 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
54 *profile
= ST_PROFILE_DEFAULT
;
56 switch (ctx
->ClientAPI
) {
57 case EGL_OPENGL_ES_API
:
58 switch (ctx
->ClientVersion
) {
61 *profile
= ST_PROFILE_OPENGL_ES1
;
65 *profile
= ST_PROFILE_OPENGL_ES2
;
68 _eglLog(_EGL_WARNING
, "unknown client version %d",
80 _eglLog(_EGL_WARNING
, "unknown client API 0x%04x", ctx
->ClientAPI
);
86 stapi
= gdrv
->loader
->guess_gl_api(*profile
);
89 stapi
= gdrv
->loader
->get_st_api(api
);
95 if (stapi
&& !(stapi
->profile_mask
& (1 << *profile
)))
102 egl_g3d_compare_config(const _EGLConfig
*conf1
, const _EGLConfig
*conf2
,
105 const _EGLConfig
*criteria
= (const _EGLConfig
*) priv_data
;
107 /* EGL_NATIVE_VISUAL_TYPE ignored? */
108 return _eglCompareConfigs(conf1
, conf2
, criteria
, EGL_TRUE
);
112 egl_g3d_match_config(const _EGLConfig
*conf
, const _EGLConfig
*criteria
)
114 if (!_eglMatchConfig(conf
, criteria
))
117 if (criteria
->MatchNativePixmap
!= EGL_NONE
&&
118 criteria
->MatchNativePixmap
!= EGL_DONT_CARE
) {
119 struct egl_g3d_display
*gdpy
= egl_g3d_display(conf
->Display
);
120 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
121 EGLNativePixmapType pix
=
122 (EGLNativePixmapType
) criteria
->MatchNativePixmap
;
124 if (!gdpy
->native
->is_pixmap_supported(gdpy
->native
, pix
, gconf
->native
))
132 egl_g3d_choose_config(_EGLDriver
*drv
, _EGLDisplay
*dpy
, const EGLint
*attribs
,
133 EGLConfig
*configs
, EGLint size
, EGLint
*num_configs
)
135 _EGLConfig
**tmp_configs
, criteria
;
139 return _eglError(EGL_BAD_PARAMETER
, "eglChooseConfigs");
141 if (!_eglParseConfigAttribList(&criteria
, dpy
, attribs
))
142 return _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseConfig");
144 /* get the number of matched configs */
145 tmp_size
= _eglFilterArray(dpy
->Configs
, NULL
, 0,
146 (_EGLArrayForEach
) egl_g3d_match_config
, (void *) &criteria
);
148 *num_configs
= tmp_size
;
152 tmp_configs
= MALLOC(sizeof(tmp_configs
[0]) * tmp_size
);
154 return _eglError(EGL_BAD_ALLOC
, "eglChooseConfig(out of memory)");
156 /* get the matched configs */
157 _eglFilterArray(dpy
->Configs
, (void **) tmp_configs
, tmp_size
,
158 (_EGLArrayForEach
) egl_g3d_match_config
, (void *) &criteria
);
160 /* perform sorting of configs */
161 if (tmp_configs
&& tmp_size
) {
162 _eglSortConfigs((const _EGLConfig
**) tmp_configs
, tmp_size
,
163 egl_g3d_compare_config
, (void *) &criteria
);
164 size
= MIN2(tmp_size
, size
);
165 for (i
= 0; i
< size
; i
++)
166 configs
[i
] = _eglGetConfigHandle(tmp_configs
[i
]);
177 egl_g3d_create_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
178 _EGLContext
*share
, const EGLint
*attribs
)
180 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
181 struct egl_g3d_context
*gshare
= egl_g3d_context(share
);
182 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
183 struct egl_g3d_context
*gctx
;
184 struct st_context_attribs stattribs
;
186 gctx
= CALLOC_STRUCT(egl_g3d_context
);
188 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
192 if (!_eglInitContext(&gctx
->base
, dpy
, conf
, attribs
)) {
197 memset(&stattribs
, 0, sizeof(stattribs
));
199 stattribs
.visual
= gconf
->stvis
;
201 gctx
->stapi
= egl_g3d_choose_st(drv
, &gctx
->base
, &stattribs
.profile
);
207 gctx
->stctxi
= gctx
->stapi
->create_context(gctx
->stapi
, gdpy
->smapi
,
208 &stattribs
, (gshare
) ? gshare
->stctxi
: NULL
);
214 gctx
->stctxi
->st_manager_private
= (void *) &gctx
->base
;
223 destroy_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
225 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
227 /* FIXME a context might live longer than its display */
228 if (!dpy
->Initialized
)
229 _eglLog(_EGL_FATAL
, "destroy a context with an unitialized display");
231 gctx
->stctxi
->destroy(gctx
->stctxi
);
237 egl_g3d_destroy_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
239 if (_eglPutContext(ctx
))
240 destroy_context(dpy
, ctx
);
244 struct egl_g3d_create_surface_arg
{
247 EGLNativeWindowType win
;
248 EGLNativePixmapType pix
;
253 egl_g3d_create_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
254 struct egl_g3d_create_surface_arg
*arg
,
255 const EGLint
*attribs
)
257 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
258 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
259 struct egl_g3d_surface
*gsurf
;
260 struct native_surface
*nsurf
;
265 err
= "eglCreateWindowSurface";
268 err
= "eglCreatePixmapSurface";
270 #ifdef EGL_MESA_screen_surface
271 case EGL_SCREEN_BIT_MESA
:
272 err
= "eglCreateScreenSurface";
276 err
= "eglCreateUnknownSurface";
280 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
282 _eglError(EGL_BAD_ALLOC
, err
);
286 if (!_eglInitSurface(&gsurf
->base
, dpy
, arg
->type
, conf
, attribs
)) {
291 /* create the native surface */
294 nsurf
= gdpy
->native
->create_window_surface(gdpy
->native
,
295 arg
->u
.win
, gconf
->native
);
298 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
,
299 arg
->u
.pix
, gconf
->native
);
301 #ifdef EGL_MESA_screen_surface
302 case EGL_SCREEN_BIT_MESA
:
303 /* prefer back buffer (move to _eglInitSurface?) */
304 gsurf
->base
.RenderBuffer
= EGL_BACK_BUFFER
;
305 nsurf
= gdpy
->native
->modeset
->create_scanout_surface(gdpy
->native
,
306 gconf
->native
, gsurf
->base
.Width
, gsurf
->base
.Height
);
318 /* initialize the geometry */
319 if (!nsurf
->validate(nsurf
, 0x0, &gsurf
->sequence_number
, NULL
,
320 &gsurf
->base
.Width
, &gsurf
->base
.Height
)) {
321 nsurf
->destroy(nsurf
);
326 gsurf
->stvis
= gconf
->stvis
;
327 if (gsurf
->base
.RenderBuffer
== EGL_SINGLE_BUFFER
&&
328 gconf
->stvis
.buffer_mask
& ST_ATTACHMENT_FRONT_LEFT_MASK
)
329 gsurf
->stvis
.render_buffer
= ST_ATTACHMENT_FRONT_LEFT
;
331 gsurf
->stfbi
= egl_g3d_create_st_framebuffer(&gsurf
->base
);
333 nsurf
->destroy(nsurf
);
338 nsurf
->user_data
= &gsurf
->base
;
339 gsurf
->native
= nsurf
;
345 egl_g3d_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
346 _EGLConfig
*conf
, EGLNativeWindowType win
,
347 const EGLint
*attribs
)
349 struct egl_g3d_create_surface_arg arg
;
351 memset(&arg
, 0, sizeof(arg
));
352 arg
.type
= EGL_WINDOW_BIT
;
355 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
359 egl_g3d_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
360 _EGLConfig
*conf
, EGLNativePixmapType pix
,
361 const EGLint
*attribs
)
363 struct egl_g3d_create_surface_arg arg
;
365 memset(&arg
, 0, sizeof(arg
));
366 arg
.type
= EGL_PIXMAP_BIT
;
369 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
372 static struct egl_g3d_surface
*
373 create_pbuffer_surface(_EGLDisplay
*dpy
, _EGLConfig
*conf
,
374 const EGLint
*attribs
, const char *func
)
376 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
377 struct egl_g3d_surface
*gsurf
;
379 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
381 _eglError(EGL_BAD_ALLOC
, func
);
385 if (!_eglInitSurface(&gsurf
->base
, dpy
, EGL_PBUFFER_BIT
, conf
, attribs
)) {
390 gsurf
->stvis
= gconf
->stvis
;
392 gsurf
->stfbi
= egl_g3d_create_st_framebuffer(&gsurf
->base
);
402 egl_g3d_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
403 _EGLConfig
*conf
, const EGLint
*attribs
)
405 struct egl_g3d_surface
*gsurf
;
407 gsurf
= create_pbuffer_surface(dpy
, conf
, attribs
,
408 "eglCreatePbufferSurface");
412 gsurf
->client_buffer_type
= EGL_NONE
;
418 egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
420 EGLClientBuffer buffer
,
422 const EGLint
*attribs
)
424 struct egl_g3d_surface
*gsurf
;
425 struct pipe_resource
*ptex
= NULL
;
426 EGLint pbuffer_attribs
[32];
430 case EGL_OPENVG_IMAGE
:
433 _eglError(EGL_BAD_PARAMETER
, "eglCreatePbufferFromClientBuffer");
438 /* parse the attributes first */
440 for (i
= 0; attribs
&& attribs
[i
] != EGL_NONE
; i
++) {
441 EGLint attr
= attribs
[i
++];
442 EGLint val
= attribs
[i
];
443 EGLint err
= EGL_SUCCESS
;
446 case EGL_TEXTURE_FORMAT
:
447 case EGL_TEXTURE_TARGET
:
448 case EGL_MIPMAP_TEXTURE
:
449 pbuffer_attribs
[count
++] = attr
;
450 pbuffer_attribs
[count
++] = val
;
453 err
= EGL_BAD_ATTRIBUTE
;
457 if (err
!= EGL_SUCCESS
) {
458 _eglError(err
, "eglCreatePbufferFromClientBuffer");
463 pbuffer_attribs
[count
++] = EGL_NONE
;
465 gsurf
= create_pbuffer_surface(dpy
, conf
, pbuffer_attribs
,
466 "eglCreatePbufferFromClientBuffer");
470 gsurf
->client_buffer_type
= buftype
;
471 gsurf
->client_buffer
= buffer
;
473 /* validate now so that it fails if the client buffer is invalid */
474 if (!gsurf
->stfbi
->validate(gsurf
->stfbi
,
475 &gsurf
->stvis
.render_buffer
, 1, &ptex
)) {
476 egl_g3d_destroy_st_framebuffer(gsurf
->stfbi
);
480 pipe_resource_reference(&ptex
, NULL
);
489 destroy_surface(_EGLDisplay
*dpy
, _EGLSurface
*surf
)
491 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
493 /* FIXME a surface might live longer than its display */
494 if (!dpy
->Initialized
)
495 _eglLog(_EGL_FATAL
, "destroy a surface with an unitialized display");
497 pipe_resource_reference(&gsurf
->render_texture
, NULL
);
498 egl_g3d_destroy_st_framebuffer(gsurf
->stfbi
);
500 gsurf
->native
->destroy(gsurf
->native
);
505 egl_g3d_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
507 if (_eglPutSurface(surf
))
508 destroy_surface(dpy
, surf
);
513 egl_g3d_make_current(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
514 _EGLSurface
*draw
, _EGLSurface
*read
, _EGLContext
*ctx
)
516 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
517 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(draw
);
518 struct egl_g3d_surface
*gread
= egl_g3d_surface(read
);
519 struct egl_g3d_context
*old_gctx
;
520 _EGLContext
*old_ctx
;
521 _EGLSurface
*old_draw
, *old_read
;
522 EGLBoolean ok
= EGL_TRUE
;
524 /* make new bindings */
525 if (!_eglBindContext(ctx
, draw
, read
, &old_ctx
, &old_draw
, &old_read
))
528 old_gctx
= egl_g3d_context(old_ctx
);
530 /* flush old context */
531 old_gctx
->stctxi
->flush(old_gctx
->stctxi
,
532 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
536 ok
= gctx
->stapi
->make_current(gctx
->stapi
, gctx
->stctxi
,
537 (gdraw
) ? gdraw
->stfbi
: NULL
, (gread
) ? gread
->stfbi
: NULL
);
540 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
,
543 if (gdraw
->base
.Type
== EGL_WINDOW_BIT
) {
544 gctx
->base
.WindowRenderBuffer
=
545 (gdraw
->stvis
.render_buffer
== ST_ATTACHMENT_FRONT_LEFT
) ?
546 EGL_SINGLE_BUFFER
: EGL_BACK_BUFFER
;
549 if (gread
&& gread
!= gdraw
) {
550 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
,
556 ok
= old_gctx
->stapi
->make_current(old_gctx
->stapi
, NULL
, NULL
, NULL
);
558 old_gctx
->base
.WindowRenderBuffer
= EGL_NONE
;
562 if (_eglPutContext(old_ctx
))
563 destroy_context(dpy
, old_ctx
);
564 if (_eglPutSurface(old_draw
))
565 destroy_surface(dpy
, old_draw
);
566 if (_eglPutSurface(old_read
))
567 destroy_surface(dpy
, old_read
);
570 /* undo the previous _eglBindContext */
571 _eglBindContext(old_ctx
, old_draw
, old_read
, &ctx
, &draw
, &read
);
572 assert(&gctx
->base
== ctx
&&
573 &gdraw
->base
== draw
&&
574 &gread
->base
== read
);
576 _eglPutSurface(draw
);
577 _eglPutSurface(read
);
580 _eglPutSurface(old_draw
);
581 _eglPutSurface(old_read
);
582 _eglPutContext(old_ctx
);
589 egl_g3d_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
591 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
592 _EGLContext
*ctx
= _eglGetCurrentContext();
593 struct egl_g3d_context
*gctx
= NULL
;
595 /* no-op for pixmap or pbuffer surface */
596 if (gsurf
->base
.Type
== EGL_PIXMAP_BIT
||
597 gsurf
->base
.Type
== EGL_PBUFFER_BIT
)
600 /* or when the surface is single-buffered */
601 if (gsurf
->stvis
.render_buffer
== ST_ATTACHMENT_FRONT_LEFT
)
604 if (ctx
&& ctx
->DrawSurface
== surf
)
605 gctx
= egl_g3d_context(ctx
);
607 /* flush if the surface is current */
609 gctx
->stctxi
->flush(gctx
->stctxi
,
610 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
613 return gsurf
->native
->present(gsurf
->native
,
614 NATIVE_ATTACHMENT_BACK_LEFT
,
615 gsurf
->base
.SwapBehavior
== EGL_BUFFER_PRESERVED
,
616 gsurf
->base
.SwapInterval
);
620 * Get the pipe surface of the given attachment of the native surface.
622 static struct pipe_resource
*
623 get_pipe_resource(struct native_display
*ndpy
, struct native_surface
*nsurf
,
624 enum native_attachment natt
)
626 struct pipe_resource
*textures
[NUM_NATIVE_ATTACHMENTS
];
628 textures
[natt
] = NULL
;
629 nsurf
->validate(nsurf
, 1 << natt
, NULL
, textures
, NULL
, NULL
);
631 return textures
[natt
];
635 egl_g3d_copy_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
636 EGLNativePixmapType target
)
638 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
639 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
640 _EGLContext
*ctx
= _eglGetCurrentContext();
641 struct native_surface
*nsurf
;
642 struct pipe_resource
*ptex
;
644 if (!gsurf
->render_texture
)
647 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
, target
, NULL
);
649 return _eglError(EGL_BAD_NATIVE_PIXMAP
, "eglCopyBuffers");
651 /* flush if the surface is current */
652 if (ctx
&& ctx
->DrawSurface
== &gsurf
->base
) {
653 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
654 gctx
->stctxi
->flush(gctx
->stctxi
,
655 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
658 /* create a pipe context to copy surfaces */
661 gdpy
->native
->screen
->context_create(gdpy
->native
->screen
, NULL
);
666 ptex
= get_pipe_resource(gdpy
->native
, nsurf
, NATIVE_ATTACHMENT_FRONT_LEFT
);
668 struct pipe_box src_box
;
670 u_box_origin_2d(ptex
->width0
, ptex
->height0
, &src_box
);
671 gdpy
->pipe
->resource_copy_region(gdpy
->pipe
, ptex
, 0, 0, 0, 0,
672 gsurf
->render_texture
, 0, &src_box
);
673 gdpy
->pipe
->flush(gdpy
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
674 nsurf
->present(nsurf
, NATIVE_ATTACHMENT_FRONT_LEFT
, FALSE
, 0);
676 pipe_resource_reference(&ptex
, NULL
);
679 nsurf
->destroy(nsurf
);
685 egl_g3d_wait_client(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
687 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
688 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
689 struct pipe_screen
*screen
= gdpy
->native
->screen
;
690 struct pipe_fence_handle
*fence
= NULL
;
692 gctx
->stctxi
->flush(gctx
->stctxi
,
693 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, &fence
);
695 screen
->fence_finish(screen
, fence
, 0);
696 screen
->fence_reference(screen
, &fence
, NULL
);
703 egl_g3d_wait_native(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
705 _EGLContext
*ctx
= _eglGetCurrentContext();
707 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
708 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
710 if (ctx
&& ctx
->DrawSurface
) {
711 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(ctx
->DrawSurface
);
714 gsurf
->native
->wait(gsurf
->native
);
721 egl_g3d_bind_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
722 _EGLSurface
*surf
, EGLint buffer
)
724 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
725 _EGLContext
*es1
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
726 struct egl_g3d_context
*gctx
;
727 enum pipe_format internal_format
;
728 enum st_texture_type target
;
730 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
)
731 return _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
732 if (buffer
!= EGL_BACK_BUFFER
)
733 return _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
734 if (gsurf
->base
.BoundToTexture
)
735 return _eglError(EGL_BAD_ACCESS
, "eglBindTexImage");
737 switch (gsurf
->base
.TextureFormat
) {
738 case EGL_TEXTURE_RGB
:
739 internal_format
= PIPE_FORMAT_R8G8B8_UNORM
;
741 case EGL_TEXTURE_RGBA
:
742 internal_format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
745 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
748 switch (gsurf
->base
.TextureTarget
) {
750 target
= ST_TEXTURE_2D
;
753 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
758 if (!gsurf
->render_texture
)
761 /* flush properly if the surface is bound */
762 if (gsurf
->base
.CurrentContext
) {
763 gctx
= egl_g3d_context(gsurf
->base
.CurrentContext
);
764 gctx
->stctxi
->flush(gctx
->stctxi
,
765 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
768 gctx
= egl_g3d_context(es1
);
769 if (gctx
->stctxi
->teximage
) {
770 if (!gctx
->stctxi
->teximage(gctx
->stctxi
, target
,
771 gsurf
->base
.MipmapLevel
, internal_format
,
772 gsurf
->render_texture
, gsurf
->base
.MipmapTexture
))
774 gsurf
->base
.BoundToTexture
= EGL_TRUE
;
781 egl_g3d_release_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
782 _EGLSurface
*surf
, EGLint buffer
)
784 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
786 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
||
787 !gsurf
->base
.BoundToTexture
)
788 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
789 if (buffer
!= EGL_BACK_BUFFER
)
790 return _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
792 if (gsurf
->render_texture
) {
793 _EGLContext
*ctx
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
794 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
796 /* what if the context the surface binds to is no longer current? */
798 gctx
->stctxi
->teximage(gctx
->stctxi
, ST_TEXTURE_2D
,
799 gsurf
->base
.MipmapLevel
, PIPE_FORMAT_NONE
, NULL
, FALSE
);
803 gsurf
->base
.BoundToTexture
= EGL_FALSE
;
808 #ifdef EGL_MESA_screen_surface
811 egl_g3d_create_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
812 _EGLConfig
*conf
, const EGLint
*attribs
)
814 struct egl_g3d_create_surface_arg arg
;
816 memset(&arg
, 0, sizeof(arg
));
817 arg
.type
= EGL_SCREEN_BIT_MESA
;
819 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
823 egl_g3d_show_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
824 _EGLScreen
*scr
, _EGLSurface
*surf
,
827 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
828 struct egl_g3d_screen
*gscr
= egl_g3d_screen(scr
);
829 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
830 struct native_surface
*nsurf
;
831 const struct native_mode
*nmode
;
838 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
839 if (gsurf
->base
.Type
!= EGL_SCREEN_BIT_MESA
)
840 return _eglError(EGL_BAD_SURFACE
, "eglShowScreenSurfaceMESA");
841 if (gsurf
->base
.Width
< mode
->Width
|| gsurf
->base
.Height
< mode
->Height
)
842 return _eglError(EGL_BAD_MATCH
,
843 "eglShowSurfaceMESA(surface smaller than mode size)");
845 /* find the index of the mode */
846 for (idx
= 0; idx
< gscr
->base
.NumModes
; idx
++)
847 if (mode
== &gscr
->base
.Modes
[idx
])
849 if (idx
>= gscr
->base
.NumModes
) {
850 return _eglError(EGL_BAD_MODE_MESA
,
851 "eglShowSurfaceMESA(unknown mode)");
854 nsurf
= gsurf
->native
;
855 nmode
= gscr
->native_modes
[idx
];
859 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
861 /* disable the screen */
866 /* TODO surface panning by CRTC choosing */
867 changed
= gdpy
->native
->modeset
->program(gdpy
->native
, 0, nsurf
,
868 gscr
->base
.OriginX
, gscr
->base
.OriginY
, &gscr
->native
, 1, nmode
);
870 gscr
->base
.CurrentSurface
= &gsurf
->base
;
871 gscr
->base
.CurrentMode
= mode
;
877 #endif /* EGL_MESA_screen_surface */
880 egl_g3d_init_driver_api(_EGLDriver
*drv
)
882 _eglInitDriverFallbacks(drv
);
884 drv
->API
.ChooseConfig
= egl_g3d_choose_config
;
886 drv
->API
.CreateContext
= egl_g3d_create_context
;
887 drv
->API
.DestroyContext
= egl_g3d_destroy_context
;
888 drv
->API
.CreateWindowSurface
= egl_g3d_create_window_surface
;
889 drv
->API
.CreatePixmapSurface
= egl_g3d_create_pixmap_surface
;
890 drv
->API
.CreatePbufferSurface
= egl_g3d_create_pbuffer_surface
;
891 drv
->API
.CreatePbufferFromClientBuffer
= egl_g3d_create_pbuffer_from_client_buffer
;
892 drv
->API
.DestroySurface
= egl_g3d_destroy_surface
;
893 drv
->API
.MakeCurrent
= egl_g3d_make_current
;
894 drv
->API
.SwapBuffers
= egl_g3d_swap_buffers
;
895 drv
->API
.CopyBuffers
= egl_g3d_copy_buffers
;
896 drv
->API
.WaitClient
= egl_g3d_wait_client
;
897 drv
->API
.WaitNative
= egl_g3d_wait_native
;
899 drv
->API
.BindTexImage
= egl_g3d_bind_tex_image
;
900 drv
->API
.ReleaseTexImage
= egl_g3d_release_tex_image
;
902 drv
->API
.CreateImageKHR
= egl_g3d_create_image
;
903 drv
->API
.DestroyImageKHR
= egl_g3d_destroy_image
;
904 #ifdef EGL_MESA_drm_image
905 drv
->API
.CreateDRMImageMESA
= egl_g3d_create_drm_image
;
906 drv
->API
.ExportDRMImageMESA
= egl_g3d_export_drm_image
;
909 #ifdef EGL_KHR_reusable_sync
910 drv
->API
.CreateSyncKHR
= egl_g3d_create_sync
;
911 drv
->API
.DestroySyncKHR
= egl_g3d_destroy_sync
;
912 drv
->API
.ClientWaitSyncKHR
= egl_g3d_client_wait_sync
;
913 drv
->API
.SignalSyncKHR
= egl_g3d_signal_sync
;
916 #ifdef EGL_MESA_screen_surface
917 drv
->API
.CreateScreenSurfaceMESA
= egl_g3d_create_screen_surface
;
918 drv
->API
.ShowScreenSurfaceMESA
= egl_g3d_show_screen_surface
;