1/* 2 * Copyright 2009-2011 VMWare, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Author: Thomas Hellstrom <thellstrom@vmware.com> 26 * Author: Zack Ruzin <zackr@vmware.com> 27 * 28 * The code in this file translates XRender PICT composite stuff 29 * to fit the libxatracker API. 30 */ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include <pixman.h> 37#include <picturestr.h> 38#include "xa_composite.h" 39#include "vmwgfx_saa.h" 40#include "vmwgfx_saa_priv.h" 41 42 43struct vmwgfx_composite { 44 union xa_source_pict *src_spict; 45 union xa_source_pict *mask_spict; 46 union xa_source_pict *dst_spict; 47 struct xa_picture *src_pict; 48 struct xa_picture *mask_pict; 49 struct xa_picture *dst_pict; 50 struct xa_composite *comp; 51}; 52 53static const enum xa_composite_op vmwgfx_op_map[] = { 54 [PictOpClear] = xa_op_clear, 55 [PictOpSrc] = xa_op_src, 56 [PictOpDst] = xa_op_dst, 57 [PictOpOver] = xa_op_over, 58 [PictOpOverReverse] = xa_op_over_reverse, 59 [PictOpIn] = xa_op_in, 60 [PictOpInReverse] = xa_op_in_reverse, 61 [PictOpOut] = xa_op_out, 62 [PictOpOutReverse] = xa_op_out_reverse, 63 [PictOpAtop] = xa_op_atop, 64 [PictOpAtopReverse] = xa_op_atop_reverse, 65 [PictOpXor] = xa_op_xor, 66 [PictOpAdd] = xa_op_add 67}; 68 69static const unsigned int vmwgfx_op_map_size = 70 sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op); 71 72static Bool 73vmwgfx_matrix_from_pict_transform(PictTransform *trans, float *matrix) 74{ 75 if (!trans) 76 return FALSE; 77 78 matrix[0] = pixman_fixed_to_double(trans->matrix[0][0]); 79 matrix[3] = pixman_fixed_to_double(trans->matrix[0][1]); 80 matrix[6] = pixman_fixed_to_double(trans->matrix[0][2]); 81 82 matrix[1] = pixman_fixed_to_double(trans->matrix[1][0]); 83 matrix[4] = pixman_fixed_to_double(trans->matrix[1][1]); 84 matrix[7] = pixman_fixed_to_double(trans->matrix[1][2]); 85 86 matrix[2] = pixman_fixed_to_double(trans->matrix[2][0]); 87 matrix[5] = pixman_fixed_to_double(trans->matrix[2][1]); 88 matrix[8] = pixman_fixed_to_double(trans->matrix[2][2]); 89 90 return TRUE; 91} 92 93static enum xa_composite_wrap 94vmwgfx_xa_setup_wrap(Bool pict_has_repeat, int pict_repeat) 95{ 96 enum xa_composite_wrap wrap = xa_wrap_clamp_to_border; 97 98 if (!pict_has_repeat) 99 return wrap; 100 101 switch(pict_repeat) { 102 case RepeatNormal: 103 wrap = xa_wrap_repeat; 104 break; 105 case RepeatReflect: 106 wrap = xa_wrap_mirror_repeat; 107 break; 108 case RepeatPad: 109 wrap = xa_wrap_clamp_to_edge; 110 break; 111 default: 112 break; 113 } 114 return wrap; 115} 116 117static Bool 118vmwgfx_render_filter_to_xa(int xrender_filter, 119 enum xa_composite_filter *out_filter) 120{ 121 switch (xrender_filter) { 122 case PictFilterConvolution: 123 case PictFilterNearest: 124 case PictFilterFast: 125 *out_filter = xa_filter_nearest; 126 break; 127 case PictFilterBest: 128 case PictFilterGood: 129 case PictFilterBilinear: 130 *out_filter = xa_filter_linear; 131 break; 132 default: 133 *out_filter = xa_filter_nearest; 134 return FALSE; 135 } 136 return TRUE; 137} 138 139static Bool 140vmwgfx_xa_setup_pict(PicturePtr pict, 141 struct xa_picture *xa_pict, 142 union xa_source_pict *src_pict) 143{ 144 if (!pict) 145 return FALSE; 146 147 memset(xa_pict, 0, sizeof(*xa_pict)); 148 149 xa_pict->pict_format = vmwgfx_xa_format(pict->format); 150 if (xa_pict->pict_format == xa_format_unknown) 151 return FALSE; 152 153 /* 154 * Saa doesn't let drivers accelerate alpha maps. 155 */ 156 xa_pict->alpha_map = NULL; 157 xa_pict->component_alpha = pict->componentAlpha; 158 159 xa_pict->has_transform = 160 vmwgfx_matrix_from_pict_transform(pict->transform, 161 xa_pict->transform); 162 163 xa_pict->wrap = vmwgfx_xa_setup_wrap(pict->repeat, 164 pict->repeatType); 165 166 (void) vmwgfx_render_filter_to_xa(pict->filter, &xa_pict->filter); 167 168 if (pict->pSourcePict) { 169 if (pict->pSourcePict->type != SourcePictTypeSolidFill) 170 return FALSE; 171 172 src_pict->type = xa_src_pict_solid_fill; 173 src_pict->solid_fill.color = pict->pSourcePict->solidFill.color; 174 xa_pict->src_pict = src_pict; 175 } 176 177 return TRUE; 178} 179 180struct xa_composite * 181vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, 182 int op, 183 PicturePtr src_pict, 184 PicturePtr mask_pict, 185 PicturePtr dst_pict) 186{ 187 struct xa_composite *comp = vcomp->comp; 188 189 if (op >= vmwgfx_op_map_size) 190 return NULL; 191 192 comp->op = vmwgfx_op_map[op]; 193 if (comp->op == xa_op_clear && op != PictOpClear) 194 return NULL; 195 196 if (!vmwgfx_xa_setup_pict(dst_pict, vcomp->dst_pict, 197 vcomp->dst_spict)) 198 return NULL; 199 if (!vmwgfx_xa_setup_pict(src_pict, vcomp->src_pict, 200 vcomp->src_spict)) 201 return NULL; 202 if (mask_pict && !vmwgfx_xa_setup_pict(mask_pict, 203 vcomp->mask_pict, 204 vcomp->mask_spict)) 205 return NULL; 206 207 comp->dst = vcomp->dst_pict; 208 comp->src = vcomp->src_pict; 209 comp->mask = (mask_pict) ? vcomp->mask_pict : NULL; 210 211 return comp; 212} 213 214Bool 215vmwgfx_xa_update_comp(struct xa_composite *comp, 216 PixmapPtr src_pix, 217 PixmapPtr mask_pix, 218 PixmapPtr dst_pix) 219{ 220 comp->dst->srf = vmwgfx_saa_pixmap(dst_pix)->hw; 221 if (src_pix) 222 comp->src->srf = vmwgfx_saa_pixmap(src_pix)->hw; 223 if (mask_pix && comp->mask) 224 comp->mask->srf = vmwgfx_saa_pixmap(mask_pix)->hw; 225 return TRUE; 226} 227 228 229void 230vmwgfx_free_composite(struct vmwgfx_composite *vcomp) 231{ 232 if (!vcomp) 233 return; 234 235 if (vcomp->src_spict) 236 free(vcomp->src_spict); 237 if (vcomp->mask_spict) 238 free(vcomp->mask_spict); 239 if (vcomp->dst_spict) 240 free(vcomp->dst_spict); 241 if (vcomp->src_pict) 242 free(vcomp->src_pict); 243 if (vcomp->mask_pict) 244 free(vcomp->mask_pict); 245 if (vcomp->dst_pict) 246 free(vcomp->dst_pict); 247 if (vcomp->comp) 248 free(vcomp->comp); 249 free(vcomp); 250} 251 252struct vmwgfx_composite * 253vmwgfx_alloc_composite(void) 254{ 255 const struct xa_composite_allocation *a = xa_composite_allocation(); 256 struct vmwgfx_composite *vcomp = calloc(1, sizeof(*vcomp)); 257 258 if (!vcomp) 259 return NULL; 260 261 vcomp->src_spict = calloc(1, a->xa_source_pict_size); 262 vcomp->mask_spict = calloc(1, a->xa_source_pict_size); 263 vcomp->dst_spict = calloc(1, a->xa_source_pict_size); 264 vcomp->src_pict = calloc(1, a->xa_picture_size); 265 vcomp->mask_pict = calloc(1, a->xa_picture_size); 266 vcomp->dst_pict = calloc(1, a->xa_picture_size); 267 vcomp->comp = calloc(1, a->xa_composite_size); 268 269 if (!vcomp->src_spict || !vcomp->mask_spict || !vcomp->dst_spict || 270 !vcomp->src_pict || !vcomp->mask_pict || !vcomp->dst_pict || 271 !vcomp->comp) { 272 vmwgfx_free_composite(vcomp); 273 return NULL; 274 } 275 276 return vcomp; 277} 278