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 egl_g3d_invalid_surface(struct native_display *ndpy,
43 struct native_surface *nsurf,
46 /* XXX not thread safe? */
47 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
48 struct egl_g3d_context *gctx;
51 * Some functions such as egl_g3d_copy_buffers create a temporary native
52 * surface. There is no gsurf associated with it.
54 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
56 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
59 static struct pipe_screen *
60 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
62 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
63 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
64 return gdpy->loader->create_drm_screen(name, fd);
67 static struct pipe_screen *
68 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
70 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
71 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
72 return gdpy->loader->create_sw_screen(ws);
75 static struct pipe_resource *
76 egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image)
78 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
79 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
80 struct st_egl_image img;
81 struct pipe_resource *resource = NULL;
83 memset(&img, 0, sizeof(img));
84 if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img))
85 resource = img.texture;
90 static const struct native_event_handler egl_g3d_native_event_handler = {
91 egl_g3d_invalid_surface,
92 egl_g3d_new_drm_screen,
93 egl_g3d_new_sw_screen,
94 egl_g3d_lookup_egl_image
98 * Get the native platform.
100 static const struct native_platform *
101 egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
103 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
105 if (!gdrv->platforms[plat]) {
106 const char *plat_name = NULL;
107 const struct native_platform *nplat = NULL;
110 case _EGL_PLATFORM_WINDOWS:
111 plat_name = "Windows";
112 #ifdef HAVE_GDI_BACKEND
113 nplat = native_get_gdi_platform(&egl_g3d_native_event_handler);
116 case _EGL_PLATFORM_X11:
118 #ifdef HAVE_X11_BACKEND
119 nplat = native_get_x11_platform(&egl_g3d_native_event_handler);
122 case _EGL_PLATFORM_WAYLAND:
123 plat_name = "wayland";
124 #ifdef HAVE_WAYLAND_BACKEND
125 nplat = native_get_wayland_platform(&egl_g3d_native_event_handler);
128 case _EGL_PLATFORM_DRM:
130 #ifdef HAVE_DRM_BACKEND
131 nplat = native_get_drm_platform(&egl_g3d_native_event_handler);
134 case _EGL_PLATFORM_FBDEV:
136 #ifdef HAVE_FBDEV_BACKEND
137 nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler);
145 _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
147 gdrv->platforms[plat] = nplat;
150 return gdrv->platforms[plat];
153 #ifdef EGL_MESA_screen_surface
156 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
158 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
159 const struct native_connector **native_connectors;
160 EGLint num_connectors, i;
163 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
164 if (!num_connectors) {
165 if (native_connectors)
166 FREE(native_connectors);
170 for (i = 0; i < num_connectors; i++) {
171 const struct native_connector *nconn = native_connectors[i];
172 struct egl_g3d_screen *gscr;
173 const struct native_mode **native_modes;
176 /* TODO support for hotplug */
178 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
185 gscr = CALLOC_STRUCT(egl_g3d_screen);
191 _eglInitScreen(&gscr->base, dpy, num_modes);
192 for (j = 0; j < gscr->base.NumModes; j++) {
193 const struct native_mode *nmode = native_modes[j];
194 _EGLMode *mode = &gscr->base.Modes[j];
196 mode->Width = nmode->width;
197 mode->Height = nmode->height;
198 mode->RefreshRate = nmode->refresh_rate;
199 mode->Optimal = EGL_FALSE;
200 mode->Interlaced = EGL_FALSE;
201 /* no need to strdup() */
202 mode->Name = nmode->desc;
205 gscr->native = nconn;
206 gscr->native_modes = native_modes;
208 _eglLinkScreen(&gscr->base);
211 FREE(native_connectors);
214 #endif /* EGL_MESA_screen_surface */
217 * Initialize and validate the EGL config attributes.
220 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
221 EGLint api_mask, enum pipe_format depth_stencil_format,
222 EGLBoolean preserve_buffer, EGLint max_swap_interval)
224 uint rgba[4], depth_stencil[2], buffer_size;
228 /* get the color and depth/stencil component sizes */
229 assert(nconf->color_format != PIPE_FORMAT_NONE);
231 for (i = 0; i < 4; i++) {
232 rgba[i] = util_format_get_component_bits(nconf->color_format,
233 UTIL_FORMAT_COLORSPACE_RGB, i);
234 buffer_size += rgba[i];
236 for (i = 0; i < 2; i++) {
237 if (depth_stencil_format != PIPE_FORMAT_NONE) {
239 util_format_get_component_bits(depth_stencil_format,
240 UTIL_FORMAT_COLORSPACE_ZS, i);
243 depth_stencil[i] = 0;
248 /* pixmap surfaces should be EGL_SINGLE_BUFFER */
249 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) {
250 if (nconf->pixmap_bit)
251 surface_type |= EGL_PIXMAP_BIT;
253 /* the others surfaces should be EGL_BACK_BUFFER (or settable) */
254 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) {
255 if (nconf->window_bit)
256 surface_type |= EGL_WINDOW_BIT;
257 #ifdef EGL_MESA_screen_surface
258 if (nconf->scanout_bit)
259 surface_type |= EGL_SCREEN_BIT_MESA;
261 surface_type |= EGL_PBUFFER_BIT;
264 conf->Conformant = api_mask;
265 conf->RenderableType = api_mask;
267 conf->RedSize = rgba[0];
268 conf->GreenSize = rgba[1];
269 conf->BlueSize = rgba[2];
270 conf->AlphaSize = rgba[3];
271 conf->BufferSize = buffer_size;
273 conf->DepthSize = depth_stencil[0];
274 conf->StencilSize = depth_stencil[1];
276 /* st/vega will allocate the mask on demand */
277 if (api_mask & EGL_OPENVG_BIT)
278 conf->AlphaMaskSize = 8;
280 conf->SurfaceType = surface_type;
282 conf->NativeRenderable = EGL_TRUE;
283 if (surface_type & EGL_WINDOW_BIT) {
284 conf->NativeVisualID = nconf->native_visual_id;
285 conf->NativeVisualType = nconf->native_visual_type;
288 if (surface_type & EGL_PBUFFER_BIT) {
289 conf->BindToTextureRGB = EGL_TRUE;
291 conf->BindToTextureRGBA = EGL_TRUE;
293 conf->MaxPbufferWidth = 4096;
294 conf->MaxPbufferHeight = 4096;
295 conf->MaxPbufferPixels = 4096 * 4096;
298 conf->Level = nconf->level;
300 if (nconf->transparent_rgb) {
301 conf->TransparentType = EGL_TRANSPARENT_RGB;
302 conf->TransparentRedValue = nconf->transparent_rgb_values[0];
303 conf->TransparentGreenValue = nconf->transparent_rgb_values[1];
304 conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
307 conf->MinSwapInterval = 0;
308 conf->MaxSwapInterval = max_swap_interval;
310 conf->SurfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
312 return _eglValidateConfig(conf, EGL_FALSE);
316 * Initialize an EGL config from the native config.
319 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
320 _EGLConfig *conf, const struct native_config *nconf,
321 enum pipe_format depth_stencil_format,
322 int preserve_buffer, int max_swap_interval)
324 struct egl_g3d_config *gconf = egl_g3d_config(conf);
329 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
330 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
331 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
332 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
333 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
334 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
335 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
336 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
338 gconf->stvis.buffer_mask = buffer_mask;
339 gconf->stvis.color_format = nconf->color_format;
340 gconf->stvis.depth_stencil_format = depth_stencil_format;
341 gconf->stvis.accum_format = PIPE_FORMAT_NONE;
342 gconf->stvis.samples = 0;
344 /* will be overridden per surface */
345 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
346 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
348 valid = init_config_attributes(&gconf->base,
349 nconf, dpy->ClientAPIs, depth_stencil_format,
350 preserve_buffer, max_swap_interval);
352 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
356 gconf->native = nconf;
362 * Get all interested depth/stencil formats of a display.
365 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
366 enum pipe_format formats[8])
368 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
369 struct pipe_screen *screen = gdpy->native->screen;
370 const EGLint candidates[] = {
371 1, PIPE_FORMAT_Z16_UNORM,
372 1, PIPE_FORMAT_Z32_UNORM,
373 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
374 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
377 const EGLint *fmt = candidates;
381 formats[count++] = PIPE_FORMAT_NONE;
384 EGLint i, n = *fmt++;
386 /* pick the first supported format */
387 for (i = 0; i < n; i++) {
388 if (screen->is_format_supported(screen, fmt[i],
389 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) {
390 formats[count++] = fmt[i];
402 * Add configs to display and return the next config ID.
405 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
407 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
408 const struct native_config **native_configs;
409 enum pipe_format depth_stencil_formats[8];
410 int num_formats, num_configs, i, j;
411 int preserve_buffer, max_swap_interval;
413 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
416 FREE(native_configs);
421 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
423 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
425 num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
426 depth_stencil_formats);
428 for (i = 0; i < num_configs; i++) {
429 for (j = 0; j < num_formats; j++) {
430 struct egl_g3d_config *gconf;
432 gconf = CALLOC_STRUCT(egl_g3d_config);
434 _eglInitConfig(&gconf->base, dpy, id);
435 if (!egl_g3d_init_config(drv, dpy, &gconf->base,
436 native_configs[i], depth_stencil_formats[j],
437 preserve_buffer, max_swap_interval)) {
442 _eglLinkConfig(&gconf->base);
448 FREE(native_configs);
453 egl_g3d_free_config(void *conf)
455 struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
460 egl_g3d_free_screen(void *scr)
462 #ifdef EGL_MESA_screen_surface
463 struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
464 FREE(gscr->native_modes);
470 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
472 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
474 _eglReleaseDisplayResources(drv, dpy);
477 _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
481 _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
485 _eglCleanupDisplay(dpy);
488 egl_g3d_destroy_st_manager(gdpy->smapi);
491 gdpy->native->destroy(gdpy->native);
494 dpy->DriverData = NULL;
500 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
502 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
503 struct egl_g3d_display *gdpy;
504 const struct native_platform *nplat;
506 nplat = egl_g3d_get_platform(drv, dpy->Platform);
510 if (dpy->Options.TestOnly)
513 gdpy = CALLOC_STRUCT(egl_g3d_display);
515 _eglError(EGL_BAD_ALLOC, "eglInitialize");
518 gdpy->loader = gdrv->loader;
519 dpy->DriverData = gdpy;
521 _eglLog(_EGL_INFO, "use %s for display %p",
522 nplat->name, dpy->PlatformDisplay);
524 nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback);
526 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
529 gdpy->native->user_data = (void *) dpy;
530 if (!gdpy->native->init_screen(gdpy->native)) {
531 _eglError(EGL_NOT_INITIALIZED,
532 "eglInitialize(failed to initialize screen)");
536 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK)
537 dpy->ClientAPIs |= EGL_OPENGL_BIT;
538 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK)
539 dpy->ClientAPIs |= EGL_OPENGL_ES_BIT;
540 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK)
541 dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT;
542 if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK)
543 dpy->ClientAPIs |= EGL_OPENVG_BIT;
545 gdpy->smapi = egl_g3d_create_st_manager(dpy);
547 _eglError(EGL_NOT_INITIALIZED,
548 "eglInitialize(failed to create st manager)");
552 #ifdef EGL_MESA_screen_surface
553 /* enable MESA_screen_surface before adding (and validating) configs */
554 if (gdpy->native->modeset) {
555 dpy->Extensions.MESA_screen_surface = EGL_TRUE;
556 egl_g3d_add_screens(drv, dpy);
560 dpy->Extensions.KHR_image_base = EGL_TRUE;
561 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
562 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
564 dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
565 dpy->Extensions.KHR_fence_sync = EGL_TRUE;
567 dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
568 dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
569 dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
571 if (dpy->Platform == _EGL_PLATFORM_DRM) {
572 dpy->Extensions.MESA_drm_display = EGL_TRUE;
573 if (gdpy->native->buffer)
574 dpy->Extensions.MESA_drm_image = EGL_TRUE;
577 if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
578 dpy->Extensions.MESA_drm_image = EGL_TRUE;
580 #ifdef EGL_WL_bind_wayland_display
581 if (gdpy->native->wayland_bufmgr)
582 dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
585 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
586 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
590 dpy->VersionMajor = 1;
591 dpy->VersionMinor = 4;
597 egl_g3d_terminate(drv, dpy);
602 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
604 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
605 struct st_api *stapi = NULL;
607 if (procname && procname[0] == 'v' && procname[1] == 'g')
608 stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
609 else if (procname && procname[0] == 'g' && procname[1] == 'l')
610 stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
612 return (_EGLProc) ((stapi) ?
613 stapi->get_proc_address(stapi, procname) : NULL);
617 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
619 struct egl_g3d_driver *gdrv;
621 gdrv = CALLOC_STRUCT(egl_g3d_driver);
625 gdrv->loader = loader;
627 egl_g3d_init_driver_api(&gdrv->base);
628 gdrv->base.API.Initialize = egl_g3d_initialize;
629 gdrv->base.API.Terminate = egl_g3d_terminate;
630 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
632 /* to be filled by the caller */
633 gdrv->base.Name = NULL;
634 gdrv->base.Unload = NULL;
640 egl_g3d_destroy_driver(_EGLDriver *drv)
642 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);