1f29dbc25Smrg/* 2f29dbc25Smrg * Copyright (c) 2007-2008 Advanced Micro Devices, Inc. 3f29dbc25Smrg * 4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"), 6f29dbc25Smrg * to deal in the Software without restriction, including without limitation 7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the 9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions: 10f29dbc25Smrg * 11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 12f29dbc25Smrg * all copies or substantial portions of the Software. 13f29dbc25Smrg * 14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20f29dbc25Smrg * DEALINGS IN THE SOFTWARE. 21f29dbc25Smrg * 22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 24f29dbc25Smrg * software without specific prior written permission. 25f29dbc25Smrg */ 26f29dbc25Smrg 27f29dbc25Smrg/* TODO: 28f29dbc25Smrg Support a8 as a source or destination? 29f29dbc25Smrg convert !a8 or !a4 masks? 30f29dbc25Smrg support multiple pass operations? 31f29dbc25Smrg*/ 32f29dbc25Smrg 33f29dbc25Smrg/* To support PictOptAdd with a mask */ 34f29dbc25Smrg 35f29dbc25Smrg#ifdef HAVE_CONFIG_H 36f29dbc25Smrg#include "config.h" 37f29dbc25Smrg#endif 38f29dbc25Smrg 3900be8644Schristos#include "xorg-server.h" 4000be8644Schristos 41f29dbc25Smrg#include "xf86.h" 42f29dbc25Smrg#include "exa.h" 43f29dbc25Smrg 44f29dbc25Smrg#include "geode.h" 45f29dbc25Smrg#include "cim_defs.h" 46f29dbc25Smrg#include "cim_regs.h" 47f29dbc25Smrg 48f29dbc25Smrg#include "geode_blend.h" 49f29dbc25Smrg 50f29dbc25Smrg#define F(x) IntToxFixed(x) 51f29dbc25Smrg#define I(x) xFixedToInt(x) 52f29dbc25Smrg 5304007ebaSmrg#define GEODE_TRACE_FALL 0 5404007ebaSmrg 5504007ebaSmrg#if GEODE_TRACE_FALL 5604007ebaSmrg#define GEODE_FALLBACK(x) \ 5704007ebaSmrgdo { \ 5804007ebaSmrg ErrorF("%s: ", __FUNCTION__); \ 5904007ebaSmrg ErrorF x; \ 6004007ebaSmrg return FALSE; \ 6104007ebaSmrg} while (0) 6204007ebaSmrg#else 6304007ebaSmrg#define GEODE_FALLBACK(x) return FALSE 6404007ebaSmrg#endif 6504007ebaSmrg 6604007ebaSmrgstatic const struct exa_format_t { 67f29dbc25Smrg int exa; 68f29dbc25Smrg int bpp; 69f29dbc25Smrg int fmt; 70f29dbc25Smrg int alphabits; 71f29dbc25Smrg} lx_exa_formats[] = { 72f29dbc25Smrg { 73f29dbc25Smrg PICT_a8r8g8b8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 8}, { 74f29dbc25Smrg PICT_x8r8g8b8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 0}, { 75f29dbc25Smrg PICT_x8b8g8r8, 32, CIMGP_SOURCE_FMT_32BPP_BGR, 0}, { 76f29dbc25Smrg PICT_a4r4g4b4, 16, CIMGP_SOURCE_FMT_4_4_4_4, 4}, { 77f29dbc25Smrg PICT_a1r5g5b5, 16, CIMGP_SOURCE_FMT_1_5_5_5, 1}, { 78f29dbc25Smrg PICT_r5g6b5, 16, CIMGP_SOURCE_FMT_0_5_6_5, 0}, { 79f29dbc25Smrg PICT_b5g6r5, 16, CIMGP_SOURCE_FMT_16BPP_BGR, 0}, { 80f29dbc25Smrg PICT_x1r5g5b5, 16, CIMGP_SOURCE_FMT_1_5_5_5, 0}, { 81f29dbc25Smrg PICT_x1b5g5r5, 16, CIMGP_SOURCE_FMT_15BPP_BGR, 0}, { 82170d5fdcSmrg PICT_r3g3b2, 8, CIMGP_SOURCE_FMT_3_3_2, 0}, { 83170d5fdcSmrg PICT_a8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 8} 84f29dbc25Smrg}; 85f29dbc25Smrg 86f29dbc25Smrg/* This is a chunk of memory we use for scratch space */ 87f29dbc25Smrg 88f29dbc25Smrg#define COMP_TYPE_MASK 0 89f29dbc25Smrg#define COMP_TYPE_ONEPASS 1 90f29dbc25Smrg#define COMP_TYPE_TWOPASS 3 91f29dbc25Smrg#define COMP_TYPE_ROTATE 5 92f29dbc25Smrg 9304007ebaSmrgstatic struct { 94f29dbc25Smrg int type; 95f29dbc25Smrg 96f29dbc25Smrg unsigned int srcOffset; 97f29dbc25Smrg unsigned int srcPitch; 98f29dbc25Smrg unsigned int srcBpp; 99f29dbc25Smrg unsigned int srcWidth, srcHeight; 100f29dbc25Smrg 101f29dbc25Smrg unsigned int srcColor; 102f29dbc25Smrg int op; 103f29dbc25Smrg int repeat; 104170d5fdcSmrg int maskrepeat; 105f29dbc25Smrg unsigned int fourBpp; 106f29dbc25Smrg unsigned int bufferOffset; 107f29dbc25Smrg struct exa_format_t *srcFormat; 108f29dbc25Smrg struct exa_format_t *dstFormat; 109f29dbc25Smrg 110f29dbc25Smrg int rotate; 111f29dbc25Smrg PictTransform *transform; 112f29dbc25Smrg 113f29dbc25Smrg} exaScratch; 114f29dbc25Smrg 115f29dbc25Smrgstatic const int SDfn[16] = { 116f29dbc25Smrg 0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE, 117f29dbc25Smrg 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF 118f29dbc25Smrg}; 119f29dbc25Smrg 120f29dbc25Smrgstatic const int SDfn_PM[16] = { 121f29dbc25Smrg 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 122f29dbc25Smrg 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA 123f29dbc25Smrg}; 124f29dbc25Smrg 125f29dbc25Smrg/* These functions check to see if we can safely prefetch the memory 126f29dbc25Smrg * for the blt, or if we have to wait the previous blt to complete. 127f29dbc25Smrg * One function is for the fill, and the other is for the copy because 128f29dbc25Smrg * they have different requirements based on ROP 129f29dbc25Smrg */ 130f29dbc25Smrg 131f29dbc25Smrgstatic int lx0 = -1, ly0 = -1, lx1 = -1, ly1 = -1; 132f29dbc25Smrg 133f29dbc25Smrgstatic int 134f29dbc25Smrglx_fill_flags(int x0, int y0, int w, int h, int rop) 135f29dbc25Smrg{ 136f29dbc25Smrg int x1 = x0 + w, y1 = y0 + h; 13704007ebaSmrg int n = ((rop ^ (rop >> 1)) & 0x55) == 0 || /* no dst */ 13804007ebaSmrg x0 >= lx1 || y0 >= ly1 || /* rght/below */ 13904007ebaSmrg x1 <= lx0 || y1 <= ly0 ? /* left/above */ 14004007ebaSmrg 0 : CIMGP_BLTFLAGS_HAZARD; 141f29dbc25Smrg 142f29dbc25Smrg lx0 = x0; 143f29dbc25Smrg ly0 = y0; 144f29dbc25Smrg lx1 = x1; 145f29dbc25Smrg ly1 = y1; 146f29dbc25Smrg 147f29dbc25Smrg return n; 148f29dbc25Smrg} 149f29dbc25Smrg 150f29dbc25Smrgstatic int 151f29dbc25Smrglx_copy_flags(int x0, int y0, int x1, int y1, int w, int h, int rop) 152f29dbc25Smrg{ 153f29dbc25Smrg int x2 = x1 + w, y2 = y1 + h; 154f29dbc25Smrg 155f29dbc25Smrg /* dst not hazzard and src not hazzard */ 156f29dbc25Smrg int n = (((rop ^ (rop >> 1)) & 0x55) == 0 || 15704007ebaSmrg x1 >= lx1 || y1 >= ly1 || 15804007ebaSmrg x2 <= lx0 || y2 <= ly0) && 15904007ebaSmrg (((rop ^ (rop >> 2)) & 0x33) == 0 || 16004007ebaSmrg x0 >= lx1 || y0 >= ly1 || 16104007ebaSmrg x0 + w <= lx0 || y0 + h <= ly0) ? 0 : CIMGP_BLTFLAGS_HAZARD; 162f29dbc25Smrg 163f29dbc25Smrg lx0 = x1; 164f29dbc25Smrg ly0 = y1; 165f29dbc25Smrg lx1 = x2; 166f29dbc25Smrg ly1 = y2; 167f29dbc25Smrg 168f29dbc25Smrg return n; 169f29dbc25Smrg} 170f29dbc25Smrg 171f29dbc25Smrg/* These are borrowed from the exa engine - they should be made global 172f29dbc25Smrg and available to drivers, but until then.... 173f29dbc25Smrg*/ 174f29dbc25Smrg 175f29dbc25Smrg/* exaGetPixelFromRGBA (exa_render.c) */ 176f29dbc25Smrg 177f29dbc25Smrgstatic Bool 17804007ebaSmrg_GetPixelFromRGBA(CARD32 *pixel, 17904007ebaSmrg CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, 18004007ebaSmrg CARD32 format) 181f29dbc25Smrg{ 182f29dbc25Smrg int rbits, bbits, gbits, abits; 183f29dbc25Smrg int rshift, bshift, gshift, ashift; 184f29dbc25Smrg 185f29dbc25Smrg *pixel = 0; 186f29dbc25Smrg 187f29dbc25Smrg if (!PICT_FORMAT_COLOR(format)) 18804007ebaSmrg return FALSE; 189f29dbc25Smrg 190f29dbc25Smrg rbits = PICT_FORMAT_R(format); 191f29dbc25Smrg gbits = PICT_FORMAT_G(format); 192f29dbc25Smrg bbits = PICT_FORMAT_B(format); 193f29dbc25Smrg abits = PICT_FORMAT_A(format); 194f29dbc25Smrg 195f29dbc25Smrg if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 19604007ebaSmrg bshift = 0; 19704007ebaSmrg gshift = bbits; 19804007ebaSmrg rshift = gshift + gbits; 19904007ebaSmrg ashift = rshift + rbits; 20004007ebaSmrg } 20104007ebaSmrg else { /* PICT_TYPE_ABGR */ 20204007ebaSmrg rshift = 0; 20304007ebaSmrg gshift = rbits; 20404007ebaSmrg bshift = gshift + gbits; 20504007ebaSmrg ashift = bshift + bbits; 206f29dbc25Smrg } 207f29dbc25Smrg 208f29dbc25Smrg *pixel |= (blue >> (16 - bbits)) << bshift; 209f29dbc25Smrg *pixel |= (red >> (16 - rbits)) << rshift; 210f29dbc25Smrg *pixel |= (green >> (16 - gbits)) << gshift; 211f29dbc25Smrg *pixel |= (alpha >> (16 - abits)) << ashift; 212f29dbc25Smrg 213f29dbc25Smrg return TRUE; 214f29dbc25Smrg} 215f29dbc25Smrg 216f29dbc25Smrg/* exaGetRGBAFromPixel (exa_render.c) */ 217f29dbc25Smrg 218f29dbc25Smrgstatic Bool 219f29dbc25Smrg_GetRGBAFromPixel(CARD32 pixel, 22004007ebaSmrg CARD16 *red, 22104007ebaSmrg CARD16 *green, CARD16 *blue, CARD16 *alpha, CARD32 format) 222f29dbc25Smrg{ 223f29dbc25Smrg int rbits, bbits, gbits, abits; 224f29dbc25Smrg int rshift, bshift, gshift, ashift; 225f29dbc25Smrg 226f29dbc25Smrg if (!PICT_FORMAT_COLOR(format)) 22704007ebaSmrg return FALSE; 228f29dbc25Smrg 229f29dbc25Smrg rbits = PICT_FORMAT_R(format); 230f29dbc25Smrg gbits = PICT_FORMAT_G(format); 231f29dbc25Smrg bbits = PICT_FORMAT_B(format); 232f29dbc25Smrg abits = PICT_FORMAT_A(format); 233f29dbc25Smrg 234f29dbc25Smrg if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 23504007ebaSmrg bshift = 0; 23604007ebaSmrg gshift = bbits; 23704007ebaSmrg rshift = gshift + gbits; 23804007ebaSmrg ashift = rshift + rbits; 23904007ebaSmrg } 24004007ebaSmrg else { /* PICT_TYPE_ABGR */ 24104007ebaSmrg rshift = 0; 24204007ebaSmrg gshift = rbits; 24304007ebaSmrg bshift = gshift + gbits; 24404007ebaSmrg ashift = bshift + bbits; 245f29dbc25Smrg } 246f29dbc25Smrg 247f29dbc25Smrg *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); 248f29dbc25Smrg while (rbits < 16) { 24904007ebaSmrg *red |= *red >> rbits; 25004007ebaSmrg rbits <<= 1; 251f29dbc25Smrg } 252f29dbc25Smrg 253f29dbc25Smrg *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); 254f29dbc25Smrg while (gbits < 16) { 25504007ebaSmrg *green |= *green >> gbits; 25604007ebaSmrg gbits <<= 1; 257f29dbc25Smrg } 258f29dbc25Smrg 259f29dbc25Smrg *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); 260f29dbc25Smrg while (bbits < 16) { 26104007ebaSmrg *blue |= *blue >> bbits; 26204007ebaSmrg bbits <<= 1; 263f29dbc25Smrg } 264f29dbc25Smrg 265f29dbc25Smrg if (abits) { 26604007ebaSmrg *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); 26704007ebaSmrg while (abits < 16) { 26804007ebaSmrg *alpha |= *alpha >> abits; 26904007ebaSmrg abits <<= 1; 27004007ebaSmrg } 27104007ebaSmrg } 27204007ebaSmrg else 27304007ebaSmrg *alpha = 0xffff; 274f29dbc25Smrg 275f29dbc25Smrg return TRUE; 276f29dbc25Smrg} 277f29dbc25Smrg 278f29dbc25Smrgstatic unsigned int 279f29dbc25Smrglx_get_source_color(PixmapPtr pSrc, int srcFormat, int dstFormat) 280f29dbc25Smrg{ 281f29dbc25Smrg CARD32 in, out; 282f29dbc25Smrg CARD16 red = 0, green = 0, blue = 0, alpha = 0; 283f29dbc25Smrg 284f29dbc25Smrg /* Stall to avoid a race with the upload function */ 285f29dbc25Smrg /* for 1.4 and newer, the problem will be resolved within 286f29dbc25Smrg * exaGetPixmapFirstPixel, so this should be adjusted so 287f29dbc25Smrg * the stall isn't run needlessly 288f29dbc25Smrg */ 28904007ebaSmrg /* FIXME: xserver-1.4 with a supposed fix for this is really old, so kill the stall? */ 290f29dbc25Smrg 291f29dbc25Smrg gp_wait_until_idle(); 292f29dbc25Smrg in = exaGetPixmapFirstPixel(pSrc); 293f29dbc25Smrg 294f29dbc25Smrg _GetRGBAFromPixel(in, &red, &blue, &green, &alpha, srcFormat); 295f29dbc25Smrg _GetPixelFromRGBA(&out, red, blue, green, alpha, dstFormat); 296f29dbc25Smrg 297f29dbc25Smrg return out; 298f29dbc25Smrg} 299f29dbc25Smrg 300f29dbc25Smrgstatic Bool 301f29dbc25Smrglx_prepare_solid(PixmapPtr pxMap, int alu, Pixel planemask, Pixel fg) 302f29dbc25Smrg{ 303f29dbc25Smrg int pitch = exaGetPixmapPitch(pxMap); 304f29dbc25Smrg int op = (planemask == ~0U) ? SDfn[alu] : SDfn_PM[alu]; 305f29dbc25Smrg 306f29dbc25Smrg gp_declare_blt(0); 307f29dbc25Smrg gp_set_bpp(pxMap->drawable.bitsPerPixel); 308f29dbc25Smrg 309f29dbc25Smrg gp_set_raster_operation(op); 310f29dbc25Smrg 311f29dbc25Smrg if (planemask != ~0U) 31204007ebaSmrg gp_set_solid_pattern(planemask); 313f29dbc25Smrg 314f29dbc25Smrg exaScratch.op = op; 315f29dbc25Smrg 316f29dbc25Smrg gp_set_solid_source(fg); 317f29dbc25Smrg 318f29dbc25Smrg gp_set_strides(pitch, pitch); 319f29dbc25Smrg gp_write_parameters(); 320f29dbc25Smrg return TRUE; 321f29dbc25Smrg} 322f29dbc25Smrg 323f29dbc25Smrgstatic void 324f29dbc25Smrglx_do_solid(PixmapPtr pxMap, int x1, int y1, int x2, int y2) 325f29dbc25Smrg{ 326f29dbc25Smrg int bpp = (pxMap->drawable.bitsPerPixel + 7) / 8; 327f29dbc25Smrg int pitch = exaGetPixmapPitch(pxMap); 32804007ebaSmrg unsigned int offset = exaGetPixmapOffset(pxMap) + (pitch * y1) + (bpp * x1); 329f29dbc25Smrg 330f29dbc25Smrg gp_declare_blt(lx_fill_flags(x1, y1, x2 - x1, y2 - y1, exaScratch.op)); 331f29dbc25Smrg gp_pattern_fill(offset, x2 - x1, y2 - y1); 332f29dbc25Smrg} 333f29dbc25Smrg 334f29dbc25Smrgstatic Bool 335f29dbc25Smrglx_prepare_copy(PixmapPtr pxSrc, PixmapPtr pxDst, int dx, int dy, 33604007ebaSmrg int alu, Pixel planemask) 337f29dbc25Smrg{ 338f29dbc25Smrg int dpitch = exaGetPixmapPitch(pxDst); 339f29dbc25Smrg int op = (planemask == ~0U) ? SDfn[alu] : SDfn_PM[alu]; 340f29dbc25Smrg 341f29dbc25Smrg gp_declare_blt(0); 342f29dbc25Smrg gp_set_bpp(pxDst->drawable.bitsPerPixel); 343f29dbc25Smrg 344f29dbc25Smrg gp_set_raster_operation(op); 345f29dbc25Smrg 346f29dbc25Smrg if (planemask != ~0U) 34704007ebaSmrg gp_set_solid_pattern(planemask); 348f29dbc25Smrg 349f29dbc25Smrg exaScratch.srcOffset = exaGetPixmapOffset(pxSrc); 350f29dbc25Smrg exaScratch.srcPitch = exaGetPixmapPitch(pxSrc); 351f29dbc25Smrg exaScratch.srcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; 352f29dbc25Smrg 353f29dbc25Smrg exaScratch.op = op; 354f29dbc25Smrg 355f29dbc25Smrg gp_set_strides(dpitch, exaScratch.srcPitch); 356f29dbc25Smrg gp_write_parameters(); 357f29dbc25Smrg return TRUE; 358f29dbc25Smrg} 359f29dbc25Smrg 360f29dbc25Smrgstatic void 361f29dbc25Smrglx_do_copy(PixmapPtr pxDst, int srcX, int srcY, 36204007ebaSmrg int dstX, int dstY, int w, int h) 363f29dbc25Smrg{ 364f29dbc25Smrg int dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8; 365f29dbc25Smrg int dstPitch = exaGetPixmapPitch(pxDst); 366f29dbc25Smrg unsigned int srcOffset, dstOffset; 367f29dbc25Smrg int flags = 0; 368f29dbc25Smrg 36904007ebaSmrg gp_declare_blt(lx_copy_flags(srcX, srcY, dstX, dstY, w, h, exaScratch.op)); 370f29dbc25Smrg 371f29dbc25Smrg srcOffset = exaScratch.srcOffset + (exaScratch.srcPitch * srcY) + 37204007ebaSmrg (exaScratch.srcBpp) * srcX; 373f29dbc25Smrg 37404007ebaSmrg dstOffset = exaGetPixmapOffset(pxDst) + (dstPitch * dstY) + (dstBpp * dstX); 375f29dbc25Smrg 376f29dbc25Smrg if (dstX > srcX) 37704007ebaSmrg flags |= CIMGP_NEGXDIR; 378f29dbc25Smrg 379f29dbc25Smrg if (dstY > srcY) 38004007ebaSmrg flags |= CIMGP_NEGYDIR; 381f29dbc25Smrg 382f29dbc25Smrg gp_screen_to_screen_blt(dstOffset, srcOffset, w, h, flags); 383f29dbc25Smrg} 384f29dbc25Smrg 385f29dbc25Smrg/* Composite operations 386f29dbc25Smrg 387f29dbc25SmrgThese are the simplest - one pass operations - if there is no format or 388f29dbc25Smrgmask, the we can make these happen pretty fast 389f29dbc25Smrg 390f29dbc25Smrg Operation Type Channel Alpha 391f29dbc25SmrgPictOpClear 0 2 0 3 392f29dbc25SmrgPictOpSrc 0 3 0 3 393f29dbc25SmrgPictOpDst 0 3 1 3 394f29dbc25SmrgPictOpOver 2 0 0 3 395f29dbc25SmrgPictOpOverReverse 2 0 1 3 396f29dbc25SmrgPictOpIn 0 1 0 3 397f29dbc25SmrgPictOpInReverse 0 1 1 3 398f29dbc25SmrgPictOpOut 1 0 0 3 399f29dbc25SmrgPictOpOutReverse 1 0 1 3 400f29dbc25SmrgPictOpAdd 2 2 0 3 401f29dbc25Smrg 402f29dbc25SmrgThe following require multiple passes 403f29dbc25SmrgPictOpAtop 404f29dbc25SmrgPictOpXor 405f29dbc25Smrg*/ 406f29dbc25Smrg 40704007ebaSmrgstruct blend_ops_t { 408f29dbc25Smrg int operation; 409f29dbc25Smrg int type; 410f29dbc25Smrg int channel; 411f29dbc25Smrg} lx_alpha_ops[] = { 412f29dbc25Smrg /* PictOpClear */ 413f29dbc25Smrg { 414f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CONSTANT_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 415f29dbc25Smrg }, 41604007ebaSmrg /* PictOpSrc */ 417f29dbc25Smrg { 418f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_ALPHA_EQUALS_ONE, CIMGP_CHANNEL_A_SOURCE}, { 419f29dbc25Smrg }, 42004007ebaSmrg /* PictOpDst */ 421f29dbc25Smrg { 422f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_ALPHA_EQUALS_ONE, CIMGP_CHANNEL_A_DEST}, { 423f29dbc25Smrg }, 42404007ebaSmrg /* PictOpOver */ 425f29dbc25Smrg { 426170d5fdcSmrg CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 427170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 42804007ebaSmrg /* PictOpOverReverse */ 429f29dbc25Smrg { 430170d5fdcSmrg CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { 431170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 43204007ebaSmrg /* PictOpIn */ 433f29dbc25Smrg { 434f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 435170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 43604007ebaSmrg /* PictOpInReverse */ 437f29dbc25Smrg { 438f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_DEST}, { 439170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 44004007ebaSmrg /* PictOpOut */ 441f29dbc25Smrg { 442170d5fdcSmrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { 443170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 44404007ebaSmrg /* PictOpOutReverse */ 445f29dbc25Smrg { 446170d5fdcSmrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 447170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 44804007ebaSmrg /* SrcAtop */ 449f29dbc25Smrg { 450f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_DEST}, { 451f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 45204007ebaSmrg /* SrcAtopReverse */ 453f29dbc25Smrg { 454f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 455f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, 45604007ebaSmrg /* Xor */ 457f29dbc25Smrg { 458f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 459f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 46004007ebaSmrg /* PictOpAdd */ 461f29dbc25Smrg { 462f29dbc25Smrg CIMGP_A_PLUS_BETA_B, CIMGP_CONSTANT_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 463f29dbc25Smrg } 464f29dbc25Smrg}; 465f29dbc25Smrg 46604007ebaSmrg#ifndef ARRAY_SIZE 467f29dbc25Smrg#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a)))) 46804007ebaSmrg#endif 469f29dbc25Smrg 470f29dbc25Smrgstatic const struct exa_format_t * 471f29dbc25Smrglx_get_format(PicturePtr p) 472f29dbc25Smrg{ 473f29dbc25Smrg int i; 474f29dbc25Smrg unsigned int format = p->format; 475f29dbc25Smrg 476170d5fdcSmrg for (i = 0; i < ARRAY_SIZE(lx_exa_formats); i++) 47704007ebaSmrg if (lx_exa_formats[i].exa == format) 47804007ebaSmrg return (&lx_exa_formats[i]); 479f29dbc25Smrg 480f29dbc25Smrg return NULL; 481f29dbc25Smrg} 482f29dbc25Smrg 483f29dbc25Smrgstatic Bool 484f29dbc25Smrglx_process_transform(PicturePtr pSrc) 485f29dbc25Smrg{ 486f29dbc25Smrg PictTransformPtr t = pSrc->transform; 487f29dbc25Smrg xFixed c0 = t->matrix[0][0]; 488f29dbc25Smrg xFixed s0 = t->matrix[0][1]; 489f29dbc25Smrg xFixed s1 = t->matrix[1][0]; 490f29dbc25Smrg xFixed c1 = t->matrix[1][1]; 491f29dbc25Smrg 492f29dbc25Smrg /* If the transform doesn't have any rotation 493f29dbc25Smrg * or scaling components, then just grab the 494f29dbc25Smrg * translate coordinates */ 495f29dbc25Smrg 496f29dbc25Smrg if (t->matrix[0][0] == 0 && 49704007ebaSmrg t->matrix[0][1] == 0 && t->matrix[1][0] == 0 && t->matrix[1][1] == 0) { 49804007ebaSmrg exaScratch.transform = pSrc->transform; 49904007ebaSmrg return TRUE; 500f29dbc25Smrg } 501f29dbc25Smrg 502f29dbc25Smrg /* Otherwise, see if this is a simple 503f29dbc25Smrg * rotate transform - if it isn't, then 504f29dbc25Smrg * we have to punt back to software */ 505f29dbc25Smrg 506f29dbc25Smrg if (t->matrix[2][2] != F(1)) 50704007ebaSmrg return FALSE; 508f29dbc25Smrg 509f29dbc25Smrg /* The rotate matrix looks like this: 510f29dbc25Smrg * [ cos X -sin x 511f29dbc25Smrg * sin X cos X ] 512f29dbc25Smrg * 513f29dbc25Smrg * Where X is the angle. We do a simple 514f29dbc25Smrg * check first - if [0,0] != [1,1], then 515f29dbc25Smrg * scaling was specified too, and we can 516f29dbc25Smrg * bail, and if [0,1] != -[1,1] then this 517f29dbc25Smrg * isn't scaling that we can handle. 518f29dbc25Smrg */ 519f29dbc25Smrg 520f29dbc25Smrg if ((c0 != c1) || (s0 != -s1)) 52104007ebaSmrg return FALSE; 522f29dbc25Smrg 523f29dbc25Smrg /* Now, figure out what angle we want - we 524f29dbc25Smrg * can only accelerate right angle rotations, 525f29dbc25Smrg * so this turns into an easy set of if statements */ 526f29dbc25Smrg 527f29dbc25Smrg if (c0 == F(1) && s1 == F(0)) 52804007ebaSmrg exaScratch.rotate = RR_Rotate_0; 529f29dbc25Smrg else if (c0 == F(0) && s1 == F(1)) 53004007ebaSmrg exaScratch.rotate = RR_Rotate_90; 531f29dbc25Smrg else if (c0 == F(-1) && s1 == F(0)) 53204007ebaSmrg exaScratch.rotate = RR_Rotate_180; 533f29dbc25Smrg else if (c0 == F(0) && s1 == F(-1)) 53404007ebaSmrg exaScratch.rotate = RR_Rotate_270; 535f29dbc25Smrg else 53604007ebaSmrg return FALSE; 537f29dbc25Smrg 538f29dbc25Smrg exaScratch.transform = pSrc->transform; 539f29dbc25Smrg 540f29dbc25Smrg return TRUE; 541f29dbc25Smrg} 542f29dbc25Smrg 543f29dbc25Smrgstatic Bool 544f29dbc25Smrglx_check_composite(int op, PicturePtr pSrc, PicturePtr pMsk, PicturePtr pDst) 545f29dbc25Smrg{ 546f29dbc25Smrg GeodeRec *pGeode = GEODEPTR_FROM_PICTURE(pDst); 547170d5fdcSmrg const struct exa_format_t *srcFmt, *dstFmt; 548f29dbc25Smrg 549f29dbc25Smrg if (op > PictOpAdd) 55004007ebaSmrg GEODE_FALLBACK(("Operation %d is not supported\n", op)); 55104007ebaSmrg 55204007ebaSmrg /* XXX - don't know if we can do any hwaccel on solid fills or gradient types in generic cases */ 55304007ebaSmrg if (pMsk && pMsk->pSourcePict) 55404007ebaSmrg GEODE_FALLBACK(("%s are not supported as a mask\n", 55504007ebaSmrg pMsk->pSourcePict->type == 55604007ebaSmrg SourcePictTypeSolidFill ? "Solid pictures" : 55704007ebaSmrg "Gradients")); 55804007ebaSmrg 55904007ebaSmrg if (pSrc->pSourcePict && pSrc->pSourcePict->type != SourcePictTypeSolidFill) 56004007ebaSmrg GEODE_FALLBACK(("Gradients are not supported as the source\n")); 56104007ebaSmrg 56204007ebaSmrg if (pMsk && op == PictOpAdd) 56304007ebaSmrg GEODE_FALLBACK(("PictOpAdd with mask is not supported\n")); 564f29dbc25Smrg 565170d5fdcSmrg /* FIXME: Meet this conditions from the debug for PictOpAdd. 566170d5fdcSmrg * Any Other possibilities? Add a judge for the future supplement */ 567170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_a8r8g8b8 && 56804007ebaSmrg pDst->format == PICT_a8) 56904007ebaSmrg return TRUE; 570170d5fdcSmrg 571170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_x8r8g8b8 && 57204007ebaSmrg pDst->format == PICT_a8) 57304007ebaSmrg return TRUE; 574170d5fdcSmrg 575170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_r5g6b5 && 57604007ebaSmrg pDst->format == PICT_a8) 57704007ebaSmrg return TRUE; 578170d5fdcSmrg 579f29dbc25Smrg if (usesPasses(op)) { 58004007ebaSmrg /* FIXME: Slightly misleading fallback msg when !pMsk */ 58104007ebaSmrg if (pGeode->exaBfrOffset == 0 || !pMsk) 58204007ebaSmrg GEODE_FALLBACK(("Multipass operation requires off-screen buffer\n")); 583f29dbc25Smrg } 584f29dbc25Smrg 585f29dbc25Smrg /* Check that the filter matches what we support */ 586f29dbc25Smrg 587f29dbc25Smrg switch (pSrc->filter) { 588f29dbc25Smrg case PictFilterNearest: 589f29dbc25Smrg case PictFilterFast: 590f29dbc25Smrg case PictFilterGood: 591f29dbc25Smrg case PictFilterBest: 59204007ebaSmrg break; 593f29dbc25Smrg 594f29dbc25Smrg default: 59504007ebaSmrg GEODE_FALLBACK(("Bilinear or convolution filters are not supported\n")); 596f29dbc25Smrg } 597f29dbc25Smrg 598f29dbc25Smrg if (pMsk && pMsk->transform) 59904007ebaSmrg GEODE_FALLBACK(("Mask transforms are not supported\n")); 600170d5fdcSmrg 601f29dbc25Smrg /* Keep an eye out for source rotation transforms - those we can 602f29dbc25Smrg * do something about */ 603f29dbc25Smrg 604f29dbc25Smrg exaScratch.rotate = RR_Rotate_0; 605f29dbc25Smrg exaScratch.transform = NULL; 606f29dbc25Smrg 607f29dbc25Smrg if (pSrc->transform && !lx_process_transform(pSrc)) 60804007ebaSmrg GEODE_FALLBACK(("Transform operation is non-trivial\n")); 609f29dbc25Smrg 610f29dbc25Smrg /* XXX - I don't understand PICT_a8 enough - so I'm punting */ 611170d5fdcSmrg if ((op != PictOpAdd) && (pSrc->format == PICT_a8 || 61204007ebaSmrg pDst->format == PICT_a8)) 61304007ebaSmrg GEODE_FALLBACK(("PICT_a8 as src or dst format is unsupported\n")); 614f29dbc25Smrg 615f29dbc25Smrg if (pMsk && op != PictOpClear) { 61604007ebaSmrg struct blend_ops_t *opPtr = &lx_alpha_ops[op * 2]; 61704007ebaSmrg int direction = (opPtr->channel == CIMGP_CHANNEL_A_SOURCE) ? 0 : 1; 61804007ebaSmrg 61904007ebaSmrg /* Direction 0 indicates src->dst, 1 indicates dst->src */ 62004007ebaSmrg if (((direction == 0) && 62104007ebaSmrg (pSrc->pDrawable && pSrc->pDrawable->bitsPerPixel < 16)) || 62204007ebaSmrg ((direction == 1) && (pDst->pDrawable->bitsPerPixel < 16))) { 62304007ebaSmrg ErrorF("Mask blending unsupported with <16bpp\n"); 62404007ebaSmrg return FALSE; 62504007ebaSmrg } 62604007ebaSmrg if (pMsk->format != PICT_a8 && pMsk->format != PICT_a4) 62704007ebaSmrg GEODE_FALLBACK(("Masks can be only done with a 8bpp or 4bpp depth\n")); 62804007ebaSmrg 62904007ebaSmrg /* The pSrc should be 1x1 pixel if the pMsk is not zero */ 63004007ebaSmrg if (pSrc->pDrawable && 63104007ebaSmrg (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)) 63204007ebaSmrg GEODE_FALLBACK(("pSrc should be 1x1 pixel if pMsk is not zero\n")); 63304007ebaSmrg /* FIXME: In lx_prepare_composite, there are no variables to record the 63404007ebaSmrg * one pixel source's width and height when the mask is not zero. 63504007ebaSmrg * That will lead to bigger region to render instead of one pixel in lx 63604007ebaSmrg * _do_composite, so we should fallback currently to avoid this */ 63704007ebaSmrg /* Not an issue for solid pictures, because we'll treat it as 1x1R too */ 63804007ebaSmrg if (!pSrc->repeat && 63904007ebaSmrg !(pSrc->pSourcePict && 64004007ebaSmrg pSrc->pSourcePict->type == SourcePictTypeSolidFill)) { 64104007ebaSmrg GEODE_FALLBACK(("FIXME: unzero mask might lead to bigger rendering region than 1x1 pixels\n")); 64204007ebaSmrg } 64304007ebaSmrg } 64404007ebaSmrg else { 64504007ebaSmrg if (pSrc->pSourcePict) 64604007ebaSmrg GEODE_FALLBACK(("Solid source pictures without a mask are not supported\n")); 647f29dbc25Smrg } 648f29dbc25Smrg 649f29dbc25Smrg /* Get the formats for the source and destination */ 650f29dbc25Smrg 65104007ebaSmrg if ((srcFmt = lx_get_format(pSrc)) == NULL) 65204007ebaSmrg GEODE_FALLBACK(("Unsupported source format %x\n", pSrc->format)); 653f29dbc25Smrg 65404007ebaSmrg if ((dstFmt = lx_get_format(pDst)) == NULL) 65504007ebaSmrg GEODE_FALLBACK(("Unsupported destination format %x\n", pDst->format)); 656f29dbc25Smrg 657f29dbc25Smrg /* Make sure operations that need alpha bits have them */ 658f29dbc25Smrg /* If a mask is enabled, the alpha will come from there */ 659f29dbc25Smrg 660f29dbc25Smrg if (!pMsk && (!srcFmt->alphabits && usesSrcAlpha(op))) 66104007ebaSmrg GEODE_FALLBACK(("Operation requires src alpha, but alphabits is unset\n")); 662f29dbc25Smrg 663f29dbc25Smrg if (!pMsk && (!dstFmt->alphabits && usesDstAlpha(op))) 66404007ebaSmrg GEODE_FALLBACK(("Operation requires dst alpha, but alphabits is unset\n")); 665f29dbc25Smrg 66604007ebaSmrg /* FIXME: See a way around this! */ 667f29dbc25Smrg if (srcFmt->alphabits == 0 && dstFmt->alphabits != 0) 66804007ebaSmrg GEODE_FALLBACK(("src_alphabits=0, dst_alphabits!=0\n")); 669f29dbc25Smrg 670f29dbc25Smrg /* If this is a rotate operation, then make sure the src and dst 671f29dbc25Smrg * formats are the same */ 672f29dbc25Smrg if (exaScratch.rotate != RR_Rotate_0 && srcFmt != dstFmt) { 67304007ebaSmrg ErrorF("EXA: Unable to rotate and convert formats at the same time\n"); 67404007ebaSmrg return FALSE; 675f29dbc25Smrg } 676170d5fdcSmrg return TRUE; 677170d5fdcSmrg} 678170d5fdcSmrg 679170d5fdcSmrgstatic Bool 680170d5fdcSmrglx_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMsk, 68104007ebaSmrg PicturePtr pDst, PixmapPtr pxSrc, PixmapPtr pxMsk, 68204007ebaSmrg PixmapPtr pxDst) 683170d5fdcSmrg{ 684170d5fdcSmrg GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); 685170d5fdcSmrg const struct exa_format_t *srcFmt, *dstFmt; 686170d5fdcSmrg 687170d5fdcSmrg /* Get the formats for the source and destination */ 688170d5fdcSmrg 689170d5fdcSmrg srcFmt = lx_get_format(pSrc); 690170d5fdcSmrg dstFmt = lx_get_format(pDst); 691f29dbc25Smrg 692f29dbc25Smrg /* Set up the scratch buffer with the information we need */ 693f29dbc25Smrg 69404007ebaSmrg exaScratch.srcFormat = (struct exa_format_t *) srcFmt; 69504007ebaSmrg exaScratch.dstFormat = (struct exa_format_t *) dstFmt; 696f29dbc25Smrg exaScratch.op = op; 697f29dbc25Smrg exaScratch.repeat = pSrc->repeat; 698f29dbc25Smrg exaScratch.bufferOffset = pGeode->exaBfrOffset; 699f29dbc25Smrg 700f29dbc25Smrg if (pMsk && op != PictOpClear) { 70104007ebaSmrg /* Get the source color */ 70204007ebaSmrg if (pSrc->pSourcePict) { 70304007ebaSmrg exaScratch.srcColor = pSrc->pSourcePict->solidFill.color; 70404007ebaSmrg } 70504007ebaSmrg else { 70604007ebaSmrg /* If the op is PictOpOver(or PictOpOutReverse, PictOpInReverse, 70704007ebaSmrg * PictOpIn, PictOpOut, PictOpOverReverse), we should get the 70804007ebaSmrg * ARGB32 source format */ 70904007ebaSmrg 71004007ebaSmrg if ((op == PictOpOver || op == PictOpOutReverse || op == 71104007ebaSmrg PictOpInReverse || op == PictOpIn || op == PictOpOut || 71204007ebaSmrg op == PictOpOverReverse) && (srcFmt->alphabits != 0)) 71304007ebaSmrg exaScratch.srcColor = exaGetPixmapFirstPixel(pxSrc); 71404007ebaSmrg else if ((op == PictOpOver || op == PictOpOutReverse || op == 71504007ebaSmrg PictOpInReverse || op == PictOpIn || op == PictOpOut || 71604007ebaSmrg op == PictOpOverReverse) && (srcFmt->alphabits == 0)) 71704007ebaSmrg exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, 71804007ebaSmrg PICT_a8r8g8b8); 71904007ebaSmrg else 72004007ebaSmrg exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, 72104007ebaSmrg pDst->format); 72204007ebaSmrg } 72304007ebaSmrg 72404007ebaSmrg /* Save off the info we need (reuse the source values to save space) */ 72504007ebaSmrg exaScratch.type = COMP_TYPE_MASK; 72604007ebaSmrg exaScratch.maskrepeat = pMsk->repeat; 72704007ebaSmrg 72804007ebaSmrg exaScratch.srcOffset = exaGetPixmapOffset(pxMsk); 72904007ebaSmrg exaScratch.srcPitch = exaGetPixmapPitch(pxMsk); 73004007ebaSmrg exaScratch.srcBpp = (pxMsk->drawable.bitsPerPixel + 7) / 8; 73104007ebaSmrg 73204007ebaSmrg exaScratch.srcWidth = pMsk->pDrawable->width; 73304007ebaSmrg exaScratch.srcHeight = pMsk->pDrawable->height; 73404007ebaSmrg 73504007ebaSmrg /* Flag to indicate if this a 8BPP or a 4BPP mask */ 73604007ebaSmrg exaScratch.fourBpp = (pxMsk->drawable.bitsPerPixel == 4) ? 1 : 0; 73704007ebaSmrg } 73804007ebaSmrg else { 73904007ebaSmrg if (usesPasses(op)) 74004007ebaSmrg exaScratch.type = COMP_TYPE_TWOPASS; 74104007ebaSmrg else if (exaScratch.rotate != RR_Rotate_0) 74204007ebaSmrg exaScratch.type = COMP_TYPE_ROTATE; 74304007ebaSmrg else 74404007ebaSmrg exaScratch.type = COMP_TYPE_ONEPASS; 74504007ebaSmrg 74604007ebaSmrg exaScratch.srcOffset = exaGetPixmapOffset(pxSrc); 74704007ebaSmrg exaScratch.srcPitch = exaGetPixmapPitch(pxSrc); 74804007ebaSmrg exaScratch.srcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; 74904007ebaSmrg 75004007ebaSmrg exaScratch.srcWidth = pSrc->pDrawable->width; 75104007ebaSmrg exaScratch.srcHeight = pSrc->pDrawable->height; 752f29dbc25Smrg } 753f29dbc25Smrg 754f29dbc25Smrg return TRUE; 755f29dbc25Smrg} 756f29dbc25Smrg 757f29dbc25Smrgstatic int 758f29dbc25Smrglx_get_bpp_from_format(int format) 759f29dbc25Smrg{ 760f29dbc25Smrg 761f29dbc25Smrg switch (format) { 762f29dbc25Smrg case CIMGP_SOURCE_FMT_8_8_8_8: 763f29dbc25Smrg case CIMGP_SOURCE_FMT_32BPP_BGR: 76404007ebaSmrg return 32; 765f29dbc25Smrg 766f29dbc25Smrg case CIMGP_SOURCE_FMT_4_4_4_4: 76704007ebaSmrg return 12; 768f29dbc25Smrg 769f29dbc25Smrg case CIMGP_SOURCE_FMT_0_5_6_5: 770f29dbc25Smrg case CIMGP_SOURCE_FMT_16BPP_BGR: 77104007ebaSmrg return 16; 772f29dbc25Smrg 773f29dbc25Smrg case CIMGP_SOURCE_FMT_1_5_5_5: 774f29dbc25Smrg case CIMGP_SOURCE_FMT_15BPP_BGR: 77504007ebaSmrg return 15; 776f29dbc25Smrg 777f29dbc25Smrg case CIMGP_SOURCE_FMT_3_3_2: 77804007ebaSmrg return 8; 779f29dbc25Smrg } 780f29dbc25Smrg 781f29dbc25Smrg return 0; 782f29dbc25Smrg} 783f29dbc25Smrg 784f29dbc25Smrg/* BGR needs to be set in the source for it to take - so adjust the source 785f29dbc25Smrg * to enable BGR if the two formats are different, and disable it if they 786f29dbc25Smrg * are the same 787f29dbc25Smrg */ 788f29dbc25Smrg 789f29dbc25Smrgstatic void 790f29dbc25Smrglx_set_source_format(int srcFormat, int dstFormat) 791f29dbc25Smrg{ 792f29dbc25Smrg if (!(srcFormat & 0x10) && (dstFormat & 0x10)) 79304007ebaSmrg gp_set_source_format(srcFormat | 0x10); 794f29dbc25Smrg else if ((srcFormat & 0x10) && (dstFormat & 0x10)) 79504007ebaSmrg gp_set_source_format(srcFormat & ~0x10); 796f29dbc25Smrg else 79704007ebaSmrg gp_set_source_format(srcFormat); 798f29dbc25Smrg} 799f29dbc25Smrg 800f29dbc25Smrg/* If we are converting colors and we need the channel A alpha, 801f29dbc25Smrg * then use a special alpha type that preserves the alpha before 802f29dbc25Smrg * converting the format 803f29dbc25Smrg */ 804f29dbc25Smrg 805f29dbc25Smrgstatic inline int 806f29dbc25Smrgget_op_type(struct exa_format_t *src, struct exa_format_t *dst, int type) 807f29dbc25Smrg{ 808f29dbc25Smrg return (type == CIMGP_CHANNEL_A_ALPHA && 80904007ebaSmrg src->alphabits != dst->alphabits) ? CIMGP_CONVERTED_ALPHA : type; 810f29dbc25Smrg} 811f29dbc25Smrg 812f29dbc25Smrg/* Note - this is the preferred onepass method. The other will remain 813f29dbc25Smrg * ifdefed out until such time that we are sure its not needed 814f29dbc25Smrg */ 815f29dbc25Smrg 816170d5fdcSmrg#define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \ 817170d5fdcSmrg (exaGetPixmapPitch((px)) * (y)) + \ 818170d5fdcSmrg ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) ) 819170d5fdcSmrg 820170d5fdcSmrg#define GetSrcOffset(_x, _y) (exaScratch.srcOffset + ((_y) * exaScratch.srcPitch) + \ 821170d5fdcSmrg ((_x) * exaScratch.srcBpp)) 822170d5fdcSmrg 823170d5fdcSmrgstatic void 824170d5fdcSmrglx_composite_onepass_add_a8(PixmapPtr pxDst, unsigned long dstOffset, 82504007ebaSmrg unsigned long srcOffset, int width, int height, 82604007ebaSmrg int opX, int opY, int srcX, int srcY) 827170d5fdcSmrg{ 828170d5fdcSmrg struct blend_ops_t *opPtr; 829170d5fdcSmrg int apply, type; 830170d5fdcSmrg int optempX, optempY; 831170d5fdcSmrg int i, j; 832170d5fdcSmrg unsigned long pixmapOffset, pixmapPitch, calBitsPixel; 833170d5fdcSmrg 834170d5fdcSmrg pixmapOffset = exaGetPixmapOffset(pxDst); 835170d5fdcSmrg pixmapPitch = exaGetPixmapPitch(pxDst); 836170d5fdcSmrg calBitsPixel = (pxDst->drawable.bitsPerPixel + 7) / 8; 837170d5fdcSmrg 838170d5fdcSmrg /* Keep this GP idle judge here. Otherwise the SW method has chance to 839170d5fdcSmrg * conflict with the HW rendering method */ 840170d5fdcSmrg gp_wait_until_idle(); 841170d5fdcSmrg 842170d5fdcSmrg if (opX % 4 == 0 && srcX % 4 == 0) { 84304007ebaSmrg /* HW acceleration */ 84404007ebaSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 84504007ebaSmrg apply = CIMGP_APPLY_BLEND_TO_ALL; 84604007ebaSmrg gp_declare_blt(0); 84704007ebaSmrg gp_set_bpp(32); 84804007ebaSmrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 84904007ebaSmrg gp_set_source_format(8); 85004007ebaSmrg type = opPtr->type; 85104007ebaSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 85204007ebaSmrg 0); 85304007ebaSmrg gp_screen_to_screen_convert(dstOffset, srcOffset, width / 4, height, 0); 85404007ebaSmrg /* Calculate the pixels in the tail of each line */ 85504007ebaSmrg for (j = srcY; j < srcY + height; j++) 85604007ebaSmrg for (i = srcX + (width / 4) * 4; i < srcX + width; i++) { 85704007ebaSmrg srcOffset = GetSrcOffset(i, j); 85804007ebaSmrg optempX = opX + i - srcX; 85904007ebaSmrg optempY = opY + j - srcY; 86004007ebaSmrg dstOffset = pixmapOffset + pixmapPitch * optempY + 86104007ebaSmrg calBitsPixel * optempX; 86204007ebaSmrg *(cim_fb_ptr + dstOffset) = (*(cim_fb_ptr + srcOffset) 86304007ebaSmrg + *(cim_fb_ptr + dstOffset) <= 86404007ebaSmrg 0xff) ? *(cim_fb_ptr + srcOffset) + 86504007ebaSmrg *(cim_fb_ptr + dstOffset) : 0xff; 86604007ebaSmrg } 86704007ebaSmrg } 86804007ebaSmrg else { 86904007ebaSmrg for (j = srcY; j < srcY + height; j++) 87004007ebaSmrg for (i = srcX; i < srcX + width; i++) { 87104007ebaSmrg srcOffset = GetSrcOffset(i, j); 87204007ebaSmrg optempX = opX + i - srcX; 87304007ebaSmrg optempY = opY + j - srcY; 87404007ebaSmrg dstOffset = pixmapOffset + pixmapPitch * optempY + 87504007ebaSmrg calBitsPixel * optempX; 87604007ebaSmrg *(cim_fb_ptr + dstOffset) = (*(cim_fb_ptr + srcOffset) + 87704007ebaSmrg *(cim_fb_ptr + dstOffset) <= 87804007ebaSmrg 0xff) ? *(cim_fb_ptr + srcOffset) + 87904007ebaSmrg *(cim_fb_ptr + dstOffset) : 0xff; 88004007ebaSmrg } 881170d5fdcSmrg } 882170d5fdcSmrg} 883170d5fdcSmrg 884f29dbc25Smrgstatic void 885f29dbc25Smrglx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset, 88604007ebaSmrg unsigned long srcOffset, int width, int height) 887f29dbc25Smrg{ 888f29dbc25Smrg struct blend_ops_t *opPtr; 889f29dbc25Smrg int apply, type; 890f29dbc25Smrg 891f29dbc25Smrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 892f29dbc25Smrg 893f29dbc25Smrg apply = (exaScratch.dstFormat->alphabits != 0 && 89404007ebaSmrg exaScratch.srcFormat->alphabits != 0) ? 89504007ebaSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 896f29dbc25Smrg 897f29dbc25Smrg gp_declare_blt(0); 898f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 899f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 900f29dbc25Smrg 90104007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt); 902f29dbc25Smrg 90304007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type); 904f29dbc25Smrg 905f29dbc25Smrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 906f29dbc25Smrg 907f29dbc25Smrg gp_screen_to_screen_convert(dstOffset, srcOffset, width, height, 0); 908f29dbc25Smrg} 909f29dbc25Smrg 910170d5fdcSmrgstatic void 911170d5fdcSmrglx_composite_all_black(unsigned long srcOffset, int width, int height) 912170d5fdcSmrg{ 913170d5fdcSmrg struct blend_ops_t *opPtr; 914170d5fdcSmrg int apply, type; 915170d5fdcSmrg 916170d5fdcSmrg opPtr = &lx_alpha_ops[0]; 917170d5fdcSmrg apply = (exaScratch.srcFormat->alphabits != 0) ? 91804007ebaSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 919170d5fdcSmrg gp_declare_blt(0); 920170d5fdcSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.srcFormat->fmt)); 921170d5fdcSmrg gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch); 92204007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.srcFormat->fmt); 92304007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.srcFormat, opPtr->type); 924170d5fdcSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 925170d5fdcSmrg gp_screen_to_screen_convert(srcOffset, srcOffset, width, height, 0); 926170d5fdcSmrg 927170d5fdcSmrg} 928170d5fdcSmrg 929170d5fdcSmrgstatic void 930170d5fdcSmrglx_composite_onepass_special(PixmapPtr pxDst, int width, int height, int opX, 93104007ebaSmrg int opY, int srcX, int srcY) 932170d5fdcSmrg{ 933170d5fdcSmrg struct blend_ops_t *opPtr; 934170d5fdcSmrg int apply, type; 935170d5fdcSmrg int opWidth, opHeight; 936170d5fdcSmrg int optempX, optempY; 937170d5fdcSmrg unsigned int dstOffset, srcOffset = 0; 938170d5fdcSmrg 939170d5fdcSmrg optempX = opX; 940170d5fdcSmrg optempY = opY; 941170d5fdcSmrg 942170d5fdcSmrg /* Make sure srcX and srcY are in source region */ 94304007ebaSmrg srcX = ((srcX % (int) exaScratch.srcWidth) + (int) exaScratch.srcWidth) 94404007ebaSmrg % (int) exaScratch.srcWidth; 94504007ebaSmrg srcY = ((srcY % (int) exaScratch.srcHeight) + (int) exaScratch.srcHeight) 94604007ebaSmrg % (int) exaScratch.srcHeight; 947170d5fdcSmrg 948170d5fdcSmrg opWidth = exaScratch.srcWidth - srcX; 94904007ebaSmrg opHeight = exaScratch.srcHeight - srcY; 950170d5fdcSmrg 951170d5fdcSmrg srcOffset = GetSrcOffset(srcX, srcY); 952170d5fdcSmrg 953170d5fdcSmrg if (width < opWidth) 95404007ebaSmrg opWidth = width; 955170d5fdcSmrg if (height < opHeight) 95604007ebaSmrg opHeight = height; 957170d5fdcSmrg 958170d5fdcSmrg while (1) { 95904007ebaSmrg gp_wait_until_idle(); 96004007ebaSmrg dstOffset = GetPixmapOffset(pxDst, optempX, optempY); 96104007ebaSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 96204007ebaSmrg apply = (exaScratch.dstFormat->alphabits != 0 && 96304007ebaSmrg exaScratch.srcFormat->alphabits != 0) ? 96404007ebaSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 96504007ebaSmrg gp_declare_blt(0); 96604007ebaSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 96704007ebaSmrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 96804007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, 96904007ebaSmrg exaScratch.dstFormat->fmt); 97004007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, 97104007ebaSmrg opPtr->type); 97204007ebaSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, 97304007ebaSmrg apply, 0); 97404007ebaSmrg gp_screen_to_screen_convert(dstOffset, srcOffset, opWidth, opHeight, 0); 97504007ebaSmrg 97604007ebaSmrg optempX += opWidth; 97704007ebaSmrg if (optempX >= opX + width) { 97804007ebaSmrg optempX = opX; 97904007ebaSmrg optempY += opHeight; 98004007ebaSmrg if (optempY >= opY + height) 98104007ebaSmrg break; 98204007ebaSmrg } 98304007ebaSmrg if (optempX == opX) { 98404007ebaSmrg srcOffset = GetSrcOffset(srcX, 0); 98504007ebaSmrg opWidth = ((opX + width) - optempX) > (exaScratch.srcWidth - srcX) 98604007ebaSmrg ? (exaScratch.srcWidth - srcX) : ((opX + width) - optempX); 98704007ebaSmrg opHeight = ((opY + height) - optempY) > exaScratch.srcHeight 98804007ebaSmrg ? exaScratch.srcHeight : ((opY + height) - optempY); 98904007ebaSmrg } 99004007ebaSmrg else if (optempY == opY) { 99104007ebaSmrg srcOffset = GetSrcOffset(0, srcY); 99204007ebaSmrg opWidth = ((opX + width) - optempX) > exaScratch.srcWidth 99304007ebaSmrg ? exaScratch.srcWidth : ((opX + width) - optempX); 99404007ebaSmrg opHeight = ((opY + height) - optempY) > (exaScratch.srcHeight - 99504007ebaSmrg srcY) 99604007ebaSmrg ? (exaScratch.srcHeight - srcY) : ((opY + height) 99704007ebaSmrg - optempY); 99804007ebaSmrg } 99904007ebaSmrg else { 100004007ebaSmrg srcOffset = GetSrcOffset(0, 0); 100104007ebaSmrg opWidth = ((opX + width) - optempX) > exaScratch.srcWidth 100204007ebaSmrg ? exaScratch.srcWidth : ((opX + width) - optempX); 100304007ebaSmrg opHeight = ((opY + height) - optempY) > exaScratch.srcHeight 100404007ebaSmrg ? exaScratch.srcHeight : ((opY + height) - optempY); 100504007ebaSmrg } 1006170d5fdcSmrg } 1007170d5fdcSmrg} 1008170d5fdcSmrg 1009f29dbc25Smrg/* This function handles the multipass blend functions */ 1010f29dbc25Smrg 1011f29dbc25Smrgstatic void 1012f29dbc25Smrglx_composite_multipass(PixmapPtr pxDst, unsigned long dstOffset, 101304007ebaSmrg unsigned long srcOffset, int width, int height) 1014f29dbc25Smrg{ 1015f29dbc25Smrg struct blend_ops_t *opPtr; 1016f29dbc25Smrg int sbpp = lx_get_bpp_from_format(exaScratch.srcFormat->fmt); 1017f29dbc25Smrg int apply, type; 1018f29dbc25Smrg 1019f29dbc25Smrg /* Wait until the GP is idle - this will ensure that the scratch buffer 1020f29dbc25Smrg * isn't occupied */ 1021f29dbc25Smrg 1022f29dbc25Smrg gp_wait_until_idle(); 1023f29dbc25Smrg 1024f29dbc25Smrg /* Copy the destination to the scratch buffer, and convert it to the 1025f29dbc25Smrg * source format */ 1026f29dbc25Smrg 1027f29dbc25Smrg gp_declare_blt(0); 1028f29dbc25Smrg 1029f29dbc25Smrg gp_set_bpp(sbpp); 1030f29dbc25Smrg gp_set_source_format(exaScratch.dstFormat->fmt); 1031f29dbc25Smrg gp_set_raster_operation(0xCC); 1032f29dbc25Smrg gp_set_strides(exaScratch.srcPitch, exaGetPixmapPitch(pxDst)); 1033f29dbc25Smrg gp_screen_to_screen_convert(exaScratch.bufferOffset, dstOffset, 103404007ebaSmrg width, height, 0); 1035f29dbc25Smrg 1036f29dbc25Smrg /* Do the first blend from the source to the scratch buffer */ 1037f29dbc25Smrg 1038f29dbc25Smrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1039f29dbc25Smrg gp_set_bpp(sbpp); 1040f29dbc25Smrg gp_set_source_format(exaScratch.srcFormat->fmt); 1041f29dbc25Smrg gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch); 1042f29dbc25Smrg 1043f29dbc25Smrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1044f29dbc25Smrg 1045f29dbc25Smrg apply = (exaScratch.srcFormat->alphabits == 0) ? 104604007ebaSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1047f29dbc25Smrg 1048f29dbc25Smrg /* If we're destroying the source alpha bits, then make sure we 1049f29dbc25Smrg * use the alpha before the color conversion 1050f29dbc25Smrg */ 1051f29dbc25Smrg 1052f29dbc25Smrg gp_screen_to_screen_blt(exaScratch.bufferOffset, srcOffset, width, height, 105304007ebaSmrg 0); 1054f29dbc25Smrg 1055f29dbc25Smrg /* Finally, do the second blend back to the destination */ 1056f29dbc25Smrg 1057f29dbc25Smrg opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; 1058f29dbc25Smrg 1059f29dbc25Smrg apply = (exaScratch.dstFormat->alphabits == 0) ? 106004007ebaSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1061f29dbc25Smrg 1062f29dbc25Smrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1063f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1064f29dbc25Smrg 106504007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt); 1066f29dbc25Smrg 106704007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type); 1068f29dbc25Smrg 1069f29dbc25Smrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 1070f29dbc25Smrg 1071f29dbc25Smrg gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, 107204007ebaSmrg width, height, 0); 1073f29dbc25Smrg} 1074f29dbc25Smrg 1075f29dbc25Smrgstatic void 1076f29dbc25Smrglx_composite_rotate(PixmapPtr pxDst, unsigned long dstOffset, 107704007ebaSmrg unsigned int srcOffset, int width, int height) 1078f29dbc25Smrg{ 1079f29dbc25Smrg int degrees = 0; 1080f29dbc25Smrg 1081f29dbc25Smrg gp_declare_blt(0); 1082f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1083f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 1084f29dbc25Smrg 108504007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt); 1086f29dbc25Smrg 1087f29dbc25Smrg gp_set_raster_operation(0xCC); 1088f29dbc25Smrg 1089f29dbc25Smrg /* RandR rotation is counter-clockwise, our rotation 1090f29dbc25Smrg * is clockwise, so adjust the numbers accordingly */ 1091f29dbc25Smrg 1092f29dbc25Smrg switch (exaScratch.rotate) { 1093f29dbc25Smrg case RR_Rotate_90: 109404007ebaSmrg degrees = 270; 109504007ebaSmrg break; 1096f29dbc25Smrg case RR_Rotate_180: 109704007ebaSmrg degrees = 180; 109804007ebaSmrg break; 1099f29dbc25Smrg case RR_Rotate_270: 110004007ebaSmrg degrees = 90; 110104007ebaSmrg break; 1102f29dbc25Smrg } 1103f29dbc25Smrg 1104f29dbc25Smrg gp_rotate_blt(dstOffset, srcOffset, width, height, degrees); 1105f29dbc25Smrg} 1106f29dbc25Smrg 1107f29dbc25Smrgstatic void 1108f29dbc25Smrglx_do_composite_mask(PixmapPtr pxDst, unsigned long dstOffset, 110904007ebaSmrg unsigned int maskOffset, int width, int height) 1110f29dbc25Smrg{ 1111f29dbc25Smrg struct blend_ops_t *opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1112f29dbc25Smrg 1113f29dbc25Smrg gp_declare_blt(0); 1114f29dbc25Smrg 1115f29dbc25Smrg gp_set_source_format(exaScratch.srcFormat->fmt); 1116f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 1117f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1118f29dbc25Smrg gp_set_solid_source(exaScratch.srcColor); 1119f29dbc25Smrg 1120f29dbc25Smrg gp_blend_mask_blt(dstOffset, 0, width, height, maskOffset, 112104007ebaSmrg exaScratch.srcPitch, opPtr->operation, 112204007ebaSmrg exaScratch.fourBpp); 1123f29dbc25Smrg} 1124f29dbc25Smrg 1125170d5fdcSmrgstatic void 1126170d5fdcSmrglx_do_composite_mask_two_pass(PixmapPtr pxDst, unsigned long dstOffset, 112704007ebaSmrg unsigned int maskOffset, int width, int height, 112804007ebaSmrg int opX, int opY, xPointFixed srcPoint) 1129170d5fdcSmrg{ 1130170d5fdcSmrg int apply, type; 1131170d5fdcSmrg struct blend_ops_t *opPtr; 1132170d5fdcSmrg int opWidth, opHeight; 1133170d5fdcSmrg int opoverX, opoverY; 1134170d5fdcSmrg 1135170d5fdcSmrg opoverX = opX; 1136170d5fdcSmrg opoverY = opY; 1137170d5fdcSmrg 1138170d5fdcSmrg /* The rendering region should not be bigger than off-screen memory size 1139170d5fdcSmrg * which equals to DEFAULT_EXA_SCRATCH_BFRSZ. If that happens, we split 1140170d5fdcSmrg * the PictOpOver rendering region into several 256KB chunks. And because 1141c744f008Smrg * of the Pitch(stride) parameter, so we use maximum width of mask picture. 1142170d5fdcSmrg * that is to say it is a scanline rendering process */ 1143170d5fdcSmrg if (width * height * 4 > DEFAULT_EXA_SCRATCH_BFRSZ) { 114404007ebaSmrg opWidth = width; 114504007ebaSmrg opHeight = DEFAULT_EXA_SCRATCH_BFRSZ / (width * 4); 114604007ebaSmrg } 114704007ebaSmrg else { 114804007ebaSmrg opWidth = width; 114904007ebaSmrg opHeight = height; 1150170d5fdcSmrg } 1151f29dbc25Smrg 1152170d5fdcSmrg while (1) { 1153170d5fdcSmrg 115404007ebaSmrg /* Wait until the GP is idle - this will ensure that the scratch buffer 115504007ebaSmrg * isn't occupied */ 115604007ebaSmrg 115704007ebaSmrg gp_wait_until_idle(); 115804007ebaSmrg 115904007ebaSmrg /* Copy the source to the scratch buffer, and do a src * mask raster 116004007ebaSmrg * operation */ 116104007ebaSmrg 116204007ebaSmrg gp_declare_blt(0); 116304007ebaSmrg opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; 116404007ebaSmrg gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); 116504007ebaSmrg gp_set_strides(opWidth * 4, exaScratch.srcPitch); 116604007ebaSmrg gp_set_bpp(lx_get_bpp_from_format(CIMGP_SOURCE_FMT_8_8_8_8)); 116704007ebaSmrg gp_set_solid_source(exaScratch.srcColor); 116804007ebaSmrg gp_blend_mask_blt(exaScratch.bufferOffset, 0, opWidth, opHeight, 116904007ebaSmrg maskOffset, exaScratch.srcPitch, opPtr->operation, 117004007ebaSmrg exaScratch.fourBpp); 117104007ebaSmrg 117204007ebaSmrg /* Do a relative operation(refer rendercheck ops.c), and copy the 117304007ebaSmrg * operation result to destination */ 117404007ebaSmrg 117504007ebaSmrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 117604007ebaSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 117704007ebaSmrg apply = (exaScratch.dstFormat->alphabits == 0) ? 117804007ebaSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 117904007ebaSmrg gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); 118004007ebaSmrg gp_set_strides(exaGetPixmapPitch(pxDst), opWidth * 4); 118104007ebaSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 118204007ebaSmrg type = CIMGP_CONVERTED_ALPHA; 118304007ebaSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, 118404007ebaSmrg apply, 0); 118504007ebaSmrg gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, 118604007ebaSmrg opWidth, opHeight, 0); 118704007ebaSmrg 118804007ebaSmrg if (width * height * 4 > DEFAULT_EXA_SCRATCH_BFRSZ) { 118904007ebaSmrg /* Finish the rendering */ 119004007ebaSmrg if (opoverY + opHeight == opY + height) 119104007ebaSmrg break; 119204007ebaSmrg /* Recalculate the Dest and Mask rendering start point */ 119304007ebaSmrg srcPoint.y = srcPoint.y + F(opHeight); 119404007ebaSmrg opoverY = opoverY + opHeight; 119504007ebaSmrg if (opoverY + opHeight > opY + height) 119604007ebaSmrg opHeight = opY + height - opoverY; 119704007ebaSmrg dstOffset = GetPixmapOffset(pxDst, opoverX, opoverY); 119804007ebaSmrg maskOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); 119904007ebaSmrg } 120004007ebaSmrg else 120104007ebaSmrg break; 1202170d5fdcSmrg } 1203170d5fdcSmrg} 1204f29dbc25Smrg 1205f29dbc25Smrgstatic void 1206f29dbc25SmrgtransformPoint(PictTransform * t, xPointFixed * point) 1207f29dbc25Smrg{ 1208f29dbc25Smrg PictVector v; 1209f29dbc25Smrg 1210f29dbc25Smrg v.vector[0] = point->x; 1211f29dbc25Smrg v.vector[1] = point->y; 1212f29dbc25Smrg v.vector[2] = xFixed1; 1213f29dbc25Smrg 1214f29dbc25Smrg if (t != NULL) 121504007ebaSmrg PictureTransformPoint(t, &v); 1216f29dbc25Smrg 1217f29dbc25Smrg point->x = v.vector[0]; 1218f29dbc25Smrg point->y = v.vector[1]; 1219f29dbc25Smrg} 1220f29dbc25Smrg 1221f29dbc25Smrgstatic void 1222f29dbc25Smrglx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX, 122304007ebaSmrg int maskY, int dstX, int dstY, int width, int height) 1224f29dbc25Smrg{ 1225f29dbc25Smrg unsigned int dstOffset, srcOffset = 0; 1226f29dbc25Smrg 1227f29dbc25Smrg xPointFixed srcPoint; 1228f29dbc25Smrg 1229f29dbc25Smrg int opX = dstX; 1230f29dbc25Smrg int opY = dstY; 1231f29dbc25Smrg int opWidth = width; 1232f29dbc25Smrg int opHeight = height; 1233f29dbc25Smrg 1234f29dbc25Smrg /* Transform the source coordinates */ 1235f29dbc25Smrg 1236f29dbc25Smrg if (exaScratch.type == COMP_TYPE_MASK) { 123704007ebaSmrg srcPoint.x = F(maskX); 123804007ebaSmrg srcPoint.y = F(maskY); 123904007ebaSmrg } 124004007ebaSmrg else { 124104007ebaSmrg srcPoint.x = F(srcX); 124204007ebaSmrg srcPoint.y = F(srcY); 1243f29dbc25Smrg } 1244f29dbc25Smrg 1245f29dbc25Smrg /* srcX, srcY point to the upper right side of the bounding box 1246f29dbc25Smrg * in the unrotated coordinate space. Depending on the orientation, 1247f29dbc25Smrg * we have to translate the coordinates to point to the origin of 1248f29dbc25Smrg * the rectangle in the source pixmap */ 1249f29dbc25Smrg 1250f29dbc25Smrg switch (exaScratch.rotate) { 1251f29dbc25Smrg case RR_Rotate_270: 125204007ebaSmrg srcPoint.x += F(width); 1253f29dbc25Smrg 125404007ebaSmrg opWidth = height; 125504007ebaSmrg opHeight = width; 125604007ebaSmrg break; 1257f29dbc25Smrg 1258f29dbc25Smrg case RR_Rotate_180: 125904007ebaSmrg srcPoint.x += F(width); 126004007ebaSmrg srcPoint.y += F(height); 1261f29dbc25Smrg 126204007ebaSmrg srcX += width; 126304007ebaSmrg srcY += height; 126404007ebaSmrg break; 1265f29dbc25Smrg 1266f29dbc25Smrg case RR_Rotate_90: 126704007ebaSmrg srcPoint.y += F(height); 1268f29dbc25Smrg 126904007ebaSmrg opWidth = height; 127004007ebaSmrg opHeight = width; 127104007ebaSmrg break; 1272f29dbc25Smrg } 1273f29dbc25Smrg 1274f29dbc25Smrg transformPoint(exaScratch.transform, &srcPoint); 1275f29dbc25Smrg 1276f29dbc25Smrg /* Adjust the point to fit into the pixmap */ 1277f29dbc25Smrg 1278f29dbc25Smrg if (I(srcPoint.x) < 0) { 127904007ebaSmrg opWidth += I(srcPoint.x); 128004007ebaSmrg srcPoint.x = F(0); 1281f29dbc25Smrg } 1282f29dbc25Smrg 1283f29dbc25Smrg if (I(srcPoint.y) < 0) { 128404007ebaSmrg opHeight += I(srcPoint.y); 128504007ebaSmrg srcPoint.y = F(0); 1286f29dbc25Smrg } 1287f29dbc25Smrg 1288170d5fdcSmrg /* Get the source point offset position */ 1289170d5fdcSmrg 1290f29dbc25Smrg srcOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); 1291f29dbc25Smrg 1292170d5fdcSmrg /* When mask exists, exaScratch.srcWidth and exaScratch.srcHeight are 1293170d5fdcSmrg * the source width and source height; Otherwise, they are mask width 1294170d5fdcSmrg * and mask height */ 1295170d5fdcSmrg /* exaScratch.repeat is the source repeat attribute 1296170d5fdcSmrg * exaScratch.maskrepeat is the mask repeat attribute */ 1297170d5fdcSmrg /* If type is COMP_TYPE_MASK, maskX and maskY are not zero, we should 1298170d5fdcSmrg * subtract them to do the operation in the correct region */ 1299f29dbc25Smrg 1300170d5fdcSmrg /* FIXME: Please add the code to handle the condition when the maskX 1301170d5fdcSmrg * and maskY coordinate are negative or greater than 1302170d5fdcSmrg * exaScratch.srcWidth and exaScratch.srcHeight */ 1303170d5fdcSmrg 1304170d5fdcSmrg if (exaScratch.type == COMP_TYPE_MASK) { 130504007ebaSmrg if ((exaScratch.srcWidth - maskX) < opWidth) 130604007ebaSmrg opWidth = exaScratch.srcWidth - maskX; 130704007ebaSmrg if ((exaScratch.srcHeight - maskY) < opHeight) 130804007ebaSmrg opHeight = exaScratch.srcHeight - maskY; 130904007ebaSmrg } 131004007ebaSmrg else { 131104007ebaSmrg if (exaScratch.type == COMP_TYPE_ONEPASS) { 131204007ebaSmrg /* This is the condition srcX or/and srcY is/are out of source 131304007ebaSmrg * region */ 131404007ebaSmrg if (((srcY >= 0 && srcY >= exaScratch.srcHeight) 131504007ebaSmrg || (srcX >= 0 && srcX >= exaScratch.srcWidth)) && 131604007ebaSmrg (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) { 131704007ebaSmrg if (exaScratch.repeat == 1) { 131804007ebaSmrg opWidth = width; 131904007ebaSmrg opHeight = height; 132004007ebaSmrg } 132104007ebaSmrg else { 132204007ebaSmrg if (exaScratch.op == PictOpOver) 132304007ebaSmrg return; 132404007ebaSmrg else { 132504007ebaSmrg exaScratch.op = PictOpClear; 132604007ebaSmrg opWidth = width; 132704007ebaSmrg opHeight = height; 132804007ebaSmrg } 132904007ebaSmrg } 133004007ebaSmrg /* This is the condition srcX or/and srcY is/are in the source 133104007ebaSmrg * region */ 133204007ebaSmrg } 133304007ebaSmrg else if (srcX >= 0 && srcY >= 0 && 133404007ebaSmrg (exaScratch.op == PictOpOver || 133504007ebaSmrg exaScratch.op == PictOpSrc)) { 133604007ebaSmrg if (exaScratch.repeat == 1) { 133704007ebaSmrg opWidth = width; 133804007ebaSmrg opHeight = height; 133904007ebaSmrg } 134004007ebaSmrg else { 134104007ebaSmrg if ((exaScratch.srcWidth - srcX) < opWidth) 134204007ebaSmrg opWidth = exaScratch.srcWidth - srcX; 134304007ebaSmrg if ((exaScratch.srcHeight - srcY) < opHeight) 134404007ebaSmrg opHeight = exaScratch.srcHeight - srcY; 134504007ebaSmrg } 134604007ebaSmrg /* This is the condition srcX or/and srcY is/are negative */ 134704007ebaSmrg } 134804007ebaSmrg else if ((srcX < 0 || srcY < 0) && 134904007ebaSmrg (exaScratch.op == PictOpOver || 135004007ebaSmrg exaScratch.op == PictOpSrc)) { 135104007ebaSmrg if (exaScratch.repeat == 1) { 135204007ebaSmrg opWidth = width; 135304007ebaSmrg opHeight = height; 135404007ebaSmrg } 135504007ebaSmrg else { 135604007ebaSmrg /* FIXME: We can't support negative srcX/Y for all corner cases in 135704007ebaSmrg * a sane way without a bit bigger refactoring. So as to avoid 135804007ebaSmrg * gross misrenderings (e.g missing tray icons) in current real-world 135904007ebaSmrg * applications, just shift destination appropriately for now and 136004007ebaSmrg * ignore out of bounds source pixmap zero-vector handling. This is 136104007ebaSmrg * actually correct for PictOpOver, but PictOpSrc out of bounds regions 136204007ebaSmrg * should be blacked out, but aren't - without this workaround however 136304007ebaSmrg * it'd be simply all black instead, which is probably worse till a full 136404007ebaSmrg * clean solution solves it for all cases. */ 136504007ebaSmrg if (srcX < 0) { 136604007ebaSmrg opX -= srcX; 136704007ebaSmrg srcX = 0; 136804007ebaSmrg } 136904007ebaSmrg 137004007ebaSmrg if (srcY < 0) { 137104007ebaSmrg opY -= srcY; 137204007ebaSmrg srcY = 0; 137304007ebaSmrg } 137404007ebaSmrg 137504007ebaSmrg /* EXA has taken care of adjusting srcWidth if it gets cut on the right */ 137604007ebaSmrg width = opWidth = exaScratch.srcWidth; 137704007ebaSmrg /* EXA has taken care of adjusting srcHeight if it gets cut on the bottom */ 137804007ebaSmrg height = opHeight = exaScratch.srcHeight; 137904007ebaSmrg } 138004007ebaSmrg } 138104007ebaSmrg else { 138204007ebaSmrg if (exaScratch.srcWidth < opWidth) 138304007ebaSmrg opWidth = exaScratch.srcWidth; 138404007ebaSmrg if (exaScratch.srcHeight < opHeight) 138504007ebaSmrg opHeight = exaScratch.srcHeight; 138604007ebaSmrg } 138704007ebaSmrg } 138804007ebaSmrg else { 138904007ebaSmrg if (exaScratch.rotate == RR_Rotate_180) { 139004007ebaSmrg } 139104007ebaSmrg else { 139204007ebaSmrg if ((exaScratch.srcWidth - srcY) < opWidth) 139304007ebaSmrg opWidth = exaScratch.srcWidth - srcY; 139404007ebaSmrg if ((exaScratch.srcHeight - srcX) < opHeight) 139504007ebaSmrg opHeight = exaScratch.srcHeight - srcX; 139604007ebaSmrg } 139704007ebaSmrg } 1398170d5fdcSmrg } 1399f29dbc25Smrg 1400f29dbc25Smrg while (1) { 1401f29dbc25Smrg 140204007ebaSmrg dstOffset = GetPixmapOffset(pxDst, opX, opY); 140304007ebaSmrg 140404007ebaSmrg switch (exaScratch.type) { 140504007ebaSmrg 140604007ebaSmrg case COMP_TYPE_MASK:{ 140704007ebaSmrg if (exaScratch.op == PictOpOver || exaScratch.op == 140804007ebaSmrg PictOpOutReverse || exaScratch.op == PictOpInReverse || 140904007ebaSmrg exaScratch.op == PictOpIn || exaScratch.op == PictOpOut || 141004007ebaSmrg exaScratch.op == PictOpOverReverse) 141104007ebaSmrg lx_do_composite_mask_two_pass(pxDst, dstOffset, 141204007ebaSmrg srcOffset, opWidth, opHeight, opX, 141304007ebaSmrg opY, srcPoint); 141404007ebaSmrg else 141504007ebaSmrg lx_do_composite_mask(pxDst, dstOffset, srcOffset, 141604007ebaSmrg opWidth, opHeight); 141704007ebaSmrg } 141804007ebaSmrg break; 141904007ebaSmrg 142004007ebaSmrg case COMP_TYPE_ONEPASS: 142104007ebaSmrg if ((exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc) 142204007ebaSmrg && (exaScratch.repeat == 1)) { 142304007ebaSmrg lx_composite_onepass_special(pxDst, opWidth, opHeight, opX, opY, 142404007ebaSmrg srcX, srcY); 142504007ebaSmrg return; 142604007ebaSmrg } 142704007ebaSmrg else if ((exaScratch.op == PictOpAdd) && (exaScratch.srcFormat->exa 142804007ebaSmrg == PICT_a8) && 142904007ebaSmrg (exaScratch.dstFormat->exa == PICT_a8)) 143004007ebaSmrg lx_composite_onepass_add_a8(pxDst, dstOffset, srcOffset, 143104007ebaSmrg opWidth, opHeight, opX, opY, srcX, 143204007ebaSmrg srcY); 143304007ebaSmrg else 143404007ebaSmrg lx_composite_onepass(pxDst, dstOffset, srcOffset, opWidth, 143504007ebaSmrg opHeight); 143604007ebaSmrg break; 143704007ebaSmrg 143804007ebaSmrg case COMP_TYPE_TWOPASS: 143904007ebaSmrg lx_composite_multipass(pxDst, dstOffset, srcOffset, opWidth, 144004007ebaSmrg opHeight); 144104007ebaSmrg 144204007ebaSmrg case COMP_TYPE_ROTATE: 144304007ebaSmrg lx_composite_rotate(pxDst, dstOffset, srcOffset, opWidth, opHeight); 144404007ebaSmrg break; 144504007ebaSmrg } 144604007ebaSmrg 144704007ebaSmrg opX += opWidth; 144804007ebaSmrg 144904007ebaSmrg if (opX >= dstX + width) { 145004007ebaSmrg opX = dstX; 145104007ebaSmrg opY += opHeight; 145204007ebaSmrg 145304007ebaSmrg if (opY >= dstY + height) 145404007ebaSmrg break; 145504007ebaSmrg } 145604007ebaSmrg 145704007ebaSmrg /* FIXME: Please add the code to handle the condition when the maskX 145804007ebaSmrg * and maskY coordinate are negative or greater than 145904007ebaSmrg * exaScratch.srcWidth and exaScratch.srcHeight */ 146004007ebaSmrg 146104007ebaSmrg if (exaScratch.type == COMP_TYPE_MASK) { 146204007ebaSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - maskX) 146304007ebaSmrg ? (exaScratch.srcWidth - maskX) : (dstX + width) - opX; 146404007ebaSmrg opHeight = ((dstY + height) - opY) > (exaScratch.srcHeight - maskY) 146504007ebaSmrg ? (exaScratch.srcHeight - maskY) : (dstY + height) - opY; 146604007ebaSmrg /* All black out of the mask */ 146704007ebaSmrg if (!exaScratch.maskrepeat) 146804007ebaSmrg exaScratch.srcColor = 0x0; 146904007ebaSmrg } 147004007ebaSmrg else { 147104007ebaSmrg if (exaScratch.type == COMP_TYPE_ONEPASS) { 147204007ebaSmrg if (srcX >= 0 && srcY >= 0 && (exaScratch.op == PictOpOver || 147304007ebaSmrg exaScratch.op == PictOpSrc || 147404007ebaSmrg exaScratch.op == PictOpClear)) { 147504007ebaSmrg opWidth = 147604007ebaSmrg ((dstX + width) - opX) > 147704007ebaSmrg (exaScratch.srcWidth - srcX) ? (exaScratch.srcWidth - 147804007ebaSmrg srcX) : (dstX + width) 147904007ebaSmrg - opX; 148004007ebaSmrg opHeight = ((dstY + height) - opY) > 148104007ebaSmrg (exaScratch.srcHeight - srcY) ? 148204007ebaSmrg (exaScratch.srcHeight - srcY) : (dstY + height) - opY; 148304007ebaSmrg } 148404007ebaSmrg else { 148504007ebaSmrg opWidth = ((dstX + width) - opX) > exaScratch.srcWidth ? 148604007ebaSmrg exaScratch.srcWidth : (dstX + width) - opX; 148704007ebaSmrg opHeight = ((dstY + height) - opY) > exaScratch.srcHeight ? 148804007ebaSmrg exaScratch.srcHeight : (dstY + height) - opY; 148904007ebaSmrg } 149004007ebaSmrg } 149104007ebaSmrg else { 149204007ebaSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - srcY) 149304007ebaSmrg ? (exaScratch.srcWidth - srcY) : (dstX + width) - opX; 149404007ebaSmrg opHeight = 149504007ebaSmrg ((dstY + height) - opY) > 149604007ebaSmrg (exaScratch.srcHeight - srcX) ? (exaScratch.srcHeight - 149704007ebaSmrg srcX) : (dstY + height) - 149804007ebaSmrg opY; 149904007ebaSmrg } 150004007ebaSmrg /* All black out of the source */ 150104007ebaSmrg if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ONEPASS)) { 150204007ebaSmrg /* FIXME: We black out the source here, so that any further regions 150304007ebaSmrg * in the loop get handled as a source that's a zero-vector (as 150404007ebaSmrg * defined for out-of-bounds from source pixmap for RepeatModeNone), 150504007ebaSmrg * but this will likely interfere with cases where srcX and/or srcY 150604007ebaSmrg * is negative - as opposed to e.g width being larger than srcWidth, 150704007ebaSmrg * which is exercised in rendercheck (always rectangle in top-left 150804007ebaSmrg * corner). 150904007ebaSmrg * Additionally it forces the drawing into tiles of srcWidth/srcHeight 151004007ebaSmrg * for non-repeat modes too, where we don't really need to tile it like 151104007ebaSmrg * this and could draw the out of bound regions all at once (or at most 151204007ebaSmrg * in 4 operations without the big loop). */ 151304007ebaSmrg lx_composite_all_black(srcOffset, exaScratch.srcWidth, 151404007ebaSmrg exaScratch.srcHeight); 151504007ebaSmrg } 151604007ebaSmrg if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ROTATE)) 151704007ebaSmrg break; 151804007ebaSmrg } 1519f29dbc25Smrg } 1520f29dbc25Smrg} 1521f29dbc25Smrg 1522f29dbc25Smrgstatic void 1523f29dbc25Smrglx_wait_marker(ScreenPtr PScreen, int marker) 1524f29dbc25Smrg{ 1525f29dbc25Smrg gp_wait_until_idle(); 1526f29dbc25Smrg} 1527f29dbc25Smrg 1528f29dbc25Smrgstatic void 1529f29dbc25Smrglx_done(PixmapPtr ptr) 1530f29dbc25Smrg{ 1531f29dbc25Smrg} 1532f29dbc25Smrg 1533f29dbc25Smrg#if 0 1534f29dbc25Smrgstatic void 1535f29dbc25Smrglx_upload_to_screen(PixmapPtr pxDst, int x, int y, int w, int h, 153604007ebaSmrg char *src, int src_pitch) 1537f29dbc25Smrg{ 1538f29dbc25Smrg GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); 1539f29dbc25Smrg int dst_pitch = exaGetPixmapPitch(pxDst); 1540f29dbc25Smrg int cpp = (pxDst->drawable.bitsPerPixel + 7) / 8; 1541f29dbc25Smrg 1542f29dbc25Smrg char *dst; 1543f29dbc25Smrg int offset = exaGetPixmapOffset(pxDst); 1544f29dbc25Smrg 154504007ebaSmrg dst = (char *) (pGeode->FBBase + offset + (y * dst_pitch) + (x * cpp)); 1546f29dbc25Smrg int i; 1547f29dbc25Smrg 1548f29dbc25Smrg for (i = 0; i < h; i++) { 154904007ebaSmrg memcpy(dst, src, w * cpp); 155004007ebaSmrg dst += dst_pitch; 155104007ebaSmrg src += src_pitch; 1552f29dbc25Smrg } 1553f29dbc25Smrg} 1554f29dbc25Smrg#endif 1555f29dbc25Smrg 155604007ebaSmrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 2) 1557f29dbc25Smrg 1558f29dbc25Smrgstatic Bool 1559f29dbc25Smrglx_exa_pixmap_is_offscreen(PixmapPtr pPixmap) 1560f29dbc25Smrg{ 156104007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pPixmap->drawable.pScreen); 1562f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 156304007ebaSmrg void *start = (void *) (pGeode->FBBase); 1564f29dbc25Smrg void *end = 156504007ebaSmrg (void *) (pGeode->FBBase + pGeode->offscreenStart + 156604007ebaSmrg pGeode->offscreenSize); 1567f29dbc25Smrg 156804007ebaSmrg if ((void *) pPixmap->devPrivate.ptr >= start && 156904007ebaSmrg (void *) pPixmap->devPrivate.ptr < end) 157004007ebaSmrg return TRUE; 1571f29dbc25Smrg 1572f29dbc25Smrg return FALSE; 1573f29dbc25Smrg} 1574f29dbc25Smrg 1575f29dbc25Smrg#endif 1576f29dbc25Smrg 1577f29dbc25SmrgBool 1578f29dbc25SmrgLXExaInit(ScreenPtr pScreen) 1579f29dbc25Smrg{ 158004007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 1581f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1582f29dbc25Smrg ExaDriverPtr pExa = pGeode->pExa; 1583f29dbc25Smrg 1584f29dbc25Smrg pExa->exa_major = EXA_VERSION_MAJOR; 1585f29dbc25Smrg pExa->exa_minor = EXA_VERSION_MINOR; 1586f29dbc25Smrg 1587f29dbc25Smrg pExa->WaitMarker = lx_wait_marker; 1588f29dbc25Smrg 1589f29dbc25Smrg pExa->PrepareSolid = lx_prepare_solid; 1590f29dbc25Smrg pExa->Solid = lx_do_solid; 1591f29dbc25Smrg pExa->DoneSolid = lx_done; 1592f29dbc25Smrg 1593f29dbc25Smrg pExa->PrepareCopy = lx_prepare_copy; 1594f29dbc25Smrg pExa->Copy = lx_do_copy; 1595f29dbc25Smrg pExa->DoneCopy = lx_done; 1596f29dbc25Smrg 1597f29dbc25Smrg /* Composite */ 1598f29dbc25Smrg pExa->CheckComposite = lx_check_composite; 1599f29dbc25Smrg pExa->PrepareComposite = lx_prepare_composite; 1600f29dbc25Smrg pExa->Composite = lx_do_composite; 1601f29dbc25Smrg pExa->DoneComposite = lx_done; 1602f29dbc25Smrg //pExa->UploadToScreen = lx_upload_to_screen; 1603f29dbc25Smrg 160404007ebaSmrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 2) 1605f29dbc25Smrg pExa->PixmapIsOffscreen = lx_exa_pixmap_is_offscreen; 1606f29dbc25Smrg#endif 1607f29dbc25Smrg 1608f29dbc25Smrg //pExa->flags = EXA_OFFSCREEN_PIXMAPS; 1609f29dbc25Smrg 1610f29dbc25Smrg return exaDriverInit(pScreen, pGeode->pExa); 1611f29dbc25Smrg} 1612