3 * Copyright © 2000 SuSE, Inc.
4 * Copyright © 2007 Red Hat, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of SuSE not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. SuSE makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Keith Packard, SuSE, Inc.
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
34 #include "picturestr.h"
46 INT16 yMask
, INT16 xDst
, INT16 yDst
, CARD16 width
, CARD16 height
)
48 pixman_image_t
*src
, *mask
, *dest
;
49 int src_xoff
, src_yoff
;
50 int msk_xoff
, msk_yoff
;
51 int dst_xoff
, dst_yoff
;
53 miCompositeSourceValidate(pSrc
);
55 miCompositeSourceValidate(pMask
);
57 src
= image_from_pict(pSrc
, FALSE
, &src_xoff
, &src_yoff
);
58 mask
= image_from_pict(pMask
, FALSE
, &msk_xoff
, &msk_yoff
);
59 dest
= image_from_pict(pDst
, TRUE
, &dst_xoff
, &dst_yoff
);
61 if (src
&& dest
&& !(pMask
&& !mask
)) {
62 pixman_image_composite(op
, src
, mask
, dest
,
63 xSrc
+ src_xoff
, ySrc
+ src_yoff
,
64 xMask
+ msk_xoff
, yMask
+ msk_yoff
,
65 xDst
+ dst_xoff
, yDst
+ dst_yoff
, width
, height
);
68 free_pixman_pict(pSrc
, src
);
69 free_pixman_pict(pMask
, mask
);
70 free_pixman_pict(pDst
, dest
);
73 static pixman_glyph_cache_t
*glyphCache
;
76 fbDestroyGlyphCache(void)
80 pixman_glyph_cache_destroy (glyphCache
);
86 fbUnrealizeGlyph(ScreenPtr pScreen
,
90 pixman_glyph_cache_remove (glyphCache
, pGlyph
, NULL
);
97 PictFormatPtr maskFormat
,
99 INT16 ySrc
, int nlist
,
103 #define N_STACK_GLYPHS 512
104 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
105 pixman_glyph_t stack_glyphs
[N_STACK_GLYPHS
];
106 pixman_glyph_t
*pglyphs
= stack_glyphs
;
107 pixman_image_t
*srcImage
, *dstImage
;
108 int srcXoff
, srcYoff
, dstXoff
, dstYoff
;
113 int xDst
= list
->xOff
, yDst
= list
->yOff
;
115 miCompositeSourceValidate(pSrc
);
118 for (i
= 0; i
< nlist
; ++i
)
119 n_glyphs
+= list
[i
].len
;
122 glyphCache
= pixman_glyph_cache_create();
124 pixman_glyph_cache_freeze (glyphCache
);
126 if (n_glyphs
> N_STACK_GLYPHS
) {
127 if (!(pglyphs
= malloc (n_glyphs
* sizeof (pixman_glyph_t
))))
142 if (!(g
= pixman_glyph_cache_lookup (glyphCache
, glyph
, NULL
))) {
143 pixman_image_t
*glyphImage
;
147 pPicture
= GetGlyphPicture(glyph
, pScreen
);
153 if (!(glyphImage
= image_from_pict(pPicture
, FALSE
, &xoff
, &yoff
)))
156 g
= pixman_glyph_cache_insert(glyphCache
, glyph
, NULL
,
161 free_pixman_pict(pPicture
, glyphImage
);
169 pglyphs
[i
].glyph
= g
;
173 x
+= glyph
->info
.xOff
;
174 y
+= glyph
->info
.yOff
;
179 if (!(srcImage
= image_from_pict(pSrc
, FALSE
, &srcXoff
, &srcYoff
)))
182 if (!(dstImage
= image_from_pict(pDst
, TRUE
, &dstXoff
, &dstYoff
)))
186 pixman_format_code_t format
;
187 pixman_box32_t extents
;
189 format
= maskFormat
->format
| (maskFormat
->depth
<< 24);
191 pixman_glyph_get_extents(glyphCache
, n_glyphs
, pglyphs
, &extents
);
193 pixman_composite_glyphs(op
, srcImage
, dstImage
, format
,
194 xSrc
+ srcXoff
+ xDst
, ySrc
+ srcYoff
+ yDst
,
195 extents
.x1
, extents
.y1
,
196 extents
.x1
+ dstXoff
, extents
.y1
+ dstYoff
,
197 extents
.x2
- extents
.x1
,
198 extents
.y2
- extents
.y1
,
199 glyphCache
, n_glyphs
, pglyphs
);
202 pixman_composite_glyphs_no_mask(op
, srcImage
, dstImage
,
203 xSrc
+ srcXoff
- xDst
, ySrc
+ srcYoff
- yDst
,
205 glyphCache
, n_glyphs
, pglyphs
);
208 free_pixman_pict(pDst
, dstImage
);
211 free_pixman_pict(pSrc
, srcImage
);
214 pixman_glyph_cache_thaw(glyphCache
);
215 if (pglyphs
!= stack_glyphs
)
219 static pixman_image_t
*
220 create_solid_fill_image(PicturePtr pict
)
222 PictSolidFill
*solid
= &pict
->pSourcePict
->solidFill
;
223 pixman_color_t color
;
226 a
= (solid
->color
& 0xff000000) >> 24;
227 r
= (solid
->color
& 0x00ff0000) >> 16;
228 g
= (solid
->color
& 0x0000ff00) >> 8;
229 b
= (solid
->color
& 0x000000ff) >> 0;
231 color
.alpha
= (a
<< 8) | a
;
232 color
.red
= (r
<< 8) | r
;
233 color
.green
= (g
<< 8) | g
;
234 color
.blue
= (b
<< 8) | b
;
236 return pixman_image_create_solid_fill(&color
);
239 static pixman_image_t
*
240 create_linear_gradient_image(PictGradient
* gradient
)
242 PictLinearGradient
*linear
= (PictLinearGradient
*) gradient
;
243 pixman_point_fixed_t p1
;
244 pixman_point_fixed_t p2
;
251 return pixman_image_create_linear_gradient(&p1
, &p2
,
252 (pixman_gradient_stop_t
*)
257 static pixman_image_t
*
258 create_radial_gradient_image(PictGradient
* gradient
)
260 PictRadialGradient
*radial
= (PictRadialGradient
*) gradient
;
261 pixman_point_fixed_t c1
;
262 pixman_point_fixed_t c2
;
269 return pixman_image_create_radial_gradient(&c1
, &c2
, radial
->c1
.radius
,
271 (pixman_gradient_stop_t
*)
276 static pixman_image_t
*
277 create_conical_gradient_image(PictGradient
* gradient
)
279 PictConicalGradient
*conical
= (PictConicalGradient
*) gradient
;
280 pixman_point_fixed_t center
;
282 center
.x
= conical
->center
.x
;
283 center
.y
= conical
->center
.y
;
285 return pixman_image_create_conical_gradient(¢er
, conical
->angle
,
286 (pixman_gradient_stop_t
*)
291 static pixman_image_t
*
292 create_bits_picture(PicturePtr pict
, Bool has_clip
, int *xoff
, int *yoff
)
298 pixman_image_t
*image
;
300 fbGetDrawablePixmap(pict
->pDrawable
, pixmap
, *xoff
, *yoff
);
301 fbGetPixmapBitsData(pixmap
, bits
, stride
, bpp
);
303 image
= pixman_image_create_bits((pixman_format_code_t
) pict
->format
,
304 pixmap
->drawable
.width
,
305 pixmap
->drawable
.height
, (uint32_t *) bits
,
306 stride
* sizeof(FbStride
));
311 #ifdef FB_ACCESS_WRAPPER
314 pixman_image_set_accessors(image
,
315 (pixman_read_memory_func_t
) wfbReadMemory
,
316 (pixman_write_memory_func_t
) wfbWriteMemory
);
320 #error The pixman library only works when FbBits is 32 bits wide
325 /* pCompositeClip is undefined for source pictures, so
326 * only set the clip region for pictures with drawables
329 if (pict
->clientClipType
!= CT_NONE
)
330 pixman_image_set_has_client_clip(image
, TRUE
);
333 pixman_region_translate(pict
->pCompositeClip
, *xoff
, *yoff
);
335 pixman_image_set_clip_region(image
, pict
->pCompositeClip
);
338 pixman_region_translate(pict
->pCompositeClip
, -*xoff
, -*yoff
);
342 if (pict
->pFormat
->index
.devPrivate
)
343 pixman_image_set_indexed(image
, pict
->pFormat
->index
.devPrivate
);
345 /* Add in drawable origin to position within the image */
346 *xoff
+= pict
->pDrawable
->x
;
347 *yoff
+= pict
->pDrawable
->y
;
352 static pixman_image_t
*image_from_pict_internal(PicturePtr pict
, Bool has_clip
,
353 int *xoff
, int *yoff
,
357 set_image_properties(pixman_image_t
* image
, PicturePtr pict
, Bool has_clip
,
358 int *xoff
, int *yoff
, Bool is_alpha_map
)
360 pixman_repeat_t repeat
;
361 pixman_filter_t filter
;
363 if (pict
->transform
) {
364 /* For source images, adjust the transform to account
365 * for the drawable offset within the pixman image,
366 * then set the offset to 0 as it will be used
367 * to compute positions within the transformed image.
370 struct pixman_transform adjusted
;
372 adjusted
= *pict
->transform
;
373 pixman_transform_translate(&adjusted
,
375 pixman_int_to_fixed(*xoff
),
376 pixman_int_to_fixed(*yoff
));
377 pixman_image_set_transform(image
, &adjusted
);
382 pixman_image_set_transform(image
, pict
->transform
);
385 switch (pict
->repeatType
) {
388 repeat
= PIXMAN_REPEAT_NONE
;
392 repeat
= PIXMAN_REPEAT_PAD
;
396 repeat
= PIXMAN_REPEAT_NORMAL
;
400 repeat
= PIXMAN_REPEAT_REFLECT
;
404 pixman_image_set_repeat(image
, repeat
);
406 /* Fetch alpha map unless 'pict' is being used
407 * as the alpha map for this operation
409 if (pict
->alphaMap
&& !is_alpha_map
) {
410 int alpha_xoff
, alpha_yoff
;
411 pixman_image_t
*alpha_map
=
412 image_from_pict_internal(pict
->alphaMap
, FALSE
, &alpha_xoff
,
415 pixman_image_set_alpha_map(image
, alpha_map
, pict
->alphaOrigin
.x
,
416 pict
->alphaOrigin
.y
);
418 free_pixman_pict(pict
->alphaMap
, alpha_map
);
421 pixman_image_set_component_alpha(image
, pict
->componentAlpha
);
423 switch (pict
->filter
) {
425 case PictFilterNearest
:
427 filter
= PIXMAN_FILTER_NEAREST
;
430 case PictFilterBilinear
:
432 filter
= PIXMAN_FILTER_BILINEAR
;
435 case PictFilterConvolution
:
436 filter
= PIXMAN_FILTER_CONVOLUTION
;
440 pixman_image_set_filter(image
, filter
,
441 (pixman_fixed_t
*) pict
->filter_params
,
442 pict
->filter_nparams
);
443 pixman_image_set_source_clipping(image
, TRUE
);
446 static pixman_image_t
*
447 image_from_pict_internal(PicturePtr pict
, Bool has_clip
, int *xoff
, int *yoff
,
450 pixman_image_t
*image
= NULL
;
455 if (pict
->pDrawable
) {
456 image
= create_bits_picture(pict
, has_clip
, xoff
, yoff
);
458 else if (pict
->pSourcePict
) {
459 SourcePict
*sp
= pict
->pSourcePict
;
461 if (sp
->type
== SourcePictTypeSolidFill
) {
462 image
= create_solid_fill_image(pict
);
465 PictGradient
*gradient
= &pict
->pSourcePict
->gradient
;
467 if (sp
->type
== SourcePictTypeLinear
)
468 image
= create_linear_gradient_image(gradient
);
469 else if (sp
->type
== SourcePictTypeRadial
)
470 image
= create_radial_gradient_image(gradient
);
471 else if (sp
->type
== SourcePictTypeConical
)
472 image
= create_conical_gradient_image(gradient
);
478 set_image_properties(image
, pict
, has_clip
, xoff
, yoff
, is_alpha_map
);
484 image_from_pict(PicturePtr pict
, Bool has_clip
, int *xoff
, int *yoff
)
486 return image_from_pict_internal(pict
, has_clip
, xoff
, yoff
, FALSE
);
490 free_pixman_pict(PicturePtr pict
, pixman_image_t
* image
)
492 if (image
&& pixman_image_unref(image
) && pict
->pDrawable
)
493 fbFinishAccess(pict
->pDrawable
);
497 fbPictureInit(ScreenPtr pScreen
, PictFormatPtr formats
, int nformats
)
502 if (!miPictureInit(pScreen
, formats
, nformats
))
504 ps
= GetPictureScreen(pScreen
);
505 ps
->Composite
= fbComposite
;
506 ps
->Glyphs
= fbGlyphs
;
507 ps
->UnrealizeGlyph
= fbUnrealizeGlyph
;
508 ps
->CompositeRects
= miCompositeRects
;
509 ps
->RasterizeTrapezoid
= fbRasterizeTrapezoid
;
510 ps
->Trapezoids
= fbTrapezoids
;
511 ps
->AddTraps
= fbAddTraps
;
512 ps
->AddTriangles
= fbAddTriangles
;
513 ps
->Triangles
= fbTriangles
;