1fa225cbcSrjs/* 2fa225cbcSrjs * Copyright © 2001 Keith Packard 3fa225cbcSrjs * 4fa225cbcSrjs * Partly based on code that is Copyright © The XFree86 Project Inc. 5fa225cbcSrjs * 6fa225cbcSrjs * Permission to use, copy, modify, distribute, and sell this software and its 7fa225cbcSrjs * documentation for any purpose is hereby granted without fee, provided that 8fa225cbcSrjs * the above copyright notice appear in all copies and that both that 9fa225cbcSrjs * copyright notice and this permission notice appear in supporting 10fa225cbcSrjs * documentation, and that the name of Keith Packard not be used in 11fa225cbcSrjs * advertising or publicity pertaining to distribution of the software without 12fa225cbcSrjs * specific, written prior permission. Keith Packard makes no 13fa225cbcSrjs * representations about the suitability of this software for any purpose. It 14fa225cbcSrjs * is provided "as is" without express or implied warranty. 15fa225cbcSrjs * 16fa225cbcSrjs * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17fa225cbcSrjs * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18fa225cbcSrjs * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19fa225cbcSrjs * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20fa225cbcSrjs * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21fa225cbcSrjs * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22fa225cbcSrjs * PERFORMANCE OF THIS SOFTWARE. 23fa225cbcSrjs */ 24fa225cbcSrjs 25fa225cbcSrjs#ifdef HAVE_DIX_CONFIG_H 26fa225cbcSrjs#include <dix-config.h> 27fa225cbcSrjs#endif 28fa225cbcSrjs 29fa225cbcSrjs#include <stdlib.h> 30fa225cbcSrjs 31fa225cbcSrjs#include "uxa-priv.h" 32fa225cbcSrjs#include <xorgVersion.h> 33fa225cbcSrjs 34fa225cbcSrjs#ifdef RENDER 35fa225cbcSrjs#include "mipict.h" 36fa225cbcSrjs 37fa225cbcSrjsstatic void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, int n) 38fa225cbcSrjs{ 39fa225cbcSrjs char format[20]; 40fa225cbcSrjs char size[20]; 41fa225cbcSrjs char loc; 42fa225cbcSrjs 43fa225cbcSrjs if (!pict) { 44fa225cbcSrjs snprintf(string, n, "None"); 45fa225cbcSrjs return; 46fa225cbcSrjs } 47fa225cbcSrjs 48fa225cbcSrjs if (pict->pDrawable == NULL) { 49fa225cbcSrjs snprintf(string, n, "source-only"); 50fa225cbcSrjs return; 51fa225cbcSrjs } 52fa225cbcSrjs 53fa225cbcSrjs switch (pict->format) 54fa225cbcSrjs { 55fa225cbcSrjs case PICT_a8r8g8b8: 56fa225cbcSrjs snprintf(format, 20, "ARGB8888"); 57fa225cbcSrjs break; 58fa225cbcSrjs case PICT_x8r8g8b8: 59fa225cbcSrjs snprintf(format, 20, "XRGB8888"); 60fa225cbcSrjs break; 61fa225cbcSrjs case PICT_r5g6b5: 62fa225cbcSrjs snprintf(format, 20, "RGB565 "); 63fa225cbcSrjs break; 64fa225cbcSrjs case PICT_x1r5g5b5: 65fa225cbcSrjs snprintf(format, 20, "RGB555 "); 66fa225cbcSrjs break; 67fa225cbcSrjs case PICT_a8: 68fa225cbcSrjs snprintf(format, 20, "A8 "); 69fa225cbcSrjs break; 70fa225cbcSrjs case PICT_a1: 71fa225cbcSrjs snprintf(format, 20, "A1 "); 72fa225cbcSrjs break; 73fa225cbcSrjs default: 74fa225cbcSrjs snprintf(format, 20, "0x%x", (int)pict->format); 75fa225cbcSrjs break; 76fa225cbcSrjs } 77fa225cbcSrjs 78fa225cbcSrjs loc = uxa_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm'; 79fa225cbcSrjs 80fa225cbcSrjs snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, 81fa225cbcSrjs pict->pDrawable->height, pict->repeat ? 82fa225cbcSrjs " R" : ""); 83fa225cbcSrjs 84fa225cbcSrjs snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size); 85fa225cbcSrjs} 86fa225cbcSrjs 87fa225cbcSrjsstatic void 88fa225cbcSrjsuxa_print_composite_fallback(CARD8 op, 89fa225cbcSrjs PicturePtr pSrc, 90fa225cbcSrjs PicturePtr pMask, 91fa225cbcSrjs PicturePtr pDst) 92fa225cbcSrjs{ 93fa225cbcSrjs char sop[20]; 94fa225cbcSrjs char srcdesc[40], maskdesc[40], dstdesc[40]; 95fa225cbcSrjs 96fa225cbcSrjs switch(op) 97fa225cbcSrjs { 98fa225cbcSrjs case PictOpSrc: 99fa225cbcSrjs sprintf(sop, "Src"); 100fa225cbcSrjs break; 101fa225cbcSrjs case PictOpOver: 102fa225cbcSrjs sprintf(sop, "Over"); 103fa225cbcSrjs break; 104fa225cbcSrjs default: 105fa225cbcSrjs sprintf(sop, "0x%x", (int)op); 106fa225cbcSrjs break; 107fa225cbcSrjs } 108fa225cbcSrjs 109fa225cbcSrjs uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40); 110fa225cbcSrjs uxa_composite_fallback_pict_desc(pMask, maskdesc, 40); 111fa225cbcSrjs uxa_composite_fallback_pict_desc(pDst, dstdesc, 40); 112fa225cbcSrjs 113fa225cbcSrjs ErrorF("Composite fallback: op %s, \n" 114fa225cbcSrjs " src %s, \n" 115fa225cbcSrjs " mask %s, \n" 116fa225cbcSrjs " dst %s, \n", 117fa225cbcSrjs sop, srcdesc, maskdesc, dstdesc); 118fa225cbcSrjs} 119fa225cbcSrjs 120fa225cbcSrjsBool 121fa225cbcSrjsuxa_op_reads_destination (CARD8 op) 122fa225cbcSrjs{ 123fa225cbcSrjs /* FALSE (does not read destination) is the list of ops in the protocol 124fa225cbcSrjs * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. 125fa225cbcSrjs * That's just Clear and Src. ReduceCompositeOp() will already have 126fa225cbcSrjs * converted con/disjoint clear/src to Clear or Src. 127fa225cbcSrjs */ 128fa225cbcSrjs switch (op) { 129fa225cbcSrjs case PictOpClear: 130fa225cbcSrjs case PictOpSrc: 131fa225cbcSrjs return FALSE; 132fa225cbcSrjs default: 133fa225cbcSrjs return TRUE; 134fa225cbcSrjs } 135fa225cbcSrjs} 136fa225cbcSrjs 137fa225cbcSrjs 138fa225cbcSrjsstatic Bool 139fa225cbcSrjsuxa_get_pixel_from_rgba(CARD32 *pixel, 140fa225cbcSrjs CARD16 red, 141fa225cbcSrjs CARD16 green, 142fa225cbcSrjs CARD16 blue, 143fa225cbcSrjs CARD16 alpha, 144fa225cbcSrjs CARD32 format) 145fa225cbcSrjs{ 146fa225cbcSrjs int rbits, bbits, gbits, abits; 147fa225cbcSrjs int rshift, bshift, gshift, ashift; 148fa225cbcSrjs 149fa225cbcSrjs *pixel = 0; 150fa225cbcSrjs 151fa225cbcSrjs if (!PICT_FORMAT_COLOR(format)) 152fa225cbcSrjs return FALSE; 153fa225cbcSrjs 154fa225cbcSrjs rbits = PICT_FORMAT_R(format); 155fa225cbcSrjs gbits = PICT_FORMAT_G(format); 156fa225cbcSrjs bbits = PICT_FORMAT_B(format); 157fa225cbcSrjs abits = PICT_FORMAT_A(format); 158fa225cbcSrjs 159fa225cbcSrjs if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 160fa225cbcSrjs bshift = 0; 161fa225cbcSrjs gshift = bbits; 162fa225cbcSrjs rshift = gshift + gbits; 163fa225cbcSrjs ashift = rshift + rbits; 164fa225cbcSrjs } else { /* PICT_TYPE_ABGR */ 165fa225cbcSrjs rshift = 0; 166fa225cbcSrjs gshift = rbits; 167fa225cbcSrjs bshift = gshift + gbits; 168fa225cbcSrjs ashift = bshift + bbits; 169fa225cbcSrjs } 170fa225cbcSrjs 171fa225cbcSrjs *pixel |= ( blue >> (16 - bbits)) << bshift; 172fa225cbcSrjs *pixel |= ( red >> (16 - rbits)) << rshift; 173fa225cbcSrjs *pixel |= (green >> (16 - gbits)) << gshift; 174fa225cbcSrjs *pixel |= (alpha >> (16 - abits)) << ashift; 175fa225cbcSrjs 176fa225cbcSrjs return TRUE; 177fa225cbcSrjs} 178fa225cbcSrjs 179fa225cbcSrjsstatic Bool 180fa225cbcSrjsuxa_get_rgba_from_pixel(CARD32 pixel, 181fa225cbcSrjs CARD16 *red, 182fa225cbcSrjs CARD16 *green, 183fa225cbcSrjs CARD16 *blue, 184fa225cbcSrjs CARD16 *alpha, 185fa225cbcSrjs CARD32 format) 186fa225cbcSrjs{ 187fa225cbcSrjs int rbits, bbits, gbits, abits; 188fa225cbcSrjs int rshift, bshift, gshift, ashift; 189fa225cbcSrjs 190fa225cbcSrjs if (!PICT_FORMAT_COLOR(format)) 191fa225cbcSrjs return FALSE; 192fa225cbcSrjs 193fa225cbcSrjs rbits = PICT_FORMAT_R(format); 194fa225cbcSrjs gbits = PICT_FORMAT_G(format); 195fa225cbcSrjs bbits = PICT_FORMAT_B(format); 196fa225cbcSrjs abits = PICT_FORMAT_A(format); 197fa225cbcSrjs 198fa225cbcSrjs if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 199fa225cbcSrjs bshift = 0; 200fa225cbcSrjs gshift = bbits; 201fa225cbcSrjs rshift = gshift + gbits; 202fa225cbcSrjs ashift = rshift + rbits; 203fa225cbcSrjs } else { /* PICT_TYPE_ABGR */ 204fa225cbcSrjs rshift = 0; 205fa225cbcSrjs gshift = rbits; 206fa225cbcSrjs bshift = gshift + gbits; 207fa225cbcSrjs ashift = bshift + bbits; 208fa225cbcSrjs } 209fa225cbcSrjs 210fa225cbcSrjs *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits); 211fa225cbcSrjs while (rbits < 16) { 212fa225cbcSrjs *red |= *red >> rbits; 213fa225cbcSrjs rbits <<= 1; 214fa225cbcSrjs } 215fa225cbcSrjs 216fa225cbcSrjs *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits); 217fa225cbcSrjs while (gbits < 16) { 218fa225cbcSrjs *green |= *green >> gbits; 219fa225cbcSrjs gbits <<= 1; 220fa225cbcSrjs } 221fa225cbcSrjs 222fa225cbcSrjs *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits); 223fa225cbcSrjs while (bbits < 16) { 224fa225cbcSrjs *blue |= *blue >> bbits; 225fa225cbcSrjs bbits <<= 1; 226fa225cbcSrjs } 227fa225cbcSrjs 228fa225cbcSrjs if (abits) { 229fa225cbcSrjs *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits); 230fa225cbcSrjs while (abits < 16) { 231fa225cbcSrjs *alpha |= *alpha >> abits; 232fa225cbcSrjs abits <<= 1; 233fa225cbcSrjs } 234fa225cbcSrjs } else 235fa225cbcSrjs *alpha = 0xffff; 236fa225cbcSrjs 237fa225cbcSrjs return TRUE; 238fa225cbcSrjs} 239fa225cbcSrjs 240fa225cbcSrjsstatic int 241fa225cbcSrjsuxa_try_driver_solid_fill(PicturePtr pSrc, 242fa225cbcSrjs PicturePtr pDst, 243fa225cbcSrjs INT16 xSrc, 244fa225cbcSrjs INT16 ySrc, 245fa225cbcSrjs INT16 xDst, 246fa225cbcSrjs INT16 yDst, 247fa225cbcSrjs CARD16 width, 248fa225cbcSrjs CARD16 height) 249fa225cbcSrjs{ 250fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 251fa225cbcSrjs RegionRec region; 252fa225cbcSrjs BoxPtr pbox; 253fa225cbcSrjs int nbox; 254fa225cbcSrjs int dst_off_x, dst_off_y; 255fa225cbcSrjs PixmapPtr pSrcPix, pDstPix; 256fa225cbcSrjs CARD32 pixel; 257fa225cbcSrjs CARD16 red, green, blue, alpha; 258fa225cbcSrjs 259fa225cbcSrjs pDstPix = uxa_get_drawable_pixmap (pDst->pDrawable); 260fa225cbcSrjs pSrcPix = uxa_get_drawable_pixmap (pSrc->pDrawable); 261fa225cbcSrjs 262fa225cbcSrjs xDst += pDst->pDrawable->x; 263fa225cbcSrjs yDst += pDst->pDrawable->y; 264fa225cbcSrjs xSrc += pSrc->pDrawable->x; 265fa225cbcSrjs ySrc += pSrc->pDrawable->y; 266fa225cbcSrjs 267fa225cbcSrjs if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, 268fa225cbcSrjs xSrc, ySrc, 0, 0, xDst, yDst, 269fa225cbcSrjs width, height)) 270fa225cbcSrjs return 1; 271fa225cbcSrjs 272fa225cbcSrjs uxa_get_drawable_deltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); 273fa225cbcSrjs 274fa225cbcSrjs REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); 275fa225cbcSrjs 276fa225cbcSrjs pixel = uxa_get_pixmap_first_pixel (pSrcPix); 277fa225cbcSrjs 278fa225cbcSrjs if (!uxa_pixmap_is_offscreen(pDstPix)) { 279fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 280fa225cbcSrjs return 0; 281fa225cbcSrjs } 282fa225cbcSrjs 283fa225cbcSrjs if (!uxa_get_rgba_from_pixel(pixel, &red, &green, &blue, &alpha, 284fa225cbcSrjs pSrc->format)) 285fa225cbcSrjs { 286fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 287fa225cbcSrjs return -1; 288fa225cbcSrjs } 289fa225cbcSrjs 290fa225cbcSrjs if (!uxa_get_pixel_from_rgba(&pixel, red, green, blue, alpha, 291fa225cbcSrjs pDst->format)) 292fa225cbcSrjs { 293fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 294fa225cbcSrjs return -1; 295fa225cbcSrjs } 296fa225cbcSrjs 297fa225cbcSrjs if (!(*uxa_screen->info->prepare_solid) (pDstPix, GXcopy, 0xffffffff, pixel)) 298fa225cbcSrjs { 299fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 300fa225cbcSrjs return -1; 301fa225cbcSrjs } 302fa225cbcSrjs 303fa225cbcSrjs nbox = REGION_NUM_RECTS(®ion); 304fa225cbcSrjs pbox = REGION_RECTS(®ion); 305fa225cbcSrjs 306fa225cbcSrjs while (nbox--) 307fa225cbcSrjs { 308fa225cbcSrjs (*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2); 309fa225cbcSrjs pbox++; 310fa225cbcSrjs } 311fa225cbcSrjs 312fa225cbcSrjs (*uxa_screen->info->done_solid) (pDstPix); 313fa225cbcSrjs 314fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 315fa225cbcSrjs return 1; 316fa225cbcSrjs} 317fa225cbcSrjs 318fa225cbcSrjs/* In order to avoid fallbacks when using an a1 source/mask, 319fa225cbcSrjs * for example with non-antialiased trapezoids, we need to 320fa225cbcSrjs * expand the bitmap into an a8 Picture. We do so by using the generic 321fa225cbcSrjs * composition routines, which while may not be perfect is far faster 322fa225cbcSrjs * than causing a fallback. 323fa225cbcSrjs */ 324fa225cbcSrjsstatic PicturePtr 325fa225cbcSrjsuxa_picture_from_a1_pixman_image (ScreenPtr pScreen, 326fa225cbcSrjs pixman_image_t *image) 327fa225cbcSrjs{ 328fa225cbcSrjs PicturePtr pPicture; 329fa225cbcSrjs PicturePtr pSrc; 330fa225cbcSrjs PixmapPtr pPixmap; 331fa225cbcSrjs int width, height; 332fa225cbcSrjs int error; 333fa225cbcSrjs 334fa225cbcSrjs width = pixman_image_get_width (image); 335fa225cbcSrjs height = pixman_image_get_height (image); 336fa225cbcSrjs 337fa225cbcSrjs pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 8, 338fa225cbcSrjs UXA_CREATE_PIXMAP_FOR_MAP); 339fa225cbcSrjs if (!pPixmap) 340fa225cbcSrjs return 0; 341fa225cbcSrjs 342fa225cbcSrjs pPicture = CreatePicture (0, &pPixmap->drawable, 343fa225cbcSrjs PictureMatchFormat (pScreen, 8, PICT_a8), 344fa225cbcSrjs 0, 0, serverClient, &error); 345fa225cbcSrjs (*pScreen->DestroyPixmap) (pPixmap); 346fa225cbcSrjs if (!pPicture) 347fa225cbcSrjs return 0; 348fa225cbcSrjs 349fa225cbcSrjs ValidatePicture (pPicture); 350fa225cbcSrjs 351fa225cbcSrjs pPixmap = GetScratchPixmapHeader(pScreen, width, height, 1, 352fa225cbcSrjs BitsPerPixel (1), 353fa225cbcSrjs pixman_image_get_stride (image), 354fa225cbcSrjs pixman_image_get_data (image)); 355fa225cbcSrjs if (!pPixmap) { 356fa225cbcSrjs FreePicture (pPicture, 0); 357fa225cbcSrjs return 0; 358fa225cbcSrjs } 359fa225cbcSrjs 360fa225cbcSrjs pSrc = CreatePicture (0, &pPixmap->drawable, 361fa225cbcSrjs PictureMatchFormat (pScreen, 1, PICT_a1), 362fa225cbcSrjs 0, 0, serverClient, &error); 363fa225cbcSrjs if (!pSrc) { 364fa225cbcSrjs FreeScratchPixmapHeader (pPixmap); 365fa225cbcSrjs FreePicture (pPicture, 0); 366fa225cbcSrjs return 0; 367fa225cbcSrjs } 368fa225cbcSrjs 369fa225cbcSrjs CompositePicture (PictOpSrc, pSrc, NULL, pPicture, 370fa225cbcSrjs 0, 0, 371fa225cbcSrjs 0, 0, 372fa225cbcSrjs 0, 0, 373fa225cbcSrjs width, height); 374fa225cbcSrjs 375fa225cbcSrjs FreePicture (pSrc, 0); 376fa225cbcSrjs FreeScratchPixmapHeader (pPixmap); 377fa225cbcSrjs 378fa225cbcSrjs return pPicture; 379fa225cbcSrjs} 380fa225cbcSrjs 381fa225cbcSrjsstatic PicturePtr 382fa225cbcSrjsuxa_picture_from_pixman_image (ScreenPtr pScreen, 383fa225cbcSrjs pixman_image_t *image, 384fa225cbcSrjs pixman_format_code_t format) 385fa225cbcSrjs{ 386fa225cbcSrjs PicturePtr pPicture; 387fa225cbcSrjs PixmapPtr pPixmap; 388fa225cbcSrjs GCPtr pGC; 389fa225cbcSrjs int width, height, depth; 390fa225cbcSrjs int error; 391fa225cbcSrjs 392fa225cbcSrjs if (format == PICT_a1) 393fa225cbcSrjs return uxa_picture_from_a1_pixman_image (pScreen, image); 394fa225cbcSrjs 395fa225cbcSrjs width = pixman_image_get_width (image); 396fa225cbcSrjs height = pixman_image_get_height (image); 397fa225cbcSrjs depth = pixman_image_get_depth (image); 398fa225cbcSrjs 399fa225cbcSrjs pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth, 400fa225cbcSrjs UXA_CREATE_PIXMAP_FOR_MAP); 401fa225cbcSrjs if (!pPixmap) 402fa225cbcSrjs return 0; 403fa225cbcSrjs 404fa225cbcSrjs pPicture = CreatePicture (0, &pPixmap->drawable, 405fa225cbcSrjs PictureMatchFormat (pScreen, depth, format), 406fa225cbcSrjs 0, 0, serverClient, &error); 407fa225cbcSrjs (*pScreen->DestroyPixmap) (pPixmap); 408fa225cbcSrjs if (!pPicture) 409fa225cbcSrjs return 0; 410fa225cbcSrjs 411fa225cbcSrjs ValidatePicture (pPicture); 412fa225cbcSrjs 413fa225cbcSrjs pPixmap = GetScratchPixmapHeader(pScreen, width, height, depth, 414fa225cbcSrjs BitsPerPixel (depth), 415fa225cbcSrjs pixman_image_get_stride (image), 416fa225cbcSrjs pixman_image_get_data (image)); 417fa225cbcSrjs if (!pPixmap) 418fa225cbcSrjs { 419fa225cbcSrjs FreePicture (pPicture, 0); 420fa225cbcSrjs return 0; 421fa225cbcSrjs } 422fa225cbcSrjs 423fa225cbcSrjs pGC = GetScratchGC (depth, pScreen); 424fa225cbcSrjs if (!pGC) 425fa225cbcSrjs { 426fa225cbcSrjs FreeScratchPixmapHeader (pPixmap); 427fa225cbcSrjs FreePicture (pPicture, 0); 428fa225cbcSrjs return 0; 429fa225cbcSrjs } 430fa225cbcSrjs ValidateGC (pPicture->pDrawable, pGC); 431fa225cbcSrjs 432fa225cbcSrjs (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable, 433fa225cbcSrjs pGC, 0, 0, width, height, 0, 0); 434fa225cbcSrjs 435fa225cbcSrjs FreeScratchGC (pGC); 436fa225cbcSrjs FreeScratchPixmapHeader (pPixmap); 437fa225cbcSrjs 438fa225cbcSrjs return pPicture; 439fa225cbcSrjs} 440fa225cbcSrjs 441fa225cbcSrjsstatic PicturePtr 442fa225cbcSrjsuxa_acquire_pattern (ScreenPtr pScreen, 443fa225cbcSrjs PicturePtr pPict, 444fa225cbcSrjs pixman_format_code_t format, 445fa225cbcSrjs INT16 x, INT16 y, 446fa225cbcSrjs CARD16 width, CARD16 height) 447fa225cbcSrjs{ 448fa225cbcSrjs pixman_image_t *source, *image; 449be514f52Srjs int src_xoff, src_yoff; 450be514f52Srjs 451be514f52Srjs source = image_from_pict(pPict, FALSE, &src_xoff, &src_yoff); 452fa225cbcSrjs if (!source) 453fa225cbcSrjs return 0; 454fa225cbcSrjs 455fa225cbcSrjs image = pixman_image_create_bits (format, width, height, NULL, 0); 456fa225cbcSrjs if (!image) { 457fa225cbcSrjs pixman_image_unref (source); 458fa225cbcSrjs return 0; 459fa225cbcSrjs } 460fa225cbcSrjs 461fa225cbcSrjs pixman_image_composite (PIXMAN_OP_SRC, 462fa225cbcSrjs source, NULL, image, 463fa225cbcSrjs x, y, 464fa225cbcSrjs 0, 0, 465fa225cbcSrjs 0, 0, 466fa225cbcSrjs width, height); 467fa225cbcSrjs pixman_image_unref (source); 468fa225cbcSrjs 469fa225cbcSrjs pPict = uxa_picture_from_pixman_image (pScreen, image, format); 470fa225cbcSrjs pixman_image_unref (image); 471fa225cbcSrjs 472fa225cbcSrjs return pPict; 473fa225cbcSrjs} 474fa225cbcSrjs 475fa225cbcSrjsstatic PicturePtr 476fa225cbcSrjsuxa_acquire_source (ScreenPtr pScreen, 477fa225cbcSrjs PicturePtr pPict, 478fa225cbcSrjs INT16 x, INT16 y, 479fa225cbcSrjs CARD16 width, CARD16 height, 480fa225cbcSrjs INT16 *out_x, INT16 *out_y) 481fa225cbcSrjs{ 482fa225cbcSrjs if (pPict->pDrawable) { 483fa225cbcSrjs *out_x = x + pPict->pDrawable->x; 484fa225cbcSrjs *out_y = y + pPict->pDrawable->y; 485fa225cbcSrjs return pPict; 486fa225cbcSrjs } 487fa225cbcSrjs 488fa225cbcSrjs *out_x = 0; 489fa225cbcSrjs *out_y = 0; 490fa225cbcSrjs return uxa_acquire_pattern (pScreen, pPict, 491fa225cbcSrjs PICT_a8r8g8b8, x, y, width, height); 492fa225cbcSrjs} 493fa225cbcSrjs 494fa225cbcSrjsstatic PicturePtr 495fa225cbcSrjsuxa_acquire_mask (ScreenPtr pScreen, 496fa225cbcSrjs PicturePtr pPict, 497fa225cbcSrjs INT16 x, INT16 y, 498fa225cbcSrjs INT16 width, INT16 height, 499fa225cbcSrjs INT16 *out_x, INT16 *out_y) 500fa225cbcSrjs{ 501fa225cbcSrjs if (pPict->pDrawable) { 502fa225cbcSrjs *out_x = x + pPict->pDrawable->x; 503fa225cbcSrjs *out_y = y + pPict->pDrawable->y; 504fa225cbcSrjs return pPict; 505fa225cbcSrjs } 506fa225cbcSrjs 507fa225cbcSrjs *out_x = 0; 508fa225cbcSrjs *out_y = 0; 509fa225cbcSrjs return uxa_acquire_pattern (pScreen, pPict, 510fa225cbcSrjs PICT_a8, x, y, width, height); 511fa225cbcSrjs} 512fa225cbcSrjs 513fa225cbcSrjsstatic int 514fa225cbcSrjsuxa_try_driver_composite_rects(CARD8 op, 515fa225cbcSrjs PicturePtr pSrc, 516fa225cbcSrjs PicturePtr pDst, 517fa225cbcSrjs int nrect, 518fa225cbcSrjs uxa_composite_rect_t *rects) 519fa225cbcSrjs{ 520fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 521fa225cbcSrjs int src_off_x, src_off_y, dst_off_x, dst_off_y; 522fa225cbcSrjs PixmapPtr pSrcPix, pDstPix; 523fa225cbcSrjs 524fa225cbcSrjs if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut) 525fa225cbcSrjs return -1; 526fa225cbcSrjs 527fa225cbcSrjs if (uxa_screen->info->check_composite && 528fa225cbcSrjs !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) 529fa225cbcSrjs { 530fa225cbcSrjs return -1; 531fa225cbcSrjs } 532fa225cbcSrjs 533fa225cbcSrjs pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); 534fa225cbcSrjs if (!pDstPix) 535fa225cbcSrjs return 0; 536fa225cbcSrjs 537fa225cbcSrjs pSrcPix = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); 538fa225cbcSrjs if (!pSrcPix) 539fa225cbcSrjs return 0; 540fa225cbcSrjs 541fa225cbcSrjs if (!(*uxa_screen->info->prepare_composite) (op, pSrc, NULL, pDst, pSrcPix, 542fa225cbcSrjs NULL, pDstPix)) 543fa225cbcSrjs return -1; 544fa225cbcSrjs 545fa225cbcSrjs while (nrect--) 546fa225cbcSrjs { 547fa225cbcSrjs INT16 xDst = rects->xDst + pDst->pDrawable->x; 548fa225cbcSrjs INT16 yDst = rects->yDst + pDst->pDrawable->y; 549fa225cbcSrjs INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; 550fa225cbcSrjs INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; 551fa225cbcSrjs 552fa225cbcSrjs RegionRec region; 553fa225cbcSrjs BoxPtr pbox; 554fa225cbcSrjs int nbox; 555fa225cbcSrjs 556fa225cbcSrjs if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, 557fa225cbcSrjs xSrc, ySrc, 0, 0, xDst, yDst, 558fa225cbcSrjs rects->width, rects->height)) 559fa225cbcSrjs goto next_rect; 560fa225cbcSrjs 561fa225cbcSrjs REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); 562fa225cbcSrjs 563fa225cbcSrjs nbox = REGION_NUM_RECTS(®ion); 564fa225cbcSrjs pbox = REGION_RECTS(®ion); 565fa225cbcSrjs 566fa225cbcSrjs xSrc = xSrc + src_off_x - xDst - dst_off_x; 567fa225cbcSrjs ySrc = ySrc + src_off_y - yDst - dst_off_y; 568fa225cbcSrjs 569fa225cbcSrjs while (nbox--) 570fa225cbcSrjs { 571fa225cbcSrjs (*uxa_screen->info->composite) (pDstPix, 572fa225cbcSrjs pbox->x1 + xSrc, 573fa225cbcSrjs pbox->y1 + ySrc, 574fa225cbcSrjs 0, 0, 575fa225cbcSrjs pbox->x1, 576fa225cbcSrjs pbox->y1, 577fa225cbcSrjs pbox->x2 - pbox->x1, 578fa225cbcSrjs pbox->y2 - pbox->y1); 579fa225cbcSrjs pbox++; 580fa225cbcSrjs } 581fa225cbcSrjs 582fa225cbcSrjs next_rect: 583fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 584fa225cbcSrjs 585fa225cbcSrjs rects++; 586fa225cbcSrjs } 587fa225cbcSrjs (*uxa_screen->info->done_composite) (pDstPix); 588fa225cbcSrjs 589fa225cbcSrjs return 1; 590fa225cbcSrjs} 591fa225cbcSrjs 592fa225cbcSrjs/** 593fa225cbcSrjs * Copy a number of rectangles from source to destination in a single 594fa225cbcSrjs * operation. This is specialized for building a glyph mask: we don'y 595fa225cbcSrjs * have a mask argument because we don't need it for that, and we 596fa225cbcSrjs * don't have he special-case fallbacks found in uxa_composite() - if the 597fa225cbcSrjs * driver can support it, we use the driver functionality, otherwise we 598fa225cbcSrjs * fallback straight to software. 599fa225cbcSrjs */ 600fa225cbcSrjsvoid 601fa225cbcSrjsuxa_composite_rects(CARD8 op, 602fa225cbcSrjs PicturePtr pSrc, 603fa225cbcSrjs PicturePtr pDst, 604fa225cbcSrjs int nrect, 605fa225cbcSrjs uxa_composite_rect_t *rects) 606fa225cbcSrjs{ 607fa225cbcSrjs int n; 608fa225cbcSrjs uxa_composite_rect_t *r; 609fa225cbcSrjs 610fa225cbcSrjs /************************************************************/ 611fa225cbcSrjs 612fa225cbcSrjs ValidatePicture (pSrc); 613fa225cbcSrjs ValidatePicture (pDst); 614fa225cbcSrjs 615fa225cbcSrjs if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) { 616fa225cbcSrjs n = nrect; 617fa225cbcSrjs r = rects; 618fa225cbcSrjs while (n--) { 619fa225cbcSrjs uxa_check_composite (op, pSrc, NULL, pDst, 620fa225cbcSrjs r->xSrc, r->ySrc, 621fa225cbcSrjs 0, 0, 622fa225cbcSrjs r->xDst, r->yDst, 623fa225cbcSrjs r->width, r->height); 624fa225cbcSrjs r++; 625fa225cbcSrjs } 626fa225cbcSrjs } 627fa225cbcSrjs 628fa225cbcSrjs /************************************************************/ 629fa225cbcSrjs 630fa225cbcSrjs} 631fa225cbcSrjs 632fa225cbcSrjsstatic int 633fa225cbcSrjsuxa_try_driver_composite(CARD8 op, 634fa225cbcSrjs PicturePtr pSrc, 635fa225cbcSrjs PicturePtr pMask, 636fa225cbcSrjs PicturePtr pDst, 637fa225cbcSrjs INT16 xSrc, 638fa225cbcSrjs INT16 ySrc, 639fa225cbcSrjs INT16 xMask, 640fa225cbcSrjs INT16 yMask, 641fa225cbcSrjs INT16 xDst, 642fa225cbcSrjs INT16 yDst, 643fa225cbcSrjs CARD16 width, 644fa225cbcSrjs CARD16 height) 645fa225cbcSrjs{ 646fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 647fa225cbcSrjs RegionRec region; 648fa225cbcSrjs BoxPtr pbox; 649fa225cbcSrjs int nbox; 650fa225cbcSrjs int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; 651fa225cbcSrjs PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; 652fa225cbcSrjs PicturePtr localSrc, localMask = NULL; 653fa225cbcSrjs 654fa225cbcSrjs xDst += pDst->pDrawable->x; 655fa225cbcSrjs yDst += pDst->pDrawable->y; 656fa225cbcSrjs 657fa225cbcSrjs localSrc = uxa_acquire_source (pDst->pDrawable->pScreen, 658fa225cbcSrjs pSrc, xSrc, ySrc, width, height, 659fa225cbcSrjs &xSrc, &ySrc); 660fa225cbcSrjs if (! localSrc) 661fa225cbcSrjs return 0; 662fa225cbcSrjs 663fa225cbcSrjs if (pMask) { 664fa225cbcSrjs localMask = uxa_acquire_mask (pDst->pDrawable->pScreen, 665fa225cbcSrjs pMask, xMask, yMask, width, height, 666fa225cbcSrjs &xMask, &yMask); 667fa225cbcSrjs if (! localMask) { 668fa225cbcSrjs if (localSrc != pSrc) 669fa225cbcSrjs FreePicture (localSrc, 0); 670fa225cbcSrjs 671fa225cbcSrjs return 0; 672fa225cbcSrjs } 673fa225cbcSrjs } 674fa225cbcSrjs 675fa225cbcSrjs if (uxa_screen->info->check_composite && 676fa225cbcSrjs !(*uxa_screen->info->check_composite) (op, localSrc, localMask, pDst)) 677fa225cbcSrjs { 678fa225cbcSrjs if (localSrc != pSrc) 679fa225cbcSrjs FreePicture (localSrc, 0); 680fa225cbcSrjs if (localMask && localMask != pMask) 681fa225cbcSrjs FreePicture (localMask, 0); 682fa225cbcSrjs 683fa225cbcSrjs return -1; 684fa225cbcSrjs } 685fa225cbcSrjs 686fa225cbcSrjs if (!miComputeCompositeRegion (®ion, localSrc, localMask, pDst, 687fa225cbcSrjs xSrc, ySrc, xMask, yMask, xDst, yDst, 688fa225cbcSrjs width, height)) 689fa225cbcSrjs { 690fa225cbcSrjs if (localSrc != pSrc) 691fa225cbcSrjs FreePicture (localSrc, 0); 692fa225cbcSrjs if (localMask && localMask != pMask) 693fa225cbcSrjs FreePicture (localMask, 0); 694fa225cbcSrjs 695fa225cbcSrjs return 1; 696fa225cbcSrjs } 697fa225cbcSrjs 698fa225cbcSrjs pDstPix = uxa_get_offscreen_pixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); 699fa225cbcSrjs 700fa225cbcSrjs pSrcPix = uxa_get_offscreen_pixmap (localSrc->pDrawable, 701fa225cbcSrjs &src_off_x, &src_off_y); 702fa225cbcSrjs 703fa225cbcSrjs if (localMask) 704fa225cbcSrjs pMaskPix = uxa_get_offscreen_pixmap (localMask->pDrawable, 705fa225cbcSrjs &mask_off_x, &mask_off_y); 706fa225cbcSrjs 707fa225cbcSrjs if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) { 708fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 709fa225cbcSrjs 710fa225cbcSrjs if (localSrc != pSrc) 711fa225cbcSrjs FreePicture (localSrc, 0); 712fa225cbcSrjs if (localMask && localMask != pMask) 713fa225cbcSrjs FreePicture (localMask, 0); 714fa225cbcSrjs 715fa225cbcSrjs return 0; 716fa225cbcSrjs } 717fa225cbcSrjs 718fa225cbcSrjs REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); 719fa225cbcSrjs 720fa225cbcSrjs if (!(*uxa_screen->info->prepare_composite) (op, localSrc, localMask, pDst, 721fa225cbcSrjs pSrcPix, pMaskPix, pDstPix)) 722fa225cbcSrjs { 723fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 724fa225cbcSrjs 725fa225cbcSrjs if (localSrc != pSrc) 726fa225cbcSrjs FreePicture (localSrc, 0); 727fa225cbcSrjs if (localMask && localMask != pMask) 728fa225cbcSrjs FreePicture (localMask, 0); 729fa225cbcSrjs 730fa225cbcSrjs return -1; 731fa225cbcSrjs } 732fa225cbcSrjs 733fa225cbcSrjs nbox = REGION_NUM_RECTS(®ion); 734fa225cbcSrjs pbox = REGION_RECTS(®ion); 735fa225cbcSrjs 736fa225cbcSrjs xMask = xMask + mask_off_x - xDst - dst_off_x; 737fa225cbcSrjs yMask = yMask + mask_off_y - yDst - dst_off_y; 738fa225cbcSrjs 739fa225cbcSrjs xSrc = xSrc + src_off_x - xDst - dst_off_x; 740fa225cbcSrjs ySrc = ySrc + src_off_y - yDst - dst_off_y; 741fa225cbcSrjs 742fa225cbcSrjs while (nbox--) 743fa225cbcSrjs { 744fa225cbcSrjs (*uxa_screen->info->composite) (pDstPix, 745fa225cbcSrjs pbox->x1 + xSrc, 746fa225cbcSrjs pbox->y1 + ySrc, 747fa225cbcSrjs pbox->x1 + xMask, 748fa225cbcSrjs pbox->y1 + yMask, 749fa225cbcSrjs pbox->x1, 750fa225cbcSrjs pbox->y1, 751fa225cbcSrjs pbox->x2 - pbox->x1, 752fa225cbcSrjs pbox->y2 - pbox->y1); 753fa225cbcSrjs pbox++; 754fa225cbcSrjs } 755fa225cbcSrjs (*uxa_screen->info->done_composite) (pDstPix); 756fa225cbcSrjs 757fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 758fa225cbcSrjs 759fa225cbcSrjs if (localSrc != pSrc) 760fa225cbcSrjs FreePicture (localSrc, 0); 761fa225cbcSrjs if (localMask && localMask != pMask) 762fa225cbcSrjs FreePicture (localMask, 0); 763fa225cbcSrjs 764fa225cbcSrjs return 1; 765fa225cbcSrjs} 766fa225cbcSrjs 767fa225cbcSrjs/** 768fa225cbcSrjs * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of 769fa225cbcSrjs * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component 770fa225cbcSrjs * alpha and limited 1-tmu cards. 771fa225cbcSrjs * 772fa225cbcSrjs * From http://anholt.livejournal.com/32058.html: 773fa225cbcSrjs * 774fa225cbcSrjs * The trouble is that component-alpha rendering requires two different sources 775fa225cbcSrjs * for blending: one for the source value to the blender, which is the 776fa225cbcSrjs * per-channel multiplication of source and mask, and one for the source alpha 777fa225cbcSrjs * for multiplying with the destination channels, which is the multiplication 778fa225cbcSrjs * of the source channels by the mask alpha. So the equation for Over is: 779fa225cbcSrjs * 780fa225cbcSrjs * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A 781fa225cbcSrjs * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R 782fa225cbcSrjs * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G 783fa225cbcSrjs * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B 784fa225cbcSrjs * 785fa225cbcSrjs * But we can do some simpler operations, right? How about PictOpOutReverse, 786fa225cbcSrjs * which has a source factor of 0 and dest factor of (1 - source alpha). We 787fa225cbcSrjs * can get the source alpha value (srca.X = src.A * mask.X) out of the texture 788fa225cbcSrjs * blenders pretty easily. So we can do a component-alpha OutReverse, which 789fa225cbcSrjs * gets us: 790fa225cbcSrjs * 791fa225cbcSrjs * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A 792fa225cbcSrjs * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R 793fa225cbcSrjs * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G 794fa225cbcSrjs * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B 795fa225cbcSrjs * 796fa225cbcSrjs * OK. And if an op doesn't use the source alpha value for the destination 797fa225cbcSrjs * factor, then we can do the channel multiplication in the texture blenders 798fa225cbcSrjs * to get the source value, and ignore the source alpha that we wouldn't use. 799fa225cbcSrjs * We've supported this in the Radeon driver for a long time. An example would 800fa225cbcSrjs * be PictOpAdd, which does: 801fa225cbcSrjs * 802fa225cbcSrjs * dst.A = src.A * mask.A + dst.A 803fa225cbcSrjs * dst.R = src.R * mask.R + dst.R 804fa225cbcSrjs * dst.G = src.G * mask.G + dst.G 805fa225cbcSrjs * dst.B = src.B * mask.B + dst.B 806fa225cbcSrjs * 807fa225cbcSrjs * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right 808fa225cbcSrjs * after it, we get: 809fa225cbcSrjs * 810fa225cbcSrjs * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) 811fa225cbcSrjs * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) 812fa225cbcSrjs * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) 813fa225cbcSrjs * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) 814fa225cbcSrjs */ 815fa225cbcSrjs 816fa225cbcSrjsstatic int 817fa225cbcSrjsuxa_try_magic_two_pass_composite_helper(CARD8 op, 818fa225cbcSrjs PicturePtr pSrc, 819fa225cbcSrjs PicturePtr pMask, 820fa225cbcSrjs PicturePtr pDst, 821fa225cbcSrjs INT16 xSrc, 822fa225cbcSrjs INT16 ySrc, 823fa225cbcSrjs INT16 xMask, 824fa225cbcSrjs INT16 yMask, 825fa225cbcSrjs INT16 xDst, 826fa225cbcSrjs INT16 yDst, 827fa225cbcSrjs CARD16 width, 828fa225cbcSrjs CARD16 height) 829fa225cbcSrjs{ 830fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 831fa225cbcSrjs 832fa225cbcSrjs assert(op == PictOpOver); 833fa225cbcSrjs 834fa225cbcSrjs if (uxa_screen->info->check_composite && 835fa225cbcSrjs (!(*uxa_screen->info->check_composite)(PictOpOutReverse, pSrc, pMask, 836fa225cbcSrjs pDst) || 837fa225cbcSrjs !(*uxa_screen->info->check_composite)(PictOpAdd, pSrc, pMask, pDst))) 838fa225cbcSrjs { 839fa225cbcSrjs return -1; 840fa225cbcSrjs } 841fa225cbcSrjs 842fa225cbcSrjs /* Now, we think we should be able to accelerate this operation. First, 843fa225cbcSrjs * composite the destination to be the destination times the source alpha 844fa225cbcSrjs * factors. 845fa225cbcSrjs */ 846fa225cbcSrjs uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, 847fa225cbcSrjs xDst, yDst, width, height); 848fa225cbcSrjs 849fa225cbcSrjs /* Then, add in the source value times the destination alpha factors (1.0). 850fa225cbcSrjs */ 851fa225cbcSrjs uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, 852fa225cbcSrjs xDst, yDst, width, height); 853fa225cbcSrjs 854fa225cbcSrjs return 1; 855fa225cbcSrjs} 856fa225cbcSrjs 857fa225cbcSrjsvoid 858fa225cbcSrjsuxa_composite(CARD8 op, 859fa225cbcSrjs PicturePtr pSrc, 860fa225cbcSrjs PicturePtr pMask, 861fa225cbcSrjs PicturePtr pDst, 862fa225cbcSrjs INT16 xSrc, 863fa225cbcSrjs INT16 ySrc, 864fa225cbcSrjs INT16 xMask, 865fa225cbcSrjs INT16 yMask, 866fa225cbcSrjs INT16 xDst, 867fa225cbcSrjs INT16 yDst, 868fa225cbcSrjs CARD16 width, 869fa225cbcSrjs CARD16 height) 870fa225cbcSrjs{ 871fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 872fa225cbcSrjs int ret = -1; 873fa225cbcSrjs Bool saveSrcRepeat = pSrc->repeat; 874fa225cbcSrjs Bool saveMaskRepeat = pMask ? pMask->repeat : 0; 875fa225cbcSrjs RegionRec region; 876fa225cbcSrjs 877fa225cbcSrjs if (uxa_screen->swappedOut) 878fa225cbcSrjs goto fallback; 879fa225cbcSrjs 880fa225cbcSrjs if (pSrc->pDrawable == NULL || (pMask && pMask->pDrawable == NULL)) 881fa225cbcSrjs goto composite; 882fa225cbcSrjs 883fa225cbcSrjs /* Remove repeat in source if useless */ 884fa225cbcSrjs if (pSrc->repeat && !pSrc->transform && xSrc >= 0 && 885fa225cbcSrjs (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 && 886fa225cbcSrjs (ySrc + height) <= pSrc->pDrawable->height) 887fa225cbcSrjs pSrc->repeat = 0; 888fa225cbcSrjs 889fa225cbcSrjs if (!pMask) 890fa225cbcSrjs { 891fa225cbcSrjs if ((op == PictOpSrc && 892fa225cbcSrjs ((pSrc->format == pDst->format) || 893fa225cbcSrjs (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || 894fa225cbcSrjs (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || 895fa225cbcSrjs (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && 896fa225cbcSrjs pSrc->format == pDst->format && 897fa225cbcSrjs (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8))) 898fa225cbcSrjs { 899fa225cbcSrjs if (pSrc->pDrawable->width == 1 && 900fa225cbcSrjs pSrc->pDrawable->height == 1 && 901fa225cbcSrjs pSrc->repeat) 902fa225cbcSrjs { 903fa225cbcSrjs ret = uxa_try_driver_solid_fill(pSrc, pDst, xSrc, ySrc, xDst, yDst, 904fa225cbcSrjs width, height); 905fa225cbcSrjs if (ret == 1) 906fa225cbcSrjs goto done; 907fa225cbcSrjs } 908fa225cbcSrjs else if (pSrc->pDrawable != NULL && 909fa225cbcSrjs !pSrc->repeat && 910fa225cbcSrjs !pSrc->transform) 911fa225cbcSrjs { 912fa225cbcSrjs xDst += pDst->pDrawable->x; 913fa225cbcSrjs yDst += pDst->pDrawable->y; 914fa225cbcSrjs xSrc += pSrc->pDrawable->x; 915fa225cbcSrjs ySrc += pSrc->pDrawable->y; 916fa225cbcSrjs 917fa225cbcSrjs if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, 918fa225cbcSrjs xSrc, ySrc, xMask, yMask, xDst, 919fa225cbcSrjs yDst, width, height)) 920fa225cbcSrjs goto done; 921fa225cbcSrjs 922fa225cbcSrjs 923fa225cbcSrjs uxa_copy_n_to_n (pSrc->pDrawable, pDst->pDrawable, NULL, 924fa225cbcSrjs REGION_RECTS(®ion), REGION_NUM_RECTS(®ion), 925fa225cbcSrjs xSrc - xDst, ySrc - yDst, 926fa225cbcSrjs FALSE, FALSE, 0, NULL); 927fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 928fa225cbcSrjs goto done; 929fa225cbcSrjs } 930fa225cbcSrjs else if (pSrc->pDrawable != NULL && 931fa225cbcSrjs pSrc->pDrawable->type == DRAWABLE_PIXMAP && 932fa225cbcSrjs !pSrc->transform && 933fa225cbcSrjs pSrc->repeatType == RepeatNormal) 934fa225cbcSrjs { 935fa225cbcSrjs DDXPointRec patOrg; 936fa225cbcSrjs 937fa225cbcSrjs /* Let's see if the driver can do the repeat in one go */ 938fa225cbcSrjs if (uxa_screen->info->prepare_composite && !pSrc->alphaMap && 939fa225cbcSrjs !pDst->alphaMap) 940fa225cbcSrjs { 941fa225cbcSrjs ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, 942fa225cbcSrjs ySrc, xMask, yMask, xDst, yDst, 943fa225cbcSrjs width, height); 944fa225cbcSrjs if (ret == 1) 945fa225cbcSrjs goto done; 946fa225cbcSrjs } 947fa225cbcSrjs 948fa225cbcSrjs /* Now see if we can use uxa_fill_region_tiled() */ 949fa225cbcSrjs xDst += pDst->pDrawable->x; 950fa225cbcSrjs yDst += pDst->pDrawable->y; 951fa225cbcSrjs xSrc += pSrc->pDrawable->x; 952fa225cbcSrjs ySrc += pSrc->pDrawable->y; 953fa225cbcSrjs 954fa225cbcSrjs if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, 955fa225cbcSrjs ySrc, xMask, yMask, xDst, yDst, 956fa225cbcSrjs width, height)) 957fa225cbcSrjs goto done; 958fa225cbcSrjs 959fa225cbcSrjs /* pattern origin is the point in the destination drawable 960fa225cbcSrjs * corresponding to (0,0) in the source */ 961fa225cbcSrjs patOrg.x = xDst - xSrc; 962fa225cbcSrjs patOrg.y = yDst - ySrc; 963fa225cbcSrjs 964fa225cbcSrjs ret = uxa_fill_region_tiled(pDst->pDrawable, ®ion, 965fa225cbcSrjs (PixmapPtr)pSrc->pDrawable, 966fa225cbcSrjs &patOrg, FB_ALLONES, GXcopy); 967fa225cbcSrjs 968fa225cbcSrjs REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 969fa225cbcSrjs 970fa225cbcSrjs if (ret) 971fa225cbcSrjs goto done; 972fa225cbcSrjs } 973fa225cbcSrjs } 974fa225cbcSrjs } 975fa225cbcSrjs 976fa225cbcSrjscomposite: 977fa225cbcSrjs /* Remove repeat in mask if useless */ 978fa225cbcSrjs if (pMask && pMask->repeat && !pMask->transform && pMask->pDrawable && 979fa225cbcSrjs xMask >= 0 && (xMask + width) <= pMask->pDrawable->width && 980fa225cbcSrjs yMask >= 0 && (yMask + height) <= pMask->pDrawable->height) 981fa225cbcSrjs pMask->repeat = 0; 982fa225cbcSrjs 983fa225cbcSrjs if (uxa_screen->info->prepare_composite && 984fa225cbcSrjs !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) 985fa225cbcSrjs { 986fa225cbcSrjs Bool isSrcSolid; 987fa225cbcSrjs 988fa225cbcSrjs ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, 989fa225cbcSrjs yMask, xDst, yDst, width, height); 990fa225cbcSrjs if (ret == 1) 991fa225cbcSrjs goto done; 992fa225cbcSrjs 993fa225cbcSrjs /* For generic masks and solid src pictures, mach64 can do Over in two 994fa225cbcSrjs * passes, similar to the component-alpha case. 995fa225cbcSrjs */ 996fa225cbcSrjs isSrcSolid = pSrc->pDrawable && 997fa225cbcSrjs pSrc->pDrawable->width == 1 && 998fa225cbcSrjs pSrc->pDrawable->height == 1 && 999fa225cbcSrjs pSrc->repeat; 1000fa225cbcSrjs 1001fa225cbcSrjs /* If we couldn't do the Composite in a single pass, and it was a 1002fa225cbcSrjs * component-alpha Over, see if we can do it in two passes with 1003fa225cbcSrjs * an OutReverse and then an Add. 1004fa225cbcSrjs */ 1005fa225cbcSrjs if (ret == -1 && op == PictOpOver && pMask && 1006fa225cbcSrjs (pMask->componentAlpha || isSrcSolid)) { 1007fa225cbcSrjs ret = uxa_try_magic_two_pass_composite_helper(op, pSrc, pMask, pDst, 1008fa225cbcSrjs xSrc, ySrc, 1009fa225cbcSrjs xMask, yMask, xDst, yDst, 1010fa225cbcSrjs width, height); 1011fa225cbcSrjs if (ret == 1) 1012fa225cbcSrjs goto done; 1013fa225cbcSrjs } 1014fa225cbcSrjs } 1015fa225cbcSrjs 1016fa225cbcSrjsfallback: 1017fa225cbcSrjs if (uxa_screen->fallback_debug) 1018fa225cbcSrjs uxa_print_composite_fallback (op, pSrc, pMask, pDst); 1019fa225cbcSrjs 1020fa225cbcSrjs uxa_check_composite (op, pSrc, pMask, pDst, xSrc, ySrc, 1021fa225cbcSrjs xMask, yMask, xDst, yDst, width, height); 1022fa225cbcSrjs 1023fa225cbcSrjsdone: 1024fa225cbcSrjs pSrc->repeat = saveSrcRepeat; 1025fa225cbcSrjs if (pMask) 1026fa225cbcSrjs pMask->repeat = saveMaskRepeat; 1027fa225cbcSrjs} 1028fa225cbcSrjs#endif 1029fa225cbcSrjs 1030fa225cbcSrjs/** 1031fa225cbcSrjs * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead 1032fa225cbcSrjs * of PolyFillRect to initialize the pixmap after creating it, to prevent 1033fa225cbcSrjs * the pixmap from being migrated. 1034fa225cbcSrjs * 1035fa225cbcSrjs * See the comments about uxa_trapezoids and uxa_triangles. 1036fa225cbcSrjs */ 1037fa225cbcSrjsstatic PicturePtr 1038fa225cbcSrjsuxa_create_alpha_picture (ScreenPtr pScreen, 1039fa225cbcSrjs PicturePtr pDst, 1040fa225cbcSrjs PictFormatPtr pPictFormat, 1041fa225cbcSrjs CARD16 width, 1042fa225cbcSrjs CARD16 height) 1043fa225cbcSrjs{ 1044fa225cbcSrjs PixmapPtr pPixmap; 1045fa225cbcSrjs PicturePtr pPicture; 1046fa225cbcSrjs int error; 1047fa225cbcSrjs 1048fa225cbcSrjs if (width > 32767 || height > 32767) 1049fa225cbcSrjs return 0; 1050fa225cbcSrjs 1051fa225cbcSrjs if (!pPictFormat) 1052fa225cbcSrjs { 1053fa225cbcSrjs if (pDst->polyEdge == PolyEdgeSharp) 1054fa225cbcSrjs pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); 1055fa225cbcSrjs else 1056fa225cbcSrjs pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); 1057fa225cbcSrjs if (!pPictFormat) 1058fa225cbcSrjs return 0; 1059fa225cbcSrjs } 1060fa225cbcSrjs 1061fa225cbcSrjs pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1062fa225cbcSrjs pPictFormat->depth, 1063fa225cbcSrjs UXA_CREATE_PIXMAP_FOR_MAP); 1064fa225cbcSrjs if (!pPixmap) 1065fa225cbcSrjs return 0; 1066fa225cbcSrjs pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, 1067fa225cbcSrjs 0, 0, serverClient, &error); 1068fa225cbcSrjs (*pScreen->DestroyPixmap) (pPixmap); 1069fa225cbcSrjs return pPicture; 1070fa225cbcSrjs} 1071fa225cbcSrjs 1072fa225cbcSrjs/** 1073fa225cbcSrjs * uxa_trapezoids is essentially a copy of miTrapezoids that uses 1074fa225cbcSrjs * uxa_create_alpha_picture instead of miCreateAlphaPicture. 1075fa225cbcSrjs * 1076fa225cbcSrjs * The problem with miCreateAlphaPicture is that it calls PolyFillRect 1077fa225cbcSrjs * to initialize the contents after creating the pixmap, which 1078fa225cbcSrjs * causes the pixmap to be moved in for acceleration. The subsequent 1079fa225cbcSrjs * call to RasterizeTrapezoid won't be accelerated however, which 1080fa225cbcSrjs * forces the pixmap to be moved out again. 1081fa225cbcSrjs * 1082fa225cbcSrjs * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect 1083fa225cbcSrjs * to initialize the contents. 1084fa225cbcSrjs */ 1085fa225cbcSrjsvoid 1086fa225cbcSrjsuxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1087fa225cbcSrjs PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 1088fa225cbcSrjs int ntrap, xTrapezoid *traps) 1089fa225cbcSrjs{ 1090fa225cbcSrjs ScreenPtr pScreen = pDst->pDrawable->pScreen; 1091fa225cbcSrjs PictureScreenPtr ps = GetPictureScreen(pScreen); 1092fa225cbcSrjs BoxRec bounds; 1093fa225cbcSrjs Bool direct = op == PictOpAdd && miIsSolidAlpha (pSrc); 1094fa225cbcSrjs 1095fa225cbcSrjs if (maskFormat || direct) { 1096fa225cbcSrjs miTrapezoidBounds (ntrap, traps, &bounds); 1097fa225cbcSrjs 1098fa225cbcSrjs if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 1099fa225cbcSrjs return; 1100fa225cbcSrjs } 1101fa225cbcSrjs 1102fa225cbcSrjs /* 1103fa225cbcSrjs * Check for solid alpha add 1104fa225cbcSrjs */ 1105fa225cbcSrjs if (direct) 1106fa225cbcSrjs { 1107fa225cbcSrjs DrawablePtr pDraw = pDst->pDrawable; 1108fa225cbcSrjs PixmapPtr pixmap = uxa_get_drawable_pixmap (pDraw); 1109fa225cbcSrjs int xoff, yoff; 1110fa225cbcSrjs 1111fa225cbcSrjs uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff); 1112fa225cbcSrjs 1113fa225cbcSrjs xoff += pDraw->x; 1114fa225cbcSrjs yoff += pDraw->y; 1115fa225cbcSrjs 1116fa225cbcSrjs if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) 1117fa225cbcSrjs { 1118fa225cbcSrjs for (; ntrap; ntrap--, traps++) 1119fa225cbcSrjs (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); 1120fa225cbcSrjs uxa_finish_access(pDraw); 1121fa225cbcSrjs } 1122fa225cbcSrjs } 1123fa225cbcSrjs else if (maskFormat) 1124fa225cbcSrjs { 1125fa225cbcSrjs PicturePtr pPicture; 1126fa225cbcSrjs INT16 xDst, yDst; 1127fa225cbcSrjs INT16 xRel, yRel; 1128fa225cbcSrjs int width, height; 1129fa225cbcSrjs pixman_image_t *image; 1130fa225cbcSrjs pixman_format_code_t format; 1131fa225cbcSrjs 1132fa225cbcSrjs xDst = traps[0].left.p1.x >> 16; 1133fa225cbcSrjs yDst = traps[0].left.p1.y >> 16; 1134fa225cbcSrjs 1135fa225cbcSrjs width = bounds.x2 - bounds.x1; 1136fa225cbcSrjs height = bounds.y2 - bounds.y1; 1137fa225cbcSrjs 1138fa225cbcSrjs format = maskFormat->format | (BitsPerPixel (maskFormat->depth) << 24); 1139fa225cbcSrjs image = pixman_image_create_bits (format, width, height, NULL, 0); 1140fa225cbcSrjs if (!image) 1141fa225cbcSrjs return; 1142fa225cbcSrjs 1143fa225cbcSrjs for (; ntrap; ntrap--, traps++) 1144fa225cbcSrjs pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *) traps, 1145fa225cbcSrjs -bounds.x1, -bounds.y1); 1146fa225cbcSrjs 1147fa225cbcSrjs pPicture = uxa_picture_from_pixman_image (pScreen, image, format); 1148fa225cbcSrjs pixman_image_unref (image); 1149fa225cbcSrjs if (!pPicture) 1150fa225cbcSrjs return; 1151fa225cbcSrjs 1152fa225cbcSrjs xRel = bounds.x1 + xSrc - xDst; 1153fa225cbcSrjs yRel = bounds.y1 + ySrc - yDst; 1154fa225cbcSrjs CompositePicture (op, pSrc, pPicture, pDst, 1155fa225cbcSrjs xRel, yRel, 0, 0, bounds.x1, bounds.y1, 1156fa225cbcSrjs bounds.x2 - bounds.x1, 1157fa225cbcSrjs bounds.y2 - bounds.y1); 1158fa225cbcSrjs FreePicture (pPicture, 0); 1159fa225cbcSrjs } 1160fa225cbcSrjs else 1161fa225cbcSrjs { 1162fa225cbcSrjs if (pDst->polyEdge == PolyEdgeSharp) 1163fa225cbcSrjs maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); 1164fa225cbcSrjs else 1165fa225cbcSrjs maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); 1166fa225cbcSrjs for (; ntrap; ntrap--, traps++) 1167fa225cbcSrjs uxa_trapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); 1168fa225cbcSrjs } 1169fa225cbcSrjs} 1170fa225cbcSrjs 1171fa225cbcSrjs/** 1172fa225cbcSrjs * uxa_triangles is essentially a copy of miTriangles that uses 1173fa225cbcSrjs * uxa_create_alpha_picture instead of miCreateAlphaPicture. 1174fa225cbcSrjs * 1175fa225cbcSrjs * The problem with miCreateAlphaPicture is that it calls PolyFillRect 1176fa225cbcSrjs * to initialize the contents after creating the pixmap, which 1177fa225cbcSrjs * causes the pixmap to be moved in for acceleration. The subsequent 1178fa225cbcSrjs * call to AddTriangles won't be accelerated however, which forces the pixmap 1179fa225cbcSrjs * to be moved out again. 1180fa225cbcSrjs * 1181fa225cbcSrjs * uxa_create_alpha_picture avoids this roundtrip by using uxa_check_poly_fill_rect 1182fa225cbcSrjs * to initialize the contents. 1183fa225cbcSrjs */ 1184fa225cbcSrjsvoid 1185fa225cbcSrjsuxa_triangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1186fa225cbcSrjs PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 1187fa225cbcSrjs int ntri, xTriangle *tris) 1188fa225cbcSrjs{ 1189fa225cbcSrjs ScreenPtr pScreen = pDst->pDrawable->pScreen; 1190fa225cbcSrjs PictureScreenPtr ps = GetPictureScreen(pScreen); 1191fa225cbcSrjs BoxRec bounds; 1192fa225cbcSrjs Bool direct = op == PictOpAdd && miIsSolidAlpha (pSrc); 1193fa225cbcSrjs 1194fa225cbcSrjs if (maskFormat || direct) { 1195fa225cbcSrjs miTriangleBounds (ntri, tris, &bounds); 1196fa225cbcSrjs 1197fa225cbcSrjs if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 1198fa225cbcSrjs return; 1199fa225cbcSrjs } 1200fa225cbcSrjs 1201fa225cbcSrjs /* 1202fa225cbcSrjs * Check for solid alpha add 1203fa225cbcSrjs */ 1204fa225cbcSrjs if (direct) 1205fa225cbcSrjs { 1206fa225cbcSrjs DrawablePtr pDraw = pDst->pDrawable; 1207fa225cbcSrjs if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) { 1208fa225cbcSrjs (*ps->AddTriangles) (pDst, 0, 0, ntri, tris); 1209fa225cbcSrjs uxa_finish_access(pDraw); 1210fa225cbcSrjs } 1211fa225cbcSrjs } 1212fa225cbcSrjs else if (maskFormat) 1213fa225cbcSrjs { 1214fa225cbcSrjs PicturePtr pPicture; 1215fa225cbcSrjs INT16 xDst, yDst; 1216fa225cbcSrjs INT16 xRel, yRel; 1217fa225cbcSrjs int width = bounds.x2 - bounds.x1; 1218fa225cbcSrjs int height = bounds.y2 - bounds.y1; 1219fa225cbcSrjs GCPtr pGC; 1220fa225cbcSrjs xRectangle rect; 1221fa225cbcSrjs 1222fa225cbcSrjs xDst = tris[0].p1.x >> 16; 1223fa225cbcSrjs yDst = tris[0].p1.y >> 16; 1224fa225cbcSrjs 1225fa225cbcSrjs pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat, 1226fa225cbcSrjs width, height); 1227fa225cbcSrjs if (!pPicture) 1228fa225cbcSrjs return; 1229fa225cbcSrjs 1230fa225cbcSrjs /* Clear the alpha picture to 0. */ 1231fa225cbcSrjs pGC = GetScratchGC (pPicture->pDrawable->depth, pScreen); 1232fa225cbcSrjs if (!pGC) { 1233fa225cbcSrjs FreePicture (pPicture, 0); 1234fa225cbcSrjs return; 1235fa225cbcSrjs } 1236fa225cbcSrjs ValidateGC (pPicture->pDrawable, pGC); 1237fa225cbcSrjs rect.x = 0; 1238fa225cbcSrjs rect.y = 0; 1239fa225cbcSrjs rect.width = width; 1240fa225cbcSrjs rect.height = height; 1241fa225cbcSrjs uxa_check_poly_fill_rect (pPicture->pDrawable, pGC, 1, &rect); 1242fa225cbcSrjs FreeScratchGC (pGC); 1243fa225cbcSrjs 1244fa225cbcSrjs if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) { 1245fa225cbcSrjs (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris); 1246fa225cbcSrjs uxa_finish_access(pPicture->pDrawable); 1247fa225cbcSrjs } 1248fa225cbcSrjs 1249fa225cbcSrjs xRel = bounds.x1 + xSrc - xDst; 1250fa225cbcSrjs yRel = bounds.y1 + ySrc - yDst; 1251fa225cbcSrjs CompositePicture (op, pSrc, pPicture, pDst, 1252fa225cbcSrjs xRel, yRel, 0, 0, bounds.x1, bounds.y1, 1253fa225cbcSrjs bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); 1254fa225cbcSrjs FreePicture (pPicture, 0); 1255fa225cbcSrjs } 1256fa225cbcSrjs else 1257fa225cbcSrjs { 1258fa225cbcSrjs if (pDst->polyEdge == PolyEdgeSharp) 1259fa225cbcSrjs maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); 1260fa225cbcSrjs else 1261fa225cbcSrjs maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); 1262fa225cbcSrjs 1263fa225cbcSrjs for (; ntri; ntri--, tris++) 1264fa225cbcSrjs uxa_triangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris); 1265fa225cbcSrjs } 1266fa225cbcSrjs} 1267