lx_exa.c revision 04007eba
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 39f29dbc25Smrg#include "xf86.h" 40f29dbc25Smrg#include "exa.h" 41f29dbc25Smrg 42f29dbc25Smrg#include "geode.h" 43f29dbc25Smrg#include "cim_defs.h" 44f29dbc25Smrg#include "cim_regs.h" 45f29dbc25Smrg 46f29dbc25Smrg#include "geode_blend.h" 47f29dbc25Smrg 48f29dbc25Smrg#define F(x) IntToxFixed(x) 49f29dbc25Smrg#define I(x) xFixedToInt(x) 50f29dbc25Smrg 5104007ebaSmrg#define GEODE_TRACE_FALL 0 5204007ebaSmrg 5304007ebaSmrg#if GEODE_TRACE_FALL 5404007ebaSmrg#define GEODE_FALLBACK(x) \ 5504007ebaSmrgdo { \ 5604007ebaSmrg ErrorF("%s: ", __FUNCTION__); \ 5704007ebaSmrg ErrorF x; \ 5804007ebaSmrg return FALSE; \ 5904007ebaSmrg} while (0) 6004007ebaSmrg#else 6104007ebaSmrg#define GEODE_FALLBACK(x) return FALSE 6204007ebaSmrg#endif 6304007ebaSmrg 6404007ebaSmrgstatic const struct exa_format_t { 65f29dbc25Smrg int exa; 66f29dbc25Smrg int bpp; 67f29dbc25Smrg int fmt; 68f29dbc25Smrg int alphabits; 69f29dbc25Smrg} lx_exa_formats[] = { 70f29dbc25Smrg { 71f29dbc25Smrg PICT_a8r8g8b8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 8}, { 72f29dbc25Smrg PICT_x8r8g8b8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 0}, { 73f29dbc25Smrg PICT_x8b8g8r8, 32, CIMGP_SOURCE_FMT_32BPP_BGR, 0}, { 74f29dbc25Smrg PICT_a4r4g4b4, 16, CIMGP_SOURCE_FMT_4_4_4_4, 4}, { 75f29dbc25Smrg PICT_a1r5g5b5, 16, CIMGP_SOURCE_FMT_1_5_5_5, 1}, { 76f29dbc25Smrg PICT_r5g6b5, 16, CIMGP_SOURCE_FMT_0_5_6_5, 0}, { 77f29dbc25Smrg PICT_b5g6r5, 16, CIMGP_SOURCE_FMT_16BPP_BGR, 0}, { 78f29dbc25Smrg PICT_x1r5g5b5, 16, CIMGP_SOURCE_FMT_1_5_5_5, 0}, { 79f29dbc25Smrg PICT_x1b5g5r5, 16, CIMGP_SOURCE_FMT_15BPP_BGR, 0}, { 80170d5fdcSmrg PICT_r3g3b2, 8, CIMGP_SOURCE_FMT_3_3_2, 0}, { 81170d5fdcSmrg PICT_a8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 8} 82f29dbc25Smrg}; 83f29dbc25Smrg 84f29dbc25Smrg/* This is a chunk of memory we use for scratch space */ 85f29dbc25Smrg 86f29dbc25Smrg#define COMP_TYPE_MASK 0 87f29dbc25Smrg#define COMP_TYPE_ONEPASS 1 88f29dbc25Smrg#define COMP_TYPE_TWOPASS 3 89f29dbc25Smrg#define COMP_TYPE_ROTATE 5 90f29dbc25Smrg 9104007ebaSmrgstatic struct { 92f29dbc25Smrg int type; 93f29dbc25Smrg 94f29dbc25Smrg unsigned int srcOffset; 95f29dbc25Smrg unsigned int srcPitch; 96f29dbc25Smrg unsigned int srcBpp; 97f29dbc25Smrg unsigned int srcWidth, srcHeight; 98f29dbc25Smrg 99f29dbc25Smrg unsigned int srcColor; 100f29dbc25Smrg int op; 101f29dbc25Smrg int repeat; 102170d5fdcSmrg int maskrepeat; 103f29dbc25Smrg unsigned int fourBpp; 104f29dbc25Smrg unsigned int bufferOffset; 105f29dbc25Smrg struct exa_format_t *srcFormat; 106f29dbc25Smrg struct exa_format_t *dstFormat; 107f29dbc25Smrg 108f29dbc25Smrg int rotate; 109f29dbc25Smrg PictTransform *transform; 110f29dbc25Smrg 111f29dbc25Smrg} exaScratch; 112f29dbc25Smrg 113f29dbc25Smrgstatic const int SDfn[16] = { 114f29dbc25Smrg 0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE, 115f29dbc25Smrg 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF 116f29dbc25Smrg}; 117f29dbc25Smrg 118f29dbc25Smrgstatic const int SDfn_PM[16] = { 119f29dbc25Smrg 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 120f29dbc25Smrg 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA 121f29dbc25Smrg}; 122f29dbc25Smrg 123f29dbc25Smrg/* These functions check to see if we can safely prefetch the memory 124f29dbc25Smrg * for the blt, or if we have to wait the previous blt to complete. 125f29dbc25Smrg * One function is for the fill, and the other is for the copy because 126f29dbc25Smrg * they have different requirements based on ROP 127f29dbc25Smrg */ 128f29dbc25Smrg 129f29dbc25Smrgstatic int lx0 = -1, ly0 = -1, lx1 = -1, ly1 = -1; 130f29dbc25Smrg 131f29dbc25Smrgstatic int 132f29dbc25Smrglx_fill_flags(int x0, int y0, int w, int h, int rop) 133f29dbc25Smrg{ 134f29dbc25Smrg int x1 = x0 + w, y1 = y0 + h; 13504007ebaSmrg int n = ((rop ^ (rop >> 1)) & 0x55) == 0 || /* no dst */ 13604007ebaSmrg x0 >= lx1 || y0 >= ly1 || /* rght/below */ 13704007ebaSmrg x1 <= lx0 || y1 <= ly0 ? /* left/above */ 13804007ebaSmrg 0 : CIMGP_BLTFLAGS_HAZARD; 139f29dbc25Smrg 140f29dbc25Smrg lx0 = x0; 141f29dbc25Smrg ly0 = y0; 142f29dbc25Smrg lx1 = x1; 143f29dbc25Smrg ly1 = y1; 144f29dbc25Smrg 145f29dbc25Smrg return n; 146f29dbc25Smrg} 147f29dbc25Smrg 148f29dbc25Smrgstatic int 149f29dbc25Smrglx_copy_flags(int x0, int y0, int x1, int y1, int w, int h, int rop) 150f29dbc25Smrg{ 151f29dbc25Smrg int x2 = x1 + w, y2 = y1 + h; 152f29dbc25Smrg 153f29dbc25Smrg /* dst not hazzard and src not hazzard */ 154f29dbc25Smrg int n = (((rop ^ (rop >> 1)) & 0x55) == 0 || 15504007ebaSmrg x1 >= lx1 || y1 >= ly1 || 15604007ebaSmrg x2 <= lx0 || y2 <= ly0) && 15704007ebaSmrg (((rop ^ (rop >> 2)) & 0x33) == 0 || 15804007ebaSmrg x0 >= lx1 || y0 >= ly1 || 15904007ebaSmrg x0 + w <= lx0 || y0 + h <= ly0) ? 0 : CIMGP_BLTFLAGS_HAZARD; 160f29dbc25Smrg 161f29dbc25Smrg lx0 = x1; 162f29dbc25Smrg ly0 = y1; 163f29dbc25Smrg lx1 = x2; 164f29dbc25Smrg ly1 = y2; 165f29dbc25Smrg 166f29dbc25Smrg return n; 167f29dbc25Smrg} 168f29dbc25Smrg 169f29dbc25Smrg/* These are borrowed from the exa engine - they should be made global 170f29dbc25Smrg and available to drivers, but until then.... 171f29dbc25Smrg*/ 172f29dbc25Smrg 173f29dbc25Smrg/* exaGetPixelFromRGBA (exa_render.c) */ 174f29dbc25Smrg 175f29dbc25Smrgstatic Bool 17604007ebaSmrg_GetPixelFromRGBA(CARD32 *pixel, 17704007ebaSmrg CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, 17804007ebaSmrg CARD32 format) 179f29dbc25Smrg{ 180f29dbc25Smrg int rbits, bbits, gbits, abits; 181f29dbc25Smrg int rshift, bshift, gshift, ashift; 182f29dbc25Smrg 183f29dbc25Smrg *pixel = 0; 184f29dbc25Smrg 185f29dbc25Smrg if (!PICT_FORMAT_COLOR(format)) 18604007ebaSmrg return FALSE; 187f29dbc25Smrg 188f29dbc25Smrg rbits = PICT_FORMAT_R(format); 189f29dbc25Smrg gbits = PICT_FORMAT_G(format); 190f29dbc25Smrg bbits = PICT_FORMAT_B(format); 191f29dbc25Smrg abits = PICT_FORMAT_A(format); 192f29dbc25Smrg 193f29dbc25Smrg if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 19404007ebaSmrg bshift = 0; 19504007ebaSmrg gshift = bbits; 19604007ebaSmrg rshift = gshift + gbits; 19704007ebaSmrg ashift = rshift + rbits; 19804007ebaSmrg } 19904007ebaSmrg else { /* PICT_TYPE_ABGR */ 20004007ebaSmrg rshift = 0; 20104007ebaSmrg gshift = rbits; 20204007ebaSmrg bshift = gshift + gbits; 20304007ebaSmrg ashift = bshift + bbits; 204f29dbc25Smrg } 205f29dbc25Smrg 206f29dbc25Smrg *pixel |= (blue >> (16 - bbits)) << bshift; 207f29dbc25Smrg *pixel |= (red >> (16 - rbits)) << rshift; 208f29dbc25Smrg *pixel |= (green >> (16 - gbits)) << gshift; 209f29dbc25Smrg *pixel |= (alpha >> (16 - abits)) << ashift; 210f29dbc25Smrg 211f29dbc25Smrg return TRUE; 212f29dbc25Smrg} 213f29dbc25Smrg 214f29dbc25Smrg/* exaGetRGBAFromPixel (exa_render.c) */ 215f29dbc25Smrg 216f29dbc25Smrgstatic Bool 217f29dbc25Smrg_GetRGBAFromPixel(CARD32 pixel, 21804007ebaSmrg CARD16 *red, 21904007ebaSmrg CARD16 *green, CARD16 *blue, CARD16 *alpha, CARD32 format) 220f29dbc25Smrg{ 221f29dbc25Smrg int rbits, bbits, gbits, abits; 222f29dbc25Smrg int rshift, bshift, gshift, ashift; 223f29dbc25Smrg 224f29dbc25Smrg if (!PICT_FORMAT_COLOR(format)) 22504007ebaSmrg return FALSE; 226f29dbc25Smrg 227f29dbc25Smrg rbits = PICT_FORMAT_R(format); 228f29dbc25Smrg gbits = PICT_FORMAT_G(format); 229f29dbc25Smrg bbits = PICT_FORMAT_B(format); 230f29dbc25Smrg abits = PICT_FORMAT_A(format); 231f29dbc25Smrg 232f29dbc25Smrg if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 23304007ebaSmrg bshift = 0; 23404007ebaSmrg gshift = bbits; 23504007ebaSmrg rshift = gshift + gbits; 23604007ebaSmrg ashift = rshift + rbits; 23704007ebaSmrg } 23804007ebaSmrg else { /* PICT_TYPE_ABGR */ 23904007ebaSmrg rshift = 0; 24004007ebaSmrg gshift = rbits; 24104007ebaSmrg bshift = gshift + gbits; 24204007ebaSmrg ashift = bshift + bbits; 243f29dbc25Smrg } 244f29dbc25Smrg 245f29dbc25Smrg *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); 246f29dbc25Smrg while (rbits < 16) { 24704007ebaSmrg *red |= *red >> rbits; 24804007ebaSmrg rbits <<= 1; 249f29dbc25Smrg } 250f29dbc25Smrg 251f29dbc25Smrg *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); 252f29dbc25Smrg while (gbits < 16) { 25304007ebaSmrg *green |= *green >> gbits; 25404007ebaSmrg gbits <<= 1; 255f29dbc25Smrg } 256f29dbc25Smrg 257f29dbc25Smrg *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); 258f29dbc25Smrg while (bbits < 16) { 25904007ebaSmrg *blue |= *blue >> bbits; 26004007ebaSmrg bbits <<= 1; 261f29dbc25Smrg } 262f29dbc25Smrg 263f29dbc25Smrg if (abits) { 26404007ebaSmrg *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); 26504007ebaSmrg while (abits < 16) { 26604007ebaSmrg *alpha |= *alpha >> abits; 26704007ebaSmrg abits <<= 1; 26804007ebaSmrg } 26904007ebaSmrg } 27004007ebaSmrg else 27104007ebaSmrg *alpha = 0xffff; 272f29dbc25Smrg 273f29dbc25Smrg return TRUE; 274f29dbc25Smrg} 275f29dbc25Smrg 276f29dbc25Smrgstatic unsigned int 277f29dbc25Smrglx_get_source_color(PixmapPtr pSrc, int srcFormat, int dstFormat) 278f29dbc25Smrg{ 279f29dbc25Smrg CARD32 in, out; 280f29dbc25Smrg CARD16 red = 0, green = 0, blue = 0, alpha = 0; 281f29dbc25Smrg 282f29dbc25Smrg /* Stall to avoid a race with the upload function */ 283f29dbc25Smrg /* for 1.4 and newer, the problem will be resolved within 284f29dbc25Smrg * exaGetPixmapFirstPixel, so this should be adjusted so 285f29dbc25Smrg * the stall isn't run needlessly 286f29dbc25Smrg */ 28704007ebaSmrg /* FIXME: xserver-1.4 with a supposed fix for this is really old, so kill the stall? */ 288f29dbc25Smrg 289f29dbc25Smrg gp_wait_until_idle(); 290f29dbc25Smrg in = exaGetPixmapFirstPixel(pSrc); 291f29dbc25Smrg 292f29dbc25Smrg _GetRGBAFromPixel(in, &red, &blue, &green, &alpha, srcFormat); 293f29dbc25Smrg _GetPixelFromRGBA(&out, red, blue, green, alpha, dstFormat); 294f29dbc25Smrg 295f29dbc25Smrg return out; 296f29dbc25Smrg} 297f29dbc25Smrg 298f29dbc25Smrgstatic Bool 299f29dbc25Smrglx_prepare_solid(PixmapPtr pxMap, int alu, Pixel planemask, Pixel fg) 300f29dbc25Smrg{ 301f29dbc25Smrg int pitch = exaGetPixmapPitch(pxMap); 302f29dbc25Smrg int op = (planemask == ~0U) ? SDfn[alu] : SDfn_PM[alu]; 303f29dbc25Smrg 304f29dbc25Smrg gp_declare_blt(0); 305f29dbc25Smrg gp_set_bpp(pxMap->drawable.bitsPerPixel); 306f29dbc25Smrg 307f29dbc25Smrg gp_set_raster_operation(op); 308f29dbc25Smrg 309f29dbc25Smrg if (planemask != ~0U) 31004007ebaSmrg gp_set_solid_pattern(planemask); 311f29dbc25Smrg 312f29dbc25Smrg exaScratch.op = op; 313f29dbc25Smrg 314f29dbc25Smrg gp_set_solid_source(fg); 315f29dbc25Smrg 316f29dbc25Smrg gp_set_strides(pitch, pitch); 317f29dbc25Smrg gp_write_parameters(); 318f29dbc25Smrg return TRUE; 319f29dbc25Smrg} 320f29dbc25Smrg 321f29dbc25Smrgstatic void 322f29dbc25Smrglx_do_solid(PixmapPtr pxMap, int x1, int y1, int x2, int y2) 323f29dbc25Smrg{ 324f29dbc25Smrg int bpp = (pxMap->drawable.bitsPerPixel + 7) / 8; 325f29dbc25Smrg int pitch = exaGetPixmapPitch(pxMap); 32604007ebaSmrg unsigned int offset = exaGetPixmapOffset(pxMap) + (pitch * y1) + (bpp * x1); 327f29dbc25Smrg 328f29dbc25Smrg gp_declare_blt(lx_fill_flags(x1, y1, x2 - x1, y2 - y1, exaScratch.op)); 329f29dbc25Smrg gp_pattern_fill(offset, x2 - x1, y2 - y1); 330f29dbc25Smrg} 331f29dbc25Smrg 332f29dbc25Smrgstatic Bool 333f29dbc25Smrglx_prepare_copy(PixmapPtr pxSrc, PixmapPtr pxDst, int dx, int dy, 33404007ebaSmrg int alu, Pixel planemask) 335f29dbc25Smrg{ 336f29dbc25Smrg int dpitch = exaGetPixmapPitch(pxDst); 337f29dbc25Smrg int op = (planemask == ~0U) ? SDfn[alu] : SDfn_PM[alu]; 338f29dbc25Smrg 339f29dbc25Smrg gp_declare_blt(0); 340f29dbc25Smrg gp_set_bpp(pxDst->drawable.bitsPerPixel); 341f29dbc25Smrg 342f29dbc25Smrg gp_set_raster_operation(op); 343f29dbc25Smrg 344f29dbc25Smrg if (planemask != ~0U) 34504007ebaSmrg gp_set_solid_pattern(planemask); 346f29dbc25Smrg 347f29dbc25Smrg exaScratch.srcOffset = exaGetPixmapOffset(pxSrc); 348f29dbc25Smrg exaScratch.srcPitch = exaGetPixmapPitch(pxSrc); 349f29dbc25Smrg exaScratch.srcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; 350f29dbc25Smrg 351f29dbc25Smrg exaScratch.op = op; 352f29dbc25Smrg 353f29dbc25Smrg gp_set_strides(dpitch, exaScratch.srcPitch); 354f29dbc25Smrg gp_write_parameters(); 355f29dbc25Smrg return TRUE; 356f29dbc25Smrg} 357f29dbc25Smrg 358f29dbc25Smrgstatic void 359f29dbc25Smrglx_do_copy(PixmapPtr pxDst, int srcX, int srcY, 36004007ebaSmrg int dstX, int dstY, int w, int h) 361f29dbc25Smrg{ 362f29dbc25Smrg int dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8; 363f29dbc25Smrg int dstPitch = exaGetPixmapPitch(pxDst); 364f29dbc25Smrg unsigned int srcOffset, dstOffset; 365f29dbc25Smrg int flags = 0; 366f29dbc25Smrg 36704007ebaSmrg gp_declare_blt(lx_copy_flags(srcX, srcY, dstX, dstY, w, h, exaScratch.op)); 368f29dbc25Smrg 369f29dbc25Smrg srcOffset = exaScratch.srcOffset + (exaScratch.srcPitch * srcY) + 37004007ebaSmrg (exaScratch.srcBpp) * srcX; 371f29dbc25Smrg 37204007ebaSmrg dstOffset = exaGetPixmapOffset(pxDst) + (dstPitch * dstY) + (dstBpp * dstX); 373f29dbc25Smrg 374f29dbc25Smrg if (dstX > srcX) 37504007ebaSmrg flags |= CIMGP_NEGXDIR; 376f29dbc25Smrg 377f29dbc25Smrg if (dstY > srcY) 37804007ebaSmrg flags |= CIMGP_NEGYDIR; 379f29dbc25Smrg 380f29dbc25Smrg gp_screen_to_screen_blt(dstOffset, srcOffset, w, h, flags); 381f29dbc25Smrg} 382f29dbc25Smrg 383f29dbc25Smrg/* Composite operations 384f29dbc25Smrg 385f29dbc25SmrgThese are the simplest - one pass operations - if there is no format or 386f29dbc25Smrgmask, the we can make these happen pretty fast 387f29dbc25Smrg 388f29dbc25Smrg Operation Type Channel Alpha 389f29dbc25SmrgPictOpClear 0 2 0 3 390f29dbc25SmrgPictOpSrc 0 3 0 3 391f29dbc25SmrgPictOpDst 0 3 1 3 392f29dbc25SmrgPictOpOver 2 0 0 3 393f29dbc25SmrgPictOpOverReverse 2 0 1 3 394f29dbc25SmrgPictOpIn 0 1 0 3 395f29dbc25SmrgPictOpInReverse 0 1 1 3 396f29dbc25SmrgPictOpOut 1 0 0 3 397f29dbc25SmrgPictOpOutReverse 1 0 1 3 398f29dbc25SmrgPictOpAdd 2 2 0 3 399f29dbc25Smrg 400f29dbc25SmrgThe following require multiple passes 401f29dbc25SmrgPictOpAtop 402f29dbc25SmrgPictOpXor 403f29dbc25Smrg*/ 404f29dbc25Smrg 40504007ebaSmrgstruct blend_ops_t { 406f29dbc25Smrg int operation; 407f29dbc25Smrg int type; 408f29dbc25Smrg int channel; 409f29dbc25Smrg} lx_alpha_ops[] = { 410f29dbc25Smrg /* PictOpClear */ 411f29dbc25Smrg { 412f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CONSTANT_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 413f29dbc25Smrg }, 41404007ebaSmrg /* PictOpSrc */ 415f29dbc25Smrg { 416f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_ALPHA_EQUALS_ONE, CIMGP_CHANNEL_A_SOURCE}, { 417f29dbc25Smrg }, 41804007ebaSmrg /* PictOpDst */ 419f29dbc25Smrg { 420f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_ALPHA_EQUALS_ONE, CIMGP_CHANNEL_A_DEST}, { 421f29dbc25Smrg }, 42204007ebaSmrg /* PictOpOver */ 423f29dbc25Smrg { 424170d5fdcSmrg CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 425170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 42604007ebaSmrg /* PictOpOverReverse */ 427f29dbc25Smrg { 428170d5fdcSmrg CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { 429170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 43004007ebaSmrg /* PictOpIn */ 431f29dbc25Smrg { 432f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 433170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 43404007ebaSmrg /* PictOpInReverse */ 435f29dbc25Smrg { 436f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_DEST}, { 437170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 43804007ebaSmrg /* PictOpOut */ 439f29dbc25Smrg { 440170d5fdcSmrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { 441170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 44204007ebaSmrg /* PictOpOutReverse */ 443f29dbc25Smrg { 444170d5fdcSmrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 445170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 44604007ebaSmrg /* SrcAtop */ 447f29dbc25Smrg { 448f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_DEST}, { 449f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 45004007ebaSmrg /* SrcAtopReverse */ 451f29dbc25Smrg { 452f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 453f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, 45404007ebaSmrg /* Xor */ 455f29dbc25Smrg { 456f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 457f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 45804007ebaSmrg /* PictOpAdd */ 459f29dbc25Smrg { 460f29dbc25Smrg CIMGP_A_PLUS_BETA_B, CIMGP_CONSTANT_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 461f29dbc25Smrg } 462f29dbc25Smrg}; 463f29dbc25Smrg 46404007ebaSmrg#ifndef ARRAY_SIZE 465f29dbc25Smrg#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a)))) 46604007ebaSmrg#endif 467f29dbc25Smrg 468f29dbc25Smrgstatic const struct exa_format_t * 469f29dbc25Smrglx_get_format(PicturePtr p) 470f29dbc25Smrg{ 471f29dbc25Smrg int i; 472f29dbc25Smrg unsigned int format = p->format; 473f29dbc25Smrg 474170d5fdcSmrg for (i = 0; i < ARRAY_SIZE(lx_exa_formats); i++) 47504007ebaSmrg if (lx_exa_formats[i].exa == format) 47604007ebaSmrg return (&lx_exa_formats[i]); 477f29dbc25Smrg 478f29dbc25Smrg return NULL; 479f29dbc25Smrg} 480f29dbc25Smrg 481f29dbc25Smrgstatic Bool 482f29dbc25Smrglx_process_transform(PicturePtr pSrc) 483f29dbc25Smrg{ 484f29dbc25Smrg PictTransformPtr t = pSrc->transform; 485f29dbc25Smrg xFixed c0 = t->matrix[0][0]; 486f29dbc25Smrg xFixed s0 = t->matrix[0][1]; 487f29dbc25Smrg xFixed s1 = t->matrix[1][0]; 488f29dbc25Smrg xFixed c1 = t->matrix[1][1]; 489f29dbc25Smrg 490f29dbc25Smrg /* If the transform doesn't have any rotation 491f29dbc25Smrg * or scaling components, then just grab the 492f29dbc25Smrg * translate coordinates */ 493f29dbc25Smrg 494f29dbc25Smrg if (t->matrix[0][0] == 0 && 49504007ebaSmrg t->matrix[0][1] == 0 && t->matrix[1][0] == 0 && t->matrix[1][1] == 0) { 49604007ebaSmrg exaScratch.transform = pSrc->transform; 49704007ebaSmrg return TRUE; 498f29dbc25Smrg } 499f29dbc25Smrg 500f29dbc25Smrg /* Otherwise, see if this is a simple 501f29dbc25Smrg * rotate transform - if it isn't, then 502f29dbc25Smrg * we have to punt back to software */ 503f29dbc25Smrg 504f29dbc25Smrg if (t->matrix[2][2] != F(1)) 50504007ebaSmrg return FALSE; 506f29dbc25Smrg 507f29dbc25Smrg /* The rotate matrix looks like this: 508f29dbc25Smrg * [ cos X -sin x 509f29dbc25Smrg * sin X cos X ] 510f29dbc25Smrg * 511f29dbc25Smrg * Where X is the angle. We do a simple 512f29dbc25Smrg * check first - if [0,0] != [1,1], then 513f29dbc25Smrg * scaling was specified too, and we can 514f29dbc25Smrg * bail, and if [0,1] != -[1,1] then this 515f29dbc25Smrg * isn't scaling that we can handle. 516f29dbc25Smrg */ 517f29dbc25Smrg 518f29dbc25Smrg if ((c0 != c1) || (s0 != -s1)) 51904007ebaSmrg return FALSE; 520f29dbc25Smrg 521f29dbc25Smrg /* Now, figure out what angle we want - we 522f29dbc25Smrg * can only accelerate right angle rotations, 523f29dbc25Smrg * so this turns into an easy set of if statements */ 524f29dbc25Smrg 525f29dbc25Smrg if (c0 == F(1) && s1 == F(0)) 52604007ebaSmrg exaScratch.rotate = RR_Rotate_0; 527f29dbc25Smrg else if (c0 == F(0) && s1 == F(1)) 52804007ebaSmrg exaScratch.rotate = RR_Rotate_90; 529f29dbc25Smrg else if (c0 == F(-1) && s1 == F(0)) 53004007ebaSmrg exaScratch.rotate = RR_Rotate_180; 531f29dbc25Smrg else if (c0 == F(0) && s1 == F(-1)) 53204007ebaSmrg exaScratch.rotate = RR_Rotate_270; 533f29dbc25Smrg else 53404007ebaSmrg return FALSE; 535f29dbc25Smrg 536f29dbc25Smrg exaScratch.transform = pSrc->transform; 537f29dbc25Smrg 538f29dbc25Smrg return TRUE; 539f29dbc25Smrg} 540f29dbc25Smrg 541f29dbc25Smrgstatic Bool 542f29dbc25Smrglx_check_composite(int op, PicturePtr pSrc, PicturePtr pMsk, PicturePtr pDst) 543f29dbc25Smrg{ 544f29dbc25Smrg GeodeRec *pGeode = GEODEPTR_FROM_PICTURE(pDst); 545170d5fdcSmrg const struct exa_format_t *srcFmt, *dstFmt; 546f29dbc25Smrg 547f29dbc25Smrg if (op > PictOpAdd) 54804007ebaSmrg GEODE_FALLBACK(("Operation %d is not supported\n", op)); 54904007ebaSmrg 55004007ebaSmrg /* XXX - don't know if we can do any hwaccel on solid fills or gradient types in generic cases */ 55104007ebaSmrg if (pMsk && pMsk->pSourcePict) 55204007ebaSmrg GEODE_FALLBACK(("%s are not supported as a mask\n", 55304007ebaSmrg pMsk->pSourcePict->type == 55404007ebaSmrg SourcePictTypeSolidFill ? "Solid pictures" : 55504007ebaSmrg "Gradients")); 55604007ebaSmrg 55704007ebaSmrg if (pSrc->pSourcePict && pSrc->pSourcePict->type != SourcePictTypeSolidFill) 55804007ebaSmrg GEODE_FALLBACK(("Gradients are not supported as the source\n")); 55904007ebaSmrg 56004007ebaSmrg if (pMsk && op == PictOpAdd) 56104007ebaSmrg GEODE_FALLBACK(("PictOpAdd with mask is not supported\n")); 562f29dbc25Smrg 563170d5fdcSmrg /* FIXME: Meet this conditions from the debug for PictOpAdd. 564170d5fdcSmrg * Any Other possibilities? Add a judge for the future supplement */ 565170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_a8r8g8b8 && 56604007ebaSmrg pDst->format == PICT_a8) 56704007ebaSmrg return TRUE; 568170d5fdcSmrg 569170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_x8r8g8b8 && 57004007ebaSmrg pDst->format == PICT_a8) 57104007ebaSmrg return TRUE; 572170d5fdcSmrg 573170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_r5g6b5 && 57404007ebaSmrg pDst->format == PICT_a8) 57504007ebaSmrg return TRUE; 576170d5fdcSmrg 577f29dbc25Smrg if (usesPasses(op)) { 57804007ebaSmrg /* FIXME: Slightly misleading fallback msg when !pMsk */ 57904007ebaSmrg if (pGeode->exaBfrOffset == 0 || !pMsk) 58004007ebaSmrg GEODE_FALLBACK(("Multipass operation requires off-screen buffer\n")); 581f29dbc25Smrg } 582f29dbc25Smrg 583f29dbc25Smrg /* Check that the filter matches what we support */ 584f29dbc25Smrg 585f29dbc25Smrg switch (pSrc->filter) { 586f29dbc25Smrg case PictFilterNearest: 587f29dbc25Smrg case PictFilterFast: 588f29dbc25Smrg case PictFilterGood: 589f29dbc25Smrg case PictFilterBest: 59004007ebaSmrg break; 591f29dbc25Smrg 592f29dbc25Smrg default: 59304007ebaSmrg GEODE_FALLBACK(("Bilinear or convolution filters are not supported\n")); 594f29dbc25Smrg } 595f29dbc25Smrg 596f29dbc25Smrg if (pMsk && pMsk->transform) 59704007ebaSmrg GEODE_FALLBACK(("Mask transforms are not supported\n")); 598170d5fdcSmrg 599f29dbc25Smrg /* Keep an eye out for source rotation transforms - those we can 600f29dbc25Smrg * do something about */ 601f29dbc25Smrg 602f29dbc25Smrg exaScratch.rotate = RR_Rotate_0; 603f29dbc25Smrg exaScratch.transform = NULL; 604f29dbc25Smrg 605f29dbc25Smrg if (pSrc->transform && !lx_process_transform(pSrc)) 60604007ebaSmrg GEODE_FALLBACK(("Transform operation is non-trivial\n")); 607f29dbc25Smrg 608f29dbc25Smrg /* XXX - I don't understand PICT_a8 enough - so I'm punting */ 609170d5fdcSmrg if ((op != PictOpAdd) && (pSrc->format == PICT_a8 || 61004007ebaSmrg pDst->format == PICT_a8)) 61104007ebaSmrg GEODE_FALLBACK(("PICT_a8 as src or dst format is unsupported\n")); 612f29dbc25Smrg 613f29dbc25Smrg if (pMsk && op != PictOpClear) { 61404007ebaSmrg struct blend_ops_t *opPtr = &lx_alpha_ops[op * 2]; 61504007ebaSmrg int direction = (opPtr->channel == CIMGP_CHANNEL_A_SOURCE) ? 0 : 1; 61604007ebaSmrg 61704007ebaSmrg /* Direction 0 indicates src->dst, 1 indicates dst->src */ 61804007ebaSmrg if (((direction == 0) && 61904007ebaSmrg (pSrc->pDrawable && pSrc->pDrawable->bitsPerPixel < 16)) || 62004007ebaSmrg ((direction == 1) && (pDst->pDrawable->bitsPerPixel < 16))) { 62104007ebaSmrg ErrorF("Mask blending unsupported with <16bpp\n"); 62204007ebaSmrg return FALSE; 62304007ebaSmrg } 62404007ebaSmrg if (pMsk->format != PICT_a8 && pMsk->format != PICT_a4) 62504007ebaSmrg GEODE_FALLBACK(("Masks can be only done with a 8bpp or 4bpp depth\n")); 62604007ebaSmrg 62704007ebaSmrg /* The pSrc should be 1x1 pixel if the pMsk is not zero */ 62804007ebaSmrg if (pSrc->pDrawable && 62904007ebaSmrg (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)) 63004007ebaSmrg GEODE_FALLBACK(("pSrc should be 1x1 pixel if pMsk is not zero\n")); 63104007ebaSmrg /* FIXME: In lx_prepare_composite, there are no variables to record the 63204007ebaSmrg * one pixel source's width and height when the mask is not zero. 63304007ebaSmrg * That will lead to bigger region to render instead of one pixel in lx 63404007ebaSmrg * _do_composite, so we should fallback currently to avoid this */ 63504007ebaSmrg /* Not an issue for solid pictures, because we'll treat it as 1x1R too */ 63604007ebaSmrg if (!pSrc->repeat && 63704007ebaSmrg !(pSrc->pSourcePict && 63804007ebaSmrg pSrc->pSourcePict->type == SourcePictTypeSolidFill)) { 63904007ebaSmrg GEODE_FALLBACK(("FIXME: unzero mask might lead to bigger rendering region than 1x1 pixels\n")); 64004007ebaSmrg } 64104007ebaSmrg } 64204007ebaSmrg else { 64304007ebaSmrg if (pSrc->pSourcePict) 64404007ebaSmrg GEODE_FALLBACK(("Solid source pictures without a mask are not supported\n")); 645f29dbc25Smrg } 646f29dbc25Smrg 647f29dbc25Smrg /* Get the formats for the source and destination */ 648f29dbc25Smrg 64904007ebaSmrg if ((srcFmt = lx_get_format(pSrc)) == NULL) 65004007ebaSmrg GEODE_FALLBACK(("Unsupported source format %x\n", pSrc->format)); 651f29dbc25Smrg 65204007ebaSmrg if ((dstFmt = lx_get_format(pDst)) == NULL) 65304007ebaSmrg GEODE_FALLBACK(("Unsupported destination format %x\n", pDst->format)); 654f29dbc25Smrg 655f29dbc25Smrg /* Make sure operations that need alpha bits have them */ 656f29dbc25Smrg /* If a mask is enabled, the alpha will come from there */ 657f29dbc25Smrg 658f29dbc25Smrg if (!pMsk && (!srcFmt->alphabits && usesSrcAlpha(op))) 65904007ebaSmrg GEODE_FALLBACK(("Operation requires src alpha, but alphabits is unset\n")); 660f29dbc25Smrg 661f29dbc25Smrg if (!pMsk && (!dstFmt->alphabits && usesDstAlpha(op))) 66204007ebaSmrg GEODE_FALLBACK(("Operation requires dst alpha, but alphabits is unset\n")); 663f29dbc25Smrg 66404007ebaSmrg /* FIXME: See a way around this! */ 665f29dbc25Smrg if (srcFmt->alphabits == 0 && dstFmt->alphabits != 0) 66604007ebaSmrg GEODE_FALLBACK(("src_alphabits=0, dst_alphabits!=0\n")); 667f29dbc25Smrg 668f29dbc25Smrg /* If this is a rotate operation, then make sure the src and dst 669f29dbc25Smrg * formats are the same */ 670f29dbc25Smrg if (exaScratch.rotate != RR_Rotate_0 && srcFmt != dstFmt) { 67104007ebaSmrg ErrorF("EXA: Unable to rotate and convert formats at the same time\n"); 67204007ebaSmrg return FALSE; 673f29dbc25Smrg } 674170d5fdcSmrg return TRUE; 675170d5fdcSmrg} 676170d5fdcSmrg 677170d5fdcSmrgstatic Bool 678170d5fdcSmrglx_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMsk, 67904007ebaSmrg PicturePtr pDst, PixmapPtr pxSrc, PixmapPtr pxMsk, 68004007ebaSmrg PixmapPtr pxDst) 681170d5fdcSmrg{ 682170d5fdcSmrg GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); 683170d5fdcSmrg const struct exa_format_t *srcFmt, *dstFmt; 684170d5fdcSmrg 685170d5fdcSmrg /* Get the formats for the source and destination */ 686170d5fdcSmrg 687170d5fdcSmrg srcFmt = lx_get_format(pSrc); 688170d5fdcSmrg dstFmt = lx_get_format(pDst); 689f29dbc25Smrg 690f29dbc25Smrg /* Set up the scratch buffer with the information we need */ 691f29dbc25Smrg 69204007ebaSmrg exaScratch.srcFormat = (struct exa_format_t *) srcFmt; 69304007ebaSmrg exaScratch.dstFormat = (struct exa_format_t *) dstFmt; 694f29dbc25Smrg exaScratch.op = op; 695f29dbc25Smrg exaScratch.repeat = pSrc->repeat; 696f29dbc25Smrg exaScratch.bufferOffset = pGeode->exaBfrOffset; 697f29dbc25Smrg 698f29dbc25Smrg if (pMsk && op != PictOpClear) { 69904007ebaSmrg /* Get the source color */ 70004007ebaSmrg if (pSrc->pSourcePict) { 70104007ebaSmrg exaScratch.srcColor = pSrc->pSourcePict->solidFill.color; 70204007ebaSmrg } 70304007ebaSmrg else { 70404007ebaSmrg /* If the op is PictOpOver(or PictOpOutReverse, PictOpInReverse, 70504007ebaSmrg * PictOpIn, PictOpOut, PictOpOverReverse), we should get the 70604007ebaSmrg * ARGB32 source format */ 70704007ebaSmrg 70804007ebaSmrg if ((op == PictOpOver || op == PictOpOutReverse || op == 70904007ebaSmrg PictOpInReverse || op == PictOpIn || op == PictOpOut || 71004007ebaSmrg op == PictOpOverReverse) && (srcFmt->alphabits != 0)) 71104007ebaSmrg exaScratch.srcColor = exaGetPixmapFirstPixel(pxSrc); 71204007ebaSmrg else if ((op == PictOpOver || op == PictOpOutReverse || op == 71304007ebaSmrg PictOpInReverse || op == PictOpIn || op == PictOpOut || 71404007ebaSmrg op == PictOpOverReverse) && (srcFmt->alphabits == 0)) 71504007ebaSmrg exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, 71604007ebaSmrg PICT_a8r8g8b8); 71704007ebaSmrg else 71804007ebaSmrg exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, 71904007ebaSmrg pDst->format); 72004007ebaSmrg } 72104007ebaSmrg 72204007ebaSmrg /* Save off the info we need (reuse the source values to save space) */ 72304007ebaSmrg exaScratch.type = COMP_TYPE_MASK; 72404007ebaSmrg exaScratch.maskrepeat = pMsk->repeat; 72504007ebaSmrg 72604007ebaSmrg exaScratch.srcOffset = exaGetPixmapOffset(pxMsk); 72704007ebaSmrg exaScratch.srcPitch = exaGetPixmapPitch(pxMsk); 72804007ebaSmrg exaScratch.srcBpp = (pxMsk->drawable.bitsPerPixel + 7) / 8; 72904007ebaSmrg 73004007ebaSmrg exaScratch.srcWidth = pMsk->pDrawable->width; 73104007ebaSmrg exaScratch.srcHeight = pMsk->pDrawable->height; 73204007ebaSmrg 73304007ebaSmrg /* Flag to indicate if this a 8BPP or a 4BPP mask */ 73404007ebaSmrg exaScratch.fourBpp = (pxMsk->drawable.bitsPerPixel == 4) ? 1 : 0; 73504007ebaSmrg } 73604007ebaSmrg else { 73704007ebaSmrg if (usesPasses(op)) 73804007ebaSmrg exaScratch.type = COMP_TYPE_TWOPASS; 73904007ebaSmrg else if (exaScratch.rotate != RR_Rotate_0) 74004007ebaSmrg exaScratch.type = COMP_TYPE_ROTATE; 74104007ebaSmrg else 74204007ebaSmrg exaScratch.type = COMP_TYPE_ONEPASS; 74304007ebaSmrg 74404007ebaSmrg exaScratch.srcOffset = exaGetPixmapOffset(pxSrc); 74504007ebaSmrg exaScratch.srcPitch = exaGetPixmapPitch(pxSrc); 74604007ebaSmrg exaScratch.srcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; 74704007ebaSmrg 74804007ebaSmrg exaScratch.srcWidth = pSrc->pDrawable->width; 74904007ebaSmrg exaScratch.srcHeight = pSrc->pDrawable->height; 750f29dbc25Smrg } 751f29dbc25Smrg 752f29dbc25Smrg return TRUE; 753f29dbc25Smrg} 754f29dbc25Smrg 755f29dbc25Smrgstatic int 756f29dbc25Smrglx_get_bpp_from_format(int format) 757f29dbc25Smrg{ 758f29dbc25Smrg 759f29dbc25Smrg switch (format) { 760f29dbc25Smrg case CIMGP_SOURCE_FMT_8_8_8_8: 761f29dbc25Smrg case CIMGP_SOURCE_FMT_32BPP_BGR: 76204007ebaSmrg return 32; 763f29dbc25Smrg 764f29dbc25Smrg case CIMGP_SOURCE_FMT_4_4_4_4: 76504007ebaSmrg return 12; 766f29dbc25Smrg 767f29dbc25Smrg case CIMGP_SOURCE_FMT_0_5_6_5: 768f29dbc25Smrg case CIMGP_SOURCE_FMT_16BPP_BGR: 76904007ebaSmrg return 16; 770f29dbc25Smrg 771f29dbc25Smrg case CIMGP_SOURCE_FMT_1_5_5_5: 772f29dbc25Smrg case CIMGP_SOURCE_FMT_15BPP_BGR: 77304007ebaSmrg return 15; 774f29dbc25Smrg 775f29dbc25Smrg case CIMGP_SOURCE_FMT_3_3_2: 77604007ebaSmrg return 8; 777f29dbc25Smrg } 778f29dbc25Smrg 779f29dbc25Smrg return 0; 780f29dbc25Smrg} 781f29dbc25Smrg 782f29dbc25Smrg/* BGR needs to be set in the source for it to take - so adjust the source 783f29dbc25Smrg * to enable BGR if the two formats are different, and disable it if they 784f29dbc25Smrg * are the same 785f29dbc25Smrg */ 786f29dbc25Smrg 787f29dbc25Smrgstatic void 788f29dbc25Smrglx_set_source_format(int srcFormat, int dstFormat) 789f29dbc25Smrg{ 790f29dbc25Smrg if (!(srcFormat & 0x10) && (dstFormat & 0x10)) 79104007ebaSmrg gp_set_source_format(srcFormat | 0x10); 792f29dbc25Smrg else if ((srcFormat & 0x10) && (dstFormat & 0x10)) 79304007ebaSmrg gp_set_source_format(srcFormat & ~0x10); 794f29dbc25Smrg else 79504007ebaSmrg gp_set_source_format(srcFormat); 796f29dbc25Smrg} 797f29dbc25Smrg 798f29dbc25Smrg/* If we are converting colors and we need the channel A alpha, 799f29dbc25Smrg * then use a special alpha type that preserves the alpha before 800f29dbc25Smrg * converting the format 801f29dbc25Smrg */ 802f29dbc25Smrg 803f29dbc25Smrgstatic inline int 804f29dbc25Smrgget_op_type(struct exa_format_t *src, struct exa_format_t *dst, int type) 805f29dbc25Smrg{ 806f29dbc25Smrg return (type == CIMGP_CHANNEL_A_ALPHA && 80704007ebaSmrg src->alphabits != dst->alphabits) ? CIMGP_CONVERTED_ALPHA : type; 808f29dbc25Smrg} 809f29dbc25Smrg 810f29dbc25Smrg/* Note - this is the preferred onepass method. The other will remain 811f29dbc25Smrg * ifdefed out until such time that we are sure its not needed 812f29dbc25Smrg */ 813f29dbc25Smrg 814170d5fdcSmrg#define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \ 815170d5fdcSmrg (exaGetPixmapPitch((px)) * (y)) + \ 816170d5fdcSmrg ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) ) 817170d5fdcSmrg 818170d5fdcSmrg#define GetSrcOffset(_x, _y) (exaScratch.srcOffset + ((_y) * exaScratch.srcPitch) + \ 819170d5fdcSmrg ((_x) * exaScratch.srcBpp)) 820170d5fdcSmrg 821170d5fdcSmrgstatic void 822170d5fdcSmrglx_composite_onepass_add_a8(PixmapPtr pxDst, unsigned long dstOffset, 82304007ebaSmrg unsigned long srcOffset, int width, int height, 82404007ebaSmrg int opX, int opY, int srcX, int srcY) 825170d5fdcSmrg{ 826170d5fdcSmrg struct blend_ops_t *opPtr; 827170d5fdcSmrg int apply, type; 828170d5fdcSmrg int optempX, optempY; 829170d5fdcSmrg int i, j; 830170d5fdcSmrg unsigned long pixmapOffset, pixmapPitch, calBitsPixel; 831170d5fdcSmrg 832170d5fdcSmrg pixmapOffset = exaGetPixmapOffset(pxDst); 833170d5fdcSmrg pixmapPitch = exaGetPixmapPitch(pxDst); 834170d5fdcSmrg calBitsPixel = (pxDst->drawable.bitsPerPixel + 7) / 8; 835170d5fdcSmrg 836170d5fdcSmrg /* Keep this GP idle judge here. Otherwise the SW method has chance to 837170d5fdcSmrg * conflict with the HW rendering method */ 838170d5fdcSmrg gp_wait_until_idle(); 839170d5fdcSmrg 840170d5fdcSmrg if (opX % 4 == 0 && srcX % 4 == 0) { 84104007ebaSmrg /* HW acceleration */ 84204007ebaSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 84304007ebaSmrg apply = CIMGP_APPLY_BLEND_TO_ALL; 84404007ebaSmrg gp_declare_blt(0); 84504007ebaSmrg gp_set_bpp(32); 84604007ebaSmrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 84704007ebaSmrg gp_set_source_format(8); 84804007ebaSmrg type = opPtr->type; 84904007ebaSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 85004007ebaSmrg 0); 85104007ebaSmrg gp_screen_to_screen_convert(dstOffset, srcOffset, width / 4, height, 0); 85204007ebaSmrg /* Calculate the pixels in the tail of each line */ 85304007ebaSmrg for (j = srcY; j < srcY + height; j++) 85404007ebaSmrg for (i = srcX + (width / 4) * 4; i < srcX + width; i++) { 85504007ebaSmrg srcOffset = GetSrcOffset(i, j); 85604007ebaSmrg optempX = opX + i - srcX; 85704007ebaSmrg optempY = opY + j - srcY; 85804007ebaSmrg dstOffset = pixmapOffset + pixmapPitch * optempY + 85904007ebaSmrg calBitsPixel * optempX; 86004007ebaSmrg *(cim_fb_ptr + dstOffset) = (*(cim_fb_ptr + srcOffset) 86104007ebaSmrg + *(cim_fb_ptr + dstOffset) <= 86204007ebaSmrg 0xff) ? *(cim_fb_ptr + srcOffset) + 86304007ebaSmrg *(cim_fb_ptr + dstOffset) : 0xff; 86404007ebaSmrg } 86504007ebaSmrg } 86604007ebaSmrg else { 86704007ebaSmrg for (j = srcY; j < srcY + height; j++) 86804007ebaSmrg for (i = srcX; i < srcX + width; i++) { 86904007ebaSmrg srcOffset = GetSrcOffset(i, j); 87004007ebaSmrg optempX = opX + i - srcX; 87104007ebaSmrg optempY = opY + j - srcY; 87204007ebaSmrg dstOffset = pixmapOffset + pixmapPitch * optempY + 87304007ebaSmrg calBitsPixel * optempX; 87404007ebaSmrg *(cim_fb_ptr + dstOffset) = (*(cim_fb_ptr + srcOffset) + 87504007ebaSmrg *(cim_fb_ptr + dstOffset) <= 87604007ebaSmrg 0xff) ? *(cim_fb_ptr + srcOffset) + 87704007ebaSmrg *(cim_fb_ptr + dstOffset) : 0xff; 87804007ebaSmrg } 879170d5fdcSmrg } 880170d5fdcSmrg} 881170d5fdcSmrg 882f29dbc25Smrgstatic void 883f29dbc25Smrglx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset, 88404007ebaSmrg unsigned long srcOffset, int width, int height) 885f29dbc25Smrg{ 886f29dbc25Smrg struct blend_ops_t *opPtr; 887f29dbc25Smrg int apply, type; 888f29dbc25Smrg 889f29dbc25Smrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 890f29dbc25Smrg 891f29dbc25Smrg apply = (exaScratch.dstFormat->alphabits != 0 && 89204007ebaSmrg exaScratch.srcFormat->alphabits != 0) ? 89304007ebaSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 894f29dbc25Smrg 895f29dbc25Smrg gp_declare_blt(0); 896f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 897f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 898f29dbc25Smrg 89904007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt); 900f29dbc25Smrg 90104007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type); 902f29dbc25Smrg 903f29dbc25Smrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 904f29dbc25Smrg 905f29dbc25Smrg gp_screen_to_screen_convert(dstOffset, srcOffset, width, height, 0); 906f29dbc25Smrg} 907f29dbc25Smrg 908170d5fdcSmrgstatic void 909170d5fdcSmrglx_composite_all_black(unsigned long srcOffset, int width, int height) 910170d5fdcSmrg{ 911170d5fdcSmrg struct blend_ops_t *opPtr; 912170d5fdcSmrg int apply, type; 913170d5fdcSmrg 914170d5fdcSmrg opPtr = &lx_alpha_ops[0]; 915170d5fdcSmrg apply = (exaScratch.srcFormat->alphabits != 0) ? 91604007ebaSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 917170d5fdcSmrg gp_declare_blt(0); 918170d5fdcSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.srcFormat->fmt)); 919170d5fdcSmrg gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch); 92004007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.srcFormat->fmt); 92104007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.srcFormat, opPtr->type); 922170d5fdcSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 923170d5fdcSmrg gp_screen_to_screen_convert(srcOffset, srcOffset, width, height, 0); 924170d5fdcSmrg 925170d5fdcSmrg} 926170d5fdcSmrg 927170d5fdcSmrgstatic void 928170d5fdcSmrglx_composite_onepass_special(PixmapPtr pxDst, int width, int height, int opX, 92904007ebaSmrg int opY, int srcX, int srcY) 930170d5fdcSmrg{ 931170d5fdcSmrg struct blend_ops_t *opPtr; 932170d5fdcSmrg int apply, type; 933170d5fdcSmrg int opWidth, opHeight; 934170d5fdcSmrg int optempX, optempY; 935170d5fdcSmrg unsigned int dstOffset, srcOffset = 0; 936170d5fdcSmrg 937170d5fdcSmrg optempX = opX; 938170d5fdcSmrg optempY = opY; 939170d5fdcSmrg 940170d5fdcSmrg /* Make sure srcX and srcY are in source region */ 94104007ebaSmrg srcX = ((srcX % (int) exaScratch.srcWidth) + (int) exaScratch.srcWidth) 94204007ebaSmrg % (int) exaScratch.srcWidth; 94304007ebaSmrg srcY = ((srcY % (int) exaScratch.srcHeight) + (int) exaScratch.srcHeight) 94404007ebaSmrg % (int) exaScratch.srcHeight; 945170d5fdcSmrg 946170d5fdcSmrg opWidth = exaScratch.srcWidth - srcX; 94704007ebaSmrg opHeight = exaScratch.srcHeight - srcY; 948170d5fdcSmrg 949170d5fdcSmrg srcOffset = GetSrcOffset(srcX, srcY); 950170d5fdcSmrg 951170d5fdcSmrg if (width < opWidth) 95204007ebaSmrg opWidth = width; 953170d5fdcSmrg if (height < opHeight) 95404007ebaSmrg opHeight = height; 955170d5fdcSmrg 956170d5fdcSmrg while (1) { 95704007ebaSmrg gp_wait_until_idle(); 95804007ebaSmrg dstOffset = GetPixmapOffset(pxDst, optempX, optempY); 95904007ebaSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 96004007ebaSmrg apply = (exaScratch.dstFormat->alphabits != 0 && 96104007ebaSmrg exaScratch.srcFormat->alphabits != 0) ? 96204007ebaSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 96304007ebaSmrg gp_declare_blt(0); 96404007ebaSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 96504007ebaSmrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 96604007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, 96704007ebaSmrg exaScratch.dstFormat->fmt); 96804007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, 96904007ebaSmrg opPtr->type); 97004007ebaSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, 97104007ebaSmrg apply, 0); 97204007ebaSmrg gp_screen_to_screen_convert(dstOffset, srcOffset, opWidth, opHeight, 0); 97304007ebaSmrg 97404007ebaSmrg optempX += opWidth; 97504007ebaSmrg if (optempX >= opX + width) { 97604007ebaSmrg optempX = opX; 97704007ebaSmrg optempY += opHeight; 97804007ebaSmrg if (optempY >= opY + height) 97904007ebaSmrg break; 98004007ebaSmrg } 98104007ebaSmrg if (optempX == opX) { 98204007ebaSmrg srcOffset = GetSrcOffset(srcX, 0); 98304007ebaSmrg opWidth = ((opX + width) - optempX) > (exaScratch.srcWidth - srcX) 98404007ebaSmrg ? (exaScratch.srcWidth - srcX) : ((opX + width) - optempX); 98504007ebaSmrg opHeight = ((opY + height) - optempY) > exaScratch.srcHeight 98604007ebaSmrg ? exaScratch.srcHeight : ((opY + height) - optempY); 98704007ebaSmrg } 98804007ebaSmrg else if (optempY == opY) { 98904007ebaSmrg srcOffset = GetSrcOffset(0, srcY); 99004007ebaSmrg opWidth = ((opX + width) - optempX) > exaScratch.srcWidth 99104007ebaSmrg ? exaScratch.srcWidth : ((opX + width) - optempX); 99204007ebaSmrg opHeight = ((opY + height) - optempY) > (exaScratch.srcHeight - 99304007ebaSmrg srcY) 99404007ebaSmrg ? (exaScratch.srcHeight - srcY) : ((opY + height) 99504007ebaSmrg - optempY); 99604007ebaSmrg } 99704007ebaSmrg else { 99804007ebaSmrg srcOffset = GetSrcOffset(0, 0); 99904007ebaSmrg opWidth = ((opX + width) - optempX) > exaScratch.srcWidth 100004007ebaSmrg ? exaScratch.srcWidth : ((opX + width) - optempX); 100104007ebaSmrg opHeight = ((opY + height) - optempY) > exaScratch.srcHeight 100204007ebaSmrg ? exaScratch.srcHeight : ((opY + height) - optempY); 100304007ebaSmrg } 1004170d5fdcSmrg } 1005170d5fdcSmrg} 1006170d5fdcSmrg 1007f29dbc25Smrg/* This function handles the multipass blend functions */ 1008f29dbc25Smrg 1009f29dbc25Smrgstatic void 1010f29dbc25Smrglx_composite_multipass(PixmapPtr pxDst, unsigned long dstOffset, 101104007ebaSmrg unsigned long srcOffset, int width, int height) 1012f29dbc25Smrg{ 1013f29dbc25Smrg struct blend_ops_t *opPtr; 1014f29dbc25Smrg int sbpp = lx_get_bpp_from_format(exaScratch.srcFormat->fmt); 1015f29dbc25Smrg int apply, type; 1016f29dbc25Smrg 1017f29dbc25Smrg /* Wait until the GP is idle - this will ensure that the scratch buffer 1018f29dbc25Smrg * isn't occupied */ 1019f29dbc25Smrg 1020f29dbc25Smrg gp_wait_until_idle(); 1021f29dbc25Smrg 1022f29dbc25Smrg /* Copy the destination to the scratch buffer, and convert it to the 1023f29dbc25Smrg * source format */ 1024f29dbc25Smrg 1025f29dbc25Smrg gp_declare_blt(0); 1026f29dbc25Smrg 1027f29dbc25Smrg gp_set_bpp(sbpp); 1028f29dbc25Smrg gp_set_source_format(exaScratch.dstFormat->fmt); 1029f29dbc25Smrg gp_set_raster_operation(0xCC); 1030f29dbc25Smrg gp_set_strides(exaScratch.srcPitch, exaGetPixmapPitch(pxDst)); 1031f29dbc25Smrg gp_screen_to_screen_convert(exaScratch.bufferOffset, dstOffset, 103204007ebaSmrg width, height, 0); 1033f29dbc25Smrg 1034f29dbc25Smrg /* Do the first blend from the source to the scratch buffer */ 1035f29dbc25Smrg 1036f29dbc25Smrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1037f29dbc25Smrg gp_set_bpp(sbpp); 1038f29dbc25Smrg gp_set_source_format(exaScratch.srcFormat->fmt); 1039f29dbc25Smrg gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch); 1040f29dbc25Smrg 1041f29dbc25Smrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1042f29dbc25Smrg 1043f29dbc25Smrg apply = (exaScratch.srcFormat->alphabits == 0) ? 104404007ebaSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1045f29dbc25Smrg 1046f29dbc25Smrg /* If we're destroying the source alpha bits, then make sure we 1047f29dbc25Smrg * use the alpha before the color conversion 1048f29dbc25Smrg */ 1049f29dbc25Smrg 1050f29dbc25Smrg gp_screen_to_screen_blt(exaScratch.bufferOffset, srcOffset, width, height, 105104007ebaSmrg 0); 1052f29dbc25Smrg 1053f29dbc25Smrg /* Finally, do the second blend back to the destination */ 1054f29dbc25Smrg 1055f29dbc25Smrg opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; 1056f29dbc25Smrg 1057f29dbc25Smrg apply = (exaScratch.dstFormat->alphabits == 0) ? 105804007ebaSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1059f29dbc25Smrg 1060f29dbc25Smrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1061f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1062f29dbc25Smrg 106304007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt); 1064f29dbc25Smrg 106504007ebaSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type); 1066f29dbc25Smrg 1067f29dbc25Smrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 1068f29dbc25Smrg 1069f29dbc25Smrg gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, 107004007ebaSmrg width, height, 0); 1071f29dbc25Smrg} 1072f29dbc25Smrg 1073f29dbc25Smrgstatic void 1074f29dbc25Smrglx_composite_rotate(PixmapPtr pxDst, unsigned long dstOffset, 107504007ebaSmrg unsigned int srcOffset, int width, int height) 1076f29dbc25Smrg{ 1077f29dbc25Smrg int degrees = 0; 1078f29dbc25Smrg 1079f29dbc25Smrg gp_declare_blt(0); 1080f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1081f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 1082f29dbc25Smrg 108304007ebaSmrg lx_set_source_format(exaScratch.srcFormat->fmt, exaScratch.dstFormat->fmt); 1084f29dbc25Smrg 1085f29dbc25Smrg gp_set_raster_operation(0xCC); 1086f29dbc25Smrg 1087f29dbc25Smrg /* RandR rotation is counter-clockwise, our rotation 1088f29dbc25Smrg * is clockwise, so adjust the numbers accordingly */ 1089f29dbc25Smrg 1090f29dbc25Smrg switch (exaScratch.rotate) { 1091f29dbc25Smrg case RR_Rotate_90: 109204007ebaSmrg degrees = 270; 109304007ebaSmrg break; 1094f29dbc25Smrg case RR_Rotate_180: 109504007ebaSmrg degrees = 180; 109604007ebaSmrg break; 1097f29dbc25Smrg case RR_Rotate_270: 109804007ebaSmrg degrees = 90; 109904007ebaSmrg break; 1100f29dbc25Smrg } 1101f29dbc25Smrg 1102f29dbc25Smrg gp_rotate_blt(dstOffset, srcOffset, width, height, degrees); 1103f29dbc25Smrg} 1104f29dbc25Smrg 1105f29dbc25Smrgstatic void 1106f29dbc25Smrglx_do_composite_mask(PixmapPtr pxDst, unsigned long dstOffset, 110704007ebaSmrg unsigned int maskOffset, int width, int height) 1108f29dbc25Smrg{ 1109f29dbc25Smrg struct blend_ops_t *opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1110f29dbc25Smrg 1111f29dbc25Smrg gp_declare_blt(0); 1112f29dbc25Smrg 1113f29dbc25Smrg gp_set_source_format(exaScratch.srcFormat->fmt); 1114f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 1115f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1116f29dbc25Smrg gp_set_solid_source(exaScratch.srcColor); 1117f29dbc25Smrg 1118f29dbc25Smrg gp_blend_mask_blt(dstOffset, 0, width, height, maskOffset, 111904007ebaSmrg exaScratch.srcPitch, opPtr->operation, 112004007ebaSmrg exaScratch.fourBpp); 1121f29dbc25Smrg} 1122f29dbc25Smrg 1123170d5fdcSmrgstatic void 1124170d5fdcSmrglx_do_composite_mask_two_pass(PixmapPtr pxDst, unsigned long dstOffset, 112504007ebaSmrg unsigned int maskOffset, int width, int height, 112604007ebaSmrg int opX, int opY, xPointFixed srcPoint) 1127170d5fdcSmrg{ 1128170d5fdcSmrg int apply, type; 1129170d5fdcSmrg struct blend_ops_t *opPtr; 1130170d5fdcSmrg int opWidth, opHeight; 1131170d5fdcSmrg int opoverX, opoverY; 1132170d5fdcSmrg 1133170d5fdcSmrg opoverX = opX; 1134170d5fdcSmrg opoverY = opY; 1135170d5fdcSmrg 1136170d5fdcSmrg /* The rendering region should not be bigger than off-screen memory size 1137170d5fdcSmrg * which equals to DEFAULT_EXA_SCRATCH_BFRSZ. If that happens, we split 1138170d5fdcSmrg * the PictOpOver rendering region into several 256KB chunks. And because 1139170d5fdcSmrg * of the Pitch(stride) parameter, so we use maximun width of mask picture. 1140170d5fdcSmrg * that is to say it is a scanline rendering process */ 1141170d5fdcSmrg if (width * height * 4 > DEFAULT_EXA_SCRATCH_BFRSZ) { 114204007ebaSmrg opWidth = width; 114304007ebaSmrg opHeight = DEFAULT_EXA_SCRATCH_BFRSZ / (width * 4); 114404007ebaSmrg } 114504007ebaSmrg else { 114604007ebaSmrg opWidth = width; 114704007ebaSmrg opHeight = height; 1148170d5fdcSmrg } 1149f29dbc25Smrg 1150170d5fdcSmrg while (1) { 1151170d5fdcSmrg 115204007ebaSmrg /* Wait until the GP is idle - this will ensure that the scratch buffer 115304007ebaSmrg * isn't occupied */ 115404007ebaSmrg 115504007ebaSmrg gp_wait_until_idle(); 115604007ebaSmrg 115704007ebaSmrg /* Copy the source to the scratch buffer, and do a src * mask raster 115804007ebaSmrg * operation */ 115904007ebaSmrg 116004007ebaSmrg gp_declare_blt(0); 116104007ebaSmrg opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; 116204007ebaSmrg gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); 116304007ebaSmrg gp_set_strides(opWidth * 4, exaScratch.srcPitch); 116404007ebaSmrg gp_set_bpp(lx_get_bpp_from_format(CIMGP_SOURCE_FMT_8_8_8_8)); 116504007ebaSmrg gp_set_solid_source(exaScratch.srcColor); 116604007ebaSmrg gp_blend_mask_blt(exaScratch.bufferOffset, 0, opWidth, opHeight, 116704007ebaSmrg maskOffset, exaScratch.srcPitch, opPtr->operation, 116804007ebaSmrg exaScratch.fourBpp); 116904007ebaSmrg 117004007ebaSmrg /* Do a relative operation(refer rendercheck ops.c), and copy the 117104007ebaSmrg * operation result to destination */ 117204007ebaSmrg 117304007ebaSmrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 117404007ebaSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 117504007ebaSmrg apply = (exaScratch.dstFormat->alphabits == 0) ? 117604007ebaSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 117704007ebaSmrg gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); 117804007ebaSmrg gp_set_strides(exaGetPixmapPitch(pxDst), opWidth * 4); 117904007ebaSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 118004007ebaSmrg type = CIMGP_CONVERTED_ALPHA; 118104007ebaSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, 118204007ebaSmrg apply, 0); 118304007ebaSmrg gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, 118404007ebaSmrg opWidth, opHeight, 0); 118504007ebaSmrg 118604007ebaSmrg if (width * height * 4 > DEFAULT_EXA_SCRATCH_BFRSZ) { 118704007ebaSmrg /* Finish the rendering */ 118804007ebaSmrg if (opoverY + opHeight == opY + height) 118904007ebaSmrg break; 119004007ebaSmrg /* Recalculate the Dest and Mask rendering start point */ 119104007ebaSmrg srcPoint.y = srcPoint.y + F(opHeight); 119204007ebaSmrg opoverY = opoverY + opHeight; 119304007ebaSmrg if (opoverY + opHeight > opY + height) 119404007ebaSmrg opHeight = opY + height - opoverY; 119504007ebaSmrg dstOffset = GetPixmapOffset(pxDst, opoverX, opoverY); 119604007ebaSmrg maskOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); 119704007ebaSmrg } 119804007ebaSmrg else 119904007ebaSmrg break; 1200170d5fdcSmrg } 1201170d5fdcSmrg} 1202f29dbc25Smrg 1203f29dbc25Smrgstatic void 1204f29dbc25SmrgtransformPoint(PictTransform * t, xPointFixed * point) 1205f29dbc25Smrg{ 1206f29dbc25Smrg PictVector v; 1207f29dbc25Smrg 1208f29dbc25Smrg v.vector[0] = point->x; 1209f29dbc25Smrg v.vector[1] = point->y; 1210f29dbc25Smrg v.vector[2] = xFixed1; 1211f29dbc25Smrg 1212f29dbc25Smrg if (t != NULL) 121304007ebaSmrg PictureTransformPoint(t, &v); 1214f29dbc25Smrg 1215f29dbc25Smrg point->x = v.vector[0]; 1216f29dbc25Smrg point->y = v.vector[1]; 1217f29dbc25Smrg} 1218f29dbc25Smrg 1219f29dbc25Smrgstatic void 1220f29dbc25Smrglx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX, 122104007ebaSmrg int maskY, int dstX, int dstY, int width, int height) 1222f29dbc25Smrg{ 1223f29dbc25Smrg unsigned int dstOffset, srcOffset = 0; 1224f29dbc25Smrg 1225f29dbc25Smrg xPointFixed srcPoint; 1226f29dbc25Smrg 1227f29dbc25Smrg int opX = dstX; 1228f29dbc25Smrg int opY = dstY; 1229f29dbc25Smrg int opWidth = width; 1230f29dbc25Smrg int opHeight = height; 1231f29dbc25Smrg 1232f29dbc25Smrg /* Transform the source coordinates */ 1233f29dbc25Smrg 1234f29dbc25Smrg if (exaScratch.type == COMP_TYPE_MASK) { 123504007ebaSmrg srcPoint.x = F(maskX); 123604007ebaSmrg srcPoint.y = F(maskY); 123704007ebaSmrg } 123804007ebaSmrg else { 123904007ebaSmrg srcPoint.x = F(srcX); 124004007ebaSmrg srcPoint.y = F(srcY); 1241f29dbc25Smrg } 1242f29dbc25Smrg 1243f29dbc25Smrg /* srcX, srcY point to the upper right side of the bounding box 1244f29dbc25Smrg * in the unrotated coordinate space. Depending on the orientation, 1245f29dbc25Smrg * we have to translate the coordinates to point to the origin of 1246f29dbc25Smrg * the rectangle in the source pixmap */ 1247f29dbc25Smrg 1248f29dbc25Smrg switch (exaScratch.rotate) { 1249f29dbc25Smrg case RR_Rotate_270: 125004007ebaSmrg srcPoint.x += F(width); 1251f29dbc25Smrg 125204007ebaSmrg opWidth = height; 125304007ebaSmrg opHeight = width; 125404007ebaSmrg break; 1255f29dbc25Smrg 1256f29dbc25Smrg case RR_Rotate_180: 125704007ebaSmrg srcPoint.x += F(width); 125804007ebaSmrg srcPoint.y += F(height); 1259f29dbc25Smrg 126004007ebaSmrg srcX += width; 126104007ebaSmrg srcY += height; 126204007ebaSmrg break; 1263f29dbc25Smrg 1264f29dbc25Smrg case RR_Rotate_90: 126504007ebaSmrg srcPoint.y += F(height); 1266f29dbc25Smrg 126704007ebaSmrg opWidth = height; 126804007ebaSmrg opHeight = width; 126904007ebaSmrg break; 1270f29dbc25Smrg } 1271f29dbc25Smrg 1272f29dbc25Smrg transformPoint(exaScratch.transform, &srcPoint); 1273f29dbc25Smrg 1274f29dbc25Smrg /* Adjust the point to fit into the pixmap */ 1275f29dbc25Smrg 1276f29dbc25Smrg if (I(srcPoint.x) < 0) { 127704007ebaSmrg opWidth += I(srcPoint.x); 127804007ebaSmrg srcPoint.x = F(0); 1279f29dbc25Smrg } 1280f29dbc25Smrg 1281f29dbc25Smrg if (I(srcPoint.y) < 0) { 128204007ebaSmrg opHeight += I(srcPoint.y); 128304007ebaSmrg srcPoint.y = F(0); 1284f29dbc25Smrg } 1285f29dbc25Smrg 1286170d5fdcSmrg /* Get the source point offset position */ 1287170d5fdcSmrg 1288f29dbc25Smrg srcOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); 1289f29dbc25Smrg 1290170d5fdcSmrg /* When mask exists, exaScratch.srcWidth and exaScratch.srcHeight are 1291170d5fdcSmrg * the source width and source height; Otherwise, they are mask width 1292170d5fdcSmrg * and mask height */ 1293170d5fdcSmrg /* exaScratch.repeat is the source repeat attribute 1294170d5fdcSmrg * exaScratch.maskrepeat is the mask repeat attribute */ 1295170d5fdcSmrg /* If type is COMP_TYPE_MASK, maskX and maskY are not zero, we should 1296170d5fdcSmrg * subtract them to do the operation in the correct region */ 1297f29dbc25Smrg 1298170d5fdcSmrg /* FIXME: Please add the code to handle the condition when the maskX 1299170d5fdcSmrg * and maskY coordinate are negative or greater than 1300170d5fdcSmrg * exaScratch.srcWidth and exaScratch.srcHeight */ 1301170d5fdcSmrg 1302170d5fdcSmrg if (exaScratch.type == COMP_TYPE_MASK) { 130304007ebaSmrg if ((exaScratch.srcWidth - maskX) < opWidth) 130404007ebaSmrg opWidth = exaScratch.srcWidth - maskX; 130504007ebaSmrg if ((exaScratch.srcHeight - maskY) < opHeight) 130604007ebaSmrg opHeight = exaScratch.srcHeight - maskY; 130704007ebaSmrg } 130804007ebaSmrg else { 130904007ebaSmrg if (exaScratch.type == COMP_TYPE_ONEPASS) { 131004007ebaSmrg /* This is the condition srcX or/and srcY is/are out of source 131104007ebaSmrg * region */ 131204007ebaSmrg if (((srcY >= 0 && srcY >= exaScratch.srcHeight) 131304007ebaSmrg || (srcX >= 0 && srcX >= exaScratch.srcWidth)) && 131404007ebaSmrg (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) { 131504007ebaSmrg if (exaScratch.repeat == 1) { 131604007ebaSmrg opWidth = width; 131704007ebaSmrg opHeight = height; 131804007ebaSmrg } 131904007ebaSmrg else { 132004007ebaSmrg if (exaScratch.op == PictOpOver) 132104007ebaSmrg return; 132204007ebaSmrg else { 132304007ebaSmrg exaScratch.op = PictOpClear; 132404007ebaSmrg opWidth = width; 132504007ebaSmrg opHeight = height; 132604007ebaSmrg } 132704007ebaSmrg } 132804007ebaSmrg /* This is the condition srcX or/and srcY is/are in the source 132904007ebaSmrg * region */ 133004007ebaSmrg } 133104007ebaSmrg else if (srcX >= 0 && srcY >= 0 && 133204007ebaSmrg (exaScratch.op == PictOpOver || 133304007ebaSmrg exaScratch.op == PictOpSrc)) { 133404007ebaSmrg if (exaScratch.repeat == 1) { 133504007ebaSmrg opWidth = width; 133604007ebaSmrg opHeight = height; 133704007ebaSmrg } 133804007ebaSmrg else { 133904007ebaSmrg if ((exaScratch.srcWidth - srcX) < opWidth) 134004007ebaSmrg opWidth = exaScratch.srcWidth - srcX; 134104007ebaSmrg if ((exaScratch.srcHeight - srcY) < opHeight) 134204007ebaSmrg opHeight = exaScratch.srcHeight - srcY; 134304007ebaSmrg } 134404007ebaSmrg /* This is the condition srcX or/and srcY is/are negative */ 134504007ebaSmrg } 134604007ebaSmrg else if ((srcX < 0 || srcY < 0) && 134704007ebaSmrg (exaScratch.op == PictOpOver || 134804007ebaSmrg exaScratch.op == PictOpSrc)) { 134904007ebaSmrg if (exaScratch.repeat == 1) { 135004007ebaSmrg opWidth = width; 135104007ebaSmrg opHeight = height; 135204007ebaSmrg } 135304007ebaSmrg else { 135404007ebaSmrg /* FIXME: We can't support negative srcX/Y for all corner cases in 135504007ebaSmrg * a sane way without a bit bigger refactoring. So as to avoid 135604007ebaSmrg * gross misrenderings (e.g missing tray icons) in current real-world 135704007ebaSmrg * applications, just shift destination appropriately for now and 135804007ebaSmrg * ignore out of bounds source pixmap zero-vector handling. This is 135904007ebaSmrg * actually correct for PictOpOver, but PictOpSrc out of bounds regions 136004007ebaSmrg * should be blacked out, but aren't - without this workaround however 136104007ebaSmrg * it'd be simply all black instead, which is probably worse till a full 136204007ebaSmrg * clean solution solves it for all cases. */ 136304007ebaSmrg if (srcX < 0) { 136404007ebaSmrg opX -= srcX; 136504007ebaSmrg srcX = 0; 136604007ebaSmrg } 136704007ebaSmrg 136804007ebaSmrg if (srcY < 0) { 136904007ebaSmrg opY -= srcY; 137004007ebaSmrg srcY = 0; 137104007ebaSmrg } 137204007ebaSmrg 137304007ebaSmrg /* EXA has taken care of adjusting srcWidth if it gets cut on the right */ 137404007ebaSmrg width = opWidth = exaScratch.srcWidth; 137504007ebaSmrg /* EXA has taken care of adjusting srcHeight if it gets cut on the bottom */ 137604007ebaSmrg height = opHeight = exaScratch.srcHeight; 137704007ebaSmrg } 137804007ebaSmrg } 137904007ebaSmrg else { 138004007ebaSmrg if (exaScratch.srcWidth < opWidth) 138104007ebaSmrg opWidth = exaScratch.srcWidth; 138204007ebaSmrg if (exaScratch.srcHeight < opHeight) 138304007ebaSmrg opHeight = exaScratch.srcHeight; 138404007ebaSmrg } 138504007ebaSmrg } 138604007ebaSmrg else { 138704007ebaSmrg if (exaScratch.rotate == RR_Rotate_180) { 138804007ebaSmrg } 138904007ebaSmrg else { 139004007ebaSmrg if ((exaScratch.srcWidth - srcY) < opWidth) 139104007ebaSmrg opWidth = exaScratch.srcWidth - srcY; 139204007ebaSmrg if ((exaScratch.srcHeight - srcX) < opHeight) 139304007ebaSmrg opHeight = exaScratch.srcHeight - srcX; 139404007ebaSmrg } 139504007ebaSmrg } 1396170d5fdcSmrg } 1397f29dbc25Smrg 1398f29dbc25Smrg while (1) { 1399f29dbc25Smrg 140004007ebaSmrg dstOffset = GetPixmapOffset(pxDst, opX, opY); 140104007ebaSmrg 140204007ebaSmrg switch (exaScratch.type) { 140304007ebaSmrg 140404007ebaSmrg case COMP_TYPE_MASK:{ 140504007ebaSmrg if (exaScratch.op == PictOpOver || exaScratch.op == 140604007ebaSmrg PictOpOutReverse || exaScratch.op == PictOpInReverse || 140704007ebaSmrg exaScratch.op == PictOpIn || exaScratch.op == PictOpOut || 140804007ebaSmrg exaScratch.op == PictOpOverReverse) 140904007ebaSmrg lx_do_composite_mask_two_pass(pxDst, dstOffset, 141004007ebaSmrg srcOffset, opWidth, opHeight, opX, 141104007ebaSmrg opY, srcPoint); 141204007ebaSmrg else 141304007ebaSmrg lx_do_composite_mask(pxDst, dstOffset, srcOffset, 141404007ebaSmrg opWidth, opHeight); 141504007ebaSmrg } 141604007ebaSmrg break; 141704007ebaSmrg 141804007ebaSmrg case COMP_TYPE_ONEPASS: 141904007ebaSmrg if ((exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc) 142004007ebaSmrg && (exaScratch.repeat == 1)) { 142104007ebaSmrg lx_composite_onepass_special(pxDst, opWidth, opHeight, opX, opY, 142204007ebaSmrg srcX, srcY); 142304007ebaSmrg return; 142404007ebaSmrg } 142504007ebaSmrg else if ((exaScratch.op == PictOpAdd) && (exaScratch.srcFormat->exa 142604007ebaSmrg == PICT_a8) && 142704007ebaSmrg (exaScratch.dstFormat->exa == PICT_a8)) 142804007ebaSmrg lx_composite_onepass_add_a8(pxDst, dstOffset, srcOffset, 142904007ebaSmrg opWidth, opHeight, opX, opY, srcX, 143004007ebaSmrg srcY); 143104007ebaSmrg else 143204007ebaSmrg lx_composite_onepass(pxDst, dstOffset, srcOffset, opWidth, 143304007ebaSmrg opHeight); 143404007ebaSmrg break; 143504007ebaSmrg 143604007ebaSmrg case COMP_TYPE_TWOPASS: 143704007ebaSmrg lx_composite_multipass(pxDst, dstOffset, srcOffset, opWidth, 143804007ebaSmrg opHeight); 143904007ebaSmrg 144004007ebaSmrg case COMP_TYPE_ROTATE: 144104007ebaSmrg lx_composite_rotate(pxDst, dstOffset, srcOffset, opWidth, opHeight); 144204007ebaSmrg break; 144304007ebaSmrg } 144404007ebaSmrg 144504007ebaSmrg opX += opWidth; 144604007ebaSmrg 144704007ebaSmrg if (opX >= dstX + width) { 144804007ebaSmrg opX = dstX; 144904007ebaSmrg opY += opHeight; 145004007ebaSmrg 145104007ebaSmrg if (opY >= dstY + height) 145204007ebaSmrg break; 145304007ebaSmrg } 145404007ebaSmrg 145504007ebaSmrg /* FIXME: Please add the code to handle the condition when the maskX 145604007ebaSmrg * and maskY coordinate are negative or greater than 145704007ebaSmrg * exaScratch.srcWidth and exaScratch.srcHeight */ 145804007ebaSmrg 145904007ebaSmrg if (exaScratch.type == COMP_TYPE_MASK) { 146004007ebaSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - maskX) 146104007ebaSmrg ? (exaScratch.srcWidth - maskX) : (dstX + width) - opX; 146204007ebaSmrg opHeight = ((dstY + height) - opY) > (exaScratch.srcHeight - maskY) 146304007ebaSmrg ? (exaScratch.srcHeight - maskY) : (dstY + height) - opY; 146404007ebaSmrg /* All black out of the mask */ 146504007ebaSmrg if (!exaScratch.maskrepeat) 146604007ebaSmrg exaScratch.srcColor = 0x0; 146704007ebaSmrg } 146804007ebaSmrg else { 146904007ebaSmrg if (exaScratch.type == COMP_TYPE_ONEPASS) { 147004007ebaSmrg if (srcX >= 0 && srcY >= 0 && (exaScratch.op == PictOpOver || 147104007ebaSmrg exaScratch.op == PictOpSrc || 147204007ebaSmrg exaScratch.op == PictOpClear)) { 147304007ebaSmrg opWidth = 147404007ebaSmrg ((dstX + width) - opX) > 147504007ebaSmrg (exaScratch.srcWidth - srcX) ? (exaScratch.srcWidth - 147604007ebaSmrg srcX) : (dstX + width) 147704007ebaSmrg - opX; 147804007ebaSmrg opHeight = ((dstY + height) - opY) > 147904007ebaSmrg (exaScratch.srcHeight - srcY) ? 148004007ebaSmrg (exaScratch.srcHeight - srcY) : (dstY + height) - opY; 148104007ebaSmrg } 148204007ebaSmrg else { 148304007ebaSmrg opWidth = ((dstX + width) - opX) > exaScratch.srcWidth ? 148404007ebaSmrg exaScratch.srcWidth : (dstX + width) - opX; 148504007ebaSmrg opHeight = ((dstY + height) - opY) > exaScratch.srcHeight ? 148604007ebaSmrg exaScratch.srcHeight : (dstY + height) - opY; 148704007ebaSmrg } 148804007ebaSmrg } 148904007ebaSmrg else { 149004007ebaSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - srcY) 149104007ebaSmrg ? (exaScratch.srcWidth - srcY) : (dstX + width) - opX; 149204007ebaSmrg opHeight = 149304007ebaSmrg ((dstY + height) - opY) > 149404007ebaSmrg (exaScratch.srcHeight - srcX) ? (exaScratch.srcHeight - 149504007ebaSmrg srcX) : (dstY + height) - 149604007ebaSmrg opY; 149704007ebaSmrg } 149804007ebaSmrg /* All black out of the source */ 149904007ebaSmrg if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ONEPASS)) { 150004007ebaSmrg /* FIXME: We black out the source here, so that any further regions 150104007ebaSmrg * in the loop get handled as a source that's a zero-vector (as 150204007ebaSmrg * defined for out-of-bounds from source pixmap for RepeatModeNone), 150304007ebaSmrg * but this will likely interfere with cases where srcX and/or srcY 150404007ebaSmrg * is negative - as opposed to e.g width being larger than srcWidth, 150504007ebaSmrg * which is exercised in rendercheck (always rectangle in top-left 150604007ebaSmrg * corner). 150704007ebaSmrg * Additionally it forces the drawing into tiles of srcWidth/srcHeight 150804007ebaSmrg * for non-repeat modes too, where we don't really need to tile it like 150904007ebaSmrg * this and could draw the out of bound regions all at once (or at most 151004007ebaSmrg * in 4 operations without the big loop). */ 151104007ebaSmrg lx_composite_all_black(srcOffset, exaScratch.srcWidth, 151204007ebaSmrg exaScratch.srcHeight); 151304007ebaSmrg } 151404007ebaSmrg if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ROTATE)) 151504007ebaSmrg break; 151604007ebaSmrg } 1517f29dbc25Smrg } 1518f29dbc25Smrg} 1519f29dbc25Smrg 1520f29dbc25Smrgstatic void 1521f29dbc25Smrglx_wait_marker(ScreenPtr PScreen, int marker) 1522f29dbc25Smrg{ 1523f29dbc25Smrg gp_wait_until_idle(); 1524f29dbc25Smrg} 1525f29dbc25Smrg 1526f29dbc25Smrgstatic void 1527f29dbc25Smrglx_done(PixmapPtr ptr) 1528f29dbc25Smrg{ 1529f29dbc25Smrg} 1530f29dbc25Smrg 1531f29dbc25Smrg#if 0 1532f29dbc25Smrgstatic void 1533f29dbc25Smrglx_upload_to_screen(PixmapPtr pxDst, int x, int y, int w, int h, 153404007ebaSmrg char *src, int src_pitch) 1535f29dbc25Smrg{ 1536f29dbc25Smrg GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); 1537f29dbc25Smrg int dst_pitch = exaGetPixmapPitch(pxDst); 1538f29dbc25Smrg int cpp = (pxDst->drawable.bitsPerPixel + 7) / 8; 1539f29dbc25Smrg 1540f29dbc25Smrg char *dst; 1541f29dbc25Smrg int offset = exaGetPixmapOffset(pxDst); 1542f29dbc25Smrg 154304007ebaSmrg dst = (char *) (pGeode->FBBase + offset + (y * dst_pitch) + (x * cpp)); 1544f29dbc25Smrg int i; 1545f29dbc25Smrg 1546f29dbc25Smrg for (i = 0; i < h; i++) { 154704007ebaSmrg memcpy(dst, src, w * cpp); 154804007ebaSmrg dst += dst_pitch; 154904007ebaSmrg src += src_pitch; 1550f29dbc25Smrg } 1551f29dbc25Smrg} 1552f29dbc25Smrg#endif 1553f29dbc25Smrg 155404007ebaSmrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 2) 1555f29dbc25Smrg 1556f29dbc25Smrgstatic Bool 1557f29dbc25Smrglx_exa_pixmap_is_offscreen(PixmapPtr pPixmap) 1558f29dbc25Smrg{ 155904007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pPixmap->drawable.pScreen); 1560f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 156104007ebaSmrg void *start = (void *) (pGeode->FBBase); 1562f29dbc25Smrg void *end = 156304007ebaSmrg (void *) (pGeode->FBBase + pGeode->offscreenStart + 156404007ebaSmrg pGeode->offscreenSize); 1565f29dbc25Smrg 156604007ebaSmrg if ((void *) pPixmap->devPrivate.ptr >= start && 156704007ebaSmrg (void *) pPixmap->devPrivate.ptr < end) 156804007ebaSmrg return TRUE; 1569f29dbc25Smrg 1570f29dbc25Smrg return FALSE; 1571f29dbc25Smrg} 1572f29dbc25Smrg 1573f29dbc25Smrg#endif 1574f29dbc25Smrg 1575f29dbc25SmrgBool 1576f29dbc25SmrgLXExaInit(ScreenPtr pScreen) 1577f29dbc25Smrg{ 157804007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 1579f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1580f29dbc25Smrg ExaDriverPtr pExa = pGeode->pExa; 1581f29dbc25Smrg 1582f29dbc25Smrg pExa->exa_major = EXA_VERSION_MAJOR; 1583f29dbc25Smrg pExa->exa_minor = EXA_VERSION_MINOR; 1584f29dbc25Smrg 1585f29dbc25Smrg pExa->WaitMarker = lx_wait_marker; 1586f29dbc25Smrg 1587f29dbc25Smrg pExa->PrepareSolid = lx_prepare_solid; 1588f29dbc25Smrg pExa->Solid = lx_do_solid; 1589f29dbc25Smrg pExa->DoneSolid = lx_done; 1590f29dbc25Smrg 1591f29dbc25Smrg pExa->PrepareCopy = lx_prepare_copy; 1592f29dbc25Smrg pExa->Copy = lx_do_copy; 1593f29dbc25Smrg pExa->DoneCopy = lx_done; 1594f29dbc25Smrg 1595f29dbc25Smrg /* Composite */ 1596f29dbc25Smrg pExa->CheckComposite = lx_check_composite; 1597f29dbc25Smrg pExa->PrepareComposite = lx_prepare_composite; 1598f29dbc25Smrg pExa->Composite = lx_do_composite; 1599f29dbc25Smrg pExa->DoneComposite = lx_done; 1600f29dbc25Smrg //pExa->UploadToScreen = lx_upload_to_screen; 1601f29dbc25Smrg 160204007ebaSmrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 2) 1603f29dbc25Smrg pExa->PixmapIsOffscreen = lx_exa_pixmap_is_offscreen; 1604f29dbc25Smrg#endif 1605f29dbc25Smrg 1606f29dbc25Smrg //pExa->flags = EXA_OFFSCREEN_PIXMAPS; 1607f29dbc25Smrg 1608f29dbc25Smrg return exaDriverInit(pScreen, pGeode->pExa); 1609f29dbc25Smrg} 1610