103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 2001 Keith Packard 303b705cfSriastradh * 403b705cfSriastradh * Partly based on code that is Copyright © The XFree86 Project Inc. 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 Keith Packard not be used in 1103b705cfSriastradh * advertising or publicity pertaining to distribution of the software without 1203b705cfSriastradh * specific, written prior permission. Keith Packard makes no 1303b705cfSriastradh * representations about the suitability of this software for any purpose. It 1403b705cfSriastradh * is provided "as is" without express or implied warranty. 1503b705cfSriastradh * 1603b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1703b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1803b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1903b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2003b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2103b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2203b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE. 2303b705cfSriastradh */ 2403b705cfSriastradh 2503b705cfSriastradh#ifdef HAVE_DIX_CONFIG_H 2603b705cfSriastradh#include <dix-config.h> 2703b705cfSriastradh#endif 2803b705cfSriastradh 2903b705cfSriastradh#include <stdlib.h> 3003b705cfSriastradh 3103b705cfSriastradh#include "uxa-priv.h" 3203b705cfSriastradh 3303b705cfSriastradh#ifdef RENDER 3403b705cfSriastradh#include "mipict.h" 3503b705cfSriastradh 3603b705cfSriastradhstatic void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, 3703b705cfSriastradh int n) 3803b705cfSriastradh{ 3903b705cfSriastradh char format[20]; 4003b705cfSriastradh char size[20]; 4103b705cfSriastradh char loc; 4203b705cfSriastradh 4303b705cfSriastradh if (!pict) { 4403b705cfSriastradh snprintf(string, n, "None"); 4503b705cfSriastradh return; 4603b705cfSriastradh } 4703b705cfSriastradh 4803b705cfSriastradh if (pict->pDrawable == NULL) { 4903b705cfSriastradh snprintf(string, n, "source-only"); 5003b705cfSriastradh return; 5103b705cfSriastradh } 5203b705cfSriastradh 5303b705cfSriastradh switch (pict->format) { 5403b705cfSriastradh case PICT_a8r8g8b8: 5503b705cfSriastradh snprintf(format, 20, "ARGB8888"); 5603b705cfSriastradh break; 5703b705cfSriastradh case PICT_x8r8g8b8: 5803b705cfSriastradh snprintf(format, 20, "XRGB8888"); 5903b705cfSriastradh break; 6003b705cfSriastradh case PICT_r5g6b5: 6103b705cfSriastradh snprintf(format, 20, "RGB565 "); 6203b705cfSriastradh break; 6303b705cfSriastradh case PICT_x1r5g5b5: 6403b705cfSriastradh snprintf(format, 20, "RGB555 "); 6503b705cfSriastradh break; 6603b705cfSriastradh case PICT_a8: 6703b705cfSriastradh snprintf(format, 20, "A8 "); 6803b705cfSriastradh break; 6903b705cfSriastradh case PICT_a1: 7003b705cfSriastradh snprintf(format, 20, "A1 "); 7103b705cfSriastradh break; 7203b705cfSriastradh default: 7303b705cfSriastradh snprintf(format, 20, "0x%x", (int)pict->format); 7403b705cfSriastradh break; 7503b705cfSriastradh } 7603b705cfSriastradh 7703b705cfSriastradh loc = uxa_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm'; 7803b705cfSriastradh 7903b705cfSriastradh snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, 8003b705cfSriastradh pict->pDrawable->height, pict->repeat ? " R" : ""); 8103b705cfSriastradh 8203b705cfSriastradh snprintf(string, n, "%p:%c fmt %s (%s)%s", 8303b705cfSriastradh pict->pDrawable, loc, format, size, 8403b705cfSriastradh pict->alphaMap ? " with alpha map" :""); 8503b705cfSriastradh} 8603b705cfSriastradh 8703b705cfSriastradhstatic const char * 8803b705cfSriastradhop_to_string(CARD8 op) 8903b705cfSriastradh{ 9003b705cfSriastradh switch (op) { 9103b705cfSriastradh#define C(x) case PictOp##x: return #x 9203b705cfSriastradh C(Clear); 9303b705cfSriastradh C(Src); 9403b705cfSriastradh C(Dst); 9503b705cfSriastradh C(Over); 9603b705cfSriastradh C(OverReverse); 9703b705cfSriastradh C(In); 9803b705cfSriastradh C(InReverse); 9903b705cfSriastradh C(Out); 10003b705cfSriastradh C(OutReverse); 10103b705cfSriastradh C(Atop); 10203b705cfSriastradh C(AtopReverse); 10303b705cfSriastradh C(Xor); 10403b705cfSriastradh C(Add); 10503b705cfSriastradh C(Saturate); 10603b705cfSriastradh 10703b705cfSriastradh /* 10803b705cfSriastradh * Operators only available in version 0.2 10903b705cfSriastradh */ 11003b705cfSriastradh#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 2 11103b705cfSriastradh C(DisjointClear); 11203b705cfSriastradh C(DisjointSrc); 11303b705cfSriastradh C(DisjointDst); 11403b705cfSriastradh C(DisjointOver); 11503b705cfSriastradh C(DisjointOverReverse); 11603b705cfSriastradh C(DisjointIn); 11703b705cfSriastradh C(DisjointInReverse); 11803b705cfSriastradh C(DisjointOut); 11903b705cfSriastradh C(DisjointOutReverse); 12003b705cfSriastradh C(DisjointAtop); 12103b705cfSriastradh C(DisjointAtopReverse); 12203b705cfSriastradh C(DisjointXor); 12303b705cfSriastradh 12403b705cfSriastradh C(ConjointClear); 12503b705cfSriastradh C(ConjointSrc); 12603b705cfSriastradh C(ConjointDst); 12703b705cfSriastradh C(ConjointOver); 12803b705cfSriastradh C(ConjointOverReverse); 12903b705cfSriastradh C(ConjointIn); 13003b705cfSriastradh C(ConjointInReverse); 13103b705cfSriastradh C(ConjointOut); 13203b705cfSriastradh C(ConjointOutReverse); 13303b705cfSriastradh C(ConjointAtop); 13403b705cfSriastradh C(ConjointAtopReverse); 13503b705cfSriastradh C(ConjointXor); 13603b705cfSriastradh#endif 13703b705cfSriastradh 13803b705cfSriastradh /* 13903b705cfSriastradh * Operators only available in version 0.11 14003b705cfSriastradh */ 14103b705cfSriastradh#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 11 14203b705cfSriastradh C(Multiply); 14303b705cfSriastradh C(Screen); 14403b705cfSriastradh C(Overlay); 14503b705cfSriastradh C(Darken); 14603b705cfSriastradh C(Lighten); 14703b705cfSriastradh C(ColorDodge); 14803b705cfSriastradh C(ColorBurn); 14903b705cfSriastradh C(HardLight); 15003b705cfSriastradh C(SoftLight); 15103b705cfSriastradh C(Difference); 15203b705cfSriastradh C(Exclusion); 15303b705cfSriastradh C(HSLHue); 15403b705cfSriastradh C(HSLSaturation); 15503b705cfSriastradh C(HSLColor); 15603b705cfSriastradh C(HSLLuminosity); 15703b705cfSriastradh#endif 15803b705cfSriastradh default: return "garbage"; 15903b705cfSriastradh#undef C 16003b705cfSriastradh } 16103b705cfSriastradh} 16203b705cfSriastradh 16303b705cfSriastradhstatic void 16403b705cfSriastradhuxa_print_composite_fallback(const char *func, CARD8 op, 16503b705cfSriastradh PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) 16603b705cfSriastradh{ 16703b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 16803b705cfSriastradh char srcdesc[40], maskdesc[40], dstdesc[40]; 16903b705cfSriastradh 17003b705cfSriastradh if (! uxa_screen->fallback_debug) 17103b705cfSriastradh return; 17203b705cfSriastradh 17303b705cfSriastradh /* Limit the noise if fallbacks are expected. */ 17403b705cfSriastradh if (uxa_screen->force_fallback) 17503b705cfSriastradh return; 17603b705cfSriastradh 17703b705cfSriastradh uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40); 17803b705cfSriastradh uxa_composite_fallback_pict_desc(pMask, maskdesc, 40); 17903b705cfSriastradh uxa_composite_fallback_pict_desc(pDst, dstdesc, 40); 18003b705cfSriastradh 18103b705cfSriastradh ErrorF("Composite fallback at %s:\n" 18203b705cfSriastradh " op %s, \n" 18303b705cfSriastradh " src %s, \n" 18403b705cfSriastradh " mask %s, \n" 18503b705cfSriastradh " dst %s, \n", 18603b705cfSriastradh func, op_to_string (op), srcdesc, maskdesc, dstdesc); 18703b705cfSriastradh} 18803b705cfSriastradh 18903b705cfSriastradhBool uxa_op_reads_destination(CARD8 op) 19003b705cfSriastradh{ 19103b705cfSriastradh /* FALSE (does not read destination) is the list of ops in the protocol 19203b705cfSriastradh * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. 19303b705cfSriastradh * That's just Clear and Src. ReduceCompositeOp() will already have 19403b705cfSriastradh * converted con/disjoint clear/src to Clear or Src. 19503b705cfSriastradh */ 19603b705cfSriastradh switch (op) { 19703b705cfSriastradh case PictOpClear: 19803b705cfSriastradh case PictOpSrc: 19903b705cfSriastradh return FALSE; 20003b705cfSriastradh default: 20103b705cfSriastradh return TRUE; 20203b705cfSriastradh } 20303b705cfSriastradh} 20403b705cfSriastradh 20503b705cfSriastradhstatic Bool 20603b705cfSriastradhuxa_get_pixel_from_rgba(CARD32 * pixel, 20703b705cfSriastradh CARD16 red, 20803b705cfSriastradh CARD16 green, 20903b705cfSriastradh CARD16 blue, 21003b705cfSriastradh CARD16 alpha, 21103b705cfSriastradh CARD32 format) 21203b705cfSriastradh{ 21303b705cfSriastradh int rbits, bbits, gbits, abits; 21403b705cfSriastradh int rshift, bshift, gshift, ashift; 21503b705cfSriastradh 21603b705cfSriastradh rbits = PICT_FORMAT_R(format); 21703b705cfSriastradh gbits = PICT_FORMAT_G(format); 21803b705cfSriastradh bbits = PICT_FORMAT_B(format); 21903b705cfSriastradh abits = PICT_FORMAT_A(format); 22003b705cfSriastradh if (abits == 0) 22103b705cfSriastradh abits = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); 22203b705cfSriastradh 22303b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { 22403b705cfSriastradh *pixel = alpha >> (16 - abits); 22503b705cfSriastradh return TRUE; 22603b705cfSriastradh } 22703b705cfSriastradh 22803b705cfSriastradh if (!PICT_FORMAT_COLOR(format)) 22903b705cfSriastradh return FALSE; 23003b705cfSriastradh 23103b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 23203b705cfSriastradh bshift = 0; 23303b705cfSriastradh gshift = bbits; 23403b705cfSriastradh rshift = gshift + gbits; 23503b705cfSriastradh ashift = rshift + rbits; 23603b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 23703b705cfSriastradh rshift = 0; 23803b705cfSriastradh gshift = rbits; 23903b705cfSriastradh bshift = gshift + gbits; 24003b705cfSriastradh ashift = bshift + bbits; 24103b705cfSriastradh#if XORG_VERSION_CURRENT >= 10699900 24203b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 24303b705cfSriastradh ashift = 0; 24403b705cfSriastradh rshift = abits; 24503b705cfSriastradh gshift = rshift + rbits; 24603b705cfSriastradh bshift = gshift + gbits; 24703b705cfSriastradh#endif 24803b705cfSriastradh } else { 24903b705cfSriastradh return FALSE; 25003b705cfSriastradh } 25103b705cfSriastradh 25203b705cfSriastradh *pixel = 0; 25303b705cfSriastradh *pixel |= (blue >> (16 - bbits)) << bshift; 25403b705cfSriastradh *pixel |= (green >> (16 - gbits)) << gshift; 25503b705cfSriastradh *pixel |= (red >> (16 - rbits)) << rshift; 25603b705cfSriastradh *pixel |= (alpha >> (16 - abits)) << ashift; 25703b705cfSriastradh 25803b705cfSriastradh return TRUE; 25903b705cfSriastradh} 26003b705cfSriastradh 26103b705cfSriastradhBool 26203b705cfSriastradhuxa_get_rgba_from_pixel(CARD32 pixel, 26303b705cfSriastradh CARD16 * red, 26403b705cfSriastradh CARD16 * green, 26503b705cfSriastradh CARD16 * blue, 26603b705cfSriastradh CARD16 * alpha, 26703b705cfSriastradh CARD32 format) 26803b705cfSriastradh{ 26903b705cfSriastradh int rbits, bbits, gbits, abits; 27003b705cfSriastradh int rshift, bshift, gshift, ashift; 27103b705cfSriastradh 27203b705cfSriastradh rbits = PICT_FORMAT_R(format); 27303b705cfSriastradh gbits = PICT_FORMAT_G(format); 27403b705cfSriastradh bbits = PICT_FORMAT_B(format); 27503b705cfSriastradh abits = PICT_FORMAT_A(format); 27603b705cfSriastradh 27703b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { 27803b705cfSriastradh rshift = gshift = bshift = ashift = 0; 27903b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 28003b705cfSriastradh bshift = 0; 28103b705cfSriastradh gshift = bbits; 28203b705cfSriastradh rshift = gshift + gbits; 28303b705cfSriastradh ashift = rshift + rbits; 28403b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 28503b705cfSriastradh rshift = 0; 28603b705cfSriastradh gshift = rbits; 28703b705cfSriastradh bshift = gshift + gbits; 28803b705cfSriastradh ashift = bshift + bbits; 28903b705cfSriastradh#if XORG_VERSION_CURRENT >= 10699900 29003b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 29103b705cfSriastradh ashift = 0; 29203b705cfSriastradh rshift = abits; 29303b705cfSriastradh if (abits == 0) 29403b705cfSriastradh rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); 29503b705cfSriastradh gshift = rshift + rbits; 29603b705cfSriastradh bshift = gshift + gbits; 29703b705cfSriastradh#endif 29803b705cfSriastradh } else { 29903b705cfSriastradh return FALSE; 30003b705cfSriastradh } 30103b705cfSriastradh 30203b705cfSriastradh if (rbits) { 30303b705cfSriastradh *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); 30403b705cfSriastradh while (rbits < 16) { 30503b705cfSriastradh *red |= *red >> rbits; 30603b705cfSriastradh rbits <<= 1; 30703b705cfSriastradh } 30803b705cfSriastradh } else 30903b705cfSriastradh *red = 0; 31003b705cfSriastradh 31103b705cfSriastradh if (gbits) { 31203b705cfSriastradh *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); 31303b705cfSriastradh while (gbits < 16) { 31403b705cfSriastradh *green |= *green >> gbits; 31503b705cfSriastradh gbits <<= 1; 31603b705cfSriastradh } 31703b705cfSriastradh } else 31803b705cfSriastradh *green = 0; 31903b705cfSriastradh 32003b705cfSriastradh if (bbits) { 32103b705cfSriastradh *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); 32203b705cfSriastradh while (bbits < 16) { 32303b705cfSriastradh *blue |= *blue >> bbits; 32403b705cfSriastradh bbits <<= 1; 32503b705cfSriastradh } 32603b705cfSriastradh } else 32703b705cfSriastradh *blue = 0; 32803b705cfSriastradh 32903b705cfSriastradh if (abits) { 33003b705cfSriastradh *alpha = 33103b705cfSriastradh ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); 33203b705cfSriastradh while (abits < 16) { 33303b705cfSriastradh *alpha |= *alpha >> abits; 33403b705cfSriastradh abits <<= 1; 33503b705cfSriastradh } 33603b705cfSriastradh } else 33703b705cfSriastradh *alpha = 0xffff; 33803b705cfSriastradh 33903b705cfSriastradh return TRUE; 34003b705cfSriastradh} 34103b705cfSriastradh 34203b705cfSriastradhBool 34303b705cfSriastradhuxa_get_color_for_pixmap (PixmapPtr pixmap, 34403b705cfSriastradh CARD32 src_format, 34503b705cfSriastradh CARD32 dst_format, 34603b705cfSriastradh CARD32 *pixel) 34703b705cfSriastradh{ 34803b705cfSriastradh CARD16 red, green, blue, alpha; 34903b705cfSriastradh 35003b705cfSriastradh *pixel = uxa_get_pixmap_first_pixel(pixmap); 35103b705cfSriastradh 35203b705cfSriastradh if (src_format != dst_format) { 35303b705cfSriastradh if (!uxa_get_rgba_from_pixel(*pixel, 35403b705cfSriastradh &red, &green, &blue, &alpha, 35503b705cfSriastradh src_format)) 35603b705cfSriastradh return FALSE; 35703b705cfSriastradh 35803b705cfSriastradh if (!uxa_get_pixel_from_rgba(pixel, 35903b705cfSriastradh red, green, blue, alpha, 36003b705cfSriastradh dst_format)) 36103b705cfSriastradh return FALSE; 36203b705cfSriastradh } 36303b705cfSriastradh 36403b705cfSriastradh return TRUE; 36503b705cfSriastradh} 36603b705cfSriastradh 36703b705cfSriastradhstatic int 36803b705cfSriastradhuxa_try_driver_solid_fill(PicturePtr pSrc, 36903b705cfSriastradh PicturePtr pDst, 37003b705cfSriastradh INT16 xSrc, 37103b705cfSriastradh INT16 ySrc, 37203b705cfSriastradh INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 37303b705cfSriastradh{ 37403b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 37503b705cfSriastradh RegionRec region; 37603b705cfSriastradh BoxPtr pbox; 37703b705cfSriastradh int nbox; 37803b705cfSriastradh int dst_off_x, dst_off_y; 37903b705cfSriastradh PixmapPtr pSrcPix = NULL, pDstPix; 38003b705cfSriastradh CARD32 pixel; 38103b705cfSriastradh 38203b705cfSriastradh if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES)) 38303b705cfSriastradh return -1; 38403b705cfSriastradh 38503b705cfSriastradh pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); 38603b705cfSriastradh if (!pDstPix) 38703b705cfSriastradh return -1; 38803b705cfSriastradh 38903b705cfSriastradh xDst += pDst->pDrawable->x; 39003b705cfSriastradh yDst += pDst->pDrawable->y; 39103b705cfSriastradh 39203b705cfSriastradh if (pSrc->pDrawable) { 39303b705cfSriastradh pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable); 39403b705cfSriastradh xSrc += pSrc->pDrawable->x; 39503b705cfSriastradh ySrc += pSrc->pDrawable->y; 39603b705cfSriastradh } 39703b705cfSriastradh 39803b705cfSriastradh if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, 39903b705cfSriastradh xSrc, ySrc, 0, 0, xDst, yDst, 40003b705cfSriastradh width, height)) 40103b705cfSriastradh return 1; 40203b705cfSriastradh 40303b705cfSriastradh if (pSrcPix) { 40403b705cfSriastradh if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) { 40503b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 40603b705cfSriastradh return -1; 40703b705cfSriastradh } 40803b705cfSriastradh } else { 40903b705cfSriastradh SourcePict *source = pSrc->pSourcePict; 41003b705cfSriastradh PictSolidFill *solid = &source->solidFill; 41103b705cfSriastradh 41203b705cfSriastradh if (source == NULL || source->type != SourcePictTypeSolidFill) { 41303b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 41403b705cfSriastradh return -1; 41503b705cfSriastradh } 41603b705cfSriastradh 41703b705cfSriastradh if (pDst->format == PICT_a8r8g8b8) { 41803b705cfSriastradh pixel = solid->color; 41903b705cfSriastradh } else if (pDst->format == PICT_x8r8g8b8) { 42003b705cfSriastradh pixel = solid->color | 0xff000000; 42103b705cfSriastradh } else { 42203b705cfSriastradh CARD16 red, green, blue, alpha; 42303b705cfSriastradh 42403b705cfSriastradh if (!uxa_get_rgba_from_pixel(solid->color, 42503b705cfSriastradh &red, &green, &blue, &alpha, 42603b705cfSriastradh PICT_a8r8g8b8) || 42703b705cfSriastradh !uxa_get_pixel_from_rgba(&pixel, 42803b705cfSriastradh red, green, blue, alpha, 42903b705cfSriastradh pDst->format)) { 43003b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 43103b705cfSriastradh return -1; 43203b705cfSriastradh } 43303b705cfSriastradh } 43403b705cfSriastradh } 43503b705cfSriastradh 43603b705cfSriastradh if (!(*uxa_screen->info->prepare_solid) 43703b705cfSriastradh (pDstPix, GXcopy, FB_ALLONES, pixel)) { 43803b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 43903b705cfSriastradh return -1; 44003b705cfSriastradh } 44103b705cfSriastradh 44203b705cfSriastradh REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); 44303b705cfSriastradh 44403b705cfSriastradh nbox = REGION_NUM_RECTS(®ion); 44503b705cfSriastradh pbox = REGION_RECTS(®ion); 44603b705cfSriastradh 44703b705cfSriastradh while (nbox--) { 44803b705cfSriastradh (*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, 44903b705cfSriastradh pbox->x2, pbox->y2); 45003b705cfSriastradh pbox++; 45103b705cfSriastradh } 45203b705cfSriastradh 45303b705cfSriastradh (*uxa_screen->info->done_solid) (pDstPix); 45403b705cfSriastradh 45503b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 45603b705cfSriastradh return 1; 45703b705cfSriastradh} 45803b705cfSriastradh 45903b705cfSriastradhstatic PicturePtr 46003b705cfSriastradhuxa_picture_for_pixman_format(ScreenPtr screen, 46103b705cfSriastradh pixman_format_code_t format, 46203b705cfSriastradh int width, int height) 46303b705cfSriastradh{ 46403b705cfSriastradh PicturePtr picture; 46503b705cfSriastradh PixmapPtr pixmap; 46603b705cfSriastradh int error; 46703b705cfSriastradh 46803b705cfSriastradh if (format == PIXMAN_a1) 46903b705cfSriastradh format = PIXMAN_a8; 47003b705cfSriastradh 47103b705cfSriastradh /* fill alpha if unset */ 47203b705cfSriastradh if (PIXMAN_FORMAT_A(format) == 0) 47303b705cfSriastradh format = PIXMAN_a8r8g8b8; 47403b705cfSriastradh 47503b705cfSriastradh pixmap = screen->CreatePixmap(screen, width, height, 47603b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 47703b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 47803b705cfSriastradh if (!pixmap) 47903b705cfSriastradh return 0; 48003b705cfSriastradh 48103b705cfSriastradh if (!uxa_pixmap_is_offscreen(pixmap)) { 48203b705cfSriastradh screen->DestroyPixmap(pixmap); 48303b705cfSriastradh return 0; 48403b705cfSriastradh } 48503b705cfSriastradh 48603b705cfSriastradh picture = CreatePicture(0, &pixmap->drawable, 48703b705cfSriastradh PictureMatchFormat(screen, 48803b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 48903b705cfSriastradh format), 49003b705cfSriastradh 0, 0, serverClient, &error); 49103b705cfSriastradh screen->DestroyPixmap(pixmap); 49203b705cfSriastradh if (!picture) 49303b705cfSriastradh return 0; 49403b705cfSriastradh 49503b705cfSriastradh ValidatePicture(picture); 49603b705cfSriastradh 49703b705cfSriastradh return picture; 49803b705cfSriastradh} 49903b705cfSriastradh 50003b705cfSriastradhstatic PicturePtr 50103b705cfSriastradhuxa_picture_from_pixman_image(ScreenPtr screen, 50203b705cfSriastradh pixman_image_t * image, 50303b705cfSriastradh pixman_format_code_t format) 50403b705cfSriastradh{ 50503b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 50603b705cfSriastradh PicturePtr picture; 50703b705cfSriastradh PixmapPtr pixmap; 50803b705cfSriastradh int width, height; 50903b705cfSriastradh 51003b705cfSriastradh width = pixman_image_get_width(image); 51103b705cfSriastradh height = pixman_image_get_height(image); 51203b705cfSriastradh 51303b705cfSriastradh picture = uxa_picture_for_pixman_format(screen, format, 51403b705cfSriastradh width, height); 51503b705cfSriastradh if (!picture) 51603b705cfSriastradh return 0; 51703b705cfSriastradh 51803b705cfSriastradh if (uxa_screen->info->put_image && 51903b705cfSriastradh ((picture->pDrawable->depth << 24) | picture->format) == format && 52003b705cfSriastradh uxa_screen->info->put_image((PixmapPtr)picture->pDrawable, 52103b705cfSriastradh 0, 0, 52203b705cfSriastradh width, height, 52303b705cfSriastradh (char *)pixman_image_get_data(image), 52403b705cfSriastradh pixman_image_get_stride(image))) 52503b705cfSriastradh return picture; 52603b705cfSriastradh 52703b705cfSriastradh pixmap = GetScratchPixmapHeader(screen, width, height, 52803b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 52903b705cfSriastradh PIXMAN_FORMAT_BPP(format), 53003b705cfSriastradh pixman_image_get_stride(image), 53103b705cfSriastradh pixman_image_get_data(image)); 53203b705cfSriastradh if (!pixmap) { 53303b705cfSriastradh FreePicture(picture, 0); 53403b705cfSriastradh return 0; 53503b705cfSriastradh } 53603b705cfSriastradh 53703b705cfSriastradh if (((picture->pDrawable->depth << 24) | picture->format) == format) { 53803b705cfSriastradh GCPtr gc; 53903b705cfSriastradh 54003b705cfSriastradh gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen); 54103b705cfSriastradh if (!gc) { 54203b705cfSriastradh FreeScratchPixmapHeader(pixmap); 54303b705cfSriastradh FreePicture(picture, 0); 54403b705cfSriastradh return 0; 54503b705cfSriastradh } 54603b705cfSriastradh ValidateGC(picture->pDrawable, gc); 54703b705cfSriastradh 54803b705cfSriastradh (*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable, 54903b705cfSriastradh gc, 0, 0, width, height, 0, 0); 55003b705cfSriastradh 55103b705cfSriastradh FreeScratchGC(gc); 55203b705cfSriastradh } else { 55303b705cfSriastradh PicturePtr src; 55403b705cfSriastradh int error; 55503b705cfSriastradh 55603b705cfSriastradh src = CreatePicture(0, &pixmap->drawable, 55703b705cfSriastradh PictureMatchFormat(screen, 55803b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 55903b705cfSriastradh format), 56003b705cfSriastradh 0, 0, serverClient, &error); 56103b705cfSriastradh if (!src) { 56203b705cfSriastradh FreeScratchPixmapHeader(pixmap); 56303b705cfSriastradh FreePicture(picture, 0); 56403b705cfSriastradh return 0; 56503b705cfSriastradh } 56603b705cfSriastradh ValidatePicture(src); 56703b705cfSriastradh 56803b705cfSriastradh if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) { 56903b705cfSriastradh fbComposite(PictOpSrc, src, NULL, picture, 57003b705cfSriastradh 0, 0, 0, 0, 0, 0, width, height); 57103b705cfSriastradh uxa_picture_finish_access(picture, UXA_ACCESS_RW); 57203b705cfSriastradh } 57303b705cfSriastradh 57403b705cfSriastradh FreePicture(src, 0); 57503b705cfSriastradh } 57603b705cfSriastradh FreeScratchPixmapHeader(pixmap); 57703b705cfSriastradh 57803b705cfSriastradh return picture; 57903b705cfSriastradh} 58003b705cfSriastradh 58103b705cfSriastradhstatic PicturePtr 58203b705cfSriastradhuxa_create_solid(ScreenPtr screen, uint32_t color) 58303b705cfSriastradh{ 58403b705cfSriastradh PixmapPtr pixmap; 58503b705cfSriastradh PicturePtr picture; 58603b705cfSriastradh XID repeat = RepeatNormal; 58703b705cfSriastradh int error = 0; 58803b705cfSriastradh 58903b705cfSriastradh pixmap = (*screen->CreatePixmap)(screen, 1, 1, 32, 59003b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 59103b705cfSriastradh if (!pixmap) 59203b705cfSriastradh return 0; 59303b705cfSriastradh 59403b705cfSriastradh if (!uxa_prepare_access((DrawablePtr)pixmap, UXA_ACCESS_RW)) { 59503b705cfSriastradh (*screen->DestroyPixmap)(pixmap); 59603b705cfSriastradh return 0; 59703b705cfSriastradh } 59803b705cfSriastradh *((uint32_t *)pixmap->devPrivate.ptr) = color; 59903b705cfSriastradh uxa_finish_access((DrawablePtr)pixmap, UXA_ACCESS_RW); 60003b705cfSriastradh 60103b705cfSriastradh picture = CreatePicture(0, &pixmap->drawable, 60203b705cfSriastradh PictureMatchFormat(screen, 32, PICT_a8r8g8b8), 60303b705cfSriastradh CPRepeat, &repeat, serverClient, &error); 60403b705cfSriastradh (*screen->DestroyPixmap)(pixmap); 60503b705cfSriastradh 60603b705cfSriastradh return picture; 60703b705cfSriastradh} 60803b705cfSriastradh 60903b705cfSriastradhstatic PicturePtr 61003b705cfSriastradhuxa_solid_clear(ScreenPtr screen) 61103b705cfSriastradh{ 61203b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 61303b705cfSriastradh PicturePtr picture; 61403b705cfSriastradh 61503b705cfSriastradh if (!uxa_screen->solid_clear) { 61603b705cfSriastradh uxa_screen->solid_clear = uxa_create_solid(screen, 0); 61703b705cfSriastradh if (!uxa_screen->solid_clear) 61803b705cfSriastradh return 0; 61903b705cfSriastradh } 62003b705cfSriastradh picture = uxa_screen->solid_clear; 62103b705cfSriastradh return picture; 62203b705cfSriastradh} 62303b705cfSriastradh 62403b705cfSriastradhPicturePtr 62503b705cfSriastradhuxa_acquire_solid(ScreenPtr screen, SourcePict *source) 62603b705cfSriastradh{ 62703b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 62803b705cfSriastradh PictSolidFill *solid = &source->solidFill; 62903b705cfSriastradh PicturePtr picture; 63003b705cfSriastradh int i; 63103b705cfSriastradh 63203b705cfSriastradh if ((solid->color >> 24) == 0) { 63303b705cfSriastradh picture = uxa_solid_clear(screen); 63403b705cfSriastradh if (!picture) 63503b705cfSriastradh return 0; 63603b705cfSriastradh 63703b705cfSriastradh goto DONE; 63803b705cfSriastradh } else if (solid->color == 0xff000000) { 63903b705cfSriastradh if (!uxa_screen->solid_black) { 64003b705cfSriastradh uxa_screen->solid_black = uxa_create_solid(screen, 0xff000000); 64103b705cfSriastradh if (!uxa_screen->solid_black) 64203b705cfSriastradh return 0; 64303b705cfSriastradh } 64403b705cfSriastradh picture = uxa_screen->solid_black; 64503b705cfSriastradh goto DONE; 64603b705cfSriastradh } else if (solid->color == 0xffffffff) { 64703b705cfSriastradh if (!uxa_screen->solid_white) { 64803b705cfSriastradh uxa_screen->solid_white = uxa_create_solid(screen, 0xffffffff); 64903b705cfSriastradh if (!uxa_screen->solid_white) 65003b705cfSriastradh return 0; 65103b705cfSriastradh } 65203b705cfSriastradh picture = uxa_screen->solid_white; 65303b705cfSriastradh goto DONE; 65403b705cfSriastradh } 65503b705cfSriastradh 65603b705cfSriastradh for (i = 0; i < uxa_screen->solid_cache_size; i++) { 65703b705cfSriastradh if (uxa_screen->solid_cache[i].color == solid->color) { 65803b705cfSriastradh picture = uxa_screen->solid_cache[i].picture; 65903b705cfSriastradh goto DONE; 66003b705cfSriastradh } 66103b705cfSriastradh } 66203b705cfSriastradh 66303b705cfSriastradh picture = uxa_create_solid(screen, solid->color); 66403b705cfSriastradh if (!picture) 66503b705cfSriastradh return 0; 66603b705cfSriastradh 66703b705cfSriastradh if (uxa_screen->solid_cache_size == UXA_NUM_SOLID_CACHE) { 66803b705cfSriastradh i = rand() % UXA_NUM_SOLID_CACHE; 66903b705cfSriastradh FreePicture(uxa_screen->solid_cache[i].picture, 0); 67003b705cfSriastradh } else 67103b705cfSriastradh uxa_screen->solid_cache_size++; 67203b705cfSriastradh 67303b705cfSriastradh uxa_screen->solid_cache[i].picture = picture; 67403b705cfSriastradh uxa_screen->solid_cache[i].color = solid->color; 67503b705cfSriastradh 67603b705cfSriastradhDONE: 67703b705cfSriastradh picture->refcnt++; 67803b705cfSriastradh return picture; 67903b705cfSriastradh} 68003b705cfSriastradh 68103b705cfSriastradhPicturePtr 68203b705cfSriastradhuxa_acquire_pattern(ScreenPtr pScreen, 68303b705cfSriastradh PicturePtr pSrc, 68403b705cfSriastradh pixman_format_code_t format, 68503b705cfSriastradh INT16 x, INT16 y, CARD16 width, CARD16 height) 68603b705cfSriastradh{ 68703b705cfSriastradh PicturePtr pDst; 68803b705cfSriastradh 68903b705cfSriastradh if (pSrc->pSourcePict) { 69003b705cfSriastradh SourcePict *source = pSrc->pSourcePict; 69103b705cfSriastradh if (source->type == SourcePictTypeSolidFill) 69203b705cfSriastradh return uxa_acquire_solid (pScreen, source); 69303b705cfSriastradh } 69403b705cfSriastradh 69503b705cfSriastradh pDst = uxa_picture_for_pixman_format(pScreen, format, width, height); 69603b705cfSriastradh if (!pDst) 69703b705cfSriastradh return 0; 69803b705cfSriastradh 69903b705cfSriastradh if (uxa_picture_prepare_access(pDst, UXA_ACCESS_RW)) { 70003b705cfSriastradh fbComposite(PictOpSrc, pSrc, NULL, pDst, 70103b705cfSriastradh x, y, 0, 0, 0, 0, width, height); 70203b705cfSriastradh uxa_picture_finish_access(pDst, UXA_ACCESS_RW); 70303b705cfSriastradh return pDst; 70403b705cfSriastradh } else { 70503b705cfSriastradh FreePicture(pDst, 0); 70603b705cfSriastradh return 0; 70703b705cfSriastradh } 70803b705cfSriastradh} 70903b705cfSriastradh 71003b705cfSriastradhstatic Bool 71103b705cfSriastradhtransform_is_integer_translation(PictTransformPtr t, int *tx, int *ty) 71203b705cfSriastradh{ 71303b705cfSriastradh if (t == NULL) { 71403b705cfSriastradh *tx = *ty = 0; 71503b705cfSriastradh return TRUE; 71603b705cfSriastradh } 71703b705cfSriastradh 71803b705cfSriastradh if (t->matrix[0][0] != IntToxFixed(1) || 71903b705cfSriastradh t->matrix[0][1] != 0 || 72003b705cfSriastradh t->matrix[1][0] != 0 || 72103b705cfSriastradh t->matrix[1][1] != IntToxFixed(1) || 72203b705cfSriastradh t->matrix[2][0] != 0 || 72303b705cfSriastradh t->matrix[2][1] != 0 || 72403b705cfSriastradh t->matrix[2][2] != IntToxFixed(1)) 72503b705cfSriastradh return FALSE; 72603b705cfSriastradh 72703b705cfSriastradh if (xFixedFrac(t->matrix[0][2]) != 0 || 72803b705cfSriastradh xFixedFrac(t->matrix[1][2]) != 0) 72903b705cfSriastradh return FALSE; 73003b705cfSriastradh 73103b705cfSriastradh *tx = xFixedToInt(t->matrix[0][2]); 73203b705cfSriastradh *ty = xFixedToInt(t->matrix[1][2]); 73303b705cfSriastradh return TRUE; 73403b705cfSriastradh} 73503b705cfSriastradh 73603b705cfSriastradhstatic PicturePtr 73703b705cfSriastradhuxa_render_picture(ScreenPtr screen, 73803b705cfSriastradh PicturePtr src, 73903b705cfSriastradh pixman_format_code_t format, 74003b705cfSriastradh INT16 x, INT16 y, 74103b705cfSriastradh CARD16 width, CARD16 height) 74203b705cfSriastradh{ 74303b705cfSriastradh PicturePtr picture; 74403b705cfSriastradh int ret = 0; 74503b705cfSriastradh 74603b705cfSriastradh /* XXX we need a mechanism for the card to choose the fallback format */ 74703b705cfSriastradh 74803b705cfSriastradh /* force alpha channel in case source does not entirely cover the extents */ 74903b705cfSriastradh if (PIXMAN_FORMAT_A(format) == 0) 75003b705cfSriastradh format = PIXMAN_a8r8g8b8; /* available on all hardware */ 75103b705cfSriastradh 75203b705cfSriastradh picture = uxa_picture_for_pixman_format(screen, format, width, height); 75303b705cfSriastradh if (!picture) 75403b705cfSriastradh return 0; 75503b705cfSriastradh 75603b705cfSriastradh if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) { 75703b705cfSriastradh if (uxa_picture_prepare_access(src, UXA_ACCESS_RO)) { 75803b705cfSriastradh ret = 1; 75903b705cfSriastradh fbComposite(PictOpSrc, src, NULL, picture, 76003b705cfSriastradh x, y, 0, 0, 0, 0, width, height); 76103b705cfSriastradh uxa_picture_finish_access(src, UXA_ACCESS_RO); 76203b705cfSriastradh } 76303b705cfSriastradh uxa_picture_finish_access(picture, UXA_ACCESS_RW); 76403b705cfSriastradh } 76503b705cfSriastradh 76603b705cfSriastradh if (!ret) { 76703b705cfSriastradh FreePicture(picture, 0); 76803b705cfSriastradh return 0; 76903b705cfSriastradh } 77003b705cfSriastradh 77103b705cfSriastradh return picture; 77203b705cfSriastradh} 77303b705cfSriastradh 77403b705cfSriastradhstatic int 77503b705cfSriastradhdrawable_contains (DrawablePtr drawable, int x, int y, int w, int h) 77603b705cfSriastradh{ 77703b705cfSriastradh if (x < 0 || y < 0) 77803b705cfSriastradh return FALSE; 77903b705cfSriastradh 78003b705cfSriastradh if (x + w > drawable->width) 78103b705cfSriastradh return FALSE; 78203b705cfSriastradh 78303b705cfSriastradh if (y + h > drawable->height) 78403b705cfSriastradh return FALSE; 78503b705cfSriastradh 78603b705cfSriastradh return TRUE; 78703b705cfSriastradh} 78803b705cfSriastradh 78903b705cfSriastradhPicturePtr 79003b705cfSriastradhuxa_acquire_drawable(ScreenPtr pScreen, 79103b705cfSriastradh PicturePtr pSrc, 79203b705cfSriastradh INT16 x, INT16 y, 79303b705cfSriastradh CARD16 width, CARD16 height, 79403b705cfSriastradh INT16 * out_x, INT16 * out_y) 79503b705cfSriastradh{ 79603b705cfSriastradh PixmapPtr pPixmap; 79703b705cfSriastradh PicturePtr pDst; 79803b705cfSriastradh int depth, error; 79903b705cfSriastradh int tx, ty; 80003b705cfSriastradh GCPtr pGC; 80103b705cfSriastradh 80203b705cfSriastradh depth = pSrc->pDrawable->depth; 80303b705cfSriastradh if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) || 80403b705cfSriastradh !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) || 80503b705cfSriastradh depth == 1 || 80603b705cfSriastradh pSrc->filter == PictFilterConvolution) { 80703b705cfSriastradh /* XXX extract the sample extents and do the transformation on the GPU */ 80803b705cfSriastradh pDst = uxa_render_picture(pScreen, pSrc, 80903b705cfSriastradh pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24), 81003b705cfSriastradh x, y, width, height); 81103b705cfSriastradh if (!pDst) 81203b705cfSriastradh return 0; 81303b705cfSriastradh 81403b705cfSriastradh goto done; 81503b705cfSriastradh } else { 81603b705cfSriastradh if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) { 81703b705cfSriastradh *out_x = x + pSrc->pDrawable->x; 81803b705cfSriastradh *out_y = y + pSrc->pDrawable->y; 81903b705cfSriastradh return pSrc; 82003b705cfSriastradh } 82103b705cfSriastradh } 82203b705cfSriastradh 82303b705cfSriastradh pPixmap = pScreen->CreatePixmap(pScreen, 82403b705cfSriastradh width, height, depth, 82503b705cfSriastradh CREATE_PIXMAP_USAGE_SCRATCH); 82603b705cfSriastradh if (!pPixmap) 82703b705cfSriastradh return 0; 82803b705cfSriastradh 82903b705cfSriastradh /* Skip the copy if the result remains in memory and not a bo */ 83003b705cfSriastradh if (!uxa_pixmap_is_offscreen(pPixmap)) { 83103b705cfSriastradh pScreen->DestroyPixmap(pPixmap); 83203b705cfSriastradh return 0; 83303b705cfSriastradh } 83403b705cfSriastradh 83503b705cfSriastradh pGC = GetScratchGC(depth, pScreen); 83603b705cfSriastradh if (!pGC) { 83703b705cfSriastradh pScreen->DestroyPixmap(pPixmap); 83803b705cfSriastradh return 0; 83903b705cfSriastradh } 84003b705cfSriastradh 84103b705cfSriastradh ValidateGC(&pPixmap->drawable, pGC); 84203b705cfSriastradh pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC, 84303b705cfSriastradh x + tx, y + ty, width, height, 0, 0); 84403b705cfSriastradh FreeScratchGC(pGC); 84503b705cfSriastradh 84603b705cfSriastradh pDst = CreatePicture(0, &pPixmap->drawable, 84703b705cfSriastradh PictureMatchFormat(pScreen, depth, pSrc->format), 84803b705cfSriastradh 0, 0, serverClient, &error); 84903b705cfSriastradh pScreen->DestroyPixmap(pPixmap); 85003b705cfSriastradh if (!pDst) 85103b705cfSriastradh return 0; 85203b705cfSriastradh 85303b705cfSriastradh ValidatePicture(pDst); 85403b705cfSriastradhdone: 85503b705cfSriastradh pDst->componentAlpha = pSrc->componentAlpha; 85603b705cfSriastradh *out_x = 0; 85703b705cfSriastradh *out_y = 0; 85803b705cfSriastradh return pDst; 85903b705cfSriastradh} 86003b705cfSriastradh 86103b705cfSriastradhstatic PicturePtr 86203b705cfSriastradhuxa_acquire_picture(ScreenPtr screen, 86303b705cfSriastradh PicturePtr src, 86403b705cfSriastradh pixman_format_code_t format, 86503b705cfSriastradh INT16 x, INT16 y, 86603b705cfSriastradh CARD16 width, CARD16 height, 86703b705cfSriastradh INT16 * out_x, INT16 * out_y) 86803b705cfSriastradh{ 86903b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 87003b705cfSriastradh 87103b705cfSriastradh if (uxa_screen->info->check_composite_texture && 87203b705cfSriastradh uxa_screen->info->check_composite_texture(screen, src)) { 87303b705cfSriastradh if (src->pDrawable) { 87403b705cfSriastradh *out_x = x + src->pDrawable->x; 87503b705cfSriastradh *out_y = y + src->pDrawable->y; 87603b705cfSriastradh } else { 87703b705cfSriastradh *out_x = x; 87803b705cfSriastradh *out_y = y; 87903b705cfSriastradh } 88003b705cfSriastradh return src; 88103b705cfSriastradh } 88203b705cfSriastradh 88303b705cfSriastradh if (src->pDrawable) { 88403b705cfSriastradh PicturePtr dst; 88503b705cfSriastradh 88603b705cfSriastradh dst = uxa_acquire_drawable(screen, src, 88703b705cfSriastradh x, y, width, height, 88803b705cfSriastradh out_x, out_y); 88903b705cfSriastradh if (!dst) 89003b705cfSriastradh return 0; 89103b705cfSriastradh 89203b705cfSriastradh if (uxa_screen->info->check_composite_texture && 89303b705cfSriastradh !uxa_screen->info->check_composite_texture(screen, dst)) { 89403b705cfSriastradh if (dst != src) 89503b705cfSriastradh FreePicture(dst, 0); 89603b705cfSriastradh return 0; 89703b705cfSriastradh } 89803b705cfSriastradh 89903b705cfSriastradh return dst; 90003b705cfSriastradh } 90103b705cfSriastradh 90203b705cfSriastradh *out_x = 0; 90303b705cfSriastradh *out_y = 0; 90403b705cfSriastradh return uxa_acquire_pattern(screen, src, 90503b705cfSriastradh format, x, y, width, height); 90603b705cfSriastradh} 90703b705cfSriastradh 90803b705cfSriastradhstatic PicturePtr 90903b705cfSriastradhuxa_acquire_source(ScreenPtr screen, 91003b705cfSriastradh PicturePtr pict, 91103b705cfSriastradh INT16 x, INT16 y, 91203b705cfSriastradh CARD16 width, CARD16 height, 91303b705cfSriastradh INT16 * out_x, INT16 * out_y) 91403b705cfSriastradh{ 91503b705cfSriastradh return uxa_acquire_picture (screen, pict, 91642542f5fSchristos PIXMAN_a8r8g8b8, 91703b705cfSriastradh x, y, 91803b705cfSriastradh width, height, 91903b705cfSriastradh out_x, out_y); 92003b705cfSriastradh} 92103b705cfSriastradh 92203b705cfSriastradhstatic PicturePtr 92303b705cfSriastradhuxa_acquire_mask(ScreenPtr screen, 92403b705cfSriastradh PicturePtr pict, 92503b705cfSriastradh INT16 x, INT16 y, 92603b705cfSriastradh INT16 width, INT16 height, 92703b705cfSriastradh INT16 * out_x, INT16 * out_y) 92803b705cfSriastradh{ 92903b705cfSriastradh return uxa_acquire_picture (screen, pict, 93042542f5fSchristos PIXMAN_a8, 93103b705cfSriastradh x, y, 93203b705cfSriastradh width, height, 93303b705cfSriastradh out_x, out_y); 93403b705cfSriastradh} 93503b705cfSriastradh 93603b705cfSriastradhstatic int 93703b705cfSriastradhuxa_try_driver_composite(CARD8 op, 93803b705cfSriastradh PicturePtr pSrc, 93903b705cfSriastradh PicturePtr pMask, 94003b705cfSriastradh PicturePtr pDst, 94103b705cfSriastradh INT16 xSrc, INT16 ySrc, 94203b705cfSriastradh INT16 xMask, INT16 yMask, 94303b705cfSriastradh INT16 xDst, INT16 yDst, 94403b705cfSriastradh CARD16 width, CARD16 height) 94503b705cfSriastradh{ 94603b705cfSriastradh ScreenPtr screen = pDst->pDrawable->pScreen; 94703b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 94803b705cfSriastradh RegionRec region; 94903b705cfSriastradh BoxPtr pbox; 95003b705cfSriastradh int nbox; 95103b705cfSriastradh int xDst_copy = 0, yDst_copy = 0; 95203b705cfSriastradh int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; 95303b705cfSriastradh PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; 95403b705cfSriastradh PicturePtr localSrc, localMask = NULL; 95503b705cfSriastradh PicturePtr localDst = pDst; 95603b705cfSriastradh 95703b705cfSriastradh if (uxa_screen->info->check_composite && 95803b705cfSriastradh !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height)) 95903b705cfSriastradh return -1; 96003b705cfSriastradh 96103b705cfSriastradh if (uxa_screen->info->check_composite_target && 96203b705cfSriastradh !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { 96303b705cfSriastradh int depth = pDst->pDrawable->depth; 96403b705cfSriastradh PixmapPtr pixmap; 96503b705cfSriastradh int error; 96603b705cfSriastradh GCPtr gc; 96703b705cfSriastradh 96803b705cfSriastradh pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); 96903b705cfSriastradh if (uxa_screen->info->check_copy && 97003b705cfSriastradh !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) 97103b705cfSriastradh return -1; 97203b705cfSriastradh 97303b705cfSriastradh pixmap = screen->CreatePixmap(screen, 97403b705cfSriastradh width, height, depth, 97503b705cfSriastradh CREATE_PIXMAP_USAGE_SCRATCH); 97603b705cfSriastradh if (!pixmap) 97703b705cfSriastradh return 0; 97803b705cfSriastradh 97903b705cfSriastradh gc = GetScratchGC(depth, screen); 98003b705cfSriastradh if (!gc) { 98103b705cfSriastradh screen->DestroyPixmap(pixmap); 98203b705cfSriastradh return 0; 98303b705cfSriastradh } 98403b705cfSriastradh 98503b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 98603b705cfSriastradh gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, 98703b705cfSriastradh xDst, yDst, width, height, 0, 0); 98803b705cfSriastradh FreeScratchGC(gc); 98903b705cfSriastradh 99003b705cfSriastradh xDst_copy = xDst; xDst = 0; 99103b705cfSriastradh yDst_copy = yDst; yDst = 0; 99203b705cfSriastradh 99303b705cfSriastradh localDst = CreatePicture(0, &pixmap->drawable, 99403b705cfSriastradh PictureMatchFormat(screen, depth, pDst->format), 99503b705cfSriastradh 0, 0, serverClient, &error); 99603b705cfSriastradh screen->DestroyPixmap(pixmap); 99703b705cfSriastradh 99803b705cfSriastradh if (!localDst) 99903b705cfSriastradh return 0; 100003b705cfSriastradh 100103b705cfSriastradh ValidatePicture(localDst); 100203b705cfSriastradh } 100303b705cfSriastradh 100403b705cfSriastradh pDstPix = 100503b705cfSriastradh uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y); 100603b705cfSriastradh if (!pDstPix) { 100703b705cfSriastradh if (localDst != pDst) 100803b705cfSriastradh FreePicture(localDst, 0); 100903b705cfSriastradh return -1; 101003b705cfSriastradh } 101103b705cfSriastradh 101203b705cfSriastradh xDst += localDst->pDrawable->x; 101303b705cfSriastradh yDst += localDst->pDrawable->y; 101403b705cfSriastradh 101503b705cfSriastradh localSrc = uxa_acquire_source(screen, pSrc, 101603b705cfSriastradh xSrc, ySrc, 101703b705cfSriastradh width, height, 101803b705cfSriastradh &xSrc, &ySrc); 101903b705cfSriastradh if (!localSrc) { 102003b705cfSriastradh if (localDst != pDst) 102103b705cfSriastradh FreePicture(localDst, 0); 102203b705cfSriastradh return 0; 102303b705cfSriastradh } 102403b705cfSriastradh 102503b705cfSriastradh if (pMask) { 102603b705cfSriastradh localMask = uxa_acquire_mask(screen, pMask, 102703b705cfSriastradh xMask, yMask, 102803b705cfSriastradh width, height, 102903b705cfSriastradh &xMask, &yMask); 103003b705cfSriastradh if (!localMask) { 103103b705cfSriastradh if (localSrc != pSrc) 103203b705cfSriastradh FreePicture(localSrc, 0); 103303b705cfSriastradh if (localDst != pDst) 103403b705cfSriastradh FreePicture(localDst, 0); 103503b705cfSriastradh 103603b705cfSriastradh return 0; 103703b705cfSriastradh } 103803b705cfSriastradh } 103903b705cfSriastradh 104003b705cfSriastradh if (!miComputeCompositeRegion(®ion, localSrc, localMask, localDst, 104103b705cfSriastradh xSrc, ySrc, xMask, yMask, xDst, yDst, 104203b705cfSriastradh width, height)) { 104303b705cfSriastradh if (localSrc != pSrc) 104403b705cfSriastradh FreePicture(localSrc, 0); 104503b705cfSriastradh if (localMask && localMask != pMask) 104603b705cfSriastradh FreePicture(localMask, 0); 104703b705cfSriastradh if (localDst != pDst) 104803b705cfSriastradh FreePicture(localDst, 0); 104903b705cfSriastradh 105003b705cfSriastradh return 1; 105103b705cfSriastradh } 105203b705cfSriastradh 105303b705cfSriastradh pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable, 105403b705cfSriastradh &src_off_x, &src_off_y); 105503b705cfSriastradh if (!pSrcPix) { 105603b705cfSriastradh REGION_UNINIT(screen, ®ion); 105703b705cfSriastradh 105803b705cfSriastradh if (localSrc != pSrc) 105903b705cfSriastradh FreePicture(localSrc, 0); 106003b705cfSriastradh if (localMask && localMask != pMask) 106103b705cfSriastradh FreePicture(localMask, 0); 106203b705cfSriastradh if (localDst != pDst) 106303b705cfSriastradh FreePicture(localDst, 0); 106403b705cfSriastradh 106503b705cfSriastradh return 0; 106603b705cfSriastradh } 106703b705cfSriastradh 106803b705cfSriastradh if (localMask) { 106903b705cfSriastradh pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable, 107003b705cfSriastradh &mask_off_x, &mask_off_y); 107103b705cfSriastradh if (!pMaskPix) { 107203b705cfSriastradh REGION_UNINIT(screen, ®ion); 107303b705cfSriastradh 107403b705cfSriastradh if (localSrc != pSrc) 107503b705cfSriastradh FreePicture(localSrc, 0); 107603b705cfSriastradh if (localMask && localMask != pMask) 107703b705cfSriastradh FreePicture(localMask, 0); 107803b705cfSriastradh if (localDst != pDst) 107903b705cfSriastradh FreePicture(localDst, 0); 108003b705cfSriastradh 108103b705cfSriastradh return 0; 108203b705cfSriastradh } 108303b705cfSriastradh } 108403b705cfSriastradh 108503b705cfSriastradh if (!(*uxa_screen->info->prepare_composite) 108603b705cfSriastradh (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) { 108703b705cfSriastradh REGION_UNINIT(screen, ®ion); 108803b705cfSriastradh 108903b705cfSriastradh if (localSrc != pSrc) 109003b705cfSriastradh FreePicture(localSrc, 0); 109103b705cfSriastradh if (localMask && localMask != pMask) 109203b705cfSriastradh FreePicture(localMask, 0); 109303b705cfSriastradh if (localDst != pDst) 109403b705cfSriastradh FreePicture(localDst, 0); 109503b705cfSriastradh 109603b705cfSriastradh return -1; 109703b705cfSriastradh } 109803b705cfSriastradh 109903b705cfSriastradh if (pMask) { 110003b705cfSriastradh xMask = xMask + mask_off_x - xDst; 110103b705cfSriastradh yMask = yMask + mask_off_y - yDst; 110203b705cfSriastradh } 110303b705cfSriastradh 110403b705cfSriastradh xSrc = xSrc + src_off_x - xDst; 110503b705cfSriastradh ySrc = ySrc + src_off_y - yDst; 110603b705cfSriastradh 110703b705cfSriastradh nbox = REGION_NUM_RECTS(®ion); 110803b705cfSriastradh pbox = REGION_RECTS(®ion); 110903b705cfSriastradh while (nbox--) { 111003b705cfSriastradh (*uxa_screen->info->composite) (pDstPix, 111103b705cfSriastradh pbox->x1 + xSrc, 111203b705cfSriastradh pbox->y1 + ySrc, 111303b705cfSriastradh pbox->x1 + xMask, 111403b705cfSriastradh pbox->y1 + yMask, 111503b705cfSriastradh pbox->x1 + dst_off_x, 111603b705cfSriastradh pbox->y1 + dst_off_y, 111703b705cfSriastradh pbox->x2 - pbox->x1, 111803b705cfSriastradh pbox->y2 - pbox->y1); 111903b705cfSriastradh pbox++; 112003b705cfSriastradh } 112103b705cfSriastradh (*uxa_screen->info->done_composite) (pDstPix); 112203b705cfSriastradh 112303b705cfSriastradh REGION_UNINIT(screen, ®ion); 112403b705cfSriastradh 112503b705cfSriastradh if (localSrc != pSrc) 112603b705cfSriastradh FreePicture(localSrc, 0); 112703b705cfSriastradh if (localMask && localMask != pMask) 112803b705cfSriastradh FreePicture(localMask, 0); 112903b705cfSriastradh 113003b705cfSriastradh if (localDst != pDst) { 113103b705cfSriastradh GCPtr gc; 113203b705cfSriastradh 113303b705cfSriastradh gc = GetScratchGC(pDst->pDrawable->depth, screen); 113403b705cfSriastradh if (gc) { 113503b705cfSriastradh ValidateGC(pDst->pDrawable, gc); 113603b705cfSriastradh gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, 113703b705cfSriastradh 0, 0, width, height, xDst_copy, yDst_copy); 113803b705cfSriastradh FreeScratchGC(gc); 113903b705cfSriastradh } 114003b705cfSriastradh 114103b705cfSriastradh FreePicture(localDst, 0); 114203b705cfSriastradh } 114303b705cfSriastradh 114403b705cfSriastradh return 1; 114503b705cfSriastradh} 114603b705cfSriastradh 114703b705cfSriastradh/** 114803b705cfSriastradh * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of 114903b705cfSriastradh * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component 115003b705cfSriastradh * alpha and limited 1-tmu cards. 115103b705cfSriastradh * 115203b705cfSriastradh * From http://anholt.livejournal.com/32058.html: 115303b705cfSriastradh * 115403b705cfSriastradh * The trouble is that component-alpha rendering requires two different sources 115503b705cfSriastradh * for blending: one for the source value to the blender, which is the 115603b705cfSriastradh * per-channel multiplication of source and mask, and one for the source alpha 115703b705cfSriastradh * for multiplying with the destination channels, which is the multiplication 115803b705cfSriastradh * of the source channels by the mask alpha. So the equation for Over is: 115903b705cfSriastradh * 116003b705cfSriastradh * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A 116103b705cfSriastradh * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R 116203b705cfSriastradh * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G 116303b705cfSriastradh * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B 116403b705cfSriastradh * 116503b705cfSriastradh * But we can do some simpler operations, right? How about PictOpOutReverse, 116603b705cfSriastradh * which has a source factor of 0 and dest factor of (1 - source alpha). We 116703b705cfSriastradh * can get the source alpha value (srca.X = src.A * mask.X) out of the texture 116803b705cfSriastradh * blenders pretty easily. So we can do a component-alpha OutReverse, which 116903b705cfSriastradh * gets us: 117003b705cfSriastradh * 117103b705cfSriastradh * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A 117203b705cfSriastradh * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R 117303b705cfSriastradh * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G 117403b705cfSriastradh * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B 117503b705cfSriastradh * 117603b705cfSriastradh * OK. And if an op doesn't use the source alpha value for the destination 117703b705cfSriastradh * factor, then we can do the channel multiplication in the texture blenders 117803b705cfSriastradh * to get the source value, and ignore the source alpha that we wouldn't use. 117903b705cfSriastradh * We've supported this in the Radeon driver for a long time. An example would 118003b705cfSriastradh * be PictOpAdd, which does: 118103b705cfSriastradh * 118203b705cfSriastradh * dst.A = src.A * mask.A + dst.A 118303b705cfSriastradh * dst.R = src.R * mask.R + dst.R 118403b705cfSriastradh * dst.G = src.G * mask.G + dst.G 118503b705cfSriastradh * dst.B = src.B * mask.B + dst.B 118603b705cfSriastradh * 118703b705cfSriastradh * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right 118803b705cfSriastradh * after it, we get: 118903b705cfSriastradh * 119003b705cfSriastradh * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) 119103b705cfSriastradh * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) 119203b705cfSriastradh * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) 119303b705cfSriastradh * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) 119403b705cfSriastradh */ 119503b705cfSriastradh 119603b705cfSriastradhstatic int 119703b705cfSriastradhuxa_try_magic_two_pass_composite_helper(CARD8 op, 119803b705cfSriastradh PicturePtr pSrc, 119903b705cfSriastradh PicturePtr pMask, 120003b705cfSriastradh PicturePtr pDst, 120103b705cfSriastradh INT16 xSrc, INT16 ySrc, 120203b705cfSriastradh INT16 xMask, INT16 yMask, 120303b705cfSriastradh INT16 xDst, INT16 yDst, 120403b705cfSriastradh CARD16 width, CARD16 height) 120503b705cfSriastradh{ 120603b705cfSriastradh ScreenPtr screen = pDst->pDrawable->pScreen; 120703b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 120803b705cfSriastradh PicturePtr localDst = pDst; 120903b705cfSriastradh int xDst_copy, yDst_copy; 121003b705cfSriastradh 121103b705cfSriastradh assert(op == PictOpOver); 121203b705cfSriastradh 121303b705cfSriastradh if (uxa_screen->info->check_composite && 121403b705cfSriastradh (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc, 121503b705cfSriastradh pMask, pDst, width, height) 121603b705cfSriastradh || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask, 121703b705cfSriastradh pDst, width, height))) { 121803b705cfSriastradh return -1; 121903b705cfSriastradh } 122003b705cfSriastradh 122103b705cfSriastradh if (uxa_screen->info->check_composite_target && 122203b705cfSriastradh !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { 122303b705cfSriastradh int depth = pDst->pDrawable->depth; 122403b705cfSriastradh PixmapPtr pixmap; 122503b705cfSriastradh int error; 122603b705cfSriastradh GCPtr gc; 122703b705cfSriastradh 122803b705cfSriastradh pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); 122903b705cfSriastradh if (uxa_screen->info->check_copy && 123003b705cfSriastradh !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) 123103b705cfSriastradh return -1; 123203b705cfSriastradh 123303b705cfSriastradh pixmap = screen->CreatePixmap(screen, 123403b705cfSriastradh width, height, depth, 123503b705cfSriastradh CREATE_PIXMAP_USAGE_SCRATCH); 123603b705cfSriastradh if (!pixmap) 123703b705cfSriastradh return 0; 123803b705cfSriastradh 123903b705cfSriastradh gc = GetScratchGC(depth, screen); 124003b705cfSriastradh if (!gc) { 124103b705cfSriastradh screen->DestroyPixmap(pixmap); 124203b705cfSriastradh return 0; 124303b705cfSriastradh } 124403b705cfSriastradh 124503b705cfSriastradh ValidateGC(&pixmap->drawable, gc); 124603b705cfSriastradh gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, 124703b705cfSriastradh xDst, yDst, width, height, 0, 0); 124803b705cfSriastradh FreeScratchGC(gc); 124903b705cfSriastradh 125003b705cfSriastradh xDst_copy = xDst; xDst = 0; 125103b705cfSriastradh yDst_copy = yDst; yDst = 0; 125203b705cfSriastradh 125303b705cfSriastradh localDst = CreatePicture(0, &pixmap->drawable, 125403b705cfSriastradh PictureMatchFormat(screen, depth, pDst->format), 125503b705cfSriastradh 0, 0, serverClient, &error); 125603b705cfSriastradh screen->DestroyPixmap(pixmap); 125703b705cfSriastradh 125803b705cfSriastradh if (!localDst) 125903b705cfSriastradh return 0; 126003b705cfSriastradh 126103b705cfSriastradh ValidatePicture(localDst); 126203b705cfSriastradh } 126303b705cfSriastradh 126403b705cfSriastradh /* Now, we think we should be able to accelerate this operation. First, 126503b705cfSriastradh * composite the destination to be the destination times the source alpha 126603b705cfSriastradh * factors. 126703b705cfSriastradh */ 126803b705cfSriastradh uxa_composite(PictOpOutReverse, pSrc, pMask, localDst, 126903b705cfSriastradh xSrc, ySrc, 127003b705cfSriastradh xMask, yMask, 127103b705cfSriastradh xDst, yDst, 127203b705cfSriastradh width, height); 127303b705cfSriastradh 127403b705cfSriastradh /* Then, add in the source value times the destination alpha factors (1.0). 127503b705cfSriastradh */ 127603b705cfSriastradh uxa_composite(PictOpAdd, pSrc, pMask, localDst, 127703b705cfSriastradh xSrc, ySrc, 127803b705cfSriastradh xMask, yMask, 127903b705cfSriastradh xDst, yDst, 128003b705cfSriastradh width, height); 128103b705cfSriastradh 128203b705cfSriastradh if (localDst != pDst) { 128303b705cfSriastradh GCPtr gc; 128403b705cfSriastradh 128503b705cfSriastradh gc = GetScratchGC(pDst->pDrawable->depth, screen); 128603b705cfSriastradh if (gc) { 128703b705cfSriastradh ValidateGC(pDst->pDrawable, gc); 128803b705cfSriastradh gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, 128903b705cfSriastradh 0, 0, width, height, xDst_copy, yDst_copy); 129003b705cfSriastradh FreeScratchGC(gc); 129103b705cfSriastradh } 129203b705cfSriastradh 129303b705cfSriastradh FreePicture(localDst, 0); 129403b705cfSriastradh } 129503b705cfSriastradh 129603b705cfSriastradh return 1; 129703b705cfSriastradh} 129803b705cfSriastradh 129903b705cfSriastradhstatic int 130003b705cfSriastradhcompatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) 130103b705cfSriastradh{ 130203b705cfSriastradh if (op == PictOpSrc) { 130303b705cfSriastradh if (src->format == dst->format) 130403b705cfSriastradh return 1; 130503b705cfSriastradh 130603b705cfSriastradh /* Is the destination an alpha-less version of source? */ 130703b705cfSriastradh if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format), 130803b705cfSriastradh PICT_FORMAT_TYPE(src->format), 130903b705cfSriastradh 0, 131003b705cfSriastradh PICT_FORMAT_R(src->format), 131103b705cfSriastradh PICT_FORMAT_G(src->format), 131203b705cfSriastradh PICT_FORMAT_B(src->format))) 131303b705cfSriastradh return 1; 131403b705cfSriastradh 131503b705cfSriastradh /* XXX xrgb is promoted to argb during image upload... */ 131603b705cfSriastradh#if 0 131703b705cfSriastradh if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8) 131803b705cfSriastradh return 1; 131903b705cfSriastradh#endif 132003b705cfSriastradh } else if (op == PictOpOver) { 132103b705cfSriastradh if (PICT_FORMAT_A(src->format)) 132203b705cfSriastradh return 0; 132303b705cfSriastradh 132403b705cfSriastradh return src->format == dst->format; 132503b705cfSriastradh } 132603b705cfSriastradh 132703b705cfSriastradh return 0; 132803b705cfSriastradh} 132903b705cfSriastradh 133003b705cfSriastradhvoid 133103b705cfSriastradhuxa_composite(CARD8 op, 133203b705cfSriastradh PicturePtr pSrc, 133303b705cfSriastradh PicturePtr pMask, 133403b705cfSriastradh PicturePtr pDst, 133503b705cfSriastradh INT16 xSrc, INT16 ySrc, 133603b705cfSriastradh INT16 xMask, INT16 yMask, 133703b705cfSriastradh INT16 xDst, INT16 yDst, 133803b705cfSriastradh CARD16 width, CARD16 height) 133903b705cfSriastradh{ 134003b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 134103b705cfSriastradh int ret = -1; 134203b705cfSriastradh Bool saveSrcRepeat = pSrc->repeat; 134303b705cfSriastradh Bool saveMaskRepeat = pMask ? pMask->repeat : 0; 134403b705cfSriastradh RegionRec region; 134503b705cfSriastradh int tx, ty; 134603b705cfSriastradh 134703b705cfSriastradh if (uxa_screen->force_fallback) 134803b705cfSriastradh goto fallback; 134903b705cfSriastradh 135003b705cfSriastradh if (!uxa_drawable_is_offscreen(pDst->pDrawable)) 135103b705cfSriastradh goto fallback; 135203b705cfSriastradh 135303b705cfSriastradh if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) 135403b705cfSriastradh goto fallback; 135503b705cfSriastradh 135603b705cfSriastradh /* Remove repeat in source if useless */ 135703b705cfSriastradh if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution && 135803b705cfSriastradh transform_is_integer_translation(pSrc->transform, &tx, &ty) && 135903b705cfSriastradh (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) && 136003b705cfSriastradh drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height)) 136103b705cfSriastradh pSrc->repeat = 0; 136203b705cfSriastradh 136303b705cfSriastradh if (!pMask) { 136403b705cfSriastradh if (op == PictOpClear) { 136503b705cfSriastradh PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen); 136603b705cfSriastradh if (clear && 136703b705cfSriastradh uxa_try_driver_solid_fill(clear, pDst, 136803b705cfSriastradh xSrc, ySrc, 136903b705cfSriastradh xDst, yDst, 137003b705cfSriastradh width, height) == 1) 137103b705cfSriastradh goto done; 137203b705cfSriastradh } 137303b705cfSriastradh 137403b705cfSriastradh if (pSrc->pDrawable == NULL) { 137503b705cfSriastradh if (pSrc->pSourcePict) { 137603b705cfSriastradh SourcePict *source = pSrc->pSourcePict; 137703b705cfSriastradh if (source->type == SourcePictTypeSolidFill) { 137803b705cfSriastradh if (op == PictOpSrc || 137903b705cfSriastradh (op == PictOpOver && 138003b705cfSriastradh (source->solidFill.color & 0xff000000) == 0xff000000)) { 138103b705cfSriastradh ret = uxa_try_driver_solid_fill(pSrc, pDst, 138203b705cfSriastradh xSrc, ySrc, 138303b705cfSriastradh xDst, yDst, 138403b705cfSriastradh width, height); 138503b705cfSriastradh if (ret == 1) 138603b705cfSriastradh goto done; 138703b705cfSriastradh } 138803b705cfSriastradh } 138903b705cfSriastradh } 139003b705cfSriastradh } else if (pSrc->pDrawable->width == 1 && 139103b705cfSriastradh pSrc->pDrawable->height == 1 && 139203b705cfSriastradh pSrc->repeat && 139303b705cfSriastradh (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) { 139403b705cfSriastradh ret = uxa_try_driver_solid_fill(pSrc, pDst, 139503b705cfSriastradh xSrc, ySrc, 139603b705cfSriastradh xDst, yDst, 139703b705cfSriastradh width, height); 139803b705cfSriastradh if (ret == 1) 139903b705cfSriastradh goto done; 140003b705cfSriastradh } else if (compatible_formats (op, pDst, pSrc) && 140103b705cfSriastradh pSrc->filter != PictFilterConvolution && 140203b705cfSriastradh transform_is_integer_translation(pSrc->transform, &tx, &ty)) { 140303b705cfSriastradh if (!pSrc->repeat && 140403b705cfSriastradh drawable_contains(pSrc->pDrawable, 140503b705cfSriastradh xSrc + tx, ySrc + ty, 140603b705cfSriastradh width, height)) { 140703b705cfSriastradh xDst += pDst->pDrawable->x; 140803b705cfSriastradh yDst += pDst->pDrawable->y; 140903b705cfSriastradh xSrc += pSrc->pDrawable->x + tx; 141003b705cfSriastradh ySrc += pSrc->pDrawable->y + ty; 141103b705cfSriastradh 141203b705cfSriastradh if (!miComputeCompositeRegion 141303b705cfSriastradh (®ion, pSrc, pMask, pDst, xSrc, ySrc, 141403b705cfSriastradh xMask, yMask, xDst, yDst, width, height)) 141503b705cfSriastradh goto done; 141603b705cfSriastradh 141703b705cfSriastradh uxa_copy_n_to_n(pSrc->pDrawable, 141803b705cfSriastradh pDst->pDrawable, NULL, 141903b705cfSriastradh REGION_RECTS(®ion), 142003b705cfSriastradh REGION_NUM_RECTS(®ion), 142103b705cfSriastradh xSrc - xDst, ySrc - yDst, FALSE, 142203b705cfSriastradh FALSE, 0, NULL); 142303b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, 142403b705cfSriastradh ®ion); 142503b705cfSriastradh goto done; 142603b705cfSriastradh } else if (pSrc->repeat && pSrc->repeatType == RepeatNormal && 142703b705cfSriastradh pSrc->pDrawable->type == DRAWABLE_PIXMAP) { 142803b705cfSriastradh DDXPointRec patOrg; 142903b705cfSriastradh 143003b705cfSriastradh /* Let's see if the driver can do the repeat 143103b705cfSriastradh * in one go 143203b705cfSriastradh */ 143303b705cfSriastradh if (uxa_screen->info->prepare_composite) { 143403b705cfSriastradh ret = uxa_try_driver_composite(op, pSrc, 143503b705cfSriastradh pMask, pDst, 143603b705cfSriastradh xSrc, ySrc, 143703b705cfSriastradh xMask, yMask, 143803b705cfSriastradh xDst, yDst, 143903b705cfSriastradh width, height); 144003b705cfSriastradh if (ret == 1) 144103b705cfSriastradh goto done; 144203b705cfSriastradh } 144303b705cfSriastradh 144403b705cfSriastradh /* Now see if we can use 144503b705cfSriastradh * uxa_fill_region_tiled() 144603b705cfSriastradh */ 144703b705cfSriastradh xDst += pDst->pDrawable->x; 144803b705cfSriastradh yDst += pDst->pDrawable->y; 144903b705cfSriastradh xSrc += pSrc->pDrawable->x + tx; 145003b705cfSriastradh ySrc += pSrc->pDrawable->y + ty; 145103b705cfSriastradh 145203b705cfSriastradh if (!miComputeCompositeRegion 145303b705cfSriastradh (®ion, pSrc, pMask, pDst, xSrc, ySrc, 145403b705cfSriastradh xMask, yMask, xDst, yDst, width, height)) 145503b705cfSriastradh goto done; 145603b705cfSriastradh 145703b705cfSriastradh /* pattern origin is the point in the 145803b705cfSriastradh * destination drawable 145903b705cfSriastradh * corresponding to (0,0) in the source */ 146003b705cfSriastradh patOrg.x = xDst - xSrc; 146103b705cfSriastradh patOrg.y = yDst - ySrc; 146203b705cfSriastradh 146303b705cfSriastradh ret = uxa_fill_region_tiled(pDst->pDrawable, 146403b705cfSriastradh ®ion, 146503b705cfSriastradh (PixmapPtr) pSrc-> 146603b705cfSriastradh pDrawable, &patOrg, 146703b705cfSriastradh FB_ALLONES, GXcopy); 146803b705cfSriastradh 146903b705cfSriastradh REGION_UNINIT(pDst->pDrawable->pScreen, 147003b705cfSriastradh ®ion); 147103b705cfSriastradh 147203b705cfSriastradh if (ret) 147303b705cfSriastradh goto done; 147403b705cfSriastradh } 147503b705cfSriastradh } 147603b705cfSriastradh } 147703b705cfSriastradh 147803b705cfSriastradh /* Remove repeat in mask if useless */ 147903b705cfSriastradh if (pMask && pMask->pDrawable && pMask->repeat && 148003b705cfSriastradh pMask->filter != PictFilterConvolution && 148103b705cfSriastradh transform_is_integer_translation(pMask->transform, &tx, &ty) && 148203b705cfSriastradh (pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) && 148303b705cfSriastradh drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height)) 148403b705cfSriastradh pMask->repeat = 0; 148503b705cfSriastradh 148603b705cfSriastradh if (uxa_screen->info->prepare_composite) { 148703b705cfSriastradh Bool isSrcSolid; 148803b705cfSriastradh 148903b705cfSriastradh ret = 149003b705cfSriastradh uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, 149103b705cfSriastradh xMask, yMask, xDst, yDst, width, 149203b705cfSriastradh height); 149303b705cfSriastradh if (ret == 1) 149403b705cfSriastradh goto done; 149503b705cfSriastradh 149603b705cfSriastradh /* For generic masks and solid src pictures, mach64 can do 149703b705cfSriastradh * Over in two passes, similar to the component-alpha case. 149803b705cfSriastradh */ 149903b705cfSriastradh 150003b705cfSriastradh isSrcSolid = 150103b705cfSriastradh pSrc->pDrawable ? 150203b705cfSriastradh pSrc->pDrawable->width == 1 && 150303b705cfSriastradh pSrc->pDrawable->height == 1 && 150403b705cfSriastradh pSrc->repeat : 150503b705cfSriastradh pSrc->pSourcePict ? 150603b705cfSriastradh pSrc->pSourcePict->type == SourcePictTypeSolidFill : 150703b705cfSriastradh 0; 150803b705cfSriastradh 150903b705cfSriastradh /* If we couldn't do the Composite in a single pass, and it 151003b705cfSriastradh * was a component-alpha Over, see if we can do it in two 151103b705cfSriastradh * passes with an OutReverse and then an Add. 151203b705cfSriastradh */ 151303b705cfSriastradh if (ret == -1 && op == PictOpOver && pMask && 151403b705cfSriastradh (pMask->componentAlpha || isSrcSolid)) { 151503b705cfSriastradh ret = 151603b705cfSriastradh uxa_try_magic_two_pass_composite_helper(op, pSrc, 151703b705cfSriastradh pMask, pDst, 151803b705cfSriastradh xSrc, ySrc, 151903b705cfSriastradh xMask, yMask, 152003b705cfSriastradh xDst, yDst, 152103b705cfSriastradh width, height); 152203b705cfSriastradh if (ret == 1) 152303b705cfSriastradh goto done; 152403b705cfSriastradh } 152503b705cfSriastradh 152603b705cfSriastradh } 152703b705cfSriastradh 152803b705cfSriastradhfallback: 152903b705cfSriastradh uxa_print_composite_fallback("uxa_composite", 153003b705cfSriastradh op, pSrc, pMask, pDst); 153103b705cfSriastradh 153203b705cfSriastradh uxa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, 153303b705cfSriastradh xMask, yMask, xDst, yDst, width, height); 153403b705cfSriastradh 153503b705cfSriastradhdone: 153603b705cfSriastradh pSrc->repeat = saveSrcRepeat; 153703b705cfSriastradh if (pMask) 153803b705cfSriastradh pMask->repeat = saveMaskRepeat; 153903b705cfSriastradh} 154003b705cfSriastradh#endif 154103b705cfSriastradh 154203b705cfSriastradh/** 154303b705cfSriastradh * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead 154403b705cfSriastradh * of PolyFillRect to initialize the pixmap after creating it, to prevent 154503b705cfSriastradh * the pixmap from being migrated. 154603b705cfSriastradh * 154703b705cfSriastradh * See the comments about uxa_trapezoids and uxa_triangles. 154803b705cfSriastradh */ 154903b705cfSriastradhstatic PicturePtr 155003b705cfSriastradhuxa_create_alpha_picture(ScreenPtr pScreen, 155103b705cfSriastradh PicturePtr pDst, 155203b705cfSriastradh PictFormatPtr pPictFormat, CARD16 width, CARD16 height) 155303b705cfSriastradh{ 155403b705cfSriastradh PixmapPtr pPixmap; 155503b705cfSriastradh PicturePtr pPicture; 155603b705cfSriastradh int error; 155703b705cfSriastradh 155803b705cfSriastradh if (width > 32767 || height > 32767) 155903b705cfSriastradh return 0; 156003b705cfSriastradh 156103b705cfSriastradh if (!pPictFormat) { 156203b705cfSriastradh if (pDst->polyEdge == PolyEdgeSharp) 156303b705cfSriastradh pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1); 156403b705cfSriastradh else 156503b705cfSriastradh pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8); 156603b705cfSriastradh if (!pPictFormat) 156703b705cfSriastradh return 0; 156803b705cfSriastradh } 156903b705cfSriastradh 157003b705cfSriastradh pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 157103b705cfSriastradh pPictFormat->depth, 157203b705cfSriastradh UXA_CREATE_PIXMAP_FOR_MAP); 157303b705cfSriastradh if (!pPixmap) 157403b705cfSriastradh return 0; 157503b705cfSriastradh pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, 157603b705cfSriastradh 0, 0, serverClient, &error); 157703b705cfSriastradh (*pScreen->DestroyPixmap) (pPixmap); 157803b705cfSriastradh return pPicture; 157903b705cfSriastradh} 158003b705cfSriastradh 158103b705cfSriastradhstatic void 158203b705cfSriastradhuxa_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, 158303b705cfSriastradh PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 158403b705cfSriastradh int ntrap, xTrapezoid * traps) 158503b705cfSriastradh{ 158603b705cfSriastradh ScreenPtr screen = dst->pDrawable->pScreen; 158703b705cfSriastradh 158803b705cfSriastradh if (maskFormat) { 158903b705cfSriastradh PixmapPtr scratch = NULL; 159003b705cfSriastradh PicturePtr mask; 159103b705cfSriastradh INT16 xDst, yDst; 159203b705cfSriastradh INT16 xRel, yRel; 159303b705cfSriastradh BoxRec bounds; 159403b705cfSriastradh int width, height; 159503b705cfSriastradh pixman_image_t *image; 159603b705cfSriastradh pixman_format_code_t format; 159703b705cfSriastradh int error; 159803b705cfSriastradh 159903b705cfSriastradh xDst = traps[0].left.p1.x >> 16; 160003b705cfSriastradh yDst = traps[0].left.p1.y >> 16; 160103b705cfSriastradh 160203b705cfSriastradh miTrapezoidBounds (ntrap, traps, &bounds); 160303b705cfSriastradh if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 160403b705cfSriastradh return; 160503b705cfSriastradh 160603b705cfSriastradh width = bounds.x2 - bounds.x1; 160703b705cfSriastradh height = bounds.y2 - bounds.y1; 160803b705cfSriastradh 160903b705cfSriastradh format = maskFormat->format | 161003b705cfSriastradh (BitsPerPixel(maskFormat->depth) << 24); 161103b705cfSriastradh image = 161203b705cfSriastradh pixman_image_create_bits(format, width, height, NULL, 0); 161303b705cfSriastradh if (!image) 161403b705cfSriastradh return; 161503b705cfSriastradh 161603b705cfSriastradh for (; ntrap; ntrap--, traps++) 161703b705cfSriastradh pixman_rasterize_trapezoid(image, 161803b705cfSriastradh (pixman_trapezoid_t *) traps, 161903b705cfSriastradh -bounds.x1, -bounds.y1); 162003b705cfSriastradh 162103b705cfSriastradh 162203b705cfSriastradh scratch = GetScratchPixmapHeader(screen, width, height, 162303b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 162403b705cfSriastradh PIXMAN_FORMAT_BPP(format), 162503b705cfSriastradh pixman_image_get_stride(image), 162603b705cfSriastradh pixman_image_get_data(image)); 162703b705cfSriastradh if (!scratch) { 162803b705cfSriastradh pixman_image_unref(image); 162903b705cfSriastradh return; 163003b705cfSriastradh } 163103b705cfSriastradh 163203b705cfSriastradh mask = CreatePicture(0, &scratch->drawable, 163303b705cfSriastradh PictureMatchFormat(screen, 163403b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 163503b705cfSriastradh format), 163603b705cfSriastradh 0, 0, serverClient, &error); 163703b705cfSriastradh if (!mask) { 163803b705cfSriastradh FreeScratchPixmapHeader(scratch); 163903b705cfSriastradh pixman_image_unref(image); 164003b705cfSriastradh return; 164103b705cfSriastradh } 164203b705cfSriastradh 164303b705cfSriastradh xRel = bounds.x1 + xSrc - xDst; 164403b705cfSriastradh yRel = bounds.y1 + ySrc - yDst; 164503b705cfSriastradh CompositePicture(op, src, mask, dst, 164603b705cfSriastradh xRel, yRel, 164703b705cfSriastradh 0, 0, 164803b705cfSriastradh bounds.x1, bounds.y1, 164903b705cfSriastradh width, height); 165003b705cfSriastradh FreePicture(mask, 0); 165103b705cfSriastradh 165203b705cfSriastradh FreeScratchPixmapHeader(scratch); 165303b705cfSriastradh pixman_image_unref(image); 165403b705cfSriastradh } else { 165503b705cfSriastradh if (dst->polyEdge == PolyEdgeSharp) 165603b705cfSriastradh maskFormat = PictureMatchFormat(screen, 1, PICT_a1); 165703b705cfSriastradh else 165803b705cfSriastradh maskFormat = PictureMatchFormat(screen, 8, PICT_a8); 165903b705cfSriastradh 166003b705cfSriastradh for (; ntrap; ntrap--, traps++) 166103b705cfSriastradh uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps); 166203b705cfSriastradh } 166303b705cfSriastradh} 166403b705cfSriastradh 166503b705cfSriastradh/** 166603b705cfSriastradh * uxa_trapezoids is essentially a copy of miTrapezoids that uses 166703b705cfSriastradh * uxa_create_alpha_picture instead of miCreateAlphaPicture. 166803b705cfSriastradh * 166903b705cfSriastradh * The problem with miCreateAlphaPicture is that it calls PolyFillRect 167003b705cfSriastradh * to initialize the contents after creating the pixmap, which 167103b705cfSriastradh * causes the pixmap to be moved in for acceleration. The subsequent 167203b705cfSriastradh * call to RasterizeTrapezoid won't be accelerated however, which 167303b705cfSriastradh * forces the pixmap to be moved out again. 167403b705cfSriastradh * 167503b705cfSriastradh * uxa_create_alpha_picture avoids this roundtrip by using 167603b705cfSriastradh * uxa_check_poly_fill_rect to initialize the contents. 167703b705cfSriastradh */ 167803b705cfSriastradhvoid 167903b705cfSriastradhuxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, 168003b705cfSriastradh PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 168103b705cfSriastradh int ntrap, xTrapezoid * traps) 168203b705cfSriastradh{ 168303b705cfSriastradh ScreenPtr screen = dst->pDrawable->pScreen; 168403b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(screen); 168503b705cfSriastradh BoxRec bounds; 168603b705cfSriastradh Bool direct; 168703b705cfSriastradh 168803b705cfSriastradh if (uxa_screen->force_fallback) { 168903b705cfSriastradh uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps); 169003b705cfSriastradh return; 169103b705cfSriastradh } 169203b705cfSriastradh 169303b705cfSriastradh direct = op == PictOpAdd && miIsSolidAlpha(src); 169403b705cfSriastradh if (maskFormat || direct) { 169503b705cfSriastradh miTrapezoidBounds(ntrap, traps, &bounds); 169603b705cfSriastradh 169703b705cfSriastradh if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 169803b705cfSriastradh return; 169903b705cfSriastradh } 170003b705cfSriastradh 170103b705cfSriastradh /* 170203b705cfSriastradh * Check for solid alpha add 170303b705cfSriastradh */ 170403b705cfSriastradh if (direct) { 170503b705cfSriastradh DrawablePtr pDraw = dst->pDrawable; 170603b705cfSriastradh PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw); 170703b705cfSriastradh int xoff, yoff; 170803b705cfSriastradh 170903b705cfSriastradh uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff); 171003b705cfSriastradh 171103b705cfSriastradh xoff += pDraw->x; 171203b705cfSriastradh yoff += pDraw->y; 171303b705cfSriastradh 171403b705cfSriastradh if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) { 171503b705cfSriastradh PictureScreenPtr ps = GetPictureScreen(screen); 171603b705cfSriastradh 171703b705cfSriastradh for (; ntrap; ntrap--, traps++) 171803b705cfSriastradh (*ps->RasterizeTrapezoid) (dst, traps, 0, 0); 171903b705cfSriastradh uxa_finish_access(pDraw, UXA_ACCESS_RW); 172003b705cfSriastradh } 172103b705cfSriastradh } else if (maskFormat) { 172203b705cfSriastradh PixmapPtr scratch = NULL; 172303b705cfSriastradh PicturePtr mask; 172403b705cfSriastradh INT16 xDst, yDst; 172503b705cfSriastradh INT16 xRel, yRel; 172603b705cfSriastradh int width, height; 172703b705cfSriastradh pixman_image_t *image; 172803b705cfSriastradh pixman_format_code_t format; 172903b705cfSriastradh 173003b705cfSriastradh xDst = traps[0].left.p1.x >> 16; 173103b705cfSriastradh yDst = traps[0].left.p1.y >> 16; 173203b705cfSriastradh 173303b705cfSriastradh width = bounds.x2 - bounds.x1; 173403b705cfSriastradh height = bounds.y2 - bounds.y1; 173503b705cfSriastradh 173603b705cfSriastradh format = maskFormat->format | 173703b705cfSriastradh (BitsPerPixel(maskFormat->depth) << 24); 173803b705cfSriastradh image = 173903b705cfSriastradh pixman_image_create_bits(format, width, height, NULL, 0); 174003b705cfSriastradh if (!image) 174103b705cfSriastradh return; 174203b705cfSriastradh 174303b705cfSriastradh for (; ntrap; ntrap--, traps++) 174403b705cfSriastradh pixman_rasterize_trapezoid(image, 174503b705cfSriastradh (pixman_trapezoid_t *) traps, 174603b705cfSriastradh -bounds.x1, -bounds.y1); 174703b705cfSriastradh if (uxa_drawable_is_offscreen(dst->pDrawable)) { 174803b705cfSriastradh mask = uxa_picture_from_pixman_image(screen, image, format); 174903b705cfSriastradh } else { 175003b705cfSriastradh int error; 175103b705cfSriastradh 175203b705cfSriastradh scratch = GetScratchPixmapHeader(screen, width, height, 175303b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 175403b705cfSriastradh PIXMAN_FORMAT_BPP(format), 175503b705cfSriastradh pixman_image_get_stride(image), 175603b705cfSriastradh pixman_image_get_data(image)); 175703b705cfSriastradh mask = CreatePicture(0, &scratch->drawable, 175803b705cfSriastradh PictureMatchFormat(screen, 175903b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 176003b705cfSriastradh format), 176103b705cfSriastradh 0, 0, serverClient, &error); 176203b705cfSriastradh } 176303b705cfSriastradh if (!mask) { 176403b705cfSriastradh if (scratch) 176503b705cfSriastradh FreeScratchPixmapHeader(scratch); 176603b705cfSriastradh pixman_image_unref(image); 176703b705cfSriastradh return; 176803b705cfSriastradh } 176903b705cfSriastradh 177003b705cfSriastradh xRel = bounds.x1 + xSrc - xDst; 177103b705cfSriastradh yRel = bounds.y1 + ySrc - yDst; 177203b705cfSriastradh CompositePicture(op, src, mask, dst, 177303b705cfSriastradh xRel, yRel, 177403b705cfSriastradh 0, 0, 177503b705cfSriastradh bounds.x1, bounds.y1, 177603b705cfSriastradh width, height); 177703b705cfSriastradh FreePicture(mask, 0); 177803b705cfSriastradh 177903b705cfSriastradh if (scratch) 178003b705cfSriastradh FreeScratchPixmapHeader(scratch); 178103b705cfSriastradh pixman_image_unref(image); 178203b705cfSriastradh } else { 178303b705cfSriastradh if (dst->polyEdge == PolyEdgeSharp) 178403b705cfSriastradh maskFormat = PictureMatchFormat(screen, 1, PICT_a1); 178503b705cfSriastradh else 178603b705cfSriastradh maskFormat = PictureMatchFormat(screen, 8, PICT_a8); 178703b705cfSriastradh for (; ntrap; ntrap--, traps++) 178803b705cfSriastradh uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 178903b705cfSriastradh 1, traps); 179003b705cfSriastradh } 179103b705cfSriastradh} 179203b705cfSriastradh 179303b705cfSriastradhstatic void 179403b705cfSriastradhuxa_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst, 179503b705cfSriastradh PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 179603b705cfSriastradh int ntri, xTriangle *tri) 179703b705cfSriastradh{ 179803b705cfSriastradh ScreenPtr screen = dst->pDrawable->pScreen; 179903b705cfSriastradh 180003b705cfSriastradh if (maskFormat) { 180103b705cfSriastradh PixmapPtr scratch = NULL; 180203b705cfSriastradh PicturePtr mask; 180303b705cfSriastradh INT16 xDst, yDst; 180403b705cfSriastradh INT16 xRel, yRel; 180503b705cfSriastradh BoxRec bounds; 180603b705cfSriastradh int width, height; 180703b705cfSriastradh pixman_image_t *image; 180803b705cfSriastradh pixman_format_code_t format; 180903b705cfSriastradh int error; 181003b705cfSriastradh 181103b705cfSriastradh xDst = pixman_fixed_to_int(tri[0].p1.x); 181203b705cfSriastradh yDst = pixman_fixed_to_int(tri[0].p1.y); 181303b705cfSriastradh 181403b705cfSriastradh miTriangleBounds (ntri, tri, &bounds); 181503b705cfSriastradh if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 181603b705cfSriastradh return; 181703b705cfSriastradh 181803b705cfSriastradh width = bounds.x2 - bounds.x1; 181903b705cfSriastradh height = bounds.y2 - bounds.y1; 182003b705cfSriastradh 182103b705cfSriastradh format = maskFormat->format | 182203b705cfSriastradh (BitsPerPixel(maskFormat->depth) << 24); 182303b705cfSriastradh image = 182403b705cfSriastradh pixman_image_create_bits(format, width, height, NULL, 0); 182503b705cfSriastradh if (!image) 182603b705cfSriastradh return; 182703b705cfSriastradh 182803b705cfSriastradh pixman_add_triangles(image, 182903b705cfSriastradh -bounds.x1, -bounds.y1, 183003b705cfSriastradh ntri, (pixman_triangle_t *)tri); 183103b705cfSriastradh 183203b705cfSriastradh scratch = GetScratchPixmapHeader(screen, width, height, 183303b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 183403b705cfSriastradh PIXMAN_FORMAT_BPP(format), 183503b705cfSriastradh pixman_image_get_stride(image), 183603b705cfSriastradh pixman_image_get_data(image)); 183703b705cfSriastradh if (!scratch) { 183803b705cfSriastradh pixman_image_unref(image); 183903b705cfSriastradh return; 184003b705cfSriastradh } 184103b705cfSriastradh 184203b705cfSriastradh mask = CreatePicture(0, &scratch->drawable, 184303b705cfSriastradh PictureMatchFormat(screen, 184403b705cfSriastradh PIXMAN_FORMAT_DEPTH(format), 184503b705cfSriastradh format), 184603b705cfSriastradh 0, 0, serverClient, &error); 184703b705cfSriastradh if (!mask) { 184803b705cfSriastradh FreeScratchPixmapHeader(scratch); 184903b705cfSriastradh pixman_image_unref(image); 185003b705cfSriastradh return; 185103b705cfSriastradh } 185203b705cfSriastradh 185303b705cfSriastradh xRel = bounds.x1 + xSrc - xDst; 185403b705cfSriastradh yRel = bounds.y1 + ySrc - yDst; 185503b705cfSriastradh CompositePicture(op, src, mask, dst, 185603b705cfSriastradh xRel, yRel, 185703b705cfSriastradh 0, 0, 185803b705cfSriastradh bounds.x1, bounds.y1, 185903b705cfSriastradh width, height); 186003b705cfSriastradh FreePicture(mask, 0); 186103b705cfSriastradh 186203b705cfSriastradh FreeScratchPixmapHeader(scratch); 186303b705cfSriastradh pixman_image_unref(image); 186403b705cfSriastradh } else { 186503b705cfSriastradh if (dst->polyEdge == PolyEdgeSharp) 186603b705cfSriastradh maskFormat = PictureMatchFormat(screen, 1, PICT_a1); 186703b705cfSriastradh else 186803b705cfSriastradh maskFormat = PictureMatchFormat(screen, 8, PICT_a8); 186903b705cfSriastradh 187003b705cfSriastradh for (; ntri; ntri--, tri++) 187103b705cfSriastradh uxa_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri); 187203b705cfSriastradh } 187303b705cfSriastradh} 187403b705cfSriastradh 187503b705cfSriastradh/** 187603b705cfSriastradh * uxa_triangles is essentially a copy of miTriangles that uses 187703b705cfSriastradh * uxa_create_alpha_picture instead of miCreateAlphaPicture. 187803b705cfSriastradh * 187903b705cfSriastradh * The problem with miCreateAlphaPicture is that it calls PolyFillRect 188003b705cfSriastradh * to initialize the contents after creating the pixmap, which 188103b705cfSriastradh * causes the pixmap to be moved in for acceleration. The subsequent 188203b705cfSriastradh * call to AddTriangles won't be accelerated however, which forces the pixmap 188303b705cfSriastradh * to be moved out again. 188403b705cfSriastradh * 188503b705cfSriastradh * uxa_create_alpha_picture avoids this roundtrip by using 188603b705cfSriastradh * uxa_check_poly_fill_rect to initialize the contents. 188703b705cfSriastradh */ 188803b705cfSriastradhvoid 188903b705cfSriastradhuxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 189003b705cfSriastradh PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 189103b705cfSriastradh int ntri, xTriangle * tris) 189203b705cfSriastradh{ 189303b705cfSriastradh ScreenPtr pScreen = pDst->pDrawable->pScreen; 189403b705cfSriastradh uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 189503b705cfSriastradh PictureScreenPtr ps = GetPictureScreen(pScreen); 189603b705cfSriastradh BoxRec bounds; 189703b705cfSriastradh Bool direct; 189803b705cfSriastradh 189903b705cfSriastradh if (uxa_screen->force_fallback) { 190003b705cfSriastradh uxa_check_triangles(op, pSrc, pDst, maskFormat, 190103b705cfSriastradh xSrc, ySrc, ntri, tris); 190203b705cfSriastradh return; 190303b705cfSriastradh } 190403b705cfSriastradh 190503b705cfSriastradh direct = op == PictOpAdd && miIsSolidAlpha(pSrc); 190603b705cfSriastradh if (maskFormat || direct) { 190703b705cfSriastradh miTriangleBounds(ntri, tris, &bounds); 190803b705cfSriastradh 190903b705cfSriastradh if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 191003b705cfSriastradh return; 191103b705cfSriastradh } 191203b705cfSriastradh 191303b705cfSriastradh /* 191403b705cfSriastradh * Check for solid alpha add 191503b705cfSriastradh */ 191603b705cfSriastradh if (direct) { 191703b705cfSriastradh DrawablePtr pDraw = pDst->pDrawable; 191803b705cfSriastradh if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) { 191903b705cfSriastradh (*ps->AddTriangles) (pDst, 0, 0, ntri, tris); 192003b705cfSriastradh uxa_finish_access(pDraw, UXA_ACCESS_RW); 192103b705cfSriastradh } 192203b705cfSriastradh } else if (maskFormat) { 192303b705cfSriastradh PicturePtr pPicture; 192403b705cfSriastradh INT16 xDst, yDst; 192503b705cfSriastradh INT16 xRel, yRel; 192603b705cfSriastradh int width = bounds.x2 - bounds.x1; 192703b705cfSriastradh int height = bounds.y2 - bounds.y1; 192803b705cfSriastradh GCPtr pGC; 192903b705cfSriastradh xRectangle rect; 193003b705cfSriastradh 193103b705cfSriastradh xDst = tris[0].p1.x >> 16; 193203b705cfSriastradh yDst = tris[0].p1.y >> 16; 193303b705cfSriastradh 193403b705cfSriastradh pPicture = uxa_create_alpha_picture(pScreen, pDst, maskFormat, 193503b705cfSriastradh width, height); 193603b705cfSriastradh if (!pPicture) 193703b705cfSriastradh return; 193803b705cfSriastradh 193903b705cfSriastradh /* Clear the alpha picture to 0. */ 194003b705cfSriastradh pGC = GetScratchGC(pPicture->pDrawable->depth, pScreen); 194103b705cfSriastradh if (!pGC) { 194203b705cfSriastradh FreePicture(pPicture, 0); 194303b705cfSriastradh return; 194403b705cfSriastradh } 194503b705cfSriastradh ValidateGC(pPicture->pDrawable, pGC); 194603b705cfSriastradh rect.x = 0; 194703b705cfSriastradh rect.y = 0; 194803b705cfSriastradh rect.width = width; 194903b705cfSriastradh rect.height = height; 195003b705cfSriastradh uxa_check_poly_fill_rect(pPicture->pDrawable, pGC, 1, &rect); 195103b705cfSriastradh FreeScratchGC(pGC); 195203b705cfSriastradh 195303b705cfSriastradh if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) { 195403b705cfSriastradh (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, 195503b705cfSriastradh ntri, tris); 195603b705cfSriastradh uxa_finish_access(pPicture->pDrawable, UXA_ACCESS_RW); 195703b705cfSriastradh } 195803b705cfSriastradh 195903b705cfSriastradh xRel = bounds.x1 + xSrc - xDst; 196003b705cfSriastradh yRel = bounds.y1 + ySrc - yDst; 196103b705cfSriastradh CompositePicture(op, pSrc, pPicture, pDst, 196203b705cfSriastradh xRel, yRel, 0, 0, bounds.x1, bounds.y1, 196303b705cfSriastradh bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); 196403b705cfSriastradh FreePicture(pPicture, 0); 196503b705cfSriastradh } else { 196603b705cfSriastradh if (pDst->polyEdge == PolyEdgeSharp) 196703b705cfSriastradh maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); 196803b705cfSriastradh else 196903b705cfSriastradh maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); 197003b705cfSriastradh 197103b705cfSriastradh for (; ntri; ntri--, tris++) 197203b705cfSriastradh uxa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, 197303b705cfSriastradh tris); 197403b705cfSriastradh } 197503b705cfSriastradh} 197603b705cfSriastradh 197703b705cfSriastradhvoid 197803b705cfSriastradhuxa_add_traps(PicturePtr pPicture, 197903b705cfSriastradh INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) 198003b705cfSriastradh{ 198103b705cfSriastradh uxa_check_add_traps(pPicture, x_off, y_off, ntrap, traps); 198203b705cfSriastradh} 1983