fbpict.c revision 03b705cf
103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 2000 SuSE, Inc. 303b705cfSriastradh * Copyright © 2007 Red Hat, Inc. 403b705cfSriastradh * Copyright © 2012 Intel Corporation 503b705cfSriastradh * 603b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its 703b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that 803b705cfSriastradh * the above copyright notice appear in all copies and that both that 903b705cfSriastradh * copyright notice and this permission notice appear in supporting 1003b705cfSriastradh * documentation, and that the name of SuSE not be used in advertising or 1103b705cfSriastradh * publicity pertaining to distribution of the software without specific, 1203b705cfSriastradh * written prior permission. SuSE makes no representations about the 1303b705cfSriastradh * suitability of this software for any purpose. It is provided "as is" 1403b705cfSriastradh * without express or implied warranty. 1503b705cfSriastradh * 1603b705cfSriastradh * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1703b705cfSriastradh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 1803b705cfSriastradh * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1903b705cfSriastradh * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 2003b705cfSriastradh * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2103b705cfSriastradh * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2203b705cfSriastradh * 2303b705cfSriastradh * Author: Keith Packard, SuSE, Inc. 2403b705cfSriastradh */ 2503b705cfSriastradh 2603b705cfSriastradh#include <string.h> 2703b705cfSriastradh 2803b705cfSriastradh#include "fb.h" 2903b705cfSriastradh#include "fbpict.h" 3003b705cfSriastradh 3103b705cfSriastradhstatic void 3203b705cfSriastradhSourceValidateOnePicture(PicturePtr picture) 3303b705cfSriastradh{ 3403b705cfSriastradh DrawablePtr drawable = picture->pDrawable; 3503b705cfSriastradh 3603b705cfSriastradh if (!drawable) 3703b705cfSriastradh return; 3803b705cfSriastradh 3903b705cfSriastradh SourceValidate(drawable, 4003b705cfSriastradh 0, 0, drawable->width, drawable->height, 4103b705cfSriastradh picture->subWindowMode); 4203b705cfSriastradh} 4303b705cfSriastradh 4403b705cfSriastradhstatic void 4503b705cfSriastradhfbCompositeSourceValidate(PicturePtr picture) 4603b705cfSriastradh{ 4703b705cfSriastradh SourceValidateOnePicture(picture); 4803b705cfSriastradh if (picture->alphaMap) 4903b705cfSriastradh SourceValidateOnePicture(picture->alphaMap); 5003b705cfSriastradh} 5103b705cfSriastradh 5203b705cfSriastradhvoid 5303b705cfSriastradhfbComposite(CARD8 op, 5403b705cfSriastradh PicturePtr pSrc, 5503b705cfSriastradh PicturePtr pMask, 5603b705cfSriastradh PicturePtr pDst, 5703b705cfSriastradh INT16 xSrc, 5803b705cfSriastradh INT16 ySrc, 5903b705cfSriastradh INT16 xMask, 6003b705cfSriastradh INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 6103b705cfSriastradh{ 6203b705cfSriastradh pixman_image_t *src, *mask, *dest; 6303b705cfSriastradh int src_xoff, src_yoff; 6403b705cfSriastradh int msk_xoff, msk_yoff; 6503b705cfSriastradh int dst_xoff, dst_yoff; 6603b705cfSriastradh 6703b705cfSriastradh fbCompositeSourceValidate(pSrc); 6803b705cfSriastradh if (pMask) 6903b705cfSriastradh fbCompositeSourceValidate(pMask); 7003b705cfSriastradh 7103b705cfSriastradh src = image_from_pict(pSrc, FALSE, &src_xoff, &src_yoff); 7203b705cfSriastradh mask = image_from_pict(pMask, FALSE, &msk_xoff, &msk_yoff); 7303b705cfSriastradh dest = image_from_pict(pDst, TRUE, &dst_xoff, &dst_yoff); 7403b705cfSriastradh 7503b705cfSriastradh if (src && dest && !(pMask && !mask)) { 7603b705cfSriastradh pixman_image_composite(op, src, mask, dest, 7703b705cfSriastradh xSrc + src_xoff, ySrc + src_yoff, 7803b705cfSriastradh xMask + msk_xoff, yMask + msk_yoff, 7903b705cfSriastradh xDst + dst_xoff, yDst + dst_yoff, width, height); 8003b705cfSriastradh } 8103b705cfSriastradh 8203b705cfSriastradh free_pixman_pict(pSrc, src); 8303b705cfSriastradh free_pixman_pict(pMask, mask); 8403b705cfSriastradh free_pixman_pict(pDst, dest); 8503b705cfSriastradh} 8603b705cfSriastradh 8703b705cfSriastradhstatic pixman_image_t * 8803b705cfSriastradhcreate_solid_fill_image(PicturePtr pict) 8903b705cfSriastradh{ 9003b705cfSriastradh PictSolidFill *solid = &pict->pSourcePict->solidFill; 9103b705cfSriastradh pixman_color_t color; 9203b705cfSriastradh CARD32 a, r, g, b; 9303b705cfSriastradh 9403b705cfSriastradh a = (solid->color & 0xff000000) >> 24; 9503b705cfSriastradh r = (solid->color & 0x00ff0000) >> 16; 9603b705cfSriastradh g = (solid->color & 0x0000ff00) >> 8; 9703b705cfSriastradh b = (solid->color & 0x000000ff) >> 0; 9803b705cfSriastradh 9903b705cfSriastradh color.alpha = (a << 8) | a; 10003b705cfSriastradh color.red = (r << 8) | r; 10103b705cfSriastradh color.green = (g << 8) | g; 10203b705cfSriastradh color.blue = (b << 8) | b; 10303b705cfSriastradh 10403b705cfSriastradh return pixman_image_create_solid_fill(&color); 10503b705cfSriastradh} 10603b705cfSriastradh 10703b705cfSriastradhstatic pixman_image_t * 10803b705cfSriastradhcreate_linear_gradient_image(PictGradient * gradient) 10903b705cfSriastradh{ 11003b705cfSriastradh PictLinearGradient *linear = (PictLinearGradient *) gradient; 11103b705cfSriastradh pixman_point_fixed_t p1; 11203b705cfSriastradh pixman_point_fixed_t p2; 11303b705cfSriastradh 11403b705cfSriastradh p1.x = linear->p1.x; 11503b705cfSriastradh p1.y = linear->p1.y; 11603b705cfSriastradh p2.x = linear->p2.x; 11703b705cfSriastradh p2.y = linear->p2.y; 11803b705cfSriastradh 11903b705cfSriastradh return pixman_image_create_linear_gradient(&p1, &p2, 12003b705cfSriastradh (pixman_gradient_stop_t *) 12103b705cfSriastradh gradient->stops, 12203b705cfSriastradh gradient->nstops); 12303b705cfSriastradh} 12403b705cfSriastradh 12503b705cfSriastradhstatic pixman_image_t * 12603b705cfSriastradhcreate_radial_gradient_image(PictGradient * gradient) 12703b705cfSriastradh{ 12803b705cfSriastradh PictRadialGradient *radial = (PictRadialGradient *) gradient; 12903b705cfSriastradh pixman_point_fixed_t c1; 13003b705cfSriastradh pixman_point_fixed_t c2; 13103b705cfSriastradh 13203b705cfSriastradh c1.x = radial->c1.x; 13303b705cfSriastradh c1.y = radial->c1.y; 13403b705cfSriastradh c2.x = radial->c2.x; 13503b705cfSriastradh c2.y = radial->c2.y; 13603b705cfSriastradh 13703b705cfSriastradh return pixman_image_create_radial_gradient(&c1, &c2, radial->c1.radius, 13803b705cfSriastradh radial->c2.radius, 13903b705cfSriastradh (pixman_gradient_stop_t *) 14003b705cfSriastradh gradient->stops, 14103b705cfSriastradh gradient->nstops); 14203b705cfSriastradh} 14303b705cfSriastradh 14403b705cfSriastradhstatic pixman_image_t * 14503b705cfSriastradhcreate_conical_gradient_image(PictGradient * gradient) 14603b705cfSriastradh{ 14703b705cfSriastradh PictConicalGradient *conical = (PictConicalGradient *) gradient; 14803b705cfSriastradh pixman_point_fixed_t center; 14903b705cfSriastradh 15003b705cfSriastradh center.x = conical->center.x; 15103b705cfSriastradh center.y = conical->center.y; 15203b705cfSriastradh 15303b705cfSriastradh return pixman_image_create_conical_gradient(¢er, conical->angle, 15403b705cfSriastradh (pixman_gradient_stop_t *) 15503b705cfSriastradh gradient->stops, 15603b705cfSriastradh gradient->nstops); 15703b705cfSriastradh} 15803b705cfSriastradh 15903b705cfSriastradhstatic pixman_image_t * 16003b705cfSriastradhcreate_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff) 16103b705cfSriastradh{ 16203b705cfSriastradh PixmapPtr pixmap; 16303b705cfSriastradh FbBits *bits; 16403b705cfSriastradh FbStride stride; 16503b705cfSriastradh int bpp; 16603b705cfSriastradh pixman_image_t *image; 16703b705cfSriastradh 16803b705cfSriastradh fbGetDrawablePixmap(pict->pDrawable, pixmap, *xoff, *yoff); 16903b705cfSriastradh fbGetPixmapBitsData(pixmap, bits, stride, bpp); 17003b705cfSriastradh 17103b705cfSriastradh image = pixman_image_create_bits((pixman_format_code_t) pict->format, 17203b705cfSriastradh pixmap->drawable.width, 17303b705cfSriastradh pixmap->drawable.height, (uint32_t *) bits, 17403b705cfSriastradh stride * sizeof(FbStride)); 17503b705cfSriastradh 17603b705cfSriastradh if (!image) 17703b705cfSriastradh return NULL; 17803b705cfSriastradh 17903b705cfSriastradh /* pCompositeClip is undefined for source pictures, so 18003b705cfSriastradh * only set the clip region for pictures with drawables 18103b705cfSriastradh */ 18203b705cfSriastradh if (has_clip) { 18303b705cfSriastradh if (pict->clientClipType != CT_NONE) 18403b705cfSriastradh pixman_image_set_has_client_clip(image, TRUE); 18503b705cfSriastradh 18603b705cfSriastradh if (*xoff || *yoff) 18703b705cfSriastradh pixman_region_translate(pict->pCompositeClip, *xoff, *yoff); 18803b705cfSriastradh 18903b705cfSriastradh pixman_image_set_clip_region(image, pict->pCompositeClip); 19003b705cfSriastradh 19103b705cfSriastradh if (*xoff || *yoff) 19203b705cfSriastradh pixman_region_translate(pict->pCompositeClip, -*xoff, -*yoff); 19303b705cfSriastradh } 19403b705cfSriastradh 19503b705cfSriastradh /* Indexed table */ 19603b705cfSriastradh if (pict->pFormat->index.devPrivate) 19703b705cfSriastradh pixman_image_set_indexed(image, pict->pFormat->index.devPrivate); 19803b705cfSriastradh 19903b705cfSriastradh /* Add in drawable origin to position within the image */ 20003b705cfSriastradh *xoff += pict->pDrawable->x; 20103b705cfSriastradh *yoff += pict->pDrawable->y; 20203b705cfSriastradh 20303b705cfSriastradh return image; 20403b705cfSriastradh} 20503b705cfSriastradh 20603b705cfSriastradhstatic pixman_image_t *image_from_pict_internal(PicturePtr pict, Bool has_clip, 20703b705cfSriastradh int *xoff, int *yoff, 20803b705cfSriastradh Bool is_alpha_map); 20903b705cfSriastradh 21003b705cfSriastradhstatic void 21103b705cfSriastradhset_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip, 21203b705cfSriastradh int *xoff, int *yoff, Bool is_alpha_map) 21303b705cfSriastradh{ 21403b705cfSriastradh pixman_repeat_t repeat; 21503b705cfSriastradh pixman_filter_t filter; 21603b705cfSriastradh 21703b705cfSriastradh if (pict->transform) { 21803b705cfSriastradh /* For source images, adjust the transform to account 21903b705cfSriastradh * for the drawable offset within the pixman image, 22003b705cfSriastradh * then set the offset to 0 as it will be used 22103b705cfSriastradh * to compute positions within the transformed image. 22203b705cfSriastradh */ 22303b705cfSriastradh if (!has_clip) { 22403b705cfSriastradh struct pixman_transform adjusted; 22503b705cfSriastradh 22603b705cfSriastradh adjusted = *pict->transform; 22703b705cfSriastradh pixman_transform_translate(&adjusted, 22803b705cfSriastradh NULL, 22903b705cfSriastradh pixman_int_to_fixed(*xoff), 23003b705cfSriastradh pixman_int_to_fixed(*yoff)); 23103b705cfSriastradh pixman_image_set_transform(image, &adjusted); 23203b705cfSriastradh *xoff = 0; 23303b705cfSriastradh *yoff = 0; 23403b705cfSriastradh } 23503b705cfSriastradh else 23603b705cfSriastradh pixman_image_set_transform(image, pict->transform); 23703b705cfSriastradh } 23803b705cfSriastradh 23903b705cfSriastradh switch (pict->repeatType) { 24003b705cfSriastradh default: 24103b705cfSriastradh case RepeatNone: 24203b705cfSriastradh repeat = PIXMAN_REPEAT_NONE; 24303b705cfSriastradh break; 24403b705cfSriastradh 24503b705cfSriastradh case RepeatPad: 24603b705cfSriastradh repeat = PIXMAN_REPEAT_PAD; 24703b705cfSriastradh break; 24803b705cfSriastradh 24903b705cfSriastradh case RepeatNormal: 25003b705cfSriastradh repeat = PIXMAN_REPEAT_NORMAL; 25103b705cfSriastradh break; 25203b705cfSriastradh 25303b705cfSriastradh case RepeatReflect: 25403b705cfSriastradh repeat = PIXMAN_REPEAT_REFLECT; 25503b705cfSriastradh break; 25603b705cfSriastradh } 25703b705cfSriastradh 25803b705cfSriastradh pixman_image_set_repeat(image, repeat); 25903b705cfSriastradh 26003b705cfSriastradh /* Fetch alpha map unless 'pict' is being used 26103b705cfSriastradh * as the alpha map for this operation 26203b705cfSriastradh */ 26303b705cfSriastradh if (pict->alphaMap && !is_alpha_map) { 26403b705cfSriastradh int alpha_xoff, alpha_yoff; 26503b705cfSriastradh pixman_image_t *alpha_map = 26603b705cfSriastradh image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff, 26703b705cfSriastradh &alpha_yoff, TRUE); 26803b705cfSriastradh 26903b705cfSriastradh pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x, 27003b705cfSriastradh pict->alphaOrigin.y); 27103b705cfSriastradh 27203b705cfSriastradh free_pixman_pict(pict->alphaMap, alpha_map); 27303b705cfSriastradh } 27403b705cfSriastradh 27503b705cfSriastradh pixman_image_set_component_alpha(image, pict->componentAlpha); 27603b705cfSriastradh 27703b705cfSriastradh switch (pict->filter) { 27803b705cfSriastradh default: 27903b705cfSriastradh case PictFilterNearest: 28003b705cfSriastradh case PictFilterFast: 28103b705cfSriastradh filter = PIXMAN_FILTER_NEAREST; 28203b705cfSriastradh break; 28303b705cfSriastradh 28403b705cfSriastradh case PictFilterBilinear: 28503b705cfSriastradh case PictFilterGood: 28603b705cfSriastradh filter = PIXMAN_FILTER_BILINEAR; 28703b705cfSriastradh break; 28803b705cfSriastradh 28903b705cfSriastradh case PictFilterConvolution: 29003b705cfSriastradh filter = PIXMAN_FILTER_CONVOLUTION; 29103b705cfSriastradh break; 29203b705cfSriastradh } 29303b705cfSriastradh 29403b705cfSriastradh pixman_image_set_filter(image, filter, 29503b705cfSriastradh (pixman_fixed_t *) pict->filter_params, 29603b705cfSriastradh pict->filter_nparams); 29703b705cfSriastradh pixman_image_set_source_clipping(image, TRUE); 29803b705cfSriastradh} 29903b705cfSriastradh 30003b705cfSriastradhstatic pixman_image_t * 30103b705cfSriastradhimage_from_pict_internal(PicturePtr pict, Bool has_clip, int *xoff, int *yoff, 30203b705cfSriastradh Bool is_alpha_map) 30303b705cfSriastradh{ 30403b705cfSriastradh pixman_image_t *image = NULL; 30503b705cfSriastradh 30603b705cfSriastradh if (!pict) 30703b705cfSriastradh return NULL; 30803b705cfSriastradh 30903b705cfSriastradh if (pict->pDrawable) { 31003b705cfSriastradh image = create_bits_picture(pict, has_clip, xoff, yoff); 31103b705cfSriastradh } 31203b705cfSriastradh else if (pict->pSourcePict) { 31303b705cfSriastradh SourcePict *sp = pict->pSourcePict; 31403b705cfSriastradh 31503b705cfSriastradh if (sp->type == SourcePictTypeSolidFill) { 31603b705cfSriastradh image = create_solid_fill_image(pict); 31703b705cfSriastradh } 31803b705cfSriastradh else { 31903b705cfSriastradh PictGradient *gradient = &pict->pSourcePict->gradient; 32003b705cfSriastradh 32103b705cfSriastradh if (sp->type == SourcePictTypeLinear) 32203b705cfSriastradh image = create_linear_gradient_image(gradient); 32303b705cfSriastradh else if (sp->type == SourcePictTypeRadial) 32403b705cfSriastradh image = create_radial_gradient_image(gradient); 32503b705cfSriastradh else if (sp->type == SourcePictTypeConical) 32603b705cfSriastradh image = create_conical_gradient_image(gradient); 32703b705cfSriastradh } 32803b705cfSriastradh *xoff = *yoff = 0; 32903b705cfSriastradh } 33003b705cfSriastradh 33103b705cfSriastradh if (image) 33203b705cfSriastradh set_image_properties(image, pict, has_clip, xoff, yoff, is_alpha_map); 33303b705cfSriastradh 33403b705cfSriastradh return image; 33503b705cfSriastradh} 33603b705cfSriastradh 33703b705cfSriastradhpixman_image_t * 33803b705cfSriastradhimage_from_pict(PicturePtr pict, Bool has_clip, int *xoff, int *yoff) 33903b705cfSriastradh{ 34003b705cfSriastradh return image_from_pict_internal(pict, has_clip, xoff, yoff, FALSE); 34103b705cfSriastradh} 34203b705cfSriastradh 34303b705cfSriastradhvoid 34403b705cfSriastradhfree_pixman_pict(PicturePtr pict, pixman_image_t * image) 34503b705cfSriastradh{ 34603b705cfSriastradh if (image) 34703b705cfSriastradh pixman_image_unref(image); 34803b705cfSriastradh} 349