diff options
Diffstat (limited to 'src/gallium/state_trackers/egl')
22 files changed, 1425 insertions, 335 deletions
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 8cfcef968e..53673a78a9 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -23,6 +23,14 @@ x11_SOURCES = $(wildcard x11/*.c) \ $(TOP)/src/glx/dri2.c x11_OBJECTS = $(x11_SOURCES:.c=.o) +wayland_INCLUDES = \ + -I$(TOP)/src/gallium/winsys \ + -I$(TOP)/src/egl/wayland/wayland-egl \ + -I$(TOP)/src/egl/wayland/wayland-drm \ + $(shell pkg-config --cflags-only-I libdrm wayland-client) + +wayland_SOURCES = $(wildcard wayland/*.c) +wayland_OBJECTS = $(wayland_SOURCES:.c=.o) drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) drm_SOURCES = $(wildcard drm/*.c) @@ -45,6 +53,10 @@ ifneq ($(findstring x11, $(EGL_PLATFORMS)),) EGL_OBJECTS += $(x11_OBJECTS) EGL_CPPFLAGS += -DHAVE_X11_BACKEND endif +ifneq ($(findstring wayland, $(EGL_PLATFORMS)),) +EGL_OBJECTS += $(wayland_OBJECTS) +EGL_CPPFLAGS += -DHAVE_WAYLAND_BACKEND +endif ifneq ($(findstring drm, $(EGL_PLATFORMS)),) EGL_OBJECTS += $(drm_OBJECTS) EGL_CPPFLAGS += -DHAVE_DRM_BACKEND @@ -87,6 +99,9 @@ $(common_OBJECTS): %.o: %.c $(x11_OBJECTS): %.o: %.c $(call egl-cc,x11) +$(wayland_OBJECTS): %.o: %.c + $(call egl-cc,wayland) + $(drm_OBJECTS): %.o: %.c $(call egl-cc,drm) diff --git a/src/gallium/state_trackers/egl/SConscript b/src/gallium/state_trackers/egl/SConscript index 50c7681995..9ade76ecbb 100644 --- a/src/gallium/state_trackers/egl/SConscript +++ b/src/gallium/state_trackers/egl/SConscript @@ -10,11 +10,8 @@ env.Append(CPPPATH = [ '#/src/gallium/winsys/sw', '.', ]) -env.Append(CPPDEFINES = [ - 'HAVE_GDI_BACKEND', -]) -common_sources = [ +sources = [ 'common/egl_g3d.c', 'common/egl_g3d_api.c', 'common/egl_g3d_image.c', @@ -23,12 +20,31 @@ common_sources = [ 'common/native_helper.c', ] -gdi_sources = common_sources + [ - 'gdi/native_gdi.c', -] +if env['platform'] == 'windows': + env.Append(CPPDEFINES = ['HAVE_GDI_BACKEND']) + sources.append('gdi/native_gdi.c') +else: + if env['x11']: + env.Append(CPPDEFINES = ['HAVE_X11_BACKEND']) + env.Prepend(CPPPATH = [ + '#/src/glx', + '#/src/mapi', + ]) + sources.append([ + 'x11/native_x11.c', + 'x11/native_dri2.c', + 'x11/native_ximage.c', + 'x11/x11_screen.c', + 'x11/glxinit.c']) + if env['dri']: + env.Append(CPPDEFINES = ['GLX_DIRECT_RENDERING']) + sources.append(['#/src/glx/dri2.c']) + if env['drm']: + env.Append(CPPDEFINES = ['HAVE_DRM_BACKEND']) + sources.append(['drm/native_drm.c', 'drm/modeset.c']) -st_egl_gdi = env.ConvenienceLibrary( - target = 'st_egl_gdi', - source = gdi_sources, +st_egl = env.ConvenienceLibrary( + target = 'st_egl', + source = sources, ) -Export('st_egl_gdi') +Export('st_egl') diff --git a/src/gallium/state_trackers/egl/android/native_android.cpp b/src/gallium/state_trackers/egl/android/native_android.cpp index 450eae3868..a584d54db4 100644 --- a/src/gallium/state_trackers/egl/android/native_android.cpp +++ b/src/gallium/state_trackers/egl/android/native_android.cpp @@ -34,7 +34,13 @@ extern "C" { #include "egllog.h" + +/* see get_drm_screen_name */ +#include <xf86drm.h> +#include <radeon_drm.h> +#include "radeon/drm/radeon_drm_public.h" } + #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_format.h" @@ -157,12 +163,12 @@ import_buffer(struct android_display *adpy, const struct pipe_resource *templ, if (templ->bind & PIPE_BIND_RENDER_TARGET) { if (!screen->is_format_supported(screen, templ->format, - templ->target, 0, PIPE_BIND_RENDER_TARGET, 0)) + templ->target, 0, PIPE_BIND_RENDER_TARGET)) LOGW("importing unsupported buffer as render target"); } if (templ->bind & PIPE_BIND_SAMPLER_VIEW) { if (!screen->is_format_supported(screen, templ->format, - templ->target, 0, PIPE_BIND_SAMPLER_VIEW, 0)) + templ->target, 0, PIPE_BIND_SAMPLER_VIEW)) LOGW("importing unsupported buffer as sampler view"); } @@ -399,7 +405,7 @@ android_display_create_window_surface(struct native_display *ndpy, LOGW("native window format 0x%x != config format 0x%x", format, nconf->color_format); if (!adpy->base.screen->is_format_supported(adpy->base.screen, - format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0)) { + format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { LOGE("and the native window cannot be used as a render target"); return NULL; } @@ -452,7 +458,7 @@ android_display_init_configs(struct native_display *ndpy) color_format = get_pipe_format(native_formats[i]); if (color_format == PIPE_FORMAT_NONE || !adpy->base.screen->is_format_supported(adpy->base.screen, - color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0)) { + color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { LOGI("skip unsupported native format 0x%x", native_formats[i]); continue; } @@ -461,8 +467,6 @@ android_display_init_configs(struct native_display *ndpy) aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT; aconf->base.color_format = color_format; aconf->base.window_bit = TRUE; - if (!adpy->use_drm) - aconf->base.slow_config = TRUE; aconf->base.native_visual_type = native_formats[i]; } @@ -470,66 +474,94 @@ android_display_init_configs(struct native_display *ndpy) return TRUE; } +static const char * +get_drm_screen_name(int fd, drmVersionPtr version) +{ + const char *name = version->name; + + if (name && !strcmp(name, "radeon")) { + int chip_id; + struct drm_radeon_info info; + + memset(&info, 0, sizeof(info)); + info.request = RADEON_INFO_DEVICE_ID; + info.value = pointer_to_intptr(&chip_id); + if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) + return NULL; + + name = is_r3xx(chip_id) ? "r300" : "r600"; + } + + return name; +} + static boolean -android_display_init(struct native_display *ndpy) +android_display_init_drm(struct native_display *ndpy) { struct android_display *adpy = android_display(ndpy); const hw_module_t *mod; int fd, err; - boolean force_sw; - char value[PROPERTY_VALUE_MAX]; - - if (property_get("debug.mesa.software", value, NULL)) - force_sw = (atoi(value) != 0); - else - force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); - /* try DRM first */ - if (!force_sw) { - err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); - if (!err) { - const gralloc_module_t *gr = (gralloc_module_t *) mod; + err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); + if (!err) { + const gralloc_module_t *gr = (gralloc_module_t *) mod; - err = -EINVAL; - if (gr->perform) - err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); + err = -EINVAL; + if (gr->perform) + err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); + } + if (!err && fd >= 0) { + drmVersionPtr version; + const char *name; + + version = drmGetVersion(fd); + if (version) { + name = get_drm_screen_name(fd, version); + if (name) { + adpy->base.screen = + adpy->event_handler->new_drm_screen(&adpy->base, name, fd); + } + drmFreeVersion(version); } - if (!err && fd >= 0) { - adpy->base.screen = - adpy->event_handler->new_drm_screen(&adpy->base, "i915", fd); - if (adpy->base.screen) - adpy->use_drm = TRUE; + else { + _eglLog(_EGL_WARNING, "invalid fd %d", fd); + err = -EINVAL; } if (adpy->base.screen) - LOGI("using DRM screen"); - else - LOGE("failed to create DRM screen"); + adpy->use_drm = TRUE; } - /* try SW screen */ - if (!adpy->base.screen) { - struct sw_winsys *ws = android_create_sw_winsys(); + if (adpy->base.screen) { + LOGI("using DRM screen"); + return TRUE; + } + else { + LOGE("failed to create DRM screen"); + return FALSE; + } +} - if (ws) { - adpy->base.screen = - adpy->event_handler->new_sw_screen(&adpy->base, ws); - } +static boolean +android_display_init_sw(struct native_display *ndpy) +{ + struct android_display *adpy = android_display(ndpy); + struct sw_winsys *ws; - if (adpy->base.screen) - LOGI("using SW screen"); - else - LOGE("failed to create SW screen"); + ws = android_create_sw_winsys(); + if (ws) { + adpy->base.screen = + adpy->event_handler->new_sw_screen(&adpy->base, ws); } if (adpy->base.screen) { - if (!android_display_init_configs(&adpy->base)) { - adpy->base.screen->destroy(adpy->base.screen); - adpy->base.screen = NULL; - } + LOGI("using SW screen"); + return TRUE; + } + else { + LOGE("failed to create SW screen"); + return FALSE; } - - return (adpy->base.screen != NULL); } static void @@ -603,9 +635,11 @@ static struct native_display_buffer android_display_buffer = { static struct android_display * android_display_create(struct native_event_handler *event_handler, - void *user_data) + boolean use_sw, void *user_data) { struct android_display *adpy; + char value[PROPERTY_VALUE_MAX]; + boolean force_sw; adpy = CALLOC_STRUCT(android_display); if (!adpy) @@ -614,7 +648,23 @@ android_display_create(struct native_event_handler *event_handler, adpy->event_handler = event_handler; adpy->base.user_data = user_data; - if (!android_display_init(&adpy->base)) { + if (property_get("debug.mesa.software", value, NULL)) + force_sw = (atoi(value) != 0); + else + force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); + + if (force_sw || use_sw) + android_display_init_sw(&adpy->base); + else + android_display_init_drm(&adpy->base); + + if (!adpy->base.screen) { + FREE(adpy); + return NULL; + } + + if (!android_display_init_configs(&adpy->base)) { + adpy->base.screen->destroy(adpy->base.screen); FREE(adpy); return NULL; } @@ -629,19 +679,27 @@ android_display_create(struct native_event_handler *event_handler, return adpy; } +static struct native_event_handler *android_event_handler; + +static void +native_set_event_handler(struct native_event_handler *event_handler) +{ + android_event_handler = event_handler; +} + static struct native_display * -native_create_display(void *dpy, struct native_event_handler *event_handler, - void *user_data) +native_create_display(void *dpy, boolean use_sw, void *user_data) { struct android_display *adpy; - adpy = android_display_create(event_handler, user_data); + adpy = android_display_create(android_event_handler, use_sw, user_data); return (adpy) ? &adpy->base : NULL; } static const struct native_platform android_platform = { "Android", /* name */ + native_set_event_handler, native_create_display }; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 604091aac0..e455167473 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -38,6 +38,46 @@ #include "egl_g3d_loader.h" #include "native.h" +static void +egl_g3d_invalid_surface(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num) +{ + /* XXX not thread safe? */ + struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); + struct egl_g3d_context *gctx; + + /* + * Some functions such as egl_g3d_copy_buffers create a temporary native + * surface. There is no gsurf associated with it. + */ + gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; + if (gctx) + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); +} + +static struct pipe_screen * +egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd) +{ + _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + return gdpy->loader->create_drm_screen(name, fd); +} + +static struct pipe_screen * +egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) +{ + _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + return gdpy->loader->create_sw_screen(ws); +} + +static struct native_event_handler egl_g3d_native_event_handler = { + egl_g3d_invalid_surface, + egl_g3d_new_drm_screen, + egl_g3d_new_sw_screen +}; + /** * Get the native platform. */ @@ -62,6 +102,12 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) #ifdef HAVE_X11_BACKEND nplat = native_get_x11_platform(); #endif + break; + case _EGL_PLATFORM_WAYLAND: + plat_name = "wayland"; +#ifdef HAVE_WAYLAND_BACKEND + nplat = native_get_wayland_platform(); +#endif break; case _EGL_PLATFORM_DRM: plat_name = "DRM"; @@ -85,7 +131,9 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) break; } - if (!nplat) + if (nplat) + nplat->set_event_handler(&egl_g3d_native_event_handler); + else _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name); gdrv->platforms[plat] = nplat; @@ -189,17 +237,21 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, } surface_type = 0x0; - if (nconf->window_bit) - surface_type |= EGL_WINDOW_BIT; - if (nconf->pixmap_bit) - surface_type |= EGL_PIXMAP_BIT; + /* pixmap surfaces should be EGL_SINGLE_BUFFER */ + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) { + if (nconf->pixmap_bit) + surface_type |= EGL_PIXMAP_BIT; + } + /* the others surfaces should be EGL_BACK_BUFFER (or settable) */ + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) { + if (nconf->window_bit) + surface_type |= EGL_WINDOW_BIT; #ifdef EGL_MESA_screen_surface - if (nconf->scanout_bit) - surface_type |= EGL_SCREEN_BIT_MESA; + if (nconf->scanout_bit) + surface_type |= EGL_SCREEN_BIT_MESA; #endif - - if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) surface_type |= EGL_PBUFFER_BIT; + } conf->Conformant = api_mask; conf->RenderableType = api_mask; @@ -232,11 +284,6 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, } conf->Level = nconf->level; - conf->Samples = nconf->samples; - conf->SampleBuffers = 0; - - if (nconf->slow_config) - conf->ConfigCaveat = EGL_SLOW_CONFIG; if (nconf->transparent_rgb) { conf->TransparentType = EGL_TRANSPARENT_RGB; @@ -263,13 +310,9 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, int preserve_buffer, int max_swap_interval) { struct egl_g3d_config *gconf = egl_g3d_config(conf); - EGLint buffer_mask, api_mask; + EGLint buffer_mask; EGLBoolean valid; - /* skip single-buffered configs */ - if (!(nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))) - return EGL_FALSE; - buffer_mask = 0x0; if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; @@ -284,24 +327,14 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, gconf->stvis.color_format = nconf->color_format; gconf->stvis.depth_stencil_format = depth_stencil_format; gconf->stvis.accum_format = PIPE_FORMAT_NONE; - gconf->stvis.samples = nconf->samples; + gconf->stvis.samples = 0; + /* will be overridden per surface */ gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; - api_mask = dpy->ClientAPIsMask; - /* this is required by EGL, not by OpenGL ES */ - if (nconf->window_bit && - gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) - api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); - - if (!api_mask) { - _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", - nconf->native_visual_id); - } - valid = init_config_attributes(&gconf->base, - nconf, api_mask, depth_stencil_format, + nconf, dpy->ClientAPIs, depth_stencil_format, preserve_buffer, max_swap_interval); if (!valid) { _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); @@ -341,7 +374,7 @@ egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, /* pick the first supported format */ for (i = 0; i < n; i++) { if (screen->is_format_supported(screen, fmt[i], - PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) { + PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) { formats[count++] = fmt[i]; break; } @@ -405,46 +438,6 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) } static void -egl_g3d_invalid_surface(struct native_display *ndpy, - struct native_surface *nsurf, - unsigned int seq_num) -{ - /* XXX not thread safe? */ - struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); - struct egl_g3d_context *gctx; - - /* - * Some functions such as egl_g3d_copy_buffers create a temporary native - * surface. There is no gsurf associated with it. - */ - gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; - if (gctx) - gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); -} - -static struct pipe_screen * -egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd) -{ - _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - return gdpy->loader->create_drm_screen(name, fd); -} - -static struct pipe_screen * -egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) -{ - _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - return gdpy->loader->create_sw_screen(ws); -} - -static struct native_event_handler egl_g3d_native_event_handler = { - egl_g3d_invalid_surface, - egl_g3d_new_drm_screen, - egl_g3d_new_sw_screen -}; - -static void egl_g3d_free_config(void *conf) { struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf); @@ -468,9 +461,6 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) _eglReleaseDisplayResources(drv, dpy); - if (gdpy->pipe) - gdpy->pipe->destroy(gdpy->pipe); - if (dpy->Configs) { _eglDestroyArray(dpy->Configs, egl_g3d_free_config); dpy->Configs = NULL; @@ -495,8 +485,7 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) } static EGLBoolean -egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, - EGLint *major, EGLint *minor) +egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct egl_g3d_display *gdpy; @@ -506,6 +495,9 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, if (!nplat) return EGL_FALSE; + if (dpy->Options.TestOnly) + return EGL_TRUE; + gdpy = CALLOC_STRUCT(egl_g3d_display); if (!gdpy) { _eglError(EGL_BAD_ALLOC, "eglInitialize"); @@ -516,20 +508,20 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); gdpy->native = nplat->create_display(dpy->PlatformDisplay, - &egl_g3d_native_event_handler, (void *) dpy); + dpy->Options.UseFallback, (void *) dpy); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) - dpy->ClientAPIsMask |= EGL_OPENGL_BIT; + dpy->ClientAPIs |= EGL_OPENGL_BIT; if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK) - dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT; + dpy->ClientAPIs |= EGL_OPENGL_ES_BIT; if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK) - dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; + dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT; if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK) - dpy->ClientAPIsMask |= EGL_OPENVG_BIT; + dpy->ClientAPIs |= EGL_OPENVG_BIT; gdpy->smapi = egl_g3d_create_st_manager(dpy); if (!gdpy->smapi) { @@ -563,6 +555,9 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, dpy->Extensions.MESA_drm_image = EGL_TRUE; } + if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer) + dpy->Extensions.MESA_drm_image = EGL_TRUE; + #ifdef EGL_ANDROID_image_native_buffer if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer) dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; @@ -573,8 +568,8 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, goto fail; } - *major = 1; - *minor = 4; + dpy->VersionMajor = 1; + dpy->VersionMinor = 4; return EGL_TRUE; @@ -599,12 +594,6 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) stapi->get_proc_address(stapi, procname) : NULL); } -static EGLint -egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) -{ - return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0; -} - _EGLDriver * egl_g3d_create_driver(const struct egl_g3d_loader *loader) { @@ -621,8 +610,6 @@ egl_g3d_create_driver(const struct egl_g3d_loader *loader) gdrv->base.API.Terminate = egl_g3d_terminate; gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; - gdrv->base.Probe = egl_g3d_probe; - /* to be filled by the caller */ gdrv->base.Name = NULL; gdrv->base.Unload = NULL; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index a5850635b2..2292d611fc 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -56,7 +56,6 @@ struct egl_g3d_display { const struct egl_g3d_loader *loader; struct st_manager *smapi; - struct pipe_context *pipe; }; struct egl_g3d_context { diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c index 8e53e1dccb..f1568329ec 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -158,17 +158,17 @@ egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs, (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria); /* perform sorting of configs */ - if (tmp_configs && tmp_size) { + if (configs && tmp_size) { _eglSortConfigs((const _EGLConfig **) tmp_configs, tmp_size, egl_g3d_compare_config, (void *) &criteria); - size = MIN2(tmp_size, size); - for (i = 0; i < size; i++) + tmp_size = MIN2(tmp_size, size); + for (i = 0; i < tmp_size; i++) configs[i] = _eglGetConfigHandle(tmp_configs[i]); } FREE(tmp_configs); - *num_configs = size; + *num_configs = tmp_size; return EGL_TRUE; } @@ -324,7 +324,8 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, } gsurf->stvis = gconf->stvis; - if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) + if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER && + gconf->stvis.buffer_mask & ST_ATTACHMENT_FRONT_LEFT_MASK) gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); @@ -402,7 +403,6 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attribs) { struct egl_g3d_surface *gsurf; - struct pipe_resource *ptex = NULL; gsurf = create_pbuffer_surface(dpy, conf, attribs, "eglCreatePbufferSurface"); @@ -411,13 +411,6 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, gsurf->client_buffer_type = EGL_NONE; - if (!gsurf->stfbi->validate(gsurf->stfbi, - &gsurf->stvis.render_buffer, 1, &ptex)) { - egl_g3d_destroy_st_framebuffer(gsurf->stfbi); - FREE(gsurf); - return NULL; - } - return &gsurf->base; } @@ -477,12 +470,14 @@ egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver *drv, _EGLDisplay *dpy, gsurf->client_buffer_type = buftype; gsurf->client_buffer = buffer; + /* validate now so that it fails if the client buffer is invalid */ if (!gsurf->stfbi->validate(gsurf->stfbi, &gsurf->stvis.render_buffer, 1, &ptex)) { egl_g3d_destroy_st_framebuffer(gsurf->stfbi); FREE(gsurf); return NULL; } + pipe_resource_reference(&ptex, NULL); return &gsurf->base; } @@ -533,8 +528,7 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, old_gctx = egl_g3d_context(old_ctx); if (old_gctx) { /* flush old context */ - old_gctx->stctxi->flush(old_gctx->stctxi, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + old_gctx->stctxi->flush(old_gctx->stctxi, ST_FLUSH_FRONT, NULL); } if (gctx) { @@ -611,8 +605,7 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) /* flush if the surface is current */ if (gctx) { - gctx->stctxi->flush(gctx->stctxi, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL); } return gsurf->native->present(gsurf->native, @@ -643,47 +636,36 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); _EGLContext *ctx = _eglGetCurrentContext(); - struct egl_g3d_config *gconf; struct native_surface *nsurf; struct pipe_resource *ptex; + struct pipe_context *pipe; if (!gsurf->render_texture) return EGL_TRUE; - gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); - if (!gconf) - return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); - - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, - target, gconf->native); + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, target, NULL); if (!nsurf) return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); /* flush if the surface is current */ if (ctx && ctx->DrawSurface == &gsurf->base) { struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stctxi->flush(gctx->stctxi, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL); } - /* create a pipe context to copy surfaces */ - if (!gdpy->pipe) { - gdpy->pipe = - gdpy->native->screen->context_create(gdpy->native->screen, NULL); - if (!gdpy->pipe) - return EGL_FALSE; - } + pipe = ndpy_get_copy_context(gdpy->native); + if (!pipe) + return EGL_FALSE; ptex = get_pipe_resource(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); if (ptex) { - struct pipe_resource *psrc = gsurf->render_texture; struct pipe_box src_box; + u_box_origin_2d(ptex->width0, ptex->height0, &src_box); - if (psrc) { - gdpy->pipe->resource_copy_region(gdpy->pipe, ptex, 0, 0, 0, 0, - gsurf->render_texture, 0, &src_box); - nsurf->present(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0); - } + pipe->resource_copy_region(pipe, ptex, 0, 0, 0, 0, + gsurf->render_texture, 0, &src_box); + pipe->flush(pipe, NULL); + nsurf->present(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0); pipe_resource_reference(&ptex, NULL); } @@ -701,10 +683,9 @@ egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) struct pipe_screen *screen = gdpy->native->screen; struct pipe_fence_handle *fence = NULL; - gctx->stctxi->flush(gctx->stctxi, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, &fence); if (fence) { - screen->fence_finish(screen, fence, 0); + screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); screen->fence_reference(screen, &fence, NULL); } @@ -773,8 +754,7 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, /* flush properly if the surface is bound */ if (gsurf->base.CurrentContext) { gctx = egl_g3d_context(gsurf->base.CurrentContext); - gctx->stctxi->flush(gctx->stctxi, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL); } gctx = egl_g3d_context(es1); @@ -888,25 +868,6 @@ egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, #endif /* EGL_MESA_screen_surface */ -/** - * Find a config that supports the pixmap. - */ -_EGLConfig * -egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf; - EGLint i; - - for (i = 0; i < dpy->Configs->Size; i++) { - gconf = egl_g3d_config((_EGLConfig *) dpy->Configs->Elements[i]); - if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) - break; - } - - return (i < dpy->Configs->Size) ? &gconf->base : NULL; -} - void egl_g3d_init_driver_api(_EGLDriver *drv) { diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.h b/src/gallium/state_trackers/egl/common/egl_g3d_api.h index d5196c12fe..17fd7958aa 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.h @@ -31,7 +31,4 @@ void egl_g3d_init_driver_api(_EGLDriver *drv); -_EGLConfig * -egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix); - #endif /* _EGL_G3D_API_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c index b53b121005..1d23305402 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -35,7 +35,6 @@ #include "native.h" #include "egl_g3d.h" -#include "egl_g3d_api.h" #include "egl_g3d_image.h" /* for struct winsys_handle */ @@ -53,17 +52,11 @@ static struct pipe_resource * egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf; struct native_surface *nsurf; struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; enum native_attachment natt; - gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix)); - if (!gconf) - return NULL; - - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, - pix, gconf->native); + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, pix, NULL); if (!nsurf) return NULL; @@ -123,6 +116,7 @@ egl_g3d_create_drm_buffer(_EGLDisplay *dpy, _EGLImage *img, templ.width0 = attrs.Width; templ.height0 = attrs.Height; templ.depth0 = 1; + templ.array_size = 1; /* * XXX fix apps (e.g. wayland) and pipe drivers (e.g. i915) and remove the @@ -147,7 +141,7 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, _EGLImageAttribs attrs; EGLint format; - if (dpy->Platform != _EGL_PLATFORM_DRM) + if (!dpy->Extensions.MESA_drm_image) return NULL; if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS) @@ -236,10 +230,12 @@ egl_g3d_reference_android_native_buffer(_EGLDisplay *dpy, memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.format = format; - templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + /* assume for texturing only */ + templ.bind = PIPE_BIND_SAMPLER_VIEW; templ.width0 = buf->width; templ.height0 = buf->height; templ.depth0 = 1; + templ.array_size = 1; res = gdpy->native->buffer->import_buffer(gdpy->native, &templ, (void *) buf); @@ -385,7 +381,7 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, struct egl_g3d_image *gimg = egl_g3d_image(img); struct winsys_handle wsh; - if (dpy->Platform != _EGL_PLATFORM_DRM) + if (!dpy->Extensions.MESA_drm_image) return EGL_FALSE; /* get shared handle */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c index 4e6d944c15..dd07af140a 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c @@ -109,7 +109,7 @@ egl_g3d_wait_fence_sync(struct egl_g3d_sync *gsync, EGLTimeKHR timeout) _eglUnlockMutex(&dpy->Mutex); /* no timed finish? */ - screen->fence_finish(screen, fence, 0x0); + screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); ret = EGL_CONDITION_SATISFIED_KHR; _eglLockMutex(&dpy->Mutex); @@ -234,7 +234,7 @@ egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, struct egl_g3d_context *gctx = egl_g3d_context(ctx); if (gctx) - gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE , NULL); + gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL); } if (timeout) { diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index ca8cb97f71..9e9cd3fd05 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -126,8 +126,6 @@ struct native_config { int native_visual_id; int native_visual_type; int level; - int samples; - boolean slow_config; boolean transparent_rgb; int transparent_rgb_values[3]; }; @@ -144,6 +142,11 @@ struct native_display { struct pipe_screen *screen; /** + * Context used for copy operations. + */ + struct pipe_context *pipe; + + /** * Available for caller's use. */ void *user_data; @@ -185,7 +188,9 @@ struct native_display { const struct native_config *nconf); /** - * Create a pixmap surface. Required unless no config has pixmap_bit set. + * Create a pixmap surface. The native config may be NULL. In that case, a + * "best config" will be picked. Required unless no config has pixmap_bit + * set. */ struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy, EGLNativePixmapType pix, @@ -223,11 +228,35 @@ native_attachment_mask_test(uint mask, enum native_attachment att) return !!(mask & (1 << att)); } +/** + * Get the display copy context + */ +static INLINE struct pipe_context * +ndpy_get_copy_context(struct native_display *ndpy) +{ + if (!ndpy->pipe) + ndpy->pipe = ndpy->screen->context_create(ndpy->screen, NULL); + return ndpy->pipe; +} + +/** + * Free display screen and context resources + */ +static INLINE void +ndpy_uninit(struct native_display *ndpy) +{ + if (ndpy->pipe) + ndpy->pipe->destroy(ndpy->pipe); + if (ndpy->screen) + ndpy->screen->destroy(ndpy->screen); +} + struct native_platform { const char *name; + void (*set_event_handler)(struct native_event_handler *handler); struct native_display *(*create_display)(void *dpy, - struct native_event_handler *handler, + boolean use_sw, void *user_data); }; @@ -238,6 +267,9 @@ const struct native_platform * native_get_x11_platform(void); const struct native_platform * +native_get_wayland_platform(void); + +const struct native_platform * native_get_drm_platform(void); const struct native_platform * diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index 0f2d02032b..ee18cb2025 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.c +++ b/src/gallium/state_trackers/egl/common/native_helper.c @@ -3,6 +3,7 @@ * Version: 7.9 * * Copyright (C) 2010 LunarG Inc. + * Copyright (C) 2011 VMware Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +25,7 @@ * * Authors: * Chia-I Wu <olv@lunarg.com> + * Thomas Hellstrom <thellstrom@vmware.com> */ #include "util/u_inlines.h" @@ -34,6 +36,14 @@ #include "native_helper.h" +/** + * Number of swap fences and mask + */ + +#define EGL_SWAP_FENCES_MAX 4 +#define EGL_SWAP_FENCES_MASK 3 +#define EGL_SWAP_FENCES_DEFAULT 1 + struct resource_surface { struct pipe_screen *screen; enum pipe_format format; @@ -42,6 +52,15 @@ struct resource_surface { struct pipe_resource *resources[NUM_NATIVE_ATTACHMENTS]; uint resource_mask; uint width, height; + + /** + * Swap fences. + */ + struct pipe_fence_handle *swap_fences[EGL_SWAP_FENCES_MAX]; + unsigned int cur_fences; + unsigned int head; + unsigned int tail; + unsigned int desired_fences; }; struct resource_surface * @@ -49,11 +68,16 @@ resource_surface_create(struct pipe_screen *screen, enum pipe_format format, uint bind) { struct resource_surface *rsurf = CALLOC_STRUCT(resource_surface); + char *swap_fences = getenv("EGL_THROTTLE_FENCES"); if (rsurf) { rsurf->screen = screen; rsurf->format = format; rsurf->bind = bind; + rsurf->desired_fences = (swap_fences) ? atoi(swap_fences) : + EGL_SWAP_FENCES_DEFAULT; + if (rsurf->desired_fences > EGL_SWAP_FENCES_MAX) + rsurf->desired_fences = EGL_SWAP_FENCES_MAX; } return rsurf; @@ -143,6 +167,14 @@ resource_surface_add_resources(struct resource_surface *rsurf, return ((rsurf->resource_mask & resource_mask) == resource_mask); } +void +resource_surface_import_resource(struct resource_surface *rsurf, + enum native_attachment which, + struct pipe_resource *pres) +{ + pipe_resource_reference(&rsurf->resources[which], pres); + rsurf->resource_mask |= 1 << which; +} void resource_surface_get_resources(struct resource_surface *rsurf, @@ -217,3 +249,121 @@ resource_surface_present(struct resource_surface *rsurf, return TRUE; } + +/** + * Schedule a copy swap from the back to the front buffer using the + * native display's copy context. + */ +boolean +resource_surface_copy_swap(struct resource_surface *rsurf, + struct native_display *ndpy) +{ + struct pipe_resource *ftex; + struct pipe_resource *btex; + struct pipe_context *pipe; + struct pipe_box src_box; + boolean ret = FALSE; + + pipe = ndpy_get_copy_context(ndpy); + if (!pipe) + return FALSE; + + ftex = resource_surface_get_single_resource(rsurf, + NATIVE_ATTACHMENT_FRONT_LEFT); + if (!ftex) + goto out_no_ftex; + btex = resource_surface_get_single_resource(rsurf, + NATIVE_ATTACHMENT_BACK_LEFT); + if (!btex) + goto out_no_btex; + + u_box_origin_2d(ftex->width0, ftex->height0, &src_box); + pipe->resource_copy_region(pipe, ftex, 0, 0, 0, 0, + btex, 0, &src_box); + ret = TRUE; + + out_no_ftex: + pipe_resource_reference(&btex, NULL); + out_no_btex: + pipe_resource_reference(&ftex, NULL); + + return ret; +} + +static struct pipe_fence_handle * +swap_fences_pop_front(struct resource_surface *rsurf) +{ + struct pipe_screen *screen = rsurf->screen; + struct pipe_fence_handle *fence = NULL; + + if (rsurf->desired_fences == 0) + return NULL; + + if (rsurf->cur_fences >= rsurf->desired_fences) { + screen->fence_reference(screen, &fence, rsurf->swap_fences[rsurf->tail]); + screen->fence_reference(screen, &rsurf->swap_fences[rsurf->tail++], NULL); + rsurf->tail &= EGL_SWAP_FENCES_MASK; + --rsurf->cur_fences; + } + return fence; +} + +static void +swap_fences_push_back(struct resource_surface *rsurf, + struct pipe_fence_handle *fence) +{ + struct pipe_screen *screen = rsurf->screen; + + if (!fence || rsurf->desired_fences == 0) + return; + + while(rsurf->cur_fences == rsurf->desired_fences) + swap_fences_pop_front(rsurf); + + rsurf->cur_fences++; + screen->fence_reference(screen, &rsurf->swap_fences[rsurf->head++], + fence); + rsurf->head &= EGL_SWAP_FENCES_MASK; +} + +boolean +resource_surface_throttle(struct resource_surface *rsurf) +{ + struct pipe_screen *screen = rsurf->screen; + struct pipe_fence_handle *fence = swap_fences_pop_front(rsurf); + + if (fence) { + (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &fence, NULL); + return TRUE; + } + + return FALSE; +} + +boolean +resource_surface_flush(struct resource_surface *rsurf, + struct native_display *ndpy) +{ + struct pipe_fence_handle *fence = NULL; + struct pipe_screen *screen = rsurf->screen; + struct pipe_context *pipe= ndpy_get_copy_context(ndpy); + + if (!pipe) + return FALSE; + + pipe->flush(pipe, &fence); + if (fence == NULL) + return FALSE; + + swap_fences_push_back(rsurf, fence); + screen->fence_reference(screen, &fence, NULL); + + return TRUE; +} + +void +resource_surface_wait(struct resource_surface *rsurf) +{ + while (resource_surface_throttle(rsurf)); +} diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h index d1569ac3ea..39564a0436 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.h +++ b/src/gallium/state_trackers/egl/common/native_helper.h @@ -3,6 +3,7 @@ * Version: 7.9 * * Copyright (C) 2010 LunarG Inc. + * Copyright (C) 2011 VMware Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +25,7 @@ * * Authors: * Chia-I Wu <olv@lunarg.com> + * Thomas Hellstrom <thellstrom@vmware.com> */ #include "native.h" @@ -51,6 +53,11 @@ resource_surface_add_resources(struct resource_surface *rsurf, uint resource_mask); void +resource_surface_import_resource(struct resource_surface *rsurf, + enum native_attachment which, + struct pipe_resource *pres); + +void resource_surface_get_resources(struct resource_surface *rsurf, struct pipe_resource **resources, uint resource_mask); @@ -69,3 +76,32 @@ boolean resource_surface_present(struct resource_surface *rsurf, enum native_attachment which, void *winsys_drawable_handle); + +/** + * Perform a gallium copy blit between the back left and front left + * surfaces. Needs to be followed by a call to resource_surface_flush. + */ +boolean +resource_surface_copy_swap(struct resource_surface *rsurf, + struct native_display *ndpy); + +/** + * Throttle on outstanding rendering using the copy context. For example + * copy swaps. + */ +boolean +resource_surface_throttle(struct resource_surface *rsurf); + +/** + * Flush pending rendering using the copy context. This function saves a + * marker for upcoming throttles. + */ +boolean +resource_surface_flush(struct resource_surface *rsurf, + struct native_display *ndpy); +/** + * Wait for all rendering using the copy context to be complete. Frees all + * throttle markers saved using resource_surface_flush. + */ +void +resource_surface_wait(struct resource_surface *rsurf); diff --git a/src/gallium/state_trackers/egl/drm/modeset.c b/src/gallium/state_trackers/egl/drm/modeset.c index 0cc06caa2a..3fff954090 100644 --- a/src/gallium/state_trackers/egl/drm/modeset.c +++ b/src/gallium/state_trackers/egl/drm/modeset.c @@ -3,6 +3,7 @@ * Version: 7.9 * * Copyright (C) 2010 LunarG Inc. + * Copyright (C) 2011 VMware Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +25,7 @@ * * Authors: * Chia-I Wu <olv@lunarg.com> + * Thomas Hellstrom <thellstrom@vmware.com> */ #include "util/u_memory.h" @@ -131,6 +133,25 @@ drm_surface_flush_frontbuffer(struct native_surface *nsurf) } static boolean +drm_surface_copy_swap(struct native_surface *nsurf) +{ + struct drm_surface *drmsurf = drm_surface(nsurf); + struct drm_display *drmdpy = drmsurf->drmdpy; + + (void) resource_surface_throttle(drmsurf->rsurf); + if (!resource_surface_copy_swap(drmsurf->rsurf, &drmdpy->base)) + return FALSE; + + (void) resource_surface_flush(drmsurf->rsurf, &drmdpy->base); + if (!drm_surface_flush_frontbuffer(nsurf)) + return FALSE; + + drmsurf->sequence_number++; + + return TRUE; +} + +static boolean drm_surface_swap_buffers(struct native_surface *nsurf) { struct drm_surface *drmsurf = drm_surface(nsurf); @@ -139,17 +160,21 @@ drm_surface_swap_buffers(struct native_surface *nsurf) struct drm_framebuffer tmp_fb; int err; + if (!drmsurf->have_pageflip) + return drm_surface_copy_swap(nsurf); + if (!drmsurf->back_fb.buffer_id) { if (!drm_surface_init_framebuffers(&drmsurf->base, TRUE)) return FALSE; } if (drmsurf->is_shown && drmcrtc->crtc) { - err = drmModeSetCrtc(drmdpy->fd, drmcrtc->crtc->crtc_id, - drmsurf->back_fb.buffer_id, drmcrtc->crtc->x, drmcrtc->crtc->y, - drmcrtc->connectors, drmcrtc->num_connectors, &drmcrtc->crtc->mode); - if (err) - return FALSE; + err = drmModePageFlip(drmdpy->fd, drmcrtc->crtc->crtc_id, + drmsurf->back_fb.buffer_id, 0, NULL); + if (err) { + drmsurf->have_pageflip = FALSE; + return drm_surface_copy_swap(nsurf); + } } /* swap the buffers */ @@ -175,7 +200,7 @@ drm_surface_present(struct native_surface *nsurf, { boolean ret; - if (preserve || swap_interval) + if (swap_interval) return FALSE; switch (natt) { @@ -183,7 +208,10 @@ drm_surface_present(struct native_surface *nsurf, ret = drm_surface_flush_frontbuffer(nsurf); break; case NATIVE_ATTACHMENT_BACK_LEFT: - ret = drm_surface_swap_buffers(nsurf); + if (preserve) + ret = drm_surface_copy_swap(nsurf); + else + ret = drm_surface_swap_buffers(nsurf); break; default: ret = FALSE; @@ -196,7 +224,9 @@ drm_surface_present(struct native_surface *nsurf, static void drm_surface_wait(struct native_surface *nsurf) { - /* no-op */ + struct drm_surface *drmsurf = drm_surface(nsurf); + + resource_surface_wait(drmsurf->rsurf); } static void @@ -204,6 +234,7 @@ drm_surface_destroy(struct native_surface *nsurf) { struct drm_surface *drmsurf = drm_surface(nsurf); + resource_surface_wait(drmsurf->rsurf); if (drmsurf->current_crtc.crtc) drmModeFreeCrtc(drmsurf->current_crtc.crtc); @@ -236,6 +267,7 @@ drm_display_create_surface(struct native_display *ndpy, drmsurf->color_format = drmconf->base.color_format; drmsurf->width = width; drmsurf->height = height; + drmsurf->have_pageflip = TRUE; drmsurf->rsurf = resource_surface_create(drmdpy->base.screen, drmsurf->color_format, diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c index 2441b43fd8..9863329ff4 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.c +++ b/src/gallium/state_trackers/egl/drm/native_drm.c @@ -43,7 +43,7 @@ drm_display_is_format_supported(struct native_display *ndpy, return ndpy->screen->is_format_supported(ndpy->screen, fmt, PIPE_TEXTURE_2D, 0, (is_color) ? PIPE_BIND_RENDER_TARGET : - PIPE_BIND_DEPTH_STENCIL, 0); + PIPE_BIND_DEPTH_STENCIL); } static const struct native_config ** @@ -124,8 +124,7 @@ drm_display_destroy(struct native_display *ndpy) drm_display_fini_modeset(&drmdpy->base); - if (drmdpy->base.screen) - drmdpy->base.screen->destroy(drmdpy->base.screen); + ndpy_uninit(ndpy); if (drmdpy->fd >= 0) close(drmdpy->fd); @@ -178,7 +177,7 @@ drm_display_init_screen(struct native_display *ndpy) drmFreeVersion(version); if (!drmdpy->base.screen) { - _eglLog(_EGL_WARNING, "failed to create DRM screen"); + _eglLog(_EGL_DEBUG, "failed to create DRM screen"); return FALSE; } @@ -237,9 +236,16 @@ drm_create_display(int fd, struct native_event_handler *event_handler, return &drmdpy->base; } +static struct native_event_handler *drm_event_handler; + +static void +native_set_event_handler(struct native_event_handler *event_handler) +{ + drm_event_handler = event_handler; +} + static struct native_display * -native_create_display(void *dpy, struct native_event_handler *event_handler, - void *user_data) +native_create_display(void *dpy, boolean use_sw, void *user_data) { int fd; @@ -252,11 +258,12 @@ native_create_display(void *dpy, struct native_event_handler *event_handler, if (fd < 0) return NULL; - return drm_create_display(fd, event_handler, user_data); + return drm_create_display(fd, drm_event_handler, user_data); } static const struct native_platform drm_platform = { "DRM", /* name */ + native_set_event_handler, native_create_display }; diff --git a/src/gallium/state_trackers/egl/drm/native_drm.h b/src/gallium/state_trackers/egl/drm/native_drm.h index 03c4fe01dc..7da9b45f23 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.h +++ b/src/gallium/state_trackers/egl/drm/native_drm.h @@ -91,6 +91,8 @@ struct drm_surface { boolean is_shown; struct drm_crtc current_crtc; + + boolean have_pageflip; }; struct drm_connector { diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c index 1b5ea8bf9d..e2fde00e97 100644 --- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c +++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c @@ -320,7 +320,7 @@ fbdev_display_destroy(struct native_display *ndpy) { struct fbdev_display *fbdpy = fbdev_display(ndpy); - fbdpy->base.screen->destroy(fbdpy->base.screen); + ndpy_uninit(&fbdpy->base); close(fbdpy->fd); FREE(fbdpy); } @@ -422,7 +422,7 @@ fbdev_display_init(struct native_display *ndpy) if (fbdpy->base.screen) { if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen, fbdpy->config.color_format, PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET, 0)) { + PIPE_BIND_RENDER_TARGET)) { fbdpy->base.screen->destroy(fbdpy->base.screen); fbdpy->base.screen = NULL; } @@ -459,9 +459,16 @@ fbdev_display_create(int fd, struct native_event_handler *event_handler, return &fbdpy->base; } +static struct native_event_handler *fbdev_event_handler; + +static void +native_set_event_handler(struct native_event_handler *event_handler) +{ + fbdev_event_handler = event_handler; +} + static struct native_display * -native_create_display(void *dpy, struct native_event_handler *event_handler, - void *user_data) +native_create_display(void *dpy, boolean use_sw, void *user_data) { struct native_display *ndpy; int fd; @@ -476,7 +483,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler, if (fd < 0) return NULL; - ndpy = fbdev_display_create(fd, event_handler, user_data); + ndpy = fbdev_display_create(fd, fbdev_event_handler, user_data); if (!ndpy) close(fd); @@ -485,6 +492,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler, static const struct native_platform fbdev_platform = { "FBDEV", /* name */ + native_set_event_handler, native_create_display }; diff --git a/src/gallium/state_trackers/egl/gdi/native_gdi.c b/src/gallium/state_trackers/egl/gdi/native_gdi.c index d259e6edc8..5d0045f92e 100644 --- a/src/gallium/state_trackers/egl/gdi/native_gdi.c +++ b/src/gallium/state_trackers/egl/gdi/native_gdi.c @@ -285,7 +285,7 @@ fill_color_formats(struct native_display *ndpy, enum pipe_format formats[8]) for (i = 0; i < Elements(candidates); i++) { if (screen->is_format_supported(screen, candidates[i], - PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0)) + PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) formats[count++] = candidates[i]; } @@ -319,7 +319,6 @@ gdi_display_get_configs(struct native_display *ndpy, int *num_configs) nconf->color_format = formats[i]; nconf->window_bit = TRUE; - nconf->slow_config = TRUE; } gdpy->num_configs = count; @@ -364,7 +363,7 @@ gdi_display_destroy(struct native_display *ndpy) if (gdpy->configs) FREE(gdpy->configs); - gdpy->base.screen->destroy(gdpy->base.screen); + ndpy_uninit(ndpy); FREE(gdpy); } @@ -407,15 +406,23 @@ gdi_create_display(HDC hDC, struct native_event_handler *event_handler, return &gdpy->base; } +static struct native_event_handler *gdi_event_handler; + +static void +native_set_event_handler(struct native_event_handler *event_handler) +{ + gdi_event_handler = event_handler; +} + static struct native_display * -native_create_display(void *dpy, struct native_event_handler *event_handler, - void *user_data) +native_create_display(void *dpy, boolean use_sw, void *user_data) { - return gdi_create_display((HDC) dpy, event_handler, user_data); + return gdi_create_display((HDC) dpy, gdi_event_handler, user_data); } static const struct native_platform gdi_platform = { "GDI", /* name */ + native_set_event_handler, native_create_display }; diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c new file mode 100644 index 0000000000..068c3cd7c8 --- /dev/null +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c @@ -0,0 +1,626 @@ +/* + * Mesa 3-D graphics library + * Version: 7.11 + * + * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/drm_driver.h" + +#include "egllog.h" + +#include "native_wayland.h" + +/* see get_drm_screen_name */ +#include <radeon_drm.h> +#include "radeon/drm/radeon_drm_public.h" + +#include <wayland-client.h> +#include "wayland-drm-client-protocol.h" +#include "wayland-egl-priv.h" + +#include <xf86drm.h> + +static struct native_event_handler *wayland_event_handler; + +static void +sync_callback(void *data) +{ + int *done = data; + + *done = 1; +} + +static void +force_roundtrip(struct wl_display *display) +{ + int done = 0; + + wl_display_sync_callback(display, sync_callback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + +static const struct native_config ** +wayland_display_get_configs (struct native_display *ndpy, int *num_configs) +{ + struct wayland_display *display = wayland_display(ndpy); + const struct native_config **configs; + + if (!display->config) { + struct native_config *nconf; + enum pipe_format format; + display->config = CALLOC(1, sizeof(*display->config)); + if (!display->config) + return NULL; + nconf = &display->config->base; + + nconf->buffer_mask = + (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); + + format = PIPE_FORMAT_B8G8R8A8_UNORM; + + nconf->color_format = format; + nconf->window_bit = TRUE; + nconf->pixmap_bit = TRUE; + } + + configs = MALLOC(sizeof(*configs)); + if (configs) { + configs[0] = &display->config->base; + if (num_configs) + *num_configs = 1; + } + + return configs; +} + +static int +wayland_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_MAX_SWAP_INTERVAL: + default: + val = 0; + break; + } + + return val; +} + +static boolean +wayland_display_is_pixmap_supported(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + /* all wl_egl_pixmaps are supported */ + + return TRUE; +} + +static void +wayland_display_destroy(struct native_display *ndpy) +{ + struct wayland_display *display = wayland_display(ndpy); + + if (display->config) + FREE(display->config); + + ndpy_uninit(ndpy); + + FREE(display); +} + + +static struct wl_buffer * +wayland_create_buffer(struct wayland_surface *surface, + enum native_attachment attachment) +{ + struct wayland_display *display = surface->display; + struct pipe_resource *resource; + struct winsys_handle wsh; + uint width, height; + + resource = resource_surface_get_single_resource(surface->rsurf, attachment); + resource_surface_get_size(surface->rsurf, &width, &height); + + wsh.type = DRM_API_HANDLE_TYPE_SHARED; + display->base.screen->resource_get_handle(display->base.screen, resource, &wsh); + + pipe_resource_reference(&resource, NULL); + + return wl_drm_create_buffer(display->dpy->drm, wsh.handle, + width, height, + wsh.stride, surface->win->visual); +} + +static void +wayland_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap) +{ + struct pipe_resource *resource = egl_pixmap->driver_private; + + assert(resource); + + pipe_resource_reference(&resource, NULL); + + egl_pixmap->driver_private = NULL; + egl_pixmap->destroy = NULL; + egl_pixmap->name = 0; +} + +static void +wayland_pixmap_surface_intialize(struct wayland_surface *surface) +{ + struct native_display *ndpy = &surface->display->base; + struct pipe_resource *resource; + struct winsys_handle wsh; + const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + if (surface->pix->name > 0) + return; + + resource = resource_surface_get_single_resource(surface->rsurf, front_natt); + + wsh.type = DRM_API_HANDLE_TYPE_SHARED; + ndpy->screen->resource_get_handle(ndpy->screen, resource, &wsh); + + surface->pix->name = wsh.handle; + surface->pix->stride = wsh.stride; + surface->pix->destroy = wayland_pixmap_destroy; + surface->pix->driver_private = resource; +} + +static void +wayland_release_pending_resource(void *data) +{ + struct wayland_surface *surface = data; + + /* FIXME: print internal error */ + if (!surface->pending_resource) + return; + + pipe_resource_reference(&surface->pending_resource, NULL); +} + +static void +wayland_window_surface_handle_resize(struct wayland_surface *surface) +{ + struct wayland_display *display = surface->display; + struct pipe_resource *front_resource; + const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT; + int i; + + front_resource = resource_surface_get_single_resource(surface->rsurf, + front_natt); + if (resource_surface_set_size(surface->rsurf, + surface->win->width, surface->win->height)) { + + if (surface->pending_resource) + force_roundtrip(display->dpy->display); + + if (front_resource) { + surface->pending_resource = front_resource; + front_resource = NULL; + wl_display_sync_callback(display->dpy->display, + wayland_release_pending_resource, surface); + } + + for (i = 0; i < WL_BUFFER_COUNT; ++i) { + if (surface->buffer[i]) + wl_buffer_destroy(surface->buffer[i]); + surface->buffer[i] = NULL; + } + } + pipe_resource_reference(&front_resource, NULL); + + surface->dx = surface->win->dx; + surface->dy = surface->win->dy; + surface->win->dx = 0; + surface->win->dy = 0; +} + +static boolean +wayland_surface_validate(struct native_surface *nsurf, uint attachment_mask, + unsigned int *seq_num, struct pipe_resource **textures, + int *width, int *height) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + + if (surface->type == WL_WINDOW_SURFACE) + wayland_window_surface_handle_resize(surface); + + if (!resource_surface_add_resources(surface->rsurf, attachment_mask | + surface->attachment_mask)) + return FALSE; + + if (textures) + resource_surface_get_resources(surface->rsurf, textures, attachment_mask); + + if (seq_num) + *seq_num = surface->sequence_number; + + resource_surface_get_size(surface->rsurf, (uint *) width, (uint *) height); + + if (surface->type == WL_PIXMAP_SURFACE) + wayland_pixmap_surface_intialize(surface); + + return TRUE; +} + +static void +wayland_frame_callback(void *data, uint32_t time) +{ + struct wayland_surface *surface = data; + + surface->block_swap_buffers = FALSE; +} + +static INLINE void +wayland_buffers_swap(struct wl_buffer **buffer, + enum wayland_buffer_type buf1, + enum wayland_buffer_type buf2) +{ + struct wl_buffer *tmp = buffer[buf1]; + buffer[buf1] = buffer[buf2]; + buffer[buf2] = tmp; +} + +static boolean +wayland_surface_swap_buffers(struct native_surface *nsurf) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + struct wayland_display *display = surface->display; + + while (surface->block_swap_buffers) + wl_display_iterate(display->dpy->display, WL_DISPLAY_READABLE); + + surface->block_swap_buffers = TRUE; + wl_display_frame_callback(display->dpy->display, wayland_frame_callback, + surface); + + if (surface->type == WL_WINDOW_SURFACE) { + resource_surface_swap_buffers(surface->rsurf, + NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE); + + wayland_buffers_swap(surface->buffer, WL_BUFFER_FRONT, WL_BUFFER_BACK); + + if (surface->buffer[WL_BUFFER_FRONT] == NULL) + surface->buffer[WL_BUFFER_FRONT] = + wayland_create_buffer(surface, NATIVE_ATTACHMENT_FRONT_LEFT); + + wl_surface_attach(surface->win->surface, surface->buffer[WL_BUFFER_FRONT], + surface->dx, surface->dy); + + resource_surface_get_size(surface->rsurf, + (uint *) &surface->win->attached_width, + (uint *) &surface->win->attached_height); + surface->dx = 0; + surface->dy = 0; + } + + surface->sequence_number++; + wayland_event_handler->invalid_surface(&display->base, + &surface->base, surface->sequence_number); + + return TRUE; +} + +static boolean +wayland_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + uint width, height; + boolean ret; + + if (preserve || swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = TRUE; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = wayland_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + if (surface->type == WL_WINDOW_SURFACE) { + resource_surface_get_size(surface->rsurf, &width, &height); + wl_surface_damage(surface->win->surface, 0, 0, width, height); + } + + return ret; +} + +static void +wayland_surface_wait(struct native_surface *nsurf) +{ + /* no-op */ +} + +static void +wayland_surface_destroy(struct native_surface *nsurf) +{ + struct wayland_surface *surface = wayland_surface(nsurf); + enum wayland_buffer_type buffer; + + for (buffer = 0; buffer < WL_BUFFER_COUNT; ++buffer) { + if (surface->buffer[buffer]) + wl_buffer_destroy(surface->buffer[buffer]); + } + + resource_surface_destroy(surface->rsurf); + FREE(surface); +} + +static struct native_surface * +wayland_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct wayland_display *display = wayland_display(ndpy); + struct wayland_config *config = wayland_config(nconf); + struct wayland_surface *surface; + struct wl_egl_pixmap *egl_pixmap = (struct wl_egl_pixmap *) pix; + enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + surface = CALLOC_STRUCT(wayland_surface); + if (!surface) + return NULL; + + surface->display = display; + + surface->pending_resource = NULL; + surface->type = WL_PIXMAP_SURFACE; + surface->pix = egl_pixmap; + + if (surface->pix->visual == wl_display_get_rgb_visual(display->dpy->display)) + surface->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; + else + surface->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; + + surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT); + + surface->rsurf = resource_surface_create(display->base.screen, + surface->color_format, + PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT); + + if (!surface->rsurf) { + FREE(surface); + return NULL; + } + + resource_surface_set_size(surface->rsurf, + egl_pixmap->width, egl_pixmap->height); + + /* the pixmap is already allocated, so import it */ + if (surface->pix->name > 0) + resource_surface_import_resource(surface->rsurf, natt, + surface->pix->driver_private); + + surface->base.destroy = wayland_surface_destroy; + surface->base.present = wayland_surface_present; + surface->base.validate = wayland_surface_validate; + surface->base.wait = wayland_surface_wait; + + return &surface->base; +} + +static struct native_surface * +wayland_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) +{ + struct wayland_display *display = wayland_display(ndpy); + struct wayland_config *config = wayland_config(nconf); + struct wayland_surface *surface; + + surface = CALLOC_STRUCT(wayland_surface); + if (!surface) + return NULL; + + surface->display = display; + surface->color_format = config->base.color_format; + + surface->win = (struct wl_egl_window *) win; + + surface->pending_resource = NULL; + surface->block_swap_buffers = FALSE; + surface->type = WL_WINDOW_SURFACE; + + surface->buffer[WL_BUFFER_FRONT] = NULL; + surface->buffer[WL_BUFFER_BACK] = NULL; + surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); + + surface->rsurf = resource_surface_create(display->base.screen, + surface->color_format, + PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT); + + if (!surface->rsurf) { + FREE(surface); + return NULL; + } + + surface->base.destroy = wayland_surface_destroy; + surface->base.present = wayland_surface_present; + surface->base.validate = wayland_surface_validate; + surface->base.wait = wayland_surface_wait; + + return &surface->base; +} + +static const char * +get_drm_screen_name(int fd, drmVersionPtr version) +{ + const char *name = version->name; + + if (name && !strcmp(name, "radeon")) { + int chip_id; + struct drm_radeon_info info; + + memset(&info, 0, sizeof(info)); + info.request = RADEON_INFO_DEVICE_ID; + info.value = pointer_to_intptr(&chip_id); + if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) + return NULL; + + name = is_r3xx(chip_id) ? "r300" : "r600"; + } + + return name; +} + +static boolean +wayland_display_init_screen(struct native_display *ndpy) +{ + struct wayland_display *display = wayland_display(ndpy); + drmVersionPtr version; + const char *driver_name; + + if (display->dpy->fd == -1) + force_roundtrip(display->dpy->display); + if (display->dpy->fd == -1) + return FALSE; + + if (!display->dpy->authenticated) + force_roundtrip(display->dpy->display); + if (!display->dpy->authenticated) + return FALSE; + + version = drmGetVersion(display->dpy->fd); + if (!version) { + _eglLog(_EGL_WARNING, "invalid fd %d", display->dpy->fd); + return FALSE; + } + + /* FIXME: share this with native_drm or egl_dri2 */ + driver_name = get_drm_screen_name(display->dpy->fd, version); + + display->base.screen = + wayland_event_handler->new_drm_screen(&display->base, + driver_name, display->dpy->fd); + drmFreeVersion(version); + + if (!display->base.screen) { + _eglLog(_EGL_WARNING, "failed to create DRM screen"); + return FALSE; + } + + return TRUE; +} + + +static void +wayland_set_event_handler(struct native_event_handler *event_handler) +{ + wayland_event_handler = event_handler; +} + +static struct pipe_resource * +wayland_display_import_buffer(struct native_display *ndpy, + const struct pipe_resource *templ, + void *buf) +{ + return ndpy->screen->resource_from_handle(ndpy->screen, + templ, (struct winsys_handle *) buf); +} + +static boolean +wayland_display_export_buffer(struct native_display *ndpy, + struct pipe_resource *res, + void *buf) +{ + return ndpy->screen->resource_get_handle(ndpy->screen, + res, (struct winsys_handle *) buf); +} + +static struct native_display_buffer wayland_display_buffer = { + wayland_display_import_buffer, + wayland_display_export_buffer +}; + +static struct native_display * +wayland_display_create(void *dpy, boolean use_sw, void *user_data) +{ + struct wayland_display *display; + + display = CALLOC_STRUCT(wayland_display); + if (!display) + return NULL; + + display->base.user_data = user_data; + + display->dpy = dpy; + if (!display->dpy->display) { + wayland_display_destroy(&display->base); + return NULL; + } + + if (!wayland_display_init_screen(&display->base)) { + wayland_display_destroy(&display->base); + return NULL; + } + + display->base.destroy = wayland_display_destroy; + display->base.get_param = wayland_display_get_param; + display->base.get_configs = wayland_display_get_configs; + display->base.is_pixmap_supported = wayland_display_is_pixmap_supported; + display->base.create_window_surface = wayland_create_window_surface; + display->base.create_pixmap_surface = wayland_create_pixmap_surface; + display->base.buffer = &wayland_display_buffer; + + return &display->base; +} + +static const struct native_platform wayland_platform = { + "wayland", /* name */ + wayland_set_event_handler, + wayland_display_create +}; + +const struct native_platform * +native_get_wayland_platform(void) +{ + return &wayland_platform; +} diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.h b/src/gallium/state_trackers/egl/wayland/native_wayland.h new file mode 100644 index 0000000000..271c10dc11 --- /dev/null +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h @@ -0,0 +1,97 @@ +/* + * Mesa 3-D graphics library + * Version: 7.11 + * + * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NATIVE_WAYLAND_H_ +#define _NATIVE_WAYLAND_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +#include "common/native.h" +#include "common/native_helper.h" + +#include "wayland-egl-priv.h" + +struct wayland_display { + struct native_display base; + + struct wayland_config *config; + struct wl_egl_display *dpy; +}; + +enum wayland_buffer_type { + WL_BUFFER_FRONT, + WL_BUFFER_BACK, + WL_BUFFER_COUNT +}; + +enum wayland_surface_type { + WL_WINDOW_SURFACE, + WL_PIXMAP_SURFACE, + WL_PBUFFER_SURFACE +}; + +struct wayland_surface { + struct native_surface base; + struct wayland_display *display; + + struct wl_egl_window *win; + struct wl_egl_pixmap *pix; + enum wayland_surface_type type; + int dx, dy; + struct resource_surface *rsurf; + struct pipe_resource *pending_resource; + enum pipe_format color_format; + + unsigned int sequence_number; + struct wl_buffer *buffer[WL_BUFFER_COUNT]; + unsigned int attachment_mask; + + boolean block_swap_buffers; +}; + +struct wayland_config { + struct native_config base; +}; + +static INLINE struct wayland_display * +wayland_display(const struct native_display *ndpy) +{ + return (struct wayland_display *) ndpy; +} + +static INLINE struct wayland_surface * +wayland_surface(const struct native_surface *nsurf) +{ + return (struct wayland_surface *) nsurf; +} + +static INLINE struct wayland_config * +wayland_config(const struct native_config *nconf) +{ + return (struct wayland_config *) nconf; +} + +#endif /* _NATIVE_WAYLAND_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 8108ce4586..5afca67a4d 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -40,11 +40,6 @@ #ifdef GLX_DIRECT_RENDERING -enum dri2_surface_type { - DRI2_SURFACE_TYPE_WINDOW, - DRI2_SURFACE_TYPE_PIXMAP, -}; - struct dri2_display { struct native_display base; Display *dpy; @@ -66,7 +61,6 @@ struct dri2_display { struct dri2_surface { struct native_surface base; Drawable drawable; - enum dri2_surface_type type; enum pipe_format color_format; struct dri2_display *dri2dpy; @@ -439,12 +433,10 @@ dri2_surface_destroy(struct native_surface *nsurf) static struct dri2_surface * dri2_display_create_surface(struct native_display *ndpy, - enum dri2_surface_type type, Drawable drawable, - const struct native_config *nconf) + enum pipe_format color_format) { struct dri2_display *dri2dpy = dri2_display(ndpy); - struct dri2_config *dri2conf = dri2_config(nconf); struct dri2_surface *dri2surf; dri2surf = CALLOC_STRUCT(dri2_surface); @@ -452,9 +444,8 @@ dri2_display_create_surface(struct native_display *ndpy, return NULL; dri2surf->dri2dpy = dri2dpy; - dri2surf->type = type; dri2surf->drawable = drawable; - dri2surf->color_format = dri2conf->base.color_format; + dri2surf->color_format = color_format; dri2surf->base.destroy = dri2_surface_destroy; dri2surf->base.present = dri2_surface_present; @@ -480,8 +471,8 @@ dri2_display_create_window_surface(struct native_display *ndpy, { struct dri2_surface *dri2surf; - dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW, - (Drawable) win, nconf); + dri2surf = dri2_display_create_surface(ndpy, + (Drawable) win, nconf->color_format); return (dri2surf) ? &dri2surf->base : NULL; } @@ -492,8 +483,29 @@ dri2_display_create_pixmap_surface(struct native_display *ndpy, { struct dri2_surface *dri2surf; - dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP, - (Drawable) pix, nconf); + if (!nconf) { + struct dri2_display *dri2dpy = dri2_display(ndpy); + uint depth, nconf_depth; + int i; + + depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); + for (i = 0; i < dri2dpy->num_configs; i++) { + nconf_depth = util_format_get_blocksizebits( + dri2dpy->configs[i].base.color_format); + /* simple depth match for now */ + if (depth == nconf_depth || + (depth == 24 && depth + 8 == nconf_depth)) { + nconf = &dri2dpy->configs[i].base; + break; + } + } + + if (!nconf) + return NULL; + } + + dri2surf = dri2_display_create_surface(ndpy, + (Drawable) pix, nconf->color_format); return (dri2surf) ? &dri2surf->base : NULL; } @@ -529,7 +541,7 @@ is_format_supported(struct pipe_screen *screen, { return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count, (is_color) ? PIPE_BIND_RENDER_TARGET : - PIPE_BIND_DEPTH_STENCIL, 0); + PIPE_BIND_DEPTH_STENCIL); } static boolean @@ -548,6 +560,10 @@ dri2_display_convert_config(struct native_display *ndpy, if (!mode->xRenderable || !mode->drawableType) return FALSE; + /* fast/slow configs are probably not relevant */ + if (mode->visualRating == GLX_SLOW_CONFIG) + return FALSE; + nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; if (mode->doubleBufferMode) nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; @@ -568,17 +584,33 @@ dri2_display_convert_config(struct native_display *ndpy, if (nconf->color_format == PIPE_FORMAT_NONE) return FALSE; - if (mode->drawableType & GLX_WINDOW_BIT) + if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID) nconf->window_bit = TRUE; if (mode->drawableType & GLX_PIXMAP_BIT) nconf->pixmap_bit = TRUE; nconf->native_visual_id = mode->visualID; - nconf->native_visual_type = mode->visualType; + switch (mode->visualType) { + case GLX_TRUE_COLOR: + nconf->native_visual_type = TrueColor; + break; + case GLX_DIRECT_COLOR: + nconf->native_visual_type = DirectColor; + break; + case GLX_PSEUDO_COLOR: + nconf->native_visual_type = PseudoColor; + break; + case GLX_STATIC_COLOR: + nconf->native_visual_type = StaticColor; + break; + case GLX_GRAY_SCALE: + nconf->native_visual_type = GrayScale; + break; + case GLX_STATIC_GRAY: + nconf->native_visual_type = StaticGray; + break; + } nconf->level = mode->level; - nconf->samples = mode->samples; - - nconf->slow_config = (mode->visualRating == GLX_SLOW_CONFIG); if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { nconf->transparent_rgb = TRUE; @@ -614,8 +646,17 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) count = 0; for (i = 0; i < num_modes; i++) { struct native_config *nconf = &dri2dpy->configs[count].base; - if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) - count++; + + if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) { + int j; + /* look for duplicates */ + for (j = 0; j < count; j++) { + if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0) + break; + } + if (j == count) + count++; + } modes = modes->next; } @@ -741,7 +782,7 @@ dri2_display_init_screen(struct native_display *ndpy) dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, dri2dpy->dri_driver, fd); if (!dri2dpy->base.screen) { - _eglLog(_EGL_WARNING, "failed to create DRM screen"); + _eglLog(_EGL_DEBUG, "failed to create DRM screen"); return FALSE; } @@ -758,7 +799,7 @@ dri2_display_hash_table_hash(void *key) static int dri2_display_hash_table_compare(void *key1, void *key2) { - return (key1 - key2); + return ((char *) key1 - (char *) key2); } struct native_display * diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 37c8b01541..a0bcad4c73 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -30,25 +30,30 @@ #include "native_x11.h" +static struct native_event_handler *x11_event_handler; + +static void +native_set_event_handler(struct native_event_handler *event_handler) +{ + x11_event_handler = event_handler; +} + static struct native_display * -native_create_display(void *dpy, struct native_event_handler *event_handler, - void *user_data) +native_create_display(void *dpy, boolean use_sw, void *user_data) { struct native_display *ndpy = NULL; boolean force_sw; force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); - if (!force_sw) { - ndpy = x11_create_dri2_display((Display *) dpy, - event_handler, user_data); - } - - if (!ndpy) { - EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; - _eglLog(level, "use software fallback"); + if (force_sw || use_sw) { + _eglLog(_EGL_INFO, "use software fallback"); ndpy = x11_create_ximage_display((Display *) dpy, - event_handler, user_data); + x11_event_handler, user_data); + } + else { + ndpy = x11_create_dri2_display((Display *) dpy, + x11_event_handler, user_data); } return ndpy; @@ -56,6 +61,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler, static const struct native_platform x11_platform = { "X11", /* name */ + native_set_event_handler, native_create_display }; diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 84811fb6e1..8e32c6ff0c 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -38,11 +38,6 @@ #include "native_x11.h" #include "x11_screen.h" -enum ximage_surface_type { - XIMAGE_SURFACE_TYPE_WINDOW, - XIMAGE_SURFACE_TYPE_PIXMAP, -}; - struct ximage_display { struct native_display base; Display *dpy; @@ -60,7 +55,6 @@ struct ximage_display { struct ximage_surface { struct native_surface base; Drawable drawable; - enum ximage_surface_type type; enum pipe_format color_format; XVisualInfo visual; struct ximage_display *xdpy; @@ -245,7 +239,6 @@ ximage_surface_destroy(struct native_surface *nsurf) static struct ximage_surface * ximage_display_create_surface(struct native_display *ndpy, - enum ximage_surface_type type, Drawable drawable, const struct native_config *nconf) { @@ -258,7 +251,6 @@ ximage_display_create_surface(struct native_display *ndpy, return NULL; xsurf->xdpy = xdpy; - xsurf->type = type; xsurf->color_format = xconf->base.color_format; xsurf->drawable = drawable; @@ -297,11 +289,37 @@ ximage_display_create_window_surface(struct native_display *ndpy, { struct ximage_surface *xsurf; - xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW, - (Drawable) win, nconf); + xsurf = ximage_display_create_surface(ndpy, (Drawable) win, nconf); return (xsurf) ? &xsurf->base : NULL; } +static enum pipe_format +get_pixmap_format(struct native_display *ndpy, EGLNativePixmapType pix) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + enum pipe_format fmt; + uint depth; + + depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); + + switch (depth) { + case 32: + fmt = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case 24: + fmt = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case 16: + fmt = PIPE_FORMAT_B5G6R5_UNORM; + break; + default: + fmt = PIPE_FORMAT_NONE; + break; + } + + return fmt; +} + static struct native_surface * ximage_display_create_pixmap_surface(struct native_display *ndpy, EGLNativePixmapType pix, @@ -309,8 +327,26 @@ ximage_display_create_pixmap_surface(struct native_display *ndpy, { struct ximage_surface *xsurf; - xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP, - (Drawable) pix, nconf); + /* find the config */ + if (!nconf) { + struct ximage_display *xdpy = ximage_display(ndpy); + enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix); + int i; + + if (fmt != PIPE_FORMAT_NONE) { + for (i = 0; i < xdpy->num_configs; i++) { + if (xdpy->configs[i].base.color_format == fmt) { + nconf = &xdpy->configs[i].base; + break; + } + } + } + + if (!nconf) + return NULL; + } + + xsurf = ximage_display_create_surface(ndpy, (Drawable) pix, nconf); return (xsurf) ? &xsurf->base : NULL; } @@ -384,8 +420,6 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) xconf->base.native_visual_type = xconf->visual->class; #endif - xconf->base.slow_config = TRUE; - count++; } @@ -408,24 +442,7 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy, const struct native_config *nconf) { struct ximage_display *xdpy = ximage_display(ndpy); - enum pipe_format fmt; - uint depth; - - depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); - switch (depth) { - case 32: - fmt = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - case 24: - fmt = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - case 16: - fmt = PIPE_FORMAT_B5G6R5_UNORM; - break; - default: - fmt = PIPE_FORMAT_NONE; - break; - } + enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix); return (fmt == nconf->color_format); } @@ -459,7 +476,7 @@ ximage_display_destroy(struct native_display *ndpy) if (xdpy->configs) FREE(xdpy->configs); - xdpy->base.screen->destroy(xdpy->base.screen); + ndpy_uninit(ndpy); x11_screen_destroy(xdpy->xscr); if (xdpy->own_dpy) |