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