diff options
author | Christian König <[email protected]> | 2011-07-04 15:04:41 +0200 |
---|---|---|
committer | Christian König <[email protected]> | 2011-07-04 15:04:41 +0200 |
commit | c3b2230b71cb3a00a7f4c0987197d397bada650b (patch) | |
tree | 018f5df0f8b5976ddb56ef4f13e9466587838998 /src/gallium/state_trackers | |
parent | 003401f95c9b59471c22368b7da16fe7a951e490 (diff) | |
parent | 424b1210d951c206e7c2fb8f2778acbd384eb247 (diff) |
Merge remote-tracking branch 'origin/master' into pipe-video
Conflicts:
configure.ac
src/gallium/drivers/r600/r600_state_inlines.h
src/gallium/tests/trivial/Makefile
src/gallium/winsys/g3dvl/dri/XF86dri.c
src/gallium/winsys/g3dvl/dri/driclient.c
src/gallium/winsys/g3dvl/dri/driclient.h
src/gallium/winsys/g3dvl/dri/xf86dri.h
src/gallium/winsys/g3dvl/dri/xf86dristr.h
src/gallium/winsys/r600/drm/r600_bo.c
Diffstat (limited to 'src/gallium/state_trackers')
60 files changed, 4834 insertions, 679 deletions
diff --git a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp index 741a97f897d..0bb9d852f84 100644 --- a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp +++ b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp @@ -250,21 +250,21 @@ struct GalliumDXGIAdapter DXGI_ADAPTER_DESC1 desc; std::vector<ComPtr<IDXGIOutput> > outputs; int num_outputs; - struct native_event_handler handler; GalliumDXGIAdapter(GalliumDXGIFactory* factory, const struct native_platform* platform, void* dpy) { this->parent = factory; - /* FIXME handler should be static */ - handler.invalid_surface = handle_invalid_surface; - handler.new_drm_screen = dxgi_loader_create_drm_screen; - handler.new_sw_screen = dxgi_loader_create_sw_screen; - platform->set_event_handler(&handler); - - display = platform->create_display(dpy, FALSE, this); + display = platform->create_display(dpy, FALSE); if(!display) - display = platform->create_display(dpy, TRUE, this); + display = platform->create_display(dpy, TRUE); + if (display) { + display->user_data = this; + if (!display->init_screen(display)) { + display->destroy(display); + display = NULL; + } + } if(!display) throw E_FAIL; memset(&desc, 0, sizeof(desc)); @@ -1413,6 +1413,11 @@ struct dxgi_binding static dxgi_binding dxgi_default_binding; static __thread dxgi_binding dxgi_thread_binding; +static const struct native_event_handler dxgi_event_handler = { + GalliumDXGIAdapter::handle_invalid_surface, + dxgi_loader_create_drm_screen, + dxgi_loader_create_sw_screen +}; void STDMETHODCALLTYPE GalliumDXGIUseNothing() { @@ -1427,7 +1432,7 @@ void STDMETHODCALLTYPE GalliumDXGIUseNothing() void STDMETHODCALLTYPE GalliumDXGIUseX11Display(Display* dpy, IGalliumDXGIBackend* backend) { GalliumDXGIUseNothing(); - dxgi_thread_binding.platform = native_get_x11_platform(); + dxgi_thread_binding.platform = native_get_x11_platform(&dxgi_event_handler); dxgi_thread_binding.display = dpy; if(backend) @@ -1443,7 +1448,7 @@ void STDMETHODCALLTYPE GalliumDXGIUseX11Display(Display* dpy, IGalliumDXGIBacken void STDMETHODCALLTYPE GalliumDXGIUseDRMCard(int fd) { GalliumDXGIUseNothing(); - dxgi_thread_binding.platform = native_get_drm_platform(); + dxgi_thread_binding.platform = native_get_drm_platform(&dxgi_event_handler); dxgi_thread_binding.display = (void*)fd; dxgi_thread_binding.backend = 0; } @@ -1453,7 +1458,7 @@ void STDMETHODCALLTYPE GalliumDXGIUseDRMCard(int fd) void STDMETHODCALLTYPE GalliumDXGIUseFBDev(int fd) { GalliumDXGIUseNothing(); - dxgi_thread_binding.platform = native_get_fbdev_platform(); + dxgi_thread_binding.platform = native_get_fbdev_platform(&dxgi_event_handler); dxgi_thread_binding.display = (void*)fd; dxgi_thread_binding.backend = 0; } @@ -1463,7 +1468,7 @@ void STDMETHODCALLTYPE GalliumDXGIUseFBDev(int fd) void STDMETHODCALLTYPE GalliumDXGIUseHDC(HDC hdc, PFNHWNDRESOLVER resolver, void* resolver_cookie) { GalliumDXGIUseNothing(); - dxgi_thread_binding.platform = native_get_gdi_platform(); + dxgi_thread_binding.platform = native_get_gdi_platform(&dxgi_event_handler); dxgi_thread_binding.display = (void*)hdc; dxgi_thread_binding.backend = 0; } @@ -1493,7 +1498,7 @@ void STDMETHODCALLTYPE GalliumDXGIMakeDefault() else if(dxgi_default_binding.platform) factory = new GalliumDXGIFactory(dxgi_default_binding.platform, dxgi_default_binding.display, dxgi_default_binding.backend); else - factory = new GalliumDXGIFactory(native_get_x11_platform(), NULL, NULL); + factory = new GalliumDXGIFactory(native_get_x11_platform(&dxgi_event_handler), NULL, NULL); HRESULT hres = factory->QueryInterface(riid, out_factory); factory->Release(); return hres; diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c index e23c1bcafaf..08bbdf96e34 100644 --- a/src/gallium/state_trackers/dri/common/dri_context.c +++ b/src/gallium/state_trackers/dri/common/dri_context.c @@ -151,8 +151,6 @@ dri_unbind_context(__DRIcontext * cPriv) if (ctx->st == ctx->stapi->get_current(ctx->stapi)) { ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); stapi->make_current(stapi, NULL, NULL, NULL); - draw->context = NULL; - read->context = NULL; } } @@ -180,12 +178,10 @@ dri_make_current(__DRIcontext * cPriv, else if (!driDrawPriv || !driReadPriv) return GL_FALSE; - draw->context = ctx; if (ctx->dPriv != driDrawPriv) { ctx->dPriv = driDrawPriv; draw->texture_stamp = driDrawPriv->lastStamp - 1; } - read->context = ctx; if (ctx->rPriv != driReadPriv) { ctx->rPriv = driReadPriv; read->texture_stamp = driReadPriv->lastStamp - 1; diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c index 28a33ac7d07..7b8de3174be 100644 --- a/src/gallium/state_trackers/dri/common/dri_drawable.c +++ b/src/gallium/state_trackers/dri/common/dri_drawable.c @@ -136,6 +136,7 @@ dri_create_buffer(__DRIscreen * sPriv, drawable->sPriv = sPriv; drawable->dPriv = dPriv; dPriv->driverPrivate = (void *)drawable; + p_atomic_set(&drawable->base.stamp, 1); return GL_TRUE; fail: diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h index 7f1aa512ca1..fd3460dd30b 100644 --- a/src/gallium/state_trackers/dri/common/dri_drawable.h +++ b/src/gallium/state_trackers/dri/common/dri_drawable.h @@ -42,7 +42,6 @@ struct dri_drawable struct st_visual stvis; struct dri_screen *screen; - struct dri_context *context; /* dri */ __DRIdrawable *dPriv; diff --git a/src/gallium/state_trackers/dri/drm/SConscript b/src/gallium/state_trackers/dri/drm/SConscript index b188f76f910..c63918a0e18 100644 --- a/src/gallium/state_trackers/dri/drm/SConscript +++ b/src/gallium/state_trackers/dri/drm/SConscript @@ -5,7 +5,7 @@ Import('*') env = env.Clone() -env.ParseConfig('pkg-config --cflags --libs libdrm') +env.PkgUseModules(['DRM']) env.Append(CPPPATH = [ '#/src/mapi', diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index e471e8e5be2..fe4ddb312be 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -52,13 +52,11 @@ static void dri2_invalidate_drawable(__DRIdrawable *dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); - struct dri_context *ctx = drawable->context; dri2InvalidateDrawable(dPriv); drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; - if (ctx) - ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base); + p_atomic_inc(&drawable->base.stamp); } static const __DRI2flushExtension dri2FlushExtension = { @@ -564,6 +562,24 @@ dri2_query_image(__DRIimage *image, int attrib, int *value) } } +static __DRIimage * +dri2_dup_image(__DRIimage *image, void *loaderPrivate) +{ + __DRIimage *img; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + img->texture = NULL; + pipe_resource_reference(&img->texture, image->texture); + img->level = image->level; + img->layer = image->layer; + img->loader_private = loaderPrivate; + + return img; +} + static void dri2_destroy_image(__DRIimage *img) { @@ -578,6 +594,7 @@ static struct __DRIimageExtensionRec dri2ImageExtension = { dri2_destroy_image, dri2_create_image, dri2_query_image, + dri2_dup_image, }; /* diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c index ac11f7c47f6..a1879a8f46a 100644 --- a/src/gallium/state_trackers/dri/sw/drisw.c +++ b/src/gallium/state_trackers/dri/sw/drisw.c @@ -103,14 +103,11 @@ drisw_present_texture(__DRIdrawable *dPriv, static INLINE void drisw_invalidate_drawable(__DRIdrawable *dPriv) { - struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); struct dri_drawable *drawable = dri_drawable(dPriv); drawable->texture_stamp = dPriv->lastStamp - 1; - /* check if swapping currently bound buffer */ - if (ctx && ctx->dPriv == dPriv) - ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base); + p_atomic_inc(&drawable->base.stamp); } static INLINE void diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 763e7b58a49..1c970222c1f 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -33,7 +33,8 @@ wayland_INCLUDES = \ 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_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) \ + -I$(TOP)/src/gbm/main -I$(TOP)/src/gallium/state_trackers/gbm drm_SOURCES = $(wildcard drm/*.c) drm_OBJECTS = $(drm_SOURCES:.c=.o) diff --git a/src/gallium/state_trackers/egl/SConscript b/src/gallium/state_trackers/egl/SConscript index 9ade76ecbb2..c04fec637c1 100644 --- a/src/gallium/state_trackers/egl/SConscript +++ b/src/gallium/state_trackers/egl/SConscript @@ -40,7 +40,12 @@ else: env.Append(CPPDEFINES = ['GLX_DIRECT_RENDERING']) sources.append(['#/src/glx/dri2.c']) if env['drm']: + env.PkgUseModules('DRM') env.Append(CPPDEFINES = ['HAVE_DRM_BACKEND']) + env.Append(CPPPATH = [ + '#/src/gbm/main', + '#/src/gallium/state_trackers/gbm', + ]) sources.append(['drm/native_drm.c', 'drm/modeset.c']) st_egl = env.ConvenienceLibrary( diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 29dbbefbf48..6649f02b244 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -31,6 +31,7 @@ #include "util/u_memory.h" #include "util/u_format.h" #include "util/u_string.h" +#include "util/u_atomic.h" #include "egl_g3d.h" #include "egl_g3d_api.h" @@ -45,15 +46,9 @@ egl_g3d_invalid_surface(struct native_display *ndpy, { /* 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); + + if (gsurf && gsurf->stfbi) + p_atomic_inc(&gsurf->stfbi->stamp); } static struct pipe_screen * @@ -72,10 +67,26 @@ egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) return gdpy->loader->create_sw_screen(ws); } -static struct native_event_handler egl_g3d_native_event_handler = { +static struct pipe_resource * +egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image) +{ + _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct st_egl_image img; + struct pipe_resource *resource = NULL; + + memset(&img, 0, sizeof(img)); + if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img)) + resource = img.texture; + + return resource; +} + +static const struct native_event_handler egl_g3d_native_event_handler = { egl_g3d_invalid_surface, egl_g3d_new_drm_screen, - egl_g3d_new_sw_screen + egl_g3d_new_sw_screen, + egl_g3d_lookup_egl_image }; /** @@ -94,40 +105,38 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) case _EGL_PLATFORM_WINDOWS: plat_name = "Windows"; #ifdef HAVE_GDI_BACKEND - nplat = native_get_gdi_platform(); + nplat = native_get_gdi_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_X11: plat_name = "X11"; #ifdef HAVE_X11_BACKEND - nplat = native_get_x11_platform(); + nplat = native_get_x11_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_WAYLAND: plat_name = "wayland"; #ifdef HAVE_WAYLAND_BACKEND - nplat = native_get_wayland_platform(); + nplat = native_get_wayland_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_DRM: plat_name = "DRM"; #ifdef HAVE_DRM_BACKEND - nplat = native_get_drm_platform(); + nplat = native_get_drm_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_FBDEV: plat_name = "FBDEV"; #ifdef HAVE_FBDEV_BACKEND - nplat = native_get_fbdev_platform(); + nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler); #endif break; default: break; } - if (nplat) - nplat->set_event_handler(&egl_g3d_native_event_handler); - else + if (!nplat) _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name); gdrv->platforms[plat] = nplat; @@ -504,13 +513,20 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) gdpy->loader = gdrv->loader; dpy->DriverData = gdpy; - _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); - gdpy->native = nplat->create_display(dpy->PlatformDisplay, - dpy->Options.UseFallback, (void *) dpy); + _eglLog(_EGL_INFO, "use %s for display %p", + nplat->name, dpy->PlatformDisplay); + gdpy->native = + nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } + gdpy->native->user_data = (void *) dpy; + if (!gdpy->native->init_screen(gdpy->native)) { + _eglError(EGL_NOT_INITIALIZED, + "eglInitialize(failed to initialize screen)"); + goto fail; + } if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) dpy->ClientAPIs |= EGL_OPENGL_BIT; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index 301db3128ff..5989a023573 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -126,4 +126,12 @@ _EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj) #endif /* EGL_MESA_screen_surface */ +static INLINE struct st_api * +egl_g3d_get_st_api(_EGLDriver *drv, enum st_api_type api) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + + return gdrv->loader->get_st_api(api); +} + #endif /* _EGL_G3D_H_ */ 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 8b1821e0055..f897054a540 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -37,7 +37,6 @@ #include "egl_g3d_image.h" #include "egl_g3d_sync.h" #include "egl_g3d_st.h" -#include "egl_g3d_loader.h" #include "native.h" /** @@ -47,7 +46,6 @@ static struct st_api * egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, enum st_profile_type *profile) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct st_api *stapi; EGLint api = -1; @@ -81,96 +79,66 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, break; } - switch (api) { - case ST_API_OPENGL: - stapi = gdrv->loader->guess_gl_api(*profile); - break; - case ST_API_OPENVG: - stapi = gdrv->loader->get_st_api(api); - break; - default: - stapi = NULL; - break; - } + stapi = egl_g3d_get_st_api(drv, api); if (stapi && !(stapi->profile_mask & (1 << *profile))) stapi = NULL; return stapi; } +struct egl_g3d_choose_config_data { + _EGLConfig criteria; + enum pipe_format format; +}; + static int egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2, void *priv_data) { - const _EGLConfig *criteria = (const _EGLConfig *) priv_data; + struct egl_g3d_choose_config_data *data = + (struct egl_g3d_choose_config_data *) priv_data; + const _EGLConfig *criteria = &data->criteria;; /* EGL_NATIVE_VISUAL_TYPE ignored? */ return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); } static EGLBoolean -egl_g3d_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) +egl_g3d_match_config(const _EGLConfig *conf, void *priv_data) { - if (!_eglMatchConfig(conf, criteria)) - return EGL_FALSE; - - if (criteria->MatchNativePixmap != EGL_NONE && - criteria->MatchNativePixmap != EGL_DONT_CARE) { - struct egl_g3d_display *gdpy = egl_g3d_display(conf->Display); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - EGLNativePixmapType pix = - (EGLNativePixmapType) criteria->MatchNativePixmap; + struct egl_g3d_choose_config_data *data = + (struct egl_g3d_choose_config_data *) priv_data; + struct egl_g3d_config *gconf = egl_g3d_config(conf); - if (!gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) - return EGL_FALSE; - } + if (data->format != PIPE_FORMAT_NONE && + data->format != gconf->native->color_format) + return EGL_FALSE; - return EGL_TRUE; + return _eglMatchConfig(conf, &data->criteria); } static EGLBoolean egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs, EGLConfig *configs, EGLint size, EGLint *num_configs) { - _EGLConfig **tmp_configs, criteria; - EGLint tmp_size, i; - - if (!num_configs) - return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); + struct egl_g3d_choose_config_data data; - if (!_eglParseConfigAttribList(&criteria, dpy, attribs)) + if (!_eglParseConfigAttribList(&data.criteria, dpy, attribs)) return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); - /* get the number of matched configs */ - tmp_size = _eglFilterArray(dpy->Configs, NULL, 0, - (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria); - if (!tmp_size) { - *num_configs = tmp_size; - return EGL_TRUE; - } - - tmp_configs = MALLOC(sizeof(tmp_configs[0]) * tmp_size); - if (!tmp_configs) - return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); + data.format = PIPE_FORMAT_NONE; + if (data.criteria.MatchNativePixmap != EGL_NONE && + data.criteria.MatchNativePixmap != EGL_DONT_CARE) { + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - /* get the matched configs */ - _eglFilterArray(dpy->Configs, (void **) tmp_configs, tmp_size, - (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria); - - /* perform sorting of configs */ - if (configs && tmp_size) { - _eglSortConfigs((const _EGLConfig **) tmp_configs, tmp_size, - egl_g3d_compare_config, (void *) &criteria); - tmp_size = MIN2(tmp_size, size); - for (i = 0; i < tmp_size; i++) - configs[i] = _eglGetConfigHandle(tmp_configs[i]); + if (!gdpy->native->get_pixmap_format(gdpy->native, + (EGLNativePixmapType) data.criteria.MatchNativePixmap, + &data.format)) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglChooseConfig"); } - FREE(tmp_configs); - - *num_configs = tmp_size; - - return EGL_TRUE; + return _eglFilterConfigArray(dpy->Configs, configs, size, num_configs, + egl_g3d_match_config, egl_g3d_compare_config, &data); } static _EGLContext * @@ -536,19 +504,12 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); if (ok) { if (gdraw) { - gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, - gdraw->stfbi); - if (gdraw->base.Type == EGL_WINDOW_BIT) { gctx->base.WindowRenderBuffer = (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ? EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; } } - if (gread && gread != gdraw) { - gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, - gread->stfbi); - } } } else if (old_gctx) { @@ -614,21 +575,6 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) gsurf->base.SwapInterval); } -/** - * Get the pipe surface of the given attachment of the native surface. - */ -static struct pipe_resource * -get_pipe_resource(struct native_display *ndpy, struct native_surface *nsurf, - enum native_attachment natt) -{ - struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; - - textures[natt] = NULL; - nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); - - return textures[natt]; -} - static EGLBoolean egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLNativePixmapType target) @@ -636,43 +582,18 @@ 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 native_surface *nsurf; - struct pipe_resource *ptex; - struct pipe_context *pipe; if (!gsurf->render_texture) return EGL_TRUE; - 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, ST_FLUSH_FRONT, NULL); } - 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_box src_box; - - u_box_origin_2d(ptex->width0, ptex->height0, &src_box); - 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); - } - - nsurf->destroy(nsurf); - - return EGL_TRUE; + return gdpy->native->copy_to_pixmap(gdpy->native, + target, gsurf->render_texture); } static EGLBoolean 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 ce72e27c3d5..7e9a29b0284 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -37,9 +37,6 @@ #include "egl_g3d.h" #include "egl_g3d_image.h" -/* for struct winsys_handle */ -#include "state_tracker/drm_driver.h" - /** * Reference and return the front left buffer of the native pixmap. */ @@ -137,10 +134,9 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, _EGLImage *img, const EGLint *attribs) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct pipe_resource templ; - struct winsys_handle wsh; _EGLImageAttribs attrs; EGLint format; + struct native_buffer nbuf; if (!dpy->Extensions.MESA_drm_image) return NULL; @@ -166,21 +162,21 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, break; } - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.format = format; - templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - templ.width0 = attrs.Width; - templ.height0 = attrs.Height; - templ.depth0 = 1; - templ.array_size = 1; - - memset(&wsh, 0, sizeof(wsh)); - wsh.handle = (unsigned) name; - wsh.stride = - attrs.DRMBufferStrideMESA * util_format_get_blocksize(templ.format); - - return gdpy->native->buffer->import_buffer(gdpy->native, &templ, &wsh); + memset(&nbuf, 0, sizeof(nbuf)); + nbuf.type = NATIVE_BUFFER_DRM; + nbuf.u.drm.templ.target = PIPE_TEXTURE_2D; + nbuf.u.drm.templ.format = format; + nbuf.u.drm.templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + nbuf.u.drm.templ.width0 = attrs.Width; + nbuf.u.drm.templ.height0 = attrs.Height; + nbuf.u.drm.templ.depth0 = 1; + nbuf.u.drm.templ.array_size = 1; + + nbuf.u.drm.name = name; + nbuf.u.drm.stride = + attrs.DRMBufferStrideMESA * util_format_get_blocksize(format); + + return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf); } #endif /* EGL_MESA_drm_image */ @@ -327,35 +323,26 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_image *gimg = egl_g3d_image(img); - struct winsys_handle wsh; + struct native_buffer nbuf; if (!dpy->Extensions.MESA_drm_image) return EGL_FALSE; - /* get shared handle */ - if (name) { - memset(&handle, 0, sizeof(handle)); - wsh.type = DRM_API_HANDLE_TYPE_SHARED; - if (!gdpy->native->buffer->export_buffer(gdpy->native, - gimg->texture, &wsh)) - return EGL_FALSE; + memset(&nbuf, 0, sizeof(nbuf)); + nbuf.type = NATIVE_BUFFER_DRM; + if (name) + nbuf.u.drm.templ.bind |= PIPE_BIND_SHARED; - *name = wsh.handle; - } + if (!gdpy->native->buffer->export_buffer(gdpy->native, + gimg->texture, &nbuf)) + return EGL_FALSE; - /* get KMS handle */ - if (handle || stride) { - memset(&wsh, 0, sizeof(wsh)); - wsh.type = DRM_API_HANDLE_TYPE_KMS; - if (!gdpy->native->buffer->export_buffer(gdpy->native, - gimg->texture, &wsh)) - return EGL_FALSE; - - if (handle) - *handle = wsh.handle; - if (stride) - *stride = wsh.stride; - } + if (name) + *name = nbuf.u.drm.name; + if (handle) + *handle = nbuf.u.drm.handle; + if (stride) + *stride = nbuf.u.drm.stride; return EGL_TRUE; } diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_loader.h b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h index 78bfe2131ef..e9403fa293b 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_loader.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h @@ -39,7 +39,6 @@ struct sw_winsys; struct egl_g3d_loader { uint profile_masks[ST_API_COUNT]; struct st_api *(*get_st_api)(enum st_api_type api); - struct st_api *(*guess_gl_api)(enum st_profile_type profile); struct pipe_screen *(*create_drm_screen)(const char *name, int fd); struct pipe_screen *(*create_sw_screen)(struct sw_winsys *ws); diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c index 2b944b521a4..60c3e332ac9 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -292,6 +292,8 @@ egl_g3d_create_st_framebuffer(_EGLSurface *surf) return NULL; stfbi->visual = &gsurf->stvis; + p_atomic_set(&stfbi->stamp, 1); + if (gsurf->base.Type != EGL_PBUFFER_BIT) { stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; stfbi->validate = egl_g3d_st_framebuffer_validate; diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 8646e52ed7c..fc50ee485fe 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -152,6 +152,11 @@ struct native_display { */ void *user_data; + /** + * Initialize and create the pipe screen. + */ + boolean (*init_screen)(struct native_display *ndpy); + void (*destroy)(struct native_display *ndpy); /** @@ -170,16 +175,21 @@ struct native_display { int *num_configs); /** - * Test if a pixmap is supported by the given config. Required unless no - * config has pixmap_bit set. - * - * This function is usually called to find a config that supports a given - * pixmap. Thus, it is usually called with the same pixmap in a row. + * Get the color format of the pixmap. Required unless no config has + * pixmap_bit set. */ - boolean (*is_pixmap_supported)(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf); + boolean (*get_pixmap_format)(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format); + /** + * Copy the contents of the resource to the pixmap's front-left attachment. + * This is used to implement eglCopyBuffers. Required unless no config has + * pixmap_bit set. + */ + boolean (*copy_to_pixmap)(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src); /** * Create a window surface. Required unless no config has window_bit set. @@ -219,6 +229,9 @@ struct native_event_handler { const char *name, int fd); struct pipe_screen *(*new_sw_screen)(struct native_display *ndpy, struct sw_winsys *ws); + + struct pipe_resource *(*lookup_egl_image)(struct native_display *ndpy, + void *egl_image); }; /** @@ -256,26 +269,29 @@ ndpy_uninit(struct native_display *ndpy) struct native_platform { const char *name; - void (*set_event_handler)(struct native_event_handler *handler); - struct native_display *(*create_display)(void *dpy, - boolean use_sw, - void *user_data); + /** + * Create the native display and usually establish a connection to the + * display server. + * + * No event should be generated at this stage. + */ + struct native_display *(*create_display)(void *dpy, boolean use_sw); }; const struct native_platform * -native_get_gdi_platform(void); +native_get_gdi_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_x11_platform(void); +native_get_x11_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_wayland_platform(void); +native_get_wayland_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_drm_platform(void); +native_get_drm_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_fbdev_platform(void); +native_get_fbdev_platform(const struct native_event_handler *event_handler); #ifdef __cplusplus } diff --git a/src/gallium/state_trackers/egl/common/native_buffer.h b/src/gallium/state_trackers/egl/common/native_buffer.h index 5c29ab97411..b8a66d17e12 100644 --- a/src/gallium/state_trackers/egl/common/native_buffer.h +++ b/src/gallium/state_trackers/egl/common/native_buffer.h @@ -30,30 +30,43 @@ #define _NATIVE_BUFFER_H_ #include "pipe/p_compiler.h" +#include "pipe/p_state.h" struct native_display; -struct pipe_resource; + +enum native_buffer_type { + NATIVE_BUFFER_DRM, + + NUM_NATIVE_BUFFERS +}; + +struct native_buffer { + enum native_buffer_type type; + + union { + struct { + struct pipe_resource templ; + unsigned name; /**< the name of the GEM object */ + unsigned handle; /**< the handle of the GEM object */ + unsigned stride; + } drm; + } u; +}; /** * Buffer interface of the native display. It allows native buffers to be * imported and exported. - * - * Just like a native window or a native pixmap, a native buffer is another - * native type. Its definition depends on the native display. - * - * For DRM platform, the type of a native buffer is struct winsys_handle. */ struct native_display_buffer { struct pipe_resource *(*import_buffer)(struct native_display *ndpy, - const struct pipe_resource *templ, - void *buf); + struct native_buffer *buf); /** * The resource must be creatred with PIPE_BIND_SHARED. */ boolean (*export_buffer)(struct native_display *ndpy, struct pipe_resource *res, - void *buf); + struct native_buffer *nbuf); }; #endif /* _NATIVE_BUFFER_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index ee18cb2025b..cca1e1c6295 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.c +++ b/src/gallium/state_trackers/egl/common/native_helper.c @@ -282,9 +282,9 @@ resource_surface_copy_swap(struct resource_surface *rsurf, btex, 0, &src_box); ret = TRUE; - out_no_ftex: - pipe_resource_reference(&btex, NULL); out_no_btex: + pipe_resource_reference(&btex, NULL); + out_no_ftex: pipe_resource_reference(&ftex, NULL); return ret; @@ -367,3 +367,116 @@ resource_surface_wait(struct resource_surface *rsurf) { while (resource_surface_throttle(rsurf)); } + +boolean +native_display_copy_to_pixmap(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src) +{ + struct pipe_context *pipe; + struct native_surface *nsurf; + struct pipe_resource *dst; + struct pipe_resource *tmp[NUM_NATIVE_ATTACHMENTS]; + const enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + pipe = ndpy_get_copy_context(ndpy); + if (!pipe) + return FALSE; + + nsurf = ndpy->create_pixmap_surface(ndpy, pix, NULL); + if (!nsurf) + return FALSE; + + /* get the texutre */ + tmp[natt] = NULL; + nsurf->validate(nsurf, 1 << natt, NULL, tmp, NULL, NULL); + dst = tmp[natt]; + + if (dst && dst->format == src->format) { + struct pipe_box src_box; + + u_box_origin_2d(src->width0, src->height0, &src_box); + pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &src_box); + pipe->flush(pipe, NULL); + nsurf->present(nsurf, natt, FALSE, 0); + } + + if (dst) + pipe_resource_reference(&dst, NULL); + + nsurf->destroy(nsurf); + + return TRUE; +} + +#include "state_tracker/drm_driver.h" +struct pipe_resource * +drm_display_import_native_buffer(struct native_display *ndpy, + struct native_buffer *nbuf) +{ + struct pipe_screen *screen = ndpy->screen; + struct pipe_resource *res = NULL; + + switch (nbuf->type) { + case NATIVE_BUFFER_DRM: + { + struct winsys_handle wsh; + + memset(&wsh, 0, sizeof(wsh)); + wsh.handle = nbuf->u.drm.name; + wsh.stride = nbuf->u.drm.stride; + + res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh); + } + break; + default: + break; + } + + return res; +} + +boolean +drm_display_export_native_buffer(struct native_display *ndpy, + struct pipe_resource *res, + struct native_buffer *nbuf) +{ + struct pipe_screen *screen = ndpy->screen; + boolean ret = FALSE; + + switch (nbuf->type) { + case NATIVE_BUFFER_DRM: + { + struct winsys_handle wsh; + + if ((nbuf->u.drm.templ.bind & res->bind) != nbuf->u.drm.templ.bind) + break; + + memset(&wsh, 0, sizeof(wsh)); + wsh.type = DRM_API_HANDLE_TYPE_KMS; + if (!screen->resource_get_handle(screen, res, &wsh)) + break; + + nbuf->u.drm.handle = wsh.handle; + nbuf->u.drm.stride = wsh.stride; + + /* get the name of the GEM object */ + if (nbuf->u.drm.templ.bind & PIPE_BIND_SHARED) { + memset(&wsh, 0, sizeof(wsh)); + wsh.type = DRM_API_HANDLE_TYPE_SHARED; + if (!screen->resource_get_handle(screen, res, &wsh)) + break; + + nbuf->u.drm.name = wsh.handle; + } + + nbuf->u.drm.templ = *res; + ret = TRUE; + } + break; + default: + break; + } + + return ret; +} diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h index 39564a04365..e8d91ccb02a 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.h +++ b/src/gallium/state_trackers/egl/common/native_helper.h @@ -105,3 +105,17 @@ resource_surface_flush(struct resource_surface *rsurf, */ void resource_surface_wait(struct resource_surface *rsurf); + +boolean +native_display_copy_to_pixmap(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src); + +struct pipe_resource * +drm_display_import_native_buffer(struct native_display *ndpy, + struct native_buffer *nbuf); + +boolean +drm_display_export_native_buffer(struct native_display *ndpy, + struct pipe_resource *res, + struct native_buffer *nbuf); diff --git a/src/gallium/state_trackers/egl/drm/modeset.c b/src/gallium/state_trackers/egl/drm/modeset.c index 3fff9540905..73968d1343b 100644 --- a/src/gallium/state_trackers/egl/drm/modeset.c +++ b/src/gallium/state_trackers/egl/drm/modeset.c @@ -290,6 +290,42 @@ drm_display_create_surface(struct native_display *ndpy, return drmsurf; } +struct native_surface * +drm_display_create_surface_from_resource(struct native_display *ndpy, + struct pipe_resource *resource) +{ + struct drm_display *drmdpy = drm_display(ndpy); + struct drm_surface *drmsurf; + enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + drmsurf = CALLOC_STRUCT(drm_surface); + if (!drmsurf) + return NULL; + + drmsurf->drmdpy = drmdpy; + drmsurf->color_format = resource->format; + drmsurf->width = resource->width0; + drmsurf->height = resource->height0; + drmsurf->have_pageflip = FALSE; + + drmsurf->rsurf = resource_surface_create(drmdpy->base.screen, + drmsurf->color_format, + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT); + + resource_surface_import_resource(drmsurf->rsurf, natt, resource); + + drmsurf->base.destroy = drm_surface_destroy; + drmsurf->base.present = drm_surface_present; + drmsurf->base.validate = drm_surface_validate; + drmsurf->base.wait = drm_surface_wait; + + return &drmsurf->base; +} + + /** * Choose a CRTC that supports all given connectors. */ diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c index 725fe28e4e2..47910de8d3c 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.c +++ b/src/gallium/state_trackers/egl/drm/native_drm.c @@ -33,6 +33,8 @@ #include "native_drm.h" +#include "gbm_gallium_drmint.h" + #ifdef HAVE_LIBUDEV #include <libudev.h> #endif @@ -125,6 +127,8 @@ drm_display_destroy(struct native_display *ndpy) drm_display_fini_modeset(&drmdpy->base); + /* gbm owns screen */ + ndpy->screen = NULL; ndpy_uninit(ndpy); if (drmdpy->device_name) @@ -136,54 +140,10 @@ drm_display_destroy(struct native_display *ndpy) FREE(drmdpy); } -/** - * Initialize KMS and pipe screen. - */ -static boolean -drm_display_init_screen(struct native_display *ndpy) -{ - struct drm_display *drmdpy = drm_display(ndpy); - drmVersionPtr version; - - version = drmGetVersion(drmdpy->fd); - if (!version) { - _eglLog(_EGL_WARNING, "invalid fd %d", drmdpy->fd); - return FALSE; - } - - drmdpy->base.screen = - drmdpy->event_handler->new_drm_screen(&drmdpy->base, NULL, drmdpy->fd); - drmFreeVersion(version); - - if (!drmdpy->base.screen) { - _eglLog(_EGL_DEBUG, "failed to create DRM screen"); - return FALSE; - } - - return TRUE; -} - -static struct pipe_resource * -drm_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 -drm_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 drm_display_buffer = { - drm_display_import_buffer, - drm_display_export_buffer + /* use the helpers */ + drm_display_import_native_buffer, + drm_display_export_native_buffer }; static int @@ -281,9 +241,25 @@ static struct native_display_wayland_bufmgr drm_display_wayland_bufmgr = { #endif /* HAVE_WAYLAND_BACKEND */ +static struct native_surface * +drm_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct gbm_gallium_drm_bo *bo = (void *) pix; + + return drm_display_create_surface_from_resource(ndpy, bo->resource); +} + +static boolean +drm_display_init_screen(struct native_display *ndpy) +{ + return TRUE; +} + static struct native_display * -drm_create_display(int fd, struct native_event_handler *event_handler, - void *user_data) +drm_create_display(struct gbm_gallium_drm_device *gbmdrm, + const struct native_event_handler *event_handler) { struct drm_display *drmdpy; @@ -291,20 +267,24 @@ drm_create_display(int fd, struct native_event_handler *event_handler, if (!drmdpy) return NULL; - drmdpy->fd = fd; - drmdpy->device_name = drm_get_device_name(fd); + drmdpy->fd = gbmdrm->base.base.fd; + drmdpy->device_name = drm_get_device_name(drmdpy->fd); + + gbmdrm->lookup_egl_image = (struct pipe_resource *(*)(void *, void *)) + event_handler->lookup_egl_image; + gbmdrm->lookup_egl_image_data = &drmdpy->base; + drmdpy->event_handler = event_handler; - drmdpy->base.user_data = user_data; - if (!drm_display_init_screen(&drmdpy->base)) { - drm_display_destroy(&drmdpy->base); - return NULL; - } + drmdpy->base.screen = gbmdrm->screen; + drmdpy->base.init_screen = drm_display_init_screen; drmdpy->base.destroy = drm_display_destroy; drmdpy->base.get_param = drm_display_get_param; drmdpy->base.get_configs = drm_display_get_configs; + drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface; + drmdpy->base.buffer = &drm_display_buffer; #ifdef HAVE_WAYLAND_BACKEND if (drmdpy->device_name) @@ -315,39 +295,39 @@ 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 const struct native_event_handler *drm_event_handler; static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { + struct gbm_gallium_drm_device *gbm; int fd; - if (dpy) { - fd = dup((int) pointer_to_intptr(dpy)); - } - else { + gbm = dpy; + + if (gbm == NULL) { fd = open("/dev/dri/card0", O_RDWR); + gbm = gbm_gallium_drm_device(gbm_create_device(fd)); } - if (fd < 0) + + if (gbm == NULL) + return NULL; + + if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 || + gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) return NULL; - return drm_create_display(fd, drm_event_handler, user_data); + return drm_create_display(gbm, drm_event_handler); } static const struct native_platform drm_platform = { "DRM", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_drm_platform(void) +native_get_drm_platform(const struct native_event_handler *event_handler) { + drm_event_handler = event_handler; return &drm_platform; } diff --git a/src/gallium/state_trackers/egl/drm/native_drm.h b/src/gallium/state_trackers/egl/drm/native_drm.h index 41cdc4f9d04..675a58a1922 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.h +++ b/src/gallium/state_trackers/egl/drm/native_drm.h @@ -50,7 +50,7 @@ struct drm_surface; struct drm_display { struct native_display base; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; int fd; char *device_name; @@ -154,4 +154,8 @@ drm_display_init_modeset(struct native_display *ndpy); void drm_display_fini_modeset(struct native_display *ndpy); +struct native_surface * +drm_display_create_surface_from_resource(struct native_display *ndpy, + struct pipe_resource *resource); + #endif /* _NATIVE_DRM_H_ */ diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c index e2fde00e975..6772d379f73 100644 --- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c +++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c @@ -26,6 +26,21 @@ * Chia-I Wu <[email protected]> */ +/** + * Considering fbdev as an in-kernel window system, + * + * - opening a device opens a connection + * - there is only one window: the framebuffer + * - fb_var_screeninfo decides window position, size, and even color format + * - there is no pixmap + * + * Now EGL is built on top of this window system. So we should have + * + * - the fd as the handle of the native display + * - reject all but one native window: NULL + * - no pixmap support + */ + #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> @@ -45,16 +60,13 @@ struct fbdev_display { struct native_display base; int fd; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct fb_fix_screeninfo finfo; - struct fb_var_screeninfo vinfo; - + struct fb_var_screeninfo config_vinfo; struct native_config config; - struct native_connector connector; - struct native_mode mode; - struct fbdev_surface *current_surface; + boolean assume_fixed_vinfo; }; struct fbdev_surface { @@ -66,7 +78,7 @@ struct fbdev_surface { unsigned int sequence_number; - boolean is_current; + struct fbdev_sw_drawable drawable; }; static INLINE struct fbdev_display * @@ -103,38 +115,70 @@ fbdev_surface_validate(struct native_surface *nsurf, uint attachment_mask, return TRUE; } -static boolean -fbdev_surface_flush_frontbuffer(struct native_surface *nsurf) +static enum pipe_format +vinfo_to_format(const struct fb_var_screeninfo *vinfo) { - struct fbdev_surface *fbsurf = fbdev_surface(nsurf); + enum pipe_format format = PIPE_FORMAT_NONE; - if (!fbsurf->is_current) - return TRUE; + /* should also check channel offsets... */ + switch (vinfo->bits_per_pixel) { + case 32: + if (vinfo->red.length == 8 && + vinfo->green.length == 8 && + vinfo->blue.length == 8) { + format = (vinfo->transp.length == 8) ? + PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM; + } + break; + case 16: + if (vinfo->red.length == 5 && + vinfo->green.length == 6 && + vinfo->blue.length == 5 && + vinfo->transp.length == 0) + format = PIPE_FORMAT_B5G6R5_UNORM; + break; + default: + break; + } - return resource_surface_present(fbsurf->rsurf, - NATIVE_ATTACHMENT_FRONT_LEFT, NULL); + return format; } static boolean -fbdev_surface_swap_buffers(struct native_surface *nsurf) +fbdev_surface_update_drawable(struct native_surface *nsurf, + const struct fb_var_screeninfo *vinfo) { struct fbdev_surface *fbsurf = fbdev_surface(nsurf); - struct fbdev_display *fbdpy = fbsurf->fbdpy; - boolean ret = TRUE; - - if (fbsurf->is_current) { - ret = resource_surface_present(fbsurf->rsurf, - NATIVE_ATTACHMENT_BACK_LEFT, NULL); + unsigned x, y, width, height; + + x = vinfo->xoffset; + y = vinfo->yoffset; + width = MIN2(vinfo->xres, fbsurf->width); + height = MIN2(vinfo->yres, fbsurf->height); + + /* sanitize the values */ + if (x + width > vinfo->xres_virtual) { + if (x > vinfo->xres_virtual) + width = 0; + else + width = vinfo->xres_virtual - x; + } + if (y + height > vinfo->yres_virtual) { + if (y > vinfo->yres_virtual) + height = 0; + else + height = vinfo->yres_virtual - y; } - resource_surface_swap_buffers(fbsurf->rsurf, - NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE); - /* the front/back textures are swapped */ - fbsurf->sequence_number++; - fbdpy->event_handler->invalid_surface(&fbdpy->base, - &fbsurf->base, fbsurf->sequence_number); + fbsurf->drawable.format = vinfo_to_format(vinfo); + fbsurf->drawable.x = vinfo->xoffset; + fbsurf->drawable.y = vinfo->yoffset; + fbsurf->drawable.width = vinfo->xres; + fbsurf->drawable.height = vinfo->yres; - return ret; + return (fbsurf->drawable.format != PIPE_FORMAT_NONE && + fbsurf->drawable.width && + fbsurf->drawable.height); } static boolean @@ -143,21 +187,43 @@ fbdev_surface_present(struct native_surface *nsurf, boolean preserve, uint swap_interval) { - boolean ret; + struct fbdev_surface *fbsurf = fbdev_surface(nsurf); + struct fbdev_display *fbdpy = fbsurf->fbdpy; + boolean ret = FALSE; - if (preserve || swap_interval) + if (swap_interval) + return FALSE; + if (natt != NATIVE_ATTACHMENT_BACK_LEFT) return FALSE; - switch (natt) { - case NATIVE_ATTACHMENT_FRONT_LEFT: - ret = fbdev_surface_flush_frontbuffer(nsurf); - break; - case NATIVE_ATTACHMENT_BACK_LEFT: - ret = fbdev_surface_swap_buffers(nsurf); - break; - default: - ret = FALSE; - break; + if (!fbdpy->assume_fixed_vinfo) { + struct fb_var_screeninfo vinfo; + + memset(&vinfo, 0, sizeof(vinfo)); + if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo)) + return FALSE; + + /* present the surface */ + if (fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) { + ret = resource_surface_present(fbsurf->rsurf, + natt, (void *) &fbsurf->drawable); + } + + fbsurf->width = vinfo.xres; + fbsurf->height = vinfo.yres; + + if (resource_surface_set_size(fbsurf->rsurf, + fbsurf->width, fbsurf->height)) { + /* surface resized */ + fbsurf->sequence_number++; + fbdpy->event_handler->invalid_surface(&fbdpy->base, + &fbsurf->base, fbsurf->sequence_number); + } + } + else { + /* the drawable never changes */ + ret = resource_surface_present(fbsurf->rsurf, + natt, (void *) &fbsurf->drawable); } return ret; @@ -179,26 +245,48 @@ fbdev_surface_destroy(struct native_surface *nsurf) } static struct native_surface * -fbdev_display_create_scanout_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) +fbdev_display_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) { struct fbdev_display *fbdpy = fbdev_display(ndpy); struct fbdev_surface *fbsurf; + struct fb_var_screeninfo vinfo; + + /* there is only one native window: NULL */ + if (win) + return NULL; fbsurf = CALLOC_STRUCT(fbdev_surface); if (!fbsurf) return NULL; fbsurf->fbdpy = fbdpy; - fbsurf->width = width; - fbsurf->height = height; + + /* get current vinfo */ + if (fbdpy->assume_fixed_vinfo) { + vinfo = fbdpy->config_vinfo; + } + else { + memset(&vinfo, 0, sizeof(vinfo)); + if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo)) { + FREE(fbsurf); + return NULL; + } + } + + fbsurf->width = vinfo.xres; + fbsurf->height = vinfo.yres; + + if (!fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) { + FREE(fbsurf); + return NULL; + } fbsurf->rsurf = resource_surface_create(fbdpy->base.screen, nconf->color_format, PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT); + PIPE_BIND_DISPLAY_TARGET); if (!fbsurf->rsurf) { FREE(fbsurf); return NULL; @@ -214,42 +302,43 @@ fbdev_display_create_scanout_surface(struct native_display *ndpy, return &fbsurf->base; } +static struct native_surface * +fbdev_display_create_scanout_surface(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height) +{ + return fbdev_display_create_window_surface(ndpy, + (EGLNativeWindowType) NULL, nconf); +} + static boolean fbdev_display_program(struct native_display *ndpy, int crtc_idx, struct native_surface *nsurf, uint x, uint y, const struct native_connector **nconns, int num_nconns, const struct native_mode *nmode) { - struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct fbdev_surface *fbsurf = fbdev_surface(nsurf); - - if (x || y) - return FALSE; - - if (fbdpy->current_surface) { - if (fbdpy->current_surface == fbsurf) - return TRUE; - fbdpy->current_surface->is_current = FALSE; - } - - if (fbsurf) - fbsurf->is_current = TRUE; - fbdpy->current_surface = fbsurf; - return TRUE; } static const struct native_mode ** fbdev_display_get_modes(struct native_display *ndpy, - const struct native_connector *nconn, - int *num_modes) + const struct native_connector *nconn, + int *num_modes) { - struct fbdev_display *fbdpy = fbdev_display(ndpy); + static struct native_mode mode; const struct native_mode **modes; + if (!mode.desc) { + struct fbdev_display *fbdpy = fbdev_display(ndpy); + mode.desc = "Current Mode"; + mode.width = fbdpy->config_vinfo.xres; + mode.height = fbdpy->config_vinfo.yres; + mode.refresh_rate = 60 * 1000; /* dummy */ + } + modes = MALLOC(sizeof(*modes)); if (modes) { - modes[0] = &fbdpy->mode; + modes[0] = &mode; if (num_modes) *num_modes = 1; } @@ -261,12 +350,12 @@ static const struct native_connector ** fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors, int *num_crtc) { - struct fbdev_display *fbdpy = fbdev_display(ndpy); + static struct native_connector connector; const struct native_connector **connectors; connectors = MALLOC(sizeof(*connectors)); if (connectors) { - connectors[0] = &fbdpy->connector; + connectors[0] = &connector; if (num_connectors) *num_connectors = 1; } @@ -274,7 +363,8 @@ fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors, return connectors; } -static struct native_display_modeset fbdev_display_modeset = { +/* remove modeset support one day! */ +static const struct native_display_modeset fbdev_display_modeset = { .get_connectors = fbdev_display_get_connectors, .get_modes = fbdev_display_get_modes, .create_scanout_surface = fbdev_display_create_scanout_surface, @@ -304,8 +394,10 @@ fbdev_display_get_param(struct native_display *ndpy, int val; switch (param) { - case NATIVE_PARAM_USE_NATIVE_BUFFER: case NATIVE_PARAM_PRESERVE_BUFFER: + val = 1; + break; + case NATIVE_PARAM_USE_NATIVE_BUFFER: case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; @@ -326,114 +418,55 @@ fbdev_display_destroy(struct native_display *ndpy) } static boolean -fbdev_display_init_modes(struct native_display *ndpy) +fbdev_display_init_screen(struct native_display *ndpy) { struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct native_mode *nmode = &fbdpy->mode; - - nmode->desc = "Current Mode"; - nmode->width = fbdpy->vinfo.xres; - nmode->height = fbdpy->vinfo.yres; - nmode->refresh_rate = 60 * 1000; /* dummy */ - - return TRUE; -} - -static boolean -fbdev_display_init_connectors(struct native_display *ndpy) -{ - return TRUE; -} + struct sw_winsys *ws; -static enum pipe_format -vinfo_to_format(const struct fb_var_screeninfo *vinfo) -{ - enum pipe_format format = PIPE_FORMAT_NONE; + ws = fbdev_create_sw_winsys(fbdpy->fd); + if (!ws) + return FALSE; - switch (vinfo->bits_per_pixel) { - case 32: - if (vinfo->red.length == 8 && - vinfo->green.length == 8 && - vinfo->blue.length == 8) { - format = (vinfo->transp.length == 8) ? - PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM; - } - break; - case 16: - if (vinfo->red.length == 5 && - vinfo->green.length == 6 && - vinfo->blue.length == 5 && - vinfo->transp.length == 0) - format = PIPE_FORMAT_B5G6R5_UNORM; - break; - default: - break; + fbdpy->base.screen = fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws); + if (!fbdpy->base.screen) { + if (ws->destroy) + ws->destroy(ws); + return FALSE; } - return format; -} - -static boolean -fbdev_display_init_configs(struct native_display *ndpy) -{ - struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct native_config *nconf = &fbdpy->config; - - nconf->color_format = vinfo_to_format(&fbdpy->vinfo); - if (nconf->color_format == PIPE_FORMAT_NONE) + if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen, + fbdpy->config.color_format, PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)) { + fbdpy->base.screen->destroy(fbdpy->base.screen); + fbdpy->base.screen = NULL; return FALSE; - - nconf->buffer_mask = - (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | - (1 << NATIVE_ATTACHMENT_BACK_LEFT); - - nconf->scanout_bit = TRUE; + } return TRUE; } static boolean -fbdev_display_init(struct native_display *ndpy) +fbdev_display_init_config(struct native_display *ndpy) { struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct sw_winsys *ws; - - if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo)) - return FALSE; + struct native_config *nconf = &fbdpy->config; - if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->vinfo)) + if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->config_vinfo)) return FALSE; - if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR || - fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS) + nconf->color_format = vinfo_to_format(&fbdpy->config_vinfo); + if (nconf->color_format == PIPE_FORMAT_NONE) return FALSE; - if (!fbdev_display_init_configs(&fbdpy->base) || - !fbdev_display_init_connectors(&fbdpy->base) || - !fbdev_display_init_modes(&fbdpy->base)) - return FALSE; + nconf->buffer_mask = (1 << NATIVE_ATTACHMENT_BACK_LEFT); - ws = fbdev_create_sw_winsys(fbdpy->fd, fbdpy->config.color_format); - if (ws) { - fbdpy->base.screen = - fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws); - } + nconf->window_bit = TRUE; - 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)) { - fbdpy->base.screen->destroy(fbdpy->base.screen); - fbdpy->base.screen = NULL; - } - } - - return (fbdpy->base.screen != NULL); + return TRUE; } static struct native_display * -fbdev_display_create(int fd, struct native_event_handler *event_handler, - void *user_data) +fbdev_display_create(int fd, const struct native_event_handler *event_handler) { struct fbdev_display *fbdpy; @@ -443,32 +476,41 @@ fbdev_display_create(int fd, struct native_event_handler *event_handler, fbdpy->fd = fd; fbdpy->event_handler = event_handler; - fbdpy->base.user_data = user_data; - if (!fbdev_display_init(&fbdpy->base)) { - FREE(fbdpy); - return NULL; - } + if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo)) + goto fail; + + if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR || + fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS) + goto fail; + + if (!fbdev_display_init_config(&fbdpy->base)) + goto fail; + fbdpy->assume_fixed_vinfo = TRUE; + + fbdpy->base.init_screen = fbdev_display_init_screen; fbdpy->base.destroy = fbdev_display_destroy; fbdpy->base.get_param = fbdev_display_get_param; fbdpy->base.get_configs = fbdev_display_get_configs; + fbdpy->base.create_window_surface = fbdev_display_create_window_surface; + + /* we'd like to remove modeset support one day */ + fbdpy->config.scanout_bit = TRUE; fbdpy->base.modeset = &fbdev_display_modeset; 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; +fail: + FREE(fbdpy); + return NULL; } +static const struct native_event_handler *fbdev_event_handler; + static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { struct native_display *ndpy; int fd; @@ -483,7 +525,7 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) if (fd < 0) return NULL; - ndpy = fbdev_display_create(fd, fbdev_event_handler, user_data); + ndpy = fbdev_display_create(fd, fbdev_event_handler); if (!ndpy) close(fd); @@ -492,12 +534,12 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) static const struct native_platform fbdev_platform = { "FBDEV", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_fbdev_platform(void) +native_get_fbdev_platform(const struct native_event_handler *event_handler) { + fbdev_event_handler = event_handler; return &fbdev_platform; } diff --git a/src/gallium/state_trackers/egl/gdi/native_gdi.c b/src/gallium/state_trackers/egl/gdi/native_gdi.c index 5d0045f92ee..6bf0d4e4668 100644 --- a/src/gallium/state_trackers/egl/gdi/native_gdi.c +++ b/src/gallium/state_trackers/egl/gdi/native_gdi.c @@ -41,7 +41,7 @@ struct gdi_display { struct native_display base; HDC hDC; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct native_config *configs; int num_configs; @@ -368,35 +368,39 @@ gdi_display_destroy(struct native_display *ndpy) FREE(gdpy); } -static struct native_display * -gdi_create_display(HDC hDC, struct native_event_handler *event_handler, - void *user_data) +static boolean +gdi_display_init_screen(struct native_display *ndpy) { - struct gdi_display *gdpy; + struct gdi_display *gdpy = gdi_display(ndpy); struct sw_winsys *winsys; - gdpy = CALLOC_STRUCT(gdi_display); - if (!gdpy) - return NULL; - - gdpy->hDC = hDC; - gdpy->event_handler = event_handler; - gdpy->base.user_data = user_data; - winsys = gdi_create_sw_winsys(); - if (!winsys) { - FREE(gdpy); - return NULL; - } + if (!winsys) + return FALSE; gdpy->base.screen = gdpy->event_handler->new_sw_screen(&gdpy->base, winsys); if (!gdpy->base.screen) { if (winsys->destroy) winsys->destroy(winsys); - FREE(gdpy); - return NULL; + return FALSE; } + return TRUE; +} + +static struct native_display * +gdi_create_display(HDC hDC, const struct native_event_handler *event_handler) +{ + struct gdi_display *gdpy; + + gdpy = CALLOC_STRUCT(gdi_display); + if (!gdpy) + return NULL; + + gdpy->hDC = hDC; + gdpy->event_handler = event_handler; + + gdpy->base.init_screen = gdi_display_init_screen; gdpy->base.destroy = gdi_display_destroy; gdpy->base.get_param = gdi_display_get_param; @@ -406,28 +410,22 @@ 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 const struct native_event_handler *gdi_event_handler; static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { - return gdi_create_display((HDC) dpy, gdi_event_handler, user_data); + return gdi_create_display((HDC) dpy, gdi_event_handler); } static const struct native_platform gdi_platform = { "GDI", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_gdi_platform(void) +native_get_gdi_platform(const struct native_event_handler *event_handler) { + gdi_event_handler = event_handler; return &gdi_platform; } diff --git a/src/gallium/state_trackers/egl/wayland/native_drm.c b/src/gallium/state_trackers/egl/wayland/native_drm.c index 15383e89301..e34b24b58b1 100644 --- a/src/gallium/state_trackers/egl/wayland/native_drm.c +++ b/src/gallium/state_trackers/egl/wayland/native_drm.c @@ -51,7 +51,7 @@ struct wayland_drm_display { struct wayland_display base; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct wl_drm *wl_drm; struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */ @@ -98,6 +98,8 @@ wayland_drm_display_destroy(struct native_display *ndpy) FREE(drmdpy->device_name); if (drmdpy->base.config) FREE(drmdpy->base.config); + if (drmdpy->base.own_dpy) + wl_display_destroy(drmdpy->base.dpy); ndpy_uninit(ndpy); @@ -210,27 +212,10 @@ wayland_drm_display_init_screen(struct native_display *ndpy) return TRUE; } -static struct pipe_resource * -wayland_drm_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_drm_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_drm_display_buffer = { - wayland_drm_display_import_buffer, - wayland_drm_display_export_buffer + /* use the helpers */ + drm_display_import_native_buffer, + drm_display_export_native_buffer }; static int @@ -300,8 +285,7 @@ static struct native_display_wayland_bufmgr wayland_drm_display_wayland_bufmgr = struct wayland_display * wayland_create_drm_display(struct wl_display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct wayland_drm_display *drmdpy; @@ -310,7 +294,6 @@ wayland_create_drm_display(struct wl_display *dpy, return NULL; drmdpy->event_handler = event_handler; - drmdpy->base.base.user_data = user_data; drmdpy->base.dpy = dpy; if (!drmdpy->base.dpy) { @@ -318,10 +301,7 @@ wayland_create_drm_display(struct wl_display *dpy, return NULL; } - if (!wayland_drm_display_init_screen(&drmdpy->base.base)) { - wayland_drm_display_destroy(&drmdpy->base.base); - return NULL; - } + drmdpy->base.base.init_screen = wayland_drm_display_init_screen; drmdpy->base.base.destroy = wayland_drm_display_destroy; drmdpy->base.base.buffer = &wayland_drm_display_buffer; drmdpy->base.base.wayland_bufmgr = &wayland_drm_display_wayland_bufmgr; diff --git a/src/gallium/state_trackers/egl/wayland/native_shm.c b/src/gallium/state_trackers/egl/wayland/native_shm.c index 609fc0cd04a..1c0799528fe 100644 --- a/src/gallium/state_trackers/egl/wayland/native_shm.c +++ b/src/gallium/state_trackers/egl/wayland/native_shm.c @@ -47,7 +47,7 @@ struct wayland_shm_display { struct wayland_display base; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct wl_shm *wl_shm; }; @@ -65,6 +65,8 @@ wayland_shm_display_destroy(struct native_display *ndpy) if (shmdpy->base.config) FREE(shmdpy->base.config); + if (shmdpy->base.own_dpy) + wl_display_destroy(shmdpy->base.dpy); ndpy_uninit(ndpy); @@ -142,8 +144,7 @@ wayland_shm_display_init_screen(struct native_display *ndpy) struct wayland_display * wayland_create_shm_display(struct wl_display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct wayland_shm_display *shmdpy; @@ -152,7 +153,6 @@ wayland_create_shm_display(struct wl_display *dpy, return NULL; shmdpy->event_handler = event_handler; - shmdpy->base.base.user_data = user_data; shmdpy->base.dpy = dpy; if (!shmdpy->base.dpy) { @@ -160,11 +160,7 @@ wayland_create_shm_display(struct wl_display *dpy, return NULL; } - if (!wayland_shm_display_init_screen(&shmdpy->base.base)) { - wayland_shm_display_destroy(&shmdpy->base.base); - return NULL; - } - + shmdpy->base.base.init_screen = wayland_shm_display_init_screen; shmdpy->base.base.destroy = wayland_shm_display_destroy; shmdpy->base.create_buffer = wayland_create_shm_buffer; diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c index 0292d5631d6..544d4be215a 100644 --- a/src/gallium/state_trackers/egl/wayland/native_wayland.c +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c @@ -35,7 +35,7 @@ #include "native_wayland.h" -static struct native_event_handler *wayland_event_handler; +static const struct native_event_handler *wayland_event_handler; static void sync_callback(void *data) @@ -114,11 +114,12 @@ wayland_display_get_param(struct native_display *ndpy, } static boolean -wayland_display_is_pixmap_supported(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf) +wayland_display_get_pixmap_format(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format) { /* all wl_egl_pixmaps are supported */ + *format = PIPE_FORMAT_NONE; return TRUE; } @@ -195,13 +196,11 @@ wayland_window_surface_handle_resize(struct wayland_surface *surface) wl_buffer_destroy(surface->buffer[i]); surface->buffer[i] = NULL; } + + surface->dx = surface->win->dx; + surface->dy = surface->win->dy; } 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 @@ -449,28 +448,28 @@ wayland_create_window_surface(struct native_display *ndpy, return &surface->base; } -static void -native_set_event_handler(struct native_event_handler *event_handler) -{ - wayland_event_handler = event_handler; -} - static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { struct wayland_display *display = NULL; + boolean own_dpy = FALSE; use_sw = use_sw || debug_get_bool_option("EGL_SOFTWARE", FALSE); + if (dpy == NULL) { + dpy = wl_display_connect(NULL); + if (dpy == NULL) + return NULL; + own_dpy = TRUE; + } + if (use_sw) { _eglLog(_EGL_INFO, "use software fallback"); display = wayland_create_shm_display((struct wl_display *) dpy, - wayland_event_handler, - user_data); + wayland_event_handler); } else { display = wayland_create_drm_display((struct wl_display *) dpy, - wayland_event_handler, - user_data); + wayland_event_handler); } if (!display) @@ -478,22 +477,25 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) 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.get_pixmap_format = wayland_display_get_pixmap_format; + display->base.copy_to_pixmap = native_display_copy_to_pixmap; display->base.create_window_surface = wayland_create_window_surface; display->base.create_pixmap_surface = wayland_create_pixmap_surface; + display->own_dpy = own_dpy; + return &display->base; } static const struct native_platform wayland_platform = { "wayland", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_wayland_platform(void) +native_get_wayland_platform(const struct native_event_handler *event_handler) { + wayland_event_handler = event_handler; 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 index e69a8f00f82..5390f2f08c9 100644 --- a/src/gallium/state_trackers/egl/wayland/native_wayland.h +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h @@ -41,6 +41,7 @@ struct wayland_display { struct wayland_config *config; struct wl_display *dpy; + boolean own_dpy; struct wl_buffer *(*create_buffer)(struct wayland_display *display, struct wayland_surface *surface, @@ -102,11 +103,10 @@ wayland_config(const struct native_config *nconf) struct wayland_display * wayland_create_shm_display(struct wl_display *display, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); + struct wayland_display * wayland_create_drm_display(struct wl_display *display, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); #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 a56d43428fc..4b8be7bc759 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -38,6 +38,7 @@ #include "native_x11.h" #include "x11_screen.h" +#include "common/native_helper.h" #ifdef HAVE_WAYLAND_BACKEND #include "common/native_wayland_drm_bufmgr_helper.h" #endif @@ -49,7 +50,7 @@ struct dri2_display { Display *dpy; boolean own_dpy; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct x11_screen *xscr; int xscr_number; @@ -682,18 +683,30 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) } static boolean -dri2_display_is_pixmap_supported(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf) +dri2_display_get_pixmap_format(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format) { struct dri2_display *dri2dpy = dri2_display(ndpy); - uint depth, nconf_depth; + boolean ret = EGL_TRUE; + uint depth; depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); - nconf_depth = util_format_get_blocksizebits(nconf->color_format); + switch (depth) { + case 32: + case 24: + *format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case 16: + *format = PIPE_FORMAT_B5G6R5_UNORM; + break; + default: + *format = PIPE_FORMAT_NONE; + ret = EGL_FALSE; + break; + } - /* simple depth match for now */ - return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); + return ret; } static int @@ -870,8 +883,7 @@ static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = { struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct dri2_display *dri2dpy; @@ -880,7 +892,6 @@ x11_create_dri2_display(Display *dpy, return NULL; dri2dpy->event_handler = event_handler; - dri2dpy->base.user_data = user_data; dri2dpy->dpy = dpy; if (!dri2dpy->dpy) { @@ -899,11 +910,6 @@ x11_create_dri2_display(Display *dpy, return NULL; } - if (!dri2_display_init_screen(&dri2dpy->base)) { - dri2_display_destroy(&dri2dpy->base); - return NULL; - } - dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, dri2_display_hash_table_compare); if (!dri2dpy->surfaces) { @@ -911,10 +917,12 @@ x11_create_dri2_display(Display *dpy, return NULL; } + dri2dpy->base.init_screen = dri2_display_init_screen; dri2dpy->base.destroy = dri2_display_destroy; dri2dpy->base.get_param = dri2_display_get_param; dri2dpy->base.get_configs = dri2_display_get_configs; - dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; + dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format; + dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap; dri2dpy->base.create_window_surface = dri2_display_create_window_surface; dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; #ifdef HAVE_WAYLAND_BACKEND @@ -928,8 +936,7 @@ x11_create_dri2_display(Display *dpy, struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { return NULL; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index a0bcad4c734..ef038b52152 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -30,16 +30,10 @@ #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 const struct native_event_handler *x11_event_handler; static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { struct native_display *ndpy = NULL; boolean force_sw; @@ -48,12 +42,10 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) if (force_sw || use_sw) { _eglLog(_EGL_INFO, "use software fallback"); - ndpy = x11_create_ximage_display((Display *) dpy, - x11_event_handler, user_data); + ndpy = x11_create_ximage_display((Display *) dpy, x11_event_handler); } else { - ndpy = x11_create_dri2_display((Display *) dpy, - x11_event_handler, user_data); + ndpy = x11_create_dri2_display((Display *) dpy, x11_event_handler); } return ndpy; @@ -61,12 +53,12 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) static const struct native_platform x11_platform = { "X11", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_x11_platform(void) +native_get_x11_platform(const struct native_event_handler *event_handler) { + x11_event_handler = event_handler; return &x11_platform; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 8945117276e..d3c9270a667 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -31,12 +31,10 @@ struct native_display * x11_create_ximage_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); #endif /* _NATIVE_X11_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 8e32c6ff0c4..e7794f0d3d7 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -43,7 +43,7 @@ struct ximage_display { Display *dpy; boolean own_dpy; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct x11_screen *xscr; int xscr_number; @@ -437,14 +437,54 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) } static boolean -ximage_display_is_pixmap_supported(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf) +ximage_display_get_pixmap_format(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format) { struct ximage_display *xdpy = ximage_display(ndpy); - enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix); - return (fmt == nconf->color_format); + *format = get_pixmap_format(&xdpy->base, pix); + + return (*format != PIPE_FORMAT_NONE); +} + +static boolean +ximage_display_copy_to_pixmap(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src) +{ + /* fast path to avoid unnecessary allocation and resource_copy_region */ + if (src->bind & PIPE_BIND_DISPLAY_TARGET) { + struct ximage_display *xdpy = ximage_display(ndpy); + enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix); + const struct ximage_config *xconf; + struct xlib_drawable xdraw; + int i; + + if (fmt == PIPE_FORMAT_NONE || src->format != fmt) + return FALSE; + + for (i = 0; i < xdpy->num_configs; i++) { + if (xdpy->configs[i].base.color_format == fmt) { + xconf = &xdpy->configs[i]; + break; + } + } + if (!xconf) + return FALSE; + + memset(&xdraw, 0, sizeof(xdraw)); + xdraw.visual = xconf->visual->visual; + xdraw.depth = xconf->visual->depth; + xdraw.drawable = (Drawable) pix; + + xdpy->base.screen->flush_frontbuffer(xdpy->base.screen, + src, 0, 0, &xdraw); + + return TRUE; + } + + return native_display_copy_to_pixmap(ndpy, pix, src); } static int @@ -484,13 +524,32 @@ ximage_display_destroy(struct native_display *ndpy) FREE(xdpy); } +static boolean +ximage_display_init_screen(struct native_display *ndpy) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + struct sw_winsys *winsys; + + winsys = xlib_create_sw_winsys(xdpy->dpy); + if (!winsys) + return FALSE; + + xdpy->base.screen = + xdpy->event_handler->new_sw_screen(&xdpy->base, winsys); + if (!xdpy->base.screen) { + if (winsys->destroy) + winsys->destroy(winsys); + return FALSE; + } + + return TRUE; +} + struct native_display * x11_create_ximage_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct ximage_display *xdpy; - struct sw_winsys *winsys = NULL; xdpy = CALLOC_STRUCT(ximage_display); if (!xdpy) @@ -507,39 +566,25 @@ x11_create_ximage_display(Display *dpy, } xdpy->event_handler = event_handler; - xdpy->base.user_data = user_data; xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); - if (!xdpy->xscr) - goto fail; - - winsys = xlib_create_sw_winsys(xdpy->dpy); - if (!winsys) - goto fail; - - xdpy->base.screen = - xdpy->event_handler->new_sw_screen(&xdpy->base, winsys); - if (!xdpy->base.screen) - goto fail; + if (!xdpy->xscr) { + if (xdpy->own_dpy) + XCloseDisplay(xdpy->dpy); + FREE(xdpy); + return NULL; + } + xdpy->base.init_screen = ximage_display_init_screen; xdpy->base.destroy = ximage_display_destroy; xdpy->base.get_param = ximage_display_get_param; xdpy->base.get_configs = ximage_display_get_configs; - xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; + xdpy->base.get_pixmap_format = ximage_display_get_pixmap_format; + xdpy->base.copy_to_pixmap = ximage_display_copy_to_pixmap; xdpy->base.create_window_surface = ximage_display_create_window_surface; xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; return &xdpy->base; - -fail: - if (winsys && winsys->destroy) - winsys->destroy(winsys); - if (xdpy->xscr) - x11_screen_destroy(xdpy->xscr); - if (xdpy->dpy && xdpy->own_dpy) - XCloseDisplay(xdpy->dpy); - FREE(xdpy); - return NULL; } diff --git a/src/gallium/state_trackers/gbm/Makefile b/src/gallium/state_trackers/gbm/Makefile new file mode 100644 index 00000000000..1d96eb2032d --- /dev/null +++ b/src/gallium/state_trackers/gbm/Makefile @@ -0,0 +1,46 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +gbm_INCLUDES = \ + -I. \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gbm/main \ + -I$(TOP)/include + +gbm_SOURCES = $(wildcard *.c) +gbm_OBJECTS = $(gbm_SOURCES:.c=.o) + +ALL_INCLUDES = $(gbm_INCLUDES) +ALL_SOURCES = $(gbm_SOURCES) + +GBM_OBJECTS = $(gbm_OBJECTS) +GBM_CPPFLAGS = $(gbm_INCLUDES) + +##### TARGETS ##### + +default: depend libgbm.a + +libgbm.a: $(GBM_OBJECTS) Makefile + $(MKLIB) -o gbm -static $(GBM_OBJECTS) + +depend: + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(ALL_INCLUDES) $(ALL_SOURCES) 2> /dev/null + +clean: + rm -f libgbm.a + rm -f $(GBM_OBJECTS) + rm -f depend depend.bak + +# Dummy target +install: + @echo -n "" + +##### RULES ##### + +$(gbm_OBJECTS): %.o: %.c + $(CC) -c $(GBM_CPPFLAGS) $(DEFINES) $(CFLAGS) $< -o $@ + +sinclude depend diff --git a/src/gallium/state_trackers/gbm/gbm_drm.c b/src/gallium/state_trackers/gbm/gbm_drm.c new file mode 100644 index 00000000000..d4baf87096a --- /dev/null +++ b/src/gallium/state_trackers/gbm/gbm_drm.c @@ -0,0 +1,226 @@ +/* + * Copyright © 2011 Intel Corporation + * + * 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 (including the next + * paragraph) 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. + * + * Authors: + * Benjamin Franzke <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "state_tracker/drm_driver.h" + +#include <unistd.h> +#include <sys/types.h> + +#include "gbm_gallium_drmint.h" + +static INLINE enum pipe_format +gbm_format_to_gallium(enum gbm_bo_format format) +{ + switch (format) { + case GBM_BO_FORMAT_XRGB8888: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case GBM_BO_FORMAT_ARGB8888: + return PIPE_FORMAT_B8G8R8A8_UNORM; + default: + return PIPE_FORMAT_NONE; + } + + return PIPE_FORMAT_NONE; +} + +static INLINE uint +gbm_usage_to_gallium(uint usage) +{ + uint resource_usage = 0; + + if (usage & GBM_BO_USE_SCANOUT) + resource_usage |= PIPE_BIND_SCANOUT; + + if (usage & GBM_BO_USE_RENDERING) + resource_usage |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + + if (usage & GBM_BO_USE_CURSOR_64X64) + resource_usage |= PIPE_BIND_CURSOR; + + return resource_usage; +} + +static int +gbm_gallium_drm_is_format_supported(struct gbm_device *gbm, + enum gbm_bo_format format, + uint32_t usage) +{ + struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); + enum pipe_format pf; + + pf = gbm_format_to_gallium(format); + if (pf == PIPE_FORMAT_NONE) + return 0; + + if (!gdrm->screen->is_format_supported(gdrm->screen, PIPE_TEXTURE_2D, pf, 0, + gbm_usage_to_gallium(usage))) + return 0; + + if (usage & GBM_BO_USE_SCANOUT && format != GBM_BO_FORMAT_XRGB8888) + return 0; + + return 1; +} + +static void +gbm_gallium_drm_bo_destroy(struct gbm_bo *_bo) +{ + struct gbm_gallium_drm_bo *bo = gbm_gallium_drm_bo(_bo); + + pipe_resource_reference(&bo->resource, NULL); + free(bo); +} + +static struct gbm_bo * +gbm_gallium_drm_bo_create_from_egl_image(struct gbm_device *gbm, + void *egl_dpy, void *egl_image, + uint32_t width, uint32_t height, + uint32_t usage) +{ + struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); + struct gbm_gallium_drm_bo *bo; + struct winsys_handle whandle; + + if (!gdrm->lookup_egl_image) + return NULL; + + bo = CALLOC_STRUCT(gbm_gallium_drm_bo); + if (bo == NULL) + return NULL; + + bo->resource = gdrm->lookup_egl_image(gdrm->lookup_egl_image_data, + egl_image); + if (bo->resource == NULL) { + FREE(bo); + return NULL; + } + + bo->base.base.gbm = gbm; + bo->base.base.width = width; + bo->base.base.height = height; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle); + + bo->base.base.handle.u32 = whandle.handle; + bo->base.base.pitch = whandle.stride; + + return &bo->base.base; +} + +static struct gbm_bo * +gbm_gallium_drm_bo_create(struct gbm_device *gbm, + uint32_t width, uint32_t height, + enum gbm_bo_format format, uint32_t usage) +{ + struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); + struct gbm_gallium_drm_bo *bo; + struct pipe_resource templ; + struct winsys_handle whandle; + enum pipe_format pf; + + bo = CALLOC_STRUCT(gbm_gallium_drm_bo); + if (bo == NULL) + return NULL; + + bo->base.base.gbm = gbm; + bo->base.base.width = width; + bo->base.base.height = height; + + pf = gbm_format_to_gallium(format); + if (pf == PIPE_FORMAT_NONE) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = gbm_usage_to_gallium(usage); + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + bo->resource = gdrm->screen->resource_create(gdrm->screen, &templ); + if (bo->resource == NULL) { + FREE(bo); + return NULL; + } + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + gdrm->screen->resource_get_handle(gdrm->screen, bo->resource, &whandle); + + bo->base.base.handle.u32 = whandle.handle; + bo->base.base.pitch = whandle.stride; + + return &bo->base.base; +} + +static void +gbm_gallium_drm_destroy(struct gbm_device *gbm) +{ + struct gbm_gallium_drm_device *gdrm = gbm_gallium_drm_device(gbm); + + gdrm->screen->destroy(gdrm->screen); + + FREE(gdrm->base.driver_name); + + FREE(gdrm); +} + +struct gbm_device * +gbm_gallium_drm_device_create(int fd) +{ + struct gbm_gallium_drm_device *gdrm; + int ret; + + gdrm = calloc(1, sizeof *gdrm); + + gdrm->base.base.fd = fd; + gdrm->base.base.bo_create = gbm_gallium_drm_bo_create; + gdrm->base.base.bo_create_from_egl_image = + gbm_gallium_drm_bo_create_from_egl_image; + gdrm->base.base.bo_destroy = gbm_gallium_drm_bo_destroy; + gdrm->base.base.is_format_supported = gbm_gallium_drm_is_format_supported; + gdrm->base.base.destroy = gbm_gallium_drm_destroy; + + gdrm->base.type = GBM_DRM_DRIVER_TYPE_GALLIUM; + gdrm->base.base.name = "drm"; + + ret = gallium_screen_create(gdrm); + if (ret) { + free(gdrm); + return NULL; + } + + return &gdrm->base.base; +} diff --git a/src/gallium/state_trackers/gbm/gbm_gallium_drmint.h b/src/gallium/state_trackers/gbm/gbm_gallium_drmint.h new file mode 100644 index 00000000000..6277b8dba2e --- /dev/null +++ b/src/gallium/state_trackers/gbm/gbm_gallium_drmint.h @@ -0,0 +1,74 @@ +/* + * Copyright © 2011 Intel Corporation + * + * 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 (including the next + * paragraph) 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. + * + * Authors: + * Benjamin Franzke <[email protected]> + */ + +#ifndef _GBM_GALLIUM_DRMINT_H_ +#define _GBM_GALLIUM_DRMINT_H_ + +#include "pipe/p_state.h" + +#include "gbmint.h" + +#include "common.h" +#include "common_drm.h" + +struct gbm_gallium_drm_device { + struct gbm_drm_device base; + + struct pipe_screen *screen; + void *driver; + + struct pipe_resource *(*lookup_egl_image)(void *data, + void *egl_image); + void *lookup_egl_image_data; + +}; + +struct gbm_gallium_drm_bo { + struct gbm_drm_bo base; + + struct pipe_resource *resource; +}; + +static inline struct gbm_gallium_drm_device * +gbm_gallium_drm_device(struct gbm_device *gbm) +{ + return (struct gbm_gallium_drm_device *) gbm; +} + +static inline struct gbm_gallium_drm_bo * +gbm_gallium_drm_bo(struct gbm_bo *bo) +{ + return (struct gbm_gallium_drm_bo *) bo; +} + +struct gbm_device * +gbm_gallium_drm_device_create(int fd); + +int +gallium_screen_create(struct gbm_gallium_drm_device *gdrm); + +#endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index ab4f6753e11..8f6406ddaee 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -59,6 +59,7 @@ #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" +#include "util/u_atomic.h" #include "xm_public.h" #include <GL/glx.h> @@ -1113,10 +1114,7 @@ XMesaDestroyBuffer(XMesaBuffer b) void xmesa_notify_invalid_buffer(XMesaBuffer b) { - XMesaContext xmctx = XMesaGetCurrentContext(); - - if (xmctx && xmctx->xm_buffer == b) - xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb); + p_atomic_inc(&b->stfb->stamp); } @@ -1126,11 +1124,18 @@ xmesa_notify_invalid_buffer(XMesaBuffer b) void xmesa_check_buffer_size(XMesaBuffer b) { + GLuint old_width, old_height; + if (b->type == PBUFFER) return; + old_width = b->width; + old_height = b->height; + xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); - xmesa_notify_invalid_buffer(b); + + if (b->width != old_width || b->height != old_height) + xmesa_notify_invalid_buffer(b); } diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c index 6bfe8b0788c..ec3f531f7df 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -30,6 +30,7 @@ #include "xm_st.h" #include "util/u_inlines.h" +#include "util/u_atomic.h" struct xmesa_st_framebuffer { XMesaDisplay display; @@ -302,6 +303,7 @@ xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) stfbi->visual = &xstfb->stvis; stfbi->flush_front = xmesa_st_framebuffer_flush_front; stfbi->validate = xmesa_st_framebuffer_validate; + p_atomic_set(&stfbi->stamp, 1); stfbi->st_manager_private = (void *) xstfb; return stfbi; diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index 71491a5aa22..d91ee9797f1 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -65,6 +65,8 @@ struct st_framebuffer { enum st_attachment_type strb_att; void *privateData; + int32_t stamp; + int32_t iface_stamp; }; enum vg_object_type { @@ -105,7 +107,6 @@ struct vg_context VGErrorCode _error; struct st_framebuffer *draw_buffer; - int32_t draw_buffer_invalid; struct cso_hash *owned_objects[VG_OBJECT_LAST]; @@ -129,6 +130,8 @@ struct vg_context struct vg_paint *default_paint; struct blit_state *blit; + + int32_t draw_stamp; }; diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c index eeea68677de..dec1581fb84 100644 --- a/src/gallium/state_trackers/vega/vg_manager.c +++ b/src/gallium/state_trackers/vega/vg_manager.c @@ -106,35 +106,38 @@ vg_manager_validate_framebuffer(struct vg_context *ctx) { struct st_framebuffer *stfb = ctx->draw_buffer; struct pipe_resource *pt; + int32_t new_stamp; /* no binding surface */ if (!stfb) return; - if (!p_atomic_read(&ctx->draw_buffer_invalid)) - return; + new_stamp = p_atomic_read(&stfb->iface->stamp); + if (stfb->iface_stamp != new_stamp) { + do { + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, + 1, &pt) || !pt) + return; - /* validate the fb */ - if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt) - return; + stfb->iface_stamp = new_stamp; + new_stamp = p_atomic_read(&stfb->iface->stamp); - p_atomic_set(&ctx->draw_buffer_invalid, FALSE); + } while (stfb->iface_stamp != new_stamp); - if (vg_context_update_color_rb(ctx, pt) || - stfb->width != pt->width0 || - stfb->height != pt->height0) - ctx->state.dirty |= FRAMEBUFFER_DIRTY; + if (vg_context_update_color_rb(ctx, pt) || + stfb->width != pt->width0 || + stfb->height != pt->height0) + ++stfb->stamp; - stfb->width = pt->width0; - stfb->height = pt->height0; -} + stfb->width = pt->width0; + stfb->height = pt->height0; + } -static void -vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, - struct st_framebuffer_iface *stfbi) -{ - struct vg_context *ctx = (struct vg_context *) stctxi; - p_atomic_set(&ctx->draw_buffer_invalid, TRUE); + if (ctx->draw_stamp != stfb->stamp) { + ctx->state.dirty |= FRAMEBUFFER_DIRTY; + ctx->draw_stamp = stfb->stamp; + } } static void @@ -187,8 +190,6 @@ vg_api_create_context(struct st_api *stapi, struct st_manager *smapi, ctx->iface.destroy = vg_context_destroy; - ctx->iface.notify_invalid_framebuffer = - vg_context_notify_invalid_framebuffer; ctx->iface.flush = vg_context_flush; ctx->iface.teximage = NULL; @@ -266,8 +267,6 @@ vg_context_bind_framebuffers(struct st_context_iface *stctxi, if (stdrawi != streadi) return FALSE; - p_atomic_set(&ctx->draw_buffer_invalid, TRUE); - strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID; if (ctx->draw_buffer) { @@ -313,11 +312,14 @@ vg_context_bind_framebuffers(struct st_context_iface *stctxi, stfb->width = 0; stfb->height = 0; stfb->strb_att = strb_att; + stfb->stamp = 1; + stfb->iface_stamp = p_atomic_read(&stdrawi->stamp) - 1; ctx->draw_buffer = stfb; } ctx->draw_buffer->iface = stdrawi; + ctx->draw_stamp = ctx->draw_buffer->stamp - 1; return TRUE; } diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 5608d4f4ce7..c2839fe815f 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -31,6 +31,7 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" #include "util/u_memory.h" +#include "util/u_atomic.h" #include "state_tracker/st_api.h" #include "stw_icd.h" @@ -361,10 +362,7 @@ stw_flush_current_locked( struct stw_framebuffer *fb ) void stw_notify_current_locked( struct stw_framebuffer *fb ) { - struct stw_context *ctx = stw_current_context(); - - if (ctx && ctx->current_framebuffer == fb) - ctx->st->notify_invalid_framebuffer(ctx->st, fb->stfb); + p_atomic_inc(&fb->stfb->stamp); } /** diff --git a/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c b/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c index 424d8daccb3..c7273f26545 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c +++ b/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c @@ -268,7 +268,7 @@ wglQueryPbufferARB(HPBUFFERARB hPbuffer, *piValue = fb->width; return TRUE; case WGL_PBUFFER_HEIGHT_ARB: - *piValue = fb->width; + *piValue = fb->height; return TRUE; case WGL_PBUFFER_LOST_ARB: /* We assume that no content is ever lost due to display mode change */ diff --git a/src/gallium/state_trackers/wgl/stw_st.c b/src/gallium/state_trackers/wgl/stw_st.c index 9174533fc06..28c93f4fb57 100644 --- a/src/gallium/state_trackers/wgl/stw_st.c +++ b/src/gallium/state_trackers/wgl/stw_st.c @@ -27,6 +27,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_atomic.h" #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ #include "stw_st.h" @@ -196,6 +197,7 @@ stw_st_create_framebuffer(struct stw_framebuffer *fb) stwfb->stvis = fb->pfi->stvis; stwfb->base.visual = &stwfb->stvis; + p_atomic_set(&stwfb->base.stamp, 1); stwfb->base.flush_front = stw_st_framebuffer_flush_front; stwfb->base.validate = stw_st_framebuffer_validate; diff --git a/src/gallium/state_trackers/xa/Makefile b/src/gallium/state_trackers/xa/Makefile new file mode 100644 index 00000000000..d95f9382630 --- /dev/null +++ b/src/gallium/state_trackers/xa/Makefile @@ -0,0 +1,67 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +##### MACROS ##### + +XA_MAJOR = 0 +XA_MINOR = 4 +XA_TINY = 0 +XA_CFLAGS = -g -fPIC -Wall + +XA_INCLUDES= -I$(TOP)/src/gallium/ \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/winsys \ + -I$(TOP)/src/gallium/drivers + +XA_LIB = xatracker +XA_LIB_NAME = lib$(XA_LIB).o +XA_LIB_DEPS = + +COMMON_GALLIUM_SOURCES= + +SOURCES = \ + xa_tracker.c \ + xa_context.c \ + xa_renderer.c \ + xa_tgsi.c \ + xa_yuv.c \ + xa_composite.c +OBJECTS = $(SOURCES:.c=.o) + +##### RULES ##### + +.c.o: + $(CC) -c $(XA_CFLAGS) $(XA_INCLUDES) $< + + +##### TARGETS ##### + +default: $(XA_LIB_NAME) + + +# Make the library +$(XA_LIB_NAME): depend $(OBJECTS) + $(CC) -r -nostdlib -o $(XA_LIB_NAME) $(OBJECTS) + +install: FORCE + +clean: + -rm -f *.o *~ + -rm -f *.lo + -rm -f *.la + -rm -f *.pc + -rm -rf .libs + -rm -f depend depend.bak + + +depend: $(SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend + @ touch depend + @ $(MKDEP) $(MKDEP_OPTIONS) -I$(TOP)/include $(XA_INCLUDES) $(SOURCES) \ + > /dev/null + +-include depend + +FORCE: diff --git a/src/gallium/state_trackers/xa/README b/src/gallium/state_trackers/xa/README new file mode 100644 index 00000000000..1f08861588c --- /dev/null +++ b/src/gallium/state_trackers/xa/README @@ -0,0 +1,72 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +The XA state tracker is intended as a versioned interface to gallium for +xorg driver writers. Initially it's mostly based on Zack Rusin's +composite / video work for the Xorg state tracker. + +The motivation behind this state tracker is that the Xorg state tracker has +a number of interfaces to work with: + +1) The Xorg sdk (versioned) +2) Gallium3D (not versioned) +3) KMS modesetting (versioned) +4) Driver-private (hopefully versioned) + +Since Gallium3D is not versioned, the Xorg state tracker needs to be compiled +with Gallium, but it's really beneficial to be able to compile xorg drivers +standalone. + +Therefore the xa state tracker is intended to supply the following +functionality: + +1) Versioning. +2) Surface functionality (creation and copying for a basic dri2 implementation) +3) YUV blits for textured Xv. +4) Solid fills without ROP functionality. +5) Copies with format conversion and - reinterpretation but without ROP +6) Xrender- type compositing for general acceleration. + + +The first user will be the vmwgfx xorg driver. When there are more users, +we need to be able to load the appropriate gallium pipe driver, and we +should investigate sharing the loadig mechanism with the EGL state tracker. + +IMPORTANT: +Version compatibilities: +While this library remains OUTSIDE any mesa release branch, +and the major version number is still 0. Any minor bump should be viewed as +an incompatibility event, and any user of this library should test for that +and refuse to use the library if minor versions differ. +As soon as the library enters a mesa release branch, if not earlier, major +will be bumped to 1, and normal incompatibility rules (major bump) +will be followed. +It is allowed to add function interfaces while only bumping minor. Any +user that uses these function interfaces must therefore use lazy symbol +lookups and test minor for compatibility before using such a function. diff --git a/src/gallium/state_trackers/xa/xa-indent b/src/gallium/state_trackers/xa/xa-indent new file mode 100755 index 00000000000..1972e53226f --- /dev/null +++ b/src/gallium/state_trackers/xa/xa-indent @@ -0,0 +1,3 @@ +# +indent --linux-style -i4 -ip4 -bad -bap -psl $* + diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c new file mode 100644 index 00000000000..5389af6f363 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_composite.c @@ -0,0 +1,499 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#include "xa_composite.h" +#include "xa_context.h" +#include "xa_priv.h" +#include "cso_cache/cso_context.h" +#include "util/u_sampler.h" +#include "util/u_inlines.h" + + +/*XXX also in Xrender.h but the including it here breaks compilition */ +#define XFixedToDouble(f) (((double) (f)) / 65536.) + +struct xa_composite_blend { + enum xa_composite_op op : 8; + + unsigned alpha_dst : 4; + unsigned alpha_src : 4; + + unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ +}; + +#define XA_BLEND_OP_OVER 3 +static const struct xa_composite_blend xa_blends[] = { + { xa_op_clear, + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, + { xa_op_src, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, + { xa_op_dst, + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, + { xa_op_over, + 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_over_reverse, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, + { xa_op_in, + 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { xa_op_in_reverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, + { xa_op_out, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { xa_op_out_reverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_atop, + 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_atop_reverse, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, + { xa_op_xor, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_add, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, +}; + + +static boolean +blend_for_op(struct xa_composite_blend *blend, + enum xa_composite_op op, + struct xa_picture *src_pic, + struct xa_picture *mask_pic, + struct xa_picture *dst_pic) +{ + const int num_blends = + sizeof(xa_blends)/sizeof(struct xa_composite_blend); + int i; + boolean supported = FALSE; + + /* + * our default in case something goes wrong + */ + + *blend = xa_blends[XA_BLEND_OP_OVER]; + + for (i = 0; i < num_blends; ++i) { + if (xa_blends[i].op == op) { + *blend = xa_blends[i]; + supported = TRUE; + } + } + + + /* + * If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + + if (dst_pic && + xa_format_a(dst_pic->pict_format) == 0 && + blend->alpha_dst) { + if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) + blend->rgb_src = PIPE_BLENDFACTOR_ONE; + else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) + blend->rgb_src = PIPE_BLENDFACTOR_ZERO; + } + + /* + * If the source alpha is being used, then we should only be in a case where + * the source blend factor is 0, and the source blend value is the mask + * channels multiplied by the source picture's alpha. + */ + if (mask_pic && mask_pic->component_alpha && + xa_format_rgb(mask_pic->pict_format) && + blend->alpha_src) { + if (blend->rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) { + blend->rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR; + } else if (blend->rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) { + blend->rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR; + } + } + + return supported; +} + + +static INLINE int +xa_repeat_to_gallium(int mode) +{ + switch(mode) { + case xa_wrap_clamp_to_border: + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case xa_wrap_repeat: + return PIPE_TEX_WRAP_REPEAT; + case xa_wrap_mirror_repeat: + return PIPE_TEX_WRAP_MIRROR_REPEAT; + case xa_wrap_clamp_to_edge: + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + default: + break; + } + return PIPE_TEX_WRAP_REPEAT; +} + +static INLINE boolean +xa_filter_to_gallium(int xrender_filter, int *out_filter) +{ + + switch (xrender_filter) { + case xa_filter_nearest: + *out_filter = PIPE_TEX_FILTER_NEAREST; + break; + case xa_filter_linear: + *out_filter = PIPE_TEX_FILTER_LINEAR; + break; + default: + *out_filter = PIPE_TEX_FILTER_NEAREST; + return FALSE; + } + return TRUE; +} + +static int +xa_is_filter_accelerated(struct xa_picture *pic) +{ + int filter; + if (pic && !xa_filter_to_gallium(pic->filter, &filter)) + return 0; + return 1; +} + +int +xa_composite_check_accelerated(const struct xa_composite *comp) +{ + struct xa_composite_blend blend; + struct xa_picture *src_pic = comp->src; + + if (!xa_is_filter_accelerated(src_pic) || + !xa_is_filter_accelerated(comp->mask)) { + return XA_ERR_INVAL; + } + + + if (src_pic->src_pict) { + if (src_pic->src_pict->type != xa_src_pict_solid_fill) + return XA_ERR_INVAL; + } + + if (blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) { + struct xa_picture *mask = comp->mask; + if (mask && mask->component_alpha && + xa_format_rgb(mask->pict_format)) { + if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { + return XA_ERR_INVAL; + } + } + + return XA_ERR_NONE; + } + return XA_ERR_INVAL; +} + +static void +bind_composite_blend_state(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct xa_composite_blend blend_opt; + struct pipe_blend_state blend; + + blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst); + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 1; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = blend_opt.rgb_src; + blend.rt[0].alpha_src_factor = blend_opt.rgb_src; + blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; + blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; + + cso_set_blend(ctx->cso, &blend); +} + +static unsigned int +picture_format_fixups(struct xa_picture *src_pic, + struct xa_picture *dst_pic, + int mask) +{ + boolean set_alpha = FALSE; + boolean swizzle = FALSE; + unsigned ret = 0; + struct xa_surface *src = src_pic->srf; + enum xa_formats src_hw_format, src_pic_format; + enum xa_surface_type src_hw_type, src_pic_type; + + if (!src) + return 0; + + src_hw_format = xa_surface_format(src); + src_pic_format = src_pic->pict_format; + + if (!src || src_hw_format == src_pic_format) { + if (src_pic_format == xa_format_a8) { + if (mask) + return FS_MASK_LUMINANCE; + else if (dst_pic->pict_format != xa_format_a8) { + + /* + * if both dst and src are luminance then + * we don't want to swizzle the alpha (X) of the + * source into W component of the dst because + * it will break our destination + */ + return FS_SRC_LUMINANCE; + } + } + return 0; + } + + src_hw_type = xa_format_type(src_hw_format); + src_pic_type = xa_format_type(src_pic_format); + + swizzle = ((src_hw_type == xa_type_argb && + src_pic_type == xa_type_abgr) || + ((src_hw_type == xa_type_abgr && + src_pic_type == xa_type_argb))); + + if (!swizzle && (src_hw_type != src_pic_type)) + return 0; + + set_alpha = (xa_format_type_is_color(src_pic_format) && + xa_format_a(src_pic_type) == 0); + + if (set_alpha) + ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; + if (swizzle) + ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; + + return ret; +} + +static void +bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) +{ + unsigned vs_traits = 0, fs_traits = 0; + struct xa_shader shader; + struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + struct xa_picture *dst_pic = comp->dst; + + ctx->has_solid_color = FALSE; + + if (src_pic) { + if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) + fs_traits |= FS_SRC_REPEAT_NONE; + + if (src_pic->src_pict) { + if (src_pic->src_pict->type == xa_src_pict_solid_fill) { + fs_traits |= FS_SOLID_FILL; + vs_traits |= VS_SOLID_FILL; + xa_pixel_to_float4(src_pic->src_pict->solid_fill.color, + ctx->solid_color); + ctx->has_solid_color = TRUE; + } + } else { + fs_traits |= FS_COMPOSITE; + vs_traits |= VS_COMPOSITE; + } + + fs_traits |= picture_format_fixups(src_pic, dst_pic, 0); + } + + if (mask_pic) { + vs_traits |= VS_MASK; + fs_traits |= FS_MASK; + if (mask_pic->wrap == xa_wrap_clamp_to_border && + mask_pic->has_transform) + fs_traits |= FS_MASK_REPEAT_NONE; + + if (mask_pic->component_alpha) { + struct xa_composite_blend blend; + blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL); + if (blend.alpha_src) { + fs_traits |= FS_CA_SRCALPHA; + } else + fs_traits |= FS_CA_FULL; + } + + fs_traits |= picture_format_fixups(mask_pic, dst_pic, 1); + } + + shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(ctx->cso, shader.vs); + cso_set_fragment_shader_handle(ctx->cso, shader.fs); +} + +static void +bind_samplers(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = ctx->pipe; + struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + + ctx->num_bound_samplers = 0; + + memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); + memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); + + if (src_pic) { + if (ctx->has_solid_color) { + samplers[0] = NULL; + pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); + } else { + unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); + int filter; + + (void) xa_filter_to_gallium(src_pic->filter, &filter); + + src_sampler.wrap_s = src_wrap; + src_sampler.wrap_t = src_wrap; + src_sampler.min_img_filter = filter; + src_sampler.mag_img_filter = filter; + src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + src_sampler.normalized_coords = 1; + samplers[0] = &src_sampler; + ctx->num_bound_samplers = 1; + u_sampler_view_default_template(&view_templ, + src_pic->srf->tex, + src_pic->srf->tex->format); + src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, + &view_templ); + pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); + ctx->bound_sampler_views[0] = src_view; + } + } + + if (mask_pic) { + unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); + int filter; + + (void) xa_filter_to_gallium(mask_pic->filter, &filter); + + mask_sampler.wrap_s = mask_wrap; + mask_sampler.wrap_t = mask_wrap; + mask_sampler.min_img_filter = filter; + mask_sampler.mag_img_filter = filter; + src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + mask_sampler.normalized_coords = 1; + samplers[1] = &mask_sampler; + ctx->num_bound_samplers = 2; + u_sampler_view_default_template(&view_templ, + mask_pic->srf->tex, + mask_pic->srf->tex->format); + src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, + &view_templ); + pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL); + ctx->bound_sampler_views[1] = src_view; + } + + cso_set_samplers(ctx->cso, ctx->num_bound_samplers, + (const struct pipe_sampler_state **)samplers); + cso_set_fragment_sampler_views(ctx->cso, ctx->num_bound_samplers, + ctx->bound_sampler_views); +} + +int +xa_composite_prepare(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct xa_surface *dst_srf = comp->dst->srf; + int ret; + + ret = xa_surface_psurf_create(ctx, dst_srf); + if (ret != XA_ERR_NONE) + return ret; + + renderer_bind_destination(ctx, dst_srf->srf, + dst_srf->srf->width, + dst_srf->srf->height); + + bind_composite_blend_state(ctx, comp); + bind_shaders(ctx, comp); + bind_samplers(ctx, comp); + + if (ctx->num_bound_samplers == 0 ) { /* solid fill */ + renderer_begin_solid(ctx); + } else { + renderer_begin_textures(ctx); + ctx->comp = comp; + } + + xa_surface_psurf_destroy(dst_srf); + return XA_ERR_NONE; +} + +void xa_composite_rect(struct xa_context *ctx, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height) +{ + if (ctx->num_bound_samplers == 0 ) { /* solid fill */ + renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height, + ctx->solid_color); + } else { + const struct xa_composite *comp = ctx->comp; + int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; + const float *src_matrix = NULL; + const float *mask_matrix = NULL; + + if (comp->src->has_transform) + src_matrix = comp->src->transform; + if (comp->mask && comp->mask->has_transform) + mask_matrix = comp->mask->transform; + + renderer_texture(ctx, pos, width, height, + src_matrix, mask_matrix); + } +} + +void +xa_composite_done(struct xa_context *ctx) +{ + renderer_draw_flush(ctx); + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); + + ctx->comp = NULL; + ctx->has_solid_color = FALSE; + ctx->num_bound_samplers = 0; +} + +static const struct xa_composite_allocation a = { + .xa_composite_size = sizeof(struct xa_composite), + .xa_picture_size = sizeof(struct xa_picture), + .xa_source_pict_size = sizeof(union xa_source_pict), +}; + +const struct xa_composite_allocation * +xa_composite_allocation(void) +{ + return &a; +} diff --git a/src/gallium/state_trackers/xa/xa_composite.h b/src/gallium/state_trackers/xa/xa_composite.h new file mode 100644 index 00000000000..d16ef89ebd8 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_composite.h @@ -0,0 +1,140 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_COMPOSITE_H_ +#define _XA_COMPOSITE_H_ + +#include "xa_tracker.h" +#include "xa_context.h" + +/* + * Supported composite ops. + */ +enum xa_composite_op { + xa_op_clear, + xa_op_src, + xa_op_dst, + xa_op_over, + xa_op_over_reverse, + xa_op_in, + xa_op_in_reverse, + xa_op_out, + xa_op_out_reverse, + xa_op_atop, + xa_op_atop_reverse, + xa_op_xor, + xa_op_add +}; + +/* + * Supported filters. + */ +enum xa_composite_filter { + xa_filter_nearest, + xa_filter_linear +}; + +/* + * Supported clamp methods. + */ +enum xa_composite_wrap { + xa_wrap_clamp_to_border, + xa_wrap_repeat, + xa_wrap_mirror_repeat, + xa_wrap_clamp_to_edge +}; + +/* + * Src picture types. + */ +enum xa_composite_src_pict_type { + xa_src_pict_solid_fill +}; + +struct xa_pict_solid_fill { + enum xa_composite_src_pict_type type; + unsigned int class; + uint32_t color; +}; + +union xa_source_pict { + unsigned int type; + struct xa_pict_solid_fill solid_fill; +}; + +struct xa_picture { + enum xa_formats pict_format; + struct xa_surface *srf; + struct xa_surface *alpha_map; + float transform[9]; + int has_transform; + int component_alpha; + enum xa_composite_wrap wrap; + enum xa_composite_filter filter; + union xa_source_pict *src_pict; +}; + +struct xa_composite { + struct xa_picture *src, *mask, *dst; + int op; + int no_solid; +}; + +struct xa_composite_allocation { + unsigned int xa_composite_size; + unsigned int xa_picture_size; + unsigned int xa_source_pict_size; +}; + +/* + * Get allocation sizes for minor bump compatibility. + */ + +extern const struct xa_composite_allocation * +xa_composite_allocation(void); + +/* + * This function checks most things except the format of the hardware + * surfaces, since they are generally not available at the time this + * function is called. Returns usual XA error codes. + */ +extern int +xa_composite_check_accelerated(const struct xa_composite *comp); + +extern int +xa_composite_prepare(struct xa_context *ctx, const struct xa_composite *comp); + +extern void +xa_composite_rect(struct xa_context *ctx, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height); +extern void +xa_composite_done(struct xa_context *ctx); + +#endif diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c new file mode 100644 index 00000000000..3cc25ed2071 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_context.c @@ -0,0 +1,386 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ +#include "xa_context.h" +#include "xa_priv.h" +#include "cso_cache/cso_context.h" +#include "util/u_inlines.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "pipe/p_context.h" + + +struct xa_context * +xa_context_default(struct xa_tracker *xa) +{ + return xa->default_ctx; +} + +struct xa_context * +xa_context_create(struct xa_tracker *xa) +{ + struct xa_context *ctx = calloc(1, sizeof(*ctx)); + + ctx->xa = xa; + ctx->pipe = xa->screen->context_create(xa->screen, NULL); + ctx->cso = cso_create_context(ctx->pipe); + ctx->shaders = xa_shaders_create(ctx); + renderer_init_state(ctx); + + return ctx; +} + +void +xa_context_destroy(struct xa_context *r) +{ + struct pipe_resource **vsbuf = &r->vs_const_buffer; + struct pipe_resource **fsbuf = &r->fs_const_buffer; + + if (*vsbuf) + pipe_resource_reference(vsbuf, NULL); + + if (*fsbuf) + pipe_resource_reference(fsbuf, NULL); + + if (r->shaders) { + xa_shaders_destroy(r->shaders); + r->shaders = NULL; + } + + if (r->cso) { + cso_release_all(r->cso); + cso_destroy_context(r->cso); + r->cso = NULL; + } +} + +int +xa_surface_dma(struct xa_context *ctx, + struct xa_surface *srf, + void *data, + unsigned int pitch, + int to_surface, struct xa_box *boxes, unsigned int num_boxes) +{ + struct pipe_transfer *transfer; + void *map; + int w, h, i; + enum pipe_transfer_usage transfer_direction; + struct pipe_context *pipe = ctx->pipe; + + transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : + PIPE_TRANSFER_READ); + + for (i = 0; i < num_boxes; ++i, ++boxes) { + w = boxes->x2 - boxes->x1; + h = boxes->y2 - boxes->y1; + + transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, + transfer_direction, boxes->x1, boxes->y1, + w, h); + if (!transfer) + return -XA_ERR_NORES; + + map = pipe_transfer_map(ctx->pipe, transfer); + if (!map) + goto out_no_map; + + if (to_surface) { + util_copy_rect(map, srf->tex->format, transfer->stride, + 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); + } else { + util_copy_rect(data, srf->tex->format, pitch, + boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, + 0); + } + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); + if (to_surface) + pipe->flush(pipe, &ctx->last_fence); + } + return XA_ERR_NONE; + out_no_map: + pipe->transfer_destroy(pipe, transfer); + return -XA_ERR_NORES; +} + +void * +xa_surface_map(struct xa_context *ctx, + struct xa_surface *srf, unsigned int usage) +{ + void *map; + unsigned int transfer_direction = 0; + struct pipe_context *pipe = ctx->pipe; + + if (srf->transfer) + return NULL; + + if (usage & XA_MAP_READ) + transfer_direction = PIPE_TRANSFER_READ; + if (usage & XA_MAP_WRITE) + transfer_direction = PIPE_TRANSFER_WRITE; + + if (!transfer_direction) + return NULL; + + srf->transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, + transfer_direction, 0, 0, + srf->tex->width0, srf->tex->height0); + if (!srf->transfer) + return NULL; + + map = pipe_transfer_map(pipe, srf->transfer); + if (!map) + pipe->transfer_destroy(pipe, srf->transfer); + + srf->mapping_pipe = pipe; + return map; +} + +void +xa_surface_unmap(struct xa_surface *srf) +{ + if (srf->transfer) { + struct pipe_context *pipe = srf->mapping_pipe; + + pipe->transfer_unmap(pipe, srf->transfer); + pipe->transfer_destroy(pipe, srf->transfer); + srf->transfer = NULL; + } +} + +int +xa_surface_psurf_create(struct xa_context *ctx, struct xa_surface *dst) +{ + struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_surface srf_templ; + + if (dst->srf) + return -XA_ERR_INVAL; + + if (!screen->is_format_supported(screen, dst->tex->format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)) + return -XA_ERR_INVAL; + + u_surface_default_template(&srf_templ, dst->tex, + PIPE_BIND_RENDER_TARGET); + dst->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ); + if (!dst->srf) + return -XA_ERR_NORES; + + return XA_ERR_NONE; +} + +void +xa_surface_psurf_destroy(struct xa_surface *dst) +{ + pipe_surface_reference(&dst->srf, NULL); +} + +int +xa_copy_prepare(struct xa_context *ctx, + struct xa_surface *dst, struct xa_surface *src) +{ + if (src == dst || dst->srf != NULL) + return -XA_ERR_INVAL; + + if (src->tex->format != dst->tex->format) { + int ret = xa_surface_psurf_create(ctx, dst); + if (ret != XA_ERR_NONE) + return ret; + renderer_copy_prepare(ctx, dst->srf, src->tex); + ctx->simple_copy = 0; + } else + ctx->simple_copy = 1; + + ctx->src = src; + ctx->dst = dst; + + return 0; +} + +void +xa_copy(struct xa_context *ctx, + int dx, int dy, int sx, int sy, int width, int height) +{ + struct pipe_box src_box; + + if (ctx->simple_copy) { + u_box_2d(sx, sy, width, height, &src_box); + ctx->pipe->resource_copy_region(ctx->pipe, + ctx->dst->tex, 0, dx, dy, 0, + ctx->src->tex, + 0, &src_box); + } else + renderer_copy(ctx, dx, dy, sx, sy, width, height, + (float) width, (float) height); +} + +void +xa_copy_done(struct xa_context *ctx) +{ + if (!ctx->simple_copy) { + renderer_draw_flush(ctx); + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); + xa_surface_psurf_destroy(ctx->dst); + } else + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); +} + +static void +bind_solid_blend_state(struct xa_context *ctx) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + cso_set_blend(ctx->cso, &blend); +} + +int +xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, + uint32_t fg) +{ + unsigned vs_traits, fs_traits; + struct xa_shader shader; + int width, height; + int ret; + + xa_pixel_to_float4(fg, ctx->solid_color); + ctx->has_solid_color = 1; + + ret = xa_surface_psurf_create(ctx, dst); + if (ret != XA_ERR_NONE) + return ret; + + ctx->dst = dst; + width = dst->srf->width; + height = dst->srf->height; + +#if 0 + debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", + (fg >> 24) & 0xff, (fg >> 16) & 0xff, + (fg >> 8) & 0xff, (fg >> 0) & 0xff, + exa->solid_color[0], exa->solid_color[1], + exa->solid_color[2], exa->solid_color[3]); +#endif + + vs_traits = VS_SOLID_FILL; + fs_traits = FS_SOLID_FILL; + + renderer_bind_destination(ctx, dst->srf, width, height); + bind_solid_blend_state(ctx); + cso_set_samplers(ctx->cso, 0, NULL); + cso_set_fragment_sampler_views(ctx->cso, 0, NULL); + + shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(ctx->cso, shader.vs); + cso_set_fragment_shader_handle(ctx->cso, shader.fs); + + renderer_begin_solid(ctx); + + xa_surface_psurf_destroy(dst); + return XA_ERR_NONE; +} + +void +xa_solid(struct xa_context *ctx, int x, int y, int width, int height) +{ + renderer_solid(ctx, x, y, x + width, y + height, ctx->solid_color); +} + +void +xa_solid_done(struct xa_context *ctx) +{ + renderer_draw_flush(ctx); + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); + + ctx->comp = NULL; + ctx->has_solid_color = FALSE; + ctx->num_bound_samplers = 0; +} + +struct xa_fence * +xa_fence_get(struct xa_context *ctx) +{ + struct xa_fence *fence = malloc(sizeof(*fence)); + struct pipe_screen *screen = ctx->xa->screen; + + if (!fence) + return NULL; + + fence->xa = ctx->xa; + + if (ctx->last_fence == NULL) + fence->pipe_fence = NULL; + else + screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence); + + return fence; +} + +int +xa_fence_wait(struct xa_fence *fence, uint64_t timeout) +{ + if (!fence) + return XA_ERR_NONE; + + if (fence->pipe_fence) { + struct pipe_screen *screen = fence->xa->screen; + boolean timed_out; + + timed_out = !screen->fence_finish(screen, fence->pipe_fence, timeout); + if (timed_out) + return -XA_ERR_BUSY; + + screen->fence_reference(screen, &fence->pipe_fence, NULL); + } + return XA_ERR_NONE; +} + +void +xa_fence_destroy(struct xa_fence *fence) +{ + if (!fence) + return; + + if (fence->pipe_fence) { + struct pipe_screen *screen = fence->xa->screen; + + screen->fence_reference(screen, &fence->pipe_fence, NULL); + } + + free(fence); +} diff --git a/src/gallium/state_trackers/xa/xa_context.h b/src/gallium/state_trackers/xa/xa_context.h new file mode 100644 index 00000000000..ea2b923a5a1 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_context.h @@ -0,0 +1,86 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_CONTEXT_H_ +#define _XA_CONTEXT_H_ +#include "xa_tracker.h" +#include <stdint.h> + +struct xa_context; + +extern struct xa_context *xa_context_default(struct xa_tracker *xa); + +extern struct xa_context *xa_context_create(struct xa_tracker *xa); + +extern void xa_context_destroy(struct xa_context *r); + +extern int xa_yuv_planar_blit(struct xa_context *r, + int src_x, + int src_y, + int src_w, + int src_h, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + struct xa_box *box, + unsigned int num_boxes, + const float conversion_matrix[], + struct xa_surface *dst, struct xa_surface *yuv[]); + +extern int xa_copy_prepare(struct xa_context *ctx, + struct xa_surface *dst, struct xa_surface *src); + +extern void xa_copy(struct xa_context *ctx, + int dx, int dy, int sx, int sy, int width, int height); + +extern void xa_copy_done(struct xa_context *ctx); + +extern int xa_surface_dma(struct xa_context *ctx, + struct xa_surface *srf, + void *data, + unsigned int byte_pitch, + int to_surface, struct xa_box *boxes, + unsigned int num_boxes); + +extern int +xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, + uint32_t fg); +extern void +xa_solid(struct xa_context *ctx, int x, int y, int width, int height); + +extern void +xa_solid_done(struct xa_context *ctx); + +extern struct xa_fence *xa_fence_get(struct xa_context *ctx); + +extern int xa_fence_wait(struct xa_fence *fence, uint64_t timeout); + +extern void xa_fence_destroy(struct xa_fence *fence); +#endif diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h new file mode 100644 index 00000000000..94627e1e9d0 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_priv.h @@ -0,0 +1,241 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_PRIV_H_ +#define _XA_PRIV_H_ + +#include "xa_tracker.h" +#include "xa_context.h" +#include "xa_composite.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +#define XA_VB_SIZE (100 * 4 * 3 * 4) +#define XA_LAST_SURFACE_TYPE (xa_type_yuv_component + 1) +#define XA_MAX_SAMPLERS 3 + +struct xa_fence { + struct pipe_fence_handle *pipe_fence; + struct xa_tracker *xa; +}; + +struct xa_format_descriptor { + enum pipe_format format; + enum xa_formats xa_format; +}; + +struct xa_surface { + struct pipe_resource template; + struct xa_tracker *xa; + struct pipe_resource *tex; + struct pipe_surface *srf; + struct pipe_sampler_view *view; + unsigned int flags; + struct xa_format_descriptor fdesc; + struct pipe_transfer *transfer; + struct pipe_context *mapping_pipe; +}; + +struct xa_tracker { + enum xa_formats *supported_formats; + unsigned int format_map[XA_LAST_SURFACE_TYPE][2]; + int d_depth_bits_last; + int ds_depth_bits_last; + struct pipe_screen *screen; + struct xa_context *default_ctx; +}; + +struct xa_context { + struct xa_tracker *xa; + struct pipe_context *pipe; + + struct cso_context *cso; + struct xa_shaders *shaders; + + struct pipe_resource *vs_const_buffer; + struct pipe_resource *fs_const_buffer; + + float buffer[XA_VB_SIZE]; + unsigned int buffer_size; + struct pipe_vertex_element velems[3]; + + /* number of attributes per vertex for the current + * draw operation */ + unsigned int attrs_per_vertex; + + unsigned int fb_width; + unsigned int fb_height; + + struct pipe_fence_handle *last_fence; + struct xa_surface *src; + struct xa_surface *dst; + int simple_copy; + + int has_solid_color; + float solid_color[4]; + + unsigned int num_bound_samplers; + struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS]; + const struct xa_composite *comp; +}; + +enum xa_vs_traits { + VS_COMPOSITE = 1 << 0, + VS_MASK = 1 << 1, + VS_SOLID_FILL = 1 << 2, + VS_LINGRAD_FILL = 1 << 3, + VS_RADGRAD_FILL = 1 << 4, + VS_YUV = 1 << 5, + + VS_FILL = (VS_SOLID_FILL | VS_LINGRAD_FILL | VS_RADGRAD_FILL) +}; + +enum xa_fs_traits { + FS_COMPOSITE = 1 << 0, + FS_MASK = 1 << 1, + FS_SOLID_FILL = 1 << 2, + FS_LINGRAD_FILL = 1 << 3, + FS_RADGRAD_FILL = 1 << 4, + FS_CA_FULL = 1 << 5, /* src.rgba * mask.rgba */ + FS_CA_SRCALPHA = 1 << 6, /* src.aaaa * mask.rgba */ + FS_YUV = 1 << 7, + FS_SRC_REPEAT_NONE = 1 << 8, + FS_MASK_REPEAT_NONE = 1 << 9, + FS_SRC_SWIZZLE_RGB = 1 << 10, + FS_MASK_SWIZZLE_RGB = 1 << 11, + FS_SRC_SET_ALPHA = 1 << 12, + FS_MASK_SET_ALPHA = 1 << 13, + FS_SRC_LUMINANCE = 1 << 14, + FS_MASK_LUMINANCE = 1 << 15, + + FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL), + FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA) +}; + +struct xa_shader { + void *fs; + void *vs; +}; + +struct xa_shaders; + +/* + * Inline utilities + */ + +static INLINE int +xa_min(int a, int b) +{ + return ((a <= b) ? a : b); +} + +static INLINE void +xa_pixel_to_float4(uint32_t pixel, float *color) +{ + uint32_t r, g, b, a; + + a = (pixel >> 24) & 0xff; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel >> 0) & 0xff; + color[0] = ((float)r) / 255.; + color[1] = ((float)g) / 255.; + color[2] = ((float)b) / 255.; + color[3] = ((float)a) / 255.; +} + + +/* + * xa_tgsi.c + */ + +extern struct xa_shaders *xa_shaders_create(struct xa_context *); + +void xa_shaders_destroy(struct xa_shaders *shaders); + +struct xa_shader xa_shaders_get(struct xa_shaders *shaders, + unsigned vs_traits, unsigned fs_traits); + +/* + * xa_context.c + */ +extern int +xa_surface_psurf_create(struct xa_context *ctx, struct xa_surface *dst); + +extern void +xa_surface_psurf_destroy(struct xa_surface *dst); + +/* + * xa_renderer.c + */ +void renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, + int param_bytes); + +void renderer_draw_yuv(struct xa_context *r, + float src_x, + float src_y, + float src_w, + float src_h, + int dst_x, + int dst_y, int dst_w, int dst_h, + struct xa_surface *srf[]); + +void renderer_bind_destination(struct xa_context *r, + struct pipe_surface *surface, int width, + int height); + +void renderer_init_state(struct xa_context *r); +void renderer_copy_prepare(struct xa_context *r, + struct pipe_surface *dst_surface, + struct pipe_resource *src_texture); +void renderer_copy(struct xa_context *r, int dx, + int dy, + int sx, + int sy, + int width, int height, float src_width, float src_height); + +void renderer_draw_flush(struct xa_context *r); + +void renderer_begin_solid(struct xa_context *r); +void renderer_solid(struct xa_context *r, + int x0, int y0, int x1, int y1, float *color); +void +renderer_begin_textures(struct xa_context *r); + +void +renderer_texture(struct xa_context *r, + int *pos, + int width, int height, + const float *src_matrix, + const float *mask_matrix); + +#endif diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c new file mode 100644 index 00000000000..559b2699da6 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_renderer.c @@ -0,0 +1,626 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + */ + +#include "xa_context.h" +#include "xa_priv.h" +#include <math.h> +#include "cso_cache/cso_context.h" +#include "util/u_inlines.h" +#include "util/u_sampler.h" +#include "util/u_draw_quad.h" + +#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y))) +#define floatIsZero(x) (floatsEqual((x) + 1, 1)) + +#define NUM_COMPONENTS 4 + +void + + +renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, int param_bytes); + +static INLINE boolean +is_affine(float *matrix) +{ + return floatIsZero(matrix[2]) && floatIsZero(matrix[5]) + && floatsEqual(matrix[8], 1); +} + +static INLINE void +map_point(float *mat, float x, float y, float *out_x, float *out_y) +{ + if (!mat) { + *out_x = x; + *out_y = y; + return; + } + + *out_x = mat[0] * x + mat[3] * y + mat[6]; + *out_y = mat[1] * x + mat[4] * y + mat[7]; + if (!is_affine(mat)) { + float w = 1 / (mat[2] * x + mat[5] * y + mat[8]); + + *out_x *= w; + *out_y *= w; + } +} + +static INLINE struct pipe_resource * +renderer_buffer_create(struct xa_context *r) +{ + struct pipe_resource *buf = pipe_user_buffer_create(r->pipe->screen, + r->buffer, + sizeof(float) * + r->buffer_size, + PIPE_BIND_VERTEX_BUFFER); + + r->buffer_size = 0; + + return buf; +} + +static INLINE void +renderer_draw(struct xa_context *r) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_resource *buf = 0; + int num_verts = r->buffer_size / (r->attrs_per_vertex * NUM_COMPONENTS); + + if (!r->buffer_size) + return; + + buf = renderer_buffer_create(r); + + if (buf) { + cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems); + + util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ + r->attrs_per_vertex); /* attribs/vert */ + + pipe_resource_reference(&buf, NULL); + } +} + +static INLINE void +renderer_draw_conditional(struct xa_context *r, int next_batch) +{ + if (r->buffer_size + next_batch >= XA_VB_SIZE || + (next_batch == 0 && r->buffer_size)) { + renderer_draw(r); + } +} + +void +renderer_init_state(struct xa_context *r) +{ + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_rasterizer_state raster; + unsigned i; + + /* set common initial clip state */ + memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + cso_set_depth_stencil_alpha(r->cso, &dsa); + + /* XXX: move to renderer_init_state? */ + memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); + raster.gl_rasterization_rules = 1; + cso_set_rasterizer(r->cso, &raster); + + /* vertex elements state */ + memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); + for (i = 0; i < 3; i++) { + r->velems[i].src_offset = i * 4 * sizeof(float); + r->velems[i].instance_divisor = 0; + r->velems[i].vertex_buffer_index = 0; + r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } +} + +static INLINE void +add_vertex_color(struct xa_context *r, float x, float y, float color[4]) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = color[0]; /*r */ + vertex[5] = color[1]; /*g */ + vertex[6] = color[2]; /*b */ + vertex[7] = color[3]; /*a */ + + r->buffer_size += 8; +} + +static INLINE void +add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = s; /*s */ + vertex[5] = t; /*t */ + vertex[6] = 0.f; /*r */ + vertex[7] = 1.f; /*q */ + + r->buffer_size += 8; +} + +static INLINE void +add_vertex_2tex(struct xa_context *r, + float x, float y, float s0, float t0, float s1, float t1) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = s0; /*s */ + vertex[5] = t0; /*t */ + vertex[6] = 0.f; /*r */ + vertex[7] = 1.f; /*q */ + + vertex[8] = s1; /*s */ + vertex[9] = t1; /*t */ + vertex[10] = 0.f; /*r */ + vertex[11] = 1.f; /*q */ + + r->buffer_size += 12; +} + +static void +add_vertex_data1(struct xa_context *r, + float srcX, float srcY, float dstX, float dstY, + float width, float height, + struct pipe_resource *src, const float *src_matrix) +{ + float s0, t0, s1, t1, s2, t2, s3, t3; + float pt0[2], pt1[2], pt2[2], pt3[2]; + + pt0[0] = srcX; + pt0[1] = srcY; + pt1[0] = (srcX + width); + pt1[1] = srcY; + pt2[0] = (srcX + width); + pt2[1] = (srcY + height); + pt3[0] = srcX; + pt3[1] = (srcY + height); + + if (src_matrix) { + map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]); + map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]); + map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]); + map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]); + } + + s0 = pt0[0] / src->width0; + s1 = pt1[0] / src->width0; + s2 = pt2[0] / src->width0; + s3 = pt3[0] / src->width0; + t0 = pt0[1] / src->height0; + t1 = pt1[1] / src->height0; + t2 = pt2[1] / src->height0; + t3 = pt3[1] / src->height0; + + /* 1st vertex */ + add_vertex_1tex(r, dstX, dstY, s0, t0); + /* 2nd vertex */ + add_vertex_1tex(r, dstX + width, dstY, s1, t1); + /* 3rd vertex */ + add_vertex_1tex(r, dstX + width, dstY + height, s2, t2); + /* 4th vertex */ + add_vertex_1tex(r, dstX, dstY + height, s3, t3); +} + +static void +add_vertex_data2(struct xa_context *r, + float srcX, float srcY, float maskX, float maskY, + float dstX, float dstY, float width, float height, + struct pipe_resource *src, + struct pipe_resource *mask, + const float *src_matrix, const float *mask_matrix) +{ + float src_s0, src_t0, src_s1, src_t1; + float mask_s0, mask_t0, mask_s1, mask_t1; + float spt0[2], spt1[2]; + float mpt0[2], mpt1[2]; + + spt0[0] = srcX; + spt0[1] = srcY; + spt1[0] = srcX + width; + spt1[1] = srcY + height; + + mpt0[0] = maskX; + mpt0[1] = maskY; + mpt1[0] = maskX + width; + mpt1[1] = maskY + height; + + if (src_matrix) { + map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]); + map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]); + } + + if (mask_matrix) { + map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]); + map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]); + } + + src_s0 = spt0[0] / src->width0; + src_t0 = spt0[1] / src->height0; + src_s1 = spt1[0] / src->width0; + src_t1 = spt1[1] / src->height0; + + mask_s0 = mpt0[0] / mask->width0; + mask_t0 = mpt0[1] / mask->height0; + mask_s1 = mpt1[0] / mask->width0; + mask_t1 = mpt1[1] / mask->height0; + + /* 1st vertex */ + add_vertex_2tex(r, dstX, dstY, + src_s0, src_t0, mask_s0, mask_t0); + /* 2nd vertex */ + add_vertex_2tex(r, dstX + width, dstY, + src_s1, src_t0, mask_s1, mask_t0); + /* 3rd vertex */ + add_vertex_2tex(r, dstX + width, dstY + height, + src_s1, src_t1, mask_s1, mask_t1); + /* 4th vertex */ + add_vertex_2tex(r, dstX, dstY + height, + src_s0, src_t1, mask_s0, mask_t1); +} + +static struct pipe_resource * +setup_vertex_data_yuv(struct xa_context *r, + float srcX, + float srcY, + float srcW, + float srcH, + float dstX, + float dstY, + float dstW, float dstH, struct xa_surface *srf[]) +{ + float s0, t0, s1, t1; + float spt0[2], spt1[2]; + struct pipe_resource *tex; + + spt0[0] = srcX; + spt0[1] = srcY; + spt1[0] = srcX + srcW; + spt1[1] = srcY + srcH; + + tex = srf[0]->tex; + s0 = spt0[0] / tex->width0; + t0 = spt0[1] / tex->height0; + s1 = spt1[0] / tex->width0; + t1 = spt1[1] / tex->height0; + + /* 1st vertex */ + add_vertex_1tex(r, dstX, dstY, s0, t0); + /* 2nd vertex */ + add_vertex_1tex(r, dstX + dstW, dstY, s1, t0); + /* 3rd vertex */ + add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1); + /* 4th vertex */ + add_vertex_1tex(r, dstX, dstY + dstH, s0, t1); + + return renderer_buffer_create(r); +} + +/* Set up framebuffer, viewport and vertex shader constant buffer + * state for a particular destinaton surface. In all our rendering, + * these concepts are linked. + */ +void +renderer_bind_destination(struct xa_context *r, + struct pipe_surface *surface, int width, int height) +{ + + struct pipe_framebuffer_state fb; + struct pipe_viewport_state viewport; + + /* Framebuffer uses actual surface width/height + */ + memset(&fb, 0, sizeof fb); + fb.width = surface->width; + fb.height = surface->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = surface; + fb.zsbuf = 0; + + /* Viewport just touches the bit we're interested in: + */ + viewport.scale[0] = width / 2.f; + viewport.scale[1] = height / 2.f; + viewport.scale[2] = 1.0; + viewport.scale[3] = 1.0; + viewport.translate[0] = width / 2.f; + viewport.translate[1] = height / 2.f; + viewport.translate[2] = 0.0; + viewport.translate[3] = 0.0; + + /* Constant buffer set up to match viewport dimensions: + */ + if (r->fb_width != width || r->fb_height != height) { + float vs_consts[8] = { + 2.f / width, 2.f / height, 1, 1, + -1, -1, 0, 0 + }; + + r->fb_width = width; + r->fb_height = height; + + renderer_set_constants(r, PIPE_SHADER_VERTEX, + vs_consts, sizeof vs_consts); + } + + cso_set_framebuffer(r->cso, &fb); + cso_set_viewport(r->cso, &viewport); +} + +void +renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, int param_bytes) +{ + struct pipe_resource **cbuf = + (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : + &r->fs_const_buffer; + + pipe_resource_reference(cbuf, NULL); + *cbuf = pipe_buffer_create(r->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC, + param_bytes); + + if (*cbuf) { + pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params); + } + r->pipe->set_constant_buffer(r->pipe, shader_type, 0, *cbuf); +} + +void +renderer_copy_prepare(struct xa_context *r, + struct pipe_surface *dst_surface, + struct pipe_resource *src_texture) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_screen *screen = pipe->screen; + struct xa_shader shader; + + assert(screen->is_format_supported(screen, dst_surface->format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)); + (void)screen; + + /* set misc state we care about */ + { + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(blend)); + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; + cso_set_blend(r->cso, &blend); + } + + /* sampler */ + { + struct pipe_sampler_state sampler; + + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.normalized_coords = 1; + cso_single_sampler(r->cso, 0, &sampler); + cso_single_sampler_done(r->cso); + } + + renderer_bind_destination(r, dst_surface, + dst_surface->width, dst_surface->height); + + /* texture/sampler view */ + { + struct pipe_sampler_view templ; + struct pipe_sampler_view *src_view; + + u_sampler_view_default_template(&templ, + src_texture, src_texture->format); + src_view = pipe->create_sampler_view(pipe, src_texture, &templ); + cso_set_fragment_sampler_views(r->cso, 1, &src_view); + pipe_sampler_view_reference(&src_view, NULL); + } + + /* shaders */ + shader = xa_shaders_get(r->shaders, VS_COMPOSITE, FS_COMPOSITE); + cso_set_vertex_shader_handle(r->cso, shader.vs); + cso_set_fragment_shader_handle(r->cso, shader.fs); + + r->buffer_size = 0; + r->attrs_per_vertex = 2; +} + +void +renderer_copy(struct xa_context *r, + int dx, + int dy, + int sx, + int sy, + int width, int height, float src_width, float src_height) +{ + float s0, t0, s1, t1; + float x0, y0, x1, y1; + + /* XXX: could put the texcoord scaling calculation into the vertex + * shader. + */ + s0 = sx / src_width; + s1 = (sx + width) / src_width; + t0 = sy / src_height; + t1 = (sy + height) / src_height; + + x0 = dx; + x1 = dx + width; + y0 = dy; + y1 = dy + height; + + /* draw quad */ + renderer_draw_conditional(r, 4 * 8); + add_vertex_1tex(r, x0, y0, s0, t0); + add_vertex_1tex(r, x1, y0, s1, t0); + add_vertex_1tex(r, x1, y1, s1, t1); + add_vertex_1tex(r, x0, y1, s0, t1); +} + +void +renderer_draw_yuv(struct xa_context *r, + float src_x, + float src_y, + float src_w, + float src_h, + int dst_x, + int dst_y, int dst_w, int dst_h, struct xa_surface *srf[]) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_resource *buf = 0; + + buf = setup_vertex_data_yuv(r, + src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, + dst_h, srf); + + if (buf) { + const int num_attribs = 2; /*pos + tex coord */ + + cso_set_vertex_elements(r->cso, num_attribs, r->velems); + + util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ + num_attribs); /* attribs/vert */ + + pipe_resource_reference(&buf, NULL); + } +} + +void +renderer_begin_solid(struct xa_context *r) +{ + r->buffer_size = 0; + r->attrs_per_vertex = 2; +} + +void +renderer_solid(struct xa_context *r, + int x0, int y0, int x1, int y1, float *color) +{ + /* + * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n", + * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */ + + renderer_draw_conditional(r, 4 * 8); + + /* 1st vertex */ + add_vertex_color(r, x0, y0, color); + /* 2nd vertex */ + add_vertex_color(r, x1, y0, color); + /* 3rd vertex */ + add_vertex_color(r, x1, y1, color); + /* 4th vertex */ + add_vertex_color(r, x0, y1, color); +} + +void +renderer_draw_flush(struct xa_context *r) +{ + renderer_draw_conditional(r, 0); +} + +void +renderer_begin_textures(struct xa_context *r) +{ + r->attrs_per_vertex = 1 + r->num_bound_samplers; + r->buffer_size = 0; +} + +void +renderer_texture(struct xa_context *r, + int *pos, + int width, int height, + const float *src_matrix, + const float *mask_matrix) +{ + struct pipe_sampler_view **sampler_view = r->bound_sampler_views; + +#if 0 + if (src_matrix) { + debug_printf("src_matrix = \n"); + debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]); + debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]); + debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]); + } + if (mask_matrix) { + debug_printf("mask_matrix = \n"); + debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]); + debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]); + debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]); + } +#endif + + switch(r->attrs_per_vertex) { + case 2: + renderer_draw_conditional(r, 4 * 8); + add_vertex_data1(r, + pos[0], pos[1], /* src */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, src_matrix); + break; + case 3: + renderer_draw_conditional(r, 4 * 12); + add_vertex_data2(r, + pos[0], pos[1], /* src */ + pos[2], pos[3], /* mask */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, sampler_view[1]->texture, + src_matrix, mask_matrix); + break; + default: + break; + } +} diff --git a/src/gallium/state_trackers/xa/xa_symbols b/src/gallium/state_trackers/xa/xa_symbols new file mode 100644 index 00000000000..6da701f9702 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_symbols @@ -0,0 +1,30 @@ +xa_tracker_version +xa_tracker_create +xa_tracker_destroy +xa_surface_create +xa_surface_destroy +xa_surface_redefine +xa_surface_dma +xa_surface_map +xa_surface_unmap +xa_surface_format +xa_surface_handle +xa_format_check_supported +xa_context_default +xa_context_create +xa_context_destroy +xa_fence_get +xa_fence_wait +xa_fence_destroy +xa_copy_prepare +xa_copy +xa_copy_done +xa_solid_prepare +xa_solid +xa_solid_done +xa_composite_allocation +xa_composite_check_accelerated +xa_composite_prepare +xa_composite_rect +xa_composite_done +xa_yuv_planar_blit diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c new file mode 100644 index 00000000000..fb6ffefd636 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_tgsi.c @@ -0,0 +1,651 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + */ +#include "xa_priv.h" + +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" + +#include "util/u_memory.h" + +#include "tgsi/tgsi_ureg.h" + +#include "cso_cache/cso_context.h" +#include "cso_cache/cso_hash.h" + +/* Vertex shader: + * IN[0] = vertex pos + * IN[1] = src tex coord | solid fill color + * IN[2] = mask tex coord + * IN[3] = dst tex coord + * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) + * CONST[1] = (-1, -1, 0, 0) + * + * OUT[0] = vertex pos + * OUT[1] = src tex coord | solid fill color + * OUT[2] = mask tex coord + * OUT[3] = dst tex coord + */ + +/* Fragment shader: + * SAMP[0] = src + * SAMP[1] = mask + * SAMP[2] = dst + * IN[0] = pos src | solid fill color + * IN[1] = pos mask + * IN[2] = pos dst + * CONST[0] = (0, 0, 0, 1) + * + * OUT[0] = color + */ + +static void +print_fs_traits(int fs_traits) +{ + const char *strings[] = { + "FS_COMPOSITE", /* = 1 << 0, */ + "FS_MASK", /* = 1 << 1, */ + "FS_SOLID_FILL", /* = 1 << 2, */ + "FS_LINGRAD_FILL", /* = 1 << 3, */ + "FS_RADGRAD_FILL", /* = 1 << 4, */ + "FS_CA_FULL", /* = 1 << 5, *//* src.rgba * mask.rgba */ + "FS_CA_SRCALPHA", /* = 1 << 6, *//* src.aaaa * mask.rgba */ + "FS_YUV", /* = 1 << 7, */ + "FS_SRC_REPEAT_NONE", /* = 1 << 8, */ + "FS_MASK_REPEAT_NONE", /* = 1 << 9, */ + "FS_SRC_SWIZZLE_RGB", /* = 1 << 10, */ + "FS_MASK_SWIZZLE_RGB", /* = 1 << 11, */ + "FS_SRC_SET_ALPHA", /* = 1 << 12, */ + "FS_MASK_SET_ALPHA", /* = 1 << 13, */ + "FS_SRC_LUMINANCE", /* = 1 << 14, */ + "FS_MASK_LUMINANCE", /* = 1 << 15, */ + }; + int i, k; + + debug_printf("%s: ", __func__); + + for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) { + if (fs_traits & k) + debug_printf("%s, ", strings[i]); + } + + debug_printf("\n"); +} + +struct xa_shaders { + struct xa_context *r; + + struct cso_hash *vs_hash; + struct cso_hash *fs_hash; +}; + +static INLINE void +src_in_mask(struct ureg_program *ureg, + struct ureg_dst dst, + struct ureg_src src, + struct ureg_src mask, + unsigned component_alpha, unsigned mask_luminance) +{ + if (component_alpha == FS_CA_FULL) { + ureg_MUL(ureg, dst, src, mask); + } else if (component_alpha == FS_CA_SRCALPHA) { + ureg_MUL(ureg, dst, ureg_scalar(src, TGSI_SWIZZLE_W), mask); + } else { + if (mask_luminance) + ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X)); + else + ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W)); + } +} + +static struct ureg_src +vs_normalize_coords(struct ureg_program *ureg, + struct ureg_src coords, + struct ureg_src const0, struct ureg_src const1) +{ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_src ret; + + ureg_MAD(ureg, tmp, coords, const0, const1); + ret = ureg_src(tmp); + ureg_release_temporary(ureg, tmp); + return ret; +} + +static void +linear_gradient(struct ureg_program *ureg, + struct ureg_dst out, + struct ureg_src pos, + struct ureg_src sampler, + struct ureg_src coords, + struct ureg_src const0124, + struct ureg_src matrow0, + struct ureg_src matrow1, struct ureg_src matrow2) +{ + struct ureg_dst temp0 = ureg_DECL_temporary(ureg); + struct ureg_dst temp1 = ureg_DECL_temporary(ureg); + struct ureg_dst temp2 = ureg_DECL_temporary(ureg); + struct ureg_dst temp3 = ureg_DECL_temporary(ureg); + struct ureg_dst temp4 = ureg_DECL_temporary(ureg); + struct ureg_dst temp5 = ureg_DECL_temporary(ureg); + + ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); + ureg_MOV(ureg, + ureg_writemask(temp0, TGSI_WRITEMASK_Z), + ureg_scalar(const0124, TGSI_SWIZZLE_Y)); + + ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); + ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); + ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); + ureg_RCP(ureg, temp3, ureg_src(temp3)); + ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); + ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); + + ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X), ureg_src(temp1)); + ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y), ureg_src(temp2)); + + ureg_MUL(ureg, temp0, + ureg_scalar(coords, TGSI_SWIZZLE_Y), + ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y)); + ureg_MAD(ureg, temp1, + ureg_scalar(coords, TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X), ureg_src(temp0)); + + ureg_MUL(ureg, temp2, ureg_src(temp1), ureg_scalar(coords, TGSI_SWIZZLE_Z)); + + ureg_TEX(ureg, out, TGSI_TEXTURE_1D, ureg_src(temp2), sampler); + + ureg_release_temporary(ureg, temp0); + ureg_release_temporary(ureg, temp1); + ureg_release_temporary(ureg, temp2); + ureg_release_temporary(ureg, temp3); + ureg_release_temporary(ureg, temp4); + ureg_release_temporary(ureg, temp5); +} + +static void +radial_gradient(struct ureg_program *ureg, + struct ureg_dst out, + struct ureg_src pos, + struct ureg_src sampler, + struct ureg_src coords, + struct ureg_src const0124, + struct ureg_src matrow0, + struct ureg_src matrow1, struct ureg_src matrow2) +{ + struct ureg_dst temp0 = ureg_DECL_temporary(ureg); + struct ureg_dst temp1 = ureg_DECL_temporary(ureg); + struct ureg_dst temp2 = ureg_DECL_temporary(ureg); + struct ureg_dst temp3 = ureg_DECL_temporary(ureg); + struct ureg_dst temp4 = ureg_DECL_temporary(ureg); + struct ureg_dst temp5 = ureg_DECL_temporary(ureg); + + ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); + ureg_MOV(ureg, + ureg_writemask(temp0, TGSI_WRITEMASK_Z), + ureg_scalar(const0124, TGSI_SWIZZLE_Y)); + + ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); + ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); + ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); + ureg_RCP(ureg, temp3, ureg_src(temp3)); + ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); + ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); + + ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X), ureg_src(temp1)); + ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y), ureg_src(temp2)); + + ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y), + ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); + ureg_MAD(ureg, temp1, + ureg_scalar(coords, TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), ureg_src(temp0)); + ureg_ADD(ureg, temp1, ureg_src(temp1), ureg_src(temp1)); + ureg_MUL(ureg, temp3, + ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y), + ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); + ureg_MAD(ureg, temp4, + ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), ureg_src(temp3)); + ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4))); + ureg_MUL(ureg, temp2, ureg_scalar(coords, TGSI_SWIZZLE_Z), ureg_src(temp4)); + ureg_MUL(ureg, temp0, + ureg_scalar(const0124, TGSI_SWIZZLE_W), ureg_src(temp2)); + ureg_MUL(ureg, temp3, ureg_src(temp1), ureg_src(temp1)); + ureg_SUB(ureg, temp2, ureg_src(temp3), ureg_src(temp0)); + ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); + ureg_RCP(ureg, temp2, ureg_src(temp2)); + ureg_SUB(ureg, temp1, ureg_src(temp2), ureg_src(temp1)); + ureg_ADD(ureg, temp0, + ureg_scalar(coords, TGSI_SWIZZLE_Z), + ureg_scalar(coords, TGSI_SWIZZLE_Z)); + ureg_RCP(ureg, temp0, ureg_src(temp0)); + ureg_MUL(ureg, temp2, ureg_src(temp1), ureg_src(temp0)); + ureg_TEX(ureg, out, TGSI_TEXTURE_1D, ureg_src(temp2), sampler); + + ureg_release_temporary(ureg, temp0); + ureg_release_temporary(ureg, temp1); + ureg_release_temporary(ureg, temp2); + ureg_release_temporary(ureg, temp3); + ureg_release_temporary(ureg, temp4); + ureg_release_temporary(ureg, temp5); +} + +static void * +create_vs(struct pipe_context *pipe, unsigned vs_traits) +{ + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst; + struct ureg_src const0, const1; + boolean is_fill = (vs_traits & VS_FILL) != 0; + boolean is_composite = (vs_traits & VS_COMPOSITE) != 0; + boolean has_mask = (vs_traits & VS_MASK) != 0; + boolean is_yuv = (vs_traits & VS_YUV) != 0; + unsigned input_slot = 0; + + ureg = ureg_create(TGSI_PROCESSOR_VERTEX); + if (ureg == NULL) + return 0; + + const0 = ureg_DECL_constant(ureg, 0); + const1 = ureg_DECL_constant(ureg, 1); + + /* it has to be either a fill or a composite op */ + debug_assert((is_fill ^ is_composite) ^ is_yuv); + + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + src = vs_normalize_coords(ureg, src, const0, const1); + ureg_MOV(ureg, dst, src); + + if (is_yuv) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } + + if (is_composite) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } + + if (is_fill) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + ureg_MOV(ureg, dst, src); + } + + if (has_mask) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); + ureg_MOV(ureg, dst, src); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +static void * +create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg) +{ + struct ureg_src y_sampler, u_sampler, v_sampler; + struct ureg_src pos; + struct ureg_src matrow0, matrow1, matrow2; + struct ureg_dst y, u, v, rgb; + struct ureg_dst out = ureg_DECL_output(ureg, + TGSI_SEMANTIC_COLOR, + 0); + + pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE); + + rgb = ureg_DECL_temporary(ureg); + y = ureg_DECL_temporary(ureg); + u = ureg_DECL_temporary(ureg); + v = ureg_DECL_temporary(ureg); + + y_sampler = ureg_DECL_sampler(ureg, 0); + u_sampler = ureg_DECL_sampler(ureg, 1); + v_sampler = ureg_DECL_sampler(ureg, 2); + + matrow0 = ureg_DECL_constant(ureg, 0); + matrow1 = ureg_DECL_constant(ureg, 1); + matrow2 = ureg_DECL_constant(ureg, 2); + + ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler); + ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler); + ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler); + + ureg_SUB(ureg, u, ureg_src(u), ureg_scalar(matrow0, TGSI_SWIZZLE_W)); + ureg_SUB(ureg, v, ureg_src(v), ureg_scalar(matrow0, TGSI_SWIZZLE_W)); + + ureg_MUL(ureg, rgb, ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb)); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb)); + + /* rgb.a = 1; */ + ureg_MOV(ureg, ureg_writemask(rgb, TGSI_WRITEMASK_W), + ureg_scalar(matrow0, TGSI_SWIZZLE_X)); + + ureg_MOV(ureg, out, ureg_src(rgb)); + + ureg_release_temporary(ureg, rgb); + ureg_release_temporary(ureg, y); + ureg_release_temporary(ureg, u); + ureg_release_temporary(ureg, v); + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +static INLINE void +xrender_tex(struct ureg_program *ureg, + struct ureg_dst dst, + struct ureg_src coords, + struct ureg_src sampler, + struct ureg_src imm0, + boolean repeat_none, boolean swizzle, boolean set_alpha) +{ + if (repeat_none) { + struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); + struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); + + ureg_SGT(ureg, tmp1, ureg_swizzle(coords, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y), ureg_scalar(imm0, + TGSI_SWIZZLE_X)); + ureg_SLT(ureg, tmp0, + ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(imm0, + TGSI_SWIZZLE_W)); + ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); + ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); + ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); + if (swizzle) + ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(tmp1, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); + ureg_release_temporary(ureg, tmp0); + ureg_release_temporary(ureg, tmp1); + } else { + if (swizzle) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + + ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); + ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + ureg_release_temporary(ureg, tmp); + } else { + ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); + } + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + } +} + +static void * +create_fs(struct pipe_context *pipe, unsigned fs_traits) +{ + struct ureg_program *ureg; + struct ureg_src /*dst_sampler, */ src_sampler, mask_sampler; + struct ureg_src /*dst_pos, */ src_input, mask_pos; + struct ureg_dst src, mask; + struct ureg_dst out; + struct ureg_src imm0 = { 0 }; + unsigned has_mask = (fs_traits & FS_MASK) != 0; + unsigned is_fill = (fs_traits & FS_FILL) != 0; + unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0; + unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0; + unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0; + unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0; + unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA; + unsigned is_yuv = (fs_traits & FS_YUV) != 0; + unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; + unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; + unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; + unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; + unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; + unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; + unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0; + unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0; + +#if 0 + print_fs_traits(fs_traits); +#else + (void)print_fs_traits; +#endif + + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (ureg == NULL) + return 0; + + /* it has to be either a fill, a composite op or a yuv conversion */ + debug_assert((is_fill ^ is_composite) ^ is_yuv); + (void)is_yuv; + + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + + if (src_repeat_none || mask_repeat_none || + src_set_alpha || mask_set_alpha || src_luminance) { + imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); + } + if (is_composite) { + src_sampler = ureg_DECL_sampler(ureg, 0); + src_input = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE); + } else if (is_fill) { + if (is_solid) + src_input = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_COLOR, 0, + TGSI_INTERPOLATE_PERSPECTIVE); + else + src_input = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_POSITION, 0, + TGSI_INTERPOLATE_PERSPECTIVE); + } else { + debug_assert(is_yuv); + return create_yuv_shader(pipe, ureg); + } + + if (has_mask) { + mask_sampler = ureg_DECL_sampler(ureg, 1); + mask_pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, 1, + TGSI_INTERPOLATE_PERSPECTIVE); + } +#if 0 /* unused right now */ + dst_sampler = ureg_DECL_sampler(ureg, 2); + dst_pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_POSITION, 2, + TGSI_INTERPOLATE_PERSPECTIVE); +#endif + + if (is_composite) { + if (has_mask || src_luminance) + src = ureg_DECL_temporary(ureg); + else + src = out; + xrender_tex(ureg, src, src_input, src_sampler, imm0, + src_repeat_none, src_swizzle, src_set_alpha); + } else if (is_fill) { + if (is_solid) { + if (has_mask || src_luminance) + src = ureg_dst(src_input); + else + ureg_MOV(ureg, out, src_input); + } else if (is_lingrad || is_radgrad) { + struct ureg_src coords, const0124, matrow0, matrow1, matrow2; + + if (has_mask || src_luminance) + src = ureg_DECL_temporary(ureg); + else + src = out; + + coords = ureg_DECL_constant(ureg, 0); + const0124 = ureg_DECL_constant(ureg, 1); + matrow0 = ureg_DECL_constant(ureg, 2); + matrow1 = ureg_DECL_constant(ureg, 3); + matrow2 = ureg_DECL_constant(ureg, 4); + + if (is_lingrad) { + linear_gradient(ureg, src, + src_input, src_sampler, + coords, const0124, matrow0, matrow1, matrow2); + } else if (is_radgrad) { + radial_gradient(ureg, src, + src_input, src_sampler, + coords, const0124, matrow0, matrow1, matrow2); + } + } else + debug_assert(!"Unknown fill type!"); + } + if (src_luminance) { + ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); + ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), + ureg_scalar(imm0, TGSI_SWIZZLE_X)); + if (!has_mask) + ureg_MOV(ureg, out, ureg_src(src)); + } + + if (has_mask) { + mask = ureg_DECL_temporary(ureg); + xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0, + mask_repeat_none, mask_swizzle, mask_set_alpha); + /* src IN mask */ + src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), + comp_alpha_mask, mask_luminance); + ureg_release_temporary(ureg, mask); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +struct xa_shaders * +xa_shaders_create(struct xa_context *r) +{ + struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders); + + sc->r = r; + sc->vs_hash = cso_hash_create(); + sc->fs_hash = cso_hash_create(); + + return sc; +} + +static void +cache_destroy(struct cso_context *cso, + struct cso_hash *hash, unsigned processor) +{ + struct cso_hash_iter iter = cso_hash_first_node(hash); + + while (!cso_hash_iter_is_null(iter)) { + void *shader = (void *)cso_hash_iter_data(iter); + + if (processor == PIPE_SHADER_FRAGMENT) { + cso_delete_fragment_shader(cso, shader); + } else if (processor == PIPE_SHADER_VERTEX) { + cso_delete_vertex_shader(cso, shader); + } + iter = cso_hash_erase(hash, iter); + } + cso_hash_delete(hash); +} + +void +xa_shaders_destroy(struct xa_shaders *sc) +{ + cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX); + cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT); + + FREE(sc); +} + +static INLINE void * +shader_from_cache(struct pipe_context *pipe, + unsigned type, struct cso_hash *hash, unsigned key) +{ + void *shader = 0; + + struct cso_hash_iter iter = cso_hash_find(hash, key); + + if (cso_hash_iter_is_null(iter)) { + if (type == PIPE_SHADER_VERTEX) + shader = create_vs(pipe, key); + else + shader = create_fs(pipe, key); + cso_hash_insert(hash, key, shader); + } else + shader = (void *)cso_hash_iter_data(iter); + + return shader; +} + +struct xa_shader +xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits) +{ + struct xa_shader shader = { NULL, NULL }; + void *vs, *fs; + + vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, + sc->vs_hash, vs_traits); + fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, + sc->fs_hash, fs_traits); + + debug_assert(vs && fs); + if (!vs || !fs) + return shader; + + shader.vs = vs; + shader.fs = fs; + + return shader; +} diff --git a/src/gallium/state_trackers/xa/xa_tracker.c b/src/gallium/state_trackers/xa/xa_tracker.c new file mode 100644 index 00000000000..50922d38378 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_tracker.c @@ -0,0 +1,448 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#include "xa_tracker.h" +#include "xa_priv.h" +#include "pipe/p_state.h" +#include "pipe/p_format.h" +#include "state_tracker/drm_driver.h" +#include "util/u_inlines.h" + +/* + * format_map [xa_surface_type][first..last in list]. + * Needs to be updated when enum xa_formats is updated. + */ + +static const enum xa_formats preferred_a[] = { xa_format_a8 }; + +static const enum xa_formats preferred_argb[] = + { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5, + xa_format_x1r5g5b5 +}; +static const enum xa_formats preferred_z[] = + { xa_format_z32, xa_format_z24, xa_format_z16 }; +static const enum xa_formats preferred_sz[] = + { xa_format_x8z24, xa_format_s8z24 }; +static const enum xa_formats preferred_zs[] = + { xa_format_z24x8, xa_format_z24s8 }; +static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 }; + +static const enum xa_formats *preferred[] = + { NULL, preferred_a, preferred_argb, NULL, NULL, + preferred_z, preferred_zs, preferred_sz, preferred_yuv +}; + +static const unsigned int num_preferred[] = { 0, + sizeof(preferred_a) / sizeof(enum xa_formats), + sizeof(preferred_argb) / sizeof(enum xa_formats), + 0, + 0, + sizeof(preferred_z) / sizeof(enum xa_formats), + sizeof(preferred_zs) / sizeof(enum xa_formats), + sizeof(preferred_sz) / sizeof(enum xa_formats), + sizeof(preferred_yuv) / sizeof(enum xa_formats) +}; + +static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_SAMPLER_VIEW +}; + +static struct xa_format_descriptor +xa_get_pipe_format(enum xa_formats xa_format) +{ + struct xa_format_descriptor fdesc; + + fdesc.xa_format = xa_format; + + switch (xa_format) { + case xa_format_a8r8g8b8: + fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case xa_format_x8r8g8b8: + fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case xa_format_r5g6b5: + fdesc.format = PIPE_FORMAT_B5G6R5_UNORM; + break; + case xa_format_x1r5g5b5: + fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM; + break; + case xa_format_a8: + fdesc.format = PIPE_FORMAT_L8_UNORM; + break; + case xa_format_z24: + fdesc.format = PIPE_FORMAT_Z24X8_UNORM; + break; + case xa_format_z16: + fdesc.format = PIPE_FORMAT_Z16_UNORM; + break; + case xa_format_z32: + fdesc.format = PIPE_FORMAT_Z32_UNORM; + break; + case xa_format_x8z24: + fdesc.format = PIPE_FORMAT_Z24X8_UNORM; + break; + case xa_format_z24x8: + fdesc.format = PIPE_FORMAT_X8Z24_UNORM; + break; + case xa_format_s8z24: + fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_USCALED; + break; + case xa_format_z24s8: + fdesc.format = PIPE_FORMAT_S8_USCALED_Z24_UNORM; + break; + case xa_format_yuv8: + fdesc.format = PIPE_FORMAT_L8_UNORM; + break; + default: + fdesc.xa_format = xa_format_unknown; + break; + } + return fdesc; +} + +struct xa_tracker * +xa_tracker_create(int drm_fd) +{ + struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker)); + enum xa_surface_type stype; + unsigned int num_formats; + + if (!xa) + return NULL; + + xa->screen = driver_descriptor.create_screen(drm_fd); + if (!xa->screen) + goto out_no_screen; + + xa->default_ctx = xa_context_create(xa); + if (!xa->default_ctx) + goto out_no_pipe; + + num_formats = 0; + for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) + num_formats += num_preferred[stype]; + + num_formats += 1; + xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats)); + if (!xa->supported_formats) + goto out_sf_alloc_fail; + + xa->supported_formats[0] = xa_format_unknown; + num_formats = 1; + memset(xa->format_map, 0, sizeof(xa->format_map)); + + for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) { + unsigned int bind = stype_bind[stype]; + enum xa_formats xa_format; + int i; + + for (i = 0; i < num_preferred[stype]; ++i) { + xa_format = preferred[stype][i]; + + struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format); + + if (xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, bind)) { + if (xa->format_map[stype][0] == 0) + xa->format_map[stype][0] = num_formats; + xa->format_map[stype][1] = num_formats; + xa->supported_formats[num_formats++] = xa_format; + } + } + } + return xa; + + out_sf_alloc_fail: + xa_context_destroy(xa->default_ctx); + out_no_pipe: + xa->screen->destroy(xa->screen); + out_no_screen: + free(xa); + return NULL; +} + +void +xa_tracker_destroy(struct xa_tracker *xa) +{ + free(xa->supported_formats); + xa_context_destroy(xa->default_ctx); + xa->screen->destroy(xa->screen); + free(xa); +} + +static int +xa_flags_compat(unsigned int old_flags, unsigned int new_flags) +{ + unsigned int flag_diff = (old_flags ^ new_flags); + + if (flag_diff == 0) + return 1; + + if (flag_diff & XA_FLAG_SHARED) + return 0; + /* + * Don't recreate if we're dropping the render target flag. + */ + if (flag_diff & XA_FLAG_RENDER_TARGET) + return ((new_flags & XA_FLAG_RENDER_TARGET) == 0); + + /* + * Always recreate for unknown / unimplemented flags. + */ + return 0; +} + +static struct xa_format_descriptor +xa_get_format_stype_depth(struct xa_tracker *xa, + enum xa_surface_type stype, unsigned int depth) +{ + unsigned int i; + struct xa_format_descriptor fdesc; + int found = 0; + + for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) { + fdesc = xa_get_pipe_format(xa->supported_formats[i]); + if (fdesc.xa_format != xa_format_unknown && + xa_format_depth(fdesc.xa_format) == depth) { + found = 1; + break; + } + } + + if (!found) + fdesc.xa_format = xa_format_unknown; + + return fdesc; +} + +int +xa_format_check_supported(struct xa_tracker *xa, + enum xa_formats xa_format, unsigned int flags) +{ + struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format); + unsigned int bind; + + if (fdesc.xa_format == xa_format_unknown) + return -XA_ERR_INVAL; + + bind = stype_bind[xa_format_type(fdesc.xa_format)]; + if (flags & XA_FLAG_SHARED) + bind |= PIPE_BIND_SHARED; + if (flags & XA_FLAG_RENDER_TARGET) + bind |= PIPE_BIND_RENDER_TARGET; + + if (!xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, bind)) + return -XA_ERR_INVAL; + + return XA_ERR_NONE; +} + +struct xa_surface * +xa_surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, unsigned int flags) +{ + struct pipe_resource *template; + struct xa_surface *srf; + struct xa_format_descriptor fdesc; + + if (xa_format == xa_format_unknown) + fdesc = xa_get_format_stype_depth(xa, stype, depth); + else + fdesc = xa_get_pipe_format(xa_format); + + if (fdesc.xa_format == xa_format_unknown) + return NULL; + + srf = calloc(1, sizeof(*srf)); + if (!srf) + return NULL; + + template = &srf->template; + template->format = fdesc.format; + template->target = PIPE_TEXTURE_2D; + template->width0 = width; + template->height0 = height; + template->depth0 = 1; + template->array_size = 1; + template->last_level = 0; + template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; + + if (flags & XA_FLAG_SHARED) + template->bind |= PIPE_BIND_SHARED; + if (flags & XA_FLAG_RENDER_TARGET) + template->bind |= PIPE_BIND_RENDER_TARGET; + + srf->tex = xa->screen->resource_create(xa->screen, template); + if (!srf->tex) + goto out_no_tex; + + srf->srf = NULL; + srf->xa = xa; + srf->flags = flags; + srf->fdesc = fdesc; + + return srf; + out_no_tex: + free(srf); + return NULL; +} + +int +xa_surface_redefine(struct xa_surface *srf, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, + unsigned int new_flags, + int copy_contents) +{ + struct pipe_resource *template = &srf->template; + struct pipe_resource *texture; + struct pipe_box src_box; + struct xa_tracker *xa = srf->xa; + int save_width; + int save_height; + struct xa_format_descriptor fdesc; + + if (xa_format == xa_format_unknown) + fdesc = xa_get_format_stype_depth(xa, stype, depth); + else + fdesc = xa_get_pipe_format(xa_format); + + if (width == template->width0 && height == template->height0 && + template->format == fdesc.format && + xa_flags_compat(srf->flags, new_flags)) + return XA_ERR_NONE; + + template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; + if (new_flags & XA_FLAG_SHARED) + template->bind |= PIPE_BIND_SHARED; + if (new_flags & XA_FLAG_RENDER_TARGET) + template->bind |= PIPE_BIND_RENDER_TARGET; + + if (copy_contents) { + if (!xa_format_type_is_color(fdesc.xa_format) || + xa_format_type(fdesc.xa_format) == xa_type_a) + return -XA_ERR_INVAL; + + if (!xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, + template->bind | + PIPE_BIND_RENDER_TARGET)) + return -XA_ERR_INVAL; + } + + save_width = template->width0; + save_height = template->height0; + + template->width0 = width; + template->height0 = height; + + texture = xa->screen->resource_create(xa->screen, template); + if (!texture) { + template->width0 = save_width; + template->height0 = save_height; + return -XA_ERR_NORES; + } + + pipe_surface_reference(&srf->srf, NULL); + + if (copy_contents) { + struct pipe_context *pipe = xa->default_ctx->pipe; + + u_box_origin_2d(xa_min(save_width, template->width0), + xa_min(save_height, template->height0), &src_box); + pipe->resource_copy_region(pipe, texture, + 0, 0, 0, 0, srf->tex, 0, &src_box); + pipe->flush(pipe, &xa->default_ctx->last_fence); + } + + pipe_resource_reference(&srf->tex, texture); + pipe_resource_reference(&texture, NULL); + srf->fdesc = fdesc; + srf->flags = new_flags; + + return XA_ERR_NONE; +} + +void +xa_surface_destroy(struct xa_surface *srf) +{ + pipe_surface_reference(&srf->srf, NULL); + pipe_resource_reference(&srf->tex, NULL); + free(srf); +} + +extern void +xa_tracker_version(int *major, int *minor, int *patch) +{ + *major = XA_TRACKER_VERSION_MAJOR; + *minor = XA_TRACKER_VERSION_MINOR; + *patch = XA_TRACKER_VERSION_PATCH; +} + +extern int +xa_surface_handle(struct xa_surface *srf, + uint32_t * handle, unsigned int *stride) +{ + struct winsys_handle whandle; + + struct pipe_screen *screen = srf->xa->screen; + boolean res; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + res = screen->resource_get_handle(screen, srf->tex, &whandle); + if (!res) + return -XA_ERR_INVAL; + + *handle = whandle.handle; + *stride = whandle.stride; + + return XA_ERR_NONE; +} + +enum xa_formats +xa_surface_format(const struct xa_surface *srf) +{ + return srf->fdesc.xa_format; +} diff --git a/src/gallium/state_trackers/xa/xa_tracker.h b/src/gallium/state_trackers/xa/xa_tracker.h new file mode 100644 index 00000000000..62f8a210fb6 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_tracker.h @@ -0,0 +1,178 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + * The format encoding idea is partially borrowed from libpixman, but it is not + * considered a "substantial part of the software", so the pixman copyright + * is left out for simplicity, and acknowledgment is instead given in this way. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_TRACKER_H_ +#define _XA_TRACKER_H_ + +#include <stdint.h> + +#define XA_TRACKER_VERSION_MAJOR 0 +#define XA_TRACKER_VERSION_MINOR 4 +#define XA_TRACKER_VERSION_PATCH 0 + +#define XA_FLAG_SHARED (1 << 0) +#define XA_FLAG_RENDER_TARGET (1 << 1) + +#define XA_MAP_READ (1 << 0) +#define XA_MAP_WRITE (1 << 1) + +#define XA_ERR_NONE 0 +#define XA_ERR_NORES 1 +#define XA_ERR_INVAL 2 +#define XA_ERR_BUSY 3 + +enum xa_surface_type { + xa_type_other, + xa_type_a, + xa_type_argb, + xa_type_abgr, + xa_type_bgra, + xa_type_z, + xa_type_zs, + xa_type_sz, + xa_type_yuv_component +}; + +/* + * Note that these formats should not be assumed to be binary compatible with + * pixman formats, but with the below macros and a format type map, + * conversion should be simple. Macros for now. We might replace with + * inline functions. + */ + +#define xa_format(bpp,type,a,r,g,b) (((bpp) << 24) | \ + ((type) << 16) | \ + ((a) << 12) | \ + ((r) << 8) | \ + ((g) << 4) | \ + ((b))) +/* + * Non-RGBA one- and two component formats. + */ + +#define xa_format_c(bpp,type,c1,c2) (((bpp) << 24) | \ + ((type) << 16) | \ + ((c1) << 8) | \ + ((c2))) +#define xa_format_bpp(f) (((f) >> 24) ) +#define xa_format_type(f) (((f) >> 16) & 0xff) +#define xa_format_a(f) (((f) >> 12) & 0x0f) +#define xa_format_r(f) (((f) >> 8) & 0x0f) +#define xa_format_g(f) (((f) >> 4) & 0x0f) +#define xa_format_b(f) (((f) ) & 0x0f) +#define xa_format_rgb(f) (((f) ) & 0xfff) +#define xa_format_c1(f) (((f) >> 8 ) & 0xff) +#define xa_format_c2(f) (((f) ) & 0xff) +#define xa_format_argb_depth(f) (xa_format_a(f) + \ + xa_format_r(f) + \ + xa_format_g(f) + \ + xa_format_b(f)) +#define xa_format_c_depth(f) (xa_format_c1(f) + \ + xa_format_c2(f)) + +static inline int +xa_format_type_is_color(uint32_t xa_format) +{ + return (xa_format_type(xa_format) < xa_type_z); +} + +static inline unsigned int +xa_format_depth(uint32_t xa_format) +{ + return ((xa_format_type_is_color(xa_format)) ? + xa_format_argb_depth(xa_format) : xa_format_c_depth(xa_format)); +} + +enum xa_formats { + xa_format_unknown = 0, + xa_format_a8 = xa_format(8, xa_type_a, 8, 0, 0, 0), + + xa_format_a8r8g8b8 = xa_format(32, xa_type_argb, 8, 8, 8, 8), + xa_format_x8r8g8b8 = xa_format(32, xa_type_argb, 0, 8, 8, 8), + xa_format_r5g6b5 = xa_format(16, xa_type_argb, 0, 5, 6, 5), + xa_format_x1r5g5b5 = xa_format(16, xa_type_argb, 0, 5, 5, 5), + + xa_format_z16 = xa_format_c(16, xa_type_z, 16, 0), + xa_format_z32 = xa_format_c(32, xa_type_z, 32, 0), + xa_format_z24 = xa_format_c(32, xa_type_z, 24, 0), + + xa_format_x8z24 = xa_format_c(32, xa_type_sz, 24, 0), + xa_format_s8z24 = xa_format_c(32, xa_type_sz, 24, 8), + xa_format_z24x8 = xa_format_c(32, xa_type_zs, 24, 0), + xa_format_z24s8 = xa_format_c(32, xa_type_zs, 24, 8), + + xa_format_yuv8 = xa_format_c(8, xa_type_yuv_component, 8, 0) +}; + +struct xa_tracker; +struct xa_surface; + +struct xa_box { + uint16_t x1, y1, x2, y2; +}; + +extern void xa_tracker_version(int *major, int *minor, int *patch); + +extern struct xa_tracker *xa_tracker_create(int drm_fd); + +extern void xa_tracker_destroy(struct xa_tracker *xa); + +extern int xa_format_check_supported(struct xa_tracker *xa, + enum xa_formats xa_format, + unsigned int flags); + +extern struct xa_surface *xa_surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats pform, + unsigned int flags); + +enum xa_formats xa_surface_format(const struct xa_surface *srf); + +extern void xa_surface_destroy(struct xa_surface *srf); + +extern int xa_surface_redefine(struct xa_surface *srf, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats rgb_format, + unsigned int new_flags, + int copy_contents); + +extern int xa_surface_handle(struct xa_surface *srf, + uint32_t * handle, unsigned int *byte_stride); + +#endif diff --git a/src/gallium/state_trackers/xa/xa_yuv.c b/src/gallium/state_trackers/xa/xa_yuv.c new file mode 100644 index 00000000000..66cbc5393b5 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_yuv.c @@ -0,0 +1,179 @@ +/********************************************************** + * Copyright 2009-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"), 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. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#include "xa_context.h" +#include "xa_priv.h" +#include "util/u_inlines.h" +#include "util/u_sampler.h" +#include "util/u_surface.h" +#include "cso_cache/cso_context.h" + +static void +xa_yuv_bind_blend_state(struct xa_context *r) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + /* porter&duff src */ + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + cso_set_blend(r->cso, &blend); +} + +static void +xa_yuv_bind_shaders(struct xa_context *r) +{ + unsigned vs_traits = 0, fs_traits = 0; + struct xa_shader shader; + + vs_traits |= VS_YUV; + fs_traits |= FS_YUV; + + shader = xa_shaders_get(r->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(r->cso, shader.vs); + cso_set_fragment_shader_handle(r->cso, shader.fs); +} + +static void +xa_yuv_bind_samplers(struct xa_context *r, struct xa_surface *yuv[]) +{ + struct pipe_sampler_state *samplers[3]; + struct pipe_sampler_state sampler; + struct pipe_sampler_view *views[3]; + struct pipe_sampler_view view_templ; + unsigned int i; + + memset(&sampler, 0, sizeof(struct pipe_sampler_state)); + + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; + sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + sampler.normalized_coords = 1; + + for (i = 0; i < 3; ++i) { + samplers[i] = &sampler; + if (!yuv[i]->view) { + u_sampler_view_default_template(&view_templ, + yuv[i]->tex, yuv[i]->tex->format); + + yuv[i]->view = r->pipe->create_sampler_view(r->pipe, + yuv[i]->tex, + &view_templ); + } + views[i] = yuv[i]->view; + } + + cso_set_samplers(r->cso, 3, (const struct pipe_sampler_state **)samplers); + cso_set_fragment_sampler_views(r->cso, 3, views); +} + +static void +xa_yuv_fs_constants(struct xa_context *r, const float conversion_matrix[]) +{ + const int param_bytes = 12 * sizeof(float); + + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, + conversion_matrix, param_bytes); +} + +static void +xa_yuv_destroy_sampler_views(struct xa_surface *yuv[]) +{ + unsigned int i; + + for (i = 0; i < 3; ++i) { + pipe_sampler_view_reference(&yuv[i]->view, NULL); + } +} + +extern int +xa_yuv_planar_blit(struct xa_context *r, + int src_x, + int src_y, + int src_w, + int src_h, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + struct xa_box *box, + unsigned int num_boxes, + const float conversion_matrix[], + struct xa_surface *dst, struct xa_surface *yuv[]) +{ + float scale_x; + float scale_y; + struct pipe_surface srf_templ; + + if (dst_w == 0 || dst_h == 0) + return XA_ERR_NONE; + + memset(&srf_templ, 0, sizeof(srf_templ)); + u_surface_default_template(&srf_templ, dst->tex, PIPE_BIND_RENDER_TARGET); + dst->srf = r->pipe->create_surface(r->pipe, dst->tex, &srf_templ); + if (!dst->srf) + return -XA_ERR_NORES; + + renderer_bind_destination(r, dst->srf, dst->srf->width, dst->srf->height); + xa_yuv_bind_blend_state(r); + xa_yuv_bind_shaders(r); + xa_yuv_bind_samplers(r, yuv); + xa_yuv_fs_constants(r, conversion_matrix); + + scale_x = (float)src_w / (float)dst_w; + scale_y = (float)src_h / (float)dst_h; + + while (num_boxes--) { + int x = box->x1; + int y = box->y1; + int w = box->x2 - box->x1; + int h = box->y2 - box->y1; + + renderer_draw_yuv(r, + (float)src_x + scale_x * (x - dst_x), + (float)src_y + scale_y * (y - dst_y), + scale_x * w, scale_y * h, x, y, w, h, yuv); + box++; + } + + r->pipe->flush(r->pipe, &r->last_fence); + + xa_yuv_destroy_sampler_views(yuv); + pipe_surface_reference(&dst->srf, NULL); + + return XA_ERR_NONE; +} diff --git a/src/gallium/state_trackers/xorg/SConscript b/src/gallium/state_trackers/xorg/SConscript index 19315694b7c..4ea4ec4ee8b 100644 --- a/src/gallium/state_trackers/xorg/SConscript +++ b/src/gallium/state_trackers/xorg/SConscript @@ -9,10 +9,11 @@ env.Append(CPPPATH = [ '#/src/mesa', ]) -env.ParseConfig('pkg-config --cflags --libs libdrm xorg-server') +env.PkgUseModules(['DRM', 'XORG']) -if env['kms']: +if env['HAVE_KMS']: env.Append(CPPDEFINES = ['HAVE_LIBKMS']) + env.PkgUseModules(['KMS']) conf = env.Configure() diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index d4dc84a122b..f696b72e1e3 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -237,7 +237,7 @@ picture_format_fixups(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture, bool boolean swizzle = FALSE; unsigned ret = 0; - if (pSrc->picture_format == pSrcPicture->format) { + if (pSrc && pSrc->picture_format == pSrcPicture->format) { if (pSrc->picture_format == PICT_a8) { if (mask) return FS_MASK_LUMINANCE; @@ -252,7 +252,7 @@ picture_format_fixups(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture, bool return 0; } - if (pSrc->picture_format != PICT_a8r8g8b8) { + if (pSrc && pSrc->picture_format != PICT_a8r8g8b8) { assert(!"can not handle formats"); return 0; } @@ -355,7 +355,7 @@ bind_samplers(struct exa_context *exa, int op, struct exa_pixmap_priv *pMask, struct exa_pixmap_priv *pDst) { - struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS] = {0}; struct pipe_sampler_state src_sampler, mask_sampler; struct pipe_sampler_view view_templ; struct pipe_sampler_view *src_view; diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 0499ed1ea0b..22e61cf7081 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -122,6 +122,7 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, drm_mode.hskew = mode->HSkew; drm_mode.vscan = mode->VScan; drm_mode.vrefresh = mode->VRefresh; + drm_mode.type = 0; if (!mode->name) xf86SetModeDefaultName(mode); strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1); diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c index 234574b968e..af4992fc2ed 100644 --- a/src/gallium/state_trackers/xorg/xorg_xv.c +++ b/src/gallium/state_trackers/xorg/xorg_xv.c @@ -466,7 +466,6 @@ bind_samplers(struct xorg_xv_port_priv *port) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler; - struct pipe_resource **dst = port->yuv[port->current_set]; struct pipe_sampler_view **dst_views = port->yuv_views[port->current_set]; memset(&sampler, 0, sizeof(struct pipe_sampler_state)); |