cg14_accel.c revision faf11d72
1faf11d72Schristos/* $NetBSD: cg14_accel.c,v 1.21 2021/12/09 17:29:14 christos Exp $ */ 24261fa58Smacallan/* 34261fa58Smacallan * Copyright (c) 2013 Michael Lorenz 44261fa58Smacallan * All rights reserved. 54261fa58Smacallan * 64261fa58Smacallan * Redistribution and use in source and binary forms, with or without 74261fa58Smacallan * modification, are permitted provided that the following conditions 84261fa58Smacallan * are met: 94261fa58Smacallan * 104261fa58Smacallan * - Redistributions of source code must retain the above copyright 114261fa58Smacallan * notice, this list of conditions and the following disclaimer. 124261fa58Smacallan * - Redistributions in binary form must reproduce the above 134261fa58Smacallan * copyright notice, this list of conditions and the following 144261fa58Smacallan * disclaimer in the documentation and/or other materials provided 154261fa58Smacallan * with the distribution. 164261fa58Smacallan * 174261fa58Smacallan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 184261fa58Smacallan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 194261fa58Smacallan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 204261fa58Smacallan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 214261fa58Smacallan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 224261fa58Smacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 234261fa58Smacallan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 244261fa58Smacallan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 254261fa58Smacallan * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 264261fa58Smacallan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 274261fa58Smacallan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 284261fa58Smacallan * POSSIBILITY OF SUCH DAMAGE. 294261fa58Smacallan * 304261fa58Smacallan */ 31c88c16f8Smacallan 32c88c16f8Smacallan#ifdef HAVE_CONFIG_H 33c88c16f8Smacallan#include "config.h" 34c88c16f8Smacallan#endif 35c88c16f8Smacallan 364261fa58Smacallan#include <sys/types.h> 374261fa58Smacallan 384261fa58Smacallan/* all driver need this */ 394261fa58Smacallan#include "xf86.h" 404261fa58Smacallan#include "xf86_OSproc.h" 414261fa58Smacallan#include "compiler.h" 424261fa58Smacallan 434261fa58Smacallan#include "cg14.h" 444261fa58Smacallan 45b8ad197aSmacallan//#define SX_DEBUG 464261fa58Smacallan 474261fa58Smacallan#ifdef SX_DEBUG 484261fa58Smacallan#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__); 494261fa58Smacallan#define DPRINTF xf86Msg 504261fa58Smacallan#else 514261fa58Smacallan#define ENTER 524261fa58Smacallan#define DPRINTF while (0) xf86Msg 534261fa58Smacallan#endif 544261fa58Smacallan 554261fa58Smacallan#define arraysize(ary) (sizeof(ary) / sizeof(ary[0])) 564261fa58Smacallan 574261fa58Smacallan/* 0xcc is SX's GXcopy equivalent */ 584261fa58Smacallanuint32_t sx_rop[] = { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, 594261fa58Smacallan 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff}; 604261fa58Smacallan 614261fa58Smacallanint src_formats[] = {PICT_a8r8g8b8, PICT_x8r8g8b8, 624261fa58Smacallan PICT_a8b8g8r8, PICT_x8b8g8r8, PICT_a8}; 634261fa58Smacallanint tex_formats[] = {PICT_a8r8g8b8, PICT_a8b8g8r8, PICT_a8}; 644261fa58Smacallan 65f71acd79Smacallanstatic void CG14Copy32(PixmapPtr, int, int, int, int, int, int); 66f71acd79Smacallanstatic void CG14Copy8(PixmapPtr, int, int, int, int, int, int); 67f71acd79Smacallan 684261fa58Smacallanstatic inline void 694261fa58SmacallanCG14Wait(Cg14Ptr p) 704261fa58Smacallan{ 71fc473876Smacallan int bail = 10000000; 72fc473876Smacallan /* we wait for the busy bit to clear */ 73fc473876Smacallan while (((read_sx_reg(p, SX_CONTROL_STATUS) & SX_BZ) != 0) && 74fc473876Smacallan (bail > 0)) { 75fc473876Smacallan bail--; 76fc473876Smacallan }; 77fc473876Smacallan if (bail == 0) { 78fc473876Smacallan xf86Msg(X_ERROR, "SX wait for idle timed out %08x %08x\n", 79fc473876Smacallan read_sx_reg(p, SX_CONTROL_STATUS), 80fc473876Smacallan read_sx_reg(p, SX_ERROR)); 81fc473876Smacallan } 824261fa58Smacallan} 834261fa58Smacallan 844261fa58Smacallanstatic void 854261fa58SmacallanCG14WaitMarker(ScreenPtr pScreen, int Marker) 864261fa58Smacallan{ 874261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 884261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 894261fa58Smacallan 904261fa58Smacallan CG14Wait(p); 914261fa58Smacallan} 924261fa58Smacallan 934261fa58Smacallanstatic Bool 944261fa58SmacallanCG14PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, 954261fa58Smacallan int xdir, int ydir, int alu, Pixel planemask) 964261fa58Smacallan{ 974261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 984261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 994261fa58Smacallan 1004261fa58Smacallan ENTER; 1018c65af2dSmacallan DPRINTF(X_ERROR, "%s bpp %d rop %x\n", __func__, 10281c68cf8Smacallan pSrcPixmap->drawable.bitsPerPixel, alu); 1034261fa58Smacallan 1044261fa58Smacallan if (planemask != p->last_mask) { 1054261fa58Smacallan CG14Wait(p); 1064261fa58Smacallan write_sx_reg(p, SX_PLANEMASK, planemask); 1074261fa58Smacallan p->last_mask = planemask; 1084261fa58Smacallan } 1094261fa58Smacallan alu = sx_rop[alu]; 1104261fa58Smacallan if (alu != p->last_rop) { 1114261fa58Smacallan CG14Wait(p); 1124261fa58Smacallan write_sx_reg(p, SX_ROP_CONTROL, alu); 1134261fa58Smacallan p->last_rop = alu; 1144261fa58Smacallan } 115f71acd79Smacallan switch (pSrcPixmap->drawable.bitsPerPixel) { 116f71acd79Smacallan case 8: 117f71acd79Smacallan p->pExa->Copy = CG14Copy8; 118f71acd79Smacallan break; 119f71acd79Smacallan case 32: 120f71acd79Smacallan p->pExa->Copy = CG14Copy32; 121f71acd79Smacallan break; 122f71acd79Smacallan default: 123f71acd79Smacallan xf86Msg(X_ERROR, "%s depth %d\n", __func__, 124f71acd79Smacallan pSrcPixmap->drawable.bitsPerPixel); 125f71acd79Smacallan } 1264261fa58Smacallan p->srcpitch = exaGetPixmapPitch(pSrcPixmap); 1274261fa58Smacallan p->srcoff = exaGetPixmapOffset(pSrcPixmap); 1284261fa58Smacallan p->xdir = xdir; 1294261fa58Smacallan p->ydir = ydir; 1304261fa58Smacallan return TRUE; 1314261fa58Smacallan} 1324261fa58Smacallan 1334261fa58Smacallanstatic void 134f71acd79SmacallanCG14Copy32(PixmapPtr pDstPixmap, 1354261fa58Smacallan int srcX, int srcY, int dstX, int dstY, int w, int h) 1364261fa58Smacallan{ 1374261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 1384261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 1394261fa58Smacallan int dstpitch, dstoff, srcpitch, srcoff; 1404261fa58Smacallan int srcstart, dststart, xinc, srcinc, dstinc; 1414261fa58Smacallan int line, count, s, d, num; 1424261fa58Smacallan 1434261fa58Smacallan ENTER; 1444261fa58Smacallan dstpitch = exaGetPixmapPitch(pDstPixmap); 1454261fa58Smacallan dstoff = exaGetPixmapOffset(pDstPixmap); 1464261fa58Smacallan srcpitch = p->srcpitch; 1474261fa58Smacallan srcoff = p->srcoff; 1484261fa58Smacallan /* 1494261fa58Smacallan * should clear the WO bit in SX_CONTROL_STATUS, then check if SX 1504261fa58Smacallan * actually wrote anything and only sync if it did 1514261fa58Smacallan */ 1524261fa58Smacallan srcstart = (srcX << 2) + (srcpitch * srcY) + srcoff; 1534261fa58Smacallan dststart = (dstX << 2) + (dstpitch * dstY) + dstoff; 1544261fa58Smacallan 1554261fa58Smacallan /* 1564261fa58Smacallan * we always copy up to 32 pixels at a time so direction doesn't 1574261fa58Smacallan * matter if w<=32 1584261fa58Smacallan */ 1594261fa58Smacallan if (w > 32) { 1604261fa58Smacallan if (p->xdir < 0) { 1614261fa58Smacallan srcstart += (w - 32) << 2; 1624261fa58Smacallan dststart += (w - 32) << 2; 1634261fa58Smacallan xinc = -128; 1644261fa58Smacallan } else 1654261fa58Smacallan xinc = 128; 1664261fa58Smacallan } else 1674261fa58Smacallan xinc = 128; 1684261fa58Smacallan if (p->ydir < 0) { 1694261fa58Smacallan srcstart += (h - 1) * srcpitch; 1704261fa58Smacallan dststart += (h - 1) * dstpitch; 1714261fa58Smacallan srcinc = -srcpitch; 1724261fa58Smacallan dstinc = -dstpitch; 1734261fa58Smacallan } else { 1744261fa58Smacallan srcinc = srcpitch; 1754261fa58Smacallan dstinc = dstpitch; 1764261fa58Smacallan } 1774261fa58Smacallan if (p->last_rop == 0xcc) { 1784261fa58Smacallan /* plain old copy */ 1794261fa58Smacallan if ( xinc > 0) { 1804261fa58Smacallan /* going left to right */ 1814261fa58Smacallan for (line = 0; line < h; line++) { 1824261fa58Smacallan count = 0; 1834261fa58Smacallan s = srcstart; 1844261fa58Smacallan d = dststart; 1854261fa58Smacallan while ( count < w) { 1864261fa58Smacallan num = min(32, w - count); 1874261fa58Smacallan write_sx_io(p, s, 1884261fa58Smacallan SX_LD(10, num - 1, s & 7)); 1894261fa58Smacallan write_sx_io(p, d, 1904261fa58Smacallan SX_STM(10, num - 1, d & 7)); 1914261fa58Smacallan s += xinc; 1924261fa58Smacallan d += xinc; 1934261fa58Smacallan count += 32; 1944261fa58Smacallan } 1954261fa58Smacallan srcstart += srcinc; 1964261fa58Smacallan dststart += dstinc; 1974261fa58Smacallan } 1984261fa58Smacallan } else { 1994261fa58Smacallan /* going right to left */ 2004261fa58Smacallan int i, chunks = (w >> 5); 2014261fa58Smacallan for (line = 0; line < h; line++) { 2024261fa58Smacallan s = srcstart; 2034261fa58Smacallan d = dststart; 2044261fa58Smacallan count = w; 2054261fa58Smacallan for (i = 0; i < chunks; i++) { 2064261fa58Smacallan write_sx_io(p, s, 2074261fa58Smacallan SX_LD(10, 31, s & 7)); 2084261fa58Smacallan write_sx_io(p, d, 2094261fa58Smacallan SX_STM(10, 31, d & 7)); 2104261fa58Smacallan s -= 128; 2114261fa58Smacallan d -= 128; 2124261fa58Smacallan count -= 32; 2134261fa58Smacallan } 2144261fa58Smacallan /* leftovers, if any */ 2154261fa58Smacallan if (count > 0) { 2164261fa58Smacallan s += (32 - count) << 2; 2174261fa58Smacallan d += (32 - count) << 2; 2184261fa58Smacallan write_sx_io(p, s, 2194261fa58Smacallan SX_LD(10, count - 1, s & 7)); 2204261fa58Smacallan write_sx_io(p, d, 2214261fa58Smacallan SX_STM(10, count - 1, d & 7)); 2224261fa58Smacallan } 2234261fa58Smacallan srcstart += srcinc; 2244261fa58Smacallan dststart += dstinc; 2254261fa58Smacallan } 2264261fa58Smacallan } 2274261fa58Smacallan } else { 2284261fa58Smacallan /* ROPs needed */ 2294261fa58Smacallan if ( xinc > 0) { 2304261fa58Smacallan /* going left to right */ 2314261fa58Smacallan for (line = 0; line < h; line++) { 2324261fa58Smacallan count = 0; 2334261fa58Smacallan s = srcstart; 2344261fa58Smacallan d = dststart; 2354261fa58Smacallan while ( count < w) { 2364261fa58Smacallan num = min(32, w - count); 2374261fa58Smacallan write_sx_io(p, s, 2384261fa58Smacallan SX_LD(10, num - 1, s & 7)); 2394261fa58Smacallan write_sx_io(p, d, 2404261fa58Smacallan SX_LD(42, num - 1, d & 7)); 2414261fa58Smacallan if (num > 16) { 2424261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2434261fa58Smacallan SX_ROP(10, 42, 74, 15)); 2444261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2454261fa58Smacallan SX_ROP(26, 58, 90, num - 17)); 2464261fa58Smacallan } else { 2474261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2484261fa58Smacallan SX_ROP(10, 42, 74, num - 1)); 2494261fa58Smacallan } 2504261fa58Smacallan write_sx_io(p, d, 2514261fa58Smacallan SX_STM(74, num - 1, d & 7)); 2524261fa58Smacallan s += xinc; 2534261fa58Smacallan d += xinc; 2544261fa58Smacallan count += 32; 2554261fa58Smacallan } 2564261fa58Smacallan srcstart += srcinc; 2574261fa58Smacallan dststart += dstinc; 2584261fa58Smacallan } 2594261fa58Smacallan } else { 2604261fa58Smacallan /* going right to left */ 2614261fa58Smacallan int i, chunks = (w >> 5); 2624261fa58Smacallan for (line = 0; line < h; line++) { 2634261fa58Smacallan s = srcstart; 2644261fa58Smacallan d = dststart; 2654261fa58Smacallan count = w; 2664261fa58Smacallan for (i = 0; i < chunks; i++) { 2674261fa58Smacallan write_sx_io(p, s, SX_LD(10, 31, s & 7)); 2684261fa58Smacallan write_sx_io(p, d, SX_LD(42, 31, d & 7)); 2694261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2704261fa58Smacallan SX_ROP(10, 42, 74, 15)); 2714261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2724261fa58Smacallan SX_ROP(26, 58, 90, 15)); 2734261fa58Smacallan write_sx_io(p, d, 2744261fa58Smacallan SX_STM(74, 31, d & 7)); 2754261fa58Smacallan s -= 128; 2764261fa58Smacallan d -= 128; 2774261fa58Smacallan count -= 32; 2784261fa58Smacallan } 2794261fa58Smacallan /* leftovers, if any */ 2804261fa58Smacallan if (count > 0) { 2814261fa58Smacallan s += (32 - count) << 2; 2824261fa58Smacallan d += (32 - count) << 2; 2834261fa58Smacallan write_sx_io(p, s, 2844261fa58Smacallan SX_LD(10, count - 1, s & 7)); 2854261fa58Smacallan write_sx_io(p, d, 2864261fa58Smacallan SX_LD(42, count - 1, d & 7)); 2874261fa58Smacallan if (count > 16) { 2884261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2894261fa58Smacallan SX_ROP(10, 42, 74, 15)); 2904261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2914261fa58Smacallan SX_ROP(26, 58, 90, count - 17)); 2924261fa58Smacallan } else { 2934261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 2944261fa58Smacallan SX_ROP(10, 42, 74, count - 1)); 2954261fa58Smacallan } 2964261fa58Smacallan 2974261fa58Smacallan write_sx_io(p, d, 2984261fa58Smacallan SX_STM(74, count - 1, d & 7)); 2994261fa58Smacallan } 3004261fa58Smacallan srcstart += srcinc; 3014261fa58Smacallan dststart += dstinc; 3024261fa58Smacallan } 3034261fa58Smacallan } 3044261fa58Smacallan } 3054261fa58Smacallan exaMarkSync(pDstPixmap->drawable.pScreen); 3064261fa58Smacallan} 3074261fa58Smacallan 30881c68cf8Smacallan/* 30981c68cf8Smacallan * copy with same alignment, left to right, no ROP 31081c68cf8Smacallan */ 31181c68cf8Smacallanstatic void 31281c68cf8SmacallanCG14Copy8_aligned_norop(Cg14Ptr p, int srcstart, int dststart, int w, int h, int srcpitch, int dstpitch) 31381c68cf8Smacallan{ 31481c68cf8Smacallan int saddr, daddr, pre, cnt, wrds; 31581c68cf8Smacallan 31681c68cf8Smacallan ENTER; 31781c68cf8Smacallan 31881c68cf8Smacallan pre = srcstart & 3; 31981c68cf8Smacallan if (pre != 0) pre = 4 - pre; 32081c68cf8Smacallan pre = min(pre, w); 32181c68cf8Smacallan 32281c68cf8Smacallan while (h > 0) { 32381c68cf8Smacallan saddr = srcstart; 32481c68cf8Smacallan daddr = dststart; 32581c68cf8Smacallan cnt = w; 32681c68cf8Smacallan if (pre > 0) { 32781c68cf8Smacallan write_sx_io(p, saddr & ~7, SX_LDB(8, pre - 1, saddr & 7)); 32881c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_STB(8, pre - 1, daddr & 7)); 32981c68cf8Smacallan saddr += pre; 33081c68cf8Smacallan daddr += pre; 33181c68cf8Smacallan cnt -= pre; 33281c68cf8Smacallan if (cnt == 0) goto next; 33381c68cf8Smacallan } 33481c68cf8Smacallan while (cnt > 3) { 33581c68cf8Smacallan wrds = min(32, cnt >> 2); 33681c68cf8Smacallan write_sx_io(p, saddr & ~7, SX_LD(8, wrds - 1, saddr & 7)); 33781c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_ST(8, wrds - 1, daddr & 7)); 33881c68cf8Smacallan saddr += wrds << 2; 33981c68cf8Smacallan daddr += wrds << 2; 34081c68cf8Smacallan cnt -= wrds << 2; 34181c68cf8Smacallan } 34281c68cf8Smacallan if (cnt > 0) { 34381c68cf8Smacallan write_sx_io(p, saddr & ~7, SX_LDB(8, cnt - 1, saddr & 7)); 34481c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_STB(8, cnt - 1, daddr & 7)); 34581c68cf8Smacallan } 34681c68cf8Smacallannext: 34781c68cf8Smacallan srcstart += srcpitch; 34881c68cf8Smacallan dststart += dstpitch; 34981c68cf8Smacallan h--; 35081c68cf8Smacallan } 35181c68cf8Smacallan} 35281c68cf8Smacallan 35381c68cf8Smacallan/* 35481c68cf8Smacallan * copy with same alignment, left to right, ROP 35581c68cf8Smacallan */ 35681c68cf8Smacallanstatic void 35781c68cf8SmacallanCG14Copy8_aligned_rop(Cg14Ptr p, int srcstart, int dststart, int w, int h, int srcpitch, int dstpitch) 35881c68cf8Smacallan{ 35981c68cf8Smacallan int saddr, daddr, pre, cnt, wrds; 36081c68cf8Smacallan 36181c68cf8Smacallan ENTER; 36281c68cf8Smacallan 36381c68cf8Smacallan pre = srcstart & 3; 36481c68cf8Smacallan if (pre != 0) pre = 4 - pre; 36581c68cf8Smacallan pre = min(pre, w); 36681c68cf8Smacallan 36781c68cf8Smacallan while (h > 0) { 36881c68cf8Smacallan saddr = srcstart; 36981c68cf8Smacallan daddr = dststart; 37081c68cf8Smacallan cnt = w; 37181c68cf8Smacallan if (pre > 0) { 37281c68cf8Smacallan write_sx_io(p, saddr & ~7, SX_LDB(8, pre - 1, saddr & 7)); 37381c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_LDB(40, pre - 1, daddr & 7)); 37481c68cf8Smacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(8, 40, 72, pre - 1)); 37581c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_STB(72, pre - 1, daddr & 7)); 37681c68cf8Smacallan saddr += pre; 37781c68cf8Smacallan daddr += pre; 37881c68cf8Smacallan cnt -= pre; 37981c68cf8Smacallan if (cnt == 0) goto next; 38081c68cf8Smacallan } 38181c68cf8Smacallan while (cnt > 3) { 38281c68cf8Smacallan wrds = min(32, cnt >> 2); 38381c68cf8Smacallan write_sx_io(p, saddr & ~7, SX_LD(8, wrds - 1, saddr & 7)); 38481c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_LD(40, wrds - 1, daddr & 7)); 38581c68cf8Smacallan if (cnt > 16) { 38681c68cf8Smacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(8, 40, 72, 15)); 38781c68cf8Smacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(8, 56, 88, wrds - 17)); 38881c68cf8Smacallan } else 38981c68cf8Smacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(8, 40, 72, wrds - 1)); 39081c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_ST(72, wrds - 1, daddr & 7)); 39181c68cf8Smacallan saddr += wrds << 2; 39281c68cf8Smacallan daddr += wrds << 2; 39381c68cf8Smacallan cnt -= wrds << 2; 39481c68cf8Smacallan } 39581c68cf8Smacallan if (cnt > 0) { 39681c68cf8Smacallan write_sx_io(p, saddr & ~7, SX_LDB(8, cnt - 1, saddr & 7)); 39781c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_LDB(40, cnt - 1, daddr & 7)); 39881c68cf8Smacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(8, 40, 72, cnt - 1)); 39981c68cf8Smacallan write_sx_io(p, daddr & ~7, SX_STB(72, cnt - 1, daddr & 7)); 40081c68cf8Smacallan } 40181c68cf8Smacallannext: 40281c68cf8Smacallan srcstart += srcpitch; 40381c68cf8Smacallan dststart += dstpitch; 40481c68cf8Smacallan h--; 40581c68cf8Smacallan } 40681c68cf8Smacallan} 40781c68cf8Smacallan 408f71acd79Smacallanstatic void 409f71acd79SmacallanCG14Copy8(PixmapPtr pDstPixmap, 410f71acd79Smacallan int srcX, int srcY, int dstX, int dstY, int w, int h) 411f71acd79Smacallan{ 412f71acd79Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 413f71acd79Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 414f71acd79Smacallan int dstpitch, dstoff, srcpitch, srcoff; 415f71acd79Smacallan int srcstart, dststart, xinc, srcinc, dstinc; 416f71acd79Smacallan int line, count, s, d, num; 417f71acd79Smacallan 418f71acd79Smacallan ENTER; 419f71acd79Smacallan dstpitch = exaGetPixmapPitch(pDstPixmap); 420f71acd79Smacallan dstoff = exaGetPixmapOffset(pDstPixmap); 421f71acd79Smacallan srcpitch = p->srcpitch; 422f71acd79Smacallan srcoff = p->srcoff; 423f71acd79Smacallan /* 424f71acd79Smacallan * should clear the WO bit in SX_CONTROL_STATUS, then check if SX 425f71acd79Smacallan * actually wrote anything and only sync if it did 426f71acd79Smacallan */ 427f71acd79Smacallan srcstart = srcX + (srcpitch * srcY) + srcoff; 428f71acd79Smacallan dststart = dstX + (dstpitch * dstY) + dstoff; 429f71acd79Smacallan 43081c68cf8Smacallan if ((p->xdir < 0) && (srcoff == dstoff) && (srcY == dstY)) { 43181c68cf8Smacallan srcstart += (w - 32); 43281c68cf8Smacallan dststart += (w - 32); 43381c68cf8Smacallan xinc = -32; 434f71acd79Smacallan } else 435f71acd79Smacallan xinc = 32; 43681c68cf8Smacallan 437f71acd79Smacallan if (p->ydir < 0) { 438f71acd79Smacallan srcstart += (h - 1) * srcpitch; 439f71acd79Smacallan dststart += (h - 1) * dstpitch; 440f71acd79Smacallan srcinc = -srcpitch; 441f71acd79Smacallan dstinc = -dstpitch; 442f71acd79Smacallan } else { 443f71acd79Smacallan srcinc = srcpitch; 444f71acd79Smacallan dstinc = dstpitch; 445f71acd79Smacallan } 44681c68cf8Smacallan if (((srcstart & 3) == (dststart & 3)) && (xinc > 0)) { 44781c68cf8Smacallan switch (p->last_rop) { 44881c68cf8Smacallan case 0xcc: 44981c68cf8Smacallan CG14Copy8_aligned_norop(p, srcstart, dststart, w, h, srcinc, dstinc); 45081c68cf8Smacallan break; 45181c68cf8Smacallan default: 45281c68cf8Smacallan CG14Copy8_aligned_rop(p, srcstart, dststart, w, h, srcinc, dstinc); 45381c68cf8Smacallan } 45481c68cf8Smacallan return; 45581c68cf8Smacallan } 456f71acd79Smacallan if (p->last_rop == 0xcc) { 457f71acd79Smacallan /* plain old copy */ 458f71acd79Smacallan if ( xinc > 0) { 459f71acd79Smacallan /* going left to right */ 460f71acd79Smacallan for (line = 0; line < h; line++) { 461f71acd79Smacallan count = 0; 462f71acd79Smacallan s = srcstart; 463f71acd79Smacallan d = dststart; 464f71acd79Smacallan while ( count < w) { 465f71acd79Smacallan num = min(32, w - count); 466f71acd79Smacallan write_sx_io(p, s, 467f71acd79Smacallan SX_LDB(10, num - 1, s & 7)); 468f71acd79Smacallan write_sx_io(p, d, 469f71acd79Smacallan SX_STBM(10, num - 1, d & 7)); 470f71acd79Smacallan s += xinc; 471f71acd79Smacallan d += xinc; 472f71acd79Smacallan count += 32; 473f71acd79Smacallan } 474f71acd79Smacallan srcstart += srcinc; 475f71acd79Smacallan dststart += dstinc; 476f71acd79Smacallan } 477f71acd79Smacallan } else { 478f71acd79Smacallan /* going right to left */ 479f71acd79Smacallan int i, chunks = (w >> 5); 480f71acd79Smacallan for (line = 0; line < h; line++) { 481f71acd79Smacallan s = srcstart; 482f71acd79Smacallan d = dststart; 483f71acd79Smacallan count = w; 484f71acd79Smacallan for (i = 0; i < chunks; i++) { 485f71acd79Smacallan write_sx_io(p, s, 486f71acd79Smacallan SX_LDB(10, 31, s & 7)); 487f71acd79Smacallan write_sx_io(p, d, 488f71acd79Smacallan SX_STBM(10, 31, d & 7)); 489f71acd79Smacallan s -= 32; 490f71acd79Smacallan d -= 32; 491f71acd79Smacallan count -= 32; 492f71acd79Smacallan } 493f71acd79Smacallan /* leftovers, if any */ 494f71acd79Smacallan if (count > 0) { 495f71acd79Smacallan s += (32 - count); 496f71acd79Smacallan d += (32 - count); 497f71acd79Smacallan write_sx_io(p, s, 498f71acd79Smacallan SX_LDB(10, count - 1, s & 7)); 499f71acd79Smacallan write_sx_io(p, d, 500f71acd79Smacallan SX_STBM(10, count - 1, d & 7)); 501f71acd79Smacallan } 502f71acd79Smacallan srcstart += srcinc; 503f71acd79Smacallan dststart += dstinc; 504f71acd79Smacallan } 505f71acd79Smacallan } 506f71acd79Smacallan } else { 507f71acd79Smacallan /* ROPs needed */ 508f71acd79Smacallan if ( xinc > 0) { 509f71acd79Smacallan /* going left to right */ 510f71acd79Smacallan for (line = 0; line < h; line++) { 511f71acd79Smacallan count = 0; 512f71acd79Smacallan s = srcstart; 513f71acd79Smacallan d = dststart; 514f71acd79Smacallan while ( count < w) { 515f71acd79Smacallan num = min(32, w - count); 516f71acd79Smacallan write_sx_io(p, s, 517f71acd79Smacallan SX_LDB(10, num - 1, s & 7)); 518f71acd79Smacallan write_sx_io(p, d, 519f71acd79Smacallan SX_LDB(42, num - 1, d & 7)); 520f71acd79Smacallan if (num > 16) { 521f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 522f71acd79Smacallan SX_ROP(10, 42, 74, 15)); 523f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 524f71acd79Smacallan SX_ROP(26, 58, 90, num - 17)); 525f71acd79Smacallan } else { 526f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 527f71acd79Smacallan SX_ROP(10, 42, 74, num - 1)); 528f71acd79Smacallan } 529f71acd79Smacallan write_sx_io(p, d, 530f71acd79Smacallan SX_STBM(74, num - 1, d & 7)); 531f71acd79Smacallan s += xinc; 532f71acd79Smacallan d += xinc; 533f71acd79Smacallan count += 32; 534f71acd79Smacallan } 535f71acd79Smacallan srcstart += srcinc; 536f71acd79Smacallan dststart += dstinc; 537f71acd79Smacallan } 538f71acd79Smacallan } else { 539f71acd79Smacallan /* going right to left */ 540f71acd79Smacallan int i, chunks = (w >> 5); 541f71acd79Smacallan for (line = 0; line < h; line++) { 542f71acd79Smacallan s = srcstart; 543f71acd79Smacallan d = dststart; 544f71acd79Smacallan count = w; 545f71acd79Smacallan for (i = 0; i < chunks; i++) { 546f71acd79Smacallan write_sx_io(p, s, SX_LDB(10, 31, s & 7)); 547f71acd79Smacallan write_sx_io(p, d, SX_LDB(42, 31, d & 7)); 548f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 549f71acd79Smacallan SX_ROP(10, 42, 74, 15)); 550f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 551f71acd79Smacallan SX_ROP(26, 58, 90, 15)); 552f71acd79Smacallan write_sx_io(p, d, 553f71acd79Smacallan SX_STBM(74, 31, d & 7)); 554f71acd79Smacallan s -= 128; 555f71acd79Smacallan d -= 128; 556f71acd79Smacallan count -= 32; 557f71acd79Smacallan } 558f71acd79Smacallan /* leftovers, if any */ 559f71acd79Smacallan if (count > 0) { 560f71acd79Smacallan s += (32 - count); 561f71acd79Smacallan d += (32 - count); 562f71acd79Smacallan write_sx_io(p, s, 563f71acd79Smacallan SX_LDB(10, count - 1, s & 7)); 564f71acd79Smacallan write_sx_io(p, d, 565f71acd79Smacallan SX_LDB(42, count - 1, d & 7)); 566f71acd79Smacallan if (count > 16) { 567f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 568f71acd79Smacallan SX_ROP(10, 42, 74, 15)); 569f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 570f71acd79Smacallan SX_ROP(26, 58, 90, count - 17)); 571f71acd79Smacallan } else { 572f71acd79Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 573f71acd79Smacallan SX_ROP(10, 42, 74, count - 1)); 574f71acd79Smacallan } 575f71acd79Smacallan 576f71acd79Smacallan write_sx_io(p, d, 577f71acd79Smacallan SX_STBM(74, count - 1, d & 7)); 578f71acd79Smacallan } 579f71acd79Smacallan srcstart += srcinc; 580f71acd79Smacallan dststart += dstinc; 581f71acd79Smacallan } 582f71acd79Smacallan } 583f71acd79Smacallan } 584f71acd79Smacallan exaMarkSync(pDstPixmap->drawable.pScreen); 585f71acd79Smacallan} 586f71acd79Smacallan 5874261fa58Smacallanstatic void 5884261fa58SmacallanCG14DoneCopy(PixmapPtr pDstPixmap) 5894261fa58Smacallan{ 5904261fa58Smacallan} 5914261fa58Smacallan 5924261fa58Smacallanstatic Bool 5934261fa58SmacallanCG14PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) 5944261fa58Smacallan{ 5954261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 5964261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 5974261fa58Smacallan 5984261fa58Smacallan ENTER; 599faf11d72Schristos DPRINTF(X_ERROR, "bits per pixel: %d %08lx\n", 600b8ad197aSmacallan pPixmap->drawable.bitsPerPixel, fg); 601b8ad197aSmacallan 602dbf8597cSmacallan /* 603dbf8597cSmacallan * GXset and GXclear are really just specual cases of GXcopy with 604dbf8597cSmacallan * fixed fill colour 605dbf8597cSmacallan */ 606dbf8597cSmacallan switch (alu) { 607dbf8597cSmacallan case GXclear: 608dbf8597cSmacallan alu = GXcopy; 609dbf8597cSmacallan fg = 0; 610dbf8597cSmacallan break; 611dbf8597cSmacallan case GXset: 612dbf8597cSmacallan alu = GXcopy; 613dbf8597cSmacallan fg = 0xffffffff; 614dbf8597cSmacallan break; 615dbf8597cSmacallan } 616b8ad197aSmacallan /* repeat the colour in every sub byte if we're in 8 bit */ 617b8ad197aSmacallan if (pPixmap->drawable.bitsPerPixel == 8) { 618b8ad197aSmacallan fg |= fg << 8; 619b8ad197aSmacallan fg |= fg << 16; 620b8ad197aSmacallan } 6214261fa58Smacallan write_sx_reg(p, SX_QUEUED(8), fg); 6224261fa58Smacallan write_sx_reg(p, SX_QUEUED(9), fg); 6234261fa58Smacallan if (planemask != p->last_mask) { 6244261fa58Smacallan CG14Wait(p); 6254261fa58Smacallan write_sx_reg(p, SX_PLANEMASK, planemask); 6264261fa58Smacallan p->last_mask = planemask; 6274261fa58Smacallan } 6284261fa58Smacallan alu = sx_rop[alu]; 6294261fa58Smacallan if (alu != p->last_rop) { 6304261fa58Smacallan CG14Wait(p); 6314261fa58Smacallan write_sx_reg(p, SX_ROP_CONTROL, alu); 6324261fa58Smacallan p->last_rop = alu; 6334261fa58Smacallan } 634dbf8597cSmacallan 6354261fa58Smacallan DPRINTF(X_ERROR, "%s: %x\n", __func__, alu); 6364261fa58Smacallan return TRUE; 6374261fa58Smacallan} 6384261fa58Smacallan 6394261fa58Smacallanstatic void 6404261fa58SmacallanCG14Solid32(Cg14Ptr p, uint32_t start, uint32_t pitch, int w, int h) 6414261fa58Smacallan{ 6424261fa58Smacallan int line, x, num; 6434261fa58Smacallan uint32_t ptr; 6444261fa58Smacallan 6454261fa58Smacallan ENTER; 6464261fa58Smacallan if (p->last_rop == 0xcc) { 6474261fa58Smacallan /* simple fill */ 6484261fa58Smacallan for (line = 0; line < h; line++) { 6494261fa58Smacallan x = 0; 6504261fa58Smacallan while (x < w) { 6514261fa58Smacallan ptr = start + (x << 2); 6524261fa58Smacallan num = min(32, w - x); 6534261fa58Smacallan write_sx_io(p, ptr, 6544261fa58Smacallan SX_STS(8, num - 1, ptr & 7)); 6554261fa58Smacallan x += 32; 6564261fa58Smacallan } 6574261fa58Smacallan start += pitch; 6584261fa58Smacallan } 6594261fa58Smacallan } else if (p->last_rop == 0xaa) { 6604261fa58Smacallan /* nothing to do here */ 6614261fa58Smacallan return; 6624261fa58Smacallan } else { 6634261fa58Smacallan /* alright, let's do actual ROP stuff */ 6644261fa58Smacallan 6654261fa58Smacallan /* first repeat the fill colour into 16 registers */ 6664261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 6674261fa58Smacallan SX_SELECT_S(8, 8, 10, 15)); 6684261fa58Smacallan 6694261fa58Smacallan for (line = 0; line < h; line++) { 6704261fa58Smacallan x = 0; 6714261fa58Smacallan while (x < w) { 6724261fa58Smacallan ptr = start + (x << 2); 6734261fa58Smacallan num = min(32, w - x); 6744261fa58Smacallan /* now suck fb data into registers */ 6754261fa58Smacallan write_sx_io(p, ptr, 6764261fa58Smacallan SX_LD(42, num - 1, ptr & 7)); 6774261fa58Smacallan /* 6784261fa58Smacallan * ROP them with the fill data we left in 10 6794261fa58Smacallan * non-memory ops can only have counts up to 16 6804261fa58Smacallan */ 6814261fa58Smacallan if (num <= 16) { 6824261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 6834261fa58Smacallan SX_ROP(10, 42, 74, num - 1)); 6844261fa58Smacallan } else { 6854261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 6864261fa58Smacallan SX_ROP(10, 42, 74, 15)); 6874261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 6884261fa58Smacallan SX_ROP(10, 58, 90, num - 17)); 6894261fa58Smacallan } 6904261fa58Smacallan /* and write the result back into memory */ 6914261fa58Smacallan write_sx_io(p, ptr, 6924261fa58Smacallan SX_ST(74, num - 1, ptr & 7)); 6934261fa58Smacallan x += 32; 6944261fa58Smacallan } 6954261fa58Smacallan start += pitch; 6964261fa58Smacallan } 6974261fa58Smacallan } 6984261fa58Smacallan} 6994261fa58Smacallan 7004261fa58Smacallanstatic void 7014261fa58SmacallanCG14Solid8(Cg14Ptr p, uint32_t start, uint32_t pitch, int w, int h) 7024261fa58Smacallan{ 703dbf8597cSmacallan int line, num, pre, cnt; 7044261fa58Smacallan uint32_t ptr; 7054261fa58Smacallan 7064261fa58Smacallan ENTER; 707b8ad197aSmacallan pre = start & 3; 708b8ad197aSmacallan if (pre != 0) pre = 4 - pre; 7094261fa58Smacallan 7104261fa58Smacallan if (p->last_rop == 0xcc) { 7114261fa58Smacallan /* simple fill */ 7124261fa58Smacallan for (line = 0; line < h; line++) { 713b8ad197aSmacallan ptr = start; 714b8ad197aSmacallan cnt = w; 715b46cab2aSmacallan pre = min(pre, cnt); 716b8ad197aSmacallan if (pre) { 717b8ad197aSmacallan write_sx_io(p, ptr & ~7, SX_STBS(8, pre - 1, ptr & 7)); 718b8ad197aSmacallan ptr += pre; 719b8ad197aSmacallan cnt -= pre; 720b46cab2aSmacallan if (cnt == 0) goto next; 721b8ad197aSmacallan } 722b8ad197aSmacallan /* now do the aligned pixels in 32bit chunks */ 723b8ad197aSmacallan if (ptr & 3) xf86Msg(X_ERROR, "%s %x\n", __func__, ptr); 724b8ad197aSmacallan while(cnt > 3) { 725b8ad197aSmacallan num = min(32, cnt >> 2); 726b8ad197aSmacallan write_sx_io(p, ptr & ~7, SX_STS(8, num - 1, ptr & 7)); 727b8ad197aSmacallan ptr += num << 2; 728b8ad197aSmacallan cnt -= num << 2; 729b8ad197aSmacallan } 730b8ad197aSmacallan if (cnt > 3) xf86Msg(X_ERROR, "%s cnt %d\n", __func__, cnt); 731b8ad197aSmacallan if (cnt > 0) { 732b8ad197aSmacallan write_sx_io(p, ptr & ~7, SX_STBS(8, cnt - 1, ptr & 7)); 7334261fa58Smacallan } 734b8ad197aSmacallan if ((ptr + cnt) != (start + w)) xf86Msg(X_ERROR, "%s %x vs %x\n", __func__, ptr + cnt, start + w); 735b46cab2aSmacallannext: 7364261fa58Smacallan start += pitch; 7374261fa58Smacallan } 7384261fa58Smacallan } else if (p->last_rop == 0xaa) { 7394261fa58Smacallan /* nothing to do here */ 7404261fa58Smacallan return; 7414261fa58Smacallan } else { 7424261fa58Smacallan /* alright, let's do actual ROP stuff */ 7434261fa58Smacallan 7444261fa58Smacallan /* first repeat the fill colour into 16 registers */ 7454261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 7464261fa58Smacallan SX_SELECT_S(8, 8, 10, 15)); 7474261fa58Smacallan 7484261fa58Smacallan for (line = 0; line < h; line++) { 749dbf8597cSmacallan ptr = start; 750dbf8597cSmacallan cnt = w; 751dbf8597cSmacallan pre = min(pre, cnt); 752dbf8597cSmacallan if (pre) { 753dbf8597cSmacallan write_sx_io(p, ptr & ~7, SX_LDB(26, pre - 1, ptr & 7)); 754dbf8597cSmacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(10, 26, 42, pre - 1)); 755dbf8597cSmacallan write_sx_io(p, ptr & ~7, SX_STB(42, pre - 1, ptr & 7)); 756dbf8597cSmacallan ptr += pre; 757dbf8597cSmacallan cnt -= pre; 758dbf8597cSmacallan if (cnt == 0) goto next2; 759dbf8597cSmacallan } 760dbf8597cSmacallan /* now do the aligned pixels in 32bit chunks */ 761dbf8597cSmacallan if (ptr & 3) xf86Msg(X_ERROR, "%s %x\n", __func__, ptr); 762dbf8597cSmacallan while(cnt > 3) { 763dbf8597cSmacallan num = min(32, cnt >> 2); 764dbf8597cSmacallan write_sx_io(p, ptr & ~7, SX_LD(26, num - 1, ptr & 7)); 7654261fa58Smacallan if (num <= 16) { 7664261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 767dbf8597cSmacallan SX_ROP(10, 26, 58, num - 1)); 7684261fa58Smacallan } else { 7694261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 770dbf8597cSmacallan SX_ROP(10, 26, 58, 15)); 7714261fa58Smacallan write_sx_reg(p, SX_INSTRUCTIONS, 772dbf8597cSmacallan SX_ROP(10, 42, 74, num - 17)); 7734261fa58Smacallan } 774dbf8597cSmacallan write_sx_io(p, ptr & ~7, SX_ST(58, num - 1, ptr & 7)); 775dbf8597cSmacallan ptr += num << 2; 776dbf8597cSmacallan cnt -= num << 2; 7774261fa58Smacallan } 778dbf8597cSmacallan if (cnt > 3) xf86Msg(X_ERROR, "%s cnt %d\n", __func__, cnt); 779dbf8597cSmacallan if (cnt > 0) { 780dbf8597cSmacallan write_sx_io(p, ptr & ~7, SX_LDB(26, cnt - 1, ptr & 7)); 781dbf8597cSmacallan write_sx_reg(p, SX_INSTRUCTIONS, SX_ROP(10, 26, 42, cnt - 1)); 782dbf8597cSmacallan write_sx_io(p, ptr & ~7, SX_STB(42, cnt - 1, ptr & 7)); 783dbf8597cSmacallan } 784dbf8597cSmacallan if ((ptr + cnt) != (start + w)) xf86Msg(X_ERROR, "%s %x vs %x\n", __func__, ptr + cnt, start + w); 785dbf8597cSmacallannext2: 7864261fa58Smacallan start += pitch; 7874261fa58Smacallan } 7884261fa58Smacallan } 7894261fa58Smacallan} 7904261fa58Smacallan 7914261fa58Smacallanstatic void 7924261fa58SmacallanCG14Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 7934261fa58Smacallan{ 7944261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 7954261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 7964261fa58Smacallan int w = x2 - x1, h = y2 - y1, dstoff, dstpitch; 7974261fa58Smacallan int start, depth; 7984261fa58Smacallan 7994261fa58Smacallan ENTER; 8004261fa58Smacallan dstpitch = exaGetPixmapPitch(pPixmap); 8014261fa58Smacallan dstoff = exaGetPixmapOffset(pPixmap); 8024261fa58Smacallan 8034261fa58Smacallan depth = pPixmap->drawable.bitsPerPixel; 8044261fa58Smacallan switch (depth) { 8054261fa58Smacallan case 32: 8064261fa58Smacallan start = dstoff + (y1 * dstpitch) + (x1 << 2); 8074261fa58Smacallan CG14Solid32(p, start, dstpitch, w, h); 8084261fa58Smacallan break; 8094261fa58Smacallan case 8: 8104261fa58Smacallan start = dstoff + (y1 * dstpitch) + x1; 8114261fa58Smacallan CG14Solid8(p, start, dstpitch, w, h); 8124261fa58Smacallan break; 8134261fa58Smacallan } 8144261fa58Smacallan 8154261fa58Smacallan DPRINTF(X_ERROR, "Solid %d %d %d %d, %d %d -> %d\n", x1, y1, x2, y2, 8164261fa58Smacallan dstpitch, dstoff, start); 8174261fa58Smacallan DPRINTF(X_ERROR, "%x %x %x\n", p->last_rop, 8184261fa58Smacallan read_sx_reg(p, SX_QUEUED(8)), read_sx_reg(p, SX_QUEUED(9))); 8194261fa58Smacallan exaMarkSync(pPixmap->drawable.pScreen); 8204261fa58Smacallan} 8214261fa58Smacallan 8224261fa58Smacallan/* 8234261fa58Smacallan * Memcpy-based UTS. 8244261fa58Smacallan */ 8254261fa58Smacallanstatic Bool 8264261fa58SmacallanCG14UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 8274261fa58Smacallan char *src, int src_pitch) 8284261fa58Smacallan{ 8294261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 8304261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 8314261fa58Smacallan char *dst = p->fb + exaGetPixmapOffset(pDst); 8324261fa58Smacallan int dst_pitch = exaGetPixmapPitch(pDst); 8334261fa58Smacallan 8344261fa58Smacallan int bpp = pDst->drawable.bitsPerPixel; 8354261fa58Smacallan int cpp = (bpp + 7) >> 3; 8364261fa58Smacallan int wBytes = w * cpp; 8374261fa58Smacallan 8384261fa58Smacallan ENTER; 839f71acd79Smacallan DPRINTF(X_ERROR, "%s depth %d\n", __func__, bpp); 8404261fa58Smacallan dst += (x * cpp) + (y * dst_pitch); 8414261fa58Smacallan 8424261fa58Smacallan CG14Wait(p); 8434261fa58Smacallan 8444261fa58Smacallan while (h--) { 8454261fa58Smacallan memcpy(dst, src, wBytes); 8464261fa58Smacallan src += src_pitch; 8474261fa58Smacallan dst += dst_pitch; 8484261fa58Smacallan } 8494261fa58Smacallan __asm("stbar;"); 8504261fa58Smacallan return TRUE; 8514261fa58Smacallan} 8524261fa58Smacallan 8534261fa58Smacallan/* 8544261fa58Smacallan * Memcpy-based DFS. 8554261fa58Smacallan */ 8564261fa58Smacallanstatic Bool 8574261fa58SmacallanCG14DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 8584261fa58Smacallan char *dst, int dst_pitch) 8594261fa58Smacallan{ 8604261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 8614261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 8624261fa58Smacallan char *src = p->fb + exaGetPixmapOffset(pSrc); 8634261fa58Smacallan int src_pitch = exaGetPixmapPitch(pSrc); 8644261fa58Smacallan 8654261fa58Smacallan ENTER; 8664261fa58Smacallan int bpp = pSrc->drawable.bitsPerPixel; 8674261fa58Smacallan int cpp = (bpp + 7) >> 3; 8684261fa58Smacallan int wBytes = w * cpp; 8694261fa58Smacallan 8704261fa58Smacallan src += (x * cpp) + (y * src_pitch); 8714261fa58Smacallan 8724261fa58Smacallan CG14Wait(p); 8734261fa58Smacallan 8744261fa58Smacallan while (h--) { 8754261fa58Smacallan memcpy(dst, src, wBytes); 8764261fa58Smacallan src += src_pitch; 8774261fa58Smacallan dst += dst_pitch; 8784261fa58Smacallan } 8794261fa58Smacallan 8804261fa58Smacallan return TRUE; 8814261fa58Smacallan} 8824261fa58Smacallan 8834261fa58SmacallanBool 8844261fa58SmacallanCG14CheckComposite(int op, PicturePtr pSrcPicture, 8854261fa58Smacallan PicturePtr pMaskPicture, 8864261fa58Smacallan PicturePtr pDstPicture) 8874261fa58Smacallan{ 8884261fa58Smacallan int i, ok = FALSE; 8894261fa58Smacallan 8904261fa58Smacallan ENTER; 8914261fa58Smacallan 8924261fa58Smacallan /* 8934261fa58Smacallan * SX is in theory capable of accelerating pretty much all Xrender ops, 8944261fa58Smacallan * even coordinate transformation and gradients. Support will be added 8954261fa58Smacallan * over time and likely have to spill over into its own source file. 8964261fa58Smacallan */ 8974261fa58Smacallan 898a3a2ba44Smacallan if ((op != PictOpOver) && (op != PictOpAdd) && (op != PictOpSrc)) { 899fe97f391Smacallan DPRINTF(X_ERROR, "%s: rejecting %d\n", __func__, op); 9004261fa58Smacallan return FALSE; 9014261fa58Smacallan } 9024261fa58Smacallan 9034bd47ccfSmacallan if (pSrcPicture != NULL) { 9044bd47ccfSmacallan i = 0; 9054bd47ccfSmacallan while ((i < arraysize(src_formats)) && (!ok)) { 9064bd47ccfSmacallan ok = (pSrcPicture->format == src_formats[i]); 9074bd47ccfSmacallan i++; 9084bd47ccfSmacallan } 9094bd47ccfSmacallan 9104bd47ccfSmacallan if (!ok) { 9114bd47ccfSmacallan DPRINTF(X_ERROR, "%s: unsupported src format %x\n", 9124bd47ccfSmacallan __func__, pSrcPicture->format); 9134bd47ccfSmacallan return FALSE; 9144bd47ccfSmacallan } 9154bd47ccfSmacallan DPRINTF(X_ERROR, "src is %x, %d\n", pSrcPicture->format, op); 9164261fa58Smacallan } 9174261fa58Smacallan 9184bd47ccfSmacallan if (pDstPicture != NULL) { 9194bd47ccfSmacallan i = 0; 9204bd47ccfSmacallan ok = FALSE; 9214bd47ccfSmacallan while ((i < arraysize(src_formats)) && (!ok)) { 9224bd47ccfSmacallan ok = (pDstPicture->format == src_formats[i]); 9234bd47ccfSmacallan i++; 9244bd47ccfSmacallan } 9254bd47ccfSmacallan 9264bd47ccfSmacallan if (!ok) { 9274bd47ccfSmacallan DPRINTF(X_ERROR, "%s: unsupported dst format %x\n", 9284bd47ccfSmacallan __func__, pDstPicture->format); 9294bd47ccfSmacallan return FALSE; 9304bd47ccfSmacallan } 9314bd47ccfSmacallan DPRINTF(X_ERROR, "dst is %x, %d\n", pDstPicture->format, op); 9324bd47ccfSmacallan } 9334261fa58Smacallan 9344261fa58Smacallan if (pMaskPicture != NULL) { 9354261fa58Smacallan DPRINTF(X_ERROR, "mask is %x %d %d\n", pMaskPicture->format, 9364261fa58Smacallan pMaskPicture->pDrawable->width, 9374261fa58Smacallan pMaskPicture->pDrawable->height); 9384261fa58Smacallan } 9394261fa58Smacallan return TRUE; 9404261fa58Smacallan} 9414261fa58Smacallan 9424261fa58SmacallanBool 9434261fa58SmacallanCG14PrepareComposite(int op, PicturePtr pSrcPicture, 9444261fa58Smacallan PicturePtr pMaskPicture, 9454261fa58Smacallan PicturePtr pDstPicture, 9464261fa58Smacallan PixmapPtr pSrc, 9474261fa58Smacallan PixmapPtr pMask, 9484261fa58Smacallan PixmapPtr pDst) 9494261fa58Smacallan{ 9504261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 9514261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 9524261fa58Smacallan 9534261fa58Smacallan ENTER; 9544261fa58Smacallan 955f7cb851fSmacallan p->no_source_pixmap = FALSE; 956f7cb851fSmacallan p->source_is_solid = FALSE; 957f7cb851fSmacallan 958a3a2ba44Smacallan if (pSrcPicture->format == PICT_a1) { 9596bdc2ffdSmacallan xf86Msg(X_ERROR, "src mono, dst %x, op %d\n", 9606bdc2ffdSmacallan pDstPicture->format, op); 961a3a2ba44Smacallan if (pMaskPicture != NULL) { 962a3a2ba44Smacallan xf86Msg(X_ERROR, "msk %x\n", pMaskPicture->format); 963a3a2ba44Smacallan } 964f7cb851fSmacallan } 9654261fa58Smacallan if (pSrcPicture->pSourcePict != NULL) { 9664261fa58Smacallan if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { 9674261fa58Smacallan p->fillcolour = 9684261fa58Smacallan pSrcPicture->pSourcePict->solidFill.color; 969f7cb851fSmacallan DPRINTF(X_ERROR, "%s: solid src %08x\n", 9704261fa58Smacallan __func__, p->fillcolour); 971f7cb851fSmacallan p->no_source_pixmap = TRUE; 972f7cb851fSmacallan p->source_is_solid = TRUE; 9734261fa58Smacallan } 9744261fa58Smacallan } 9754261fa58Smacallan if ((pMaskPicture != NULL) && (pMaskPicture->pSourcePict != NULL)) { 9764261fa58Smacallan if (pMaskPicture->pSourcePict->type == 9774261fa58Smacallan SourcePictTypeSolidFill) { 9784261fa58Smacallan p->fillcolour = 9794261fa58Smacallan pMaskPicture->pSourcePict->solidFill.color; 980a3a2ba44Smacallan xf86Msg(X_ERROR, "%s: solid mask %08x\n", 9814261fa58Smacallan __func__, p->fillcolour); 9824261fa58Smacallan } 9834261fa58Smacallan } 9844261fa58Smacallan if (pMaskPicture != NULL) { 985239808baSmacallan p->mskoff = exaGetPixmapOffset(pMask); 9864261fa58Smacallan p->mskpitch = exaGetPixmapPitch(pMask); 9874261fa58Smacallan p->mskformat = pMaskPicture->format; 988a3a2ba44Smacallan } else { 989239808baSmacallan p->mskoff = 0; 990a3a2ba44Smacallan p->mskpitch = 0; 991a3a2ba44Smacallan p->mskformat = 0; 9924261fa58Smacallan } 993f7cb851fSmacallan if (pSrc != NULL) { 994f7cb851fSmacallan p->source_is_solid = 995f7cb851fSmacallan ((pSrc->drawable.width == 1) && (pSrc->drawable.height == 1)); 996f7cb851fSmacallan p->srcoff = exaGetPixmapOffset(pSrc); 997f7cb851fSmacallan p->srcpitch = exaGetPixmapPitch(pSrc); 998f7cb851fSmacallan if (p->source_is_solid) { 999f7cb851fSmacallan p->fillcolour = *(uint32_t *)(p->fb + p->srcoff); 1000f7cb851fSmacallan } 1001f7cb851fSmacallan } 10024261fa58Smacallan p->srcformat = pSrcPicture->format; 10034261fa58Smacallan p->dstformat = pDstPicture->format; 1004f7cb851fSmacallan 1005f7cb851fSmacallan if (p->source_is_solid) { 1006f7cb851fSmacallan uint32_t temp; 1007f7cb851fSmacallan 1008f7cb851fSmacallan /* stuff source colour into SX registers, swap as needed */ 1009f7cb851fSmacallan temp = p->fillcolour; 1010f7cb851fSmacallan switch (p->srcformat) { 1011f7cb851fSmacallan case PICT_a8r8g8b8: 1012f7cb851fSmacallan case PICT_x8r8g8b8: 1013f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(9), temp & 0xff); 1014f7cb851fSmacallan temp = temp >> 8; 1015f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(10), temp & 0xff); 1016f7cb851fSmacallan temp = temp >> 8; 1017f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(11), temp & 0xff); 1018f7cb851fSmacallan break; 1019f7cb851fSmacallan case PICT_a8b8g8r8: 1020f7cb851fSmacallan case PICT_x8b8g8r8: 1021f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(11), temp & 0xff); 1022f7cb851fSmacallan temp = temp >> 8; 1023f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(10), temp & 0xff); 1024f7cb851fSmacallan temp = temp >> 8; 1025f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(9), temp & 0xff); 1026f7cb851fSmacallan break; 1027f7cb851fSmacallan } 1028f7cb851fSmacallan write_sx_reg(p, SX_QUEUED(8), 0xff); 1029f7cb851fSmacallan } 10304261fa58Smacallan p->op = op; 1031a3a2ba44Smacallan if (op == PictOpSrc) { 1032a3a2ba44Smacallan CG14PrepareCopy(pSrc, pDst, 1, 1, GXcopy, 0xffffffff); 1033a3a2ba44Smacallan } 10344261fa58Smacallan#ifdef SX_DEBUG 10354261fa58Smacallan DPRINTF(X_ERROR, "%x %x -> %x\n", p->srcoff, p->mskoff, 10364261fa58Smacallan *(uint32_t *)(p->fb + p->srcoff)); 10374261fa58Smacallan#endif 10384261fa58Smacallan return TRUE; 10394261fa58Smacallan} 10404261fa58Smacallan 10414261fa58Smacallanvoid 10424261fa58SmacallanCG14Composite(PixmapPtr pDst, int srcX, int srcY, 10434261fa58Smacallan int maskX, int maskY, 10444261fa58Smacallan int dstX, int dstY, 10454261fa58Smacallan int width, int height) 10464261fa58Smacallan{ 10474261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 10484261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 10494261fa58Smacallan uint32_t dstoff, dstpitch; 10504261fa58Smacallan uint32_t dst, msk, src; 1051e311bbeeSmacallan int flip = 0; 10524261fa58Smacallan 10534261fa58Smacallan ENTER; 10544261fa58Smacallan dstoff = exaGetPixmapOffset(pDst); 10554261fa58Smacallan dstpitch = exaGetPixmapPitch(pDst); 10564261fa58Smacallan 1057e311bbeeSmacallan flip = (PICT_FORMAT_TYPE(p->srcformat) != 1058e311bbeeSmacallan PICT_FORMAT_TYPE(p->dstformat)); 1059e311bbeeSmacallan 10604261fa58Smacallan switch (p->op) { 10614261fa58Smacallan case PictOpOver: 10624261fa58Smacallan dst = dstoff + (dstY * dstpitch) + (dstX << 2); 10634261fa58Smacallan DPRINTF(X_ERROR, "Over %08x %08x, %d %d\n", 10644261fa58Smacallan p->mskformat, p->dstformat, srcX, srcY); 1065a3a2ba44Smacallan if (p->source_is_solid) { 1066a3a2ba44Smacallan switch (p->mskformat) { 1067a3a2ba44Smacallan case PICT_a8: 1068a3a2ba44Smacallan msk = p->mskoff + 1069a3a2ba44Smacallan (maskY * p->mskpitch) + 1070a3a2ba44Smacallan maskX; 1071a3a2ba44Smacallan CG14Comp_Over8Solid(p, 1072a3a2ba44Smacallan msk, p->mskpitch, 1073a3a2ba44Smacallan dst, dstpitch, 1074a3a2ba44Smacallan width, height); 1075a3a2ba44Smacallan break; 1076a3a2ba44Smacallan case PICT_a8r8g8b8: 1077a3a2ba44Smacallan case PICT_a8b8g8r8: 1078a3a2ba44Smacallan msk = p->mskoff + 1079a3a2ba44Smacallan (maskY * p->mskpitch) + 1080a3a2ba44Smacallan (maskX << 2); 1081a3a2ba44Smacallan CG14Comp_Over32Solid(p, 1082a3a2ba44Smacallan msk, p->mskpitch, 1083a3a2ba44Smacallan dst, dstpitch, 1084a3a2ba44Smacallan width, height); 1085a3a2ba44Smacallan break; 1086a3a2ba44Smacallan default: 1087a3a2ba44Smacallan xf86Msg(X_ERROR, 1088f71acd79Smacallan "unsupported mask format %08x\n", p->mskformat); 1089a3a2ba44Smacallan } 1090a3a2ba44Smacallan } else { 10916bdc2ffdSmacallan DPRINTF(X_ERROR, "non-solid over with msk %x\n", 10926bdc2ffdSmacallan p->mskformat); 1093a3a2ba44Smacallan switch (p->srcformat) { 1094a3a2ba44Smacallan case PICT_a8r8g8b8: 1095a3a2ba44Smacallan case PICT_a8b8g8r8: 1096a3a2ba44Smacallan src = p->srcoff + 1097a3a2ba44Smacallan (srcY * p->srcpitch) + 1098a3a2ba44Smacallan (srcX << 2); 1099a3a2ba44Smacallan dst = dstoff + 1100a3a2ba44Smacallan (dstY * dstpitch) + 1101a3a2ba44Smacallan (dstX << 2); 1102a3a2ba44Smacallan if (p->mskformat == PICT_a8) { 1103a3a2ba44Smacallan msk = p->mskoff + 1104a3a2ba44Smacallan (maskY * p->mskpitch) + 1105a3a2ba44Smacallan maskX; 1106a3a2ba44Smacallan CG14Comp_Over32Mask(p, 1107a3a2ba44Smacallan src, p->srcpitch, 1108a3a2ba44Smacallan msk, p->mskpitch, 1109a3a2ba44Smacallan dst, dstpitch, 1110e311bbeeSmacallan width, height, flip); 1111a3a2ba44Smacallan } else { 1112a3a2ba44Smacallan CG14Comp_Over32(p, 1113a3a2ba44Smacallan src, p->srcpitch, 1114a3a2ba44Smacallan dst, dstpitch, 1115e311bbeeSmacallan width, height, flip); 1116a3a2ba44Smacallan } 1117a3a2ba44Smacallan break; 1118a3a2ba44Smacallan case PICT_x8r8g8b8: 1119a3a2ba44Smacallan case PICT_x8b8g8r8: 11206bdc2ffdSmacallan src = p->srcoff + 11216bdc2ffdSmacallan (srcY * p->srcpitch) + 11226bdc2ffdSmacallan (srcX << 2); 11236bdc2ffdSmacallan dst = dstoff + 11246bdc2ffdSmacallan (dstY * dstpitch) + 11256bdc2ffdSmacallan (dstX << 2); 11266bdc2ffdSmacallan if (p->mskformat == PICT_a8) { 11276bdc2ffdSmacallan msk = p->mskoff + 11286bdc2ffdSmacallan (maskY * p->mskpitch) + 11296bdc2ffdSmacallan maskX; 11306bdc2ffdSmacallan CG14Comp_Over32Mask_noalpha(p, 11316bdc2ffdSmacallan src, p->srcpitch, 11326bdc2ffdSmacallan msk, p->mskpitch, 1133fa158432Smacallan dst, dstpitch, 1134e311bbeeSmacallan width, height, flip); 1135fa158432Smacallan } else if ((p->mskformat == PICT_a8r8g8b8) || 1136fa158432Smacallan (p->mskformat == PICT_a8b8g8r8)) { 1137fa158432Smacallan msk = p->mskoff + 1138fa158432Smacallan (maskY * p->mskpitch) + 1139fa158432Smacallan (maskX << 2); 1140fa158432Smacallan CG14Comp_Over32Mask32_noalpha(p, 1141fa158432Smacallan src, p->srcpitch, 1142fa158432Smacallan msk, p->mskpitch, 11436bdc2ffdSmacallan dst, dstpitch, 1144e311bbeeSmacallan width, height, flip); 11456bdc2ffdSmacallan } else { 11466bdc2ffdSmacallan xf86Msg(X_ERROR, "no src alpha, mask is %x\n", p->mskformat); 11476bdc2ffdSmacallan } 1148a3a2ba44Smacallan break; 1149a3a2ba44Smacallan default: 1150a3a2ba44Smacallan xf86Msg(X_ERROR, "%s: format %x in non-solid Over op\n", 1151a3a2ba44Smacallan __func__, p->srcformat); 1152a3a2ba44Smacallan } 1153a3a2ba44Smacallan } 11544261fa58Smacallan break; 11554261fa58Smacallan case PictOpAdd: 11564261fa58Smacallan DPRINTF(X_ERROR, "Add %08x %08x\n", 11574261fa58Smacallan p->srcformat, p->dstformat); 11584261fa58Smacallan switch (p->srcformat) { 11594261fa58Smacallan case PICT_a8: 11604261fa58Smacallan src = p->srcoff + 11614261fa58Smacallan (srcY * p->srcpitch) + srcX; 1162d71cb32dSmacallan if (p->dstformat == PICT_a8) { 1163d71cb32dSmacallan dst = dstoff + 1164d71cb32dSmacallan (dstY * dstpitch) + dstX; 1165d71cb32dSmacallan CG14Comp_Add8(p, 1166d71cb32dSmacallan src, p->srcpitch, 1167d71cb32dSmacallan dst, dstpitch, 1168d71cb32dSmacallan width, height); 1169d71cb32dSmacallan } else { 1170d71cb32dSmacallan dst = dstoff + 1171d71cb32dSmacallan (dstY * dstpitch) + 1172d71cb32dSmacallan (dstX << 2); 1173d71cb32dSmacallan CG14Comp_Add8_32(p, 1174d71cb32dSmacallan src, p->srcpitch, 1175d71cb32dSmacallan dst, dstpitch, 1176d71cb32dSmacallan width, height); 1177d71cb32dSmacallan } 11784261fa58Smacallan break; 11794261fa58Smacallan case PICT_a8r8g8b8: 11804261fa58Smacallan case PICT_x8r8g8b8: 11814261fa58Smacallan src = p->srcoff + 11824261fa58Smacallan (srcY * p->srcpitch) + (srcX << 2); 11834261fa58Smacallan dst = dstoff + (dstY * dstpitch) + 11844261fa58Smacallan (dstX << 2); 11854261fa58Smacallan CG14Comp_Add32(p, src, p->srcpitch, 11864261fa58Smacallan dst, dstpitch, width, height); 11874261fa58Smacallan break; 11884261fa58Smacallan default: 11894261fa58Smacallan xf86Msg(X_ERROR, 11904261fa58Smacallan "unsupported src format\n"); 11914261fa58Smacallan } 11924261fa58Smacallan break; 1193a3a2ba44Smacallan case PictOpSrc: 1194a3a2ba44Smacallan DPRINTF(X_ERROR, "Src %08x %08x\n", 1195a3a2ba44Smacallan p->srcformat, p->dstformat); 1196239808baSmacallan if (p->mskformat != 0) 1197239808baSmacallan xf86Msg(X_ERROR, "Src mask %08x\n", p->mskformat); 1198f71acd79Smacallan if (p->srcformat == PICT_a8) { 1199f71acd79Smacallan CG14Copy8(pDst, srcX, srcY, dstX, dstY, width, height); 1200f71acd79Smacallan } else { 1201f71acd79Smacallan /* convert between RGB and BGR? */ 1202f71acd79Smacallan CG14Copy32(pDst, srcX, srcY, dstX, dstY, width, height); 1203f71acd79Smacallan } 1204a3a2ba44Smacallan break; 12054261fa58Smacallan default: 12064261fa58Smacallan xf86Msg(X_ERROR, "unsupported op %d\n", p->op); 12074261fa58Smacallan } 12084261fa58Smacallan exaMarkSync(pDst->drawable.pScreen); 12094261fa58Smacallan} 12104261fa58Smacallan 12114261fa58Smacallan 12124261fa58Smacallan 12134261fa58SmacallanBool 12144261fa58SmacallanCG14InitAccel(ScreenPtr pScreen) 12154261fa58Smacallan{ 12164261fa58Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 12174261fa58Smacallan Cg14Ptr p = GET_CG14_FROM_SCRN(pScrn); 12184261fa58Smacallan ExaDriverPtr pExa; 12194261fa58Smacallan 12204261fa58Smacallan pExa = exaDriverAlloc(); 12214261fa58Smacallan if (!pExa) 12224261fa58Smacallan return FALSE; 12234261fa58Smacallan 12244261fa58Smacallan p->pExa = pExa; 12254261fa58Smacallan 12264261fa58Smacallan pExa->exa_major = EXA_VERSION_MAJOR; 12274261fa58Smacallan pExa->exa_minor = EXA_VERSION_MINOR; 12284261fa58Smacallan 12294261fa58Smacallan pExa->memoryBase = p->fb; 12304261fa58Smacallan pExa->memorySize = p->memsize; 1231b8ad197aSmacallan pExa->offScreenBase = p->width * p->height * (pScrn->depth >> 3); 12324261fa58Smacallan 12334261fa58Smacallan /* 12344261fa58Smacallan * SX memory instructions are written to 64bit aligned addresses with 12354261fa58Smacallan * a 3 bit displacement. Make sure the displacement remains constant 12364261fa58Smacallan * within one column 12374261fa58Smacallan */ 12384261fa58Smacallan 12394261fa58Smacallan pExa->pixmapOffsetAlign = 8; 12404261fa58Smacallan pExa->pixmapPitchAlign = 8; 12414261fa58Smacallan 1242fe97f391Smacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS 1243f71acd79Smacallan | EXA_SUPPORTS_OFFSCREEN_OVERLAPS 1244f71acd79Smacallan /*| EXA_MIXED_PIXMAPS*/; 12454261fa58Smacallan 12464261fa58Smacallan /* 12474261fa58Smacallan * these limits are bogus 12484261fa58Smacallan * SX doesn't deal with coordinates at all, so there is no limit but 12494261fa58Smacallan * we have to put something here 12504261fa58Smacallan */ 12514261fa58Smacallan pExa->maxX = 4096; 12524261fa58Smacallan pExa->maxY = 4096; 12534261fa58Smacallan 12544261fa58Smacallan pExa->WaitMarker = CG14WaitMarker; 12554261fa58Smacallan 12564261fa58Smacallan pExa->PrepareSolid = CG14PrepareSolid; 12574261fa58Smacallan pExa->Solid = CG14Solid; 12584261fa58Smacallan pExa->DoneSolid = CG14DoneCopy; 12594261fa58Smacallan pExa->PrepareCopy = CG14PrepareCopy; 1260f71acd79Smacallan pExa->Copy = CG14Copy32; 12614261fa58Smacallan pExa->DoneCopy = CG14DoneCopy; 12624261fa58Smacallan if (p->use_xrender) { 12634261fa58Smacallan pExa->CheckComposite = CG14CheckComposite; 12644261fa58Smacallan pExa->PrepareComposite = CG14PrepareComposite; 12654261fa58Smacallan pExa->Composite = CG14Composite; 12664261fa58Smacallan pExa->DoneComposite = CG14DoneCopy; 12674261fa58Smacallan } 12684261fa58Smacallan 12694261fa58Smacallan /* EXA hits more optimized paths when it does not have to fallback 12704261fa58Smacallan * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 12714261fa58Smacallan */ 12724261fa58Smacallan pExa->UploadToScreen = CG14UploadToScreen; 12734261fa58Smacallan pExa->DownloadFromScreen = CG14DownloadFromScreen; 12744261fa58Smacallan 1275c2193d98Smacallan p->queuecount = 0; 12764261fa58Smacallan /* do some hardware init */ 12774261fa58Smacallan write_sx_reg(p, SX_PLANEMASK, 0xffffffff); 12784261fa58Smacallan p->last_mask = 0xffffffff; 12794261fa58Smacallan write_sx_reg(p, SX_ROP_CONTROL, 0xcc); 12804261fa58Smacallan p->last_rop = 0xcc; 12814261fa58Smacallan return exaDriverInit(pScreen, pExa); 12824261fa58Smacallan} 1283