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_format.h"
33 #include "util/u_string.h"
36 #include "egl_g3d_api.h"
37 #include "egl_g3d_st.h"
41 * Initialize the state trackers.
44 egl_g3d_init_st(_EGLDriver
*drv
)
46 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
49 /* already initialized */
53 egl_g3d_init_st_apis(gdrv
->stapis
);
54 for (i
= 0; i
< ST_API_COUNT
; i
++) {
56 gdrv
->api_mask
|= egl_g3d_st_api_bit(i
);
60 _eglLog(_EGL_DEBUG
, "Driver API mask: 0x%x", gdrv
->api_mask
);
62 _eglLog(_EGL_WARNING
, "No supported client API");
66 * Get the probe object of the display.
68 * Note that this function may be called before the display is initialized.
70 static struct native_probe
*
71 egl_g3d_get_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
73 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
74 struct native_probe
*nprobe
;
76 nprobe
= (struct native_probe
*) _eglGetProbeCache(gdrv
->probe_key
);
77 if (!nprobe
|| nprobe
->display
!= dpy
->NativeDisplay
) {
79 nprobe
->destroy(nprobe
);
80 nprobe
= native_create_probe(dpy
->NativeDisplay
);
81 _eglSetProbeCache(gdrv
->probe_key
, (void *) nprobe
);
88 * Destroy the probe object of the display. The display may be NULL.
90 * Note that this function may be called before the display is initialized.
93 egl_g3d_destroy_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
95 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
96 struct native_probe
*nprobe
;
98 nprobe
= (struct native_probe
*) _eglGetProbeCache(gdrv
->probe_key
);
99 if (nprobe
&& (!dpy
|| nprobe
->display
== dpy
->NativeDisplay
)) {
100 nprobe
->destroy(nprobe
);
101 _eglSetProbeCache(gdrv
->probe_key
, NULL
);
105 #ifdef EGL_MESA_screen_surface
108 egl_g3d_add_screens(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
110 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
111 const struct native_connector
**native_connectors
;
112 EGLint num_connectors
, i
;
115 gdpy
->native
->modeset
->get_connectors(gdpy
->native
, &num_connectors
, NULL
);
116 if (!num_connectors
) {
117 if (native_connectors
)
118 FREE(native_connectors
);
122 for (i
= 0; i
< num_connectors
; i
++) {
123 const struct native_connector
*nconn
= native_connectors
[i
];
124 struct egl_g3d_screen
*gscr
;
125 const struct native_mode
**native_modes
;
128 /* TODO support for hotplug */
130 gdpy
->native
->modeset
->get_modes(gdpy
->native
, nconn
, &num_modes
);
137 gscr
= CALLOC_STRUCT(egl_g3d_screen
);
143 _eglInitScreen(&gscr
->base
);
145 for (j
= 0; j
< num_modes
; j
++) {
146 const struct native_mode
*nmode
= native_modes
[j
];
149 mode
= _eglAddNewMode(&gscr
->base
, nmode
->width
, nmode
->height
,
150 nmode
->refresh_rate
, nmode
->desc
);
153 /* gscr->native_modes and gscr->base.Modes should be consistent */
154 assert(mode
== &gscr
->base
.Modes
[j
]);
157 gscr
->native
= nconn
;
158 gscr
->native_modes
= native_modes
;
160 _eglAddScreen(dpy
, &gscr
->base
);
163 FREE(native_connectors
);
166 #endif /* EGL_MESA_screen_surface */
169 * Initialize and validate the EGL config attributes.
172 init_config_attributes(_EGLConfig
*conf
, const struct native_config
*nconf
,
173 EGLint api_mask
, enum pipe_format depth_stencil_format
)
175 uint rgba
[4], depth_stencil
[2], buffer_size
;
179 /* get the color and depth/stencil component sizes */
180 assert(nconf
->color_format
!= PIPE_FORMAT_NONE
);
182 for (i
= 0; i
< 4; i
++) {
183 rgba
[i
] = util_format_get_component_bits(nconf
->color_format
,
184 UTIL_FORMAT_COLORSPACE_RGB
, i
);
185 buffer_size
+= rgba
[i
];
187 for (i
= 0; i
< 2; i
++) {
188 if (depth_stencil_format
!= PIPE_FORMAT_NONE
) {
190 util_format_get_component_bits(depth_stencil_format
,
191 UTIL_FORMAT_COLORSPACE_ZS
, i
);
194 depth_stencil
[i
] = 0;
199 if (nconf
->window_bit
)
200 surface_type
|= EGL_WINDOW_BIT
;
201 if (nconf
->pixmap_bit
)
202 surface_type
|= EGL_PIXMAP_BIT
;
203 #ifdef EGL_MESA_screen_surface
204 if (nconf
->scanout_bit
)
205 surface_type
|= EGL_SCREEN_BIT_MESA
;
208 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
))
209 surface_type
|= EGL_PBUFFER_BIT
;
211 SET_CONFIG_ATTRIB(conf
, EGL_CONFORMANT
, api_mask
);
212 SET_CONFIG_ATTRIB(conf
, EGL_RENDERABLE_TYPE
, api_mask
);
214 SET_CONFIG_ATTRIB(conf
, EGL_RED_SIZE
, rgba
[0]);
215 SET_CONFIG_ATTRIB(conf
, EGL_GREEN_SIZE
, rgba
[1]);
216 SET_CONFIG_ATTRIB(conf
, EGL_BLUE_SIZE
, rgba
[2]);
217 SET_CONFIG_ATTRIB(conf
, EGL_ALPHA_SIZE
, rgba
[3]);
218 SET_CONFIG_ATTRIB(conf
, EGL_BUFFER_SIZE
, buffer_size
);
220 SET_CONFIG_ATTRIB(conf
, EGL_DEPTH_SIZE
, depth_stencil
[0]);
221 SET_CONFIG_ATTRIB(conf
, EGL_STENCIL_SIZE
, depth_stencil
[1]);
223 SET_CONFIG_ATTRIB(conf
, EGL_SURFACE_TYPE
, surface_type
);
225 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_RENDERABLE
, EGL_TRUE
);
226 if (surface_type
& EGL_WINDOW_BIT
) {
227 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_ID
, nconf
->native_visual_id
);
228 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_TYPE
,
229 nconf
->native_visual_type
);
232 if (surface_type
& EGL_PBUFFER_BIT
) {
233 SET_CONFIG_ATTRIB(conf
, EGL_BIND_TO_TEXTURE_RGB
, EGL_TRUE
);
235 SET_CONFIG_ATTRIB(conf
, EGL_BIND_TO_TEXTURE_RGBA
, EGL_TRUE
);
237 SET_CONFIG_ATTRIB(conf
, EGL_MAX_PBUFFER_WIDTH
, 4096);
238 SET_CONFIG_ATTRIB(conf
, EGL_MAX_PBUFFER_HEIGHT
, 4096);
239 SET_CONFIG_ATTRIB(conf
, EGL_MAX_PBUFFER_PIXELS
, 4096 * 4096);
242 SET_CONFIG_ATTRIB(conf
, EGL_LEVEL
, nconf
->level
);
243 SET_CONFIG_ATTRIB(conf
, EGL_SAMPLES
, nconf
->samples
);
244 SET_CONFIG_ATTRIB(conf
, EGL_SAMPLE_BUFFERS
, 1);
246 if (nconf
->slow_config
)
247 SET_CONFIG_ATTRIB(conf
, EGL_CONFIG_CAVEAT
, EGL_SLOW_CONFIG
);
249 if (nconf
->transparent_rgb
) {
250 rgba
[0] = nconf
->transparent_rgb_values
[0];
251 rgba
[1] = nconf
->transparent_rgb_values
[1];
252 rgba
[2] = nconf
->transparent_rgb_values
[2];
254 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_TYPE
, EGL_TRANSPARENT_RGB
);
255 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_RED_VALUE
, rgba
[0]);
256 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_GREEN_VALUE
, rgba
[1]);
257 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_BLUE_VALUE
, rgba
[2]);
260 return _eglValidateConfig(conf
, EGL_FALSE
);
264 * Initialize an EGL config from the native config.
267 egl_g3d_init_config(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
268 _EGLConfig
*conf
, const struct native_config
*nconf
,
269 enum pipe_format depth_stencil_format
)
271 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
272 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
273 EGLint buffer_mask
, api_mask
;
278 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_LEFT
))
279 buffer_mask
|= ST_ATTACHMENT_FRONT_LEFT_MASK
;
280 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
))
281 buffer_mask
|= ST_ATTACHMENT_BACK_LEFT_MASK
;
282 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_RIGHT
))
283 buffer_mask
|= ST_ATTACHMENT_FRONT_RIGHT_MASK
;
284 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_RIGHT
))
285 buffer_mask
|= ST_ATTACHMENT_BACK_RIGHT_MASK
;
287 gconf
->stvis
.buffer_mask
= buffer_mask
;
288 gconf
->stvis
.color_format
= nconf
->color_format
;
289 gconf
->stvis
.depth_stencil_format
= depth_stencil_format
;
290 gconf
->stvis
.accum_format
= PIPE_FORMAT_NONE
;
291 gconf
->stvis
.samples
= nconf
->samples
;
293 gconf
->stvis
.render_buffer
= (buffer_mask
& ST_ATTACHMENT_BACK_LEFT_MASK
) ?
294 ST_ATTACHMENT_BACK_LEFT
: ST_ATTACHMENT_FRONT_LEFT
;
297 for (i
= 0; i
< ST_API_COUNT
; i
++) {
298 struct st_api
*stapi
= gdrv
->stapis
[i
];
300 if (stapi
->is_visual_supported(stapi
, &gconf
->stvis
))
301 api_mask
|= egl_g3d_st_api_bit(i
);
304 /* this is required by EGL, not by OpenGL ES */
305 if (nconf
->window_bit
&&
306 gconf
->stvis
.render_buffer
!= ST_ATTACHMENT_BACK_LEFT
)
307 api_mask
&= ~(EGL_OPENGL_ES_BIT
| EGL_OPENGL_ES2_BIT
);
310 _eglLog(_EGL_DEBUG
, "no state tracker supports config 0x%x",
311 nconf
->native_visual_id
);
314 valid
= init_config_attributes(&gconf
->base
,
315 nconf
, api_mask
, depth_stencil_format
);
317 _eglLog(_EGL_DEBUG
, "skip invalid config 0x%x", nconf
->native_visual_id
);
321 gconf
->native
= nconf
;
327 * Get all interested depth/stencil formats of a display.
330 egl_g3d_fill_depth_stencil_formats(_EGLDisplay
*dpy
,
331 enum pipe_format formats
[8])
333 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
334 struct pipe_screen
*screen
= gdpy
->native
->screen
;
335 const EGLint candidates
[] = {
336 1, PIPE_FORMAT_Z16_UNORM
,
337 1, PIPE_FORMAT_Z32_UNORM
,
338 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED
, PIPE_FORMAT_S8_USCALED_Z24_UNORM
,
339 2, PIPE_FORMAT_Z24X8_UNORM
, PIPE_FORMAT_X8Z24_UNORM
,
342 const EGLint
*fmt
= candidates
;
346 formats
[count
++] = PIPE_FORMAT_NONE
;
349 EGLint i
, n
= *fmt
++;
351 /* pick the first supported format */
352 for (i
= 0; i
< n
; i
++) {
353 if (screen
->is_format_supported(screen
, fmt
[i
],
354 PIPE_TEXTURE_2D
, 0, PIPE_BIND_DEPTH_STENCIL
, 0)) {
355 formats
[count
++] = fmt
[i
];
367 * Add configs to display and return the next config ID.
370 egl_g3d_add_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint id
)
372 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
373 const struct native_config
**native_configs
;
374 enum pipe_format depth_stencil_formats
[8];
375 int num_formats
, num_configs
, i
, j
;
377 native_configs
= gdpy
->native
->get_configs(gdpy
->native
, &num_configs
);
380 FREE(native_configs
);
384 num_formats
= egl_g3d_fill_depth_stencil_formats(dpy
,
385 depth_stencil_formats
);
387 for (i
= 0; i
< num_configs
; i
++) {
388 for (j
= 0; j
< num_formats
; j
++) {
389 struct egl_g3d_config
*gconf
;
391 gconf
= CALLOC_STRUCT(egl_g3d_config
);
393 _eglInitConfig(&gconf
->base
, dpy
, id
);
394 if (!egl_g3d_init_config(drv
, dpy
, &gconf
->base
,
395 native_configs
[i
], depth_stencil_formats
[j
])) {
400 _eglAddConfig(dpy
, &gconf
->base
);
406 FREE(native_configs
);
411 egl_g3d_invalid_surface(struct native_display
*ndpy
,
412 struct native_surface
*nsurf
,
413 unsigned int seq_num
)
415 /* XXX not thread safe? */
416 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(nsurf
->user_data
);
417 struct egl_g3d_context
*gctx
;
420 * Some functions such as egl_g3d_copy_buffers create a temporary native
421 * surface. There is no gsurf associated with it.
423 gctx
= (gsurf
) ? egl_g3d_context(gsurf
->base
.CurrentContext
) : NULL
;
425 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
, gsurf
->stfbi
);
428 static struct native_event_handler egl_g3d_native_event_handler
= {
429 .invalid_surface
= egl_g3d_invalid_surface
433 egl_g3d_terminate(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
435 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
438 _eglReleaseDisplayResources(drv
, dpy
);
439 _eglCleanupDisplay(dpy
);
442 gdpy
->pipe
->destroy(gdpy
->pipe
);
445 for (i
= 0; i
< dpy
->NumScreens
; i
++) {
446 struct egl_g3d_screen
*gscr
= egl_g3d_screen(dpy
->Screens
[i
]);
447 FREE(gscr
->native_modes
);
454 egl_g3d_destroy_st_manager(gdpy
->smapi
);
457 gdpy
->native
->destroy(gdpy
->native
);
460 dpy
->DriverData
= NULL
;
466 egl_g3d_initialize(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
467 EGLint
*major
, EGLint
*minor
)
469 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
470 struct egl_g3d_display
*gdpy
;
472 /* the probe object is unlikely to be needed again */
473 egl_g3d_destroy_probe(drv
, dpy
);
475 gdpy
= CALLOC_STRUCT(egl_g3d_display
);
477 _eglError(EGL_BAD_ALLOC
, "eglInitialize");
480 dpy
->DriverData
= gdpy
;
482 gdpy
->native
= native_create_display(dpy
->NativeDisplay
,
483 &egl_g3d_native_event_handler
);
485 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(no usable display)");
489 gdpy
->native
->user_data
= (void *) dpy
;
491 egl_g3d_init_st(&gdrv
->base
);
492 dpy
->ClientAPIsMask
= gdrv
->api_mask
;
494 gdpy
->smapi
= egl_g3d_create_st_manager(dpy
);
496 _eglError(EGL_NOT_INITIALIZED
,
497 "eglInitialize(failed to create st manager)");
501 #ifdef EGL_MESA_screen_surface
502 /* enable MESA_screen_surface before adding (and validating) configs */
503 if (gdpy
->native
->modeset
) {
504 dpy
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
505 egl_g3d_add_screens(drv
, dpy
);
509 dpy
->Extensions
.KHR_image_base
= EGL_TRUE
;
510 if (gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_USE_NATIVE_BUFFER
))
511 dpy
->Extensions
.KHR_image_pixmap
= EGL_TRUE
;
513 if (egl_g3d_add_configs(drv
, dpy
, 1) == 1) {
514 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(unable to add configs)");
525 egl_g3d_terminate(drv
, dpy
);
530 egl_g3d_get_proc_address(_EGLDriver
*drv
, const char *procname
)
532 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
536 /* in case this is called before a display is initialized */
537 egl_g3d_init_st(&gdrv
->base
);
539 for (i
= 0; i
< ST_API_COUNT
; i
++) {
540 struct st_api
*stapi
= gdrv
->stapis
[i
];
542 proc
= (_EGLProc
) stapi
->get_proc_address(stapi
, procname
);
548 return (_EGLProc
) NULL
;
552 egl_g3d_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
554 struct native_probe
*nprobe
;
555 enum native_probe_result res
;
558 nprobe
= egl_g3d_get_probe(drv
, dpy
);
559 res
= native_get_probe_result(nprobe
);
562 case NATIVE_PROBE_UNKNOWN
:
566 case NATIVE_PROBE_FALLBACK
:
569 case NATIVE_PROBE_SUPPORTED
:
572 case NATIVE_PROBE_EXACT
:
581 egl_g3d_unload(_EGLDriver
*drv
)
583 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
585 egl_g3d_destroy_st_apis();
586 egl_g3d_destroy_probe(drv
, NULL
);
591 _eglMain(const char *args
)
593 static char driver_name
[64];
594 struct egl_g3d_driver
*gdrv
;
596 util_snprintf(driver_name
, sizeof(driver_name
),
597 "Gallium/%s", native_get_name());
599 gdrv
= CALLOC_STRUCT(egl_g3d_driver
);
603 egl_g3d_init_driver_api(&gdrv
->base
);
604 gdrv
->base
.API
.Initialize
= egl_g3d_initialize
;
605 gdrv
->base
.API
.Terminate
= egl_g3d_terminate
;
606 gdrv
->base
.API
.GetProcAddress
= egl_g3d_get_proc_address
;
608 gdrv
->base
.Name
= driver_name
;
609 gdrv
->base
.Probe
= egl_g3d_probe
;
610 gdrv
->base
.Unload
= egl_g3d_unload
;
612 /* the key is " EGL G3D" */
613 gdrv
->probe_key
= 0x0E61063D;