diff options
Diffstat (limited to 'vmwgfx/vmwgfx_xa_composite.c')
-rw-r--r-- | vmwgfx/vmwgfx_xa_composite.c | 277 |
1 files changed, 277 insertions, 0 deletions
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; +} |