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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "pipe/p_screen.h"
29 #include "util/u_memory.h"
30 #include "util/u_rect.h"
31 #include "util/u_inlines.h"
32 #include "egldriver.h"
33 #include "eglcurrent.h"
34 #include "eglconfigutil.h"
39 #include "egl_g3d_st.h"
40 #include "egl_g3d_image.h"
43 * Return the state tracker for the given context.
45 static struct st_api
*
46 egl_g3d_choose_st(_EGLDriver
*drv
, _EGLContext
*ctx
)
48 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
52 switch (ctx
->ClientAPI
) {
53 case EGL_OPENGL_ES_API
:
54 switch (ctx
->ClientVersion
) {
56 idx
= ST_API_OPENGL_ES1
;
59 idx
= ST_API_OPENGL_ES2
;
62 _eglLog(_EGL_WARNING
, "unknown client version %d",
74 _eglLog(_EGL_WARNING
, "unknown client API 0x%04x", ctx
->ClientAPI
);
78 stapi
= (idx
>= 0) ? gdrv
->stapis
[idx
] : NULL
;
83 * Initialize the state trackers.
86 egl_g3d_init_st(_EGLDriver
*drv
)
88 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
91 /* already initialized */
95 for (i
= 0; i
< ST_API_COUNT
; i
++) {
96 gdrv
->stapis
[i
] = egl_g3d_create_st_api(i
);
98 gdrv
->api_mask
|= egl_g3d_st_api_bit(i
);
102 _eglLog(_EGL_DEBUG
, "Driver API mask: 0x%x", gdrv
->api_mask
);
104 _eglLog(_EGL_WARNING
, "No supported client API");
108 * Get the probe object of the display.
110 * Note that this function may be called before the display is initialized.
112 static struct native_probe
*
113 egl_g3d_get_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
115 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
116 struct native_probe
*nprobe
;
118 nprobe
= (struct native_probe
*) _eglGetProbeCache(gdrv
->probe_key
);
119 if (!nprobe
|| nprobe
->display
!= dpy
->NativeDisplay
) {
121 nprobe
->destroy(nprobe
);
122 nprobe
= native_create_probe(dpy
->NativeDisplay
);
123 _eglSetProbeCache(gdrv
->probe_key
, (void *) nprobe
);
130 * Destroy the probe object of the display. The display may be NULL.
132 * Note that this function may be called before the display is initialized.
135 egl_g3d_destroy_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
137 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
138 struct native_probe
*nprobe
;
140 nprobe
= (struct native_probe
*) _eglGetProbeCache(gdrv
->probe_key
);
141 if (nprobe
&& (!dpy
|| nprobe
->display
== dpy
->NativeDisplay
)) {
142 nprobe
->destroy(nprobe
);
143 _eglSetProbeCache(gdrv
->probe_key
, NULL
);
147 #ifdef EGL_MESA_screen_surface
150 egl_g3d_add_screens(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
152 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
153 const struct native_connector
**native_connectors
;
154 EGLint num_connectors
, i
;
157 gdpy
->native
->modeset
->get_connectors(gdpy
->native
, &num_connectors
, NULL
);
158 if (!num_connectors
) {
159 if (native_connectors
)
160 free(native_connectors
);
164 for (i
= 0; i
< num_connectors
; i
++) {
165 const struct native_connector
*nconn
= native_connectors
[i
];
166 struct egl_g3d_screen
*gscr
;
167 const struct native_mode
**native_modes
;
170 /* TODO support for hotplug */
172 gdpy
->native
->modeset
->get_modes(gdpy
->native
, nconn
, &num_modes
);
179 gscr
= CALLOC_STRUCT(egl_g3d_screen
);
185 _eglInitScreen(&gscr
->base
);
187 for (j
= 0; j
< num_modes
; j
++) {
188 const struct native_mode
*nmode
= native_modes
[j
];
191 mode
= _eglAddNewMode(&gscr
->base
, nmode
->width
, nmode
->height
,
192 nmode
->refresh_rate
, nmode
->desc
);
195 /* gscr->native_modes and gscr->base.Modes should be consistent */
196 assert(mode
== &gscr
->base
.Modes
[j
]);
199 gscr
->native
= nconn
;
200 gscr
->native_modes
= native_modes
;
202 _eglAddScreen(dpy
, &gscr
->base
);
205 free(native_connectors
);
208 #endif /* EGL_MESA_screen_surface */
211 * Initialize an EGL config from the native config.
214 egl_g3d_init_config(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
215 _EGLConfig
*conf
, const struct native_config
*nconf
)
217 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
218 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
219 const __GLcontextModes
*mode
= &nconf
->mode
;
220 EGLint buffer_mask
, api_mask
;
224 buffer_mask
= ST_ATTACHMENT_FRONT_LEFT_MASK
;
225 if (mode
->doubleBufferMode
)
226 buffer_mask
|= ST_ATTACHMENT_BACK_LEFT_MASK
;
227 if (mode
->stereoMode
) {
228 buffer_mask
|= ST_ATTACHMENT_FRONT_RIGHT_MASK
;
229 if (mode
->doubleBufferMode
)
230 buffer_mask
|= ST_ATTACHMENT_BACK_RIGHT_MASK
;
233 gconf
->stvis
.buffer_mask
= buffer_mask
;
234 gconf
->stvis
.color_format
= nconf
->color_format
;
235 gconf
->stvis
.depth_stencil_format
= nconf
->depth_format
;
236 gconf
->stvis
.accum_format
= PIPE_FORMAT_NONE
;
237 gconf
->stvis
.samples
= 0;
239 gconf
->stvis
.render_buffer
= (buffer_mask
& ST_ATTACHMENT_BACK_LEFT
) ?
240 ST_ATTACHMENT_BACK_LEFT
: ST_ATTACHMENT_FRONT_LEFT
;
243 for (i
= 0; i
< ST_API_COUNT
; i
++) {
244 struct st_api
*stapi
= gdrv
->stapis
[i
];
246 if (stapi
->is_visual_supported(stapi
, &gconf
->stvis
))
247 api_mask
|= egl_g3d_st_api_bit(i
);
250 /* this is required by EGL, not by OpenGL ES */
251 if ((mode
->drawableType
& GLX_WINDOW_BIT
) && !mode
->doubleBufferMode
)
252 api_mask
&= ~(EGL_OPENGL_ES_BIT
| EGL_OPENGL_ES2_BIT
);
255 _eglLog(_EGL_DEBUG
, "no state tracker supports config 0x%x",
259 valid
= _eglConfigFromContextModesRec(&gconf
->base
,
260 mode
, api_mask
, api_mask
);
262 #ifdef EGL_MESA_screen_surface
263 /* check if scanout surface bit is set */
264 if (nconf
->scanout_bit
) {
265 EGLint val
= GET_CONFIG_ATTRIB(&gconf
->base
, EGL_SURFACE_TYPE
);
266 val
|= EGL_SCREEN_BIT_MESA
;
267 SET_CONFIG_ATTRIB(&gconf
->base
, EGL_SURFACE_TYPE
, val
);
270 valid
= _eglValidateConfig(&gconf
->base
, EGL_FALSE
);
273 _eglLog(_EGL_DEBUG
, "skip invalid config 0x%x", mode
->visualID
);
277 gconf
->native
= nconf
;
283 * Add configs to display and return the next config ID.
286 egl_g3d_add_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint id
)
288 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
289 const struct native_config
**native_configs
;
292 native_configs
= gdpy
->native
->get_configs(gdpy
->native
, &num_configs
);
295 free(native_configs
);
299 for (i
= 0; i
< num_configs
; i
++) {
300 struct egl_g3d_config
*gconf
;
302 gconf
= CALLOC_STRUCT(egl_g3d_config
);
304 _eglInitConfig(&gconf
->base
, dpy
, id
);
305 if (!egl_g3d_init_config(drv
, dpy
, &gconf
->base
, native_configs
[i
])) {
310 _eglAddConfig(dpy
, &gconf
->base
);
315 free(native_configs
);
320 egl_g3d_invalid_surface(struct native_display
*ndpy
,
321 struct native_surface
*nsurf
,
322 unsigned int seq_num
)
324 /* XXX not thread safe? */
325 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(nsurf
->user_data
);
326 struct egl_g3d_context
*gctx
;
329 * Some functions such as egl_g3d_copy_buffers create a temporary native
330 * surface. There is no gsurf associated with it.
332 gctx
= (gsurf
) ? egl_g3d_context(gsurf
->base
.CurrentContext
) : NULL
;
334 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
, gsurf
->stfbi
);
337 static struct native_event_handler egl_g3d_native_event_handler
= {
338 .invalid_surface
= egl_g3d_invalid_surface
342 egl_g3d_terminate(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
344 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
347 _eglReleaseDisplayResources(drv
, dpy
);
348 _eglCleanupDisplay(dpy
);
351 gdpy
->pipe
->destroy(gdpy
->pipe
);
354 for (i
= 0; i
< dpy
->NumScreens
; i
++) {
355 struct egl_g3d_screen
*gscr
= egl_g3d_screen(dpy
->Screens
[i
]);
356 free(gscr
->native_modes
);
363 egl_g3d_destroy_st_manager(gdpy
->smapi
);
366 gdpy
->native
->destroy(gdpy
->native
);
369 dpy
->DriverData
= NULL
;
375 egl_g3d_initialize(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
376 EGLint
*major
, EGLint
*minor
)
378 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
379 struct egl_g3d_display
*gdpy
;
381 /* the probe object is unlikely to be needed again */
382 egl_g3d_destroy_probe(drv
, dpy
);
384 gdpy
= CALLOC_STRUCT(egl_g3d_display
);
386 _eglError(EGL_BAD_ALLOC
, "eglInitialize");
389 dpy
->DriverData
= gdpy
;
391 gdpy
->native
= native_create_display(dpy
->NativeDisplay
,
392 &egl_g3d_native_event_handler
);
394 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(no usable display)");
398 gdpy
->native
->user_data
= (void *) dpy
;
400 egl_g3d_init_st(&gdrv
->base
);
401 dpy
->ClientAPIsMask
= gdrv
->api_mask
;
403 gdpy
->smapi
= egl_g3d_create_st_manager(dpy
);
405 _eglError(EGL_NOT_INITIALIZED
,
406 "eglInitialize(failed to create st manager)");
410 #ifdef EGL_MESA_screen_surface
411 /* enable MESA_screen_surface before adding (and validating) configs */
412 if (gdpy
->native
->modeset
) {
413 dpy
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
414 egl_g3d_add_screens(drv
, dpy
);
418 dpy
->Extensions
.KHR_image_base
= EGL_TRUE
;
419 if (gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_USE_NATIVE_BUFFER
))
420 dpy
->Extensions
.KHR_image_pixmap
= EGL_TRUE
;
422 if (egl_g3d_add_configs(drv
, dpy
, 1) == 1) {
423 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(unable to add configs)");
434 egl_g3d_terminate(drv
, dpy
);
439 egl_g3d_create_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
440 _EGLContext
*share
, const EGLint
*attribs
)
442 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
443 struct egl_g3d_context
*gshare
= egl_g3d_context(share
);
444 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
445 struct egl_g3d_context
*gctx
;
447 gctx
= CALLOC_STRUCT(egl_g3d_context
);
449 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
453 if (!_eglInitContext(&gctx
->base
, dpy
, conf
, attribs
)) {
458 gctx
->stapi
= egl_g3d_choose_st(drv
, &gctx
->base
);
464 gctx
->stctxi
= gctx
->stapi
->create_context(gctx
->stapi
, gdpy
->smapi
,
465 &gconf
->stvis
, (gshare
) ? gshare
->stctxi
: NULL
);
471 gctx
->stctxi
->st_manager_private
= (void *) &gctx
->base
;
480 destroy_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
482 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
484 /* FIXME a context might live longer than its display */
485 if (!dpy
->Initialized
)
486 _eglLog(_EGL_FATAL
, "destroy a context with an unitialized display");
488 gctx
->stctxi
->destroy(gctx
->stctxi
);
494 egl_g3d_destroy_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
496 if (!_eglIsContextBound(ctx
))
497 destroy_context(dpy
, ctx
);
501 struct egl_g3d_create_surface_arg
{
504 EGLNativeWindowType win
;
505 EGLNativePixmapType pix
;
510 egl_g3d_create_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
511 struct egl_g3d_create_surface_arg
*arg
,
512 const EGLint
*attribs
)
514 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
515 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
516 struct egl_g3d_surface
*gsurf
;
517 struct native_surface
*nsurf
;
522 err
= "eglCreateWindowSurface";
525 err
= "eglCreatePixmapSurface";
527 #ifdef EGL_MESA_screen_surface
528 case EGL_SCREEN_BIT_MESA
:
529 err
= "eglCreateScreenSurface";
533 err
= "eglCreateUnknownSurface";
537 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
539 _eglError(EGL_BAD_ALLOC
, err
);
543 if (!_eglInitSurface(&gsurf
->base
, dpy
, arg
->type
, conf
, attribs
)) {
548 /* create the native surface */
551 nsurf
= gdpy
->native
->create_window_surface(gdpy
->native
,
552 arg
->u
.win
, gconf
->native
);
555 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
,
556 arg
->u
.pix
, gconf
->native
);
558 #ifdef EGL_MESA_screen_surface
559 case EGL_SCREEN_BIT_MESA
:
560 /* prefer back buffer (move to _eglInitSurface?) */
561 gsurf
->base
.RenderBuffer
= EGL_BACK_BUFFER
;
562 nsurf
= gdpy
->native
->modeset
->create_scanout_surface(gdpy
->native
,
563 gconf
->native
, gsurf
->base
.Width
, gsurf
->base
.Height
);
575 /* initialize the geometry */
576 if (!nsurf
->validate(nsurf
, 0x0, &gsurf
->sequence_number
, NULL
,
577 &gsurf
->base
.Width
, &gsurf
->base
.Height
)) {
578 nsurf
->destroy(nsurf
);
583 gsurf
->stvis
= gconf
->stvis
;
584 if (gsurf
->base
.RenderBuffer
== EGL_SINGLE_BUFFER
)
585 gsurf
->stvis
.render_buffer
= ST_ATTACHMENT_FRONT_LEFT
;
587 gsurf
->stfbi
= egl_g3d_create_st_framebuffer(&gsurf
->base
);
589 nsurf
->destroy(nsurf
);
594 nsurf
->user_data
= &gsurf
->base
;
595 gsurf
->native
= nsurf
;
601 egl_g3d_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
602 _EGLConfig
*conf
, EGLNativeWindowType win
,
603 const EGLint
*attribs
)
605 struct egl_g3d_create_surface_arg arg
;
607 memset(&arg
, 0, sizeof(arg
));
608 arg
.type
= EGL_WINDOW_BIT
;
611 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
615 egl_g3d_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
616 _EGLConfig
*conf
, EGLNativePixmapType pix
,
617 const EGLint
*attribs
)
619 struct egl_g3d_create_surface_arg arg
;
621 memset(&arg
, 0, sizeof(arg
));
622 arg
.type
= EGL_PIXMAP_BIT
;
625 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
629 egl_g3d_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
630 _EGLConfig
*conf
, const EGLint
*attribs
)
632 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
633 struct egl_g3d_surface
*gsurf
;
635 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
637 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
641 if (!_eglInitSurface(&gsurf
->base
, dpy
, EGL_PBUFFER_BIT
, conf
, attribs
)) {
646 gsurf
->stvis
= gconf
->stvis
;
648 gsurf
->stfbi
= egl_g3d_create_st_framebuffer(&gsurf
->base
);
661 destroy_surface(_EGLDisplay
*dpy
, _EGLSurface
*surf
)
663 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
665 /* FIXME a surface might live longer than its display */
666 if (!dpy
->Initialized
)
667 _eglLog(_EGL_FATAL
, "destroy a surface with an unitialized display");
669 pipe_texture_reference(&gsurf
->render_texture
, NULL
);
670 egl_g3d_destroy_st_framebuffer(gsurf
->stfbi
);
672 gsurf
->native
->destroy(gsurf
->native
);
677 egl_g3d_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
679 if (!_eglIsSurfaceBound(surf
))
680 destroy_surface(dpy
, surf
);
685 egl_g3d_make_current(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
686 _EGLSurface
*draw
, _EGLSurface
*read
, _EGLContext
*ctx
)
688 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
689 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(draw
);
690 struct egl_g3d_surface
*gread
= egl_g3d_surface(read
);
691 struct egl_g3d_context
*old_gctx
;
692 EGLBoolean ok
= EGL_TRUE
;
694 /* bind the new context and return the "orphaned" one */
695 if (!_eglBindContext(&ctx
, &draw
, &read
))
697 old_gctx
= egl_g3d_context(ctx
);
700 /* flush old context */
701 old_gctx
->stctxi
->flush(old_gctx
->stctxi
,
702 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
706 ok
= gctx
->stapi
->make_current(gctx
->stapi
, gctx
->stctxi
,
707 (gdraw
) ? gdraw
->stfbi
: NULL
, (gread
) ? gread
->stfbi
: NULL
);
709 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
, gdraw
->stfbi
);
710 if (gread
!= gdraw
) {
711 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
,
715 if (gdraw
->base
.Type
== EGL_WINDOW_BIT
) {
716 gctx
->base
.WindowRenderBuffer
=
717 (gdraw
->stvis
.render_buffer
== ST_ATTACHMENT_FRONT_LEFT
) ?
718 EGL_SINGLE_BUFFER
: EGL_BACK_BUFFER
;
723 ok
= old_gctx
->stapi
->make_current(old_gctx
->stapi
, NULL
, NULL
, NULL
);
724 old_gctx
->base
.WindowRenderBuffer
= EGL_NONE
;
727 if (ctx
&& !_eglIsContextLinked(ctx
))
728 destroy_context(dpy
, ctx
);
729 if (draw
&& !_eglIsSurfaceLinked(draw
))
730 destroy_surface(dpy
, draw
);
731 if (read
&& read
!= draw
&& !_eglIsSurfaceLinked(read
))
732 destroy_surface(dpy
, read
);
738 egl_g3d_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
740 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
741 _EGLContext
*ctx
= _eglGetCurrentContext();
742 struct egl_g3d_context
*gctx
= NULL
;
744 /* no-op for pixmap or pbuffer surface */
745 if (gsurf
->base
.Type
== EGL_PIXMAP_BIT
||
746 gsurf
->base
.Type
== EGL_PBUFFER_BIT
)
749 /* or when the surface is single-buffered */
750 if (gsurf
->stvis
.render_buffer
== ST_ATTACHMENT_FRONT_LEFT
)
753 if (ctx
&& ctx
->DrawSurface
== surf
)
754 gctx
= egl_g3d_context(ctx
);
756 /* flush if the surface is current */
758 gctx
->stctxi
->flush(gctx
->stctxi
,
759 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
762 return gsurf
->native
->swap_buffers(gsurf
->native
);
766 * Find a config that supports the pixmap.
769 egl_g3d_find_pixmap_config(_EGLDisplay
*dpy
, EGLNativePixmapType pix
)
771 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
772 struct egl_g3d_config
*gconf
;
775 for (i
= 0; i
< dpy
->NumConfigs
; i
++) {
776 gconf
= egl_g3d_config(dpy
->Configs
[i
]);
777 if (gdpy
->native
->is_pixmap_supported(gdpy
->native
, pix
, gconf
->native
))
781 return (i
< dpy
->NumConfigs
) ? &gconf
->base
: NULL
;
785 * Get the pipe surface of the given attachment of the native surface.
787 static struct pipe_surface
*
788 get_pipe_surface(struct native_display
*ndpy
, struct native_surface
*nsurf
,
789 enum native_attachment natt
)
791 struct pipe_texture
*textures
[NUM_NATIVE_ATTACHMENTS
];
792 struct pipe_surface
*psurf
;
794 textures
[natt
] = NULL
;
795 nsurf
->validate(nsurf
, 1 << natt
, NULL
, textures
, NULL
, NULL
);
799 psurf
= ndpy
->screen
->get_tex_surface(ndpy
->screen
, textures
[natt
],
800 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
801 pipe_texture_reference(&textures
[natt
], NULL
);
807 egl_g3d_copy_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
808 EGLNativePixmapType target
)
810 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
811 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
812 _EGLContext
*ctx
= _eglGetCurrentContext();
813 struct egl_g3d_config
*gconf
;
814 struct native_surface
*nsurf
;
815 struct pipe_screen
*screen
= gdpy
->native
->screen
;
816 struct pipe_surface
*psurf
;
818 if (!gsurf
->render_texture
)
821 gconf
= egl_g3d_config(egl_g3d_find_pixmap_config(dpy
, target
));
823 return _eglError(EGL_BAD_NATIVE_PIXMAP
, "eglCopyBuffers");
825 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
,
826 target
, gconf
->native
);
828 return _eglError(EGL_BAD_NATIVE_PIXMAP
, "eglCopyBuffers");
830 /* flush if the surface is current */
831 if (ctx
&& ctx
->DrawSurface
== &gsurf
->base
) {
832 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
833 gctx
->stctxi
->flush(gctx
->stctxi
,
834 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
837 /* create a pipe context to copy surfaces */
840 gdpy
->native
->screen
->context_create(gdpy
->native
->screen
, NULL
);
845 psurf
= get_pipe_surface(gdpy
->native
, nsurf
, NATIVE_ATTACHMENT_FRONT_LEFT
);
847 struct pipe_surface
*psrc
;
849 psrc
= screen
->get_tex_surface(screen
, gsurf
->render_texture
,
850 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
852 gdpy
->pipe
->surface_copy(gdpy
->pipe
, psurf
, 0, 0,
853 psrc
, 0, 0, psurf
->width
, psurf
->height
);
854 pipe_surface_reference(&psrc
, NULL
);
856 nsurf
->flush_frontbuffer(nsurf
);
859 pipe_surface_reference(&psurf
, NULL
);
862 nsurf
->destroy(nsurf
);
868 egl_g3d_wait_client(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
870 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
871 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
872 struct pipe_screen
*screen
= gdpy
->native
->screen
;
873 struct pipe_fence_handle
*fence
= NULL
;
875 gctx
->stctxi
->flush(gctx
->stctxi
,
876 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, &fence
);
877 screen
->fence_finish(screen
, fence
, 0);
878 screen
->fence_reference(screen
, &fence
, NULL
);
884 egl_g3d_wait_native(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
886 _EGLContext
*ctx
= _eglGetCurrentContext();
888 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
889 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
891 if (ctx
&& ctx
->DrawSurface
) {
892 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(ctx
->DrawSurface
);
895 gsurf
->native
->wait(gsurf
->native
);
902 egl_g3d_get_proc_address(_EGLDriver
*drv
, const char *procname
)
904 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
908 /* in case this is called before a display is initialized */
909 egl_g3d_init_st(&gdrv
->base
);
911 for (i
= 0; i
< ST_API_COUNT
; i
++) {
912 struct st_api
*stapi
= gdrv
->stapis
[i
];
914 proc
= (_EGLProc
) stapi
->get_proc_address(stapi
, procname
);
920 return (_EGLProc
) NULL
;
924 egl_g3d_bind_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
925 _EGLSurface
*surf
, EGLint buffer
)
927 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
928 _EGLContext
*es1
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
929 struct egl_g3d_context
*gctx
;
930 enum pipe_format internal_format
;
931 enum st_texture_type target
;
933 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
)
934 return _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
935 if (buffer
!= EGL_BACK_BUFFER
)
936 return _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
937 if (gsurf
->base
.BoundToTexture
)
938 return _eglError(EGL_BAD_ACCESS
, "eglBindTexImage");
940 switch (gsurf
->base
.TextureFormat
) {
941 case EGL_TEXTURE_RGB
:
942 internal_format
= PIPE_FORMAT_R8G8B8_UNORM
;
944 case EGL_TEXTURE_RGBA
:
945 internal_format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
948 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
951 switch (gsurf
->base
.TextureTarget
) {
953 target
= ST_TEXTURE_2D
;
956 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
961 if (!gsurf
->render_texture
)
964 /* flush properly if the surface is bound */
965 if (gsurf
->base
.CurrentContext
) {
966 gctx
= egl_g3d_context(gsurf
->base
.CurrentContext
);
967 gctx
->stctxi
->flush(gctx
->stctxi
,
968 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
971 gctx
= egl_g3d_context(es1
);
972 if (gctx
->stctxi
->teximage
) {
973 if (!gctx
->stctxi
->teximage(gctx
->stctxi
, target
,
974 gsurf
->base
.MipmapLevel
, internal_format
,
975 gsurf
->render_texture
, gsurf
->base
.MipmapTexture
))
977 gsurf
->base
.BoundToTexture
= EGL_TRUE
;
984 egl_g3d_release_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
985 _EGLSurface
*surf
, EGLint buffer
)
987 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
989 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
||
990 !gsurf
->base
.BoundToTexture
)
991 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
992 if (buffer
!= EGL_BACK_BUFFER
)
993 return _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
995 if (gsurf
->render_texture
) {
996 _EGLContext
*ctx
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
997 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
999 /* what if the context the surface binds to is no longer current? */
1001 gctx
->stctxi
->teximage(gctx
->stctxi
, ST_TEXTURE_2D
,
1002 gsurf
->base
.MipmapLevel
, PIPE_FORMAT_NONE
, NULL
, FALSE
);
1006 gsurf
->base
.BoundToTexture
= EGL_FALSE
;
1011 #ifdef EGL_MESA_screen_surface
1013 static _EGLSurface
*
1014 egl_g3d_create_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
1015 _EGLConfig
*conf
, const EGLint
*attribs
)
1017 struct egl_g3d_create_surface_arg arg
;
1019 memset(&arg
, 0, sizeof(arg
));
1020 arg
.type
= EGL_SCREEN_BIT_MESA
;
1022 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
1026 egl_g3d_show_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
1027 _EGLScreen
*scr
, _EGLSurface
*surf
,
1030 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
1031 struct egl_g3d_screen
*gscr
= egl_g3d_screen(scr
);
1032 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
1033 struct native_surface
*nsurf
;
1034 const struct native_mode
*nmode
;
1041 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
1042 if (gsurf
->base
.Type
!= EGL_SCREEN_BIT_MESA
)
1043 return _eglError(EGL_BAD_SURFACE
, "eglShowScreenSurfaceMESA");
1044 if (gsurf
->base
.Width
< mode
->Width
|| gsurf
->base
.Height
< mode
->Height
)
1045 return _eglError(EGL_BAD_MATCH
,
1046 "eglShowSurfaceMESA(surface smaller than mode size)");
1048 /* find the index of the mode */
1049 for (idx
= 0; idx
< gscr
->base
.NumModes
; idx
++)
1050 if (mode
== &gscr
->base
.Modes
[idx
])
1052 if (idx
>= gscr
->base
.NumModes
) {
1053 return _eglError(EGL_BAD_MODE_MESA
,
1054 "eglShowSurfaceMESA(unknown mode)");
1057 nsurf
= gsurf
->native
;
1058 nmode
= gscr
->native_modes
[idx
];
1062 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
1064 /* disable the screen */
1069 /* TODO surface panning by CRTC choosing */
1070 changed
= gdpy
->native
->modeset
->program(gdpy
->native
, 0, nsurf
,
1071 gscr
->base
.OriginX
, gscr
->base
.OriginY
, &gscr
->native
, 1, nmode
);
1073 gscr
->base
.CurrentSurface
= &gsurf
->base
;
1074 gscr
->base
.CurrentMode
= mode
;
1080 #endif /* EGL_MESA_screen_surface */
1083 egl_g3d_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
1085 struct native_probe
*nprobe
;
1086 enum native_probe_result res
;
1089 nprobe
= egl_g3d_get_probe(drv
, dpy
);
1090 res
= native_get_probe_result(nprobe
);
1093 case NATIVE_PROBE_UNKNOWN
:
1097 case NATIVE_PROBE_FALLBACK
:
1100 case NATIVE_PROBE_SUPPORTED
:
1103 case NATIVE_PROBE_EXACT
:
1112 egl_g3d_unload(_EGLDriver
*drv
)
1114 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
1117 for (i
= 0; i
< ST_API_COUNT
; i
++) {
1118 if (gdrv
->stapis
[i
])
1119 gdrv
->stapis
[i
]->destroy(gdrv
->stapis
[i
]);
1122 egl_g3d_destroy_probe(drv
, NULL
);
1127 _eglMain(const char *args
)
1129 static char driver_name
[64];
1130 struct egl_g3d_driver
*gdrv
;
1132 snprintf(driver_name
, sizeof(driver_name
),
1133 "Gallium/%s", native_get_name());
1135 gdrv
= CALLOC_STRUCT(egl_g3d_driver
);
1139 _eglInitDriverFallbacks(&gdrv
->base
);
1141 gdrv
->base
.API
.Initialize
= egl_g3d_initialize
;
1142 gdrv
->base
.API
.Terminate
= egl_g3d_terminate
;
1143 gdrv
->base
.API
.CreateContext
= egl_g3d_create_context
;
1144 gdrv
->base
.API
.DestroyContext
= egl_g3d_destroy_context
;
1145 gdrv
->base
.API
.CreateWindowSurface
= egl_g3d_create_window_surface
;
1146 gdrv
->base
.API
.CreatePixmapSurface
= egl_g3d_create_pixmap_surface
;
1147 gdrv
->base
.API
.CreatePbufferSurface
= egl_g3d_create_pbuffer_surface
;
1148 gdrv
->base
.API
.DestroySurface
= egl_g3d_destroy_surface
;
1149 gdrv
->base
.API
.MakeCurrent
= egl_g3d_make_current
;
1150 gdrv
->base
.API
.SwapBuffers
= egl_g3d_swap_buffers
;
1151 gdrv
->base
.API
.CopyBuffers
= egl_g3d_copy_buffers
;
1152 gdrv
->base
.API
.WaitClient
= egl_g3d_wait_client
;
1153 gdrv
->base
.API
.WaitNative
= egl_g3d_wait_native
;
1154 gdrv
->base
.API
.GetProcAddress
= egl_g3d_get_proc_address
;
1156 gdrv
->base
.API
.BindTexImage
= egl_g3d_bind_tex_image
;
1157 gdrv
->base
.API
.ReleaseTexImage
= egl_g3d_release_tex_image
;
1159 gdrv
->base
.API
.CreateImageKHR
= egl_g3d_create_image
;
1160 gdrv
->base
.API
.DestroyImageKHR
= egl_g3d_destroy_image
;
1162 #ifdef EGL_MESA_screen_surface
1163 gdrv
->base
.API
.CreateScreenSurfaceMESA
= egl_g3d_create_screen_surface
;
1164 gdrv
->base
.API
.ShowScreenSurfaceMESA
= egl_g3d_show_screen_surface
;
1167 gdrv
->base
.Name
= driver_name
;
1168 gdrv
->base
.Probe
= egl_g3d_probe
;
1169 gdrv
->base
.Unload
= egl_g3d_unload
;
1171 /* the key is " EGL G3D" */
1172 gdrv
->probe_key
= 0x0E61063D;