lx_exa.c revision 170d5fdc
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 51f29dbc25Smrgstatic const struct exa_format_t 52f29dbc25Smrg{ 53f29dbc25Smrg int exa; 54f29dbc25Smrg int bpp; 55f29dbc25Smrg int fmt; 56f29dbc25Smrg int alphabits; 57f29dbc25Smrg} lx_exa_formats[] = { 58f29dbc25Smrg { 59f29dbc25Smrg PICT_a8r8g8b8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 8}, { 60f29dbc25Smrg PICT_x8r8g8b8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 0}, { 61f29dbc25Smrg PICT_x8b8g8r8, 32, CIMGP_SOURCE_FMT_32BPP_BGR, 0}, { 62f29dbc25Smrg PICT_a4r4g4b4, 16, CIMGP_SOURCE_FMT_4_4_4_4, 4}, { 63f29dbc25Smrg PICT_a1r5g5b5, 16, CIMGP_SOURCE_FMT_1_5_5_5, 1}, { 64f29dbc25Smrg PICT_r5g6b5, 16, CIMGP_SOURCE_FMT_0_5_6_5, 0}, { 65f29dbc25Smrg PICT_b5g6r5, 16, CIMGP_SOURCE_FMT_16BPP_BGR, 0}, { 66f29dbc25Smrg PICT_x1r5g5b5, 16, CIMGP_SOURCE_FMT_1_5_5_5, 0}, { 67f29dbc25Smrg PICT_x1b5g5r5, 16, CIMGP_SOURCE_FMT_15BPP_BGR, 0}, { 68170d5fdcSmrg PICT_r3g3b2, 8, CIMGP_SOURCE_FMT_3_3_2, 0}, { 69170d5fdcSmrg PICT_a8, 32, CIMGP_SOURCE_FMT_8_8_8_8, 8} 70f29dbc25Smrg}; 71f29dbc25Smrg 72f29dbc25Smrg/* This is a chunk of memory we use for scratch space */ 73f29dbc25Smrg 74f29dbc25Smrg#define COMP_TYPE_MASK 0 75f29dbc25Smrg#define COMP_TYPE_ONEPASS 1 76f29dbc25Smrg#define COMP_TYPE_TWOPASS 3 77f29dbc25Smrg#define COMP_TYPE_ROTATE 5 78f29dbc25Smrg 79f29dbc25Smrgstatic struct 80f29dbc25Smrg{ 81f29dbc25Smrg int type; 82f29dbc25Smrg 83f29dbc25Smrg unsigned int srcOffset; 84f29dbc25Smrg unsigned int srcPitch; 85f29dbc25Smrg unsigned int srcBpp; 86f29dbc25Smrg unsigned int srcWidth, srcHeight; 87f29dbc25Smrg PixmapPtr srcPixmap; 88f29dbc25Smrg 89f29dbc25Smrg unsigned int srcColor; 90f29dbc25Smrg int op; 91f29dbc25Smrg int repeat; 92170d5fdcSmrg int maskrepeat; 93f29dbc25Smrg unsigned int fourBpp; 94f29dbc25Smrg unsigned int bufferOffset; 95f29dbc25Smrg struct exa_format_t *srcFormat; 96f29dbc25Smrg struct exa_format_t *dstFormat; 97f29dbc25Smrg 98f29dbc25Smrg int rotate; 99f29dbc25Smrg PictTransform *transform; 100f29dbc25Smrg 101f29dbc25Smrg} exaScratch; 102f29dbc25Smrg 103f29dbc25Smrgstatic const int SDfn[16] = { 104f29dbc25Smrg 0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE, 105f29dbc25Smrg 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF 106f29dbc25Smrg}; 107f29dbc25Smrg 108f29dbc25Smrgstatic const int SDfn_PM[16] = { 109f29dbc25Smrg 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 110f29dbc25Smrg 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA 111f29dbc25Smrg}; 112f29dbc25Smrg 113f29dbc25Smrg/* These functions check to see if we can safely prefetch the memory 114f29dbc25Smrg * for the blt, or if we have to wait the previous blt to complete. 115f29dbc25Smrg * One function is for the fill, and the other is for the copy because 116f29dbc25Smrg * they have different requirements based on ROP 117f29dbc25Smrg */ 118f29dbc25Smrg 119f29dbc25Smrgstatic int lx0 = -1, ly0 = -1, lx1 = -1, ly1 = -1; 120f29dbc25Smrg 121f29dbc25Smrgstatic int 122f29dbc25Smrglx_fill_flags(int x0, int y0, int w, int h, int rop) 123f29dbc25Smrg{ 124f29dbc25Smrg int x1 = x0 + w, y1 = y0 + h; 125f29dbc25Smrg int n = ((rop ^ (rop >> 1)) & 0x55) == 0 || /* no dst */ 126f29dbc25Smrg x0 >= lx1 || y0 >= ly1 || /* rght/below */ 127f29dbc25Smrg x1 <= lx0 || y1 <= ly0 ? /* left/above */ 128f29dbc25Smrg 0 : CIMGP_BLTFLAGS_HAZARD; 129f29dbc25Smrg 130f29dbc25Smrg lx0 = x0; 131f29dbc25Smrg ly0 = y0; 132f29dbc25Smrg lx1 = x1; 133f29dbc25Smrg ly1 = y1; 134f29dbc25Smrg 135f29dbc25Smrg return n; 136f29dbc25Smrg} 137f29dbc25Smrg 138f29dbc25Smrgstatic int 139f29dbc25Smrglx_copy_flags(int x0, int y0, int x1, int y1, int w, int h, int rop) 140f29dbc25Smrg{ 141f29dbc25Smrg int x2 = x1 + w, y2 = y1 + h; 142f29dbc25Smrg 143f29dbc25Smrg /* dst not hazzard and src not hazzard */ 144f29dbc25Smrg int n = (((rop ^ (rop >> 1)) & 0x55) == 0 || 145f29dbc25Smrg x1 >= lx1 || y1 >= ly1 || 146f29dbc25Smrg x2 <= lx0 || y2 <= ly0) && 147f29dbc25Smrg (((rop ^ (rop >> 2)) & 0x33) == 0 || 148f29dbc25Smrg x0 >= lx1 || y0 >= ly1 || 149f29dbc25Smrg x0 + w <= lx0 || y0 + h <= ly0) ? 0 : CIMGP_BLTFLAGS_HAZARD; 150f29dbc25Smrg 151f29dbc25Smrg lx0 = x1; 152f29dbc25Smrg ly0 = y1; 153f29dbc25Smrg lx1 = x2; 154f29dbc25Smrg ly1 = y2; 155f29dbc25Smrg 156f29dbc25Smrg return n; 157f29dbc25Smrg} 158f29dbc25Smrg 159f29dbc25Smrg/* These are borrowed from the exa engine - they should be made global 160f29dbc25Smrg and available to drivers, but until then.... 161f29dbc25Smrg*/ 162f29dbc25Smrg 163f29dbc25Smrg/* exaGetPixelFromRGBA (exa_render.c) */ 164f29dbc25Smrg 165f29dbc25Smrgstatic Bool 166f29dbc25Smrg_GetPixelFromRGBA(CARD32 * pixel, 167f29dbc25Smrg CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, CARD32 format) 168f29dbc25Smrg{ 169f29dbc25Smrg int rbits, bbits, gbits, abits; 170f29dbc25Smrg int rshift, bshift, gshift, ashift; 171f29dbc25Smrg 172f29dbc25Smrg *pixel = 0; 173f29dbc25Smrg 174f29dbc25Smrg if (!PICT_FORMAT_COLOR(format)) 175f29dbc25Smrg return FALSE; 176f29dbc25Smrg 177f29dbc25Smrg rbits = PICT_FORMAT_R(format); 178f29dbc25Smrg gbits = PICT_FORMAT_G(format); 179f29dbc25Smrg bbits = PICT_FORMAT_B(format); 180f29dbc25Smrg abits = PICT_FORMAT_A(format); 181f29dbc25Smrg 182f29dbc25Smrg if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 183f29dbc25Smrg bshift = 0; 184f29dbc25Smrg gshift = bbits; 185f29dbc25Smrg rshift = gshift + gbits; 186f29dbc25Smrg ashift = rshift + rbits; 187f29dbc25Smrg } else { /* PICT_TYPE_ABGR */ 188f29dbc25Smrg rshift = 0; 189f29dbc25Smrg gshift = rbits; 190f29dbc25Smrg bshift = gshift + gbits; 191f29dbc25Smrg ashift = bshift + bbits; 192f29dbc25Smrg } 193f29dbc25Smrg 194f29dbc25Smrg *pixel |= (blue >> (16 - bbits)) << bshift; 195f29dbc25Smrg *pixel |= (red >> (16 - rbits)) << rshift; 196f29dbc25Smrg *pixel |= (green >> (16 - gbits)) << gshift; 197f29dbc25Smrg *pixel |= (alpha >> (16 - abits)) << ashift; 198f29dbc25Smrg 199f29dbc25Smrg return TRUE; 200f29dbc25Smrg} 201f29dbc25Smrg 202f29dbc25Smrg/* exaGetRGBAFromPixel (exa_render.c) */ 203f29dbc25Smrg 204f29dbc25Smrgstatic Bool 205f29dbc25Smrg_GetRGBAFromPixel(CARD32 pixel, 206f29dbc25Smrg CARD16 * red, 207f29dbc25Smrg CARD16 * green, CARD16 * blue, CARD16 * alpha, CARD32 format) 208f29dbc25Smrg{ 209f29dbc25Smrg int rbits, bbits, gbits, abits; 210f29dbc25Smrg int rshift, bshift, gshift, ashift; 211f29dbc25Smrg 212f29dbc25Smrg if (!PICT_FORMAT_COLOR(format)) 213f29dbc25Smrg return FALSE; 214f29dbc25Smrg 215f29dbc25Smrg rbits = PICT_FORMAT_R(format); 216f29dbc25Smrg gbits = PICT_FORMAT_G(format); 217f29dbc25Smrg bbits = PICT_FORMAT_B(format); 218f29dbc25Smrg abits = PICT_FORMAT_A(format); 219f29dbc25Smrg 220f29dbc25Smrg if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 221f29dbc25Smrg bshift = 0; 222f29dbc25Smrg gshift = bbits; 223f29dbc25Smrg rshift = gshift + gbits; 224f29dbc25Smrg ashift = rshift + rbits; 225f29dbc25Smrg } else { /* PICT_TYPE_ABGR */ 226f29dbc25Smrg rshift = 0; 227f29dbc25Smrg gshift = rbits; 228f29dbc25Smrg bshift = gshift + gbits; 229f29dbc25Smrg ashift = bshift + bbits; 230f29dbc25Smrg } 231f29dbc25Smrg 232f29dbc25Smrg *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); 233f29dbc25Smrg while (rbits < 16) { 234f29dbc25Smrg *red |= *red >> rbits; 235f29dbc25Smrg rbits <<= 1; 236f29dbc25Smrg } 237f29dbc25Smrg 238f29dbc25Smrg *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); 239f29dbc25Smrg while (gbits < 16) { 240f29dbc25Smrg *green |= *green >> gbits; 241f29dbc25Smrg gbits <<= 1; 242f29dbc25Smrg } 243f29dbc25Smrg 244f29dbc25Smrg *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); 245f29dbc25Smrg while (bbits < 16) { 246f29dbc25Smrg *blue |= *blue >> bbits; 247f29dbc25Smrg bbits <<= 1; 248f29dbc25Smrg } 249f29dbc25Smrg 250f29dbc25Smrg if (abits) { 251f29dbc25Smrg *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); 252f29dbc25Smrg while (abits < 16) { 253f29dbc25Smrg *alpha |= *alpha >> abits; 254f29dbc25Smrg abits <<= 1; 255f29dbc25Smrg } 256f29dbc25Smrg } else 257f29dbc25Smrg *alpha = 0xffff; 258f29dbc25Smrg 259f29dbc25Smrg return TRUE; 260f29dbc25Smrg} 261f29dbc25Smrg 262f29dbc25Smrgstatic unsigned int 263f29dbc25Smrglx_get_source_color(PixmapPtr pSrc, int srcFormat, int dstFormat) 264f29dbc25Smrg{ 265f29dbc25Smrg CARD32 in, out; 266f29dbc25Smrg CARD16 red = 0, green = 0, blue = 0, alpha = 0; 267f29dbc25Smrg 268f29dbc25Smrg /* Stall to avoid a race with the upload function */ 269f29dbc25Smrg /* for 1.4 and newer, the problem will be resolved within 270f29dbc25Smrg * exaGetPixmapFirstPixel, so this should be adjusted so 271f29dbc25Smrg * the stall isn't run needlessly 272f29dbc25Smrg */ 273f29dbc25Smrg 274f29dbc25Smrg gp_wait_until_idle(); 275f29dbc25Smrg in = exaGetPixmapFirstPixel(pSrc); 276f29dbc25Smrg 277f29dbc25Smrg _GetRGBAFromPixel(in, &red, &blue, &green, &alpha, srcFormat); 278f29dbc25Smrg _GetPixelFromRGBA(&out, red, blue, green, alpha, dstFormat); 279f29dbc25Smrg 280f29dbc25Smrg return out; 281f29dbc25Smrg} 282f29dbc25Smrg 283f29dbc25Smrgstatic Bool 284f29dbc25Smrglx_prepare_solid(PixmapPtr pxMap, int alu, Pixel planemask, Pixel fg) 285f29dbc25Smrg{ 286f29dbc25Smrg int pitch = exaGetPixmapPitch(pxMap); 287f29dbc25Smrg int op = (planemask == ~0U) ? SDfn[alu] : SDfn_PM[alu]; 288f29dbc25Smrg 289f29dbc25Smrg gp_declare_blt(0); 290f29dbc25Smrg gp_set_bpp(pxMap->drawable.bitsPerPixel); 291f29dbc25Smrg 292f29dbc25Smrg gp_set_raster_operation(op); 293f29dbc25Smrg 294f29dbc25Smrg if (planemask != ~0U) 295f29dbc25Smrg gp_set_solid_pattern(planemask); 296f29dbc25Smrg 297f29dbc25Smrg exaScratch.op = op; 298f29dbc25Smrg 299f29dbc25Smrg gp_set_solid_source(fg); 300f29dbc25Smrg 301f29dbc25Smrg gp_set_strides(pitch, pitch); 302f29dbc25Smrg gp_write_parameters(); 303f29dbc25Smrg return TRUE; 304f29dbc25Smrg} 305f29dbc25Smrg 306f29dbc25Smrgstatic void 307f29dbc25Smrglx_do_solid(PixmapPtr pxMap, int x1, int y1, int x2, int y2) 308f29dbc25Smrg{ 309f29dbc25Smrg int bpp = (pxMap->drawable.bitsPerPixel + 7) / 8; 310f29dbc25Smrg int pitch = exaGetPixmapPitch(pxMap); 311f29dbc25Smrg unsigned int offset = 312f29dbc25Smrg exaGetPixmapOffset(pxMap) + (pitch * y1) + (bpp * x1); 313f29dbc25Smrg 314f29dbc25Smrg gp_declare_blt(lx_fill_flags(x1, y1, x2 - x1, y2 - y1, exaScratch.op)); 315f29dbc25Smrg gp_pattern_fill(offset, x2 - x1, y2 - y1); 316f29dbc25Smrg} 317f29dbc25Smrg 318f29dbc25Smrgstatic Bool 319f29dbc25Smrglx_prepare_copy(PixmapPtr pxSrc, PixmapPtr pxDst, int dx, int dy, 320f29dbc25Smrg int alu, Pixel planemask) 321f29dbc25Smrg{ 322f29dbc25Smrg int dpitch = exaGetPixmapPitch(pxDst); 323f29dbc25Smrg int op = (planemask == ~0U) ? SDfn[alu] : SDfn_PM[alu]; 324f29dbc25Smrg 325f29dbc25Smrg gp_declare_blt(0); 326f29dbc25Smrg gp_set_bpp(pxDst->drawable.bitsPerPixel); 327f29dbc25Smrg 328f29dbc25Smrg gp_set_raster_operation(op); 329f29dbc25Smrg 330f29dbc25Smrg if (planemask != ~0U) 331f29dbc25Smrg gp_set_solid_pattern(planemask); 332f29dbc25Smrg 333f29dbc25Smrg exaScratch.srcOffset = exaGetPixmapOffset(pxSrc); 334f29dbc25Smrg exaScratch.srcPitch = exaGetPixmapPitch(pxSrc); 335f29dbc25Smrg exaScratch.srcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; 336f29dbc25Smrg 337f29dbc25Smrg exaScratch.op = op; 338f29dbc25Smrg 339f29dbc25Smrg gp_set_strides(dpitch, exaScratch.srcPitch); 340f29dbc25Smrg gp_write_parameters(); 341f29dbc25Smrg return TRUE; 342f29dbc25Smrg} 343f29dbc25Smrg 344f29dbc25Smrgstatic void 345f29dbc25Smrglx_do_copy(PixmapPtr pxDst, int srcX, int srcY, 346f29dbc25Smrg int dstX, int dstY, int w, int h) 347f29dbc25Smrg{ 348f29dbc25Smrg int dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8; 349f29dbc25Smrg int dstPitch = exaGetPixmapPitch(pxDst); 350f29dbc25Smrg unsigned int srcOffset, dstOffset; 351f29dbc25Smrg int flags = 0; 352f29dbc25Smrg 353f29dbc25Smrg gp_declare_blt(lx_copy_flags(srcX, srcY, dstX, dstY, w, h, 354f29dbc25Smrg exaScratch.op)); 355f29dbc25Smrg 356f29dbc25Smrg srcOffset = exaScratch.srcOffset + (exaScratch.srcPitch * srcY) + 357f29dbc25Smrg (exaScratch.srcBpp) * srcX; 358f29dbc25Smrg 359f29dbc25Smrg dstOffset = exaGetPixmapOffset(pxDst) + 360f29dbc25Smrg (dstPitch * dstY) + (dstBpp * dstX); 361f29dbc25Smrg 362f29dbc25Smrg if (dstX > srcX) 363f29dbc25Smrg flags |= CIMGP_NEGXDIR; 364f29dbc25Smrg 365f29dbc25Smrg if (dstY > srcY) 366f29dbc25Smrg flags |= CIMGP_NEGYDIR; 367f29dbc25Smrg 368f29dbc25Smrg gp_screen_to_screen_blt(dstOffset, srcOffset, w, h, flags); 369f29dbc25Smrg} 370f29dbc25Smrg 371f29dbc25Smrg/* Composite operations 372f29dbc25Smrg 373f29dbc25SmrgThese are the simplest - one pass operations - if there is no format or 374f29dbc25Smrgmask, the we can make these happen pretty fast 375f29dbc25Smrg 376f29dbc25Smrg Operation Type Channel Alpha 377f29dbc25SmrgPictOpClear 0 2 0 3 378f29dbc25SmrgPictOpSrc 0 3 0 3 379f29dbc25SmrgPictOpDst 0 3 1 3 380f29dbc25SmrgPictOpOver 2 0 0 3 381f29dbc25SmrgPictOpOverReverse 2 0 1 3 382f29dbc25SmrgPictOpIn 0 1 0 3 383f29dbc25SmrgPictOpInReverse 0 1 1 3 384f29dbc25SmrgPictOpOut 1 0 0 3 385f29dbc25SmrgPictOpOutReverse 1 0 1 3 386f29dbc25SmrgPictOpAdd 2 2 0 3 387f29dbc25Smrg 388f29dbc25SmrgThe following require multiple passes 389f29dbc25SmrgPictOpAtop 390f29dbc25SmrgPictOpXor 391f29dbc25Smrg*/ 392f29dbc25Smrg 393f29dbc25Smrgstruct blend_ops_t 394f29dbc25Smrg{ 395f29dbc25Smrg int operation; 396f29dbc25Smrg int type; 397f29dbc25Smrg int channel; 398f29dbc25Smrg} lx_alpha_ops[] = { 399f29dbc25Smrg /* PictOpClear */ 400f29dbc25Smrg { 401f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CONSTANT_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 402f29dbc25Smrg }, 403f29dbc25Smrg /* PictOpSrc */ 404f29dbc25Smrg { 405f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_ALPHA_EQUALS_ONE, CIMGP_CHANNEL_A_SOURCE}, { 406f29dbc25Smrg }, 407f29dbc25Smrg /* PictOpDst */ 408f29dbc25Smrg { 409f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_ALPHA_EQUALS_ONE, CIMGP_CHANNEL_A_DEST}, { 410f29dbc25Smrg }, 411f29dbc25Smrg /* PictOpOver */ 412f29dbc25Smrg { 413170d5fdcSmrg CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 414170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 415f29dbc25Smrg /* PictOpOverReverse */ 416f29dbc25Smrg { 417170d5fdcSmrg CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { 418170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 419f29dbc25Smrg /* PictOpIn */ 420f29dbc25Smrg { 421f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 422170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 423f29dbc25Smrg /* PictOpInReverse */ 424f29dbc25Smrg { 425f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_DEST}, { 426170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 427f29dbc25Smrg /* PictOpOut */ 428f29dbc25Smrg { 429170d5fdcSmrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { 430170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 431f29dbc25Smrg /* PictOpOutReverse */ 432f29dbc25Smrg { 433170d5fdcSmrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 434170d5fdcSmrg CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 435f29dbc25Smrg /* SrcAtop */ 436f29dbc25Smrg { 437f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_DEST}, { 438f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 439f29dbc25Smrg /* SrcAtopReverse */ 440f29dbc25Smrg { 441f29dbc25Smrg CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 442f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, 443f29dbc25Smrg /* Xor */ 444f29dbc25Smrg { 445f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 446f29dbc25Smrg CIMGP_BETA_TIMES_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, 447f29dbc25Smrg /* PictOpAdd */ 448f29dbc25Smrg { 449f29dbc25Smrg CIMGP_A_PLUS_BETA_B, CIMGP_CONSTANT_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { 450f29dbc25Smrg } 451f29dbc25Smrg}; 452f29dbc25Smrg 453f29dbc25Smrg#define ARRAY_SIZE(a) (sizeof((a)) / (sizeof(*(a)))) 454f29dbc25Smrg 455f29dbc25Smrgstatic const struct exa_format_t * 456f29dbc25Smrglx_get_format(PicturePtr p) 457f29dbc25Smrg{ 458f29dbc25Smrg int i; 459f29dbc25Smrg unsigned int format = p->format; 460f29dbc25Smrg 461170d5fdcSmrg for (i = 0; i < ARRAY_SIZE(lx_exa_formats); i++) 462f29dbc25Smrg if (lx_exa_formats[i].exa == format) 463f29dbc25Smrg return (&lx_exa_formats[i]); 464f29dbc25Smrg 465f29dbc25Smrg return NULL; 466f29dbc25Smrg} 467f29dbc25Smrg 468f29dbc25Smrgstatic Bool 469f29dbc25Smrglx_process_transform(PicturePtr pSrc) 470f29dbc25Smrg{ 471f29dbc25Smrg PictTransformPtr t = pSrc->transform; 472f29dbc25Smrg xFixed c0 = t->matrix[0][0]; 473f29dbc25Smrg xFixed s0 = t->matrix[0][1]; 474f29dbc25Smrg xFixed s1 = t->matrix[1][0]; 475f29dbc25Smrg xFixed c1 = t->matrix[1][1]; 476f29dbc25Smrg 477f29dbc25Smrg /* If the transform doesn't have any rotation 478f29dbc25Smrg * or scaling components, then just grab the 479f29dbc25Smrg * translate coordinates */ 480f29dbc25Smrg 481f29dbc25Smrg if (t->matrix[0][0] == 0 && 482f29dbc25Smrg t->matrix[0][1] == 0 && 483f29dbc25Smrg t->matrix[1][0] == 0 && t->matrix[1][1] == 0) { 484f29dbc25Smrg exaScratch.transform = pSrc->transform; 485f29dbc25Smrg return TRUE; 486f29dbc25Smrg } 487f29dbc25Smrg 488f29dbc25Smrg /* Otherwise, see if this is a simple 489f29dbc25Smrg * rotate transform - if it isn't, then 490f29dbc25Smrg * we have to punt back to software */ 491f29dbc25Smrg 492f29dbc25Smrg if (t->matrix[2][2] != F(1)) 493f29dbc25Smrg return FALSE; 494f29dbc25Smrg 495f29dbc25Smrg /* The rotate matrix looks like this: 496f29dbc25Smrg * [ cos X -sin x 497f29dbc25Smrg * sin X cos X ] 498f29dbc25Smrg * 499f29dbc25Smrg * Where X is the angle. We do a simple 500f29dbc25Smrg * check first - if [0,0] != [1,1], then 501f29dbc25Smrg * scaling was specified too, and we can 502f29dbc25Smrg * bail, and if [0,1] != -[1,1] then this 503f29dbc25Smrg * isn't scaling that we can handle. 504f29dbc25Smrg */ 505f29dbc25Smrg 506f29dbc25Smrg if ((c0 != c1) || (s0 != -s1)) 507f29dbc25Smrg return FALSE; 508f29dbc25Smrg 509f29dbc25Smrg /* Now, figure out what angle we want - we 510f29dbc25Smrg * can only accelerate right angle rotations, 511f29dbc25Smrg * so this turns into an easy set of if statements */ 512f29dbc25Smrg 513f29dbc25Smrg if (c0 == F(1) && s1 == F(0)) 514f29dbc25Smrg exaScratch.rotate = RR_Rotate_0; 515f29dbc25Smrg else if (c0 == F(0) && s1 == F(1)) 516f29dbc25Smrg exaScratch.rotate = RR_Rotate_90; 517f29dbc25Smrg else if (c0 == F(-1) && s1 == F(0)) 518f29dbc25Smrg exaScratch.rotate = RR_Rotate_180; 519f29dbc25Smrg else if (c0 == F(0) && s1 == F(-1)) 520f29dbc25Smrg exaScratch.rotate = RR_Rotate_270; 521f29dbc25Smrg else 522f29dbc25Smrg return FALSE; 523f29dbc25Smrg 524f29dbc25Smrg exaScratch.transform = pSrc->transform; 525f29dbc25Smrg 526f29dbc25Smrg return TRUE; 527f29dbc25Smrg} 528f29dbc25Smrg 529f29dbc25Smrgstatic Bool 530f29dbc25Smrglx_check_composite(int op, PicturePtr pSrc, PicturePtr pMsk, PicturePtr pDst) 531f29dbc25Smrg{ 532f29dbc25Smrg GeodeRec *pGeode = GEODEPTR_FROM_PICTURE(pDst); 533170d5fdcSmrg const struct exa_format_t *srcFmt, *dstFmt; 534f29dbc25Smrg 535f29dbc25Smrg /* Check that the operation is supported */ 536f29dbc25Smrg 537f29dbc25Smrg if (op > PictOpAdd) 538f29dbc25Smrg return FALSE; 539f29dbc25Smrg 540170d5fdcSmrg /* FIXME: Meet this conditions from the debug for PictOpAdd. 541170d5fdcSmrg * Any Other possibilities? Add a judge for the future supplement */ 542170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_a8r8g8b8 && 543170d5fdcSmrg pDst->format == PICT_a8 && !pMsk) 544170d5fdcSmrg return TRUE; 545170d5fdcSmrg 546170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_x8r8g8b8 && 547170d5fdcSmrg pDst->format == PICT_a8 && !pMsk) 548170d5fdcSmrg return TRUE; 549170d5fdcSmrg 550170d5fdcSmrg if (op == PictOpAdd && pSrc->format == PICT_r5g6b5 && 551170d5fdcSmrg pDst->format == PICT_a8 && !pMsk) 552170d5fdcSmrg return TRUE; 553170d5fdcSmrg 554170d5fdcSmrg /* We need the off-screen buffer to do the multipass work */ 555170d5fdcSmrg 556f29dbc25Smrg if (usesPasses(op)) { 557f29dbc25Smrg if (pGeode->exaBfrOffset == 0 || !pMsk) 558f29dbc25Smrg return FALSE; 559f29dbc25Smrg } 560f29dbc25Smrg 561f29dbc25Smrg if (pMsk && op == PictOpAdd) 562f29dbc25Smrg return FALSE; 563f29dbc25Smrg 564f29dbc25Smrg /* Check that the filter matches what we support */ 565f29dbc25Smrg 566f29dbc25Smrg switch (pSrc->filter) { 567f29dbc25Smrg case PictFilterNearest: 568f29dbc25Smrg case PictFilterFast: 569f29dbc25Smrg case PictFilterGood: 570f29dbc25Smrg case PictFilterBest: 571f29dbc25Smrg break; 572f29dbc25Smrg 573f29dbc25Smrg default: 574f29dbc25Smrg /* WE don't support bilinear or convolution filters */ 575f29dbc25Smrg return FALSE; 576f29dbc25Smrg } 577f29dbc25Smrg 578f29dbc25Smrg /* We don't support any mask transforms */ 579f29dbc25Smrg if (pMsk && pMsk->transform) 580f29dbc25Smrg return FALSE; 581f29dbc25Smrg 582170d5fdcSmrg /* XXX - don't know if we can do any hwaccel on solid fills or gradient types */ 583170d5fdcSmrg if (pSrc->pSourcePict || (pMsk && pMsk->pSourcePict)) 584170d5fdcSmrg return FALSE; 585170d5fdcSmrg 586f29dbc25Smrg /* Keep an eye out for source rotation transforms - those we can 587f29dbc25Smrg * do something about */ 588f29dbc25Smrg 589f29dbc25Smrg exaScratch.rotate = RR_Rotate_0; 590f29dbc25Smrg exaScratch.transform = NULL; 591f29dbc25Smrg 592f29dbc25Smrg if (pSrc->transform && !lx_process_transform(pSrc)) 593f29dbc25Smrg return FALSE; 594f29dbc25Smrg 595f29dbc25Smrg /* XXX - I don't understand PICT_a8 enough - so I'm punting */ 596f29dbc25Smrg 597170d5fdcSmrg if ((op != PictOpAdd) && (pSrc->format == PICT_a8 || 598170d5fdcSmrg pDst->format == PICT_a8)) 599f29dbc25Smrg return FALSE; 600f29dbc25Smrg 601f29dbc25Smrg if (pMsk && op != PictOpClear) { 602170d5fdcSmrg struct blend_ops_t *opPtr = &lx_alpha_ops[op * 2]; 603170d5fdcSmrg int direction = (opPtr->channel == CIMGP_CHANNEL_A_SOURCE) ? 0 : 1; 604170d5fdcSmrg 605170d5fdcSmrg /* Direction 0 indicates src->dst, 1 indiates dst->src */ 606170d5fdcSmrg if (((direction == 0) && (pSrc->pDrawable->bitsPerPixel < 16)) || 607170d5fdcSmrg ((direction == 1) && (pDst->pDrawable->bitsPerPixel < 16))) { 608170d5fdcSmrg ErrorF("Can't do mask blending with less then 16bpp\n"); 609170d5fdcSmrg return FALSE; 610170d5fdcSmrg } 611f29dbc25Smrg /* We can only do masks with a 8bpp or a 4bpp mask */ 612f29dbc25Smrg if (pMsk->format != PICT_a8 && pMsk->format != PICT_a4) 613f29dbc25Smrg return FALSE; 614170d5fdcSmrg /* The pSrc should be 1x1 pixel if the pMsk is not zero */ 615170d5fdcSmrg if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) 616170d5fdcSmrg return FALSE; 617170d5fdcSmrg /* FIXME: In lx_prepare_composite, there are no variables to record the 618170d5fdcSmrg * one pixel source's width and height when the mask is not zero. 619170d5fdcSmrg * That will lead to bigger region to render instead of one pixel in lx 620170d5fdcSmrg * _do_composite, so we should fallback currently to avoid this */ 621170d5fdcSmrg if (!pSrc->repeat) 622170d5fdcSmrg return FALSE; 623f29dbc25Smrg } 624f29dbc25Smrg 625f29dbc25Smrg /* Get the formats for the source and destination */ 626f29dbc25Smrg 627f29dbc25Smrg if ((srcFmt = lx_get_format(pSrc)) == NULL) { 628f29dbc25Smrg ErrorF("EXA: Invalid source format %x\n", pSrc->format); 629f29dbc25Smrg return FALSE; 630f29dbc25Smrg } 631f29dbc25Smrg 632f29dbc25Smrg if ((dstFmt = lx_get_format(pDst)) == NULL) { 633f29dbc25Smrg ErrorF("EXA: Invalid destination format %x\n", pDst->format); 634f29dbc25Smrg return FALSE; 635f29dbc25Smrg } 636f29dbc25Smrg 637f29dbc25Smrg /* Make sure operations that need alpha bits have them */ 638f29dbc25Smrg /* If a mask is enabled, the alpha will come from there */ 639f29dbc25Smrg 640f29dbc25Smrg if (!pMsk && (!srcFmt->alphabits && usesSrcAlpha(op))) 641f29dbc25Smrg return FALSE; 642f29dbc25Smrg 643f29dbc25Smrg if (!pMsk && (!dstFmt->alphabits && usesDstAlpha(op))) 644f29dbc25Smrg return FALSE; 645f29dbc25Smrg 646f29dbc25Smrg /* FIXME: See a way around this! */ 647f29dbc25Smrg 648f29dbc25Smrg if (srcFmt->alphabits == 0 && dstFmt->alphabits != 0) 649f29dbc25Smrg return FALSE; 650f29dbc25Smrg 651f29dbc25Smrg /* If this is a rotate operation, then make sure the src and dst 652f29dbc25Smrg * formats are the same */ 653f29dbc25Smrg 654f29dbc25Smrg if (exaScratch.rotate != RR_Rotate_0 && srcFmt != dstFmt) { 655f29dbc25Smrg ErrorF("EXA: Can't rotate and convert formats at the same time\n"); 656f29dbc25Smrg return FALSE; 657f29dbc25Smrg } 658170d5fdcSmrg return TRUE; 659170d5fdcSmrg} 660170d5fdcSmrg 661170d5fdcSmrgstatic Bool 662170d5fdcSmrglx_prepare_composite(int op, PicturePtr pSrc, PicturePtr pMsk, 663170d5fdcSmrg PicturePtr pDst, PixmapPtr pxSrc, PixmapPtr pxMsk, PixmapPtr pxDst) 664170d5fdcSmrg{ 665170d5fdcSmrg GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); 666170d5fdcSmrg const struct exa_format_t *srcFmt, *dstFmt; 667170d5fdcSmrg 668170d5fdcSmrg /* Get the formats for the source and destination */ 669170d5fdcSmrg 670170d5fdcSmrg srcFmt = lx_get_format(pSrc); 671170d5fdcSmrg dstFmt = lx_get_format(pDst); 672f29dbc25Smrg 673f29dbc25Smrg /* Set up the scratch buffer with the information we need */ 674f29dbc25Smrg 675f29dbc25Smrg exaScratch.srcFormat = (struct exa_format_t *)srcFmt; 676f29dbc25Smrg exaScratch.dstFormat = (struct exa_format_t *)dstFmt; 677f29dbc25Smrg exaScratch.op = op; 678f29dbc25Smrg exaScratch.repeat = pSrc->repeat; 679f29dbc25Smrg exaScratch.bufferOffset = pGeode->exaBfrOffset; 680f29dbc25Smrg 681f29dbc25Smrg if (pMsk && op != PictOpClear) { 682f29dbc25Smrg /* Get the source color */ 683170d5fdcSmrg /* If the op is PictOpOver(or PictOpOutReverse, PictOpInReverse, 684170d5fdcSmrg * PictOpIn, PictOpOut, PictOpOverReverse), we should get the 685170d5fdcSmrg * ARGB32 source format */ 686170d5fdcSmrg 687170d5fdcSmrg if ((op == PictOpOver || op == PictOpOutReverse || op == 688170d5fdcSmrg PictOpInReverse || op == PictOpIn || op == PictOpOut || 689170d5fdcSmrg op == PictOpOverReverse) && (srcFmt->alphabits != 0)) 690170d5fdcSmrg exaScratch.srcColor = exaGetPixmapFirstPixel(pxSrc); 691170d5fdcSmrg else if ((op == PictOpOver || op == PictOpOutReverse || op == 692170d5fdcSmrg PictOpInReverse || op == PictOpIn || op == PictOpOut || 693170d5fdcSmrg op == PictOpOverReverse) && 694170d5fdcSmrg (srcFmt->alphabits == 0)) 695f29dbc25Smrg exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, 696170d5fdcSmrg PICT_a8r8g8b8); 697f29dbc25Smrg else 698170d5fdcSmrg exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, 699170d5fdcSmrg pDst->format); 700f29dbc25Smrg 701f29dbc25Smrg /* Save off the info we need (reuse the source values to save space) */ 702f29dbc25Smrg 703f29dbc25Smrg exaScratch.type = COMP_TYPE_MASK; 704170d5fdcSmrg exaScratch.maskrepeat = pMsk->repeat; 705f29dbc25Smrg 706f29dbc25Smrg exaScratch.srcOffset = exaGetPixmapOffset(pxMsk); 707f29dbc25Smrg exaScratch.srcPitch = exaGetPixmapPitch(pxMsk); 708f29dbc25Smrg exaScratch.srcBpp = (pxMsk->drawable.bitsPerPixel + 7) / 8; 709f29dbc25Smrg 710f29dbc25Smrg exaScratch.srcWidth = pMsk->pDrawable->width; 711f29dbc25Smrg exaScratch.srcHeight = pMsk->pDrawable->height; 712f29dbc25Smrg 713f29dbc25Smrg /* Flag to indicate if this a 8BPP or a 4BPP mask */ 714f29dbc25Smrg exaScratch.fourBpp = (pxMsk->drawable.bitsPerPixel == 4) ? 1 : 0; 715f29dbc25Smrg } else { 716f29dbc25Smrg if (usesPasses(op)) 717f29dbc25Smrg exaScratch.type = COMP_TYPE_TWOPASS; 718f29dbc25Smrg else if (exaScratch.rotate != RR_Rotate_0) 719f29dbc25Smrg exaScratch.type = COMP_TYPE_ROTATE; 720f29dbc25Smrg else 721f29dbc25Smrg exaScratch.type = COMP_TYPE_ONEPASS; 722f29dbc25Smrg 723f29dbc25Smrg exaScratch.srcOffset = exaGetPixmapOffset(pxSrc); 724f29dbc25Smrg exaScratch.srcPitch = exaGetPixmapPitch(pxSrc); 725f29dbc25Smrg exaScratch.srcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; 726f29dbc25Smrg 727f29dbc25Smrg exaScratch.srcWidth = pSrc->pDrawable->width; 728f29dbc25Smrg exaScratch.srcHeight = pSrc->pDrawable->height; 729f29dbc25Smrg } 730f29dbc25Smrg 731f29dbc25Smrg return TRUE; 732f29dbc25Smrg} 733f29dbc25Smrg 734f29dbc25Smrgstatic int 735f29dbc25Smrglx_get_bpp_from_format(int format) 736f29dbc25Smrg{ 737f29dbc25Smrg 738f29dbc25Smrg switch (format) { 739f29dbc25Smrg case CIMGP_SOURCE_FMT_8_8_8_8: 740f29dbc25Smrg case CIMGP_SOURCE_FMT_32BPP_BGR: 741f29dbc25Smrg return 32; 742f29dbc25Smrg 743f29dbc25Smrg case CIMGP_SOURCE_FMT_4_4_4_4: 744f29dbc25Smrg return 12; 745f29dbc25Smrg 746f29dbc25Smrg case CIMGP_SOURCE_FMT_0_5_6_5: 747f29dbc25Smrg case CIMGP_SOURCE_FMT_16BPP_BGR: 748f29dbc25Smrg return 16; 749f29dbc25Smrg 750f29dbc25Smrg case CIMGP_SOURCE_FMT_1_5_5_5: 751f29dbc25Smrg case CIMGP_SOURCE_FMT_15BPP_BGR: 752f29dbc25Smrg return 15; 753f29dbc25Smrg 754f29dbc25Smrg case CIMGP_SOURCE_FMT_3_3_2: 755f29dbc25Smrg return 8; 756f29dbc25Smrg } 757f29dbc25Smrg 758f29dbc25Smrg return 0; 759f29dbc25Smrg} 760f29dbc25Smrg 761f29dbc25Smrg/* BGR needs to be set in the source for it to take - so adjust the source 762f29dbc25Smrg * to enable BGR if the two formats are different, and disable it if they 763f29dbc25Smrg * are the same 764f29dbc25Smrg */ 765f29dbc25Smrg 766f29dbc25Smrgstatic void 767f29dbc25Smrglx_set_source_format(int srcFormat, int dstFormat) 768f29dbc25Smrg{ 769f29dbc25Smrg if (!(srcFormat & 0x10) && (dstFormat & 0x10)) 770f29dbc25Smrg gp_set_source_format(srcFormat | 0x10); 771f29dbc25Smrg else if ((srcFormat & 0x10) && (dstFormat & 0x10)) 772f29dbc25Smrg gp_set_source_format(srcFormat & ~0x10); 773f29dbc25Smrg else 774f29dbc25Smrg gp_set_source_format(srcFormat); 775f29dbc25Smrg} 776f29dbc25Smrg 777f29dbc25Smrg/* If we are converting colors and we need the channel A alpha, 778f29dbc25Smrg * then use a special alpha type that preserves the alpha before 779f29dbc25Smrg * converting the format 780f29dbc25Smrg */ 781f29dbc25Smrg 782f29dbc25Smrgstatic inline int 783f29dbc25Smrgget_op_type(struct exa_format_t *src, struct exa_format_t *dst, int type) 784f29dbc25Smrg{ 785f29dbc25Smrg return (type == CIMGP_CHANNEL_A_ALPHA && 786f29dbc25Smrg src->alphabits != dst->alphabits) ? CIMGP_CONVERTED_ALPHA : type; 787f29dbc25Smrg} 788f29dbc25Smrg 789f29dbc25Smrg/* Note - this is the preferred onepass method. The other will remain 790f29dbc25Smrg * ifdefed out until such time that we are sure its not needed 791f29dbc25Smrg */ 792f29dbc25Smrg 793170d5fdcSmrg#define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \ 794170d5fdcSmrg (exaGetPixmapPitch((px)) * (y)) + \ 795170d5fdcSmrg ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) ) 796170d5fdcSmrg 797170d5fdcSmrg#define GetSrcOffset(_x, _y) (exaScratch.srcOffset + ((_y) * exaScratch.srcPitch) + \ 798170d5fdcSmrg ((_x) * exaScratch.srcBpp)) 799170d5fdcSmrg 800170d5fdcSmrgstatic void 801170d5fdcSmrglx_composite_onepass_add_a8(PixmapPtr pxDst, unsigned long dstOffset, 802170d5fdcSmrg unsigned long srcOffset, int width, int height, int opX, int opY, 803170d5fdcSmrg int srcX, int srcY) 804170d5fdcSmrg{ 805170d5fdcSmrg struct blend_ops_t *opPtr; 806170d5fdcSmrg int apply, type; 807170d5fdcSmrg int optempX, optempY; 808170d5fdcSmrg int i, j; 809170d5fdcSmrg unsigned long pixmapOffset, pixmapPitch, calBitsPixel; 810170d5fdcSmrg 811170d5fdcSmrg pixmapOffset = exaGetPixmapOffset(pxDst); 812170d5fdcSmrg pixmapPitch = exaGetPixmapPitch(pxDst); 813170d5fdcSmrg calBitsPixel = (pxDst->drawable.bitsPerPixel + 7) / 8; 814170d5fdcSmrg 815170d5fdcSmrg /* Keep this GP idle judge here. Otherwise the SW method has chance to 816170d5fdcSmrg * conflict with the HW rendering method */ 817170d5fdcSmrg gp_wait_until_idle(); 818170d5fdcSmrg 819170d5fdcSmrg if (opX % 4 == 0 && srcX % 4 == 0) { 820170d5fdcSmrg /* HW acceleration */ 821170d5fdcSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 822170d5fdcSmrg apply = CIMGP_APPLY_BLEND_TO_ALL; 823170d5fdcSmrg gp_declare_blt(0); 824170d5fdcSmrg gp_set_bpp(32); 825170d5fdcSmrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 826170d5fdcSmrg gp_set_source_format(8); 827170d5fdcSmrg type = opPtr->type; 828170d5fdcSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 829170d5fdcSmrg gp_screen_to_screen_convert(dstOffset, srcOffset, width / 4, height, 0); 830170d5fdcSmrg /* Calculate the pixels in the tail of each line */ 831170d5fdcSmrg for (j = srcY; j < srcY + height; j++) 832170d5fdcSmrg for (i = srcX + (width / 4) * 4; i < srcX + width; i++) { 833170d5fdcSmrg srcOffset = GetSrcOffset(i, j); 834170d5fdcSmrg optempX = opX + i - srcX; 835170d5fdcSmrg optempY = opY + j - srcY; 836170d5fdcSmrg dstOffset = pixmapOffset + pixmapPitch * optempY + 837170d5fdcSmrg calBitsPixel * optempX; 838170d5fdcSmrg *(cim_fb_ptr + dstOffset) = (*(cim_fb_ptr + srcOffset) 839170d5fdcSmrg + *(cim_fb_ptr + dstOffset) <= 0xff) ? 840170d5fdcSmrg *(cim_fb_ptr + srcOffset) + *(cim_fb_ptr + dstOffset) : 0xff; 841170d5fdcSmrg } 842170d5fdcSmrg } else { 843170d5fdcSmrg for (j = srcY; j < srcY + height; j++) 844170d5fdcSmrg for (i = srcX; i < srcX + width; i++) { 845170d5fdcSmrg srcOffset = GetSrcOffset(i, j); 846170d5fdcSmrg optempX = opX + i - srcX; 847170d5fdcSmrg optempY = opY + j - srcY; 848170d5fdcSmrg dstOffset = pixmapOffset + pixmapPitch * optempY + 849170d5fdcSmrg calBitsPixel * optempX; 850170d5fdcSmrg *(cim_fb_ptr + dstOffset) = (*(cim_fb_ptr + srcOffset) + 851170d5fdcSmrg *(cim_fb_ptr + dstOffset) <= 0xff) ? 852170d5fdcSmrg *(cim_fb_ptr + srcOffset) + *(cim_fb_ptr + dstOffset) : 0xff; 853170d5fdcSmrg } 854170d5fdcSmrg } 855170d5fdcSmrg} 856170d5fdcSmrg 857f29dbc25Smrgstatic void 858f29dbc25Smrglx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset, 859f29dbc25Smrg unsigned long srcOffset, int width, int height) 860f29dbc25Smrg{ 861f29dbc25Smrg struct blend_ops_t *opPtr; 862f29dbc25Smrg int apply, type; 863f29dbc25Smrg 864f29dbc25Smrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 865f29dbc25Smrg 866f29dbc25Smrg apply = (exaScratch.dstFormat->alphabits != 0 && 867f29dbc25Smrg exaScratch.srcFormat->alphabits != 0) ? 868f29dbc25Smrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 869f29dbc25Smrg 870f29dbc25Smrg gp_declare_blt(0); 871f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 872f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 873f29dbc25Smrg 874f29dbc25Smrg lx_set_source_format(exaScratch.srcFormat->fmt, 875f29dbc25Smrg exaScratch.dstFormat->fmt); 876f29dbc25Smrg 877f29dbc25Smrg type = 878f29dbc25Smrg get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type); 879f29dbc25Smrg 880f29dbc25Smrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 881f29dbc25Smrg 882f29dbc25Smrg gp_screen_to_screen_convert(dstOffset, srcOffset, width, height, 0); 883f29dbc25Smrg} 884f29dbc25Smrg 885170d5fdcSmrgstatic void 886170d5fdcSmrglx_composite_all_black(unsigned long srcOffset, int width, int height) 887170d5fdcSmrg{ 888170d5fdcSmrg struct blend_ops_t *opPtr; 889170d5fdcSmrg int apply, type; 890170d5fdcSmrg 891170d5fdcSmrg opPtr = &lx_alpha_ops[0]; 892170d5fdcSmrg apply = (exaScratch.srcFormat->alphabits != 0) ? 893170d5fdcSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 894170d5fdcSmrg gp_declare_blt(0); 895170d5fdcSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.srcFormat->fmt)); 896170d5fdcSmrg gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch); 897170d5fdcSmrg lx_set_source_format(exaScratch.srcFormat->fmt, 898170d5fdcSmrg exaScratch.srcFormat->fmt); 899170d5fdcSmrg type = 900170d5fdcSmrg get_op_type(exaScratch.srcFormat, exaScratch.srcFormat, opPtr->type); 901170d5fdcSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 902170d5fdcSmrg gp_screen_to_screen_convert(srcOffset, srcOffset, width, height, 0); 903170d5fdcSmrg 904170d5fdcSmrg} 905170d5fdcSmrg 906170d5fdcSmrgstatic void 907170d5fdcSmrglx_composite_onepass_special(PixmapPtr pxDst, int width, int height, int opX, 908170d5fdcSmrg int opY, int srcX, int srcY) 909170d5fdcSmrg{ 910170d5fdcSmrg struct blend_ops_t *opPtr; 911170d5fdcSmrg int apply, type; 912170d5fdcSmrg int opWidth, opHeight; 913170d5fdcSmrg int optempX, optempY; 914170d5fdcSmrg unsigned int dstOffset, srcOffset = 0; 915170d5fdcSmrg 916170d5fdcSmrg optempX = opX; 917170d5fdcSmrg optempY = opY; 918170d5fdcSmrg 919170d5fdcSmrg /* Make sure srcX and srcY are in source region */ 920170d5fdcSmrg srcX = ((srcX % (int)exaScratch.srcWidth) + (int)exaScratch.srcWidth) 921170d5fdcSmrg % (int)exaScratch.srcWidth; 922170d5fdcSmrg srcY = ((srcY % (int)exaScratch.srcHeight) + (int)exaScratch.srcHeight) 923170d5fdcSmrg % (int)exaScratch.srcHeight; 924170d5fdcSmrg 925170d5fdcSmrg opWidth = exaScratch.srcWidth - srcX; 926170d5fdcSmrg opHeight = exaScratch.srcHeight - srcY; 927170d5fdcSmrg 928170d5fdcSmrg srcOffset = GetSrcOffset(srcX, srcY); 929170d5fdcSmrg 930170d5fdcSmrg if (width < opWidth) 931170d5fdcSmrg opWidth = width; 932170d5fdcSmrg if (height < opHeight) 933170d5fdcSmrg opHeight = height; 934170d5fdcSmrg 935170d5fdcSmrg while (1) { 936170d5fdcSmrg gp_wait_until_idle(); 937170d5fdcSmrg dstOffset = GetPixmapOffset(pxDst, optempX, optempY); 938170d5fdcSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 939170d5fdcSmrg apply = (exaScratch.dstFormat->alphabits != 0 && 940170d5fdcSmrg exaScratch.srcFormat->alphabits != 0) ? 941170d5fdcSmrg CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB; 942170d5fdcSmrg gp_declare_blt(0); 943170d5fdcSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 944170d5fdcSmrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 945170d5fdcSmrg lx_set_source_format(exaScratch.srcFormat->fmt, 946170d5fdcSmrg exaScratch.dstFormat->fmt); 947170d5fdcSmrg type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, 948170d5fdcSmrg opPtr->type); 949170d5fdcSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, 950170d5fdcSmrg apply, 0); 951170d5fdcSmrg gp_screen_to_screen_convert(dstOffset, srcOffset, opWidth, opHeight, 0); 952170d5fdcSmrg 953170d5fdcSmrg optempX += opWidth; 954170d5fdcSmrg if (optempX >= opX + width) { 955170d5fdcSmrg optempX = opX; 956170d5fdcSmrg optempY += opHeight; 957170d5fdcSmrg if (optempY >= opY + height) 958170d5fdcSmrg break; 959170d5fdcSmrg } 960170d5fdcSmrg if (optempX == opX) { 961170d5fdcSmrg srcOffset = GetSrcOffset(srcX, 0); 962170d5fdcSmrg opWidth = ((opX + width) - optempX) > (exaScratch.srcWidth - srcX) 963170d5fdcSmrg ? (exaScratch.srcWidth - srcX) : ((opX + width) - optempX); 964170d5fdcSmrg opHeight = ((opY + height) - optempY) > exaScratch.srcHeight 965170d5fdcSmrg ? exaScratch.srcHeight : ((opY + height) - optempY); 966170d5fdcSmrg } else if (optempY == opY) { 967170d5fdcSmrg srcOffset = GetSrcOffset(0, srcY); 968170d5fdcSmrg opWidth = ((opX + width) - optempX) > exaScratch.srcWidth 969170d5fdcSmrg ? exaScratch.srcWidth : ((opX + width) - optempX); 970170d5fdcSmrg opHeight = ((opY + height) - optempY) > (exaScratch.srcHeight - 971170d5fdcSmrg srcY) ? (exaScratch.srcHeight - srcY) : ((opY + height) - optempY); 972170d5fdcSmrg } else { 973170d5fdcSmrg srcOffset = GetSrcOffset(0, 0); 974170d5fdcSmrg opWidth = ((opX + width) - optempX) > exaScratch.srcWidth 975170d5fdcSmrg ? exaScratch.srcWidth : ((opX + width) - optempX); 976170d5fdcSmrg opHeight = ((opY + height) - optempY) > exaScratch.srcHeight 977170d5fdcSmrg ? exaScratch.srcHeight : ((opY + height) - optempY); 978170d5fdcSmrg } 979170d5fdcSmrg } 980170d5fdcSmrg} 981170d5fdcSmrg 982f29dbc25Smrg/* This function handles the multipass blend functions */ 983f29dbc25Smrg 984f29dbc25Smrgstatic void 985f29dbc25Smrglx_composite_multipass(PixmapPtr pxDst, unsigned long dstOffset, 986f29dbc25Smrg unsigned long srcOffset, int width, int height) 987f29dbc25Smrg{ 988f29dbc25Smrg struct blend_ops_t *opPtr; 989f29dbc25Smrg int sbpp = lx_get_bpp_from_format(exaScratch.srcFormat->fmt); 990f29dbc25Smrg int apply, type; 991f29dbc25Smrg 992f29dbc25Smrg /* Wait until the GP is idle - this will ensure that the scratch buffer 993f29dbc25Smrg * isn't occupied */ 994f29dbc25Smrg 995f29dbc25Smrg gp_wait_until_idle(); 996f29dbc25Smrg 997f29dbc25Smrg /* Copy the destination to the scratch buffer, and convert it to the 998f29dbc25Smrg * source format */ 999f29dbc25Smrg 1000f29dbc25Smrg gp_declare_blt(0); 1001f29dbc25Smrg 1002f29dbc25Smrg gp_set_bpp(sbpp); 1003f29dbc25Smrg gp_set_source_format(exaScratch.dstFormat->fmt); 1004f29dbc25Smrg gp_set_raster_operation(0xCC); 1005f29dbc25Smrg gp_set_strides(exaScratch.srcPitch, exaGetPixmapPitch(pxDst)); 1006f29dbc25Smrg gp_screen_to_screen_convert(exaScratch.bufferOffset, dstOffset, 1007f29dbc25Smrg width, height, 0); 1008f29dbc25Smrg 1009f29dbc25Smrg /* Do the first blend from the source to the scratch buffer */ 1010f29dbc25Smrg 1011f29dbc25Smrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1012f29dbc25Smrg gp_set_bpp(sbpp); 1013f29dbc25Smrg gp_set_source_format(exaScratch.srcFormat->fmt); 1014f29dbc25Smrg gp_set_strides(exaScratch.srcPitch, exaScratch.srcPitch); 1015f29dbc25Smrg 1016f29dbc25Smrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1017f29dbc25Smrg 1018f29dbc25Smrg apply = (exaScratch.srcFormat->alphabits == 0) ? 1019f29dbc25Smrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1020f29dbc25Smrg 1021f29dbc25Smrg /* If we're destroying the source alpha bits, then make sure we 1022f29dbc25Smrg * use the alpha before the color conversion 1023f29dbc25Smrg */ 1024f29dbc25Smrg 1025f29dbc25Smrg gp_screen_to_screen_blt(exaScratch.bufferOffset, srcOffset, width, height, 1026f29dbc25Smrg 0); 1027f29dbc25Smrg 1028f29dbc25Smrg /* Finally, do the second blend back to the destination */ 1029f29dbc25Smrg 1030f29dbc25Smrg opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; 1031f29dbc25Smrg 1032f29dbc25Smrg apply = (exaScratch.dstFormat->alphabits == 0) ? 1033f29dbc25Smrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1034f29dbc25Smrg 1035f29dbc25Smrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1036f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1037f29dbc25Smrg 1038f29dbc25Smrg lx_set_source_format(exaScratch.srcFormat->fmt, 1039f29dbc25Smrg exaScratch.dstFormat->fmt); 1040f29dbc25Smrg 1041f29dbc25Smrg type = 1042f29dbc25Smrg get_op_type(exaScratch.srcFormat, exaScratch.dstFormat, opPtr->type); 1043f29dbc25Smrg 1044f29dbc25Smrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); 1045f29dbc25Smrg 1046f29dbc25Smrg gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, 1047f29dbc25Smrg width, height, 0); 1048f29dbc25Smrg} 1049f29dbc25Smrg 1050f29dbc25Smrgstatic void 1051f29dbc25Smrglx_composite_rotate(PixmapPtr pxDst, unsigned long dstOffset, 1052f29dbc25Smrg unsigned int srcOffset, int width, int height) 1053f29dbc25Smrg{ 1054f29dbc25Smrg int degrees = 0; 1055f29dbc25Smrg 1056f29dbc25Smrg gp_declare_blt(0); 1057f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1058f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 1059f29dbc25Smrg 1060f29dbc25Smrg lx_set_source_format(exaScratch.srcFormat->fmt, 1061f29dbc25Smrg exaScratch.dstFormat->fmt); 1062f29dbc25Smrg 1063f29dbc25Smrg gp_set_raster_operation(0xCC); 1064f29dbc25Smrg 1065f29dbc25Smrg /* RandR rotation is counter-clockwise, our rotation 1066f29dbc25Smrg * is clockwise, so adjust the numbers accordingly */ 1067f29dbc25Smrg 1068f29dbc25Smrg switch (exaScratch.rotate) { 1069f29dbc25Smrg case RR_Rotate_90: 1070f29dbc25Smrg degrees = 270; 1071f29dbc25Smrg break; 1072f29dbc25Smrg case RR_Rotate_180: 1073f29dbc25Smrg degrees = 180; 1074f29dbc25Smrg break; 1075f29dbc25Smrg case RR_Rotate_270: 1076f29dbc25Smrg degrees = 90; 1077f29dbc25Smrg break; 1078f29dbc25Smrg } 1079f29dbc25Smrg 1080f29dbc25Smrg gp_rotate_blt(dstOffset, srcOffset, width, height, degrees); 1081f29dbc25Smrg} 1082f29dbc25Smrg 1083f29dbc25Smrgstatic void 1084f29dbc25Smrglx_do_composite_mask(PixmapPtr pxDst, unsigned long dstOffset, 1085f29dbc25Smrg unsigned int maskOffset, int width, int height) 1086f29dbc25Smrg{ 1087f29dbc25Smrg struct blend_ops_t *opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1088f29dbc25Smrg 1089f29dbc25Smrg gp_declare_blt(0); 1090f29dbc25Smrg 1091f29dbc25Smrg gp_set_source_format(exaScratch.srcFormat->fmt); 1092f29dbc25Smrg gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch); 1093f29dbc25Smrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1094f29dbc25Smrg gp_set_solid_source(exaScratch.srcColor); 1095f29dbc25Smrg 1096f29dbc25Smrg gp_blend_mask_blt(dstOffset, 0, width, height, maskOffset, 1097f29dbc25Smrg exaScratch.srcPitch, opPtr->operation, exaScratch.fourBpp); 1098f29dbc25Smrg} 1099f29dbc25Smrg 1100170d5fdcSmrgstatic void 1101170d5fdcSmrglx_do_composite_mask_two_pass(PixmapPtr pxDst, unsigned long dstOffset, 1102170d5fdcSmrg unsigned int maskOffset, int width, int height, int opX, int opY, 1103170d5fdcSmrg xPointFixed srcPoint) 1104170d5fdcSmrg{ 1105170d5fdcSmrg int apply, type; 1106170d5fdcSmrg struct blend_ops_t *opPtr; 1107170d5fdcSmrg int opWidth, opHeight; 1108170d5fdcSmrg int opoverX, opoverY; 1109170d5fdcSmrg 1110170d5fdcSmrg opoverX = opX; 1111170d5fdcSmrg opoverY = opY; 1112170d5fdcSmrg 1113170d5fdcSmrg /* The rendering region should not be bigger than off-screen memory size 1114170d5fdcSmrg * which equals to DEFAULT_EXA_SCRATCH_BFRSZ. If that happens, we split 1115170d5fdcSmrg * the PictOpOver rendering region into several 256KB chunks. And because 1116170d5fdcSmrg * of the Pitch(stride) parameter, so we use maximun width of mask picture. 1117170d5fdcSmrg * that is to say it is a scanline rendering process */ 1118170d5fdcSmrg if (width * height * 4 > DEFAULT_EXA_SCRATCH_BFRSZ) { 1119170d5fdcSmrg opWidth = width; 1120170d5fdcSmrg opHeight = DEFAULT_EXA_SCRATCH_BFRSZ / (width * 4); 1121170d5fdcSmrg } else { 1122170d5fdcSmrg opWidth = width; 1123170d5fdcSmrg opHeight = height; 1124170d5fdcSmrg } 1125f29dbc25Smrg 1126170d5fdcSmrg while (1) { 1127170d5fdcSmrg 1128170d5fdcSmrg /* Wait until the GP is idle - this will ensure that the scratch buffer 1129170d5fdcSmrg * isn't occupied */ 1130170d5fdcSmrg 1131170d5fdcSmrg gp_wait_until_idle(); 1132170d5fdcSmrg 1133170d5fdcSmrg /* Copy the source to the scratch buffer, and do a src * mask raster 1134170d5fdcSmrg * operation */ 1135170d5fdcSmrg 1136170d5fdcSmrg gp_declare_blt(0); 1137170d5fdcSmrg opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; 1138170d5fdcSmrg gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); 1139170d5fdcSmrg gp_set_strides(opWidth * 4, exaScratch.srcPitch); 1140170d5fdcSmrg gp_set_bpp(lx_get_bpp_from_format(CIMGP_SOURCE_FMT_8_8_8_8)); 1141170d5fdcSmrg gp_set_solid_source(exaScratch.srcColor); 1142170d5fdcSmrg gp_blend_mask_blt(exaScratch.bufferOffset, 0, opWidth, opHeight, 1143170d5fdcSmrg maskOffset, exaScratch.srcPitch, opPtr->operation, 1144170d5fdcSmrg exaScratch.fourBpp); 1145170d5fdcSmrg 1146170d5fdcSmrg /* Do a relative operation(refer rendercheck ops.c), and copy the 1147170d5fdcSmrg * operation result to destination */ 1148170d5fdcSmrg 1149170d5fdcSmrg gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); 1150170d5fdcSmrg opPtr = &lx_alpha_ops[exaScratch.op * 2]; 1151170d5fdcSmrg apply = (exaScratch.dstFormat->alphabits == 0) ? 1152170d5fdcSmrg CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; 1153170d5fdcSmrg gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); 1154170d5fdcSmrg gp_set_strides(exaGetPixmapPitch(pxDst), opWidth * 4); 1155170d5fdcSmrg gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); 1156170d5fdcSmrg type = CIMGP_CONVERTED_ALPHA; 1157170d5fdcSmrg gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, 1158170d5fdcSmrg apply, 0); 1159170d5fdcSmrg gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, 1160170d5fdcSmrg opWidth, opHeight, 0); 1161170d5fdcSmrg 1162170d5fdcSmrg if (width * height * 4 > DEFAULT_EXA_SCRATCH_BFRSZ) { 1163170d5fdcSmrg /* Finish the rendering */ 1164170d5fdcSmrg if (opoverY + opHeight == opY + height) 1165170d5fdcSmrg break; 1166170d5fdcSmrg /* Recalculate the Dest and Mask rendering start point */ 1167170d5fdcSmrg srcPoint.y = srcPoint.y + F(opHeight); 1168170d5fdcSmrg opoverY = opoverY + opHeight; 1169170d5fdcSmrg if (opoverY + opHeight > opY + height) 1170170d5fdcSmrg opHeight = opY + height - opoverY; 1171170d5fdcSmrg dstOffset = GetPixmapOffset(pxDst, opoverX, opoverY); 1172170d5fdcSmrg maskOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); 1173170d5fdcSmrg } else 1174170d5fdcSmrg break; 1175170d5fdcSmrg } 1176170d5fdcSmrg} 1177f29dbc25Smrg 1178f29dbc25Smrgstatic void 1179f29dbc25SmrgtransformPoint(PictTransform * t, xPointFixed * point) 1180f29dbc25Smrg{ 1181f29dbc25Smrg PictVector v; 1182f29dbc25Smrg 1183f29dbc25Smrg v.vector[0] = point->x; 1184f29dbc25Smrg v.vector[1] = point->y; 1185f29dbc25Smrg v.vector[2] = xFixed1; 1186f29dbc25Smrg 1187f29dbc25Smrg if (t != NULL) 1188f29dbc25Smrg PictureTransformPoint(t, &v); 1189f29dbc25Smrg 1190f29dbc25Smrg point->x = v.vector[0]; 1191f29dbc25Smrg point->y = v.vector[1]; 1192f29dbc25Smrg} 1193f29dbc25Smrg 1194f29dbc25Smrgstatic void 1195f29dbc25Smrglx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX, 1196f29dbc25Smrg int maskY, int dstX, int dstY, int width, int height) 1197f29dbc25Smrg{ 1198f29dbc25Smrg unsigned int dstOffset, srcOffset = 0; 1199f29dbc25Smrg 1200f29dbc25Smrg xPointFixed srcPoint; 1201f29dbc25Smrg 1202f29dbc25Smrg int opX = dstX; 1203f29dbc25Smrg int opY = dstY; 1204f29dbc25Smrg int opWidth = width; 1205f29dbc25Smrg int opHeight = height; 1206f29dbc25Smrg 1207f29dbc25Smrg /* Transform the source coordinates */ 1208f29dbc25Smrg 1209f29dbc25Smrg if (exaScratch.type == COMP_TYPE_MASK) { 1210f29dbc25Smrg srcPoint.x = F(maskX); 1211f29dbc25Smrg srcPoint.y = F(maskY); 1212f29dbc25Smrg } else { 1213f29dbc25Smrg srcPoint.x = F(srcX); 1214f29dbc25Smrg srcPoint.y = F(srcY); 1215f29dbc25Smrg } 1216f29dbc25Smrg 1217f29dbc25Smrg /* srcX, srcY point to the upper right side of the bounding box 1218f29dbc25Smrg * in the unrotated coordinate space. Depending on the orientation, 1219f29dbc25Smrg * we have to translate the coordinates to point to the origin of 1220f29dbc25Smrg * the rectangle in the source pixmap */ 1221f29dbc25Smrg 1222f29dbc25Smrg switch (exaScratch.rotate) { 1223f29dbc25Smrg case RR_Rotate_270: 1224f29dbc25Smrg srcPoint.x += F(width); 1225f29dbc25Smrg 1226f29dbc25Smrg opWidth = height; 1227f29dbc25Smrg opHeight = width; 1228f29dbc25Smrg break; 1229f29dbc25Smrg 1230f29dbc25Smrg case RR_Rotate_180: 1231f29dbc25Smrg srcPoint.x += F(width); 1232f29dbc25Smrg srcPoint.y += F(height); 1233f29dbc25Smrg 1234f29dbc25Smrg srcX += width; 1235f29dbc25Smrg srcY += height; 1236f29dbc25Smrg break; 1237f29dbc25Smrg 1238f29dbc25Smrg case RR_Rotate_90: 1239f29dbc25Smrg srcPoint.y += F(height); 1240f29dbc25Smrg 1241f29dbc25Smrg opWidth = height; 1242f29dbc25Smrg opHeight = width; 1243f29dbc25Smrg break; 1244f29dbc25Smrg } 1245f29dbc25Smrg 1246f29dbc25Smrg transformPoint(exaScratch.transform, &srcPoint); 1247f29dbc25Smrg 1248f29dbc25Smrg /* Adjust the point to fit into the pixmap */ 1249f29dbc25Smrg 1250f29dbc25Smrg if (I(srcPoint.x) < 0) { 1251f29dbc25Smrg opWidth += I(srcPoint.x); 1252f29dbc25Smrg srcPoint.x = F(0); 1253f29dbc25Smrg } 1254f29dbc25Smrg 1255f29dbc25Smrg if (I(srcPoint.y) < 0) { 1256f29dbc25Smrg opHeight += I(srcPoint.y); 1257f29dbc25Smrg srcPoint.y = F(0); 1258f29dbc25Smrg } 1259f29dbc25Smrg 1260170d5fdcSmrg /* Get the source point offset position */ 1261170d5fdcSmrg 1262f29dbc25Smrg srcOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); 1263f29dbc25Smrg 1264170d5fdcSmrg /* When mask exists, exaScratch.srcWidth and exaScratch.srcHeight are 1265170d5fdcSmrg * the source width and source height; Otherwise, they are mask width 1266170d5fdcSmrg * and mask height */ 1267170d5fdcSmrg /* exaScratch.repeat is the source repeat attribute 1268170d5fdcSmrg * exaScratch.maskrepeat is the mask repeat attribute */ 1269170d5fdcSmrg /* If type is COMP_TYPE_MASK, maskX and maskY are not zero, we should 1270170d5fdcSmrg * subtract them to do the operation in the correct region */ 1271f29dbc25Smrg 1272170d5fdcSmrg /* FIXME: Please add the code to handle the condition when the maskX 1273170d5fdcSmrg * and maskY coordinate are negative or greater than 1274170d5fdcSmrg * exaScratch.srcWidth and exaScratch.srcHeight */ 1275170d5fdcSmrg 1276170d5fdcSmrg if (exaScratch.type == COMP_TYPE_MASK) { 1277170d5fdcSmrg if ((exaScratch.srcWidth - maskX) < opWidth) 1278170d5fdcSmrg opWidth = exaScratch.srcWidth - maskX; 1279170d5fdcSmrg if ((exaScratch.srcHeight - maskY) < opHeight) 1280170d5fdcSmrg opHeight = exaScratch.srcHeight - maskY; 1281170d5fdcSmrg } else { 1282170d5fdcSmrg if (exaScratch.type == COMP_TYPE_ONEPASS) { 1283170d5fdcSmrg /* This is the condition srcX or/and srcY is/are out of source 1284170d5fdcSmrg * region */ 1285170d5fdcSmrg if (((srcX >= 0 && srcY >= exaScratch.srcHeight) 1286170d5fdcSmrg || (srcX >= exaScratch.srcWidth && srcY >= 0)) && 1287170d5fdcSmrg (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) { 1288170d5fdcSmrg if (exaScratch.repeat == 1) { 1289170d5fdcSmrg opWidth = width; 1290170d5fdcSmrg opHeight = height; 1291170d5fdcSmrg } else { 1292170d5fdcSmrg if (exaScratch.op == PictOpOver) 1293170d5fdcSmrg return ; 1294170d5fdcSmrg else { 1295170d5fdcSmrg exaScratch.op = PictOpClear; 1296170d5fdcSmrg opWidth = width; 1297170d5fdcSmrg opHeight = height; 1298170d5fdcSmrg } 1299170d5fdcSmrg } 1300170d5fdcSmrg /* This is the condition srcX or/and srcY is/are in the source 1301170d5fdcSmrg * region */ 1302170d5fdcSmrg } else if (srcX >= 0 && srcY >= 0 && 1303170d5fdcSmrg (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) { 1304170d5fdcSmrg if (exaScratch.repeat == 1) { 1305170d5fdcSmrg opWidth = width; 1306170d5fdcSmrg opHeight = height; 1307170d5fdcSmrg } else { 1308170d5fdcSmrg if ((exaScratch.srcWidth - srcX) < opWidth) 1309170d5fdcSmrg opWidth = exaScratch.srcWidth - srcX; 1310170d5fdcSmrg if ((exaScratch.srcHeight - srcY) < opHeight) 1311170d5fdcSmrg opHeight = exaScratch.srcHeight - srcY; 1312170d5fdcSmrg } 1313170d5fdcSmrg /* This is the condition srcX or/and srcY is/are negative */ 1314170d5fdcSmrg } else if ((srcX < 0 || srcY < 0) && 1315170d5fdcSmrg (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) { 1316170d5fdcSmrg if (exaScratch.repeat == 1) { 1317170d5fdcSmrg opWidth = width; 1318170d5fdcSmrg opHeight = height; 1319170d5fdcSmrg } else { 1320170d5fdcSmrg /* Have not met this condition till now */ 1321170d5fdcSmrg return ; 1322170d5fdcSmrg } 1323170d5fdcSmrg } else { 1324170d5fdcSmrg if (exaScratch.srcWidth < opWidth) 1325170d5fdcSmrg opWidth = exaScratch.srcWidth; 1326170d5fdcSmrg if (exaScratch.srcHeight < opHeight) 1327170d5fdcSmrg opHeight = exaScratch.srcHeight; 1328170d5fdcSmrg } 1329170d5fdcSmrg } else { 1330170d5fdcSmrg if (exaScratch.rotate == RR_Rotate_180) { 1331170d5fdcSmrg } else { 1332170d5fdcSmrg if ((exaScratch.srcWidth - srcY) < opWidth) 1333170d5fdcSmrg opWidth = exaScratch.srcWidth - srcY; 1334170d5fdcSmrg if ((exaScratch.srcHeight - srcX) < opHeight) 1335170d5fdcSmrg opHeight = exaScratch.srcHeight - srcX; 1336170d5fdcSmrg } 1337170d5fdcSmrg } 1338170d5fdcSmrg } 1339f29dbc25Smrg 1340f29dbc25Smrg while (1) { 1341f29dbc25Smrg 1342f29dbc25Smrg dstOffset = GetPixmapOffset(pxDst, opX, opY); 1343f29dbc25Smrg 1344f29dbc25Smrg switch (exaScratch.type) { 1345f29dbc25Smrg 1346f29dbc25Smrg case COMP_TYPE_MASK:{ 1347170d5fdcSmrg if (exaScratch.op == PictOpOver || exaScratch.op == 1348170d5fdcSmrg PictOpOutReverse || exaScratch.op == PictOpInReverse || 1349170d5fdcSmrg exaScratch.op == PictOpIn || exaScratch.op == PictOpOut || 1350170d5fdcSmrg exaScratch.op == PictOpOverReverse) 1351170d5fdcSmrg lx_do_composite_mask_two_pass(pxDst, dstOffset, 1352170d5fdcSmrg srcOffset, opWidth, opHeight, opX, opY, srcPoint); 1353170d5fdcSmrg else 1354170d5fdcSmrg lx_do_composite_mask(pxDst, dstOffset, srcOffset, 1355170d5fdcSmrg opWidth, opHeight); 1356f29dbc25Smrg } 1357f29dbc25Smrg break; 1358f29dbc25Smrg 1359f29dbc25Smrg case COMP_TYPE_ONEPASS: 1360170d5fdcSmrg if ((exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc) 1361170d5fdcSmrg && (exaScratch.repeat == 1)) { 1362170d5fdcSmrg lx_composite_onepass_special(pxDst, opWidth, opHeight, opX, opY, 1363170d5fdcSmrg srcX, srcY); 1364170d5fdcSmrg return ; 1365170d5fdcSmrg } else if ((exaScratch.op == PictOpAdd) && (exaScratch.srcFormat->exa 1366170d5fdcSmrg == PICT_a8) && (exaScratch.dstFormat->exa == PICT_a8)) 1367170d5fdcSmrg lx_composite_onepass_add_a8(pxDst, dstOffset, srcOffset, 1368170d5fdcSmrg opWidth, opHeight, opX, opY, srcX, srcY); 1369170d5fdcSmrg else 1370170d5fdcSmrg lx_composite_onepass(pxDst, dstOffset, srcOffset, opWidth, 1371170d5fdcSmrg opHeight); 1372f29dbc25Smrg break; 1373f29dbc25Smrg 1374f29dbc25Smrg case COMP_TYPE_TWOPASS: 1375f29dbc25Smrg lx_composite_multipass(pxDst, dstOffset, srcOffset, opWidth, 1376f29dbc25Smrg opHeight); 1377f29dbc25Smrg 1378f29dbc25Smrg case COMP_TYPE_ROTATE: 1379f29dbc25Smrg lx_composite_rotate(pxDst, dstOffset, srcOffset, opWidth, 1380f29dbc25Smrg opHeight); 1381f29dbc25Smrg break; 1382f29dbc25Smrg } 1383f29dbc25Smrg 1384f29dbc25Smrg opX += opWidth; 1385f29dbc25Smrg 1386f29dbc25Smrg if (opX >= dstX + width) { 1387f29dbc25Smrg opX = dstX; 1388f29dbc25Smrg opY += opHeight; 1389f29dbc25Smrg 1390f29dbc25Smrg if (opY >= dstY + height) 1391f29dbc25Smrg break; 1392f29dbc25Smrg } 1393f29dbc25Smrg 1394170d5fdcSmrg /* FIXME: Please add the code to handle the condition when the maskX 1395170d5fdcSmrg * and maskY coordinate are negative or greater than 1396170d5fdcSmrg * exaScratch.srcWidth and exaScratch.srcHeight */ 1397170d5fdcSmrg 1398170d5fdcSmrg if (exaScratch.type == COMP_TYPE_MASK) { 1399170d5fdcSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - maskX) 1400170d5fdcSmrg ? (exaScratch.srcWidth - maskX) : (dstX + width) - opX; 1401170d5fdcSmrg opHeight = ((dstY + height) - opY) > (exaScratch.srcHeight - maskY) 1402170d5fdcSmrg ? (exaScratch.srcHeight - maskY) : (dstY + height) - opY; 1403170d5fdcSmrg /* All black out of the mask */ 1404170d5fdcSmrg if (!exaScratch.maskrepeat) 1405170d5fdcSmrg exaScratch.srcColor = 0x0; 1406170d5fdcSmrg } else { 1407170d5fdcSmrg if (exaScratch.type == COMP_TYPE_ONEPASS) { 1408170d5fdcSmrg if (srcX >= 0 && srcY >= 0 && (exaScratch.op == PictOpOver || 1409170d5fdcSmrg exaScratch.op == PictOpSrc || exaScratch.op == 1410170d5fdcSmrg PictOpClear)) { 1411170d5fdcSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - 1412170d5fdcSmrg srcX) ? (exaScratch.srcWidth - srcX) : (dstX + width) 1413170d5fdcSmrg - opX; 1414170d5fdcSmrg opHeight = ((dstY + height) - opY) > 1415170d5fdcSmrg (exaScratch.srcHeight - srcY) ? 1416170d5fdcSmrg (exaScratch.srcHeight - srcY) : (dstY + height) - opY; 1417170d5fdcSmrg } else { 1418170d5fdcSmrg opWidth = ((dstX + width) - opX) > exaScratch.srcWidth ? 1419170d5fdcSmrg exaScratch.srcWidth : (dstX + width) - opX; 1420170d5fdcSmrg opHeight = ((dstY + height) - opY) > exaScratch.srcHeight ? 1421170d5fdcSmrg exaScratch.srcHeight : (dstY + height) - opY; 1422170d5fdcSmrg } 1423170d5fdcSmrg } else { 1424170d5fdcSmrg opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - srcY) 1425170d5fdcSmrg ? (exaScratch.srcWidth - srcY) : (dstX + width) - opX; 1426170d5fdcSmrg opHeight = ((dstY + height) - opY) > (exaScratch.srcHeight - srcX 1427170d5fdcSmrg ) ? (exaScratch.srcHeight - srcX) : (dstY + height) - opY; 1428170d5fdcSmrg } 1429170d5fdcSmrg /* All black out of the source */ 1430170d5fdcSmrg if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ONEPASS)) { 1431170d5fdcSmrg lx_composite_all_black(srcOffset, exaScratch.srcWidth, 1432170d5fdcSmrg exaScratch.srcHeight); 1433170d5fdcSmrg } 1434170d5fdcSmrg if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ROTATE)) 1435170d5fdcSmrg break; 1436170d5fdcSmrg } 1437f29dbc25Smrg } 1438f29dbc25Smrg} 1439f29dbc25Smrg 1440f29dbc25Smrgstatic void 1441f29dbc25Smrglx_wait_marker(ScreenPtr PScreen, int marker) 1442f29dbc25Smrg{ 1443f29dbc25Smrg gp_wait_until_idle(); 1444f29dbc25Smrg} 1445f29dbc25Smrg 1446f29dbc25Smrgstatic void 1447f29dbc25Smrglx_done(PixmapPtr ptr) 1448f29dbc25Smrg{ 1449f29dbc25Smrg} 1450f29dbc25Smrg 1451f29dbc25Smrg#if 0 1452f29dbc25Smrgstatic void 1453f29dbc25Smrglx_upload_to_screen(PixmapPtr pxDst, int x, int y, int w, int h, 1454f29dbc25Smrg char *src, int src_pitch) 1455f29dbc25Smrg{ 1456f29dbc25Smrg GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); 1457f29dbc25Smrg int dst_pitch = exaGetPixmapPitch(pxDst); 1458f29dbc25Smrg int cpp = (pxDst->drawable.bitsPerPixel + 7) / 8; 1459f29dbc25Smrg 1460f29dbc25Smrg char *dst; 1461f29dbc25Smrg int offset = exaGetPixmapOffset(pxDst); 1462f29dbc25Smrg 1463f29dbc25Smrg dst = (char *)(pGeode->FBBase + offset + (y * dst_pitch) + (x * cpp)); 1464f29dbc25Smrg int i; 1465f29dbc25Smrg 1466f29dbc25Smrg for (i = 0; i < h; i++) { 1467f29dbc25Smrg memcpy(dst, src, w * cpp); 1468f29dbc25Smrg dst += dst_pitch; 1469f29dbc25Smrg src += src_pitch; 1470f29dbc25Smrg } 1471f29dbc25Smrg} 1472f29dbc25Smrg#endif 1473f29dbc25Smrg 1474f29dbc25Smrg#if EXA_VERSION_MINOR >= 2 1475f29dbc25Smrg 1476f29dbc25Smrgstatic Bool 1477f29dbc25Smrglx_exa_pixmap_is_offscreen(PixmapPtr pPixmap) 1478f29dbc25Smrg{ 1479f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[pPixmap->drawable.pScreen->myNum]; 1480f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1481f29dbc25Smrg void *start = (void *)(pGeode->FBBase); 1482f29dbc25Smrg void *end = 1483f29dbc25Smrg (void *)(pGeode->FBBase + pGeode->offscreenStart + 1484f29dbc25Smrg pGeode->offscreenSize); 1485f29dbc25Smrg 1486f29dbc25Smrg if ((void *)pPixmap->devPrivate.ptr >= start && 1487f29dbc25Smrg (void *)pPixmap->devPrivate.ptr < end) 1488f29dbc25Smrg return TRUE; 1489f29dbc25Smrg 1490f29dbc25Smrg return FALSE; 1491f29dbc25Smrg} 1492f29dbc25Smrg 1493f29dbc25Smrg#endif 1494f29dbc25Smrg 1495f29dbc25SmrgBool 1496f29dbc25SmrgLXExaInit(ScreenPtr pScreen) 1497f29dbc25Smrg{ 1498f29dbc25Smrg ScrnInfoPtr pScrni = xf86Screens[pScreen->myNum]; 1499f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1500f29dbc25Smrg ExaDriverPtr pExa = pGeode->pExa; 1501f29dbc25Smrg 1502f29dbc25Smrg pExa->exa_major = EXA_VERSION_MAJOR; 1503f29dbc25Smrg pExa->exa_minor = EXA_VERSION_MINOR; 1504f29dbc25Smrg 1505f29dbc25Smrg pExa->WaitMarker = lx_wait_marker; 1506f29dbc25Smrg 1507f29dbc25Smrg pExa->PrepareSolid = lx_prepare_solid; 1508f29dbc25Smrg pExa->Solid = lx_do_solid; 1509f29dbc25Smrg pExa->DoneSolid = lx_done; 1510f29dbc25Smrg 1511f29dbc25Smrg pExa->PrepareCopy = lx_prepare_copy; 1512f29dbc25Smrg pExa->Copy = lx_do_copy; 1513f29dbc25Smrg pExa->DoneCopy = lx_done; 1514f29dbc25Smrg 1515f29dbc25Smrg /* Composite */ 1516f29dbc25Smrg pExa->CheckComposite = lx_check_composite; 1517f29dbc25Smrg pExa->PrepareComposite = lx_prepare_composite; 1518f29dbc25Smrg pExa->Composite = lx_do_composite; 1519f29dbc25Smrg pExa->DoneComposite = lx_done; 1520f29dbc25Smrg //pExa->UploadToScreen = lx_upload_to_screen; 1521f29dbc25Smrg 1522f29dbc25Smrg#if EXA_VERSION_MINOR >= 2 1523f29dbc25Smrg pExa->PixmapIsOffscreen = lx_exa_pixmap_is_offscreen; 1524f29dbc25Smrg#endif 1525f29dbc25Smrg 1526f29dbc25Smrg //pExa->flags = EXA_OFFSCREEN_PIXMAPS; 1527f29dbc25Smrg 1528f29dbc25Smrg return exaDriverInit(pScreen, pGeode->pExa); 1529f29dbc25Smrg} 1530