142a55b46Smrg/* 242a55b46Smrg * Copyright 2006 Joseph Garvin 342a55b46Smrg * Copyright 2012 Connor Behan 442a55b46Smrg * All Rights Reserved. 542a55b46Smrg * 642a55b46Smrg * Permission is hereby granted, free of charge, to any person obtaining a 742a55b46Smrg * copy of this software and associated documentation files (the "Software"), 842a55b46Smrg * to deal in the Software without restriction, including without limitation 942a55b46Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1042a55b46Smrg * and/or sell copies of the Software, and to permit persons to whom the 1142a55b46Smrg * Software is furnished to do so, subject to the following conditions: 1242a55b46Smrg * 1342a55b46Smrg * The above copyright notice and this permission notice (including the next 1442a55b46Smrg * paragraph) shall be included in all copies or substantial portions of the 1542a55b46Smrg * Software. 1642a55b46Smrg * 1742a55b46Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1842a55b46Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1942a55b46Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2042a55b46Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2142a55b46Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2242a55b46Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2342a55b46Smrg * SOFTWARE. 2442a55b46Smrg * 2542a55b46Smrg * Authors: 2642a55b46Smrg * Joseph Garvin <joseph.h.garvin@gmail.com> 2742a55b46Smrg * Connor Behan <connor.behan@gmail.com> 2842a55b46Smrg * 2942a55b46Smrg */ 3042a55b46Smrg 3142a55b46Smrg#ifdef HAVE_CONFIG_H 3242a55b46Smrg#include "config.h" 3342a55b46Smrg#endif 3442a55b46Smrg 3542a55b46Smrg#include "r128.h" 3642a55b46Smrg#include "exa.h" 3742a55b46Smrg 3842a55b46Smrg#include "r128_reg.h" 3981f79626Smrg#include "r128_rop.h" 4042a55b46Smrg 4142a55b46Smrg#include "xf86.h" 4242a55b46Smrg 4342a55b46Smrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 4442a55b46Smrg * require src and dest datatypes to be equal. 4542a55b46Smrg */ 4642a55b46SmrgBool R128GetDatatypeBpp(int bpp, uint32_t *type) 4742a55b46Smrg{ 4842a55b46Smrg switch (bpp) { 4942a55b46Smrg case 8: 5042a55b46Smrg *type = R128_DATATYPE_CI8; 5142a55b46Smrg return TRUE; 5242a55b46Smrg case 16: 5342a55b46Smrg *type = R128_DATATYPE_RGB565; 5442a55b46Smrg return TRUE; 5542a55b46Smrg case 24: 5642a55b46Smrg *type = R128_DATATYPE_RGB888; 5742a55b46Smrg return TRUE; 5842a55b46Smrg case 32: 5942a55b46Smrg *type = R128_DATATYPE_ARGB8888; 6042a55b46Smrg return TRUE; 6142a55b46Smrg default: 6242a55b46Smrg return FALSE; 6342a55b46Smrg } 6442a55b46Smrg} 6542a55b46Smrg 6642a55b46Smrgstatic Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 6742a55b46Smrg unsigned int offset, unsigned int pitch) 6842a55b46Smrg{ 6942a55b46Smrg ScreenPtr pScreen = pPix->drawable.pScreen; 7042a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 7142a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 7242a55b46Smrg 7342a55b46Smrg if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) { 7481f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7581f79626Smrg "Bad pitch 0x%08x\n", pitch)); 7642a55b46Smrg return FALSE; 7742a55b46Smrg } 7842a55b46Smrg 7942a55b46Smrg if (offset % info->ExaDriver->pixmapOffsetAlign != 0) { 8081f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8181f79626Smrg "Bad offset 0x%08x\n", offset)); 8242a55b46Smrg return FALSE; 8342a55b46Smrg } 8442a55b46Smrg 8542a55b46Smrg *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5); 8642a55b46Smrg 8742a55b46Smrg return TRUE; 8842a55b46Smrg} 8942a55b46Smrg 9042a55b46SmrgBool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 9142a55b46Smrg{ 9242a55b46Smrg uint32_t pitch, offset; 9342a55b46Smrg int bpp; 9442a55b46Smrg 9542a55b46Smrg bpp = pPix->drawable.bitsPerPixel; 9642a55b46Smrg if (bpp == 24) 9742a55b46Smrg bpp = 8; 9842a55b46Smrg 9942a55b46Smrg offset = exaGetPixmapOffset(pPix); 10042a55b46Smrg pitch = exaGetPixmapPitch(pPix); 10142a55b46Smrg 10242a55b46Smrg return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 10342a55b46Smrg} 10442a55b46Smrg 10542a55b46Smrgstatic void Emit2DState(ScrnInfoPtr pScrn) 10642a55b46Smrg{ 10742a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 10842a55b46Smrg int has_src = info->state_2d.src_pitch_offset; 10942a55b46Smrg unsigned char *R128MMIO = info->MMIO; 11042a55b46Smrg 11142a55b46Smrg R128WaitForFifo(pScrn, (has_src ? 10 : 9)); 11242a55b46Smrg 11342a55b46Smrg OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); 11442a55b46Smrg OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); 11542a55b46Smrg OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); 11642a55b46Smrg OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); 11742a55b46Smrg OUTREG(R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); 11842a55b46Smrg OUTREG(R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); 11942a55b46Smrg OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask); 12042a55b46Smrg OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl); 12142a55b46Smrg 12242a55b46Smrg OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); 12342a55b46Smrg if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); 12442a55b46Smrg} 12542a55b46Smrg 12642a55b46Smrg#ifdef R128DRI 12781f79626Smrgvoid EmitCCE2DState(ScrnInfoPtr pScrn) 12842a55b46Smrg{ 12942a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 13042a55b46Smrg int has_src = info->state_2d.src_pitch_offset; 13142a55b46Smrg RING_LOCALS; 13242a55b46Smrg 13342a55b46Smrg R128CCE_REFRESH( pScrn, info ); 13442a55b46Smrg 13542a55b46Smrg BEGIN_RING( (has_src ? 20 : 18) ); 13642a55b46Smrg 13742a55b46Smrg OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right ); 13842a55b46Smrg OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl ); 13942a55b46Smrg OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr ); 14042a55b46Smrg OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr ); 14142a55b46Smrg OUT_RING_REG( R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr ); 14242a55b46Smrg OUT_RING_REG( R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr ); 14342a55b46Smrg OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask ); 14442a55b46Smrg OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl ); 14542a55b46Smrg 14642a55b46Smrg OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset ); 14742a55b46Smrg if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset ); 14842a55b46Smrg 14942a55b46Smrg ADVANCE_RING(); 15042a55b46Smrg} 15142a55b46Smrg#endif 15242a55b46Smrg 15342a55b46Smrg/* EXA Callbacks */ 15442a55b46Smrg 15542a55b46Smrgstatic Bool 15642a55b46SmrgR128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) 15742a55b46Smrg{ 15842a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 15942a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 16042a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 16142a55b46Smrg 16242a55b46Smrg int bpp = pPixmap->drawable.bitsPerPixel; 16342a55b46Smrg uint32_t datatype, dst_pitch_offset; 16442a55b46Smrg 16542a55b46Smrg if (!R128GetDatatypeBpp(bpp, &datatype)) { 16681f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 16781f79626Smrg "R128GetDatatypeBpp failed\n")); 16842a55b46Smrg return FALSE; 16942a55b46Smrg } 17042a55b46Smrg if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) { 17181f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 17281f79626Smrg "R128GetPixmapOffsetPitch failed\n")); 17342a55b46Smrg return FALSE; 17442a55b46Smrg } 17542a55b46Smrg if (info->state_2d.in_use) return FALSE; 17642a55b46Smrg 17742a55b46Smrg info->state_2d.in_use = TRUE; 17842a55b46Smrg info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX); 17942a55b46Smrg info->state_2d.dp_brush_bkgd_clr = 0x00000000; 18042a55b46Smrg info->state_2d.dp_src_frgd_clr = 0xffffffff; 18142a55b46Smrg info->state_2d.dp_src_bkgd_clr = 0x00000000; 18242a55b46Smrg info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | 18342a55b46Smrg R128_GMC_BRUSH_SOLID_COLOR | 18442a55b46Smrg (datatype >> 8) | 18542a55b46Smrg R128_GMC_SRC_DATATYPE_COLOR | 18642a55b46Smrg R128_ROP[alu].pattern | 18742a55b46Smrg R128_GMC_CLR_CMP_CNTL_DIS); 18842a55b46Smrg info->state_2d.dp_brush_frgd_clr = fg; 18942a55b46Smrg info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM); 19042a55b46Smrg info->state_2d.dp_write_mask = planemask; 19142a55b46Smrg info->state_2d.dst_pitch_offset = dst_pitch_offset; 19242a55b46Smrg info->state_2d.src_pitch_offset = 0; 19342a55b46Smrg 19442a55b46Smrg#ifdef R128DRI 19542a55b46Smrg if (info->directRenderingEnabled) { 19642a55b46Smrg EmitCCE2DState(pScrn); 19742a55b46Smrg } else 19842a55b46Smrg#endif 19942a55b46Smrg { 20042a55b46Smrg Emit2DState(pScrn); 20142a55b46Smrg } 20242a55b46Smrg return TRUE; 20342a55b46Smrg} 20442a55b46Smrg 20542a55b46Smrgstatic void 20642a55b46SmrgR128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 20742a55b46Smrg{ 20842a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 20942a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 21042a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 21142a55b46Smrg unsigned char *R128MMIO = info->MMIO; 21242a55b46Smrg 21342a55b46Smrg R128WaitForFifo(pScrn, 2); 21442a55b46Smrg OUTREG(R128_DST_Y_X, (y1 << 16) | x1); 21542a55b46Smrg OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1)); 216bb3c570cSmacallan exaMarkSync(pScreen); 21742a55b46Smrg} 21842a55b46Smrg 21942a55b46Smrg#define R128DoneSolid R128Done 22042a55b46Smrg 22142a55b46Smrgvoid 22242a55b46SmrgR128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, 22342a55b46Smrg uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask) 22442a55b46Smrg{ 22542a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 22642a55b46Smrg 22742a55b46Smrg info->state_2d.in_use = TRUE; 22842a55b46Smrg info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | 22942a55b46Smrg R128_GMC_SRC_PITCH_OFFSET_CNTL | 23042a55b46Smrg R128_GMC_BRUSH_NONE | 23142a55b46Smrg (datatype >> 8) | 23242a55b46Smrg R128_GMC_SRC_DATATYPE_COLOR | 23342a55b46Smrg R128_ROP[alu].rop | 23442a55b46Smrg R128_DP_SRC_SOURCE_MEMORY | 23542a55b46Smrg R128_GMC_CLR_CMP_CNTL_DIS); 23642a55b46Smrg info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) | 23742a55b46Smrg (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0)); 23842a55b46Smrg info->state_2d.dp_brush_frgd_clr = 0xffffffff; 23942a55b46Smrg info->state_2d.dp_brush_bkgd_clr = 0x00000000; 24042a55b46Smrg info->state_2d.dp_src_frgd_clr = 0xffffffff; 24142a55b46Smrg info->state_2d.dp_src_bkgd_clr = 0x00000000; 24242a55b46Smrg info->state_2d.dp_write_mask = planemask; 24342a55b46Smrg info->state_2d.dst_pitch_offset = dst_pitch_offset; 24442a55b46Smrg info->state_2d.src_pitch_offset = src_pitch_offset; 24542a55b46Smrg info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX); 24642a55b46Smrg 24742a55b46Smrg#ifdef R128DRI 24842a55b46Smrg if (info->directRenderingEnabled) { 24942a55b46Smrg EmitCCE2DState(pScrn); 25042a55b46Smrg } else 25142a55b46Smrg#endif 25242a55b46Smrg { 25342a55b46Smrg Emit2DState(pScrn); 25442a55b46Smrg } 25542a55b46Smrg} 25642a55b46Smrg 25742a55b46Smrgstatic Bool 25842a55b46SmrgR128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask) 25942a55b46Smrg{ 26042a55b46Smrg ScreenPtr pScreen = pSrcPixmap->drawable.pScreen; 26142a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 26242a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 26342a55b46Smrg 26442a55b46Smrg int bpp = pDstPixmap->drawable.bitsPerPixel; 26542a55b46Smrg uint32_t datatype, src_pitch_offset, dst_pitch_offset; 26642a55b46Smrg 26742a55b46Smrg if (!R128GetDatatypeBpp(bpp, &datatype)) { 26881f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 26981f79626Smrg "R128GetDatatypeBpp failed\n")); 27042a55b46Smrg return FALSE; 27142a55b46Smrg } 27242a55b46Smrg if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) { 27381f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 27481f79626Smrg "R128GetPixmapOffsetPitch source " 27581f79626Smrg "failed\n")); 27642a55b46Smrg return FALSE; 27742a55b46Smrg } 27842a55b46Smrg if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) { 27981f79626Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 28081f79626Smrg "R128GetPixmapOffsetPitch dest failed\n")); 28142a55b46Smrg return FALSE; 28242a55b46Smrg } 28342a55b46Smrg if (info->state_2d.in_use) return FALSE; 28442a55b46Smrg 28542a55b46Smrg info->xdir = xdir; 28642a55b46Smrg info->ydir = ydir; 28742a55b46Smrg 28842a55b46Smrg R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask); 28942a55b46Smrg 29042a55b46Smrg return TRUE; 29142a55b46Smrg} 29242a55b46Smrg 29342a55b46Smrgstatic void 29442a55b46SmrgR128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) 29542a55b46Smrg{ 29642a55b46Smrg ScreenPtr pScreen = pDstPixmap->drawable.pScreen; 29742a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 29842a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 29942a55b46Smrg unsigned char *R128MMIO = info->MMIO; 30042a55b46Smrg 30142a55b46Smrg if (info->xdir < 0) srcX += width - 1, dstX += width - 1; 30242a55b46Smrg if (info->ydir < 0) srcY += height - 1, dstY += height - 1; 30342a55b46Smrg 30442a55b46Smrg R128WaitForFifo(pScrn, 3); 30542a55b46Smrg OUTREG(R128_SRC_Y_X, (srcY << 16) | srcX); 30642a55b46Smrg OUTREG(R128_DST_Y_X, (dstY << 16) | dstX); 30742a55b46Smrg OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width); 308bb3c570cSmacallan exaMarkSync(pScreen); 30942a55b46Smrg} 31042a55b46Smrg 31142a55b46Smrg#define R128DoneCopy R128Done 31242a55b46Smrg 31342a55b46Smrgstatic void 31442a55b46SmrgR128Sync(ScreenPtr pScreen, int marker) 31542a55b46Smrg{ 31642a55b46Smrg R128WaitForIdle(xf86ScreenToScrn(pScreen)); 31742a55b46Smrg} 31842a55b46Smrg 31981f79626Smrgvoid 32042a55b46SmrgR128Done(PixmapPtr pPixmap) 32142a55b46Smrg{ 32242a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 32342a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 32442a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 32542a55b46Smrg 32642a55b46Smrg info->state_2d.in_use = FALSE; 32742a55b46Smrg#if defined(R128DRI) && defined(RENDER) 32842a55b46Smrg if (info->state_2d.src_pix) { 32942a55b46Smrg pScreen->DestroyPixmap(info->state_2d.src_pix); 33042a55b46Smrg info->state_2d.src_pix = NULL; 33142a55b46Smrg } 33242a55b46Smrg if (info->state_2d.msk_pix) { 33342a55b46Smrg pScreen->DestroyPixmap(info->state_2d.msk_pix); 33442a55b46Smrg info->state_2d.msk_pix = NULL; 33542a55b46Smrg } 33642a55b46Smrg#endif 33742a55b46Smrg} 33842a55b46Smrg 33942a55b46Smrg#ifdef R128DRI 34042a55b46Smrg 34142a55b46Smrg#define R128CCEPrepareSolid R128PrepareSolid 34242a55b46Smrg 34342a55b46Smrgstatic void 34442a55b46SmrgR128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 34542a55b46Smrg{ 34642a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 34742a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 34842a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 34942a55b46Smrg RING_LOCALS; 35042a55b46Smrg 35142a55b46Smrg R128CCE_REFRESH( pScrn, info ); 35242a55b46Smrg 35342a55b46Smrg BEGIN_RING( 4 ); 35442a55b46Smrg 35542a55b46Smrg OUT_RING_REG( R128_DST_Y_X, (y1 << 16) | x1 ); 35642a55b46Smrg OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) ); 35742a55b46Smrg 35842a55b46Smrg ADVANCE_RING(); 35942a55b46Smrg} 36042a55b46Smrg 36142a55b46Smrg#define R128CCEDoneSolid R128Done 36242a55b46Smrg 36342a55b46Smrg#define R128CCEPrepareCopy R128PrepareCopy 36442a55b46Smrg 36542a55b46Smrgstatic void 36642a55b46SmrgR128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, 36742a55b46Smrg int width, int height) 36842a55b46Smrg{ 36942a55b46Smrg ScreenPtr pScreen = pDstPixmap->drawable.pScreen; 37042a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 37142a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 37242a55b46Smrg RING_LOCALS; 37342a55b46Smrg 37442a55b46Smrg R128CCE_REFRESH( pScrn, info ); 37542a55b46Smrg 37642a55b46Smrg if (info->xdir < 0) srcX += width - 1, dstX += width - 1; 37742a55b46Smrg if (info->ydir < 0) srcY += height - 1, dstY += height - 1; 37842a55b46Smrg 37942a55b46Smrg BEGIN_RING( 6 ); 38042a55b46Smrg 38142a55b46Smrg OUT_RING_REG( R128_SRC_Y_X, (srcY << 16) | srcX ); 38242a55b46Smrg OUT_RING_REG( R128_DST_Y_X, (dstY << 16) | dstX ); 38342a55b46Smrg OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width ); 38442a55b46Smrg 38542a55b46Smrg ADVANCE_RING(); 38642a55b46Smrg} 38742a55b46Smrg 38842a55b46Smrg#define R128CCEDoneCopy R128Done 38942a55b46Smrg 39042a55b46Smrgstatic void 39142a55b46SmrgR128CCESync(ScreenPtr pScreen, int marker) 39242a55b46Smrg{ 39342a55b46Smrg R128CCEWaitForIdle(xf86ScreenToScrn(pScreen)); 39442a55b46Smrg} 39542a55b46Smrg 39642a55b46Smrg#endif 39742a55b46Smrg 398bb3c570cSmacallan/* 399bb3c570cSmacallan * Memcpy-based UTS. 400bb3c570cSmacallan */ 401bb3c570cSmacallanstatic Bool 402bb3c570cSmacallanR128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 403bb3c570cSmacallan char *src, int src_pitch) 404bb3c570cSmacallan{ 405bb3c570cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 406bb3c570cSmacallan R128InfoPtr info = R128PTR(pScrn); 407bb3c570cSmacallan char *dst = info->FB + exaGetPixmapOffset(pDst); 408bb3c570cSmacallan int dst_pitch = exaGetPixmapPitch(pDst); 409bb3c570cSmacallan int bpp = pDst->drawable.bitsPerPixel; 410bb3c570cSmacallan int cpp = (bpp + 7) >> 3; 411bb3c570cSmacallan int wBytes = w * cpp; 412bb3c570cSmacallan 413bb3c570cSmacallan dst += (x * cpp) + (y * dst_pitch); 414bb3c570cSmacallan 415bb3c570cSmacallan R128WaitForIdle(pScrn); 416bb3c570cSmacallan 417bb3c570cSmacallan while (h--) { 418bb3c570cSmacallan memcpy(dst, src, wBytes); 419bb3c570cSmacallan src += src_pitch; 420bb3c570cSmacallan dst += dst_pitch; 421bb3c570cSmacallan } 422bb3c570cSmacallan 423bb3c570cSmacallan return TRUE; 424bb3c570cSmacallan} 425bb3c570cSmacallan 426bb3c570cSmacallan/* 427bb3c570cSmacallan * Hostblit-based UTS. 428bb3c570cSmacallan * this assumes 32bit pixels 429bb3c570cSmacallan */ 430bb3c570cSmacallanstatic Bool 431bb3c570cSmacallanR128UploadToScreenHW(PixmapPtr pDst, int x, int y, int w, int h, 432bb3c570cSmacallan char *src, int src_pitch) 433bb3c570cSmacallan{ 434bb3c570cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 435bb3c570cSmacallan R128InfoPtr info = R128PTR(pScrn); 436bb3c570cSmacallan uint32_t dst_pitch_offset, datatype; 437bb3c570cSmacallan int cnt, line, px; 438bb3c570cSmacallan unsigned char *R128MMIO = info->MMIO; 439bb3c570cSmacallan int bpp = pDst->drawable.bitsPerPixel; 440bb3c570cSmacallan uint32_t *s; 441bb3c570cSmacallan 442bb3c570cSmacallan if (!R128GetDatatypeBpp(bpp, &datatype)) { 443bb3c570cSmacallan return FALSE; 444bb3c570cSmacallan } 445bb3c570cSmacallan 446bb3c570cSmacallan if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) { 447bb3c570cSmacallan return FALSE; 448bb3c570cSmacallan } 449bb3c570cSmacallan 450bb3c570cSmacallan info->state_2d.in_use = TRUE; 451bb3c570cSmacallan info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | 452bb3c570cSmacallan R128_GMC_BRUSH_NONE | 453bb3c570cSmacallan (datatype >> 8) | 454bb3c570cSmacallan R128_GMC_SRC_DATATYPE_COLOR | 455bb3c570cSmacallan R128_ROP3_S | 456bb3c570cSmacallan R128_DP_SRC_SOURCE_HOST_DATA | 457bb3c570cSmacallan R128_GMC_CLR_CMP_CNTL_DIS); 458bb3c570cSmacallan info->state_2d.dp_cntl = R128_DST_X_LEFT_TO_RIGHT | 459bb3c570cSmacallan R128_DST_Y_TOP_TO_BOTTOM; 460bb3c570cSmacallan info->state_2d.dp_write_mask = 0xffffffff; 461bb3c570cSmacallan info->state_2d.dst_pitch_offset = dst_pitch_offset; 462bb3c570cSmacallan info->state_2d.default_sc_bottom_right = R128_DEFAULT_SC_RIGHT_MAX | 463bb3c570cSmacallan R128_DEFAULT_SC_BOTTOM_MAX; 464bb3c570cSmacallan Emit2DState(pScrn); 465bb3c570cSmacallan 466bb3c570cSmacallan R128WaitForFifo(pScrn, 3); 467bb3c570cSmacallan OUTREG(R128_SRC_Y_X, 0); 468bb3c570cSmacallan OUTREG(R128_DST_Y_X, (y << 16) | x); 469bb3c570cSmacallan OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w); 470bb3c570cSmacallan 471bb3c570cSmacallan R128WaitForFifo(pScrn, 32); 472bb3c570cSmacallan cnt = 0; 473bb3c570cSmacallan 474bb3c570cSmacallan for (line = 0; line < h; line++) { 475bb3c570cSmacallan s = (void *)src; 476bb3c570cSmacallan for (px = 0; px < w; px++) { 477bb3c570cSmacallan OUTREG(R128_HOST_DATA0, cpu_to_le32(*s)); 478bb3c570cSmacallan s++; 479bb3c570cSmacallan cnt++; 480bb3c570cSmacallan if (cnt > 31) { 481bb3c570cSmacallan R128WaitForFifo(pScrn, 32); 482bb3c570cSmacallan cnt = 0; 483bb3c570cSmacallan } 484bb3c570cSmacallan } 485bb3c570cSmacallan src += src_pitch; 486bb3c570cSmacallan } 487bb3c570cSmacallan info->state_2d.in_use = FALSE; 488bb3c570cSmacallan exaMarkSync(pDst->drawable.pScreen); 489bb3c570cSmacallan return TRUE; 490bb3c570cSmacallan} 491bb3c570cSmacallan 492bb3c570cSmacallan/* 493bb3c570cSmacallan * Memcpy-based DFS. 494bb3c570cSmacallan */ 495bb3c570cSmacallanstatic Bool 496bb3c570cSmacallanR128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 497bb3c570cSmacallan char *dst, int dst_pitch) 498bb3c570cSmacallan{ 499bb3c570cSmacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 500bb3c570cSmacallan R128InfoPtr info = R128PTR(pScrn); 501bb3c570cSmacallan char *src = info->FB + exaGetPixmapOffset(pSrc); 502bb3c570cSmacallan int src_pitch = exaGetPixmapPitch(pSrc); 503bb3c570cSmacallan 504bb3c570cSmacallan int bpp = pSrc->drawable.bitsPerPixel; 505bb3c570cSmacallan int cpp = (bpp + 7) >> 3; 506bb3c570cSmacallan int wBytes = w * cpp; 507bb3c570cSmacallan 508bb3c570cSmacallan src += (x * cpp) + (y * src_pitch); 509bb3c570cSmacallan 510bb3c570cSmacallan R128WaitForIdle(pScrn); 511bb3c570cSmacallan 512bb3c570cSmacallan while (h--) { 513bb3c570cSmacallan memcpy(dst, src, wBytes); 514bb3c570cSmacallan src += src_pitch; 515bb3c570cSmacallan dst += dst_pitch; 516bb3c570cSmacallan } 517bb3c570cSmacallan 518bb3c570cSmacallan return TRUE; 519bb3c570cSmacallan} 520bb3c570cSmacallan 52142a55b46SmrgBool 52281f79626SmrgR128EXAInit(ScreenPtr pScreen, int total) 52342a55b46Smrg{ 52442a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 52542a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 52642a55b46Smrg 52781f79626Smrg info->ExaDriver = exaDriverAlloc(); 52881f79626Smrg if (!info->ExaDriver) { 52981f79626Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 53081f79626Smrg "Could not allocate EXA driver...\n"); 53181f79626Smrg return FALSE; 53281f79626Smrg } 53381f79626Smrg 53442a55b46Smrg info->ExaDriver->exa_major = EXA_VERSION_MAJOR; 53542a55b46Smrg info->ExaDriver->exa_minor = EXA_VERSION_MINOR; 53642a55b46Smrg 53742a55b46Smrg info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset; 53881f79626Smrg info->ExaDriver->offScreenBase = pScrn->virtualY * 53981f79626Smrg (pScrn->displayWidth * 54081f79626Smrg info->CurrentLayout.pixel_bytes); 54181f79626Smrg info->ExaDriver->memorySize = total; 542bb3c570cSmacallan info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS; 54342a55b46Smrg 54442a55b46Smrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) 54542a55b46Smrg info->ExaDriver->maxPitchBytes = 16320; 54642a55b46Smrg#endif 54742a55b46Smrg /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */ 54842a55b46Smrg info->ExaDriver->pixmapPitchAlign = 32; 54942a55b46Smrg info->ExaDriver->pixmapOffsetAlign = 32; 55042a55b46Smrg info->ExaDriver->maxX = 2048; 55142a55b46Smrg info->ExaDriver->maxY = 2048; 55242a55b46Smrg 55342a55b46Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 55442a55b46Smrg "Setting up EXA callbacks\n"); 55542a55b46Smrg 55642a55b46Smrg#ifdef R128DRI 55742a55b46Smrg if (info->directRenderingEnabled) { 55842a55b46Smrg info->ExaDriver->PrepareSolid = R128CCEPrepareSolid; 55942a55b46Smrg info->ExaDriver->Solid = R128CCESolid; 56042a55b46Smrg info->ExaDriver->DoneSolid = R128CCEDoneSolid; 56142a55b46Smrg 56242a55b46Smrg info->ExaDriver->PrepareCopy = R128CCEPrepareCopy; 56342a55b46Smrg info->ExaDriver->Copy = R128CCECopy; 56442a55b46Smrg info->ExaDriver->DoneCopy = R128CCEDoneCopy; 56542a55b46Smrg 56642a55b46Smrg#ifdef RENDER 56742a55b46Smrg if (info->RenderAccel) { 568bb3c570cSmacallan info->ExaDriver->flags |= EXA_OFFSCREEN_ALIGN_POT; 56942a55b46Smrg info->ExaDriver->CheckComposite = R128CCECheckComposite; 57042a55b46Smrg info->ExaDriver->PrepareComposite = R128CCEPrepareComposite; 57142a55b46Smrg info->ExaDriver->Composite = R128CCEComposite; 57242a55b46Smrg info->ExaDriver->DoneComposite = R128CCEDoneComposite; 57342a55b46Smrg } 57442a55b46Smrg#endif 57542a55b46Smrg 57642a55b46Smrg info->ExaDriver->WaitMarker = R128CCESync; 57742a55b46Smrg } else 57842a55b46Smrg#endif 57942a55b46Smrg { 58042a55b46Smrg info->ExaDriver->PrepareSolid = R128PrepareSolid; 58142a55b46Smrg info->ExaDriver->Solid = R128Solid; 58242a55b46Smrg info->ExaDriver->DoneSolid = R128DoneSolid; 58342a55b46Smrg 58442a55b46Smrg info->ExaDriver->PrepareCopy = R128PrepareCopy; 58542a55b46Smrg info->ExaDriver->Copy = R128Copy; 58642a55b46Smrg info->ExaDriver->DoneCopy = R128DoneCopy; 58742a55b46Smrg 588bb3c570cSmacallan if (pScrn->bitsPerPixel < 24) { 589bb3c570cSmacallan info->ExaDriver->UploadToScreen = R128UploadToScreen; 590bb3c570cSmacallan } else { 591bb3c570cSmacallan info->ExaDriver->UploadToScreen = R128UploadToScreenHW; 592bb3c570cSmacallan } 593bb3c570cSmacallan info->ExaDriver->DownloadFromScreen = R128DownloadFromScreen; 594bb3c570cSmacallan 59542a55b46Smrg /* The registers used for r128 compositing are CCE specific, just like the 59642a55b46Smrg * registers used for radeon compositing are CP specific. The radeon driver 59742a55b46Smrg * falls back to different registers when there is no DRI. The equivalent 59842a55b46Smrg * registers on the r128 (if they even exist) are not listed in the register 59942a55b46Smrg * file so I can't implement compositing without DRI. 60042a55b46Smrg */ 60142a55b46Smrg 60242a55b46Smrg info->ExaDriver->WaitMarker = R128Sync; 60342a55b46Smrg } 60442a55b46Smrg 60542a55b46Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 60681f79626Smrg "Initializing 2D acceleration engine...\n"); 60742a55b46Smrg 60842a55b46Smrg R128EngineInit(pScrn); 60942a55b46Smrg 61042a55b46Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 61142a55b46Smrg "Initializing EXA driver...\n"); 61242a55b46Smrg 61342a55b46Smrg if (!exaDriverInit(pScreen, info->ExaDriver)) { 61442a55b46Smrg free(info->ExaDriver); 61542a55b46Smrg return FALSE; 61642a55b46Smrg } 61742a55b46Smrg 61842a55b46Smrg info->state_2d.composite_setup = FALSE; 61942a55b46Smrg return TRUE; 62042a55b46Smrg} 621