diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-06-22 22:26:20 +0200 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-07-01 11:35:32 +0200 |
commit | 8a21da8eaa77bb1ec55ab8b5584554ae6cc41e1e (patch) | |
tree | 40be543c94f45eb87e521b67237dfeb7c39a24de | |
parent | c7e8388280fc047b33be4f603afa4b7615ffc585 (diff) |
vmwgfx: Support xa composite.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r-- | vmwgfx/Makefile.am | 1 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_saa.c | 147 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_saa.h | 27 | ||||
-rw-r--r-- | vmwgfx/vmwgfx_xa_composite.c | 277 |
4 files changed, 443 insertions, 9 deletions
diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index 3c31543..03dbf6a 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -20,6 +20,7 @@ vmwgfx_drv_la_SOURCES = \ vmwgfx_overlay.c \ vmwgfx_ctrl.c \ vmwgfx_ctrl.h \ + vmwgfx_xa_composite.c \ wsbm_util.h diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 297e1f3..48c327d 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -33,7 +33,6 @@ #include "vmwgfx_saa.h" #include "vmwgfx_drmi.h" - #define VMWGFX_PIX_MALLOC (1 << 0) #define VMWGFX_PIX_GMR (1 << 1) #define VMWGFX_PIX_SURFACE (1 << 2) @@ -56,6 +55,7 @@ struct vmwgfx_saa { Bool can_optimize_dma; void (*present_flush) (ScreenPtr pScreen); struct _WsbmListHead sync_x_list; + struct vmwgfx_composite *vcomp; }; static inline struct vmwgfx_saa * @@ -277,13 +277,6 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, return TRUE; /* - * Flush dirty stuff to screen. - */ - - - vsaa->present_flush(vsaa->pScreen); - - /* * Intersect dirty region with region to be read back, if any. */ @@ -1014,11 +1007,141 @@ vmwgfx_copy_done(struct saa_driver *driver) xa_copy_done(vsaa->xa_ctx); } +static Bool +vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, + PicturePtr src_pict, PicturePtr mask_pict, + PicturePtr dst_pict, + PixmapPtr src_pix, PixmapPtr mask_pix, + PixmapPtr dst_pix, + RegionPtr src_region, + RegionPtr mask_region, + RegionPtr dst_region) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + struct vmwgfx_saa_pixmap *src_vpix; + struct vmwgfx_saa_pixmap *dst_vpix; + struct vmwgfx_saa_pixmap *mask_vpix; + Bool tmp_valid_hw; + Bool dirty_hw; + Bool valid_hw; + RegionRec empty; + struct xa_composite *xa_comp; + + REGION_NULL(pScreen, &empty); + + /* + * First we define our migration policy. We accelerate only if there + * is dirty hw regions to be read or if all source data is + * available in hw, and the destination has a hardware surface. + */ + + dst_vpix = vmwgfx_saa_pixmap(dst_pix); + valid_hw = (dst_vpix->hw != NULL); + if (saa_op_reads_destination(op)) { + vmwgfx_check_hw_contents(vsaa, dst_vpix, dst_region, + &dirty_hw, &tmp_valid_hw); + valid_hw = (valid_hw && tmp_valid_hw); + } else { + dirty_hw = FALSE; + dst_region = ∅ + } + + if (src_pix && !dirty_hw) { + src_vpix = vmwgfx_saa_pixmap(src_pix); + vmwgfx_check_hw_contents(vsaa, src_vpix, src_region, + &dirty_hw, &tmp_valid_hw); + valid_hw = (valid_hw && tmp_valid_hw); + } + + if (mask_pict && mask_pix && !dirty_hw) { + mask_vpix = vmwgfx_saa_pixmap(mask_pix); + vmwgfx_check_hw_contents(vsaa, mask_vpix, mask_region, + &dirty_hw, &tmp_valid_hw); + valid_hw = (valid_hw && tmp_valid_hw); + } + + if (!valid_hw && !dirty_hw) + goto out_err; + + /* + * Then, setup most of the XA composite state (except hardware surfaces) + * and check whether XA can accelerate. + */ + + xa_comp = vmwgfx_xa_setup_comp(vsaa->vcomp, op, + src_pict, mask_pict, dst_pict); + if (!xa_comp) + goto out_err; + + if (xa_composite_check_accelerated(xa_comp) != XA_ERR_NONE) + goto out_err; + + /* + * Create hw surfaces and migrate data needed for HW compositing. + */ + + if (src_region == NULL) + src_region = ∅ + if (src_pix && + !vmwgfx_pixmap_validate_hw(src_pix, src_region, 0, 0, 0)) + goto out_err; + + if (mask_region == NULL) + mask_region = ∅ + if (mask_pict && mask_pix && + !vmwgfx_pixmap_validate_hw(mask_pix, mask_region, 0, 0, 0)) + goto out_err; + + if (dst_region == NULL) + dst_region = ∅ + if (!vmwgfx_pixmap_validate_hw(dst_pix, dst_region, 0, 0, 0)) + goto out_err; + + /* + * Update the XA state with our hardware surfaces and + * surface formats, and bind the XA state for compositing. + */ + + if (!vmwgfx_xa_update_comp(xa_comp, src_pix, mask_pix, dst_pix)) + goto out_err; + + if (xa_composite_prepare(vsaa->xa_ctx, xa_comp)) + goto out_err; + + REGION_UNINIT(pScreen, &empty); + return TRUE; + out_err: + REGION_UNINIT(pScreen, &empty); + return FALSE; +} + +static void +vmwgfx_composite(struct saa_driver *driver, + int src_x, int src_y, int mask_x, int mask_y, + int dst_x, int dst_y, + int width, int height) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + xa_composite_rect(vsaa->xa_ctx, src_x, src_y, mask_x, mask_y, + dst_x, dst_y, width, height); +} + +static void +vmwgfx_composite_done(struct saa_driver *driver) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + xa_composite_done(vsaa->xa_ctx); +} + static void vmwgfx_takedown(struct saa_driver *driver) { struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + if (vsaa->vcomp) + vmwgfx_free_composite(vsaa->vcomp); free(vsaa); } @@ -1130,6 +1253,9 @@ static const struct saa_driver vmwgfx_saa_driver = { .copy_prepare = vmwgfx_copy_prepare, .copy = vmwgfx_copy, .copy_done = vmwgfx_copy_done, + .composite_prepare = vmwgfx_composite_prepare, + .composite = vmwgfx_composite, + .composite_done = vmwgfx_composite_done, .takedown = vmwgfx_takedown, }; @@ -1154,6 +1280,11 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, WSBMINITLISTHEAD(&vsaa->sync_x_list); vsaa->driver = vmwgfx_saa_driver; + vsaa->vcomp = vmwgfx_alloc_composite(); + + if (!vsaa->vcomp) + vsaa->driver.composite_prepare = NULL; + if (!saa_driver_init(pScreen, &vsaa->driver)) goto out_no_saa; diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 29863c5..deb3f37 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -29,10 +29,11 @@ #define _VMWGFX_SAA_H_ #include "saa.h" -#include <xa_tracker.h> +#include <xa_composite.h> #include "vmwgfx_drmi.h" #include "wsbm_util.h" + #define VMWGFX_FLAG_FORCE_GMR (1 << 0) /* Create with GMR as backing store */ #define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */ #define VMWGFX_FLAG_AVOID_HWACCEL (1 << 2) /* Avoid Hardware acceleration on this pixmap */ @@ -98,4 +99,28 @@ vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix); extern void vmwgfx_flush_dri2(ScreenPtr pScreen); +/* + * vmwgfx_xa_composite.c + */ + +struct vmwgfx_composite; + +void +vmwgfx_free_composite(struct vmwgfx_composite *vcomp); +struct vmwgfx_composite * +vmwgfx_alloc_composite(void); + +Bool +vmwgfx_xa_update_comp(struct xa_composite *comp, + PixmapPtr src_pix, + PixmapPtr mask_pix, + PixmapPtr dst_pix); + +struct xa_composite * +vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, + int op, + PicturePtr src_pict, + PicturePtr mask_pict, + PicturePtr dst_pict); + #endif diff --git a/vmwgfx/vmwgfx_xa_composite.c b/vmwgfx/vmwgfx_xa_composite.c new file mode 100644 index 0000000..a2e3970 --- /dev/null +++ b/vmwgfx/vmwgfx_xa_composite.c @@ -0,0 +1,277 @@ +/* + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + * + * Author: Thomas Hellstrom <thellstrom@vmware.com> + * Author: Zack Ruzin <zackr@vmware.com> + * + * The code in this file translates XRender PICT composite stuff + * to fit the libxatracker API. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <picturestr.h> +#include <X11/extensions/Xrender.h> +#include "xa_composite.h" +#include "vmwgfx_saa.h" +#include "vmwgfx_saa_priv.h" + + +struct vmwgfx_composite { + union xa_source_pict *src_spict; + union xa_source_pict *mask_spict; + union xa_source_pict *dst_spict; + struct xa_picture *src_pict; + struct xa_picture *mask_pict; + struct xa_picture *dst_pict; + struct xa_composite *comp; +}; + +static const enum xa_composite_op vmwgfx_op_map[] = { + [PictOpClear] = xa_op_clear, + [PictOpSrc] = xa_op_src, + [PictOpDst] = xa_op_dst, + [PictOpOver] = xa_op_over, + [PictOpOverReverse] = xa_op_over_reverse, + [PictOpIn] = xa_op_in, + [PictOpInReverse] = xa_op_in_reverse, + [PictOpOut] = xa_op_out, + [PictOpOutReverse] = xa_op_out_reverse, + [PictOpAtop] = xa_op_atop, + [PictOpAtopReverse] = xa_op_atop_reverse, + [PictOpXor] = xa_op_xor, + [PictOpAdd] = xa_op_add +}; + +static const unsigned int vmwgfx_op_map_size = + sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op); + +static Bool +vmwgfx_matrix_from_pict_transform(PictTransform *trans, float *matrix) +{ + if (!trans) + return FALSE; + + matrix[0] = XFixedToDouble(trans->matrix[0][0]); + matrix[3] = XFixedToDouble(trans->matrix[0][1]); + matrix[6] = XFixedToDouble(trans->matrix[0][2]); + + matrix[1] = XFixedToDouble(trans->matrix[1][0]); + matrix[4] = XFixedToDouble(trans->matrix[1][1]); + matrix[7] = XFixedToDouble(trans->matrix[1][2]); + + matrix[2] = XFixedToDouble(trans->matrix[2][0]); + matrix[5] = XFixedToDouble(trans->matrix[2][1]); + matrix[8] = XFixedToDouble(trans->matrix[2][2]); + + return TRUE; +} + +static enum xa_composite_wrap +vmwgfx_xa_setup_wrap(Bool pict_has_repeat, int pict_repeat) +{ + enum xa_composite_wrap wrap = xa_wrap_clamp_to_border; + + if (!pict_has_repeat) + return wrap; + + switch(pict_repeat) { + case RepeatNormal: + wrap = xa_wrap_repeat; + break; + case RepeatReflect: + wrap = xa_wrap_mirror_repeat; + break; + case RepeatPad: + wrap = xa_wrap_clamp_to_edge; + break; + default: + break; + } + return wrap; +} + +static Bool +vmwgfx_render_filter_to_xa(int xrender_filter, + enum xa_composite_filter *out_filter) +{ + switch (xrender_filter) { + case PictFilterConvolution: + case PictFilterNearest: + case PictFilterFast: + *out_filter = xa_filter_nearest; + break; + case PictFilterBest: + case PictFilterGood: + case PictFilterBilinear: + *out_filter = xa_filter_linear; + break; + default: + *out_filter = xa_filter_nearest; + return FALSE; + } + return TRUE; +} + +static Bool +vmwgfx_xa_setup_pict(PicturePtr pict, + struct xa_picture *xa_pict, + union xa_source_pict *src_pict) +{ + if (!pict) + return FALSE; + + memset(xa_pict, 0, sizeof(*xa_pict)); + + xa_pict->pict_format = vmwgfx_xa_format(pict->format); + if (xa_pict->pict_format == xa_format_unknown) + return FALSE; + + /* + * Saa doesn't let drivers accelerate alpha maps. + */ + xa_pict->alpha_map = NULL; + xa_pict->component_alpha = pict->componentAlpha; + + xa_pict->has_transform = + vmwgfx_matrix_from_pict_transform(pict->transform, + xa_pict->transform); + + xa_pict->wrap = vmwgfx_xa_setup_wrap(pict->repeat, + pict->repeatType); + + (void) vmwgfx_render_filter_to_xa(pict->filter, &xa_pict->filter); + + if (pict->pSourcePict) { + if (pict->pSourcePict->type != SourcePictTypeSolidFill) + return FALSE; + + src_pict->type = xa_src_pict_solid_fill; + src_pict->solid_fill.color = pict->pSourcePict->solidFill.color; + xa_pict->src_pict = src_pict; + } + + return TRUE; +} + +struct xa_composite * +vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, + int op, + PicturePtr src_pict, + PicturePtr mask_pict, + PicturePtr dst_pict) +{ + struct xa_composite *comp = vcomp->comp; + + if (op >= vmwgfx_op_map_size) + return NULL; + + comp->op = vmwgfx_op_map[op]; + if (comp->op == xa_op_clear && op != PictOpClear) + return NULL; + + if (!vmwgfx_xa_setup_pict(dst_pict, vcomp->dst_pict, + vcomp->dst_spict)) + return NULL; + if (!vmwgfx_xa_setup_pict(src_pict, vcomp->src_pict, + vcomp->src_spict)) + return NULL; + if (mask_pict && !vmwgfx_xa_setup_pict(mask_pict, + vcomp->mask_pict, + vcomp->mask_spict)) + return NULL; + + comp->dst = vcomp->dst_pict; + comp->src = vcomp->src_pict; + comp->mask = (mask_pict) ? vcomp->mask_pict : NULL; + + return comp; +} + +Bool +vmwgfx_xa_update_comp(struct xa_composite *comp, + PixmapPtr src_pix, + PixmapPtr mask_pix, + PixmapPtr dst_pix) +{ + comp->dst->srf = vmwgfx_saa_pixmap(dst_pix)->hw; + if (src_pix) + comp->src->srf = vmwgfx_saa_pixmap(src_pix)->hw; + if (mask_pix && comp->mask) + comp->mask->srf = vmwgfx_saa_pixmap(mask_pix)->hw; + return TRUE; +} + + +void +vmwgfx_free_composite(struct vmwgfx_composite *vcomp) +{ + if (!vcomp) + return; + + if (vcomp->src_spict) + free(vcomp->src_spict); + if (vcomp->mask_spict) + free(vcomp->mask_spict); + if (vcomp->dst_spict) + free(vcomp->dst_spict); + if (vcomp->src_pict) + free(vcomp->src_pict); + if (vcomp->mask_pict) + free(vcomp->mask_pict); + if (vcomp->dst_pict) + free(vcomp->dst_pict); + if (vcomp->comp) + free(vcomp->comp); + free(vcomp); +} + +struct vmwgfx_composite * +vmwgfx_alloc_composite(void) +{ + const struct xa_composite_allocation *a = xa_composite_allocation(); + struct vmwgfx_composite *vcomp = calloc(1, sizeof(*vcomp)); + + if (!vcomp) + return NULL; + + vcomp->src_spict = calloc(1, a->xa_source_pict_size); + vcomp->mask_spict = calloc(1, a->xa_source_pict_size); + vcomp->dst_spict = calloc(1, a->xa_source_pict_size); + vcomp->src_pict = calloc(1, a->xa_picture_size); + vcomp->mask_pict = calloc(1, a->xa_picture_size); + vcomp->dst_pict = calloc(1, a->xa_picture_size); + vcomp->comp = calloc(1, a->xa_composite_size); + + if (!vcomp->src_spict || !vcomp->mask_spict || !vcomp->dst_spict || + !vcomp->src_pict || !vcomp->mask_pict || !vcomp->dst_pict || + !vcomp->comp) { + vmwgfx_free_composite(vcomp); + return NULL; + } + + return vcomp; +} |