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"
38 #include "egl_g3d_loader.h"
42 * Get the native platform.
44 static const struct native_platform
*
45 egl_g3d_get_platform(_EGLDriver
*drv
, _EGLPlatformType plat
)
47 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
49 if (!gdrv
->platforms
[plat
]) {
50 const char *plat_name
= NULL
;
51 const struct native_platform
*nplat
= NULL
;
54 case _EGL_PLATFORM_WINDOWS
:
55 plat_name
= "Windows";
56 #ifdef HAVE_GDI_BACKEND
57 nplat
= native_get_gdi_platform();
60 case _EGL_PLATFORM_X11
:
62 #ifdef HAVE_X11_BACKEND
63 nplat
= native_get_x11_platform();
66 case _EGL_PLATFORM_DRM
:
68 #ifdef HAVE_KMS_BACKEND
69 nplat
= native_get_kms_platform();
72 case _EGL_PLATFORM_FBDEV
:
74 #ifdef HAVE_FBDEV_BACKEND
75 nplat
= native_get_fbdev_platform();
83 _eglLog(_EGL_WARNING
, "unsupported platform %s", plat_name
);
85 gdrv
->platforms
[plat
] = nplat
;
88 return gdrv
->platforms
[plat
];
91 #ifdef EGL_MESA_screen_surface
94 egl_g3d_add_screens(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
96 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
97 const struct native_connector
**native_connectors
;
98 EGLint num_connectors
, i
;
101 gdpy
->native
->modeset
->get_connectors(gdpy
->native
, &num_connectors
, NULL
);
102 if (!num_connectors
) {
103 if (native_connectors
)
104 FREE(native_connectors
);
108 for (i
= 0; i
< num_connectors
; i
++) {
109 const struct native_connector
*nconn
= native_connectors
[i
];
110 struct egl_g3d_screen
*gscr
;
111 const struct native_mode
**native_modes
;
114 /* TODO support for hotplug */
116 gdpy
->native
->modeset
->get_modes(gdpy
->native
, nconn
, &num_modes
);
123 gscr
= CALLOC_STRUCT(egl_g3d_screen
);
129 _eglInitScreen(&gscr
->base
);
131 for (j
= 0; j
< num_modes
; j
++) {
132 const struct native_mode
*nmode
= native_modes
[j
];
135 mode
= _eglAddNewMode(&gscr
->base
, nmode
->width
, nmode
->height
,
136 nmode
->refresh_rate
, nmode
->desc
);
139 /* gscr->native_modes and gscr->base.Modes should be consistent */
140 assert(mode
== &gscr
->base
.Modes
[j
]);
143 gscr
->native
= nconn
;
144 gscr
->native_modes
= native_modes
;
146 _eglAddScreen(dpy
, &gscr
->base
);
149 FREE(native_connectors
);
152 #endif /* EGL_MESA_screen_surface */
155 * Initialize and validate the EGL config attributes.
158 init_config_attributes(_EGLConfig
*conf
, const struct native_config
*nconf
,
159 EGLint api_mask
, enum pipe_format depth_stencil_format
)
161 uint rgba
[4], depth_stencil
[2], buffer_size
;
165 /* get the color and depth/stencil component sizes */
166 assert(nconf
->color_format
!= PIPE_FORMAT_NONE
);
168 for (i
= 0; i
< 4; i
++) {
169 rgba
[i
] = util_format_get_component_bits(nconf
->color_format
,
170 UTIL_FORMAT_COLORSPACE_RGB
, i
);
171 buffer_size
+= rgba
[i
];
173 for (i
= 0; i
< 2; i
++) {
174 if (depth_stencil_format
!= PIPE_FORMAT_NONE
) {
176 util_format_get_component_bits(depth_stencil_format
,
177 UTIL_FORMAT_COLORSPACE_ZS
, i
);
180 depth_stencil
[i
] = 0;
185 if (nconf
->window_bit
)
186 surface_type
|= EGL_WINDOW_BIT
;
187 if (nconf
->pixmap_bit
)
188 surface_type
|= EGL_PIXMAP_BIT
;
189 #ifdef EGL_MESA_screen_surface
190 if (nconf
->scanout_bit
)
191 surface_type
|= EGL_SCREEN_BIT_MESA
;
194 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
))
195 surface_type
|= EGL_PBUFFER_BIT
;
197 SET_CONFIG_ATTRIB(conf
, EGL_CONFORMANT
, api_mask
);
198 SET_CONFIG_ATTRIB(conf
, EGL_RENDERABLE_TYPE
, api_mask
);
200 SET_CONFIG_ATTRIB(conf
, EGL_RED_SIZE
, rgba
[0]);
201 SET_CONFIG_ATTRIB(conf
, EGL_GREEN_SIZE
, rgba
[1]);
202 SET_CONFIG_ATTRIB(conf
, EGL_BLUE_SIZE
, rgba
[2]);
203 SET_CONFIG_ATTRIB(conf
, EGL_ALPHA_SIZE
, rgba
[3]);
204 SET_CONFIG_ATTRIB(conf
, EGL_BUFFER_SIZE
, buffer_size
);
206 SET_CONFIG_ATTRIB(conf
, EGL_DEPTH_SIZE
, depth_stencil
[0]);
207 SET_CONFIG_ATTRIB(conf
, EGL_STENCIL_SIZE
, depth_stencil
[1]);
209 SET_CONFIG_ATTRIB(conf
, EGL_SURFACE_TYPE
, surface_type
);
211 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_RENDERABLE
, EGL_TRUE
);
212 if (surface_type
& EGL_WINDOW_BIT
) {
213 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_ID
, nconf
->native_visual_id
);
214 SET_CONFIG_ATTRIB(conf
, EGL_NATIVE_VISUAL_TYPE
,
215 nconf
->native_visual_type
);
218 if (surface_type
& EGL_PBUFFER_BIT
) {
219 SET_CONFIG_ATTRIB(conf
, EGL_BIND_TO_TEXTURE_RGB
, EGL_TRUE
);
221 SET_CONFIG_ATTRIB(conf
, EGL_BIND_TO_TEXTURE_RGBA
, EGL_TRUE
);
223 SET_CONFIG_ATTRIB(conf
, EGL_MAX_PBUFFER_WIDTH
, 4096);
224 SET_CONFIG_ATTRIB(conf
, EGL_MAX_PBUFFER_HEIGHT
, 4096);
225 SET_CONFIG_ATTRIB(conf
, EGL_MAX_PBUFFER_PIXELS
, 4096 * 4096);
228 SET_CONFIG_ATTRIB(conf
, EGL_LEVEL
, nconf
->level
);
229 SET_CONFIG_ATTRIB(conf
, EGL_SAMPLES
, nconf
->samples
);
230 SET_CONFIG_ATTRIB(conf
, EGL_SAMPLE_BUFFERS
, 1);
232 if (nconf
->slow_config
)
233 SET_CONFIG_ATTRIB(conf
, EGL_CONFIG_CAVEAT
, EGL_SLOW_CONFIG
);
235 if (nconf
->transparent_rgb
) {
236 rgba
[0] = nconf
->transparent_rgb_values
[0];
237 rgba
[1] = nconf
->transparent_rgb_values
[1];
238 rgba
[2] = nconf
->transparent_rgb_values
[2];
240 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_TYPE
, EGL_TRANSPARENT_RGB
);
241 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_RED_VALUE
, rgba
[0]);
242 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_GREEN_VALUE
, rgba
[1]);
243 SET_CONFIG_ATTRIB(conf
, EGL_TRANSPARENT_BLUE_VALUE
, rgba
[2]);
246 return _eglValidateConfig(conf
, EGL_FALSE
);
250 * Initialize an EGL config from the native config.
253 egl_g3d_init_config(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
254 _EGLConfig
*conf
, const struct native_config
*nconf
,
255 enum pipe_format depth_stencil_format
)
257 struct egl_g3d_config
*gconf
= egl_g3d_config(conf
);
258 EGLint buffer_mask
, api_mask
;
262 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_LEFT
))
263 buffer_mask
|= ST_ATTACHMENT_FRONT_LEFT_MASK
;
264 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
))
265 buffer_mask
|= ST_ATTACHMENT_BACK_LEFT_MASK
;
266 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_FRONT_RIGHT
))
267 buffer_mask
|= ST_ATTACHMENT_FRONT_RIGHT_MASK
;
268 if (nconf
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_RIGHT
))
269 buffer_mask
|= ST_ATTACHMENT_BACK_RIGHT_MASK
;
271 gconf
->stvis
.buffer_mask
= buffer_mask
;
272 gconf
->stvis
.color_format
= nconf
->color_format
;
273 gconf
->stvis
.depth_stencil_format
= depth_stencil_format
;
274 gconf
->stvis
.accum_format
= PIPE_FORMAT_NONE
;
275 gconf
->stvis
.samples
= nconf
->samples
;
277 gconf
->stvis
.render_buffer
= (buffer_mask
& ST_ATTACHMENT_BACK_LEFT_MASK
) ?
278 ST_ATTACHMENT_BACK_LEFT
: ST_ATTACHMENT_FRONT_LEFT
;
280 api_mask
= dpy
->ClientAPIsMask
;
281 /* this is required by EGL, not by OpenGL ES */
282 if (nconf
->window_bit
&&
283 gconf
->stvis
.render_buffer
!= ST_ATTACHMENT_BACK_LEFT
)
284 api_mask
&= ~(EGL_OPENGL_ES_BIT
| EGL_OPENGL_ES2_BIT
);
287 _eglLog(_EGL_DEBUG
, "no state tracker supports config 0x%x",
288 nconf
->native_visual_id
);
291 valid
= init_config_attributes(&gconf
->base
,
292 nconf
, api_mask
, depth_stencil_format
);
294 _eglLog(_EGL_DEBUG
, "skip invalid config 0x%x", nconf
->native_visual_id
);
298 gconf
->native
= nconf
;
304 * Get all interested depth/stencil formats of a display.
307 egl_g3d_fill_depth_stencil_formats(_EGLDisplay
*dpy
,
308 enum pipe_format formats
[8])
310 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
311 struct pipe_screen
*screen
= gdpy
->native
->screen
;
312 const EGLint candidates
[] = {
313 1, PIPE_FORMAT_Z16_UNORM
,
314 1, PIPE_FORMAT_Z32_UNORM
,
315 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED
, PIPE_FORMAT_S8_USCALED_Z24_UNORM
,
316 2, PIPE_FORMAT_Z24X8_UNORM
, PIPE_FORMAT_X8Z24_UNORM
,
319 const EGLint
*fmt
= candidates
;
323 formats
[count
++] = PIPE_FORMAT_NONE
;
326 EGLint i
, n
= *fmt
++;
328 /* pick the first supported format */
329 for (i
= 0; i
< n
; i
++) {
330 if (screen
->is_format_supported(screen
, fmt
[i
],
331 PIPE_TEXTURE_2D
, 0, PIPE_BIND_DEPTH_STENCIL
, 0)) {
332 formats
[count
++] = fmt
[i
];
344 * Add configs to display and return the next config ID.
347 egl_g3d_add_configs(_EGLDriver
*drv
, _EGLDisplay
*dpy
, EGLint id
)
349 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
350 const struct native_config
**native_configs
;
351 enum pipe_format depth_stencil_formats
[8];
352 int num_formats
, num_configs
, i
, j
;
354 native_configs
= gdpy
->native
->get_configs(gdpy
->native
, &num_configs
);
357 FREE(native_configs
);
361 num_formats
= egl_g3d_fill_depth_stencil_formats(dpy
,
362 depth_stencil_formats
);
364 for (i
= 0; i
< num_configs
; i
++) {
365 for (j
= 0; j
< num_formats
; j
++) {
366 struct egl_g3d_config
*gconf
;
368 gconf
= CALLOC_STRUCT(egl_g3d_config
);
370 _eglInitConfig(&gconf
->base
, dpy
, id
);
371 if (!egl_g3d_init_config(drv
, dpy
, &gconf
->base
,
372 native_configs
[i
], depth_stencil_formats
[j
])) {
377 _eglAddConfig(dpy
, &gconf
->base
);
383 FREE(native_configs
);
388 egl_g3d_invalid_surface(struct native_display
*ndpy
,
389 struct native_surface
*nsurf
,
390 unsigned int seq_num
)
392 /* XXX not thread safe? */
393 struct egl_g3d_surface
*gsurf
= egl_g3d_surface(nsurf
->user_data
);
394 struct egl_g3d_context
*gctx
;
397 * Some functions such as egl_g3d_copy_buffers create a temporary native
398 * surface. There is no gsurf associated with it.
400 gctx
= (gsurf
) ? egl_g3d_context(gsurf
->base
.CurrentContext
) : NULL
;
402 gctx
->stctxi
->notify_invalid_framebuffer(gctx
->stctxi
, gsurf
->stfbi
);
405 static struct pipe_screen
*
406 egl_g3d_new_drm_screen(struct native_display
*ndpy
, const char *name
, int fd
)
408 _EGLDisplay
*dpy
= (_EGLDisplay
*) ndpy
->user_data
;
409 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
410 return gdpy
->loader
->create_drm_screen(name
, fd
);
413 static struct pipe_screen
*
414 egl_g3d_new_sw_screen(struct native_display
*ndpy
, struct sw_winsys
*ws
)
416 _EGLDisplay
*dpy
= (_EGLDisplay
*) ndpy
->user_data
;
417 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
418 return gdpy
->loader
->create_sw_screen(ws
);
421 static struct native_event_handler egl_g3d_native_event_handler
= {
422 egl_g3d_invalid_surface
,
423 egl_g3d_new_drm_screen
,
424 egl_g3d_new_sw_screen
428 egl_g3d_free_config(void *conf
)
430 struct egl_g3d_config
*gconf
= egl_g3d_config((_EGLConfig
*) conf
);
435 egl_g3d_free_screen(void *scr
)
437 #ifdef EGL_MESA_screen_surface
438 struct egl_g3d_screen
*gscr
= egl_g3d_screen((_EGLScreen
*) scr
);
439 FREE(gscr
->native_modes
);
445 egl_g3d_terminate(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
447 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
449 _eglReleaseDisplayResources(drv
, dpy
);
452 gdpy
->pipe
->destroy(gdpy
->pipe
);
455 _eglDestroyArray(dpy
->Configs
, egl_g3d_free_config
);
459 _eglDestroyArray(dpy
->Screens
, egl_g3d_free_screen
);
463 _eglCleanupDisplay(dpy
);
466 egl_g3d_destroy_st_manager(gdpy
->smapi
);
469 gdpy
->native
->destroy(gdpy
->native
);
472 dpy
->DriverData
= NULL
;
478 egl_g3d_initialize(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
479 EGLint
*major
, EGLint
*minor
)
481 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
482 struct egl_g3d_display
*gdpy
;
483 const struct native_platform
*nplat
;
485 nplat
= egl_g3d_get_platform(drv
, dpy
->Platform
);
489 gdpy
= CALLOC_STRUCT(egl_g3d_display
);
491 _eglError(EGL_BAD_ALLOC
, "eglInitialize");
494 gdpy
->loader
= gdrv
->loader
;
495 dpy
->DriverData
= gdpy
;
497 _eglLog(_EGL_INFO
, "use %s for display %p", nplat
->name
, dpy
->PlatformDisplay
);
498 gdpy
->native
= nplat
->create_display(dpy
->PlatformDisplay
,
499 &egl_g3d_native_event_handler
, (void *) dpy
);
501 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(no usable display)");
505 if (gdpy
->loader
->api_mask
& (1 << ST_API_OPENGL
))
506 dpy
->ClientAPIsMask
|= EGL_OPENGL_BIT
;
507 if (gdpy
->loader
->api_mask
& (1 << ST_API_OPENGL_ES1
))
508 dpy
->ClientAPIsMask
|= EGL_OPENGL_ES_BIT
;
509 if (gdpy
->loader
->api_mask
& (1 << ST_API_OPENGL_ES2
))
510 dpy
->ClientAPIsMask
|= EGL_OPENGL_ES2_BIT
;
511 if (gdpy
->loader
->api_mask
& (1 << ST_API_OPENVG
))
512 dpy
->ClientAPIsMask
|= EGL_OPENVG_BIT
;
514 gdpy
->smapi
= egl_g3d_create_st_manager(dpy
);
516 _eglError(EGL_NOT_INITIALIZED
,
517 "eglInitialize(failed to create st manager)");
521 #ifdef EGL_MESA_screen_surface
522 /* enable MESA_screen_surface before adding (and validating) configs */
523 if (gdpy
->native
->modeset
) {
524 dpy
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
525 egl_g3d_add_screens(drv
, dpy
);
529 dpy
->Extensions
.KHR_image_base
= EGL_TRUE
;
530 if (gdpy
->native
->get_param(gdpy
->native
, NATIVE_PARAM_USE_NATIVE_BUFFER
))
531 dpy
->Extensions
.KHR_image_pixmap
= EGL_TRUE
;
533 dpy
->Extensions
.KHR_reusable_sync
= EGL_TRUE
;
534 dpy
->Extensions
.KHR_fence_sync
= EGL_TRUE
;
536 dpy
->Extensions
.KHR_surfaceless_gles1
= EGL_TRUE
;
537 dpy
->Extensions
.KHR_surfaceless_gles2
= EGL_TRUE
;
538 dpy
->Extensions
.KHR_surfaceless_opengl
= EGL_TRUE
;
540 if (dpy
->Platform
== _EGL_PLATFORM_DRM
) {
541 dpy
->Extensions
.MESA_drm_display
= EGL_TRUE
;
542 dpy
->Extensions
.MESA_drm_image
= EGL_TRUE
;
545 if (egl_g3d_add_configs(drv
, dpy
, 1) == 1) {
546 _eglError(EGL_NOT_INITIALIZED
, "eglInitialize(unable to add configs)");
557 egl_g3d_terminate(drv
, dpy
);
562 egl_g3d_get_proc_address(_EGLDriver
*drv
, const char *procname
)
564 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);
565 struct st_api
*stapi
= NULL
;
567 if (procname
&& procname
[0] == 'v' && procname
[1] == 'g')
568 stapi
= gdrv
->loader
->get_st_api(ST_API_OPENVG
);
569 else if (procname
&& procname
[0] == 'g' && procname
[1] == 'l')
570 stapi
= gdrv
->loader
->guess_gl_api();
572 return (_EGLProc
) ((stapi
) ?
573 stapi
->get_proc_address(stapi
, procname
) : NULL
);
577 egl_g3d_probe(_EGLDriver
*drv
, _EGLDisplay
*dpy
)
579 return (egl_g3d_get_platform(drv
, dpy
->Platform
)) ? 90 : 0;
583 egl_g3d_create_driver(const struct egl_g3d_loader
*loader
)
585 struct egl_g3d_driver
*gdrv
;
587 gdrv
= CALLOC_STRUCT(egl_g3d_driver
);
591 gdrv
->loader
= loader
;
593 egl_g3d_init_driver_api(&gdrv
->base
);
594 gdrv
->base
.API
.Initialize
= egl_g3d_initialize
;
595 gdrv
->base
.API
.Terminate
= egl_g3d_terminate
;
596 gdrv
->base
.API
.GetProcAddress
= egl_g3d_get_proc_address
;
598 gdrv
->base
.Probe
= egl_g3d_probe
;
600 /* to be filled by the caller */
601 gdrv
->base
.Name
= NULL
;
602 gdrv
->base
.Unload
= NULL
;
608 egl_g3d_destroy_driver(_EGLDriver
*drv
)
610 struct egl_g3d_driver
*gdrv
= egl_g3d_driver(drv
);