xref: /OK3568_Linux_fs/external/xserver/fb/fbpict.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * Copyright © 2000 SuSE, Inc.
4*4882a593Smuzhiyun  * Copyright © 2007 Red Hat, Inc.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
7*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
8*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that
9*4882a593Smuzhiyun  * copyright notice and this permission notice appear in supporting
10*4882a593Smuzhiyun  * documentation, and that the name of SuSE not be used in advertising or
11*4882a593Smuzhiyun  * publicity pertaining to distribution of the software without specific,
12*4882a593Smuzhiyun  * written prior permission.  SuSE makes no representations about the
13*4882a593Smuzhiyun  * suitability of this software for any purpose.  It is provided "as is"
14*4882a593Smuzhiyun  * without express or implied warranty.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17*4882a593Smuzhiyun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18*4882a593Smuzhiyun  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*4882a593Smuzhiyun  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20*4882a593Smuzhiyun  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21*4882a593Smuzhiyun  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * Author:  Keith Packard, SuSE, Inc.
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
27*4882a593Smuzhiyun #include <dix-config.h>
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <string.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "fb.h"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "picturestr.h"
35*4882a593Smuzhiyun #include "mipict.h"
36*4882a593Smuzhiyun #include "fbpict.h"
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun void
fbComposite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)39*4882a593Smuzhiyun fbComposite(CARD8 op,
40*4882a593Smuzhiyun             PicturePtr pSrc,
41*4882a593Smuzhiyun             PicturePtr pMask,
42*4882a593Smuzhiyun             PicturePtr pDst,
43*4882a593Smuzhiyun             INT16 xSrc,
44*4882a593Smuzhiyun             INT16 ySrc,
45*4882a593Smuzhiyun             INT16 xMask,
46*4882a593Smuzhiyun             INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun     pixman_image_t *src, *mask, *dest;
49*4882a593Smuzhiyun     int src_xoff, src_yoff;
50*4882a593Smuzhiyun     int msk_xoff, msk_yoff;
51*4882a593Smuzhiyun     int dst_xoff, dst_yoff;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun     miCompositeSourceValidate(pSrc);
54*4882a593Smuzhiyun     if (pMask)
55*4882a593Smuzhiyun         miCompositeSourceValidate(pMask);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun     src = image_from_pict(pSrc, FALSE, &src_xoff, &src_yoff);
58*4882a593Smuzhiyun     mask = image_from_pict(pMask, FALSE, &msk_xoff, &msk_yoff);
59*4882a593Smuzhiyun     dest = image_from_pict(pDst, TRUE, &dst_xoff, &dst_yoff);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun     if (src && dest && !(pMask && !mask)) {
62*4882a593Smuzhiyun         pixman_image_composite(op, src, mask, dest,
63*4882a593Smuzhiyun                                xSrc + src_xoff, ySrc + src_yoff,
64*4882a593Smuzhiyun                                xMask + msk_xoff, yMask + msk_yoff,
65*4882a593Smuzhiyun                                xDst + dst_xoff, yDst + dst_yoff, width, height);
66*4882a593Smuzhiyun     }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun     free_pixman_pict(pSrc, src);
69*4882a593Smuzhiyun     free_pixman_pict(pMask, mask);
70*4882a593Smuzhiyun     free_pixman_pict(pDst, dest);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun static pixman_glyph_cache_t *glyphCache;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun void
fbDestroyGlyphCache(void)76*4882a593Smuzhiyun fbDestroyGlyphCache(void)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun     if (glyphCache)
79*4882a593Smuzhiyun     {
80*4882a593Smuzhiyun 	pixman_glyph_cache_destroy (glyphCache);
81*4882a593Smuzhiyun 	glyphCache = NULL;
82*4882a593Smuzhiyun     }
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun static void
fbUnrealizeGlyph(ScreenPtr pScreen,GlyphPtr pGlyph)86*4882a593Smuzhiyun fbUnrealizeGlyph(ScreenPtr pScreen,
87*4882a593Smuzhiyun 		 GlyphPtr pGlyph)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun     if (glyphCache)
90*4882a593Smuzhiyun 	pixman_glyph_cache_remove (glyphCache, pGlyph, NULL);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun void
fbGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlist,GlyphListPtr list,GlyphPtr * glyphs)94*4882a593Smuzhiyun fbGlyphs(CARD8 op,
95*4882a593Smuzhiyun 	 PicturePtr pSrc,
96*4882a593Smuzhiyun 	 PicturePtr pDst,
97*4882a593Smuzhiyun 	 PictFormatPtr maskFormat,
98*4882a593Smuzhiyun 	 INT16 xSrc,
99*4882a593Smuzhiyun 	 INT16 ySrc, int nlist,
100*4882a593Smuzhiyun 	 GlyphListPtr list,
101*4882a593Smuzhiyun 	 GlyphPtr *glyphs)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun #define N_STACK_GLYPHS 512
104*4882a593Smuzhiyun     ScreenPtr pScreen = pDst->pDrawable->pScreen;
105*4882a593Smuzhiyun     pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
106*4882a593Smuzhiyun     pixman_glyph_t *pglyphs = stack_glyphs;
107*4882a593Smuzhiyun     pixman_image_t *srcImage, *dstImage;
108*4882a593Smuzhiyun     int srcXoff, srcYoff, dstXoff, dstYoff;
109*4882a593Smuzhiyun     GlyphPtr glyph;
110*4882a593Smuzhiyun     int n_glyphs;
111*4882a593Smuzhiyun     int x, y;
112*4882a593Smuzhiyun     int i, n;
113*4882a593Smuzhiyun     int xDst = list->xOff, yDst = list->yOff;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun     miCompositeSourceValidate(pSrc);
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun     n_glyphs = 0;
118*4882a593Smuzhiyun     for (i = 0; i < nlist; ++i)
119*4882a593Smuzhiyun 	n_glyphs += list[i].len;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun     if (!glyphCache)
122*4882a593Smuzhiyun 	glyphCache = pixman_glyph_cache_create();
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     pixman_glyph_cache_freeze (glyphCache);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     if (n_glyphs > N_STACK_GLYPHS) {
127*4882a593Smuzhiyun 	if (!(pglyphs = xallocarray(n_glyphs, sizeof(pixman_glyph_t))))
128*4882a593Smuzhiyun 	    goto out;
129*4882a593Smuzhiyun     }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     i = 0;
132*4882a593Smuzhiyun     x = y = 0;
133*4882a593Smuzhiyun     while (nlist--) {
134*4882a593Smuzhiyun         x += list->xOff;
135*4882a593Smuzhiyun         y += list->yOff;
136*4882a593Smuzhiyun         n = list->len;
137*4882a593Smuzhiyun         while (n--) {
138*4882a593Smuzhiyun 	    const void *g;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun             glyph = *glyphs++;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	    if (!(g = pixman_glyph_cache_lookup (glyphCache, glyph, NULL))) {
143*4882a593Smuzhiyun 		pixman_image_t *glyphImage;
144*4882a593Smuzhiyun 		PicturePtr pPicture;
145*4882a593Smuzhiyun 		int xoff, yoff;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 		pPicture = GetGlyphPicture(glyph, pScreen);
148*4882a593Smuzhiyun 		if (!pPicture) {
149*4882a593Smuzhiyun 		    n_glyphs--;
150*4882a593Smuzhiyun 		    goto next;
151*4882a593Smuzhiyun 		}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		if (!(glyphImage = image_from_pict(pPicture, FALSE, &xoff, &yoff)))
154*4882a593Smuzhiyun 		    goto out;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 		g = pixman_glyph_cache_insert(glyphCache, glyph, NULL,
157*4882a593Smuzhiyun 					      glyph->info.x,
158*4882a593Smuzhiyun 					      glyph->info.y,
159*4882a593Smuzhiyun 					      glyphImage);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 		free_pixman_pict(pPicture, glyphImage);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 		if (!g)
164*4882a593Smuzhiyun 		    goto out;
165*4882a593Smuzhiyun 	    }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	    pglyphs[i].x = x;
168*4882a593Smuzhiyun 	    pglyphs[i].y = y;
169*4882a593Smuzhiyun 	    pglyphs[i].glyph = g;
170*4882a593Smuzhiyun 	    i++;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	next:
173*4882a593Smuzhiyun             x += glyph->info.xOff;
174*4882a593Smuzhiyun             y += glyph->info.yOff;
175*4882a593Smuzhiyun 	}
176*4882a593Smuzhiyun 	list++;
177*4882a593Smuzhiyun     }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun     if (!(srcImage = image_from_pict(pSrc, FALSE, &srcXoff, &srcYoff)))
180*4882a593Smuzhiyun 	goto out;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun     if (!(dstImage = image_from_pict(pDst, TRUE, &dstXoff, &dstYoff)))
183*4882a593Smuzhiyun 	goto out_free_src;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     if (maskFormat) {
186*4882a593Smuzhiyun 	pixman_format_code_t format;
187*4882a593Smuzhiyun 	pixman_box32_t extents;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	format = maskFormat->format | (maskFormat->depth << 24);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	pixman_composite_glyphs(op, srcImage, dstImage, format,
194*4882a593Smuzhiyun 				xSrc + srcXoff + extents.x1 - xDst, ySrc + srcYoff + extents.y1 - yDst,
195*4882a593Smuzhiyun 				extents.x1, extents.y1,
196*4882a593Smuzhiyun 				extents.x1 + dstXoff, extents.y1 + dstYoff,
197*4882a593Smuzhiyun 				extents.x2 - extents.x1,
198*4882a593Smuzhiyun 				extents.y2 - extents.y1,
199*4882a593Smuzhiyun 				glyphCache, n_glyphs, pglyphs);
200*4882a593Smuzhiyun     }
201*4882a593Smuzhiyun     else {
202*4882a593Smuzhiyun 	pixman_composite_glyphs_no_mask(op, srcImage, dstImage,
203*4882a593Smuzhiyun 					xSrc + srcXoff - xDst, ySrc + srcYoff - yDst,
204*4882a593Smuzhiyun 					dstXoff, dstYoff,
205*4882a593Smuzhiyun 					glyphCache, n_glyphs, pglyphs);
206*4882a593Smuzhiyun     }
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun     free_pixman_pict(pDst, dstImage);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun out_free_src:
211*4882a593Smuzhiyun     free_pixman_pict(pSrc, srcImage);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun out:
214*4882a593Smuzhiyun     pixman_glyph_cache_thaw(glyphCache);
215*4882a593Smuzhiyun     if (pglyphs != stack_glyphs)
216*4882a593Smuzhiyun 	free(pglyphs);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun static pixman_image_t *
create_solid_fill_image(PicturePtr pict)220*4882a593Smuzhiyun create_solid_fill_image(PicturePtr pict)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun     PictSolidFill *solid = &pict->pSourcePict->solidFill;
223*4882a593Smuzhiyun     /* pixman_color_t and xRenderColor have the same layout */
224*4882a593Smuzhiyun     pixman_color_t *color = (pixman_color_t *)&solid->fullcolor;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun     return pixman_image_create_solid_fill(color);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static pixman_image_t *
create_linear_gradient_image(PictGradient * gradient)230*4882a593Smuzhiyun create_linear_gradient_image(PictGradient * gradient)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun     PictLinearGradient *linear = (PictLinearGradient *) gradient;
233*4882a593Smuzhiyun     pixman_point_fixed_t p1;
234*4882a593Smuzhiyun     pixman_point_fixed_t p2;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     p1.x = linear->p1.x;
237*4882a593Smuzhiyun     p1.y = linear->p1.y;
238*4882a593Smuzhiyun     p2.x = linear->p2.x;
239*4882a593Smuzhiyun     p2.y = linear->p2.y;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun     return pixman_image_create_linear_gradient(&p1, &p2,
242*4882a593Smuzhiyun                                                (pixman_gradient_stop_t *)
243*4882a593Smuzhiyun                                                gradient->stops,
244*4882a593Smuzhiyun                                                gradient->nstops);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun static pixman_image_t *
create_radial_gradient_image(PictGradient * gradient)248*4882a593Smuzhiyun create_radial_gradient_image(PictGradient * gradient)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun     PictRadialGradient *radial = (PictRadialGradient *) gradient;
251*4882a593Smuzhiyun     pixman_point_fixed_t c1;
252*4882a593Smuzhiyun     pixman_point_fixed_t c2;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun     c1.x = radial->c1.x;
255*4882a593Smuzhiyun     c1.y = radial->c1.y;
256*4882a593Smuzhiyun     c2.x = radial->c2.x;
257*4882a593Smuzhiyun     c2.y = radial->c2.y;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun     return pixman_image_create_radial_gradient(&c1, &c2, radial->c1.radius,
260*4882a593Smuzhiyun                                                radial->c2.radius,
261*4882a593Smuzhiyun                                                (pixman_gradient_stop_t *)
262*4882a593Smuzhiyun                                                gradient->stops,
263*4882a593Smuzhiyun                                                gradient->nstops);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun static pixman_image_t *
create_conical_gradient_image(PictGradient * gradient)267*4882a593Smuzhiyun create_conical_gradient_image(PictGradient * gradient)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun     PictConicalGradient *conical = (PictConicalGradient *) gradient;
270*4882a593Smuzhiyun     pixman_point_fixed_t center;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     center.x = conical->center.x;
273*4882a593Smuzhiyun     center.y = conical->center.y;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun     return pixman_image_create_conical_gradient(&center, conical->angle,
276*4882a593Smuzhiyun                                                 (pixman_gradient_stop_t *)
277*4882a593Smuzhiyun                                                 gradient->stops,
278*4882a593Smuzhiyun                                                 gradient->nstops);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun static pixman_image_t *
create_bits_picture(PicturePtr pict,Bool has_clip,int * xoff,int * yoff)282*4882a593Smuzhiyun create_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun     PixmapPtr pixmap;
285*4882a593Smuzhiyun     FbBits *bits;
286*4882a593Smuzhiyun     FbStride stride;
287*4882a593Smuzhiyun     int bpp;
288*4882a593Smuzhiyun     pixman_image_t *image;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     fbGetDrawablePixmap(pict->pDrawable, pixmap, *xoff, *yoff);
291*4882a593Smuzhiyun     fbGetPixmapBitsData(pixmap, bits, stride, bpp);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun     image = pixman_image_create_bits((pixman_format_code_t) pict->format,
294*4882a593Smuzhiyun                                      pixmap->drawable.width,
295*4882a593Smuzhiyun                                      pixmap->drawable.height, (uint32_t *) bits,
296*4882a593Smuzhiyun                                      stride * sizeof(FbStride));
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun     if (!image)
299*4882a593Smuzhiyun         return NULL;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun #ifdef FB_ACCESS_WRAPPER
302*4882a593Smuzhiyun     pixman_image_set_accessors(image,
303*4882a593Smuzhiyun                                (pixman_read_memory_func_t) wfbReadMemory,
304*4882a593Smuzhiyun                                (pixman_write_memory_func_t) wfbWriteMemory);
305*4882a593Smuzhiyun #endif
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     /* pCompositeClip is undefined for source pictures, so
308*4882a593Smuzhiyun      * only set the clip region for pictures with drawables
309*4882a593Smuzhiyun      */
310*4882a593Smuzhiyun     if (has_clip) {
311*4882a593Smuzhiyun         if (pict->clientClip)
312*4882a593Smuzhiyun             pixman_image_set_has_client_clip(image, TRUE);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun         if (*xoff || *yoff)
315*4882a593Smuzhiyun             pixman_region_translate(pict->pCompositeClip, *xoff, *yoff);
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun         pixman_image_set_clip_region(image, pict->pCompositeClip);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun         if (*xoff || *yoff)
320*4882a593Smuzhiyun             pixman_region_translate(pict->pCompositeClip, -*xoff, -*yoff);
321*4882a593Smuzhiyun     }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun     /* Indexed table */
324*4882a593Smuzhiyun     if (pict->pFormat->index.devPrivate)
325*4882a593Smuzhiyun         pixman_image_set_indexed(image, pict->pFormat->index.devPrivate);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun     /* Add in drawable origin to position within the image */
328*4882a593Smuzhiyun     *xoff += pict->pDrawable->x;
329*4882a593Smuzhiyun     *yoff += pict->pDrawable->y;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun     return image;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun static pixman_image_t *image_from_pict_internal(PicturePtr pict, Bool has_clip,
335*4882a593Smuzhiyun                                                 int *xoff, int *yoff,
336*4882a593Smuzhiyun                                                 Bool is_alpha_map);
337*4882a593Smuzhiyun 
image_destroy(pixman_image_t * image,void * data)338*4882a593Smuzhiyun static void image_destroy(pixman_image_t *image, void *data)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun     fbFinishAccess((DrawablePtr)data);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun static void
set_image_properties(pixman_image_t * image,PicturePtr pict,Bool has_clip,int * xoff,int * yoff,Bool is_alpha_map)344*4882a593Smuzhiyun set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
345*4882a593Smuzhiyun                      int *xoff, int *yoff, Bool is_alpha_map)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun     pixman_repeat_t repeat;
348*4882a593Smuzhiyun     pixman_filter_t filter;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun     if (pict->transform) {
351*4882a593Smuzhiyun         /* For source images, adjust the transform to account
352*4882a593Smuzhiyun          * for the drawable offset within the pixman image,
353*4882a593Smuzhiyun          * then set the offset to 0 as it will be used
354*4882a593Smuzhiyun          * to compute positions within the transformed image.
355*4882a593Smuzhiyun          */
356*4882a593Smuzhiyun         if (!has_clip) {
357*4882a593Smuzhiyun             struct pixman_transform adjusted;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun             adjusted = *pict->transform;
360*4882a593Smuzhiyun             pixman_transform_translate(&adjusted,
361*4882a593Smuzhiyun                                        NULL,
362*4882a593Smuzhiyun                                        pixman_int_to_fixed(*xoff),
363*4882a593Smuzhiyun                                        pixman_int_to_fixed(*yoff));
364*4882a593Smuzhiyun             pixman_image_set_transform(image, &adjusted);
365*4882a593Smuzhiyun             *xoff = 0;
366*4882a593Smuzhiyun             *yoff = 0;
367*4882a593Smuzhiyun         }
368*4882a593Smuzhiyun         else
369*4882a593Smuzhiyun             pixman_image_set_transform(image, pict->transform);
370*4882a593Smuzhiyun     }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun     switch (pict->repeatType) {
373*4882a593Smuzhiyun     default:
374*4882a593Smuzhiyun     case RepeatNone:
375*4882a593Smuzhiyun         repeat = PIXMAN_REPEAT_NONE;
376*4882a593Smuzhiyun         break;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     case RepeatPad:
379*4882a593Smuzhiyun         repeat = PIXMAN_REPEAT_PAD;
380*4882a593Smuzhiyun         break;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun     case RepeatNormal:
383*4882a593Smuzhiyun         repeat = PIXMAN_REPEAT_NORMAL;
384*4882a593Smuzhiyun         break;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun     case RepeatReflect:
387*4882a593Smuzhiyun         repeat = PIXMAN_REPEAT_REFLECT;
388*4882a593Smuzhiyun         break;
389*4882a593Smuzhiyun     }
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     pixman_image_set_repeat(image, repeat);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     /* Fetch alpha map unless 'pict' is being used
394*4882a593Smuzhiyun      * as the alpha map for this operation
395*4882a593Smuzhiyun      */
396*4882a593Smuzhiyun     if (pict->alphaMap && !is_alpha_map) {
397*4882a593Smuzhiyun         int alpha_xoff, alpha_yoff;
398*4882a593Smuzhiyun         pixman_image_t *alpha_map =
399*4882a593Smuzhiyun             image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff,
400*4882a593Smuzhiyun                                      &alpha_yoff, TRUE);
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun         pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x,
403*4882a593Smuzhiyun                                    pict->alphaOrigin.y);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun         free_pixman_pict(pict->alphaMap, alpha_map);
406*4882a593Smuzhiyun     }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun     pixman_image_set_component_alpha(image, pict->componentAlpha);
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun     switch (pict->filter) {
411*4882a593Smuzhiyun     default:
412*4882a593Smuzhiyun     case PictFilterNearest:
413*4882a593Smuzhiyun     case PictFilterFast:
414*4882a593Smuzhiyun         filter = PIXMAN_FILTER_NEAREST;
415*4882a593Smuzhiyun         break;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun     case PictFilterBilinear:
418*4882a593Smuzhiyun     case PictFilterGood:
419*4882a593Smuzhiyun         filter = PIXMAN_FILTER_BILINEAR;
420*4882a593Smuzhiyun         break;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun     case PictFilterConvolution:
423*4882a593Smuzhiyun         filter = PIXMAN_FILTER_CONVOLUTION;
424*4882a593Smuzhiyun         break;
425*4882a593Smuzhiyun     }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun     if (pict->pDrawable)
428*4882a593Smuzhiyun         pixman_image_set_destroy_function(image, &image_destroy,
429*4882a593Smuzhiyun                                           pict->pDrawable);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun     pixman_image_set_filter(image, filter,
432*4882a593Smuzhiyun                             (pixman_fixed_t *) pict->filter_params,
433*4882a593Smuzhiyun                             pict->filter_nparams);
434*4882a593Smuzhiyun     pixman_image_set_source_clipping(image, TRUE);
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun static pixman_image_t *
image_from_pict_internal(PicturePtr pict,Bool has_clip,int * xoff,int * yoff,Bool is_alpha_map)438*4882a593Smuzhiyun image_from_pict_internal(PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
439*4882a593Smuzhiyun                          Bool is_alpha_map)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun     pixman_image_t *image = NULL;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun     if (!pict)
444*4882a593Smuzhiyun         return NULL;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun     if (pict->pDrawable) {
447*4882a593Smuzhiyun         image = create_bits_picture(pict, has_clip, xoff, yoff);
448*4882a593Smuzhiyun     }
449*4882a593Smuzhiyun     else if (pict->pSourcePict) {
450*4882a593Smuzhiyun         SourcePict *sp = pict->pSourcePict;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun         if (sp->type == SourcePictTypeSolidFill) {
453*4882a593Smuzhiyun             image = create_solid_fill_image(pict);
454*4882a593Smuzhiyun         }
455*4882a593Smuzhiyun         else {
456*4882a593Smuzhiyun             PictGradient *gradient = &pict->pSourcePict->gradient;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun             if (sp->type == SourcePictTypeLinear)
459*4882a593Smuzhiyun                 image = create_linear_gradient_image(gradient);
460*4882a593Smuzhiyun             else if (sp->type == SourcePictTypeRadial)
461*4882a593Smuzhiyun                 image = create_radial_gradient_image(gradient);
462*4882a593Smuzhiyun             else if (sp->type == SourcePictTypeConical)
463*4882a593Smuzhiyun                 image = create_conical_gradient_image(gradient);
464*4882a593Smuzhiyun         }
465*4882a593Smuzhiyun         *xoff = *yoff = 0;
466*4882a593Smuzhiyun     }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun     if (image)
469*4882a593Smuzhiyun         set_image_properties(image, pict, has_clip, xoff, yoff, is_alpha_map);
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun     return image;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun pixman_image_t *
image_from_pict(PicturePtr pict,Bool has_clip,int * xoff,int * yoff)475*4882a593Smuzhiyun image_from_pict(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun     return image_from_pict_internal(pict, has_clip, xoff, yoff, FALSE);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun void
free_pixman_pict(PicturePtr pict,pixman_image_t * image)481*4882a593Smuzhiyun free_pixman_pict(PicturePtr pict, pixman_image_t * image)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun     if (image)
484*4882a593Smuzhiyun         pixman_image_unref(image);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun Bool
fbPictureInit(ScreenPtr pScreen,PictFormatPtr formats,int nformats)488*4882a593Smuzhiyun fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun     PictureScreenPtr ps;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun     if (!miPictureInit(pScreen, formats, nformats))
494*4882a593Smuzhiyun         return FALSE;
495*4882a593Smuzhiyun     ps = GetPictureScreen(pScreen);
496*4882a593Smuzhiyun     ps->Composite = fbComposite;
497*4882a593Smuzhiyun     ps->Glyphs = fbGlyphs;
498*4882a593Smuzhiyun     ps->UnrealizeGlyph = fbUnrealizeGlyph;
499*4882a593Smuzhiyun     ps->CompositeRects = miCompositeRects;
500*4882a593Smuzhiyun     ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
501*4882a593Smuzhiyun     ps->Trapezoids = fbTrapezoids;
502*4882a593Smuzhiyun     ps->AddTraps = fbAddTraps;
503*4882a593Smuzhiyun     ps->AddTriangles = fbAddTriangles;
504*4882a593Smuzhiyun     ps->Triangles = fbTriangles;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun     return TRUE;
507*4882a593Smuzhiyun }
508