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_image.h"
43 * Validate the draw/read surfaces of the context.
46 egl_g3d_validate_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
48 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
49 struct pipe_screen
*screen
= gdpy
->native
->screen
;
50 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
51 const uint st_att_map
[NUM_NATIVE_ATTACHMENTS
] = {
52 ST_SURFACE_FRONT_LEFT
,
54 ST_SURFACE_FRONT_RIGHT
,
55 ST_SURFACE_BACK_RIGHT
,
57 EGLint num_surfaces
, s
;
59 /* validate draw and/or read buffers */
60 num_surfaces
= (gctx
->base
.ReadSurface
== gctx
->base
.DrawSurface
) ? 1 : 2;
61 for (s
= 0; s
< num_surfaces
; s
++) {
62 struct pipe_texture
*textures
[NUM_NATIVE_ATTACHMENTS
];
63 struct egl_g3d_surface
*gsurf
;
64 struct egl_g3d_buffer
*gbuf
;
68 gsurf
= egl_g3d_surface(gctx
->base
.DrawSurface
);
72 gsurf
= egl_g3d_surface(gctx
->base
.ReadSurface
);
76 if (!gctx
->force_validate
) {
79 gsurf
->native
->validate(gsurf
->native
, gbuf
->attachment_mask
,
80 &seq_num
, NULL
, NULL
, NULL
);
82 if (gsurf
->sequence_number
== seq_num
)
86 pipe_surface_reference(&gsurf
->render_surface
, NULL
);
87 memset(textures
, 0, sizeof(textures
));
89 gsurf
->native
->validate(gsurf
->native
, gbuf
->attachment_mask
,
90 &gsurf
->sequence_number
, textures
,
91 &gsurf
->base
.Width
, &gsurf
->base
.Height
);
92 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
93 struct pipe_texture
*pt
= textures
[att
];
94 struct pipe_surface
*ps
;
96 if (native_attachment_mask_test(gbuf
->attachment_mask
, att
) && pt
) {
97 ps
= screen
->get_tex_surface(screen
, pt
, 0, 0, 0,
98 PIPE_BUFFER_USAGE_GPU_READ
|
99 PIPE_BUFFER_USAGE_GPU_WRITE
);
100 gctx
->stapi
->st_set_framebuffer_surface(gbuf
->st_fb
,
101 st_att_map
[att
], ps
);
103 if (gsurf
->render_att
== att
)
104 pipe_surface_reference(&gsurf
->render_surface
, ps
);
106 pipe_surface_reference(&ps
, NULL
);
107 pipe_texture_reference(&pt
, NULL
);
111 gctx
->stapi
->st_resize_framebuffer(gbuf
->st_fb
,
112 gsurf
->base
.Width
, gsurf
->base
.Height
);
115 gctx
->force_validate
= EGL_FALSE
;
120 * Create a st_framebuffer.
122 static struct st_framebuffer
*
123 create_framebuffer(_EGLContext
*ctx
, _EGLSurface
*surf
)
125 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
126 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
127 struct egl_g3d_config
*gconf
= egl_g3d_config(gsurf
->base
.Config
);
129 return gctx
->stapi
->st_create_framebuffer(&gconf
->native
->mode
,
130 gconf
->native
->color_format
, gconf
->native
->depth_format
,
131 gconf
->native
->stencil_format
,
132 gsurf
->base
.Width
, gsurf
->base
.Height
, &gsurf
->base
);
136 * Update the attachments of draw/read surfaces.
139 egl_g3d_route_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
141 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
144 /* route draw and read buffers' attachments */
145 for (s
= 0; s
< 2; s
++) {
146 struct egl_g3d_surface
*gsurf
;
147 struct egl_g3d_buffer
*gbuf
;
150 gsurf
= egl_g3d_surface(gctx
->base
.DrawSurface
);
154 gsurf
= egl_g3d_surface(gctx
->base
.ReadSurface
);
158 gbuf
->attachment_mask
= (1 << gsurf
->render_att
);
160 /* FIXME OpenGL defaults to draw the front or back buffer when the
161 * context is single-buffered or double-buffered respectively. In EGL,
162 * however, the buffer to be drawn is determined by the surface, instead
163 * of the context. As a result, rendering to a pixmap surface with a
164 * double-buffered context does not work as expected.
166 * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
167 * NATIVE_ATTACHMENT_FRONT_LEFT);
171 * FIXME If the back buffer is asked for here, and the front buffer is
172 * later needed by the client API (e.g. glDrawBuffer is called to draw
173 * the front buffer), it will create a new pipe texture and draw there.
174 * One fix is to ask for both buffers here, but it would be a waste if
175 * the front buffer is never used. A better fix is to add a callback to
176 * the pipe screen with context private (just like flush_frontbuffer).
182 * Reallocate the context's framebuffers after draw/read surfaces change.
185 egl_g3d_realloc_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
187 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
188 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(gctx
->base
.DrawSurface
);
189 struct egl_g3d_surface
*gread
= egl_g3d_surface(gctx
->base
.ReadSurface
);
191 /* unreference the old framebuffers */
192 if (gctx
->draw
.st_fb
) {
193 EGLBoolean is_equal
= (gctx
->draw
.st_fb
== gctx
->read
.st_fb
);
196 priv
= gctx
->stapi
->st_framebuffer_private(gctx
->draw
.st_fb
);
197 if (!gdraw
|| priv
!= (void *) &gdraw
->base
) {
198 gctx
->stapi
->st_unreference_framebuffer(gctx
->draw
.st_fb
);
199 gctx
->draw
.st_fb
= NULL
;
200 gctx
->draw
.attachment_mask
= 0x0;
204 gctx
->read
.st_fb
= NULL
;
205 gctx
->draw
.attachment_mask
= 0x0;
208 priv
= gctx
->stapi
->st_framebuffer_private(gctx
->read
.st_fb
);
209 if (!gread
|| priv
!= (void *) &gread
->base
) {
210 gctx
->stapi
->st_unreference_framebuffer(gctx
->read
.st_fb
);
211 gctx
->read
.st_fb
= NULL
;
212 gctx
->draw
.attachment_mask
= 0x0;
220 /* create the draw fb */
221 if (!gctx
->draw
.st_fb
) {
222 gctx
->draw
.st_fb
= create_framebuffer(&gctx
->base
, &gdraw
->base
);
223 if (!gctx
->draw
.st_fb
)
227 /* create the read fb */
228 if (!gctx
->read
.st_fb
) {
229 if (gread
!= gdraw
) {
230 gctx
->read
.st_fb
= create_framebuffer(&gctx
->base
, &gread
->base
);
231 if (!gctx
->read
.st_fb
) {
232 gctx
->stapi
->st_unreference_framebuffer(gctx
->draw
.st_fb
);
233 gctx
->draw
.st_fb
= NULL
;
238 /* there is no st_reference_framebuffer... */
239 gctx
->read
.st_fb
= gctx
->draw
.st_fb
;
243 egl_g3d_route_context(dpy
, &gctx
->base
);
244 gctx
->force_validate
= EGL_TRUE
;
250 * Return the state tracker for the given context.
252 static const struct egl_g3d_st
*
253 egl_g3d_choose_st(_EGLDriver
*drv
, _EGLContext
*ctx
)
255 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
256 const struct egl_g3d_st
*stapi
;
259 switch (ctx
->ClientAPI
) {
260 case EGL_OPENGL_ES_API
:
261 switch (ctx
->ClientVersion
) {
263 idx
= EGL_G3D_ST_OPENGL_ES
;
266 idx
= EGL_G3D_ST_OPENGL_ES2
;
269 _eglLog(_EGL_WARNING
, "unknown client version %d",
275 idx
= EGL_G3D_ST_OPENVG
;
278 idx
= EGL_G3D_ST_OPENGL
;
281 _eglLog(_EGL_WARNING
, "unknown client API 0x%04x", ctx
->ClientAPI
);
285 stapi
= (idx
>= 0) ? gdrv
->stapis
[idx
] : NULL
;
290 * Initialize the state trackers.
293 egl_g3d_init_st(_EGLDriver
*drv
)
295 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
298 /* already initialized */
302 for (i
= 0; i
< NUM_EGL_G3D_STS
; i
++) {
303 gdrv
->stapis
[i
] = egl_g3d_get_st(i
);
305 gdrv
->api_mask
|= gdrv
->stapis
[i
]->api_bit
;
309 _eglLog(_EGL_DEBUG
, "Driver API mask: 0x%x", gdrv
->api_mask
);
311 _eglLog(_EGL_WARNING
, "No supported client API");
315 * Get the probe object of the display.
317 * Note that this function may be called before the display is initialized.
319 static struct native_probe
*
320 egl_g3d_get_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
322 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
323 struct native_probe
*nprobe
;
325 nprobe
= (struct native_probe
*) _eglGetProbeCache(gdrv
->probe_key
);
326 if (!nprobe
|| nprobe
->display
!= dpy
->NativeDisplay
) {
328 nprobe
->destroy(nprobe
);
329 nprobe
= native_create_probe(dpy
->NativeDisplay
);
330 _eglSetProbeCache(gdrv
->probe_key
, (void *) nprobe
);
337 * Destroy the probe object of the display. The display may be NULL.
339 * Note that this function may be called before the display is initialized.
342 egl_g3d_destroy_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
344 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
345 struct native_probe
*nprobe
;
347 nprobe
= (struct native_probe
*) _eglGetProbeCache(gdrv
->probe_key
);
348 if (nprobe
&& (!dpy
|| nprobe
->display
== dpy
->NativeDisplay
)) {
349 nprobe
->destroy(nprobe
);
350 _eglSetProbeCache(gdrv
->probe_key
, NULL
);
355 * Return an API mask that consists of the state trackers that supports the
358 * FIXME add st_is_mode_supported()?
361 get_mode_api_mask(const __GLcontextModes
*mode
, EGLint api_mask
)
365 /* OpenGL ES 1.x and 2.x are checked together */
366 check
= EGL_OPENGL_ES_BIT
| EGL_OPENGL_ES2_BIT
;
367 if (api_mask
& check
) {
368 /* this is required by EGL, not by OpenGL ES */
369 if (mode
->drawableType
& GLX_WINDOW_BIT
&& !mode
->doubleBufferMode
)
373 check
= EGL_OPENVG_BIT
;
374 if (api_mask
& check
) {
375 /* vega st needs the depth/stencil rb */
376 if (!mode
->depthBits
&& !mode
->stencilBits
)
383 #ifdef EGL_MESA_screen_surface
386 egl_g3d_add_screens(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
388 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
389 const struct native_connector
**native_connectors
;
390 EGLint num_connectors
, i
;
393 gdpy
->native
->modeset
->get_connectors(gdpy
->native
, &num_connectors
, NULL
);
394 if (!num_connectors
) {
395 if (native_connectors
)
396 free(native_connectors
);
400 for (i
= 0; i
< num_connectors
; i
++) {
401 const struct native_connector
*nconn
= native_connectors
[i
];
402 struct egl_g3d_screen
*gscr
;
403 const struct native_mode
**native_modes
;
406 /* TODO support for hotplug */
408 gdpy
->native
->modeset
->get_modes(gdpy
->native
, nconn
, &num_modes
);
415 gscr
= CALLOC_STRUCT(egl_g3d_screen
);
421 _eglInitScreen(&gscr
->base
);
423 for (j
= 0; j
< num_modes
; j
++) {
424 const struct native_mode
*nmode
= native_modes
[j
];
427 mode
= _eglAddNewMode(&gscr
->base
, nmode
->width
, nmode
->height
,
428 nmode
->refresh_rate
, nmode
->desc
);
431 /* gscr->native_modes and gscr->base.Modes should be consistent */
432 assert(mode
== &gscr
->base
.Modes
[j
]);
435 gscr
->native
= nconn
;
436 gscr
->native_modes
= native_modes
;
438 _eglAddScreen(dpy
, &gscr
->base
);
441 free(native_connectors
);
444 #endif /* EGL_MESA_screen_surface */
447 * Add configs to display and return the next config ID.
450 egl_g3d_add_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint id
)
452 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
453 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
454 const struct native_config
**native_configs
;
457 native_configs
= gdpy
->native
->get_configs(gdpy
->native
,
461 free(native_configs
);
465 for (i
= 0; i
< num_configs
; i
++) {
467 struct egl_g3d_config
*gconf
;
470 gconf
= CALLOC_STRUCT(egl_g3d_config
);
474 _eglInitConfig(&gconf
->base
, dpy
, id
);
476 api_mask
= get_mode_api_mask(&native_configs
[i
]->mode
, gdrv
->api_mask
);
478 _eglLog(_EGL_DEBUG
, "no state tracker supports config 0x%x",
479 native_configs
[i
]->mode
.visualID
);
482 valid
= _eglConfigFromContextModesRec(&gconf
->base
,
483 &native_configs
[i
]->mode
, api_mask
, api_mask
);
485 #ifdef EGL_MESA_screen_surface
486 /* check if scanout surface bit is set */
487 if (native_configs
[i
]->scanout_bit
) {
488 EGLint val
= GET_CONFIG_ATTRIB(&gconf
->base
, EGL_SURFACE_TYPE
);
489 val
|= EGL_SCREEN_BIT_MESA
;
490 SET_CONFIG_ATTRIB(&gconf
->base
, EGL_SURFACE_TYPE
, val
);
493 valid
= _eglValidateConfig(&gconf
->base
, EGL_FALSE
);
496 _eglLog(_EGL_DEBUG
, "skip invalid config 0x%x",
497 native_configs
[i
]->mode
.visualID
);
502 gconf
->native
= native_configs
[i
];
503 _eglAddConfig(dpy
, &gconf
->base
);
507 free(native_configs
);
512 * Flush the front buffer of the context's draw surface.
515 egl_g3d_flush_frontbuffer(struct pipe_screen
*screen
,
516 struct pipe_surface
*surf
, void *context_private
)
518 struct egl_g3d_context
*gctx
= egl_g3d_context(context_private
);
519 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(gctx
->base
.DrawSurface
);
522 gsurf
->native
->flush_frontbuffer(gsurf
->native
);
526 * Re-validate the context.
529 egl_g3d_update_buffer(struct pipe_screen
*screen
, void *context_private
)
531 struct egl_g3d_context
*gctx
= egl_g3d_context(context_private
);
532 egl_g3d_validate_context(gctx
->base
.Resource
.Display
, &gctx
->base
);
536 egl_g3d_invalid_surface(struct native_display
*ndpy
,
537 struct native_surface
*nsurf
,
538 unsigned int seq_num
)
540 /* XXX not thread safe? */
541 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(nsurf
->user_data
);
542 struct egl_g3d_context
*gctx
= egl_g3d_context(gsurf
->base
.CurrentContext
);
544 /* set force_validate to skip an unnecessary check */
546 gctx
->force_validate
= TRUE
;
549 static struct native_event_handler egl_g3d_native_event_handler
= {
550 .invalid_surface
= egl_g3d_invalid_surface
554 egl_g3d_terminate(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
556 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
559 _eglReleaseDisplayResources(drv
, dpy
);
560 _eglCleanupDisplay(dpy
);
563 for (i
= 0; i
< dpy
->NumScreens
; i
++) {
564 struct egl_g3d_screen
*gscr
= egl_g3d_screen(dpy
->Screens
[i
]);
565 free(gscr
->native_modes
);
572 gdpy
->native
->destroy(gdpy
->native
);
575 dpy
->DriverData
= NULL
;
581 egl_g3d_initialize(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
582 EGLint
*major
, EGLint
*minor
)
584 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
585 struct egl_g3d_display
*gdpy
;
587 /* the probe object is unlikely to be needed again */
588 egl_g3d_destroy_probe(drv
, dpy
);
590 gdpy
= CALLOC_STRUCT(egl_g3d_display
);
592 _eglError(EGL_BAD_ALLOC
, "eglInitialize");
595 dpy
->DriverData
= gdpy
;
597 gdpy
->native
= native_create_display(dpy
->NativeDisplay
,
598 &egl_g3d_native_event_handler
);
600 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(no usable display)");
604 gdpy
->native
->user_data
= (void *) dpy
;
605 gdpy
->native
->screen
->flush_frontbuffer
= egl_g3d_flush_frontbuffer
;
606 gdpy
->native
->screen
->update_buffer
= egl_g3d_update_buffer
;
608 egl_g3d_init_st(&gdrv
->base
);
609 dpy
->ClientAPIsMask
= gdrv
->api_mask
;
611 #ifdef EGL_MESA_screen_surface
612 /* enable MESA_screen_surface before adding (and validating) configs */
613 if (gdpy
->native
->modeset
) {
614 dpy
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
615 egl_g3d_add_screens(drv
, dpy
);
619 dpy
->Extensions
.KHR_image_base
= EGL_TRUE
;
620 if (gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_USE_NATIVE_BUFFER
))
621 dpy
->Extensions
.KHR_image_pixmap
= EGL_TRUE
;
623 if (egl_g3d_add_configs(drv
, dpy
, 1) == 1) {
624 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(unable to add configs)");
635 egl_g3d_terminate(drv
, dpy
);
640 egl_g3d_create_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
641 _EGLContext
*share
, const EGLint
*attribs
)
643 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
644 struct egl_g3d_context
*gshare
= egl_g3d_context(share
);
645 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
646 struct egl_g3d_context
*gctx
;
647 const __GLcontextModes
*mode
;
649 gctx
= CALLOC_STRUCT(egl_g3d_context
);
651 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
655 if (!_eglInitContext(&gctx
->base
, dpy
, conf
, attribs
)) {
660 gctx
->stapi
= egl_g3d_choose_st(drv
, &gctx
->base
);
666 mode
= &gconf
->native
->mode
;
668 gctx
->pipe
= gdpy
->native
->screen
->context_create(
669 gdpy
->native
->screen
,
670 (void *) &gctx
->base
);
677 gctx
->st_ctx
= gctx
->stapi
->st_create_context(gctx
->pipe
, mode
,
678 (gshare
) ? gshare
->st_ctx
: NULL
);
680 gctx
->pipe
->destroy(gctx
->pipe
);
692 destroy_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
694 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
696 /* FIXME a context might live longer than its display */
697 if (!dpy
->Initialized
)
698 _eglLog(_EGL_FATAL
, "destroy a context with an unitialized display");
700 egl_g3d_realloc_context(dpy
, &gctx
->base
);
701 /* it will destroy the associated pipe context */
702 gctx
->stapi
->st_destroy_context(gctx
->st_ctx
);
708 egl_g3d_destroy_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
710 if (!_eglIsContextBound(ctx
))
711 destroy_context(dpy
, ctx
);
715 struct egl_g3d_create_surface_arg
{
718 EGLNativeWindowType win
;
719 EGLNativePixmapType pix
;
724 egl_g3d_create_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
725 struct egl_g3d_create_surface_arg
*arg
,
726 const EGLint
*attribs
)
728 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
729 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
730 struct egl_g3d_surface
*gsurf
;
731 struct native_surface
*nsurf
;
736 err
= "eglCreateWindowSurface";
739 err
= "eglCreatePixmapSurface";
741 case EGL_PBUFFER_BIT
:
742 err
= "eglCreatePBufferSurface";
744 #ifdef EGL_MESA_screen_surface
745 case EGL_SCREEN_BIT_MESA
:
746 err
= "eglCreateScreenSurface";
750 err
= "eglCreateUnknownSurface";
754 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
756 _eglError(EGL_BAD_ALLOC
, err
);
760 if (!_eglInitSurface(&gsurf
->base
, dpy
, arg
->type
, conf
, attribs
)) {
765 /* create the native surface */
768 nsurf
= gdpy
->native
->create_window_surface(gdpy
->native
,
769 arg
->u
.win
, gconf
->native
);
772 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
,
773 arg
->u
.pix
, gconf
->native
);
775 case EGL_PBUFFER_BIT
:
776 nsurf
= gdpy
->native
->create_pbuffer_surface(gdpy
->native
,
777 gconf
->native
, gsurf
->base
.Width
, gsurf
->base
.Height
);
779 #ifdef EGL_MESA_screen_surface
780 case EGL_SCREEN_BIT_MESA
:
781 /* prefer back buffer (move to _eglInitSurface?) */
782 gsurf
->base
.RenderBuffer
= EGL_BACK_BUFFER
;
783 nsurf
= gdpy
->native
->modeset
->create_scanout_surface(gdpy
->native
,
784 gconf
->native
, gsurf
->base
.Width
, gsurf
->base
.Height
);
796 /* initialize the geometry */
797 if (!nsurf
->validate(nsurf
, 0x0, &gsurf
->sequence_number
, NULL
,
798 &gsurf
->base
.Width
, &gsurf
->base
.Height
)) {
799 nsurf
->destroy(nsurf
);
804 nsurf
->user_data
= &gsurf
->base
;
805 gsurf
->native
= nsurf
;
807 gsurf
->render_att
= (gsurf
->base
.RenderBuffer
== EGL_SINGLE_BUFFER
) ?
808 NATIVE_ATTACHMENT_FRONT_LEFT
: NATIVE_ATTACHMENT_BACK_LEFT
;
809 if (!gconf
->native
->mode
.doubleBufferMode
)
810 gsurf
->render_att
= NATIVE_ATTACHMENT_FRONT_LEFT
;
816 egl_g3d_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
817 _EGLConfig
*conf
, EGLNativeWindowType win
,
818 const EGLint
*attribs
)
820 struct egl_g3d_create_surface_arg arg
;
822 memset(&arg
, 0, sizeof(arg
));
823 arg
.type
= EGL_WINDOW_BIT
;
826 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
830 egl_g3d_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
831 _EGLConfig
*conf
, EGLNativePixmapType pix
,
832 const EGLint
*attribs
)
834 struct egl_g3d_create_surface_arg arg
;
836 memset(&arg
, 0, sizeof(arg
));
837 arg
.type
= EGL_PIXMAP_BIT
;
840 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
844 egl_g3d_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
845 _EGLConfig
*conf
, const EGLint
*attribs
)
847 struct egl_g3d_create_surface_arg arg
;
849 memset(&arg
, 0, sizeof(arg
));
850 arg
.type
= EGL_PBUFFER_BIT
;
852 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
859 destroy_surface(_EGLDisplay
*dpy
, _EGLSurface
*surf
)
861 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
863 /* FIXME a surface might live longer than its display */
864 if (!dpy
->Initialized
)
865 _eglLog(_EGL_FATAL
, "destroy a surface with an unitialized display");
867 pipe_surface_reference(&gsurf
->render_surface
, NULL
);
868 gsurf
->native
->destroy(gsurf
->native
);
873 egl_g3d_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
875 if (!_eglIsSurfaceBound(surf
))
876 destroy_surface(dpy
, surf
);
881 egl_g3d_make_current(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
882 _EGLSurface
*draw
, _EGLSurface
*read
, _EGLContext
*ctx
)
884 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
885 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(draw
);
886 struct egl_g3d_context
*old_gctx
;
887 EGLBoolean ok
= EGL_TRUE
;
889 /* bind the new context and return the "orphaned" one */
890 if (!_eglBindContext(&ctx
, &draw
, &read
))
892 old_gctx
= egl_g3d_context(ctx
);
895 /* flush old context */
896 old_gctx
->stapi
->st_flush(old_gctx
->st_ctx
,
897 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
900 * The old context is no longer current, and egl_g3d_realloc_context()
901 * should be called to destroy the framebuffers. However, it is possible
902 * that it will be made current again with the same draw/read surfaces.
903 * It might be better to keep it around.
908 ok
= egl_g3d_realloc_context(dpy
, &gctx
->base
);
910 ok
= gctx
->stapi
->st_make_current(gctx
->st_ctx
,
911 gctx
->draw
.st_fb
, gctx
->read
.st_fb
);
913 egl_g3d_validate_context(dpy
, &gctx
->base
);
914 if (gdraw
->base
.Type
== EGL_WINDOW_BIT
) {
915 gctx
->base
.WindowRenderBuffer
=
916 (gdraw
->render_att
== NATIVE_ATTACHMENT_FRONT_LEFT
) ?
917 EGL_SINGLE_BUFFER
: EGL_BACK_BUFFER
;
923 ok
= old_gctx
->stapi
->st_make_current(NULL
, NULL
, NULL
);
924 old_gctx
->base
.WindowRenderBuffer
= EGL_NONE
;
927 if (ctx
&& !_eglIsContextLinked(ctx
))
928 destroy_context(dpy
, ctx
);
929 if (draw
&& !_eglIsSurfaceLinked(draw
))
930 destroy_surface(dpy
, draw
);
931 if (read
&& read
!= draw
&& !_eglIsSurfaceLinked(read
))
932 destroy_surface(dpy
, read
);
938 egl_g3d_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
940 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
941 _EGLContext
*ctx
= _eglGetCurrentContext();
942 struct egl_g3d_context
*gctx
= NULL
;
944 /* no-op for pixmap or pbuffer surface */
945 if (gsurf
->base
.Type
== EGL_PIXMAP_BIT
||
946 gsurf
->base
.Type
== EGL_PBUFFER_BIT
)
949 /* or when the surface is single-buffered */
950 if (gsurf
->render_att
== NATIVE_ATTACHMENT_FRONT_LEFT
)
953 if (ctx
&& ctx
->DrawSurface
== surf
)
954 gctx
= egl_g3d_context(ctx
);
956 /* flush if the surface is current */
958 gctx
->stapi
->st_notify_swapbuffers(gctx
->draw
.st_fb
);
960 return gsurf
->native
->swap_buffers(gsurf
->native
);
964 * Find a config that supports the pixmap.
967 egl_g3d_find_pixmap_config(_EGLDisplay
*dpy
, EGLNativePixmapType pix
)
969 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
970 struct egl_g3d_config
*gconf
;
973 for (i
= 0; i
< dpy
->NumConfigs
; i
++) {
974 gconf
= egl_g3d_config(dpy
->Configs
[i
]);
975 if (gdpy
->native
->is_pixmap_supported(gdpy
->native
, pix
, gconf
->native
))
979 return (i
< dpy
->NumConfigs
) ? &gconf
->base
: NULL
;
983 * Get the pipe surface of the given attachment of the native surface.
985 static struct pipe_surface
*
986 get_pipe_surface(struct native_display
*ndpy
, struct native_surface
*nsurf
,
987 enum native_attachment natt
)
989 struct pipe_texture
*textures
[NUM_NATIVE_ATTACHMENTS
];
990 struct pipe_surface
*psurf
;
992 textures
[natt
] = NULL
;
993 nsurf
->validate(nsurf
, 1 << natt
, NULL
, textures
, NULL
, NULL
);
997 psurf
= ndpy
->screen
->get_tex_surface(ndpy
->screen
, textures
[natt
],
998 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
);
999 pipe_texture_reference(&textures
[natt
], NULL
);
1005 egl_g3d_copy_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
1006 EGLNativePixmapType target
)
1008 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
1009 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
1010 _EGLContext
*ctx
= _eglGetCurrentContext();
1011 struct egl_g3d_config
*gconf
;
1012 struct native_surface
*nsurf
;
1013 struct pipe_screen
*screen
= gdpy
->native
->screen
;
1014 struct pipe_surface
*psurf
;
1016 if (!gsurf
->render_surface
)
1019 gconf
= egl_g3d_config(egl_g3d_find_pixmap_config(dpy
, target
));
1021 return _eglError(EGL_BAD_NATIVE_PIXMAP
, "eglCopyBuffers");
1023 nsurf
= gdpy
->native
->create_pixmap_surface(gdpy
->native
,
1024 target
, gconf
->native
);
1026 return _eglError(EGL_BAD_NATIVE_PIXMAP
, "eglCopyBuffers");
1028 /* flush if the surface is current */
1029 if (ctx
&& ctx
->DrawSurface
== &gsurf
->base
) {
1030 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
1031 gctx
->stapi
->st_flush(gctx
->st_ctx
,
1032 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
1035 psurf
= get_pipe_surface(gdpy
->native
, nsurf
, NATIVE_ATTACHMENT_FRONT_LEFT
);
1037 struct pipe_context pipe
;
1040 * XXX This is hacky. If we might allow the EGLDisplay to create a pipe
1041 * context of its own and use the blitter context for this.
1043 memset(&pipe
, 0, sizeof(pipe
));
1044 pipe
.screen
= screen
;
1046 util_surface_copy(&pipe
, FALSE
, psurf
, 0, 0,
1047 gsurf
->render_surface
, 0, 0, psurf
->width
, psurf
->height
);
1049 pipe_surface_reference(&psurf
, NULL
);
1050 nsurf
->flush_frontbuffer(nsurf
);
1053 nsurf
->destroy(nsurf
);
1059 egl_g3d_wait_client(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
1061 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
1062 gctx
->stapi
->st_finish(gctx
->st_ctx
);
1067 egl_g3d_wait_native(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
1069 _EGLContext
*ctx
= _eglGetCurrentContext();
1071 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
1072 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
1074 if (ctx
&& ctx
->DrawSurface
) {
1075 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(ctx
->DrawSurface
);
1076 gsurf
->native
->wait(gsurf
->native
);
1083 egl_g3d_get_proc_address(_EGLDriver
*drv
, const char *procname
)
1085 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
1089 /* in case this is called before a display is initialized */
1090 egl_g3d_init_st(&gdrv
->base
);
1092 for (i
= 0; i
< NUM_EGL_G3D_STS
; i
++) {
1093 const struct egl_g3d_st
*stapi
= gdrv
->stapis
[i
];
1095 proc
= (_EGLProc
) stapi
->st_get_proc_address(procname
);
1101 return (_EGLProc
) NULL
;
1105 egl_g3d_bind_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
1106 _EGLSurface
*surf
, EGLint buffer
)
1108 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
1109 _EGLContext
*es1
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
1110 struct egl_g3d_context
*gctx
;
1111 enum pipe_format target_format
;
1114 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
)
1115 return _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
1116 if (buffer
!= EGL_BACK_BUFFER
)
1117 return _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
1118 if (gsurf
->base
.BoundToTexture
)
1119 return _eglError(EGL_BAD_ACCESS
, "eglBindTexImage");
1121 switch (gsurf
->base
.TextureFormat
) {
1122 case EGL_TEXTURE_RGB
:
1123 target_format
= PIPE_FORMAT_R8G8B8_UNORM
;
1125 case EGL_TEXTURE_RGBA
:
1126 target_format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
1129 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
1132 switch (gsurf
->base
.TextureTarget
) {
1133 case EGL_TEXTURE_2D
:
1134 target
= ST_TEXTURE_2D
;
1137 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
1142 if (!gsurf
->render_surface
)
1145 /* flush properly if the surface is bound */
1146 if (gsurf
->base
.CurrentContext
) {
1147 gctx
= egl_g3d_context(gsurf
->base
.CurrentContext
);
1148 gctx
->stapi
->st_flush(gctx
->st_ctx
,
1149 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
1152 gctx
= egl_g3d_context(es1
);
1153 gctx
->stapi
->st_bind_texture_surface(gsurf
->render_surface
,
1154 target
, gsurf
->base
.MipmapLevel
, target_format
);
1156 gsurf
->base
.BoundToTexture
= EGL_TRUE
;
1162 egl_g3d_release_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
1163 _EGLSurface
*surf
, EGLint buffer
)
1165 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
1167 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
||
1168 !gsurf
->base
.BoundToTexture
)
1169 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
1170 if (buffer
!= EGL_BACK_BUFFER
)
1171 return _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
1173 if (gsurf
->render_surface
) {
1174 _EGLContext
*ctx
= _eglGetAPIContext(EGL_OPENGL_ES_API
);
1175 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
1177 /* what if the context the surface binds to is no longer current? */
1179 gctx
->stapi
->st_unbind_texture_surface(gsurf
->render_surface
,
1180 ST_TEXTURE_2D
, gsurf
->base
.MipmapLevel
);
1183 gsurf
->base
.BoundToTexture
= EGL_FALSE
;
1188 #ifdef EGL_MESA_screen_surface
1190 static _EGLSurface
*
1191 egl_g3d_create_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
1192 _EGLConfig
*conf
, const EGLint
*attribs
)
1194 struct egl_g3d_create_surface_arg arg
;
1196 memset(&arg
, 0, sizeof(arg
));
1197 arg
.type
= EGL_SCREEN_BIT_MESA
;
1199 return egl_g3d_create_surface(drv
, dpy
, conf
, &arg
, attribs
);
1203 egl_g3d_show_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
1204 _EGLScreen
*scr
, _EGLSurface
*surf
,
1207 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
1208 struct egl_g3d_screen
*gscr
= egl_g3d_screen(scr
);
1209 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
1210 struct native_surface
*nsurf
;
1211 const struct native_mode
*nmode
;
1218 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
1219 if (gsurf
->base
.Type
!= EGL_SCREEN_BIT_MESA
)
1220 return _eglError(EGL_BAD_SURFACE
, "eglShowScreenSurfaceMESA");
1221 if (gsurf
->base
.Width
< mode
->Width
|| gsurf
->base
.Height
< mode
->Height
)
1222 return _eglError(EGL_BAD_MATCH
,
1223 "eglShowSurfaceMESA(surface smaller than mode size)");
1225 /* find the index of the mode */
1226 for (idx
= 0; idx
< gscr
->base
.NumModes
; idx
++)
1227 if (mode
== &gscr
->base
.Modes
[idx
])
1229 if (idx
>= gscr
->base
.NumModes
) {
1230 return _eglError(EGL_BAD_MODE_MESA
,
1231 "eglShowSurfaceMESA(unknown mode)");
1234 nsurf
= gsurf
->native
;
1235 nmode
= gscr
->native_modes
[idx
];
1239 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
1241 /* disable the screen */
1246 /* TODO surface panning by CRTC choosing */
1247 changed
= gdpy
->native
->modeset
->program(gdpy
->native
, 0, nsurf
,
1248 gscr
->base
.OriginX
, gscr
->base
.OriginY
, &gscr
->native
, 1, nmode
);
1250 gscr
->base
.CurrentSurface
= &gsurf
->base
;
1251 gscr
->base
.CurrentMode
= mode
;
1257 #endif /* EGL_MESA_screen_surface */
1260 egl_g3d_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
1262 struct native_probe
*nprobe
;
1263 enum native_probe_result res
;
1266 nprobe
= egl_g3d_get_probe(drv
, dpy
);
1267 res
= native_get_probe_result(nprobe
);
1270 case NATIVE_PROBE_UNKNOWN
:
1274 case NATIVE_PROBE_FALLBACK
:
1277 case NATIVE_PROBE_SUPPORTED
:
1280 case NATIVE_PROBE_EXACT
:
1289 egl_g3d_unload(_EGLDriver
*drv
)
1291 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
1293 egl_g3d_destroy_probe(drv
, NULL
);
1298 _eglMain(const char *args
)
1300 static char driver_name
[64];
1301 struct egl_g3d_driver
*gdrv
;
1303 snprintf(driver_name
, sizeof(driver_name
),
1304 "Gallium/%s", native_get_name());
1306 gdrv
= CALLOC_STRUCT(egl_g3d_driver
);
1310 _eglInitDriverFallbacks(&gdrv
->base
);
1312 gdrv
->base
.API
.Initialize
= egl_g3d_initialize
;
1313 gdrv
->base
.API
.Terminate
= egl_g3d_terminate
;
1314 gdrv
->base
.API
.CreateContext
= egl_g3d_create_context
;
1315 gdrv
->base
.API
.DestroyContext
= egl_g3d_destroy_context
;
1316 gdrv
->base
.API
.CreateWindowSurface
= egl_g3d_create_window_surface
;
1317 gdrv
->base
.API
.CreatePixmapSurface
= egl_g3d_create_pixmap_surface
;
1318 gdrv
->base
.API
.CreatePbufferSurface
= egl_g3d_create_pbuffer_surface
;
1319 gdrv
->base
.API
.DestroySurface
= egl_g3d_destroy_surface
;
1320 gdrv
->base
.API
.MakeCurrent
= egl_g3d_make_current
;
1321 gdrv
->base
.API
.SwapBuffers
= egl_g3d_swap_buffers
;
1322 gdrv
->base
.API
.CopyBuffers
= egl_g3d_copy_buffers
;
1323 gdrv
->base
.API
.WaitClient
= egl_g3d_wait_client
;
1324 gdrv
->base
.API
.WaitNative
= egl_g3d_wait_native
;
1325 gdrv
->base
.API
.GetProcAddress
= egl_g3d_get_proc_address
;
1327 gdrv
->base
.API
.BindTexImage
= egl_g3d_bind_tex_image
;
1328 gdrv
->base
.API
.ReleaseTexImage
= egl_g3d_release_tex_image
;
1330 gdrv
->base
.API
.CreateImageKHR
= egl_g3d_create_image
;
1331 gdrv
->base
.API
.DestroyImageKHR
= egl_g3d_destroy_image
;
1333 #ifdef EGL_MESA_screen_surface
1334 gdrv
->base
.API
.CreateScreenSurfaceMESA
= egl_g3d_create_screen_surface
;
1335 gdrv
->base
.API
.ShowScreenSurfaceMESA
= egl_g3d_show_screen_surface
;
1338 gdrv
->base
.Name
= driver_name
;
1339 gdrv
->base
.Probe
= egl_g3d_probe
;
1340 gdrv
->base
.Unload
= egl_g3d_unload
;
1342 /* the key is " EGL G3D" */
1343 gdrv
->probe_key
= 0x0E61063D;