r128_exa.c revision bb3c570c
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" 3942a55b46Smrg 4042a55b46Smrg#include "xf86.h" 4142a55b46Smrg 4242a55b46Smrgstatic struct { 4342a55b46Smrg int rop; 4442a55b46Smrg int pattern; 4542a55b46Smrg} R128_ROP[] = { 4642a55b46Smrg { R128_ROP3_ZERO, R128_ROP3_ZERO }, /* GXclear */ 4742a55b46Smrg { R128_ROP3_DSa, R128_ROP3_DPa }, /* Gxand */ 4842a55b46Smrg { R128_ROP3_SDna, R128_ROP3_PDna }, /* GXandReverse */ 4942a55b46Smrg { R128_ROP3_S, R128_ROP3_P }, /* GXcopy */ 5042a55b46Smrg { R128_ROP3_DSna, R128_ROP3_DPna }, /* GXandInverted */ 5142a55b46Smrg { R128_ROP3_D, R128_ROP3_D }, /* GXnoop */ 5242a55b46Smrg { R128_ROP3_DSx, R128_ROP3_DPx }, /* GXxor */ 5342a55b46Smrg { R128_ROP3_DSo, R128_ROP3_DPo }, /* GXor */ 5442a55b46Smrg { R128_ROP3_DSon, R128_ROP3_DPon }, /* GXnor */ 5542a55b46Smrg { R128_ROP3_DSxn, R128_ROP3_PDxn }, /* GXequiv */ 5642a55b46Smrg { R128_ROP3_Dn, R128_ROP3_Dn }, /* GXinvert */ 5742a55b46Smrg { R128_ROP3_SDno, R128_ROP3_PDno }, /* GXorReverse */ 5842a55b46Smrg { R128_ROP3_Sn, R128_ROP3_Pn }, /* GXcopyInverted */ 5942a55b46Smrg { R128_ROP3_DSno, R128_ROP3_DPno }, /* GXorInverted */ 6042a55b46Smrg { R128_ROP3_DSan, R128_ROP3_DPan }, /* GXnand */ 6142a55b46Smrg { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */ 6242a55b46Smrg}; 6342a55b46Smrg 6442a55b46Smrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we 6542a55b46Smrg * require src and dest datatypes to be equal. 6642a55b46Smrg */ 6742a55b46SmrgBool R128GetDatatypeBpp(int bpp, uint32_t *type) 6842a55b46Smrg{ 6942a55b46Smrg switch (bpp) { 7042a55b46Smrg case 8: 7142a55b46Smrg *type = R128_DATATYPE_CI8; 7242a55b46Smrg return TRUE; 7342a55b46Smrg case 16: 7442a55b46Smrg *type = R128_DATATYPE_RGB565; 7542a55b46Smrg return TRUE; 7642a55b46Smrg case 24: 7742a55b46Smrg *type = R128_DATATYPE_RGB888; 7842a55b46Smrg return TRUE; 7942a55b46Smrg case 32: 8042a55b46Smrg *type = R128_DATATYPE_ARGB8888; 8142a55b46Smrg return TRUE; 8242a55b46Smrg default: 8342a55b46Smrg return FALSE; 8442a55b46Smrg } 8542a55b46Smrg} 8642a55b46Smrg 8742a55b46Smrgstatic Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset, 8842a55b46Smrg unsigned int offset, unsigned int pitch) 8942a55b46Smrg{ 9042a55b46Smrg ScreenPtr pScreen = pPix->drawable.pScreen; 9142a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9242a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 9342a55b46Smrg 9442a55b46Smrg if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) { 9542a55b46Smrg R128TRACE(("Bad pitch 0x%08x\n", pitch)); 9642a55b46Smrg return FALSE; 9742a55b46Smrg } 9842a55b46Smrg 9942a55b46Smrg if (offset % info->ExaDriver->pixmapOffsetAlign != 0) { 10042a55b46Smrg R128TRACE(("Bad offset 0x%08x\n", offset)); 10142a55b46Smrg return FALSE; 10242a55b46Smrg } 10342a55b46Smrg 10442a55b46Smrg *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5); 10542a55b46Smrg 10642a55b46Smrg return TRUE; 10742a55b46Smrg} 10842a55b46Smrg 10942a55b46SmrgBool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) 11042a55b46Smrg{ 11142a55b46Smrg uint32_t pitch, offset; 11242a55b46Smrg int bpp; 11342a55b46Smrg 11442a55b46Smrg bpp = pPix->drawable.bitsPerPixel; 11542a55b46Smrg if (bpp == 24) 11642a55b46Smrg bpp = 8; 11742a55b46Smrg 11842a55b46Smrg offset = exaGetPixmapOffset(pPix); 11942a55b46Smrg pitch = exaGetPixmapPitch(pPix); 12042a55b46Smrg 12142a55b46Smrg return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); 12242a55b46Smrg} 12342a55b46Smrg 12442a55b46Smrgstatic void Emit2DState(ScrnInfoPtr pScrn) 12542a55b46Smrg{ 12642a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 12742a55b46Smrg int has_src = info->state_2d.src_pitch_offset; 12842a55b46Smrg unsigned char *R128MMIO = info->MMIO; 12942a55b46Smrg 13042a55b46Smrg R128WaitForFifo(pScrn, (has_src ? 10 : 9)); 13142a55b46Smrg 13242a55b46Smrg OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); 13342a55b46Smrg OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); 13442a55b46Smrg OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); 13542a55b46Smrg OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); 13642a55b46Smrg OUTREG(R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); 13742a55b46Smrg OUTREG(R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); 13842a55b46Smrg OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask); 13942a55b46Smrg OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl); 14042a55b46Smrg 14142a55b46Smrg OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); 14242a55b46Smrg if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); 14342a55b46Smrg} 14442a55b46Smrg 14542a55b46Smrg#ifdef R128DRI 14642a55b46Smrgstatic void EmitCCE2DState(ScrnInfoPtr pScrn) 14742a55b46Smrg{ 14842a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 14942a55b46Smrg int has_src = info->state_2d.src_pitch_offset; 15042a55b46Smrg RING_LOCALS; 15142a55b46Smrg 15242a55b46Smrg R128CCE_REFRESH( pScrn, info ); 15342a55b46Smrg 15442a55b46Smrg BEGIN_RING( (has_src ? 20 : 18) ); 15542a55b46Smrg 15642a55b46Smrg OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right ); 15742a55b46Smrg OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl ); 15842a55b46Smrg OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr ); 15942a55b46Smrg OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr ); 16042a55b46Smrg OUT_RING_REG( R128_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr ); 16142a55b46Smrg OUT_RING_REG( R128_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr ); 16242a55b46Smrg OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask ); 16342a55b46Smrg OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl ); 16442a55b46Smrg 16542a55b46Smrg OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset ); 16642a55b46Smrg if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset ); 16742a55b46Smrg 16842a55b46Smrg ADVANCE_RING(); 16942a55b46Smrg} 17042a55b46Smrg#endif 17142a55b46Smrg 17242a55b46Smrg/* EXA Callbacks */ 17342a55b46Smrg 17442a55b46Smrgstatic Bool 17542a55b46SmrgR128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) 17642a55b46Smrg{ 17742a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 17842a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 17942a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 18042a55b46Smrg 18142a55b46Smrg int bpp = pPixmap->drawable.bitsPerPixel; 18242a55b46Smrg uint32_t datatype, dst_pitch_offset; 18342a55b46Smrg 18442a55b46Smrg if (!R128GetDatatypeBpp(bpp, &datatype)) { 18542a55b46Smrg R128TRACE(("R128GetDatatypeBpp failed\n")); 18642a55b46Smrg return FALSE; 18742a55b46Smrg } 18842a55b46Smrg if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) { 18942a55b46Smrg R128TRACE(("R128GetPixmapOffsetPitch failed\n")); 19042a55b46Smrg return FALSE; 19142a55b46Smrg } 19242a55b46Smrg if (info->state_2d.in_use) return FALSE; 19342a55b46Smrg 19442a55b46Smrg info->state_2d.in_use = TRUE; 19542a55b46Smrg info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX); 19642a55b46Smrg info->state_2d.dp_brush_bkgd_clr = 0x00000000; 19742a55b46Smrg info->state_2d.dp_src_frgd_clr = 0xffffffff; 19842a55b46Smrg info->state_2d.dp_src_bkgd_clr = 0x00000000; 19942a55b46Smrg info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | 20042a55b46Smrg R128_GMC_BRUSH_SOLID_COLOR | 20142a55b46Smrg (datatype >> 8) | 20242a55b46Smrg R128_GMC_SRC_DATATYPE_COLOR | 20342a55b46Smrg R128_ROP[alu].pattern | 20442a55b46Smrg R128_GMC_CLR_CMP_CNTL_DIS); 20542a55b46Smrg info->state_2d.dp_brush_frgd_clr = fg; 20642a55b46Smrg info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM); 20742a55b46Smrg info->state_2d.dp_write_mask = planemask; 20842a55b46Smrg info->state_2d.dst_pitch_offset = dst_pitch_offset; 20942a55b46Smrg info->state_2d.src_pitch_offset = 0; 21042a55b46Smrg 21142a55b46Smrg#ifdef R128DRI 21242a55b46Smrg if (info->directRenderingEnabled) { 21342a55b46Smrg EmitCCE2DState(pScrn); 21442a55b46Smrg } else 21542a55b46Smrg#endif 21642a55b46Smrg { 21742a55b46Smrg Emit2DState(pScrn); 21842a55b46Smrg } 21942a55b46Smrg return TRUE; 22042a55b46Smrg} 22142a55b46Smrg 22242a55b46Smrgstatic void 22342a55b46SmrgR128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 22442a55b46Smrg{ 22542a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 22642a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 22742a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 22842a55b46Smrg unsigned char *R128MMIO = info->MMIO; 22942a55b46Smrg 23042a55b46Smrg R128WaitForFifo(pScrn, 2); 23142a55b46Smrg OUTREG(R128_DST_Y_X, (y1 << 16) | x1); 23242a55b46Smrg OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1)); 233bb3c570cSmacallan exaMarkSync(pScreen); 23442a55b46Smrg} 23542a55b46Smrg 23642a55b46Smrg#define R128DoneSolid R128Done 23742a55b46Smrg 23842a55b46Smrgvoid 23942a55b46SmrgR128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, 24042a55b46Smrg uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask) 24142a55b46Smrg{ 24242a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 24342a55b46Smrg 24442a55b46Smrg info->state_2d.in_use = TRUE; 24542a55b46Smrg info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | 24642a55b46Smrg R128_GMC_SRC_PITCH_OFFSET_CNTL | 24742a55b46Smrg R128_GMC_BRUSH_NONE | 24842a55b46Smrg (datatype >> 8) | 24942a55b46Smrg R128_GMC_SRC_DATATYPE_COLOR | 25042a55b46Smrg R128_ROP[alu].rop | 25142a55b46Smrg R128_DP_SRC_SOURCE_MEMORY | 25242a55b46Smrg R128_GMC_CLR_CMP_CNTL_DIS); 25342a55b46Smrg info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) | 25442a55b46Smrg (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0)); 25542a55b46Smrg info->state_2d.dp_brush_frgd_clr = 0xffffffff; 25642a55b46Smrg info->state_2d.dp_brush_bkgd_clr = 0x00000000; 25742a55b46Smrg info->state_2d.dp_src_frgd_clr = 0xffffffff; 25842a55b46Smrg info->state_2d.dp_src_bkgd_clr = 0x00000000; 25942a55b46Smrg info->state_2d.dp_write_mask = planemask; 26042a55b46Smrg info->state_2d.dst_pitch_offset = dst_pitch_offset; 26142a55b46Smrg info->state_2d.src_pitch_offset = src_pitch_offset; 26242a55b46Smrg info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX); 26342a55b46Smrg 26442a55b46Smrg#ifdef R128DRI 26542a55b46Smrg if (info->directRenderingEnabled) { 26642a55b46Smrg EmitCCE2DState(pScrn); 26742a55b46Smrg } else 26842a55b46Smrg#endif 26942a55b46Smrg { 27042a55b46Smrg Emit2DState(pScrn); 27142a55b46Smrg } 27242a55b46Smrg} 27342a55b46Smrg 27442a55b46Smrgstatic Bool 27542a55b46SmrgR128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask) 27642a55b46Smrg{ 27742a55b46Smrg ScreenPtr pScreen = pSrcPixmap->drawable.pScreen; 27842a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 27942a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 28042a55b46Smrg 28142a55b46Smrg int bpp = pDstPixmap->drawable.bitsPerPixel; 28242a55b46Smrg uint32_t datatype, src_pitch_offset, dst_pitch_offset; 28342a55b46Smrg 28442a55b46Smrg if (!R128GetDatatypeBpp(bpp, &datatype)) { 28542a55b46Smrg R128TRACE(("R128GetDatatypeBpp failed\n")); 28642a55b46Smrg return FALSE; 28742a55b46Smrg } 28842a55b46Smrg if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) { 28942a55b46Smrg R128TRACE(("R128GetPixmapOffsetPitch source failed\n")); 29042a55b46Smrg return FALSE; 29142a55b46Smrg } 29242a55b46Smrg if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) { 29342a55b46Smrg R128TRACE(("R128GetPixmapOffsetPitch dest failed\n")); 29442a55b46Smrg return FALSE; 29542a55b46Smrg } 29642a55b46Smrg if (info->state_2d.in_use) return FALSE; 29742a55b46Smrg 29842a55b46Smrg info->xdir = xdir; 29942a55b46Smrg info->ydir = ydir; 30042a55b46Smrg 30142a55b46Smrg R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask); 30242a55b46Smrg 30342a55b46Smrg return TRUE; 30442a55b46Smrg} 30542a55b46Smrg 30642a55b46Smrgstatic void 30742a55b46SmrgR128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) 30842a55b46Smrg{ 30942a55b46Smrg ScreenPtr pScreen = pDstPixmap->drawable.pScreen; 31042a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 31142a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 31242a55b46Smrg unsigned char *R128MMIO = info->MMIO; 31342a55b46Smrg 31442a55b46Smrg if (info->xdir < 0) srcX += width - 1, dstX += width - 1; 31542a55b46Smrg if (info->ydir < 0) srcY += height - 1, dstY += height - 1; 31642a55b46Smrg 31742a55b46Smrg R128WaitForFifo(pScrn, 3); 31842a55b46Smrg OUTREG(R128_SRC_Y_X, (srcY << 16) | srcX); 31942a55b46Smrg OUTREG(R128_DST_Y_X, (dstY << 16) | dstX); 32042a55b46Smrg OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width); 321bb3c570cSmacallan exaMarkSync(pScreen); 32242a55b46Smrg} 32342a55b46Smrg 32442a55b46Smrg#define R128DoneCopy R128Done 32542a55b46Smrg 32642a55b46Smrgstatic void 32742a55b46SmrgR128Sync(ScreenPtr pScreen, int marker) 32842a55b46Smrg{ 32942a55b46Smrg R128WaitForIdle(xf86ScreenToScrn(pScreen)); 33042a55b46Smrg} 33142a55b46Smrg 33242a55b46Smrgstatic void 33342a55b46SmrgR128Done(PixmapPtr pPixmap) 33442a55b46Smrg{ 33542a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 33642a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 33742a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 33842a55b46Smrg 33942a55b46Smrg info->state_2d.in_use = FALSE; 34042a55b46Smrg#if defined(R128DRI) && defined(RENDER) 34142a55b46Smrg if (info->state_2d.src_pix) { 34242a55b46Smrg pScreen->DestroyPixmap(info->state_2d.src_pix); 34342a55b46Smrg info->state_2d.src_pix = NULL; 34442a55b46Smrg } 34542a55b46Smrg if (info->state_2d.msk_pix) { 34642a55b46Smrg pScreen->DestroyPixmap(info->state_2d.msk_pix); 34742a55b46Smrg info->state_2d.msk_pix = NULL; 34842a55b46Smrg } 34942a55b46Smrg#endif 35042a55b46Smrg} 35142a55b46Smrg 35242a55b46Smrg#ifdef R128DRI 35342a55b46Smrg 35442a55b46Smrg#define R128CCEPrepareSolid R128PrepareSolid 35542a55b46Smrg 35642a55b46Smrgstatic void 35742a55b46SmrgR128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 35842a55b46Smrg{ 35942a55b46Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 36042a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 36142a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 36242a55b46Smrg RING_LOCALS; 36342a55b46Smrg 36442a55b46Smrg R128CCE_REFRESH( pScrn, info ); 36542a55b46Smrg 36642a55b46Smrg BEGIN_RING( 4 ); 36742a55b46Smrg 36842a55b46Smrg OUT_RING_REG( R128_DST_Y_X, (y1 << 16) | x1 ); 36942a55b46Smrg OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) ); 37042a55b46Smrg 37142a55b46Smrg ADVANCE_RING(); 37242a55b46Smrg} 37342a55b46Smrg 37442a55b46Smrg#define R128CCEDoneSolid R128Done 37542a55b46Smrg 37642a55b46Smrg#define R128CCEPrepareCopy R128PrepareCopy 37742a55b46Smrg 37842a55b46Smrgstatic void 37942a55b46SmrgR128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, 38042a55b46Smrg int width, int height) 38142a55b46Smrg{ 38242a55b46Smrg ScreenPtr pScreen = pDstPixmap->drawable.pScreen; 38342a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 38442a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 38542a55b46Smrg RING_LOCALS; 38642a55b46Smrg 38742a55b46Smrg R128CCE_REFRESH( pScrn, info ); 38842a55b46Smrg 38942a55b46Smrg if (info->xdir < 0) srcX += width - 1, dstX += width - 1; 39042a55b46Smrg if (info->ydir < 0) srcY += height - 1, dstY += height - 1; 39142a55b46Smrg 39242a55b46Smrg BEGIN_RING( 6 ); 39342a55b46Smrg 39442a55b46Smrg OUT_RING_REG( R128_SRC_Y_X, (srcY << 16) | srcX ); 39542a55b46Smrg OUT_RING_REG( R128_DST_Y_X, (dstY << 16) | dstX ); 39642a55b46Smrg OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width ); 39742a55b46Smrg 39842a55b46Smrg ADVANCE_RING(); 39942a55b46Smrg} 40042a55b46Smrg 40142a55b46Smrg#define R128CCEDoneCopy R128Done 40242a55b46Smrg 40342a55b46Smrgstatic void 40442a55b46SmrgR128CCESync(ScreenPtr pScreen, int marker) 40542a55b46Smrg{ 40642a55b46Smrg R128CCEWaitForIdle(xf86ScreenToScrn(pScreen)); 40742a55b46Smrg} 40842a55b46Smrg 40942a55b46Smrg#ifdef RENDER 41042a55b46Smrg#include "r128_exa_render.c" 41142a55b46Smrg#endif 41242a55b46Smrg 41342a55b46Smrg#endif 41442a55b46Smrg 415bb3c570cSmacallan/* 416bb3c570cSmacallan * Memcpy-based UTS. 417bb3c570cSmacallan */ 418bb3c570cSmacallanstatic Bool 419bb3c570cSmacallanR128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 420bb3c570cSmacallan char *src, int src_pitch) 421bb3c570cSmacallan{ 422bb3c570cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 423bb3c570cSmacallan R128InfoPtr info = R128PTR(pScrn); 424bb3c570cSmacallan char *dst = info->FB + exaGetPixmapOffset(pDst); 425bb3c570cSmacallan int dst_pitch = exaGetPixmapPitch(pDst); 426bb3c570cSmacallan int bpp = pDst->drawable.bitsPerPixel; 427bb3c570cSmacallan int cpp = (bpp + 7) >> 3; 428bb3c570cSmacallan int wBytes = w * cpp; 429bb3c570cSmacallan 430bb3c570cSmacallan dst += (x * cpp) + (y * dst_pitch); 431bb3c570cSmacallan 432bb3c570cSmacallan R128WaitForIdle(pScrn); 433bb3c570cSmacallan 434bb3c570cSmacallan while (h--) { 435bb3c570cSmacallan memcpy(dst, src, wBytes); 436bb3c570cSmacallan src += src_pitch; 437bb3c570cSmacallan dst += dst_pitch; 438bb3c570cSmacallan } 439bb3c570cSmacallan 440bb3c570cSmacallan return TRUE; 441bb3c570cSmacallan} 442bb3c570cSmacallan 443bb3c570cSmacallan/* 444bb3c570cSmacallan * Hostblit-based UTS. 445bb3c570cSmacallan * this assumes 32bit pixels 446bb3c570cSmacallan */ 447bb3c570cSmacallanstatic Bool 448bb3c570cSmacallanR128UploadToScreenHW(PixmapPtr pDst, int x, int y, int w, int h, 449bb3c570cSmacallan char *src, int src_pitch) 450bb3c570cSmacallan{ 451bb3c570cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 452bb3c570cSmacallan R128InfoPtr info = R128PTR(pScrn); 453bb3c570cSmacallan uint32_t dst_pitch_offset, datatype; 454bb3c570cSmacallan int cnt, line, px; 455bb3c570cSmacallan unsigned char *R128MMIO = info->MMIO; 456bb3c570cSmacallan int bpp = pDst->drawable.bitsPerPixel; 457bb3c570cSmacallan uint32_t *s; 458bb3c570cSmacallan 459bb3c570cSmacallan if (!R128GetDatatypeBpp(bpp, &datatype)) { 460bb3c570cSmacallan R128TRACE(("R128GetDatatypeBpp failed\n")); 461bb3c570cSmacallan return FALSE; 462bb3c570cSmacallan } 463bb3c570cSmacallan 464bb3c570cSmacallan if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) { 465bb3c570cSmacallan R128TRACE(("R128GetPixmapOffsetPitch dest failed\n")); 466bb3c570cSmacallan return FALSE; 467bb3c570cSmacallan } 468bb3c570cSmacallan 469bb3c570cSmacallan info->state_2d.in_use = TRUE; 470bb3c570cSmacallan info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL | 471bb3c570cSmacallan R128_GMC_BRUSH_NONE | 472bb3c570cSmacallan (datatype >> 8) | 473bb3c570cSmacallan R128_GMC_SRC_DATATYPE_COLOR | 474bb3c570cSmacallan R128_ROP3_S | 475bb3c570cSmacallan R128_DP_SRC_SOURCE_HOST_DATA | 476bb3c570cSmacallan R128_GMC_CLR_CMP_CNTL_DIS); 477bb3c570cSmacallan info->state_2d.dp_cntl = R128_DST_X_LEFT_TO_RIGHT | 478bb3c570cSmacallan R128_DST_Y_TOP_TO_BOTTOM; 479bb3c570cSmacallan info->state_2d.dp_write_mask = 0xffffffff; 480bb3c570cSmacallan info->state_2d.dst_pitch_offset = dst_pitch_offset; 481bb3c570cSmacallan info->state_2d.default_sc_bottom_right = R128_DEFAULT_SC_RIGHT_MAX | 482bb3c570cSmacallan R128_DEFAULT_SC_BOTTOM_MAX; 483bb3c570cSmacallan Emit2DState(pScrn); 484bb3c570cSmacallan 485bb3c570cSmacallan R128WaitForFifo(pScrn, 3); 486bb3c570cSmacallan OUTREG(R128_SRC_Y_X, 0); 487bb3c570cSmacallan OUTREG(R128_DST_Y_X, (y << 16) | x); 488bb3c570cSmacallan OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w); 489bb3c570cSmacallan 490bb3c570cSmacallan R128WaitForFifo(pScrn, 32); 491bb3c570cSmacallan cnt = 0; 492bb3c570cSmacallan 493bb3c570cSmacallan for (line = 0; line < h; line++) { 494bb3c570cSmacallan s = (void *)src; 495bb3c570cSmacallan for (px = 0; px < w; px++) { 496bb3c570cSmacallan OUTREG(R128_HOST_DATA0, cpu_to_le32(*s)); 497bb3c570cSmacallan s++; 498bb3c570cSmacallan cnt++; 499bb3c570cSmacallan if (cnt > 31) { 500bb3c570cSmacallan R128WaitForFifo(pScrn, 32); 501bb3c570cSmacallan cnt = 0; 502bb3c570cSmacallan } 503bb3c570cSmacallan } 504bb3c570cSmacallan src += src_pitch; 505bb3c570cSmacallan } 506bb3c570cSmacallan info->state_2d.in_use = FALSE; 507bb3c570cSmacallan exaMarkSync(pDst->drawable.pScreen); 508bb3c570cSmacallan return TRUE; 509bb3c570cSmacallan} 510bb3c570cSmacallan 511bb3c570cSmacallan/* 512bb3c570cSmacallan * Memcpy-based DFS. 513bb3c570cSmacallan */ 514bb3c570cSmacallanstatic Bool 515bb3c570cSmacallanR128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 516bb3c570cSmacallan char *dst, int dst_pitch) 517bb3c570cSmacallan{ 518bb3c570cSmacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 519bb3c570cSmacallan R128InfoPtr info = R128PTR(pScrn); 520bb3c570cSmacallan char *src = info->FB + exaGetPixmapOffset(pSrc); 521bb3c570cSmacallan int src_pitch = exaGetPixmapPitch(pSrc); 522bb3c570cSmacallan 523bb3c570cSmacallan int bpp = pSrc->drawable.bitsPerPixel; 524bb3c570cSmacallan int cpp = (bpp + 7) >> 3; 525bb3c570cSmacallan int wBytes = w * cpp; 526bb3c570cSmacallan 527bb3c570cSmacallan src += (x * cpp) + (y * src_pitch); 528bb3c570cSmacallan 529bb3c570cSmacallan R128WaitForIdle(pScrn); 530bb3c570cSmacallan 531bb3c570cSmacallan while (h--) { 532bb3c570cSmacallan memcpy(dst, src, wBytes); 533bb3c570cSmacallan src += src_pitch; 534bb3c570cSmacallan dst += dst_pitch; 535bb3c570cSmacallan } 536bb3c570cSmacallan 537bb3c570cSmacallan return TRUE; 538bb3c570cSmacallan} 539bb3c570cSmacallan 54042a55b46SmrgBool 54142a55b46SmrgR128EXAInit(ScreenPtr pScreen) 54242a55b46Smrg{ 54342a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 54442a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 54542a55b46Smrg 54642a55b46Smrg info->ExaDriver->exa_major = EXA_VERSION_MAJOR; 54742a55b46Smrg info->ExaDriver->exa_minor = EXA_VERSION_MINOR; 54842a55b46Smrg 54942a55b46Smrg info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset; 550bb3c570cSmacallan info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS; 55142a55b46Smrg 55242a55b46Smrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) 55342a55b46Smrg info->ExaDriver->maxPitchBytes = 16320; 55442a55b46Smrg#endif 55542a55b46Smrg /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */ 55642a55b46Smrg info->ExaDriver->pixmapPitchAlign = 32; 55742a55b46Smrg info->ExaDriver->pixmapOffsetAlign = 32; 55842a55b46Smrg info->ExaDriver->maxX = 2048; 55942a55b46Smrg info->ExaDriver->maxY = 2048; 56042a55b46Smrg 56142a55b46Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 56242a55b46Smrg "Setting up EXA callbacks\n"); 56342a55b46Smrg 56442a55b46Smrg#ifdef R128DRI 56542a55b46Smrg if (info->directRenderingEnabled) { 56642a55b46Smrg info->ExaDriver->PrepareSolid = R128CCEPrepareSolid; 56742a55b46Smrg info->ExaDriver->Solid = R128CCESolid; 56842a55b46Smrg info->ExaDriver->DoneSolid = R128CCEDoneSolid; 56942a55b46Smrg 57042a55b46Smrg info->ExaDriver->PrepareCopy = R128CCEPrepareCopy; 57142a55b46Smrg info->ExaDriver->Copy = R128CCECopy; 57242a55b46Smrg info->ExaDriver->DoneCopy = R128CCEDoneCopy; 57342a55b46Smrg 57442a55b46Smrg#ifdef RENDER 57542a55b46Smrg if (info->RenderAccel) { 576bb3c570cSmacallan info->ExaDriver->flags |= EXA_OFFSCREEN_ALIGN_POT; 57742a55b46Smrg info->ExaDriver->CheckComposite = R128CCECheckComposite; 57842a55b46Smrg info->ExaDriver->PrepareComposite = R128CCEPrepareComposite; 57942a55b46Smrg info->ExaDriver->Composite = R128CCEComposite; 58042a55b46Smrg info->ExaDriver->DoneComposite = R128CCEDoneComposite; 58142a55b46Smrg } 58242a55b46Smrg#endif 58342a55b46Smrg 58442a55b46Smrg info->ExaDriver->WaitMarker = R128CCESync; 58542a55b46Smrg } else 58642a55b46Smrg#endif 58742a55b46Smrg { 58842a55b46Smrg info->ExaDriver->PrepareSolid = R128PrepareSolid; 58942a55b46Smrg info->ExaDriver->Solid = R128Solid; 59042a55b46Smrg info->ExaDriver->DoneSolid = R128DoneSolid; 59142a55b46Smrg 59242a55b46Smrg info->ExaDriver->PrepareCopy = R128PrepareCopy; 59342a55b46Smrg info->ExaDriver->Copy = R128Copy; 59442a55b46Smrg info->ExaDriver->DoneCopy = R128DoneCopy; 59542a55b46Smrg 596bb3c570cSmacallan if (pScrn->bitsPerPixel < 24) { 597bb3c570cSmacallan info->ExaDriver->UploadToScreen = R128UploadToScreen; 598bb3c570cSmacallan } else { 599bb3c570cSmacallan info->ExaDriver->UploadToScreen = R128UploadToScreenHW; 600bb3c570cSmacallan } 601bb3c570cSmacallan info->ExaDriver->DownloadFromScreen = R128DownloadFromScreen; 602bb3c570cSmacallan 60342a55b46Smrg /* The registers used for r128 compositing are CCE specific, just like the 60442a55b46Smrg * registers used for radeon compositing are CP specific. The radeon driver 60542a55b46Smrg * falls back to different registers when there is no DRI. The equivalent 60642a55b46Smrg * registers on the r128 (if they even exist) are not listed in the register 60742a55b46Smrg * file so I can't implement compositing without DRI. 60842a55b46Smrg */ 60942a55b46Smrg 61042a55b46Smrg info->ExaDriver->WaitMarker = R128Sync; 61142a55b46Smrg } 61242a55b46Smrg 61342a55b46Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 61442a55b46Smrg "Initalizing 2D acceleration engine...\n"); 61542a55b46Smrg 61642a55b46Smrg R128EngineInit(pScrn); 61742a55b46Smrg 61842a55b46Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 61942a55b46Smrg "Initializing EXA driver...\n"); 62042a55b46Smrg 62142a55b46Smrg if (!exaDriverInit(pScreen, info->ExaDriver)) { 62242a55b46Smrg free(info->ExaDriver); 62342a55b46Smrg return FALSE; 62442a55b46Smrg } 62542a55b46Smrg 62642a55b46Smrg info->state_2d.composite_setup = FALSE; 62742a55b46Smrg return TRUE; 62842a55b46Smrg} 629