1706f2543Smrg/* 2706f2543Smrg * 3706f2543Smrg * Copyright © 2000 SuSE, Inc. 4706f2543Smrg * Copyright © 2007 Red Hat, Inc. 5706f2543Smrg * 6706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 7706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 8706f2543Smrg * the above copyright notice appear in all copies and that both that 9706f2543Smrg * copyright notice and this permission notice appear in supporting 10706f2543Smrg * documentation, and that the name of SuSE not be used in advertising or 11706f2543Smrg * publicity pertaining to distribution of the software without specific, 12706f2543Smrg * written prior permission. SuSE makes no representations about the 13706f2543Smrg * suitability of this software for any purpose. It is provided "as is" 14706f2543Smrg * without express or implied warranty. 15706f2543Smrg * 16706f2543Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 17706f2543Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 18706f2543Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19706f2543Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 20706f2543Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 21706f2543Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22706f2543Smrg * 23706f2543Smrg * Author: Keith Packard, SuSE, Inc. 24706f2543Smrg */ 25706f2543Smrg 26706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 27706f2543Smrg#include <dix-config.h> 28706f2543Smrg#endif 29706f2543Smrg 30706f2543Smrg#include <string.h> 31706f2543Smrg 32706f2543Smrg#include "fb.h" 33706f2543Smrg 34706f2543Smrg#include "picturestr.h" 35706f2543Smrg#include "mipict.h" 36706f2543Smrg#include "fbpict.h" 37706f2543Smrg 38706f2543Smrgvoid 39706f2543SmrgfbComposite (CARD8 op, 40706f2543Smrg PicturePtr pSrc, 41706f2543Smrg PicturePtr pMask, 42706f2543Smrg PicturePtr pDst, 43706f2543Smrg INT16 xSrc, 44706f2543Smrg INT16 ySrc, 45706f2543Smrg INT16 xMask, 46706f2543Smrg INT16 yMask, 47706f2543Smrg INT16 xDst, 48706f2543Smrg INT16 yDst, 49706f2543Smrg CARD16 width, 50706f2543Smrg CARD16 height) 51706f2543Smrg{ 52706f2543Smrg pixman_image_t *src, *mask, *dest; 53706f2543Smrg int src_xoff, src_yoff; 54706f2543Smrg int msk_xoff, msk_yoff; 55706f2543Smrg int dst_xoff, dst_yoff; 56706f2543Smrg 57706f2543Smrg miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height); 58706f2543Smrg if (pMask) 59706f2543Smrg miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height); 60706f2543Smrg 61706f2543Smrg src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff); 62706f2543Smrg mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff); 63706f2543Smrg dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff); 64706f2543Smrg 65706f2543Smrg if (src && dest && !(pMask && !mask)) 66706f2543Smrg { 67706f2543Smrg pixman_image_composite (op, src, mask, dest, 68706f2543Smrg xSrc + src_xoff, ySrc + src_yoff, 69706f2543Smrg xMask + msk_xoff, yMask + msk_yoff, 70706f2543Smrg xDst + dst_xoff, yDst + dst_yoff, 71706f2543Smrg width, height); 72706f2543Smrg } 73706f2543Smrg 74706f2543Smrg free_pixman_pict (pSrc, src); 75706f2543Smrg free_pixman_pict (pMask, mask); 76706f2543Smrg free_pixman_pict (pDst, dest); 77706f2543Smrg} 78706f2543Smrg 79706f2543Smrgstatic pixman_image_t * 80706f2543Smrgcreate_solid_fill_image (PicturePtr pict) 81706f2543Smrg{ 82706f2543Smrg PictSolidFill *solid = &pict->pSourcePict->solidFill; 83706f2543Smrg pixman_color_t color; 84706f2543Smrg CARD32 a, r, g, b; 85706f2543Smrg 86706f2543Smrg a = (solid->color & 0xff000000) >> 24; 87706f2543Smrg r = (solid->color & 0x00ff0000) >> 16; 88706f2543Smrg g = (solid->color & 0x0000ff00) >> 8; 89706f2543Smrg b = (solid->color & 0x000000ff) >> 0; 90706f2543Smrg 91706f2543Smrg color.alpha = (a << 8) | a; 92706f2543Smrg color.red = (r << 8) | r; 93706f2543Smrg color.green = (g << 8) | g; 94706f2543Smrg color.blue = (b << 8) | b; 95706f2543Smrg 96706f2543Smrg return pixman_image_create_solid_fill (&color); 97706f2543Smrg} 98706f2543Smrg 99706f2543Smrgstatic pixman_image_t * 100706f2543Smrgcreate_linear_gradient_image (PictGradient *gradient) 101706f2543Smrg{ 102706f2543Smrg PictLinearGradient *linear = (PictLinearGradient *)gradient; 103706f2543Smrg pixman_point_fixed_t p1; 104706f2543Smrg pixman_point_fixed_t p2; 105706f2543Smrg 106706f2543Smrg p1.x = linear->p1.x; 107706f2543Smrg p1.y = linear->p1.y; 108706f2543Smrg p2.x = linear->p2.x; 109706f2543Smrg p2.y = linear->p2.y; 110706f2543Smrg 111706f2543Smrg return pixman_image_create_linear_gradient ( 112706f2543Smrg &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrgstatic pixman_image_t * 116706f2543Smrgcreate_radial_gradient_image (PictGradient *gradient) 117706f2543Smrg{ 118706f2543Smrg PictRadialGradient *radial = (PictRadialGradient *)gradient; 119706f2543Smrg pixman_point_fixed_t c1; 120706f2543Smrg pixman_point_fixed_t c2; 121706f2543Smrg 122706f2543Smrg c1.x = radial->c1.x; 123706f2543Smrg c1.y = radial->c1.y; 124706f2543Smrg c2.x = radial->c2.x; 125706f2543Smrg c2.y = radial->c2.y; 126706f2543Smrg 127706f2543Smrg return pixman_image_create_radial_gradient ( 128706f2543Smrg &c1, &c2, radial->c1.radius, 129706f2543Smrg radial->c2.radius, 130706f2543Smrg (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); 131706f2543Smrg} 132706f2543Smrg 133706f2543Smrgstatic pixman_image_t * 134706f2543Smrgcreate_conical_gradient_image (PictGradient *gradient) 135706f2543Smrg{ 136706f2543Smrg PictConicalGradient *conical = (PictConicalGradient *)gradient; 137706f2543Smrg pixman_point_fixed_t center; 138706f2543Smrg 139706f2543Smrg center.x = conical->center.x; 140706f2543Smrg center.y = conical->center.y; 141706f2543Smrg 142706f2543Smrg return pixman_image_create_conical_gradient ( 143706f2543Smrg ¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops, 144706f2543Smrg gradient->nstops); 145706f2543Smrg} 146706f2543Smrg 147706f2543Smrgstatic pixman_image_t * 148706f2543Smrgcreate_bits_picture (PicturePtr pict, 149706f2543Smrg Bool has_clip, 150706f2543Smrg int *xoff, 151706f2543Smrg int *yoff) 152706f2543Smrg{ 153706f2543Smrg PixmapPtr pixmap; 154706f2543Smrg FbBits *bits; 155706f2543Smrg FbStride stride; 156706f2543Smrg int bpp; 157706f2543Smrg pixman_image_t *image; 158706f2543Smrg 159706f2543Smrg fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff); 160706f2543Smrg fbGetPixmapBitsData(pixmap, bits, stride, bpp); 161706f2543Smrg 162706f2543Smrg image = pixman_image_create_bits ( 163706f2543Smrg pict->format, 164706f2543Smrg pixmap->drawable.width, pixmap->drawable.height, 165706f2543Smrg (uint32_t *)bits, stride * sizeof (FbStride)); 166706f2543Smrg 167706f2543Smrg if (!image) 168706f2543Smrg return NULL; 169706f2543Smrg 170706f2543Smrg#ifdef FB_ACCESS_WRAPPER 171706f2543Smrg#if FB_SHIFT==5 172706f2543Smrg 173706f2543Smrg pixman_image_set_accessors (image, 174706f2543Smrg (pixman_read_memory_func_t)wfbReadMemory, 175706f2543Smrg (pixman_write_memory_func_t)wfbWriteMemory); 176706f2543Smrg 177706f2543Smrg#else 178706f2543Smrg 179706f2543Smrg#error The pixman library only works when FbBits is 32 bits wide 180706f2543Smrg 181706f2543Smrg#endif 182706f2543Smrg#endif 183706f2543Smrg 184706f2543Smrg /* pCompositeClip is undefined for source pictures, so 185706f2543Smrg * only set the clip region for pictures with drawables 186706f2543Smrg */ 187706f2543Smrg if (has_clip) 188706f2543Smrg { 189706f2543Smrg if (pict->clientClipType != CT_NONE) 190706f2543Smrg pixman_image_set_has_client_clip (image, TRUE); 191706f2543Smrg 192706f2543Smrg if (*xoff || *yoff) 193706f2543Smrg pixman_region_translate (pict->pCompositeClip, *xoff, *yoff); 194706f2543Smrg 195706f2543Smrg pixman_image_set_clip_region (image, pict->pCompositeClip); 196706f2543Smrg 197706f2543Smrg if (*xoff || *yoff) 198706f2543Smrg pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff); 199706f2543Smrg } 200706f2543Smrg 201706f2543Smrg /* Indexed table */ 202706f2543Smrg if (pict->pFormat->index.devPrivate) 203706f2543Smrg pixman_image_set_indexed (image, pict->pFormat->index.devPrivate); 204706f2543Smrg 205706f2543Smrg /* Add in drawable origin to position within the image */ 206706f2543Smrg *xoff += pict->pDrawable->x; 207706f2543Smrg *yoff += pict->pDrawable->y; 208706f2543Smrg 209706f2543Smrg return image; 210706f2543Smrg} 211706f2543Smrg 212706f2543Smrgstatic pixman_image_t * 213706f2543Smrgimage_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map); 214706f2543Smrg 215706f2543Smrgstatic void 216706f2543Smrgset_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) 217706f2543Smrg{ 218706f2543Smrg pixman_repeat_t repeat; 219706f2543Smrg pixman_filter_t filter; 220706f2543Smrg 221706f2543Smrg if (pict->transform) 222706f2543Smrg { 223706f2543Smrg /* For source images, adjust the transform to account 224706f2543Smrg * for the drawable offset within the pixman image, 225706f2543Smrg * then set the offset to 0 as it will be used 226706f2543Smrg * to compute positions within the transformed image. 227706f2543Smrg */ 228706f2543Smrg if (!has_clip) { 229706f2543Smrg struct pixman_transform adjusted; 230706f2543Smrg 231706f2543Smrg adjusted = *pict->transform; 232706f2543Smrg pixman_transform_translate(&adjusted, 233706f2543Smrg NULL, 234706f2543Smrg pixman_int_to_fixed(*xoff), 235706f2543Smrg pixman_int_to_fixed(*yoff)); 236706f2543Smrg pixman_image_set_transform (image, &adjusted); 237706f2543Smrg *xoff = 0; 238706f2543Smrg *yoff = 0; 239706f2543Smrg } else 240706f2543Smrg pixman_image_set_transform (image, pict->transform); 241706f2543Smrg } 242706f2543Smrg 243706f2543Smrg switch (pict->repeatType) 244706f2543Smrg { 245706f2543Smrg default: 246706f2543Smrg case RepeatNone: 247706f2543Smrg repeat = PIXMAN_REPEAT_NONE; 248706f2543Smrg break; 249706f2543Smrg 250706f2543Smrg case RepeatPad: 251706f2543Smrg repeat = PIXMAN_REPEAT_PAD; 252706f2543Smrg break; 253706f2543Smrg 254706f2543Smrg case RepeatNormal: 255706f2543Smrg repeat = PIXMAN_REPEAT_NORMAL; 256706f2543Smrg break; 257706f2543Smrg 258706f2543Smrg case RepeatReflect: 259706f2543Smrg repeat = PIXMAN_REPEAT_REFLECT; 260706f2543Smrg break; 261706f2543Smrg } 262706f2543Smrg 263706f2543Smrg pixman_image_set_repeat (image, repeat); 264706f2543Smrg 265706f2543Smrg /* Fetch alpha map unless 'pict' is being used 266706f2543Smrg * as the alpha map for this operation 267706f2543Smrg */ 268706f2543Smrg if (pict->alphaMap && !is_alpha_map) 269706f2543Smrg { 270706f2543Smrg int alpha_xoff, alpha_yoff; 271706f2543Smrg pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE); 272706f2543Smrg 273706f2543Smrg pixman_image_set_alpha_map ( 274706f2543Smrg image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y); 275706f2543Smrg 276706f2543Smrg free_pixman_pict (pict->alphaMap, alpha_map); 277706f2543Smrg } 278706f2543Smrg 279706f2543Smrg pixman_image_set_component_alpha (image, pict->componentAlpha); 280706f2543Smrg 281706f2543Smrg switch (pict->filter) 282706f2543Smrg { 283706f2543Smrg default: 284706f2543Smrg case PictFilterNearest: 285706f2543Smrg case PictFilterFast: 286706f2543Smrg filter = PIXMAN_FILTER_NEAREST; 287706f2543Smrg break; 288706f2543Smrg 289706f2543Smrg case PictFilterBilinear: 290706f2543Smrg case PictFilterGood: 291706f2543Smrg filter = PIXMAN_FILTER_BILINEAR; 292706f2543Smrg break; 293706f2543Smrg 294706f2543Smrg case PictFilterConvolution: 295706f2543Smrg filter = PIXMAN_FILTER_CONVOLUTION; 296706f2543Smrg break; 297706f2543Smrg } 298706f2543Smrg 299706f2543Smrg pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams); 300706f2543Smrg pixman_image_set_source_clipping (image, TRUE); 301706f2543Smrg} 302706f2543Smrg 303706f2543Smrgstatic pixman_image_t * 304706f2543Smrgimage_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) 305706f2543Smrg{ 306706f2543Smrg pixman_image_t *image = NULL; 307706f2543Smrg 308706f2543Smrg if (!pict) 309706f2543Smrg return NULL; 310706f2543Smrg 311706f2543Smrg if (pict->pDrawable) 312706f2543Smrg { 313706f2543Smrg image = create_bits_picture (pict, has_clip, xoff, yoff); 314706f2543Smrg } 315706f2543Smrg else if (pict->pSourcePict) 316706f2543Smrg { 317706f2543Smrg SourcePict *sp = pict->pSourcePict; 318706f2543Smrg 319706f2543Smrg if (sp->type == SourcePictTypeSolidFill) 320706f2543Smrg { 321706f2543Smrg image = create_solid_fill_image (pict); 322706f2543Smrg } 323706f2543Smrg else 324706f2543Smrg { 325706f2543Smrg PictGradient *gradient = &pict->pSourcePict->gradient; 326706f2543Smrg 327706f2543Smrg if (sp->type == SourcePictTypeLinear) 328706f2543Smrg image = create_linear_gradient_image (gradient); 329706f2543Smrg else if (sp->type == SourcePictTypeRadial) 330706f2543Smrg image = create_radial_gradient_image (gradient); 331706f2543Smrg else if (sp->type == SourcePictTypeConical) 332706f2543Smrg image = create_conical_gradient_image (gradient); 333706f2543Smrg } 334706f2543Smrg *xoff = *yoff = 0; 335706f2543Smrg } 336706f2543Smrg 337706f2543Smrg if (image) 338706f2543Smrg set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map); 339706f2543Smrg 340706f2543Smrg return image; 341706f2543Smrg} 342706f2543Smrg 343706f2543Smrgpixman_image_t * 344706f2543Smrgimage_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff) 345706f2543Smrg{ 346706f2543Smrg return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE); 347706f2543Smrg} 348706f2543Smrg 349706f2543Smrgvoid 350706f2543Smrgfree_pixman_pict (PicturePtr pict, pixman_image_t *image) 351706f2543Smrg{ 352706f2543Smrg if (image && pixman_image_unref (image) && pict->pDrawable) 353706f2543Smrg fbFinishAccess (pict->pDrawable); 354706f2543Smrg} 355706f2543Smrg 356706f2543SmrgBool 357706f2543SmrgfbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) 358706f2543Smrg{ 359706f2543Smrg 360706f2543Smrg PictureScreenPtr ps; 361706f2543Smrg 362706f2543Smrg if (!miPictureInit (pScreen, formats, nformats)) 363706f2543Smrg return FALSE; 364706f2543Smrg ps = GetPictureScreen(pScreen); 365706f2543Smrg ps->Composite = fbComposite; 366706f2543Smrg ps->Glyphs = miGlyphs; 367706f2543Smrg ps->CompositeRects = miCompositeRects; 368706f2543Smrg ps->RasterizeTrapezoid = fbRasterizeTrapezoid; 369706f2543Smrg ps->AddTraps = fbAddTraps; 370706f2543Smrg ps->AddTriangles = fbAddTriangles; 371706f2543Smrg 372706f2543Smrg return TRUE; 373706f2543Smrg} 374