via_exa.c revision 963d66ac
190b17f1bSmrg/* 290b17f1bSmrg * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. 390b17f1bSmrg * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 490b17f1bSmrg * Copyright 2006 Thomas Hellström. All Rights Reserved. 590b17f1bSmrg * 690b17f1bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 790b17f1bSmrg * copy of this software and associated documentation files (the "Software"), 890b17f1bSmrg * to deal in the Software without restriction, including without limitation 990b17f1bSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 1090b17f1bSmrg * and/or sell copies of the Software, and to permit persons to whom the 1190b17f1bSmrg * Software is furnished to do so, subject to the following conditions: 1290b17f1bSmrg * 1390b17f1bSmrg * The above copyright notice and this permission notice (including the 1490b17f1bSmrg * next paragraph) shall be included in all copies or substantial portions 1590b17f1bSmrg * of the Software. 1690b17f1bSmrg * 1790b17f1bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1890b17f1bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1990b17f1bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 2090b17f1bSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2190b17f1bSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2290b17f1bSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2390b17f1bSmrg * DEALINGS IN THE SOFTWARE. 2490b17f1bSmrg */ 2590b17f1bSmrg 2690b17f1bSmrg/* 2790b17f1bSmrg * 2D acceleration functions for the VIA/S3G UniChrome IGPs. 2890b17f1bSmrg * 2990b17f1bSmrg * Mostly rewritten, and modified for EXA support, by Thomas Hellström. 3090b17f1bSmrg */ 3190b17f1bSmrg 3290b17f1bSmrg#ifdef HAVE_CONFIG_H 3390b17f1bSmrg#include "config.h" 3490b17f1bSmrg#endif 3590b17f1bSmrg 3690b17f1bSmrg#include <X11/Xarch.h> 3790b17f1bSmrg#include "miline.h" 3890b17f1bSmrg 3990b17f1bSmrg#include <GL/gl.h> 4090b17f1bSmrg#include <sys/mman.h> 4190b17f1bSmrg 4290b17f1bSmrg#include "via_driver.h" 4390b17f1bSmrg#include "via_regs.h" 4490b17f1bSmrg#include "via_dmabuffer.h" 4590b17f1bSmrg#include "via_rop.h" 4690b17f1bSmrg 4790b17f1bSmrg/* 4890b17f1bSmrg * Use PCI MMIO to flush the command buffer when AGP DMA is not available. 4990b17f1bSmrg */ 5090b17f1bSmrgstatic void 5190b17f1bSmrgviaDumpDMA(ViaCommandBuffer *cb) 5290b17f1bSmrg{ 5390b17f1bSmrg register CARD32 *bp = cb->buf; 5490b17f1bSmrg CARD32 *endp = bp + cb->pos; 5590b17f1bSmrg 5690b17f1bSmrg while (bp != endp) { 5790b17f1bSmrg if (((bp - cb->buf) & 3) == 0) { 5890b17f1bSmrg ErrorF("\n %04lx: ", (unsigned long)(bp - cb->buf)); 5990b17f1bSmrg } 6090b17f1bSmrg ErrorF("0x%08x ", (unsigned)*bp++); 6190b17f1bSmrg } 6290b17f1bSmrg ErrorF("\n"); 6390b17f1bSmrg} 6490b17f1bSmrg 6590b17f1bSmrgvoid 6690b17f1bSmrgviaFlushPCI(ViaCommandBuffer *cb) 6790b17f1bSmrg{ 6890b17f1bSmrg register CARD32 *bp = cb->buf; 6990b17f1bSmrg CARD32 transSetting; 7090b17f1bSmrg CARD32 *endp = bp + cb->pos; 7190b17f1bSmrg unsigned loop = 0; 7290b17f1bSmrg register CARD32 offset = 0; 7390b17f1bSmrg register CARD32 value; 7490b17f1bSmrg VIAPtr pVia = VIAPTR(cb->pScrn); 7590b17f1bSmrg 7690b17f1bSmrg while (bp < endp) { 7790b17f1bSmrg if (*bp == HALCYON_HEADER2) { 7890b17f1bSmrg if (++bp == endp) 7990b17f1bSmrg return; 8090b17f1bSmrg VIASETREG(VIA_REG_TRANSET, transSetting = *bp++); 8190b17f1bSmrg while (bp < endp) { 8290b17f1bSmrg if ((transSetting != HC_ParaType_CmdVdata) 8390b17f1bSmrg && ((*bp == HALCYON_HEADER2) 8490b17f1bSmrg || (*bp & HALCYON_HEADER1MASK) == HALCYON_HEADER1)) 8590b17f1bSmrg break; 8690b17f1bSmrg VIASETREG(VIA_REG_TRANSPACE, *bp++); 8790b17f1bSmrg } 8890b17f1bSmrg } else if ((*bp & HALCYON_HEADER1MASK) == HALCYON_HEADER1) { 8990b17f1bSmrg 9090b17f1bSmrg while (bp < endp) { 9190b17f1bSmrg if (*bp == HALCYON_HEADER2) 9290b17f1bSmrg break; 9390b17f1bSmrg if (offset == 0) { 9490b17f1bSmrg /* 9590b17f1bSmrg * Not doing this wait will probably stall the processor 9690b17f1bSmrg * for an unacceptable amount of time in VIASETREG while 9790b17f1bSmrg * other high priority interrupts may be pending. 9890b17f1bSmrg */ 9990b17f1bSmrg switch (pVia->Chipset) { 10090b17f1bSmrg case VIA_VX800: 10190b17f1bSmrg case VIA_VX855: 10290b17f1bSmrg case VIA_VX900: 10390b17f1bSmrg while ((VIAGETREG(VIA_REG_STATUS) & 10490b17f1bSmrg (VIA_CMD_RGTR_BUSY_H5 | VIA_2D_ENG_BUSY_H5)) && 10590b17f1bSmrg (loop++ < MAXLOOP)) ; 10690b17f1bSmrg break; 10790b17f1bSmrg 10890b17f1bSmrg case VIA_P4M890: 109963d66acSmrg case VIA_K8M890: 11090b17f1bSmrg case VIA_P4M900: 11190b17f1bSmrg while ((VIAGETREG(VIA_REG_STATUS) & 11290b17f1bSmrg (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY)) && 11390b17f1bSmrg (loop++ < MAXLOOP)) ; 11490b17f1bSmrg break; 11590b17f1bSmrg 11690b17f1bSmrg default: 11790b17f1bSmrg while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_EMPTY) && 11890b17f1bSmrg (loop++ < MAXLOOP)) ; 11990b17f1bSmrg while ((VIAGETREG(VIA_REG_STATUS) & 12090b17f1bSmrg (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY)) && 12190b17f1bSmrg (loop++ < MAXLOOP)) ; 12290b17f1bSmrg } 12390b17f1bSmrg } 12490b17f1bSmrg offset = (*bp++ & 0x0FFFFFFF) << 2; 12590b17f1bSmrg value = *bp++; 12690b17f1bSmrg VIASETREG(offset, value); 12790b17f1bSmrg } 12890b17f1bSmrg } else { 12990b17f1bSmrg ErrorF("Command stream parser error.\n"); 13090b17f1bSmrg } 13190b17f1bSmrg } 13290b17f1bSmrg cb->pos = 0; 13390b17f1bSmrg cb->mode = 0; 13490b17f1bSmrg cb->has3dState = FALSE; 13590b17f1bSmrg} 13690b17f1bSmrg 13790b17f1bSmrg#ifdef HAVE_DRI 13890b17f1bSmrg/* 13990b17f1bSmrg * Flush the command buffer using DRM. If in PCI mode, we can bypass DRM, 14090b17f1bSmrg * but not for command buffers that contain 3D engine state, since then 14190b17f1bSmrg * the DRM command verifier will lose track of the 3D engine state. 14290b17f1bSmrg */ 14390b17f1bSmrgstatic void 14490b17f1bSmrgviaFlushDRIEnabled(ViaCommandBuffer *cb) 14590b17f1bSmrg{ 14690b17f1bSmrg ScrnInfoPtr pScrn = cb->pScrn; 14790b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 14890b17f1bSmrg char *tmp = (char *)cb->buf; 14990b17f1bSmrg int tmpSize; 15090b17f1bSmrg drm_via_cmdbuffer_t b; 15190b17f1bSmrg 15290b17f1bSmrg /* Align end of command buffer for AGP DMA. */ 15390b17f1bSmrg OUT_RING_H1(0x2f8, 0x67676767); 15490b17f1bSmrg if (pVia->agpDMA && cb->mode == 2 && cb->rindex != HC_ParaType_CmdVdata 15590b17f1bSmrg && (cb->pos & 1)) { 15690b17f1bSmrg OUT_RING(HC_DUMMY); 15790b17f1bSmrg } 15890b17f1bSmrg 15990b17f1bSmrg tmpSize = cb->pos * sizeof(CARD32); 16090b17f1bSmrg if (pVia->agpDMA || (pVia->directRenderingType && cb->has3dState)) { 16190b17f1bSmrg cb->mode = 0; 16290b17f1bSmrg cb->has3dState = FALSE; 16390b17f1bSmrg while (tmpSize > 0) { 16490b17f1bSmrg b.size = (tmpSize > VIA_DMASIZE) ? VIA_DMASIZE : tmpSize; 16590b17f1bSmrg tmpSize -= b.size; 16690b17f1bSmrg b.buf = tmp; 16790b17f1bSmrg tmp += b.size; 16890b17f1bSmrg if (drmCommandWrite(pVia->drmmode.fd, ((pVia->agpDMA) 16990b17f1bSmrg ? DRM_VIA_CMDBUFFER : 17090b17f1bSmrg DRM_VIA_PCICMD), &b, sizeof(b))) { 17190b17f1bSmrg ErrorF("DRM command buffer submission failed.\n"); 17290b17f1bSmrg viaDumpDMA(cb); 17390b17f1bSmrg return; 17490b17f1bSmrg } 17590b17f1bSmrg } 17690b17f1bSmrg cb->pos = 0; 17790b17f1bSmrg } else { 17890b17f1bSmrg viaFlushPCI(cb); 17990b17f1bSmrg } 18090b17f1bSmrg} 18190b17f1bSmrg#endif 18290b17f1bSmrg 18390b17f1bSmrg/* 18490b17f1bSmrg * Initialize a command buffer. Some fields are currently not used since they 18590b17f1bSmrg * are intended for Unichrome Pro group A video commands. 18690b17f1bSmrg */ 18790b17f1bSmrgstatic int 18890b17f1bSmrgviaSetupCBuffer(ScrnInfoPtr pScrn, ViaCommandBuffer *cb, unsigned size) 18990b17f1bSmrg{ 19090b17f1bSmrg#ifdef HAVE_DRI 19190b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 19290b17f1bSmrg#endif 19390b17f1bSmrg 19490b17f1bSmrg cb->pScrn = pScrn; 19590b17f1bSmrg cb->bufSize = ((size == 0) ? VIA_DMASIZE : size) >> 2; 19690b17f1bSmrg cb->buf = (CARD32 *) calloc(cb->bufSize, sizeof(CARD32)); 19790b17f1bSmrg if (!cb->buf) 19890b17f1bSmrg return BadAlloc; 19990b17f1bSmrg cb->waitFlags = 0; 20090b17f1bSmrg cb->pos = 0; 20190b17f1bSmrg cb->mode = 0; 20290b17f1bSmrg cb->header_start = 0; 20390b17f1bSmrg cb->rindex = 0; 20490b17f1bSmrg cb->has3dState = FALSE; 20590b17f1bSmrg cb->flushFunc = viaFlushPCI; 20690b17f1bSmrg#ifdef HAVE_DRI 20790b17f1bSmrg if (pVia->directRenderingType == DRI_1) { 20890b17f1bSmrg cb->flushFunc = viaFlushDRIEnabled; 20990b17f1bSmrg } 21090b17f1bSmrg#endif 21190b17f1bSmrg return Success; 21290b17f1bSmrg} 21390b17f1bSmrg 21490b17f1bSmrg/* 21590b17f1bSmrg * Free resources associated with a command buffer. 21690b17f1bSmrg */ 21790b17f1bSmrgstatic void 21890b17f1bSmrgviaTearDownCBuffer(ViaCommandBuffer *cb) 21990b17f1bSmrg{ 220963d66acSmrg if (cb && cb->buf) { 22190b17f1bSmrg free(cb->buf); 222963d66acSmrg cb->buf = NULL; 223963d66acSmrg } 22490b17f1bSmrg} 22590b17f1bSmrg 22690b17f1bSmrg/* 22790b17f1bSmrg * Update our 2D state (TwoDContext) with a new mode. 22890b17f1bSmrg */ 22990b17f1bSmrgBool 23090b17f1bSmrgviaAccelSetMode(int bpp, ViaTwodContext * tdc) 23190b17f1bSmrg{ 23290b17f1bSmrg switch (bpp) { 23390b17f1bSmrg case 16: 23490b17f1bSmrg tdc->mode = VIA_GEM_16bpp; 23590b17f1bSmrg tdc->bytesPPShift = 1; 23690b17f1bSmrg return TRUE; 23790b17f1bSmrg case 32: 23890b17f1bSmrg tdc->mode = VIA_GEM_32bpp; 23990b17f1bSmrg tdc->bytesPPShift = 2; 24090b17f1bSmrg return TRUE; 24190b17f1bSmrg case 8: 24290b17f1bSmrg tdc->mode = VIA_GEM_8bpp; 24390b17f1bSmrg tdc->bytesPPShift = 0; 24490b17f1bSmrg return TRUE; 24590b17f1bSmrg default: 24690b17f1bSmrg tdc->bytesPPShift = 0; 24790b17f1bSmrg return FALSE; 24890b17f1bSmrg } 24990b17f1bSmrg} 25090b17f1bSmrg 25190b17f1bSmrg/* 25290b17f1bSmrg * Switch 2D state clipping on. 25390b17f1bSmrg */ 25490b17f1bSmrgvoid 25590b17f1bSmrgviaSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) 25690b17f1bSmrg{ 25790b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 25890b17f1bSmrg ViaTwodContext *tdc = &pVia->td; 25990b17f1bSmrg 26090b17f1bSmrg tdc->clipping = TRUE; 26190b17f1bSmrg tdc->clipX1 = (x1 & 0xFFFF); 26290b17f1bSmrg tdc->clipY1 = y1; 26390b17f1bSmrg tdc->clipX2 = (x2 & 0xFFFF); 26490b17f1bSmrg tdc->clipY2 = y2; 26590b17f1bSmrg} 26690b17f1bSmrg 26790b17f1bSmrg/* 26890b17f1bSmrg * Check if we need to force upload of the whole 3D state (when other 26990b17f1bSmrg * clients or subsystems have touched the 3D engine). Also tell DRI 27090b17f1bSmrg * clients and subsystems that we have touched the 3D engine. 27190b17f1bSmrg */ 27290b17f1bSmrgBool 27390b17f1bSmrgviaCheckUpload(ScrnInfoPtr pScrn, Via3DState * v3d) 27490b17f1bSmrg{ 27590b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 27690b17f1bSmrg Bool forceUpload; 27790b17f1bSmrg 27890b17f1bSmrg forceUpload = (pVia->lastToUpload != v3d); 27990b17f1bSmrg pVia->lastToUpload = v3d; 28090b17f1bSmrg 28190b17f1bSmrg#ifdef HAVE_DRI 28290b17f1bSmrg if (pVia->directRenderingType == DRI_1) { 28390b17f1bSmrg volatile drm_via_sarea_t *saPriv = (drm_via_sarea_t *) 28490b17f1bSmrg DRIGetSAREAPrivate(pScrn->pScreen); 28590b17f1bSmrg int myContext = DRIGetContext(pScrn->pScreen); 28690b17f1bSmrg 28790b17f1bSmrg forceUpload = forceUpload || (saPriv->ctxOwner != myContext); 28890b17f1bSmrg saPriv->ctxOwner = myContext; 28990b17f1bSmrg } 29090b17f1bSmrg#endif 29190b17f1bSmrg return forceUpload; 29290b17f1bSmrg} 29390b17f1bSmrg 29490b17f1bSmrgBool 29590b17f1bSmrgviaOrder(CARD32 val, CARD32 * shift) 29690b17f1bSmrg{ 29790b17f1bSmrg *shift = 0; 29890b17f1bSmrg 29990b17f1bSmrg while (val > (1 << *shift)) 30090b17f1bSmrg (*shift)++; 30190b17f1bSmrg return (val == (1 << *shift)); 30290b17f1bSmrg} 30390b17f1bSmrg 30490b17f1bSmrg/* 30590b17f1bSmrg * Helper for bitdepth expansion. 30690b17f1bSmrg */ 30790b17f1bSmrgCARD32 30890b17f1bSmrgviaBitExpandHelper(CARD32 pixel, CARD32 bits) 30990b17f1bSmrg{ 31090b17f1bSmrg CARD32 component, mask, tmp; 31190b17f1bSmrg 31290b17f1bSmrg component = pixel & ((1 << bits) - 1); 31390b17f1bSmrg mask = (1 << (8 - bits)) - 1; 31490b17f1bSmrg tmp = component << (8 - bits); 31590b17f1bSmrg return ((component & 1) ? (tmp | mask) : tmp); 31690b17f1bSmrg} 31790b17f1bSmrg 31890b17f1bSmrg/* 31990b17f1bSmrg * Extract the components from a pixel of the given format to an argb8888 pixel. * This is used to extract data from one-pixel repeat pixmaps. 32090b17f1bSmrg * Assumes little endian. 32190b17f1bSmrg */ 32290b17f1bSmrgvoid 32390b17f1bSmrgviaPixelARGB8888(unsigned format, void *pixelP, CARD32 * argb8888) 32490b17f1bSmrg{ 32590b17f1bSmrg CARD32 bits, shift, pixel, bpp; 32690b17f1bSmrg 32790b17f1bSmrg bpp = PICT_FORMAT_BPP(format); 32890b17f1bSmrg 32990b17f1bSmrg if (bpp <= 8) { 33090b17f1bSmrg pixel = *((CARD8 *) pixelP); 33190b17f1bSmrg } else if (bpp <= 16) { 33290b17f1bSmrg pixel = *((CARD16 *) pixelP); 33390b17f1bSmrg } else { 33490b17f1bSmrg pixel = *((CARD32 *) pixelP); 33590b17f1bSmrg } 33690b17f1bSmrg 33790b17f1bSmrg switch (PICT_FORMAT_TYPE(format)) { 33890b17f1bSmrg case PICT_TYPE_A: 33990b17f1bSmrg bits = PICT_FORMAT_A(format); 34090b17f1bSmrg *argb8888 = viaBitExpandHelper(pixel, bits) << 24; 34190b17f1bSmrg return; 34290b17f1bSmrg case PICT_TYPE_ARGB: 34390b17f1bSmrg shift = 0; 34490b17f1bSmrg bits = PICT_FORMAT_B(format); 34590b17f1bSmrg *argb8888 = viaBitExpandHelper(pixel, bits); 34690b17f1bSmrg shift += bits; 34790b17f1bSmrg bits = PICT_FORMAT_G(format); 34890b17f1bSmrg *argb8888 |= viaBitExpandHelper(pixel >> shift, bits) << 8; 34990b17f1bSmrg shift += bits; 35090b17f1bSmrg bits = PICT_FORMAT_R(format); 35190b17f1bSmrg *argb8888 |= viaBitExpandHelper(pixel >> shift, bits) << 16; 35290b17f1bSmrg shift += bits; 35390b17f1bSmrg bits = PICT_FORMAT_A(format); 35490b17f1bSmrg *argb8888 |= ((bits) ? viaBitExpandHelper(pixel >> shift, 35590b17f1bSmrg bits) : 0xFF) << 24; 35690b17f1bSmrg return; 35790b17f1bSmrg case PICT_TYPE_ABGR: 35890b17f1bSmrg shift = 0; 35990b17f1bSmrg bits = PICT_FORMAT_B(format); 36090b17f1bSmrg *argb8888 = viaBitExpandHelper(pixel, bits) << 16; 36190b17f1bSmrg shift += bits; 36290b17f1bSmrg bits = PICT_FORMAT_G(format); 36390b17f1bSmrg *argb8888 |= viaBitExpandHelper(pixel >> shift, bits) << 8; 36490b17f1bSmrg shift += bits; 36590b17f1bSmrg bits = PICT_FORMAT_R(format); 36690b17f1bSmrg *argb8888 |= viaBitExpandHelper(pixel >> shift, bits); 36790b17f1bSmrg shift += bits; 36890b17f1bSmrg bits = PICT_FORMAT_A(format); 36990b17f1bSmrg *argb8888 |= ((bits) ? viaBitExpandHelper(pixel >> shift, 37090b17f1bSmrg bits) : 0xFF) << 24; 37190b17f1bSmrg return; 37290b17f1bSmrg default: 37390b17f1bSmrg break; 37490b17f1bSmrg } 37590b17f1bSmrg return; 37690b17f1bSmrg} 37790b17f1bSmrg 37890b17f1bSmrgBool 37990b17f1bSmrgviaExpandablePixel(int format) 38090b17f1bSmrg{ 38190b17f1bSmrg int formatType = PICT_FORMAT_TYPE(format); 38290b17f1bSmrg 38390b17f1bSmrg return (formatType == PICT_TYPE_A || 38490b17f1bSmrg formatType == PICT_TYPE_ABGR || formatType == PICT_TYPE_ARGB); 38590b17f1bSmrg} 38690b17f1bSmrg 38790b17f1bSmrg#ifdef VIA_DEBUG_COMPOSITE 38890b17f1bSmrgvoid 38990b17f1bSmrgviaExaCompositePictDesc(PicturePtr pict, char *string, int n) 39090b17f1bSmrg{ 39190b17f1bSmrg char format[20]; 39290b17f1bSmrg char size[20]; 39390b17f1bSmrg 39490b17f1bSmrg if (!pict) { 39590b17f1bSmrg snprintf(string, n, "None"); 39690b17f1bSmrg return; 39790b17f1bSmrg } 39890b17f1bSmrg 39990b17f1bSmrg switch (pict->format) { 40090b17f1bSmrg case PICT_x8r8g8b8: 40190b17f1bSmrg snprintf(format, 20, "RGB8888"); 40290b17f1bSmrg break; 40390b17f1bSmrg case PICT_a8r8g8b8: 40490b17f1bSmrg snprintf(format, 20, "ARGB8888"); 40590b17f1bSmrg break; 40690b17f1bSmrg case PICT_r5g6b5: 40790b17f1bSmrg snprintf(format, 20, "RGB565 "); 40890b17f1bSmrg break; 40990b17f1bSmrg case PICT_x1r5g5b5: 41090b17f1bSmrg snprintf(format, 20, "RGB555 "); 41190b17f1bSmrg break; 41290b17f1bSmrg case PICT_a8: 41390b17f1bSmrg snprintf(format, 20, "A8 "); 41490b17f1bSmrg break; 41590b17f1bSmrg case PICT_a1: 41690b17f1bSmrg snprintf(format, 20, "A1 "); 41790b17f1bSmrg break; 41890b17f1bSmrg default: 41990b17f1bSmrg snprintf(format, 20, "0x%x", (int)pict->format); 42090b17f1bSmrg break; 42190b17f1bSmrg } 42290b17f1bSmrg 42390b17f1bSmrg if (pict->pDrawable) { 42490b17f1bSmrg snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, 42590b17f1bSmrg pict->pDrawable->height, pict->repeat ? " R" : ""); 42690b17f1bSmrg 42790b17f1bSmrg snprintf(string, n, "0x%lx: fmt %s (%s)", (long)pict->pDrawable, format, 42890b17f1bSmrg size); 42990b17f1bSmrg } 43090b17f1bSmrg} 43190b17f1bSmrg 43290b17f1bSmrgvoid 43390b17f1bSmrgviaExaPrintCompositeInfo(char *info, CARD8 op, PicturePtr pSrc, PicturePtr pMask, 43490b17f1bSmrg PicturePtr pDst) 43590b17f1bSmrg{ 43690b17f1bSmrg char sop[20]; 43790b17f1bSmrg char srcdesc[40], maskdesc[40], dstdesc[40]; 43890b17f1bSmrg 43990b17f1bSmrg switch (op) { 44090b17f1bSmrg case PictOpClear: 44190b17f1bSmrg sprintf(sop, "PictOpClear "); 44290b17f1bSmrg break; 44390b17f1bSmrg case PictOpSrc: 44490b17f1bSmrg sprintf(sop, "PictOpSrc "); 44590b17f1bSmrg break; 44690b17f1bSmrg case PictOpDst: 44790b17f1bSmrg sprintf(sop, "PictOpDst "); 44890b17f1bSmrg break; 44990b17f1bSmrg case PictOpOver: 45090b17f1bSmrg sprintf(sop, "PictOpOver "); 45190b17f1bSmrg break; 45290b17f1bSmrg case PictOpOutReverse: 45390b17f1bSmrg sprintf(sop, "PictOpOutReverse "); 45490b17f1bSmrg break; 45590b17f1bSmrg case PictOpAdd: 45690b17f1bSmrg sprintf(sop, "PictOpAdd "); 45790b17f1bSmrg break; 45890b17f1bSmrg default: 45990b17f1bSmrg sprintf(sop, "PictOp%d ", op); 46090b17f1bSmrg } 46190b17f1bSmrg 46290b17f1bSmrg viaExaCompositePictDesc(pSrc, srcdesc, 40); 46390b17f1bSmrg viaExaCompositePictDesc(pMask, maskdesc, 40); 46490b17f1bSmrg viaExaCompositePictDesc(pDst, dstdesc, 40); 46590b17f1bSmrg 46690b17f1bSmrg ErrorF("Composite fallback: %s, \n" 46790b17f1bSmrg " op %s, \n" 46890b17f1bSmrg " src %s, \n" 46990b17f1bSmrg " mask %s, \n" 47090b17f1bSmrg " dst %s, \n", info, sop, srcdesc, maskdesc, dstdesc); 47190b17f1bSmrg} 47290b17f1bSmrg#endif /* VIA_DEBUG_COMPOSITE */ 47390b17f1bSmrg 47490b17f1bSmrg/* 47590b17f1bSmrg * Wait for acceleration engines idle. An expensive way to sync. 47690b17f1bSmrg */ 47790b17f1bSmrgvoid 47890b17f1bSmrgviaAccelSync(ScrnInfoPtr pScrn) 47990b17f1bSmrg{ 48090b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 48190b17f1bSmrg int loop = 0; 48290b17f1bSmrg 48390b17f1bSmrg mem_barrier(); 48490b17f1bSmrg 48590b17f1bSmrg switch (pVia->Chipset) { 48690b17f1bSmrg case VIA_VX800: 48790b17f1bSmrg case VIA_VX855: 48890b17f1bSmrg case VIA_VX900: 48990b17f1bSmrg while ((VIAGETREG(VIA_REG_STATUS) & 49090b17f1bSmrg (VIA_CMD_RGTR_BUSY_H5 | VIA_2D_ENG_BUSY_H5 | VIA_3D_ENG_BUSY_H5)) 49190b17f1bSmrg && (loop++ < MAXLOOP)) ; 49290b17f1bSmrg break; 49390b17f1bSmrg case VIA_P4M890: 49490b17f1bSmrg case VIA_K8M890: 49590b17f1bSmrg case VIA_P4M900: 49690b17f1bSmrg while ((VIAGETREG(VIA_REG_STATUS) & 49790b17f1bSmrg (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) 49890b17f1bSmrg && (loop++ < MAXLOOP)) ; 49990b17f1bSmrg break; 50090b17f1bSmrg default: 50190b17f1bSmrg while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_EMPTY) 50290b17f1bSmrg && (loop++ < MAXLOOP)) ; 50390b17f1bSmrg 50490b17f1bSmrg while ((VIAGETREG(VIA_REG_STATUS) & 50590b17f1bSmrg (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) 50690b17f1bSmrg && (loop++ < MAXLOOP)) ; 50790b17f1bSmrg break; 50890b17f1bSmrg } 50990b17f1bSmrg} 51090b17f1bSmrg 51190b17f1bSmrg/* 51290b17f1bSmrg * Wait for the value to get blitted, or in the PCI case for engine idle. 51390b17f1bSmrg */ 51490b17f1bSmrgstatic void 51590b17f1bSmrgviaAccelWaitMarker(ScreenPtr pScreen, int marker) 51690b17f1bSmrg{ 51790b17f1bSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 51890b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 51990b17f1bSmrg CARD32 uMarker = marker; 52090b17f1bSmrg 52190b17f1bSmrg if (pVia->agpDMA) { 52290b17f1bSmrg while ((pVia->lastMarkerRead - uMarker) > (1 << 24)) 52390b17f1bSmrg pVia->lastMarkerRead = *(CARD32 *) pVia->markerBuf; 52490b17f1bSmrg } else { 52590b17f1bSmrg viaAccelSync(pScrn); 52690b17f1bSmrg } 52790b17f1bSmrg} 52890b17f1bSmrg 52990b17f1bSmrg#ifdef HAVE_DRI 53090b17f1bSmrgstatic int 53190b17f1bSmrgviaAccelDMADownload(ScrnInfoPtr pScrn, unsigned long fbOffset, 53290b17f1bSmrg unsigned srcPitch, unsigned char *dst, 53390b17f1bSmrg unsigned dstPitch, unsigned w, unsigned h) 53490b17f1bSmrg{ 53590b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 53690b17f1bSmrg drm_via_dmablit_t blit[2], *curBlit; 53790b17f1bSmrg unsigned char *sysAligned = NULL; 53890b17f1bSmrg Bool doSync[2], useBounceBuffer; 53990b17f1bSmrg unsigned pitch, numLines[2]; 54090b17f1bSmrg int curBuf, err, i, ret, blitHeight; 54190b17f1bSmrg 54290b17f1bSmrg ret = 0; 54390b17f1bSmrg 54490b17f1bSmrg useBounceBuffer = (((unsigned long)dst & 15) || (dstPitch & 15)); 54590b17f1bSmrg doSync[0] = FALSE; 54690b17f1bSmrg doSync[1] = FALSE; 54790b17f1bSmrg curBuf = 1; 54890b17f1bSmrg blitHeight = h; 54990b17f1bSmrg pitch = dstPitch; 55090b17f1bSmrg if (useBounceBuffer) { 55190b17f1bSmrg pitch = ALIGN_TO(dstPitch, 16); 55290b17f1bSmrg blitHeight = VIA_DMA_DL_SIZE / pitch; 55390b17f1bSmrg } 55490b17f1bSmrg 55590b17f1bSmrg while (doSync[0] || doSync[1] || h != 0) { 55690b17f1bSmrg curBuf = 1 - curBuf; 55790b17f1bSmrg curBlit = &blit[curBuf]; 55890b17f1bSmrg if (doSync[curBuf]) { 55990b17f1bSmrg 56090b17f1bSmrg do { 56190b17f1bSmrg err = drmCommandWrite(pVia->drmmode.fd, DRM_VIA_BLIT_SYNC, 56290b17f1bSmrg &curBlit->sync, sizeof(curBlit->sync)); 56390b17f1bSmrg } while (err == -EAGAIN); 56490b17f1bSmrg 56590b17f1bSmrg if (err) 56690b17f1bSmrg return err; 56790b17f1bSmrg 56890b17f1bSmrg doSync[curBuf] = FALSE; 56990b17f1bSmrg if (useBounceBuffer) { 57090b17f1bSmrg for (i = 0; i < numLines[curBuf]; ++i) { 57190b17f1bSmrg memcpy(dst, curBlit->mem_addr, w); 57290b17f1bSmrg dst += dstPitch; 57390b17f1bSmrg curBlit->mem_addr += pitch; 57490b17f1bSmrg } 57590b17f1bSmrg } 57690b17f1bSmrg } 57790b17f1bSmrg 57890b17f1bSmrg if (h == 0) 57990b17f1bSmrg continue; 58090b17f1bSmrg 58190b17f1bSmrg curBlit->num_lines = (h > blitHeight) ? blitHeight : h; 58290b17f1bSmrg h -= curBlit->num_lines; 58390b17f1bSmrg numLines[curBuf] = curBlit->num_lines; 58490b17f1bSmrg 58590b17f1bSmrg sysAligned = 58690b17f1bSmrg (unsigned char *)pVia->dBounce + (curBuf * VIA_DMA_DL_SIZE); 58790b17f1bSmrg sysAligned = (unsigned char *) 58890b17f1bSmrg ALIGN_TO((unsigned long)sysAligned, 16); 58990b17f1bSmrg 59090b17f1bSmrg curBlit->mem_addr = (useBounceBuffer) ? sysAligned : dst; 59190b17f1bSmrg curBlit->line_length = w; 59290b17f1bSmrg curBlit->mem_stride = pitch; 59390b17f1bSmrg curBlit->fb_addr = fbOffset; 59490b17f1bSmrg curBlit->fb_stride = srcPitch; 59590b17f1bSmrg curBlit->to_fb = 0; 59690b17f1bSmrg fbOffset += curBlit->num_lines * srcPitch; 59790b17f1bSmrg 59890b17f1bSmrg do { 59990b17f1bSmrg err = drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, curBlit, 60090b17f1bSmrg sizeof(*curBlit)); 60190b17f1bSmrg } while (err == -EAGAIN); 60290b17f1bSmrg 60390b17f1bSmrg if (err) { 60490b17f1bSmrg ret = err; 60590b17f1bSmrg h = 0; 60690b17f1bSmrg continue; 60790b17f1bSmrg } 60890b17f1bSmrg 60990b17f1bSmrg doSync[curBuf] = TRUE; 61090b17f1bSmrg } 61190b17f1bSmrg 61290b17f1bSmrg return ret; 61390b17f1bSmrg} 61490b17f1bSmrg 61590b17f1bSmrg/* 61690b17f1bSmrg * Use PCI DMA if we can. If the system alignments don't match, we're using 61790b17f1bSmrg * an aligned bounce buffer for pipelined PCI DMA and memcpy. 61890b17f1bSmrg * Throughput for large transfers is around 65 MB/s. 61990b17f1bSmrg */ 62090b17f1bSmrgstatic Bool 62190b17f1bSmrgviaExaDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 62290b17f1bSmrg char *dst, int dst_pitch) 62390b17f1bSmrg{ 62490b17f1bSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pSrc->drawable.pScreen); 62590b17f1bSmrg unsigned wBytes = (pSrc->drawable.bitsPerPixel * w + 7) >> 3; 62690b17f1bSmrg unsigned srcPitch = exaGetPixmapPitch(pSrc), srcOffset; 62790b17f1bSmrg char *bounceAligned = NULL; 62890b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 62990b17f1bSmrg unsigned totSize; 63090b17f1bSmrg 63190b17f1bSmrg if (!w || !h) 63290b17f1bSmrg return TRUE; 63390b17f1bSmrg 63490b17f1bSmrg srcOffset = x * pSrc->drawable.bitsPerPixel; 63590b17f1bSmrg if (srcOffset & 3) 63690b17f1bSmrg return FALSE; 63790b17f1bSmrg srcOffset = exaGetPixmapOffset(pSrc) + y * srcPitch + (srcOffset >> 3); 63890b17f1bSmrg 63990b17f1bSmrg totSize = wBytes * h; 64090b17f1bSmrg 64190b17f1bSmrg exaWaitSync(pScrn->pScreen); 64290b17f1bSmrg if (totSize < VIA_MIN_DOWNLOAD) { 64390b17f1bSmrg bounceAligned = (char *) drm_bo_map(pScrn, pVia->drmmode.front_bo) + srcOffset; 64490b17f1bSmrg 64590b17f1bSmrg while (h--) { 64690b17f1bSmrg memcpy(dst, bounceAligned, wBytes); 64790b17f1bSmrg dst += dst_pitch; 64890b17f1bSmrg bounceAligned += srcPitch; 64990b17f1bSmrg } 65090b17f1bSmrg return TRUE; 65190b17f1bSmrg } 65290b17f1bSmrg 65390b17f1bSmrg if (!pVia->directRenderingType) 65490b17f1bSmrg return FALSE; 65590b17f1bSmrg 65690b17f1bSmrg if ((srcPitch & 3) || (srcOffset & 3)) { 65790b17f1bSmrg ErrorF("VIA EXA download src_pitch misaligned\n"); 65890b17f1bSmrg return FALSE; 65990b17f1bSmrg } 66090b17f1bSmrg 66190b17f1bSmrg if (viaAccelDMADownload(pScrn, srcOffset, srcPitch, (unsigned char *)dst, 66290b17f1bSmrg dst_pitch, wBytes, h)) 66390b17f1bSmrg return FALSE; 66490b17f1bSmrg 66590b17f1bSmrg return TRUE; 66690b17f1bSmrg} 66790b17f1bSmrg 66890b17f1bSmrg/* 66990b17f1bSmrg * Upload to framebuffer memory using memcpy to AGP pipelined with a 67090b17f1bSmrg * 3D engine texture operation from AGP to framebuffer. The AGP buffers (2) 67190b17f1bSmrg * should be kept rather small for optimal pipelining. 67290b17f1bSmrg */ 67390b17f1bSmrgstatic Bool 67490b17f1bSmrgviaExaTexUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, 67590b17f1bSmrg int src_pitch) 67690b17f1bSmrg{ 67790b17f1bSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen); 67890b17f1bSmrg unsigned dstPitch = exaGetPixmapPitch(pDst), dstOffset; 67990b17f1bSmrg unsigned wBytes = (w * pDst->drawable.bitsPerPixel + 7) >> 3; 68090b17f1bSmrg int i, sync[2], yOffs, bufH, bufOffs, height, format; 68190b17f1bSmrg CARD32 texWidth, texHeight, texPitch; 68290b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 68390b17f1bSmrg Via3DState *v3d = &pVia->v3d; 68490b17f1bSmrg char *dst, *texAddr; 68590b17f1bSmrg Bool buf; 68690b17f1bSmrg 68790b17f1bSmrg if (!w || !h) 68890b17f1bSmrg return TRUE; 68990b17f1bSmrg 69090b17f1bSmrg if (wBytes * h < VIA_MIN_TEX_UPLOAD) { 69190b17f1bSmrg dstOffset = x * pDst->drawable.bitsPerPixel; 69290b17f1bSmrg if (dstOffset & 3) 69390b17f1bSmrg return FALSE; 69490b17f1bSmrg 69590b17f1bSmrg dst = (char *) drm_bo_map(pScrn, pVia->drmmode.front_bo) + 69690b17f1bSmrg (exaGetPixmapOffset(pDst) + y * dstPitch + 69790b17f1bSmrg (dstOffset >> 3)); 69890b17f1bSmrg exaWaitSync(pScrn->pScreen); 69990b17f1bSmrg 70090b17f1bSmrg while (h--) { 70190b17f1bSmrg memcpy(dst, src, wBytes); 70290b17f1bSmrg dst += dstPitch; 70390b17f1bSmrg src += src_pitch; 70490b17f1bSmrg } 70590b17f1bSmrg return TRUE; 70690b17f1bSmrg } 70790b17f1bSmrg 70890b17f1bSmrg if (!pVia->texAGPBuffer->ptr) 70990b17f1bSmrg return FALSE; 71090b17f1bSmrg 71190b17f1bSmrg switch (pDst->drawable.bitsPerPixel) { 71290b17f1bSmrg case 32: 71390b17f1bSmrg format = PICT_a8r8g8b8; 71490b17f1bSmrg break; 71590b17f1bSmrg case 16: 71690b17f1bSmrg format = PICT_r5g6b5; 71790b17f1bSmrg break; 71890b17f1bSmrg default: 71990b17f1bSmrg return FALSE; 72090b17f1bSmrg } 72190b17f1bSmrg 72290b17f1bSmrg dstOffset = exaGetPixmapOffset(pDst); 72390b17f1bSmrg 72490b17f1bSmrg if (pVia->nPOT[0]) { 72590b17f1bSmrg texPitch = ALIGN_TO(wBytes, 32); 72690b17f1bSmrg height = VIA_AGP_UPL_SIZE / texPitch; 72790b17f1bSmrg } else { 72890b17f1bSmrg viaOrder(wBytes, &texPitch); 72990b17f1bSmrg if (texPitch < 3) 73090b17f1bSmrg texPitch = 3; 73190b17f1bSmrg height = VIA_AGP_UPL_SIZE >> texPitch; 73290b17f1bSmrg texPitch = 1 << texPitch; 73390b17f1bSmrg } 73490b17f1bSmrg 73590b17f1bSmrg if (height > 1024) 73690b17f1bSmrg height = 1024; 73790b17f1bSmrg viaOrder(w, &texWidth); 73890b17f1bSmrg texWidth = 1 << texWidth; 73990b17f1bSmrg 74090b17f1bSmrg texHeight = height << 1; 74190b17f1bSmrg bufOffs = texPitch * height; 74290b17f1bSmrg texAddr = (char *) drm_bo_map(pScrn, pVia->texAGPBuffer); 74390b17f1bSmrg 74490b17f1bSmrg v3d->setDestination(v3d, dstOffset, dstPitch, format); 74590b17f1bSmrg v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0x00); 74690b17f1bSmrg v3d->setFlags(v3d, 1, TRUE, TRUE, FALSE); 74790b17f1bSmrg if (!v3d->setTexture(v3d, 0, (unsigned long) texAddr, texPitch, 74890b17f1bSmrg pVia->nPOT[0], texWidth, texHeight, format, 74990b17f1bSmrg via_single, via_single, via_src, TRUE)) 75090b17f1bSmrg return FALSE; 75190b17f1bSmrg 75290b17f1bSmrg v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d)); 75390b17f1bSmrg v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width, 75490b17f1bSmrg pDst->drawable.height); 75590b17f1bSmrg 75690b17f1bSmrg buf = 1; 75790b17f1bSmrg yOffs = 0; 75890b17f1bSmrg sync[0] = -1; 75990b17f1bSmrg sync[1] = -1; 76090b17f1bSmrg 76190b17f1bSmrg while (h) { 76290b17f1bSmrg buf = (buf) ? 0 : 1; 76390b17f1bSmrg bufH = (h > height) ? height : h; 76490b17f1bSmrg dst = texAddr + ((buf) ? bufOffs : 0); 76590b17f1bSmrg 76690b17f1bSmrg if (sync[buf] >= 0) 76790b17f1bSmrg pVia->exaDriverPtr->WaitMarker(pScrn->pScreen, sync[buf]); 76890b17f1bSmrg 76990b17f1bSmrg for (i = 0; i < bufH; ++i) { 77090b17f1bSmrg memcpy(dst, src, wBytes); 77190b17f1bSmrg dst += texPitch; 77290b17f1bSmrg src += src_pitch; 77390b17f1bSmrg } 77490b17f1bSmrg 77590b17f1bSmrg v3d->emitQuad(v3d, &pVia->cb, x, y + yOffs, 0, (buf) ? height : 0, 0, 77690b17f1bSmrg 0, w, bufH); 77790b17f1bSmrg 77890b17f1bSmrg sync[buf] = pVia->exaDriverPtr->MarkSync(pScrn->pScreen); 77990b17f1bSmrg 78090b17f1bSmrg h -= bufH; 78190b17f1bSmrg yOffs += bufH; 78290b17f1bSmrg } 78390b17f1bSmrg 78490b17f1bSmrg if (sync[buf] >= 0) 78590b17f1bSmrg pVia->exaDriverPtr->WaitMarker(pScrn->pScreen, sync[buf]); 78690b17f1bSmrg 78790b17f1bSmrg return TRUE; 78890b17f1bSmrg} 78990b17f1bSmrg 79090b17f1bSmrg#endif /* HAVE_DRI */ 79190b17f1bSmrg 79290b17f1bSmrg#define EXAOPT_MIGRATION_HEURISTIC 0 79390b17f1bSmrg 79490b17f1bSmrgBool 79590b17f1bSmrgviaInitExa(ScreenPtr pScreen) 79690b17f1bSmrg{ 79790b17f1bSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 79890b17f1bSmrg ExaDriverPtr pExa = exaDriverAlloc(); 79990b17f1bSmrg Bool nPOTSupported = TRUE; 80090b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 80190b17f1bSmrg 80290b17f1bSmrg /* 80390b17f1bSmrg * nPOT textures. DRM versions below 2.11.0 don't allow them. 80490b17f1bSmrg * Also some CLE266 hardware may not allow nPOT textures for 80590b17f1bSmrg * texture engine 1. We need to figure that out. 80690b17f1bSmrg */ 80790b17f1bSmrg#ifdef HAVE_DRI 80890b17f1bSmrg nPOTSupported = ((!pVia->directRenderingType) || 80990b17f1bSmrg (pVia->drmVerMajor > 2) || 81090b17f1bSmrg ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor >= 11))); 81190b17f1bSmrg#endif 81290b17f1bSmrg pVia->nPOT[0] = nPOTSupported; 81390b17f1bSmrg pVia->nPOT[1] = nPOTSupported; 81490b17f1bSmrg 81590b17f1bSmrg if (Success != viaSetupCBuffer(pScrn, &pVia->cb, 0)) { 81690b17f1bSmrg pVia->NoAccel = TRUE; 81790b17f1bSmrg return FALSE; 81890b17f1bSmrg } 81990b17f1bSmrg 82090b17f1bSmrg if (!pExa) 82190b17f1bSmrg return FALSE; 82290b17f1bSmrg 82390b17f1bSmrg memset(pExa, 0, sizeof(*pExa)); 82490b17f1bSmrg 82590b17f1bSmrg pExa->exa_major = EXA_VERSION_MAJOR; 82690b17f1bSmrg pExa->exa_minor = EXA_VERSION_MINOR; 82790b17f1bSmrg pExa->memoryBase = pVia->FBBase; 82890b17f1bSmrg pExa->memorySize = pVia->FBFreeEnd; 82990b17f1bSmrg pExa->offScreenBase = pScrn->virtualY * pVia->Bpl; 83090b17f1bSmrg pExa->pixmapOffsetAlign = 32; 83190b17f1bSmrg pExa->pixmapPitchAlign = 16; 83290b17f1bSmrg pExa->flags = EXA_OFFSCREEN_PIXMAPS | 83390b17f1bSmrg (pVia->nPOT[1] ? 0 : EXA_OFFSCREEN_ALIGN_POT); 83490b17f1bSmrg 83590b17f1bSmrg 83690b17f1bSmrg /* HW Limitation are described here: 83790b17f1bSmrg * 83890b17f1bSmrg * 1. H2/H5/H6 2D source and destination: 83990b17f1bSmrg * Pitch: (1 << 14) - 1 = 16383 84090b17f1bSmrg * Dimension: (1 << 12) = 4096 84190b17f1bSmrg * X, Y position: (1 << 12) - 1 = 4095. 84290b17f1bSmrg * 84390b17f1bSmrg * 2. H2 3D engine Render target: 84490b17f1bSmrg * Pitch: (1 << 14) - 1 = 16383 84590b17f1bSmrg * Clip Rectangle: 0 - 2047 84690b17f1bSmrg * 84790b17f1bSmrg * 3. H5/H6 3D engine Render target: 84890b17f1bSmrg * Pitch: ((1 << 10) - 1)*32 = 32736 84990b17f1bSmrg * Clip Rectangle: Color Window, 12bits. As Spec saied: 0 - 2048 85090b17f1bSmrg * Scissor is the same as color window. 85190b17f1bSmrg */ 85290b17f1bSmrg pExa->maxX = 2047; 85390b17f1bSmrg pExa->maxY = 2047; 85490b17f1bSmrg pExa->WaitMarker = viaAccelWaitMarker; 85590b17f1bSmrg 85690b17f1bSmrg switch (pVia->Chipset) { 85790b17f1bSmrg case VIA_VX800: 85890b17f1bSmrg case VIA_VX855: 85990b17f1bSmrg case VIA_VX900: 86090b17f1bSmrg pExa->MarkSync = viaAccelMarkSync_H6; 86190b17f1bSmrg pExa->PrepareSolid = viaExaPrepareSolid_H6; 86290b17f1bSmrg pExa->Solid = viaExaSolid_H6; 86390b17f1bSmrg pExa->DoneSolid = viaExaDoneSolidCopy_H6; 86490b17f1bSmrg pExa->PrepareCopy = viaExaPrepareCopy_H6; 86590b17f1bSmrg pExa->Copy = viaExaCopy_H6; 86690b17f1bSmrg pExa->DoneCopy = viaExaDoneSolidCopy_H6; 86790b17f1bSmrg break; 86890b17f1bSmrg default: 86990b17f1bSmrg pExa->MarkSync = viaAccelMarkSync_H2; 87090b17f1bSmrg pExa->PrepareSolid = viaExaPrepareSolid_H2; 87190b17f1bSmrg pExa->Solid = viaExaSolid_H2; 87290b17f1bSmrg pExa->DoneSolid = viaExaDoneSolidCopy_H2; 87390b17f1bSmrg pExa->PrepareCopy = viaExaPrepareCopy_H2; 87490b17f1bSmrg pExa->Copy = viaExaCopy_H2; 87590b17f1bSmrg pExa->DoneCopy = viaExaDoneSolidCopy_H2; 87690b17f1bSmrg break; 87790b17f1bSmrg } 87890b17f1bSmrg 87990b17f1bSmrg#ifdef HAVE_DRI 88090b17f1bSmrg if (pVia->directRenderingType == DRI_1) { 88190b17f1bSmrg#ifdef linux 88290b17f1bSmrg pExa->DownloadFromScreen = viaExaDownloadFromScreen; 88390b17f1bSmrg#endif /* linux */ 88490b17f1bSmrg switch (pVia->Chipset) { 88590b17f1bSmrg case VIA_K8M800: 88690b17f1bSmrg case VIA_KM400: 88790b17f1bSmrg pExa->UploadToScreen = NULL; //viaExaTexUploadToScreen; 88890b17f1bSmrg break; 88990b17f1bSmrg default: 89090b17f1bSmrg pExa->UploadToScreen = NULL; //viaExaUploadToScreen; 89190b17f1bSmrg break; 89290b17f1bSmrg } 89390b17f1bSmrg } 89490b17f1bSmrg#endif /* HAVE_DRI */ 89590b17f1bSmrg 89690b17f1bSmrg if (!pVia->noComposite) { 89790b17f1bSmrg switch (pVia->Chipset) { 89890b17f1bSmrg case VIA_VX800: 89990b17f1bSmrg case VIA_VX855: 90090b17f1bSmrg case VIA_VX900: 90190b17f1bSmrg pExa->CheckComposite = viaExaCheckComposite_H6; 90290b17f1bSmrg pExa->PrepareComposite = viaExaPrepareComposite_H6; 90390b17f1bSmrg pExa->Composite = viaExaComposite_H6; 90490b17f1bSmrg pExa->DoneComposite = viaExaDoneSolidCopy_H6; 90590b17f1bSmrg break; 90690b17f1bSmrg default: 90790b17f1bSmrg pExa->CheckComposite = viaExaCheckComposite_H2; 90890b17f1bSmrg pExa->PrepareComposite = viaExaPrepareComposite_H2; 90990b17f1bSmrg pExa->Composite = viaExaComposite_H2; 91090b17f1bSmrg pExa->DoneComposite = viaExaDoneSolidCopy_H2; 91190b17f1bSmrg break; 91290b17f1bSmrg } 91390b17f1bSmrg } else { 91490b17f1bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 91590b17f1bSmrg "[EXA] Disabling EXA accelerated composite.\n"); 91690b17f1bSmrg } 91790b17f1bSmrg 91890b17f1bSmrg if (!exaDriverInit(pScreen, pExa)) { 91990b17f1bSmrg free(pExa); 92090b17f1bSmrg return FALSE; 92190b17f1bSmrg } 92290b17f1bSmrg 92390b17f1bSmrg pVia->exaDriverPtr = pExa; 92490b17f1bSmrg viaInit3DState(&pVia->v3d); 92590b17f1bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 92690b17f1bSmrg "[EXA] Enabled EXA acceleration.\n"); 92790b17f1bSmrg return TRUE; 92890b17f1bSmrg} 92990b17f1bSmrg 93090b17f1bSmrg/* 93190b17f1bSmrg * Allocate a command buffer and buffers for accelerated upload, download, 93290b17f1bSmrg * and EXA scratch area. The scratch area resides primarily in AGP memory, 93390b17f1bSmrg * but reverts to FB if AGP is not available. 93490b17f1bSmrg */ 93590b17f1bSmrgvoid 93690b17f1bSmrgviaFinishInitAccel(ScreenPtr pScreen) 93790b17f1bSmrg{ 93890b17f1bSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 93990b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 94090b17f1bSmrg int size; 94190b17f1bSmrg 94290b17f1bSmrg#ifdef HAVE_DRI 94390b17f1bSmrg if (pVia->directRenderingType && pVia->useEXA) { 94490b17f1bSmrg 94590b17f1bSmrg pVia->dBounce = calloc(VIA_DMA_DL_SIZE * 2, 1); 94690b17f1bSmrg 94790b17f1bSmrg if (!pVia->IsPCI) { 94890b17f1bSmrg 94990b17f1bSmrg /* Allocate upload and scratch space. */ 95090b17f1bSmrg if (pVia->exaDriverPtr->UploadToScreen == viaExaTexUploadToScreen) { 95190b17f1bSmrg size = VIA_AGP_UPL_SIZE * 2; 95290b17f1bSmrg 95390b17f1bSmrg pVia->texAGPBuffer = drm_bo_alloc(pScrn, size, 32, TTM_PL_FLAG_TT); 95490b17f1bSmrg if (pVia->texAGPBuffer) { 95590b17f1bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 95690b17f1bSmrg "Allocated %u kiB of AGP memory for " 95790b17f1bSmrg "system-to-framebuffer transfer.\n", 95890b17f1bSmrg size / 1024); 95990b17f1bSmrg pVia->texAGPBuffer->offset = (pVia->texAGPBuffer->offset + 31) & ~31; 96090b17f1bSmrg } 96190b17f1bSmrg } 96290b17f1bSmrg 96390b17f1bSmrg size = pVia->exaScratchSize * 1024; 96490b17f1bSmrg pVia->scratchBuffer = drm_bo_alloc(pScrn, size, 32, TTM_PL_FLAG_TT); 96590b17f1bSmrg if (pVia->scratchBuffer) { 96690b17f1bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 96790b17f1bSmrg "Allocated %u kiB of AGP memory for " 96890b17f1bSmrg "EXA scratch area.\n", size / 1024); 96990b17f1bSmrg pVia->scratchOffset = 97090b17f1bSmrg (pVia->scratchBuffer->offset + 31) & ~31; 97190b17f1bSmrg pVia->scratchAddr = drm_bo_map(pScrn, pVia->scratchBuffer); 97290b17f1bSmrg } 97390b17f1bSmrg } 97490b17f1bSmrg } 97590b17f1bSmrg#endif /* HAVE_DRI */ 97690b17f1bSmrg if (!pVia->scratchAddr && pVia->useEXA) { 97790b17f1bSmrg size = pVia->exaScratchSize * 1024 + 32; 97890b17f1bSmrg pVia->scratchBuffer = drm_bo_alloc(pScrn, size, 32, TTM_PL_FLAG_SYSTEM); 97990b17f1bSmrg 98090b17f1bSmrg if (pVia->scratchBuffer) { 98190b17f1bSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 98290b17f1bSmrg "Allocated %u kiB of framebuffer memory for " 98390b17f1bSmrg "EXA scratch area.\n", pVia->exaScratchSize); 98490b17f1bSmrg pVia->scratchOffset = pVia->scratchBuffer->offset; 98590b17f1bSmrg pVia->scratchAddr = drm_bo_map(pScrn, pVia->scratchBuffer); 98690b17f1bSmrg } 98790b17f1bSmrg } 98890b17f1bSmrg memset(pVia->markerBuf, 0, pVia->exa_sync_bo->size); 98990b17f1bSmrg} 99090b17f1bSmrg 99190b17f1bSmrg/* 99290b17f1bSmrg * Free the used acceleration resources. 99390b17f1bSmrg */ 99490b17f1bSmrgvoid 99590b17f1bSmrgviaExitAccel(ScreenPtr pScreen) 99690b17f1bSmrg{ 99790b17f1bSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 99890b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 99990b17f1bSmrg 100090b17f1bSmrg viaAccelSync(pScrn); 100190b17f1bSmrg viaTearDownCBuffer(&pVia->cb); 100290b17f1bSmrg 100390b17f1bSmrg if (pVia->useEXA) { 100490b17f1bSmrg#ifdef HAVE_DRI 100590b17f1bSmrg if (pVia->directRenderingType == DRI_1) { 100690b17f1bSmrg if (pVia->texAGPBuffer) { 100790b17f1bSmrg drm_bo_free(pScrn, pVia->texAGPBuffer); 100890b17f1bSmrg pVia->texAGPBuffer = NULL; 100990b17f1bSmrg } 101090b17f1bSmrg 101190b17f1bSmrg if (pVia->scratchBuffer) { 101290b17f1bSmrg drm_bo_free(pScrn, pVia->scratchBuffer); 101390b17f1bSmrg pVia->scratchBuffer = NULL; 101490b17f1bSmrg } 101590b17f1bSmrg } 101690b17f1bSmrg if (pVia->dBounce) 101790b17f1bSmrg free(pVia->dBounce); 101890b17f1bSmrg#endif /* HAVE_DRI */ 101990b17f1bSmrg if (pVia->scratchBuffer) { 102090b17f1bSmrg drm_bo_free(pScrn, pVia->scratchBuffer); 102190b17f1bSmrg pVia->scratchBuffer = NULL; 102290b17f1bSmrg } 102390b17f1bSmrg if (pVia->vq_bo) { 102490b17f1bSmrg drm_bo_unmap(pScrn, pVia->vq_bo); 102590b17f1bSmrg drm_bo_free(pScrn, pVia->vq_bo); 102690b17f1bSmrg } 102790b17f1bSmrg if (pVia->exa_sync_bo) { 102890b17f1bSmrg drm_bo_unmap(pScrn, pVia->exa_sync_bo); 102990b17f1bSmrg drm_bo_free(pScrn, pVia->exa_sync_bo); 103090b17f1bSmrg } 103190b17f1bSmrg if (pVia->exaDriverPtr) { 103290b17f1bSmrg exaDriverFini(pScreen); 103390b17f1bSmrg } 103490b17f1bSmrg free(pVia->exaDriverPtr); 103590b17f1bSmrg pVia->exaDriverPtr = NULL; 103690b17f1bSmrg return; 103790b17f1bSmrg } 103890b17f1bSmrg} 1039