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.
27 #include "util/u_memory.h"
28 #include "egldriver.h"
29 #include "eglcurrent.h"
30 #include "eglconfigutil.h"
38 * Validate the draw/read surfaces of the context.
41 egl_g3d_validate_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
43 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
44 struct pipe_screen
*screen
= gdpy
->native
->screen
;
45 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
49 /* validate draw and/or read buffers */
50 num_surfaces
= (gctx
->base
.ReadSurface
== gctx
->base
.DrawSurface
) ? 1 : 2;
51 for (s
= 0; s
< num_surfaces
; s
++) {
52 struct pipe_texture
*textures
[NUM_NATIVE_ATTACHMENTS
];
53 struct egl_g3d_surface
*gsurf
;
54 struct egl_g3d_buffer
*gbuf
;
57 gsurf
= egl_g3d_surface(gctx
->base
.DrawSurface
);
61 gsurf
= egl_g3d_surface(gctx
->base
.ReadSurface
);
65 if (!gctx
->force_validate
) {
68 cur_w
= gsurf
->base
.Width
;
69 cur_h
= gsurf
->base
.Height
;
70 gsurf
->native
->validate(gsurf
->native
,
71 gbuf
->native_atts
, gbuf
->num_atts
,
73 &gsurf
->base
.Width
, &gsurf
->base
.Height
);
74 /* validate only when the geometry changed */
75 if (gsurf
->base
.Width
== cur_w
&& gsurf
->base
.Height
== cur_h
)
79 gsurf
->native
->validate(gsurf
->native
,
80 gbuf
->native_atts
, gbuf
->num_atts
,
81 (struct pipe_texture
**) textures
,
82 &gsurf
->base
.Width
, &gsurf
->base
.Height
);
83 for (i
= 0; i
< gbuf
->num_atts
; i
++) {
84 struct pipe_texture
*pt
= textures
[i
];
85 struct pipe_surface
*ps
;
88 ps
= screen
->get_tex_surface(screen
, pt
, 0, 0, 0,
89 PIPE_BUFFER_USAGE_GPU_READ
|
90 PIPE_BUFFER_USAGE_GPU_WRITE
);
91 gctx
->stapi
->st_set_framebuffer_surface(gbuf
->st_fb
,
92 gbuf
->st_atts
[i
], ps
);
94 if (gbuf
->native_atts
[i
] == gsurf
->render_att
)
95 pipe_surface_reference(&gsurf
->render_surface
, ps
);
97 pipe_surface_reference(&ps
, NULL
);
98 pipe_texture_reference(&pt
, NULL
);
102 gctx
->stapi
->st_resize_framebuffer(gbuf
->st_fb
,
103 gsurf
->base
.Width
, gsurf
->base
.Height
);
106 gctx
->force_validate
= EGL_FALSE
;
111 * Create a st_framebuffer.
113 static struct st_framebuffer
*
114 create_framebuffer(_EGLContext
*ctx
, _EGLSurface
*surf
)
116 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
117 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
118 struct egl_g3d_config
*gconf
= egl_g3d_config(gsurf
->base
.Config
);
120 return gctx
->stapi
->st_create_framebuffer(&gconf
->native
->mode
,
121 gconf
->native
->color_format
, gconf
->native
->depth_format
,
122 gconf
->native
->stencil_format
,
123 gsurf
->base
.Width
, gsurf
->base
.Height
, &gsurf
->base
);
127 * Update the attachments of draw/read surfaces.
130 egl_g3d_route_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
132 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
133 const uint st_att_map
[NUM_NATIVE_ATTACHMENTS
] = {
134 ST_SURFACE_FRONT_LEFT
,
135 ST_SURFACE_BACK_LEFT
,
136 ST_SURFACE_FRONT_RIGHT
,
137 ST_SURFACE_BACK_RIGHT
,
141 /* route draw and read buffers' attachments */
142 for (s
= 0; s
< 2; s
++) {
143 struct egl_g3d_surface
*gsurf
;
144 struct egl_g3d_buffer
*gbuf
;
147 gsurf
= egl_g3d_surface(gctx
->base
.DrawSurface
);
151 gsurf
= egl_g3d_surface(gctx
->base
.ReadSurface
);
155 gbuf
->native_atts
[0] = gsurf
->render_att
;
158 for (i
= 0; i
< gbuf
->num_atts
; i
++)
159 gbuf
->st_atts
[i
] = st_att_map
[gbuf
->native_atts
[i
]];
161 /* FIXME OpenGL defaults to draw the front or back buffer when the
162 * context is single-buffered or double-buffered respectively. In EGL,
163 * however, the buffer to be drawn is determined by the surface, instead
164 * of the context. As a result, rendering to a pixmap surface with a
165 * double-buffered context does not work as expected.
167 * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
168 * NATIVE_ATTACHMENT_FRONT_LEFT);
172 * FIXME If the back buffer is asked for here, and the front buffer is
173 * later needed by the client API (e.g. glDrawBuffer is called to draw
174 * the front buffer), it will create a new pipe texture and draw there.
175 * One fix is to ask for both buffers here, but it would be a waste if
176 * the front buffer is never used. A better fix is to add a callback to
177 * the pipe screen with context private (just like flush_frontbuffer).
183 * Reallocate the context's framebuffers after draw/read surfaces change.
186 egl_g3d_realloc_context(_EGLDisplay
*dpy
, _EGLContext
*ctx
)
188 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
189 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(gctx
->base
.DrawSurface
);
190 struct egl_g3d_surface
*gread
= egl_g3d_surface(gctx
->base
.ReadSurface
);
192 /* unreference the old framebuffers */
193 if (gctx
->draw
.st_fb
) {
194 EGLBoolean is_equal
= (gctx
->draw
.st_fb
== gctx
->read
.st_fb
);
197 priv
= gctx
->stapi
->st_framebuffer_private(gctx
->draw
.st_fb
);
198 if (!gdraw
|| priv
!= (void *) &gdraw
->base
) {
199 gctx
->stapi
->st_unreference_framebuffer(gctx
->draw
.st_fb
);
200 gctx
->draw
.st_fb
= NULL
;
201 gctx
->draw
.num_atts
= 0;
205 gctx
->read
.st_fb
= NULL
;
206 gctx
->draw
.num_atts
= 0;
209 priv
= gctx
->stapi
->st_framebuffer_private(gctx
->read
.st_fb
);
210 if (!gread
|| priv
!= (void *) &gread
->base
) {
211 gctx
->stapi
->st_unreference_framebuffer(gctx
->read
.st_fb
);
212 gctx
->read
.st_fb
= NULL
;
213 gctx
->draw
.num_atts
= 0;
221 /* create the draw fb */
222 if (!gctx
->draw
.st_fb
) {
223 gctx
->draw
.st_fb
= create_framebuffer(&gctx
->base
, &gdraw
->base
);
224 if (!gctx
->draw
.st_fb
)
228 /* create the read fb */
229 if (!gctx
->read
.st_fb
) {
230 if (gread
!= gdraw
) {
231 gctx
->read
.st_fb
= create_framebuffer(&gctx
->base
, &gread
->base
);
232 if (!gctx
->read
.st_fb
) {
233 gctx
->stapi
->st_unreference_framebuffer(gctx
->draw
.st_fb
);
234 gctx
->draw
.st_fb
= NULL
;
239 /* there is no st_reference_framebuffer... */
240 gctx
->read
.st_fb
= gctx
->draw
.st_fb
;
244 egl_g3d_route_context(dpy
, &gctx
->base
);
245 gctx
->force_validate
= EGL_TRUE
;
251 * Return the current context of the given API.
253 static struct egl_g3d_context
*
254 egl_g3d_get_current_context(EGLint api
)
256 _EGLThreadInfo
*t
= _eglGetCurrentThread();
257 EGLint api_index
= _eglConvertApiToIndex(api
);
258 return egl_g3d_context(t
->CurrentContexts
[api_index
]);
262 * Return the state tracker for the given context.
264 static const struct egl_g3d_st
*
265 egl_g3d_choose_st(_EGLDriver
*drv
, _EGLContext
*ctx
)
267 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
268 const struct egl_g3d_st
*stapi
;
271 switch (ctx
->ClientAPI
) {
272 case EGL_OPENGL_ES_API
:
273 switch (ctx
->ClientVersion
) {
275 idx
= EGL_G3D_ST_OPENGL_ES
;
278 idx
= EGL_G3D_ST_OPENGL_ES2
;
281 _eglLog(_EGL_WARNING
, "unknown client version %d",
287 idx
= EGL_G3D_ST_OPENVG
;
290 idx
= EGL_G3D_ST_OPENGL
;
293 _eglLog(_EGL_WARNING
, "unknown client API 0x%04x", ctx
->ClientAPI
);
297 stapi
= (idx
>= 0) ? gdrv
->stapis
[idx
] : NULL
;
302 * Return an API mask that consists of the state trackers that supports the
305 * FIXME add st_is_mode_supported()?
308 get_mode_api_mask(const __GLcontextModes
*mode
, EGLint api_mask
)
312 /* OpenGL ES 1.x and 2.x are checked together */
313 check
= EGL_OPENGL_ES_BIT
| EGL_OPENGL_ES2_BIT
;
314 if (api_mask
& check
) {
315 /* this is required by EGL, not by OpenGL ES */
316 if (mode
->drawableType
& GLX_WINDOW_BIT
&& !mode
->doubleBufferMode
)
320 check
= EGL_OPENVG_BIT
;
321 if (api_mask
& check
) {
322 /* vega st needs the depth/stencil rb */
323 if (!mode
->depthBits
&& !mode
->stencilBits
)
330 #ifdef EGL_MESA_screen_surface
333 egl_g3d_add_screens(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
335 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
336 const struct native_connector
**native_connectors
;
337 EGLint num_connectors
, i
;
340 gdpy
->native
->modeset
->get_connectors(gdpy
->native
, &num_connectors
, NULL
);
341 if (!num_connectors
) {
342 if (native_connectors
)
343 free(native_connectors
);
347 for (i
= 0; i
< num_connectors
; i
++) {
348 const struct native_connector
*nconn
= native_connectors
[i
];
349 struct egl_g3d_screen
*gscr
;
350 const struct native_mode
**native_modes
;
353 /* TODO support for hotplug */
355 gdpy
->native
->modeset
->get_modes(gdpy
->native
, nconn
, &num_modes
);
362 gscr
= CALLOC_STRUCT(egl_g3d_screen
);
368 _eglInitScreen(&gscr
->base
);
370 for (j
= 0; j
< num_modes
; j
++) {
371 const struct native_mode
*nmode
= native_modes
[j
];
374 mode
= _eglAddNewMode(&gscr
->base
, nmode
->width
, nmode
->height
,
375 nmode
->refresh_rate
, nmode
->desc
);
378 /* gscr->native_modes and gscr->base.Modes should be consistent */
379 assert(mode
== &gscr
->base
.Modes
[j
]);
382 gscr
->native
= nconn
;
383 gscr
->native_modes
= native_modes
;
385 _eglAddScreen(dpy
, &gscr
->base
);
388 free(native_connectors
);
391 #endif /* EGL_MESA_screen_surface */
394 * Add configs to display and return the next config ID.
397 egl_g3d_add_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint id
)
399 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
400 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
401 const struct native_config
**native_configs
;
404 native_configs
= gdpy
->native
->get_configs(gdpy
->native
,
408 free(native_configs
);
412 for (i
= 0; i
< num_configs
; i
++) {
414 struct egl_g3d_config
*gconf
;
417 api_mask
= get_mode_api_mask(&native_configs
[i
]->mode
, gdrv
->api_mask
);
419 _eglLog(_EGL_DEBUG
, "no state tracker supports config 0x%x",
420 native_configs
[i
]->mode
.visualID
);
424 gconf
= CALLOC_STRUCT(egl_g3d_config
);
428 _eglInitConfig(&gconf
->base
, id
);
429 valid
= _eglConfigFromContextModesRec(&gconf
->base
,
430 &native_configs
[i
]->mode
, api_mask
, api_mask
);
432 #ifdef EGL_MESA_screen_surface
433 /* check if scanout surface bit is set */
434 if (native_configs
[i
]->scanout_bit
) {
435 EGLint val
= GET_CONFIG_ATTRIB(&gconf
->base
, EGL_SURFACE_TYPE
);
436 val
|= EGL_SCREEN_BIT_MESA
;
437 SET_CONFIG_ATTRIB(&gconf
->base
, EGL_SURFACE_TYPE
, val
);
440 valid
= _eglValidateConfig(&gconf
->base
, EGL_FALSE
);
443 _eglLog(_EGL_DEBUG
, "skip invalid config 0x%x",
444 native_configs
[i
]->mode
.visualID
);
449 gconf
->native
= native_configs
[i
];
450 _eglAddConfig(dpy
, &gconf
->base
);
454 free(native_configs
);
459 * Flush the front buffer of the context's draw surface.
462 egl_g3d_flush_frontbuffer(void *dummy
, struct pipe_surface
*surf
,
463 void *context_private
)
465 struct egl_g3d_context
*gctx
= egl_g3d_context(context_private
);
466 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(gctx
->base
.DrawSurface
);
469 gsurf
->native
->flush_frontbuffer(gsurf
->native
);
470 egl_g3d_validate_context(gctx
->base
.Display
, &gctx
->base
);
475 egl_g3d_terminate(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
477 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
480 _eglReleaseDisplayResources(drv
, dpy
);
481 _eglCleanupDisplay(dpy
);
484 for (i
= 0; i
< dpy
->NumScreens
; i
++) {
485 struct egl_g3d_screen
*gscr
= egl_g3d_screen(dpy
->Screens
[i
]);
486 free(gscr
->native_modes
);
493 gdpy
->native
->destroy(gdpy
->native
);
496 dpy
->DriverData
= NULL
;
502 egl_g3d_initialize(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
503 EGLint
*major
, EGLint
*minor
)
505 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
506 struct egl_g3d_display
*gdpy
;
508 gdpy
= CALLOC_STRUCT(egl_g3d_display
);
510 _eglError(EGL_BAD_ALLOC
, "eglInitialize");
513 dpy
->DriverData
= gdpy
;
516 native_create_display(dpy
->NativeDisplay
, egl_g3d_flush_frontbuffer
);
518 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(no usable display)");
522 dpy
->ClientAPIsMask
= gdrv
->api_mask
;
524 if (egl_g3d_add_configs(drv
, dpy
, 1) == 1) {
525 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(unable to add configs)");
529 #ifdef EGL_MESA_screen_surface
530 /* enable MESA_screen_surface */
531 if (gdpy
->native
->modeset
) {
532 dpy
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
533 egl_g3d_add_screens(drv
, dpy
);
544 egl_g3d_terminate(drv
, dpy
);
549 egl_g3d_create_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
550 _EGLContext
*share
, const EGLint
*attribs
)
552 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
553 struct egl_g3d_context
*xshare
= egl_g3d_context(share
);
554 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
555 struct egl_g3d_context
*gctx
;
556 const __GLcontextModes
*mode
;
558 gctx
= CALLOC_STRUCT(egl_g3d_context
);
560 _eglError(EGL_BAD_ALLOC
, "eglCreateContext");
564 if (!_eglInitContext(drv
, &gctx
->base
, conf
, attribs
)) {
569 gctx
->stapi
= egl_g3d_choose_st(drv
, &gctx
->base
);
575 mode
= &gconf
->native
->mode
;
577 gdpy
->native
->create_context(gdpy
->native
, (void *) &gctx
->base
);
578 gctx
->st_ctx
= gctx
->stapi
->st_create_context(gctx
->pipe
, mode
,
579 (xshare
) ? xshare
->st_ctx
: NULL
);
585 egl_g3d_destroy_context(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
587 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
589 if (_eglIsContextBound(&gctx
->base
))
592 egl_g3d_realloc_context(dpy
, &gctx
->base
);
594 /* it will destroy pipe context */
595 gctx
->stapi
->st_destroy_context(gctx
->st_ctx
);
603 egl_g3d_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
604 _EGLConfig
*conf
, EGLNativeWindowType win
,
605 const EGLint
*attribs
)
607 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
608 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
609 struct egl_g3d_surface
*gsurf
;
611 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
613 _eglError(EGL_BAD_ALLOC
, "eglCreateWindowSurface");
617 if (!_eglInitSurface(drv
, &gsurf
->base
, EGL_WINDOW_BIT
, conf
, attribs
)) {
623 gdpy
->native
->create_window_surface(gdpy
->native
, win
, gconf
->native
);
624 if (!gsurf
->native
) {
629 if (!gsurf
->native
->validate(gsurf
->native
, NULL
, 0, NULL
,
630 &gsurf
->base
.Width
, &gsurf
->base
.Height
)) {
631 gsurf
->native
->destroy(gsurf
->native
);
636 gsurf
->render_att
= (gsurf
->base
.RenderBuffer
== EGL_SINGLE_BUFFER
||
637 !gconf
->native
->mode
.doubleBufferMode
) ?
638 NATIVE_ATTACHMENT_FRONT_LEFT
: NATIVE_ATTACHMENT_BACK_LEFT
;
644 egl_g3d_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
645 _EGLConfig
*conf
, EGLNativePixmapType pix
,
646 const EGLint
*attribs
)
648 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
649 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
650 struct egl_g3d_surface
*gsurf
;
652 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
654 _eglError(EGL_BAD_ALLOC
, "eglCreatePixmapSurface");
658 if (!_eglInitSurface(drv
, &gsurf
->base
, EGL_PIXMAP_BIT
, conf
, attribs
)) {
664 gdpy
->native
->create_pixmap_surface(gdpy
->native
, pix
, gconf
->native
);
665 if (!gsurf
->native
) {
670 if (!gsurf
->native
->validate(gsurf
->native
, NULL
, 0, NULL
,
671 &gsurf
->base
.Width
, &gsurf
->base
.Height
)) {
672 gsurf
->native
->destroy(gsurf
->native
);
677 gsurf
->render_att
= NATIVE_ATTACHMENT_FRONT_LEFT
;
683 egl_g3d_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
684 _EGLConfig
*conf
, const EGLint
*attribs
)
686 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
687 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
688 struct egl_g3d_surface
*gsurf
;
690 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
692 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
696 if (!_eglInitSurface(drv
, &gsurf
->base
, EGL_PBUFFER_BIT
, conf
, attribs
)) {
702 gdpy
->native
->create_pbuffer_surface(gdpy
->native
, gconf
->native
,
703 gsurf
->base
.Width
, gsurf
->base
.Height
);
704 if (!gsurf
->native
) {
709 gsurf
->render_att
= (!gconf
->native
->mode
.doubleBufferMode
) ?
710 NATIVE_ATTACHMENT_FRONT_LEFT
: NATIVE_ATTACHMENT_BACK_LEFT
;
716 egl_g3d_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
718 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
720 if (_eglIsSurfaceBound(&gsurf
->base
))
723 pipe_surface_reference(&gsurf
->render_surface
, NULL
);
724 gsurf
->native
->destroy(gsurf
->native
);
730 egl_g3d_make_current(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
731 _EGLSurface
*draw
, _EGLSurface
*read
, _EGLContext
*ctx
)
733 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
734 struct egl_g3d_context
*old_gctx
;
736 EGLBoolean ok
= EGL_TRUE
;
738 /* find the old context */
739 api
= (gctx
) ? gctx
->base
.ClientAPI
: eglQueryAPI();
740 old_gctx
= egl_g3d_get_current_context(api
);
741 if (old_gctx
&& !_eglIsContextLinked(&old_gctx
->base
))
744 if (!_eglMakeCurrent(drv
, dpy
, draw
, read
, ctx
))
748 /* flush old context */
749 old_gctx
->stapi
->st_flush(old_gctx
->st_ctx
,
750 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
753 * The old context is no longer current, and egl_g3d_realloc_context()
754 * should be called to destroy the framebuffers. However, it is possible
755 * that it will be made current again with the same draw/read surfaces.
756 * It might be better to keep it around.
761 struct egl_g3d_surface
*gdraw
= egl_g3d_surface(draw
);
763 ok
= egl_g3d_realloc_context(dpy
, &gctx
->base
);
765 ok
= gctx
->stapi
->st_make_current(gctx
->st_ctx
,
766 gctx
->draw
.st_fb
, gctx
->read
.st_fb
);
768 egl_g3d_validate_context(dpy
, &gctx
->base
);
769 if (gdraw
->base
.Type
== EGL_WINDOW_BIT
) {
770 gctx
->base
.WindowRenderBuffer
=
771 (gdraw
->render_att
== NATIVE_ATTACHMENT_FRONT_LEFT
) ?
772 EGL_SINGLE_BUFFER
: EGL_BACK_BUFFER
;
778 ok
= old_gctx
->stapi
->st_make_current(NULL
, NULL
, NULL
);
779 old_gctx
->base
.WindowRenderBuffer
= EGL_NONE
;
786 egl_g3d_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
)
788 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
789 _EGLContext
*ctx
= _eglGetCurrentContext();
790 struct egl_g3d_context
*gctx
= NULL
;
792 /* no-op for pixmap or pbuffer surface */
793 if (gsurf
->base
.Type
== EGL_PIXMAP_BIT
||
794 gsurf
->base
.Type
== EGL_PBUFFER_BIT
)
797 /* or when the surface is single-buffered */
798 if (gsurf
->render_att
== NATIVE_ATTACHMENT_FRONT_LEFT
)
801 if (ctx
&& ctx
->DrawSurface
== surf
)
802 gctx
= egl_g3d_context(ctx
);
804 /* flush if the surface is current */
806 gctx
->stapi
->st_notify_swapbuffers(gctx
->draw
.st_fb
);
809 * We drew on the back buffer, unless there was no back buffer.
810 * In that case, we drew on the front buffer. Either case, we call
813 if (!gsurf
->native
->swap_buffers(gsurf
->native
))
817 struct egl_g3d_config
*gconf
= egl_g3d_config(gsurf
->base
.Config
);
819 /* force validation if the swap method is not copy */
820 if (gconf
->native
->mode
.swapMethod
!= GLX_SWAP_COPY_OML
)
821 gctx
->force_validate
= EGL_TRUE
;
822 egl_g3d_validate_context(dpy
, &gctx
->base
);
829 egl_g3d_wait_client(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLContext
*ctx
)
831 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
832 gctx
->stapi
->st_finish(gctx
->st_ctx
);
837 egl_g3d_wait_native(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint engine
)
839 _EGLSurface
*surf
= _eglGetCurrentSurface(EGL_DRAW
);
840 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
842 if (engine
!= EGL_CORE_NATIVE_ENGINE
)
843 return _eglError(EGL_BAD_PARAMETER
, "eglWaitNative");
846 gsurf
->native
->wait(gsurf
->native
);
852 egl_g3d_get_proc_address(_EGLDriver
*drv
, const char *procname
)
854 /* FIXME how come _EGLDriver is not passed? */
855 const struct egl_g3d_st
*stapi
;
859 for (i
= 0; i
< NUM_EGL_G3D_STS
; i
++) {
860 stapi
= egl_g3d_get_st(i
);
862 proc
= (_EGLProc
) stapi
->st_get_proc_address(procname
);
868 return (_EGLProc
) NULL
;
872 egl_g3d_bind_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
873 _EGLSurface
*surf
, EGLint buffer
)
875 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
876 struct egl_g3d_context
*gctx
;
877 enum pipe_format target_format
;
880 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
)
881 return _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
882 if (buffer
!= EGL_BACK_BUFFER
)
883 return _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
884 if (gsurf
->base
.BoundToTexture
)
885 return _eglError(EGL_BAD_ACCESS
, "eglBindTexImage");
887 switch (gsurf
->base
.TextureFormat
) {
888 case EGL_TEXTURE_RGB
:
889 target_format
= PIPE_FORMAT_R8G8B8_UNORM
;
891 case EGL_TEXTURE_RGBA
:
892 target_format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
895 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
898 switch (gsurf
->base
.TextureTarget
) {
900 target
= ST_TEXTURE_2D
;
903 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
906 /* flush properly if the surface is bound */
907 if (gsurf
->base
.Binding
) {
908 gctx
= egl_g3d_context(gsurf
->base
.Binding
);
909 gctx
->stapi
->st_flush(gctx
->st_ctx
,
910 PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, NULL
);
913 /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
914 gctx
= egl_g3d_get_current_context(EGL_OPENGL_API
);
916 if (!gsurf
->render_surface
)
919 gctx
->stapi
->st_bind_texture_surface(gsurf
->render_surface
,
920 target
, gsurf
->base
.MipmapLevel
, target_format
);
921 gsurf
->base
.BoundToTexture
= EGL_TRUE
;
928 egl_g3d_release_tex_image(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
929 _EGLSurface
*surf
, EGLint buffer
)
931 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
933 if (!gsurf
|| gsurf
->base
.Type
!= EGL_PBUFFER_BIT
||
934 !gsurf
->base
.BoundToTexture
)
935 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
936 if (buffer
!= EGL_BACK_BUFFER
)
937 return _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
939 if (gsurf
->render_surface
) {
940 _EGLThreadInfo
*t
= _eglGetCurrentThread();
941 /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */
942 struct egl_g3d_context
*gctx
= egl_g3d_context(
943 t
->CurrentContexts
[_eglConvertApiToIndex(EGL_OPENGL_API
)]);
945 /* what if the context the surface binds to is no longer current? */
947 gctx
->stapi
->st_unbind_texture_surface(gsurf
->render_surface
,
948 ST_TEXTURE_2D
, gsurf
->base
.MipmapLevel
);
951 gsurf
->base
.BoundToTexture
= EGL_FALSE
;
956 #ifdef EGL_MESA_screen_surface
959 egl_g3d_create_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
960 _EGLConfig
*conf
, const EGLint
*attribs
)
962 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
963 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
964 struct egl_g3d_surface
*gsurf
;
966 gsurf
= CALLOC_STRUCT(egl_g3d_surface
);
968 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
972 if (!_eglInitSurface(drv
, &gsurf
->base
,
973 EGL_SCREEN_BIT_MESA
, conf
, attribs
)) {
979 gdpy
->native
->modeset
->create_scanout_surface(gdpy
->native
,
980 gconf
->native
, gsurf
->base
.Width
, gsurf
->base
.Height
);
981 if (!gsurf
->native
) {
986 gsurf
->render_att
= (!gconf
->native
->mode
.doubleBufferMode
) ?
987 NATIVE_ATTACHMENT_FRONT_LEFT
: NATIVE_ATTACHMENT_BACK_LEFT
;
993 egl_g3d_show_screen_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
994 _EGLScreen
*scr
, _EGLSurface
*surf
,
997 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
998 struct egl_g3d_screen
*gscr
= egl_g3d_screen(scr
);
999 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(surf
);
1000 struct native_surface
*nsurf
;
1001 const struct native_mode
*nmode
;
1008 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
1009 if (gsurf
->base
.Type
!= EGL_SCREEN_BIT_MESA
)
1010 return _eglError(EGL_BAD_SURFACE
, "eglShowScreenSurfaceMESA");
1011 if (gsurf
->base
.Width
< mode
->Width
|| gsurf
->base
.Height
< mode
->Height
)
1012 return _eglError(EGL_BAD_MATCH
,
1013 "eglShowSurfaceMESA(surface smaller than mode size)");
1015 /* find the index of the mode */
1016 for (idx
= 0; idx
< gscr
->base
.NumModes
; idx
++)
1017 if (mode
== &gscr
->base
.Modes
[idx
])
1019 if (idx
>= gscr
->base
.NumModes
) {
1020 return _eglError(EGL_BAD_MODE_MESA
,
1021 "eglShowSurfaceMESA(unknown mode)");
1024 nsurf
= gsurf
->native
;
1025 nmode
= gscr
->native_modes
[idx
];
1029 return _eglError(EGL_BAD_MATCH
, "eglShowSurfaceMESA");
1031 /* disable the screen */
1036 /* TODO surface panning by CRTC choosing */
1037 changed
= gdpy
->native
->modeset
->program(gdpy
->native
, 0, nsurf
,
1038 gscr
->base
.OriginX
, gscr
->base
.OriginY
, &gscr
->native
, 1, nmode
);
1040 gscr
->base
.CurrentSurface
= &gsurf
->base
;
1041 gscr
->base
.CurrentMode
= mode
;
1047 #endif /* EGL_MESA_screen_surface */
1050 egl_g3d_unload(_EGLDriver
*drv
)
1052 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
1057 _eglMain(const char *args
)
1059 static char driver_name
[64];
1060 struct egl_g3d_driver
*gdrv
;
1063 snprintf(driver_name
, sizeof(driver_name
),
1064 "Gallium/%s", native_get_name());
1066 gdrv
= CALLOC_STRUCT(egl_g3d_driver
);
1070 _eglInitDriverFallbacks(&gdrv
->base
);
1072 gdrv
->base
.API
.Initialize
= egl_g3d_initialize
;
1073 gdrv
->base
.API
.Terminate
= egl_g3d_terminate
;
1074 gdrv
->base
.API
.CreateContext
= egl_g3d_create_context
;
1075 gdrv
->base
.API
.DestroyContext
= egl_g3d_destroy_context
;
1076 gdrv
->base
.API
.CreateWindowSurface
= egl_g3d_create_window_surface
;
1077 gdrv
->base
.API
.CreatePixmapSurface
= egl_g3d_create_pixmap_surface
;
1078 gdrv
->base
.API
.CreatePbufferSurface
= egl_g3d_create_pbuffer_surface
;
1079 gdrv
->base
.API
.DestroySurface
= egl_g3d_destroy_surface
;
1080 gdrv
->base
.API
.MakeCurrent
= egl_g3d_make_current
;
1081 gdrv
->base
.API
.SwapBuffers
= egl_g3d_swap_buffers
;
1082 gdrv
->base
.API
.WaitClient
= egl_g3d_wait_client
;
1083 gdrv
->base
.API
.WaitNative
= egl_g3d_wait_native
;
1084 gdrv
->base
.API
.GetProcAddress
= egl_g3d_get_proc_address
;
1086 gdrv
->base
.API
.BindTexImage
= egl_g3d_bind_tex_image
;
1087 gdrv
->base
.API
.ReleaseTexImage
= egl_g3d_release_tex_image
;
1089 #ifdef EGL_MESA_screen_surface
1090 gdrv
->base
.API
.CreateScreenSurfaceMESA
= egl_g3d_create_screen_surface
;
1091 gdrv
->base
.API
.ShowScreenSurfaceMESA
= egl_g3d_show_screen_surface
;
1094 gdrv
->base
.Name
= driver_name
;
1095 gdrv
->base
.Unload
= egl_g3d_unload
;
1097 for (i
= 0; i
< NUM_EGL_G3D_STS
; i
++) {
1098 gdrv
->stapis
[i
] = egl_g3d_get_st(i
);
1099 if (gdrv
->stapis
[i
])
1100 gdrv
->api_mask
|= gdrv
->stapis
[i
]->api_bit
;
1104 _eglLog(_EGL_DEBUG
, "Driver API mask: 0x%x", gdrv
->api_mask
);
1106 _eglLog(_EGL_WARNING
, "No supported client API");