1209ff23fSmrg/* 2209ff23fSmrg * Copyright 2005 Eric Anholt 3209ff23fSmrg * Copyright 2005 Benjamin Herrenschmidt 4209ff23fSmrg * Copyright 2006 Tungsten Graphics, Inc. 5209ff23fSmrg * All Rights Reserved. 6209ff23fSmrg * 7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 8209ff23fSmrg * copy of this software and associated documentation files (the "Software"), 9209ff23fSmrg * to deal in the Software without restriction, including without limitation 10209ff23fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11209ff23fSmrg * and/or sell copies of the Software, and to permit persons to whom the 12209ff23fSmrg * Software is furnished to do so, subject to the following conditions: 13209ff23fSmrg * 14209ff23fSmrg * The above copyright notice and this permission notice (including the next 15209ff23fSmrg * paragraph) shall be included in all copies or substantial portions of the 16209ff23fSmrg * Software. 17209ff23fSmrg * 18209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19209ff23fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20209ff23fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21209ff23fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22209ff23fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24209ff23fSmrg * SOFTWARE. 25209ff23fSmrg * 26209ff23fSmrg * Authors: 27209ff23fSmrg * Eric Anholt <anholt@FreeBSD.org> 28209ff23fSmrg * Zack Rusin <zrusin@trolltech.com> 29209ff23fSmrg * Benjamin Herrenschmidt <benh@kernel.crashing.org> 30f3a0071aSrjs * Michel Dänzer <michel@daenzer.net> 31209ff23fSmrg * 32209ff23fSmrg */ 33209ff23fSmrg 34209ff23fSmrg#if defined(ACCEL_MMIO) && defined(ACCEL_CP) 35209ff23fSmrg#error Cannot define both MMIO and CP acceleration! 36209ff23fSmrg#endif 37209ff23fSmrg 38209ff23fSmrg#if !defined(UNIXCPP) || defined(ANSICPP) 39209ff23fSmrg#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix 40209ff23fSmrg#else 41209ff23fSmrg#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix 42209ff23fSmrg#endif 43209ff23fSmrg 44209ff23fSmrg#ifdef ACCEL_MMIO 45209ff23fSmrg#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) 46209ff23fSmrg#else 47209ff23fSmrg#ifdef ACCEL_CP 48209ff23fSmrg#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) 49209ff23fSmrg#else 50209ff23fSmrg#error No accel type defined! 51209ff23fSmrg#endif 52209ff23fSmrg#endif 53209ff23fSmrg 54209ff23fSmrg#include <errno.h> 55209ff23fSmrg#include <string.h> 56209ff23fSmrg 57209ff23fSmrg#include "radeon.h" 58209ff23fSmrg 59209ff23fSmrg#include "exa.h" 60209ff23fSmrg 61209ff23fSmrgstatic int 62209ff23fSmrgFUNC_NAME(RADEONMarkSync)(ScreenPtr pScreen) 63209ff23fSmrg{ 64209ff23fSmrg RINFO_FROM_SCREEN(pScreen); 65209ff23fSmrg 66209ff23fSmrg TRACE; 67209ff23fSmrg 68b7e1c893Smrg return ++info->accel_state->exaSyncMarker; 69209ff23fSmrg} 70209ff23fSmrg 71209ff23fSmrgstatic void 72209ff23fSmrgFUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) 73209ff23fSmrg{ 74c135ecebSveego ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 75209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 76209ff23fSmrg 77f1bc02b7Smrg if (info->cs) 78f1bc02b7Smrg return; 79f1bc02b7Smrg 80209ff23fSmrg TRACE; 81209ff23fSmrg 82b7e1c893Smrg if (info->accel_state->exaMarkerSynced != marker) { 83209ff23fSmrg FUNC_NAME(RADEONWaitForIdle)(pScrn); 84b7e1c893Smrg info->accel_state->exaMarkerSynced = marker; 85209ff23fSmrg } 86209ff23fSmrg 87b7e1c893Smrg RADEONPTR(pScrn)->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; 88209ff23fSmrg} 89209ff23fSmrg 90f1bc02b7Smrgstatic void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op) 91f1bc02b7Smrg{ 92f1bc02b7Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 93f1bc02b7Smrg int has_src; 94f1bc02b7Smrg ACCEL_PREAMBLE(); 95f1bc02b7Smrg 96f1bc02b7Smrg /* don't emit if no operation in progress */ 97f1bc02b7Smrg if (info->state_2d.op == 0 && op == 0) 98f1bc02b7Smrg return; 99f1bc02b7Smrg 100f1bc02b7Smrg has_src = info->state_2d.src_pitch_offset || (info->cs && info->state_2d.src_bo); 101f1bc02b7Smrg 102f1bc02b7Smrg if (has_src) { 103f1bc02b7Smrg BEGIN_ACCEL_RELOC(10, 2); 104f1bc02b7Smrg } else { 105f1bc02b7Smrg BEGIN_ACCEL_RELOC(9, 1); 106f1bc02b7Smrg } 107f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); 108f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); 109f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); 110f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); 111f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); 112f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); 113f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask); 114f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl); 115f1bc02b7Smrg 116f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); 117f1bc02b7Smrg if (info->cs) 118f1bc02b7Smrg OUT_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM); 119f1bc02b7Smrg 120f1bc02b7Smrg if (has_src) { 121f1bc02b7Smrg OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); 122f1bc02b7Smrg if (info->cs) 123f1bc02b7Smrg OUT_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); 124f1bc02b7Smrg 125f1bc02b7Smrg } 126f1bc02b7Smrg FINISH_ACCEL(); 127f1bc02b7Smrg 128f1bc02b7Smrg if (op) 129f1bc02b7Smrg info->state_2d.op = op; 130f1bc02b7Smrg if (info->cs) 131f1bc02b7Smrg info->reemit_current2d = FUNC_NAME(Emit2DState); 132f1bc02b7Smrg} 133f1bc02b7Smrg 134f1bc02b7Smrgstatic void 135f3a0071aSrjsFUNC_NAME(RADEONFlush2D)(PixmapPtr pPix) 136f1bc02b7Smrg{ 137f1bc02b7Smrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 138f1bc02b7Smrg ACCEL_PREAMBLE(); 139f1bc02b7Smrg 140f1bc02b7Smrg TRACE; 141f1bc02b7Smrg 142f1bc02b7Smrg BEGIN_ACCEL(2); 143f1bc02b7Smrg OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 144f1bc02b7Smrg OUT_ACCEL_REG(RADEON_WAIT_UNTIL, 145f1bc02b7Smrg RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 146f1bc02b7Smrg FINISH_ACCEL(); 147f1bc02b7Smrg} 148f1bc02b7Smrg 149f3a0071aSrjsstatic void 150f3a0071aSrjsFUNC_NAME(RADEONDone2D)(PixmapPtr pPix) 151f3a0071aSrjs{ 152f3a0071aSrjs RINFO_FROM_SCREEN(pPix->drawable.pScreen); 153f3a0071aSrjs info->state_2d.op = 0; 154f3a0071aSrjs 155f3a0071aSrjs FUNC_NAME(RADEONFlush2D)(pPix); 156f3a0071aSrjs} 157f3a0071aSrjs 158209ff23fSmrgstatic Bool 159209ff23fSmrgFUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) 160209ff23fSmrg{ 161209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 162209ff23fSmrg uint32_t datatype, dst_pitch_offset; 163209ff23fSmrg 164209ff23fSmrg TRACE; 165209ff23fSmrg 166209ff23fSmrg if (pPix->drawable.bitsPerPixel == 24) 167209ff23fSmrg RADEON_FALLBACK(("24bpp unsupported\n")); 168209ff23fSmrg if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype)) 169209ff23fSmrg RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 170209ff23fSmrg if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset)) 171209ff23fSmrg RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); 172209ff23fSmrg 173209ff23fSmrg RADEON_SWITCH_TO_2D(); 174209ff23fSmrg 175f1bc02b7Smrg#ifdef XF86DRM_MODE 176f1bc02b7Smrg if (info->cs) { 177f1bc02b7Smrg struct radeon_exa_pixmap_priv *driver_priv; 178f1bc02b7Smrg int ret; 179f1bc02b7Smrg 180f1bc02b7Smrg radeon_cs_space_reset_bos(info->cs); 181f1bc02b7Smrg 182f1bc02b7Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 183f1bc02b7Smrg radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); 184f1bc02b7Smrg 185f1bc02b7Smrg ret = radeon_cs_space_check(info->cs); 186f1bc02b7Smrg if (ret) 187f1bc02b7Smrg RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n")); 188f1bc02b7Smrg 189f1bc02b7Smrg driver_priv = exaGetPixmapDriverPrivate(pPix); 190f1bc02b7Smrg if (driver_priv) 191f1bc02b7Smrg info->state_2d.dst_bo = driver_priv->bo; 192f1bc02b7Smrg } 193f1bc02b7Smrg#endif 194f1bc02b7Smrg 195f1bc02b7Smrg info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX | 196f1bc02b7Smrg RADEON_DEFAULT_SC_BOTTOM_MAX); 197f1bc02b7Smrg info->state_2d.dp_brush_bkgd_clr = 0x00000000; 198f1bc02b7Smrg info->state_2d.dp_src_frgd_clr = 0xffffffff; 199f1bc02b7Smrg info->state_2d.dp_src_bkgd_clr = 0x00000000; 200f1bc02b7Smrg info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | 201f1bc02b7Smrg RADEON_GMC_BRUSH_SOLID_COLOR | 202f1bc02b7Smrg (datatype << 8) | 203f1bc02b7Smrg RADEON_GMC_SRC_DATATYPE_COLOR | 204f1bc02b7Smrg RADEON_ROP[alu].pattern | 205f1bc02b7Smrg RADEON_GMC_CLR_CMP_CNTL_DIS); 206f1bc02b7Smrg info->state_2d.dp_brush_frgd_clr = fg; 207f1bc02b7Smrg info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM); 208f1bc02b7Smrg info->state_2d.dp_write_mask = pm; 209f1bc02b7Smrg info->state_2d.dst_pitch_offset = dst_pitch_offset; 210f1bc02b7Smrg info->state_2d.src_pitch_offset = 0; 211f1bc02b7Smrg info->state_2d.src_bo = NULL; 212f1bc02b7Smrg 213f1bc02b7Smrg info->accel_state->dst_pix = pPix; 214f1bc02b7Smrg 215f1bc02b7Smrg FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID); 216209ff23fSmrg 217209ff23fSmrg return TRUE; 218209ff23fSmrg} 219209ff23fSmrg 220209ff23fSmrg 221209ff23fSmrgstatic void 222209ff23fSmrgFUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2) 223209ff23fSmrg{ 224209ff23fSmrg RINFO_FROM_SCREEN(pPix->drawable.pScreen); 225209ff23fSmrg ACCEL_PREAMBLE(); 226209ff23fSmrg 227209ff23fSmrg TRACE; 228209ff23fSmrg 229f1bc02b7Smrg#if defined(ACCEL_CP) && defined(XF86DRM_MODE) 230f1bc02b7Smrg if (info->cs && CS_FULL(info->cs)) { 231f3a0071aSrjs FUNC_NAME(RADEONFlush2D)(info->accel_state->dst_pix); 232f1bc02b7Smrg radeon_cs_flush_indirect(pScrn); 233f1bc02b7Smrg } 234f1bc02b7Smrg#endif 235f1bc02b7Smrg 236b7e1c893Smrg if (info->accel_state->vsync) 237f1bc02b7Smrg FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, 238f1bc02b7Smrg radeon_pick_best_crtc(pScrn, x1, x2, y1, y2), 239f1bc02b7Smrg y1, y2); 240b7e1c893Smrg 241209ff23fSmrg BEGIN_ACCEL(2); 242209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_Y_X, (y1 << 16) | x1); 243209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1)); 244209ff23fSmrg FINISH_ACCEL(); 245209ff23fSmrg} 246209ff23fSmrg 247209ff23fSmrgvoid 248209ff23fSmrgFUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, 249209ff23fSmrg uint32_t dst_pitch_offset, uint32_t datatype, int rop, 250209ff23fSmrg Pixel planemask) 251209ff23fSmrg{ 252209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 253209ff23fSmrg 254f1bc02b7Smrg /* setup 2D state */ 255f1bc02b7Smrg info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | 256f1bc02b7Smrg RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 257f1bc02b7Smrg RADEON_GMC_BRUSH_NONE | 258f1bc02b7Smrg (datatype << 8) | 259f1bc02b7Smrg RADEON_GMC_SRC_DATATYPE_COLOR | 260f1bc02b7Smrg RADEON_ROP[rop].rop | 261f1bc02b7Smrg RADEON_DP_SRC_SOURCE_MEMORY | 262f1bc02b7Smrg RADEON_GMC_CLR_CMP_CNTL_DIS); 263f1bc02b7Smrg info->state_2d.dp_cntl = ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | 264f1bc02b7Smrg (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)); 265f1bc02b7Smrg info->state_2d.dp_brush_frgd_clr = 0xffffffff; 266f1bc02b7Smrg info->state_2d.dp_brush_bkgd_clr = 0x00000000; 267f1bc02b7Smrg info->state_2d.dp_src_frgd_clr = 0xffffffff; 268f1bc02b7Smrg info->state_2d.dp_src_bkgd_clr = 0x00000000; 269f1bc02b7Smrg info->state_2d.dp_write_mask = planemask; 270f1bc02b7Smrg info->state_2d.dst_pitch_offset = dst_pitch_offset; 271f1bc02b7Smrg info->state_2d.src_pitch_offset = src_pitch_offset; 272f1bc02b7Smrg info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX 273f1bc02b7Smrg | RADEON_DEFAULT_SC_BOTTOM_MAX); 274f1bc02b7Smrg 275f1bc02b7Smrg FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY); 276209ff23fSmrg} 277209ff23fSmrg 278209ff23fSmrgstatic Bool 279209ff23fSmrgFUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, 280209ff23fSmrg int xdir, int ydir, 281209ff23fSmrg int rop, 282209ff23fSmrg Pixel planemask) 283209ff23fSmrg{ 284209ff23fSmrg RINFO_FROM_SCREEN(pDst->drawable.pScreen); 285209ff23fSmrg uint32_t datatype, src_pitch_offset, dst_pitch_offset; 286209ff23fSmrg TRACE; 287209ff23fSmrg 288209ff23fSmrg if (pDst->drawable.bitsPerPixel == 24) 289209ff23fSmrg RADEON_FALLBACK(("24bpp unsupported")); 290209ff23fSmrg if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) 291209ff23fSmrg RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); 292209ff23fSmrg if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) 293209ff23fSmrg RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); 294209ff23fSmrg if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) 295209ff23fSmrg RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); 296209ff23fSmrg 297f1bc02b7Smrg RADEON_SWITCH_TO_2D(); 298f1bc02b7Smrg 299f1bc02b7Smrg#ifdef XF86DRM_MODE 300f1bc02b7Smrg if (info->cs) { 301f1bc02b7Smrg struct radeon_exa_pixmap_priv *driver_priv; 302f1bc02b7Smrg int ret; 303f1bc02b7Smrg 304f1bc02b7Smrg radeon_cs_space_reset_bos(info->cs); 305f1bc02b7Smrg 306f1bc02b7Smrg driver_priv = exaGetPixmapDriverPrivate(pSrc); 307f1bc02b7Smrg radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); 308f1bc02b7Smrg info->state_2d.src_bo = driver_priv->bo; 309f1bc02b7Smrg 310f1bc02b7Smrg driver_priv = exaGetPixmapDriverPrivate(pDst); 311f1bc02b7Smrg radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); 312f1bc02b7Smrg info->state_2d.dst_bo = driver_priv->bo; 313f1bc02b7Smrg 314f1bc02b7Smrg ret = radeon_cs_space_check(info->cs); 315f1bc02b7Smrg if (ret) 316f1bc02b7Smrg RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n")); 317f1bc02b7Smrg } 318f1bc02b7Smrg#endif 319f1bc02b7Smrg 320f1bc02b7Smrg info->accel_state->xdir = xdir; 321f1bc02b7Smrg info->accel_state->ydir = ydir; 322f1bc02b7Smrg info->accel_state->dst_pix = pDst; 323f1bc02b7Smrg 324209ff23fSmrg FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset, 325209ff23fSmrg datatype, rop, planemask); 326209ff23fSmrg 327209ff23fSmrg return TRUE; 328209ff23fSmrg} 329209ff23fSmrg 330209ff23fSmrgvoid 331209ff23fSmrgFUNC_NAME(RADEONCopy)(PixmapPtr pDst, 332209ff23fSmrg int srcX, int srcY, 333209ff23fSmrg int dstX, int dstY, 334209ff23fSmrg int w, int h) 335209ff23fSmrg{ 336209ff23fSmrg RINFO_FROM_SCREEN(pDst->drawable.pScreen); 337209ff23fSmrg ACCEL_PREAMBLE(); 338209ff23fSmrg 339209ff23fSmrg TRACE; 340209ff23fSmrg 341f1bc02b7Smrg#if defined(ACCEL_CP) && defined(XF86DRM_MODE) 342f1bc02b7Smrg if (info->cs && CS_FULL(info->cs)) { 343f3a0071aSrjs FUNC_NAME(RADEONFlush2D)(info->accel_state->dst_pix); 344f1bc02b7Smrg radeon_cs_flush_indirect(pScrn); 345f1bc02b7Smrg } 346f1bc02b7Smrg#endif 347f1bc02b7Smrg 348b7e1c893Smrg if (info->accel_state->xdir < 0) { 349209ff23fSmrg srcX += w - 1; 350209ff23fSmrg dstX += w - 1; 351209ff23fSmrg } 352b7e1c893Smrg if (info->accel_state->ydir < 0) { 353209ff23fSmrg srcY += h - 1; 354209ff23fSmrg dstY += h - 1; 355209ff23fSmrg } 356209ff23fSmrg 357f1bc02b7Smrg if (info->accel_state->vsync) 358f1bc02b7Smrg FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, 359f1bc02b7Smrg radeon_pick_best_crtc(pScrn, dstX, dstX + w, dstY, dstY + h), 360f1bc02b7Smrg dstY, dstY + h); 361b7e1c893Smrg 362209ff23fSmrg BEGIN_ACCEL(3); 363209ff23fSmrg 364209ff23fSmrg OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 365209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 366209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 367209ff23fSmrg 368209ff23fSmrg FINISH_ACCEL(); 369209ff23fSmrg} 370209ff23fSmrg 371b7e1c893Smrg#ifdef ACCEL_CP 372b7e1c893Smrg 373209ff23fSmrgstatic Bool 374b7e1c893SmrgRADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h, 375b7e1c893Smrg char *src, int src_pitch) 376209ff23fSmrg{ 377209ff23fSmrg RINFO_FROM_SCREEN(pDst->drawable.pScreen); 378209ff23fSmrg unsigned int bpp = pDst->drawable.bitsPerPixel; 379209ff23fSmrg unsigned int hpass; 380209ff23fSmrg uint32_t buf_pitch, dst_pitch_off; 381209ff23fSmrg 382209ff23fSmrg TRACE; 383209ff23fSmrg 384209ff23fSmrg if (bpp < 8) 385209ff23fSmrg return FALSE; 386209ff23fSmrg 387209ff23fSmrg if (info->directRenderingEnabled && 388209ff23fSmrg RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) { 389209ff23fSmrg uint8_t *buf; 390209ff23fSmrg int cpp = bpp / 8; 391209ff23fSmrg ACCEL_PREAMBLE(); 392209ff23fSmrg 393209ff23fSmrg RADEON_SWITCH_TO_2D(); 394b7e1c893Smrg 395b7e1c893Smrg if (info->accel_state->vsync) 396f1bc02b7Smrg FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, 397f1bc02b7Smrg radeon_pick_best_crtc(pScrn, x, x + w, y, y + h), 398f1bc02b7Smrg y, y + h); 399b7e1c893Smrg 400209ff23fSmrg while ((buf = RADEONHostDataBlit(pScrn, 401209ff23fSmrg cpp, w, dst_pitch_off, &buf_pitch, 402209ff23fSmrg x, &y, (unsigned int*)&h, &hpass)) != 0) { 403209ff23fSmrg RADEONHostDataBlitCopyPass(pScrn, cpp, buf, (uint8_t *)src, 404209ff23fSmrg hpass, buf_pitch, src_pitch); 405209ff23fSmrg src += hpass * src_pitch; 406209ff23fSmrg } 407209ff23fSmrg 408209ff23fSmrg exaMarkSync(pDst->drawable.pScreen); 409209ff23fSmrg return TRUE; 410209ff23fSmrg } 411209ff23fSmrg 412b7e1c893Smrg return FALSE; 413209ff23fSmrg} 414209ff23fSmrg 415209ff23fSmrg/* Emit blit with arbitrary source and destination offsets and pitches */ 416209ff23fSmrgstatic void 417f1bc02b7SmrgRADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo, 418f1bc02b7Smrg struct radeon_bo *dst_bo, uint32_t datatype, 419f1bc02b7Smrg uint32_t src_pitch_offset, uint32_t dst_pitch_offset, 420f1bc02b7Smrg int srcX, int srcY, int dstX, int dstY, int w, int h, 421f1bc02b7Smrg uint32_t src_domain, uint32_t dst_domain) 422209ff23fSmrg{ 423209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 424209ff23fSmrg ACCEL_PREAMBLE(); 425209ff23fSmrg 426f1bc02b7Smrg if (src_bo && dst_bo) { 427f1bc02b7Smrg BEGIN_ACCEL_RELOC(6, 2); 428f1bc02b7Smrg } else if (src_bo && dst_bo == NULL) { 429f1bc02b7Smrg BEGIN_ACCEL_RELOC(6, 1); 430f1bc02b7Smrg } else { 431f1bc02b7Smrg BEGIN_ACCEL(6); 432f1bc02b7Smrg } 433209ff23fSmrg OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, 434209ff23fSmrg RADEON_GMC_DST_PITCH_OFFSET_CNTL | 435209ff23fSmrg RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 436209ff23fSmrg RADEON_GMC_BRUSH_NONE | 437209ff23fSmrg (datatype << 8) | 438209ff23fSmrg RADEON_GMC_SRC_DATATYPE_COLOR | 439209ff23fSmrg RADEON_ROP3_S | 440209ff23fSmrg RADEON_DP_SRC_SOURCE_MEMORY | 441209ff23fSmrg RADEON_GMC_CLR_CMP_CNTL_DIS | 442209ff23fSmrg RADEON_GMC_WR_MSK_DIS); 443209ff23fSmrg OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); 444f1bc02b7Smrg if (src_bo) { 445f1bc02b7Smrg OUT_RELOC(src_bo, src_domain, 0); 446f1bc02b7Smrg } 447209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); 448f1bc02b7Smrg if (dst_bo) { 449f1bc02b7Smrg OUT_RELOC(dst_bo, 0, dst_domain); 450f1bc02b7Smrg } 451209ff23fSmrg OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); 452209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); 453209ff23fSmrg OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); 454209ff23fSmrg FINISH_ACCEL(); 455209ff23fSmrg BEGIN_ACCEL(2); 456209ff23fSmrg OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL); 457209ff23fSmrg OUT_ACCEL_REG(RADEON_WAIT_UNTIL, 458209ff23fSmrg RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); 459209ff23fSmrg FINISH_ACCEL(); 460209ff23fSmrg} 461b7e1c893Smrg 462f1bc02b7Smrg#if defined(XF86DRM_MODE) 463f1bc02b7Smrgstatic Bool 464f1bc02b7SmrgRADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, 465f1bc02b7Smrg char *src, int src_pitch) 466f1bc02b7Smrg{ 467f1bc02b7Smrg ScreenPtr pScreen = pDst->drawable.pScreen; 468f1bc02b7Smrg RINFO_FROM_SCREEN(pScreen); 469f1bc02b7Smrg struct radeon_exa_pixmap_priv *driver_priv; 47069d0ef43Smrg struct radeon_bo *scratch = NULL; 47169d0ef43Smrg struct radeon_bo *copy_dst; 472f1bc02b7Smrg unsigned char *dst; 473f1bc02b7Smrg unsigned size; 474f1bc02b7Smrg uint32_t datatype = 0; 475f1bc02b7Smrg uint32_t dst_domain; 476f1bc02b7Smrg uint32_t dst_pitch_offset; 477f1bc02b7Smrg unsigned bpp = pDst->drawable.bitsPerPixel; 478f1bc02b7Smrg uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); 47969d0ef43Smrg uint32_t copy_pitch; 480f1bc02b7Smrg uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; 48169d0ef43Smrg int ret; 48269d0ef43Smrg Bool flush = TRUE; 483f1bc02b7Smrg Bool r; 484f1bc02b7Smrg int i; 485f1bc02b7Smrg 486f1bc02b7Smrg if (bpp < 8) 487f1bc02b7Smrg return FALSE; 488f1bc02b7Smrg 489f1bc02b7Smrg driver_priv = exaGetPixmapDriverPrivate(pDst); 490f1bc02b7Smrg if (!driver_priv || !driver_priv->bo) 491f1bc02b7Smrg return FALSE; 492f1bc02b7Smrg 493f1bc02b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 494f1bc02b7Smrg switch (bpp) { 495f1bc02b7Smrg case 32: 496f1bc02b7Smrg swap = RADEON_HOST_DATA_SWAP_32BIT; 497f1bc02b7Smrg break; 498f1bc02b7Smrg case 16: 499f1bc02b7Smrg swap = RADEON_HOST_DATA_SWAP_16BIT; 500f1bc02b7Smrg break; 501f1bc02b7Smrg } 502f1bc02b7Smrg#endif 503f1bc02b7Smrg 50469d0ef43Smrg /* If we know the BO won't be busy, don't bother with a scratch */ 50569d0ef43Smrg copy_dst = driver_priv->bo; 50669d0ef43Smrg copy_pitch = pDst->devKind; 5070f6d6f99Smrg if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { 50870cce690Smrg if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 50970cce690Smrg flush = FALSE; 51070cce690Smrg if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain)) 51170cce690Smrg goto copy; 51270cce690Smrg } 513f1bc02b7Smrg } 514f1bc02b7Smrg 515f1bc02b7Smrg size = scratch_pitch * h; 516f1bc02b7Smrg scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); 517f1bc02b7Smrg if (scratch == NULL) { 51869d0ef43Smrg goto copy; 519f1bc02b7Smrg } 520f1bc02b7Smrg radeon_cs_space_reset_bos(info->cs); 521f1bc02b7Smrg radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM); 522f1bc02b7Smrg radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0); 52369d0ef43Smrg ret = radeon_cs_space_check(info->cs); 52469d0ef43Smrg if (ret) { 52569d0ef43Smrg goto copy; 526f1bc02b7Smrg } 52769d0ef43Smrg copy_dst = scratch; 52869d0ef43Smrg copy_pitch = scratch_pitch; 52969d0ef43Smrg flush = FALSE; 530f1bc02b7Smrg 531f1bc02b7Smrgcopy: 53269d0ef43Smrg if (flush) 53369d0ef43Smrg radeon_cs_flush_indirect(pScrn); 53469d0ef43Smrg 53569d0ef43Smrg ret = radeon_bo_map(copy_dst, 0); 53669d0ef43Smrg if (ret) { 537f1bc02b7Smrg r = FALSE; 538f1bc02b7Smrg goto out; 539f1bc02b7Smrg } 540f1bc02b7Smrg r = TRUE; 541f1bc02b7Smrg size = w * bpp / 8; 54269d0ef43Smrg dst = copy_dst->ptr; 54369d0ef43Smrg if (copy_dst == driver_priv->bo) 54469d0ef43Smrg dst += y * copy_pitch + x * bpp / 8; 545f1bc02b7Smrg for (i = 0; i < h; i++) { 54669d0ef43Smrg RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap); 547f1bc02b7Smrg src += src_pitch; 548f1bc02b7Smrg } 54969d0ef43Smrg radeon_bo_unmap(copy_dst); 550f1bc02b7Smrg 55169d0ef43Smrg if (copy_dst == scratch) { 552f1bc02b7Smrg RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype); 553f1bc02b7Smrg RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset); 554f1bc02b7Smrg ACCEL_PREAMBLE(); 555f1bc02b7Smrg RADEON_SWITCH_TO_2D(); 556f1bc02b7Smrg RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16, 557f1bc02b7Smrg dst_pitch_offset, 0, 0, x, y, w, h, 558f1bc02b7Smrg RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM); 559f1bc02b7Smrg } 560f1bc02b7Smrg 561f1bc02b7Smrgout: 56269d0ef43Smrg if (scratch) 563f1bc02b7Smrg radeon_bo_unref(scratch); 564f1bc02b7Smrg return r; 565f1bc02b7Smrg} 566f1bc02b7Smrg 567f1bc02b7Smrgstatic Bool 568f1bc02b7SmrgRADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, 569f1bc02b7Smrg int h, char *dst, int dst_pitch) 570f1bc02b7Smrg{ 571f1bc02b7Smrg RINFO_FROM_SCREEN(pSrc->drawable.pScreen); 572f1bc02b7Smrg struct radeon_exa_pixmap_priv *driver_priv; 57369d0ef43Smrg struct radeon_bo *scratch = NULL; 57469d0ef43Smrg struct radeon_bo *copy_src; 575f1bc02b7Smrg unsigned size; 576f1bc02b7Smrg uint32_t datatype = 0; 577f1bc02b7Smrg uint32_t src_domain = 0; 578f1bc02b7Smrg uint32_t src_pitch_offset; 579f1bc02b7Smrg unsigned bpp = pSrc->drawable.bitsPerPixel; 580f1bc02b7Smrg uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); 58169d0ef43Smrg uint32_t copy_pitch; 582f1bc02b7Smrg uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; 58369d0ef43Smrg int ret; 58469d0ef43Smrg Bool flush = FALSE; 585f1bc02b7Smrg Bool r; 586f1bc02b7Smrg 587f1bc02b7Smrg if (bpp < 8) 588f1bc02b7Smrg return FALSE; 589f1bc02b7Smrg 590f1bc02b7Smrg driver_priv = exaGetPixmapDriverPrivate(pSrc); 591f1bc02b7Smrg if (!driver_priv || !driver_priv->bo) 592f1bc02b7Smrg return FALSE; 593f1bc02b7Smrg 594f1bc02b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 595f1bc02b7Smrg switch (bpp) { 596f1bc02b7Smrg case 32: 597f1bc02b7Smrg swap = RADEON_HOST_DATA_SWAP_32BIT; 598f1bc02b7Smrg break; 599f1bc02b7Smrg case 16: 600f1bc02b7Smrg swap = RADEON_HOST_DATA_SWAP_16BIT; 601f1bc02b7Smrg break; 602f1bc02b7Smrg } 603f1bc02b7Smrg#endif 604f1bc02b7Smrg 60569d0ef43Smrg /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ 60669d0ef43Smrg copy_src = driver_priv->bo; 60769d0ef43Smrg copy_pitch = pSrc->devKind; 6080f6d6f99Smrg if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { 60970cce690Smrg if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 61070cce690Smrg src_domain = radeon_bo_get_src_domain(driver_priv->bo); 61170cce690Smrg if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 61270cce690Smrg (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) 61370cce690Smrg src_domain = 0; 61470cce690Smrg else /* A write may be scheduled */ 61570cce690Smrg flush = TRUE; 61670cce690Smrg } 617f1bc02b7Smrg 61870cce690Smrg if (!src_domain) 61970cce690Smrg radeon_bo_is_busy(driver_priv->bo, &src_domain); 620f1bc02b7Smrg 62170cce690Smrg if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) 62270cce690Smrg goto copy; 623f1bc02b7Smrg } 624f1bc02b7Smrg size = scratch_pitch * h; 625f1bc02b7Smrg scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); 626f1bc02b7Smrg if (scratch == NULL) { 62769d0ef43Smrg goto copy; 628f1bc02b7Smrg } 629f1bc02b7Smrg radeon_cs_space_reset_bos(info->cs); 630f1bc02b7Smrg radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); 631f1bc02b7Smrg radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT); 63269d0ef43Smrg ret = radeon_cs_space_check(info->cs); 63369d0ef43Smrg if (ret) { 63469d0ef43Smrg goto copy; 635f1bc02b7Smrg } 636f1bc02b7Smrg RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype); 637f1bc02b7Smrg RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); 638f1bc02b7Smrg ACCEL_PREAMBLE(); 639f1bc02b7Smrg RADEON_SWITCH_TO_2D(); 640f1bc02b7Smrg RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset, 641f1bc02b7Smrg scratch_pitch << 16, x, y, 0, 0, w, h, 642f1bc02b7Smrg RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 643f1bc02b7Smrg RADEON_GEM_DOMAIN_GTT); 64469d0ef43Smrg copy_src = scratch; 64569d0ef43Smrg copy_pitch = scratch_pitch; 64669d0ef43Smrg flush = TRUE; 647f1bc02b7Smrg 648f1bc02b7Smrgcopy: 64969d0ef43Smrg if (flush) 65069d0ef43Smrg FLUSH_RING(); 65169d0ef43Smrg 65269d0ef43Smrg ret = radeon_bo_map(copy_src, 0); 65369d0ef43Smrg if (ret) { 65469d0ef43Smrg ErrorF("failed to map pixmap: %d\n", ret); 655f1bc02b7Smrg r = FALSE; 656f1bc02b7Smrg goto out; 657f1bc02b7Smrg } 658f1bc02b7Smrg r = TRUE; 659f1bc02b7Smrg w *= bpp / 8; 66069d0ef43Smrg if (copy_src == driver_priv->bo) 66169d0ef43Smrg size = y * copy_pitch + x * bpp / 8; 662f1bc02b7Smrg else 663f1bc02b7Smrg size = 0; 664f1bc02b7Smrg while (h--) { 66569d0ef43Smrg RADEONCopySwap((uint8_t*)dst, copy_src->ptr + size, w, swap); 66669d0ef43Smrg size += copy_pitch; 667f1bc02b7Smrg dst += dst_pitch; 668f1bc02b7Smrg } 66969d0ef43Smrg radeon_bo_unmap(copy_src); 670f1bc02b7Smrgout: 67169d0ef43Smrg if (scratch) 672f1bc02b7Smrg radeon_bo_unref(scratch); 673f1bc02b7Smrg return r; 674f1bc02b7Smrg} 675f1bc02b7Smrg#endif 676209ff23fSmrg 677209ff23fSmrgstatic Bool 678b7e1c893SmrgRADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h, 679209ff23fSmrg char *dst, int dst_pitch) 680209ff23fSmrg{ 681209ff23fSmrg RINFO_FROM_SCREEN(pSrc->drawable.pScreen); 682209ff23fSmrg uint8_t *src = info->FB + exaGetPixmapOffset(pSrc); 683209ff23fSmrg int bpp = pSrc->drawable.bitsPerPixel; 684f1bc02b7Smrg uint32_t datatype, src_pitch_offset, scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64), scratch_off = 0; 685209ff23fSmrg drmBufPtr scratch; 686209ff23fSmrg 687209ff23fSmrg TRACE; 688209ff23fSmrg 689209ff23fSmrg /* 690209ff23fSmrg * Try to accelerate download. Use an indirect buffer as scratch space, 691209ff23fSmrg * blitting the bits to one half while copying them out of the other one and 692209ff23fSmrg * then swapping the halves. 693209ff23fSmrg */ 694b7e1c893Smrg if (bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) && 695209ff23fSmrg RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) && 696209ff23fSmrg (scratch = RADEONCPGetBuffer(pScrn))) 697209ff23fSmrg { 698209ff23fSmrg int swap = RADEON_HOST_DATA_SWAP_NONE, wpass = w * bpp / 8; 699209ff23fSmrg int hpass = min(h, scratch->total/2 / scratch_pitch); 700209ff23fSmrg uint32_t scratch_pitch_offset = scratch_pitch << 16 701b7e1c893Smrg | (info->gartLocation + info->dri->bufStart 702209ff23fSmrg + scratch->idx * scratch->total) >> 10; 703b7e1c893Smrg drm_radeon_indirect_t indirect; 704209ff23fSmrg ACCEL_PREAMBLE(); 705209ff23fSmrg 706209ff23fSmrg RADEON_SWITCH_TO_2D(); 707209ff23fSmrg 708209ff23fSmrg /* Kick the first blit as early as possible */ 709f1bc02b7Smrg RADEONBlitChunk(pScrn, NULL, NULL, datatype, src_pitch_offset, 710f1bc02b7Smrg scratch_pitch_offset, x, y, 0, 0, w, hpass, 0, 0); 711209ff23fSmrg FLUSH_RING(); 712209ff23fSmrg 713209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 714209ff23fSmrg switch (bpp) { 715209ff23fSmrg case 16: 716209ff23fSmrg swap = RADEON_HOST_DATA_SWAP_16BIT; 717209ff23fSmrg break; 718209ff23fSmrg case 32: 719209ff23fSmrg swap = RADEON_HOST_DATA_SWAP_32BIT; 720209ff23fSmrg break; 721209ff23fSmrg } 722209ff23fSmrg#endif 723209ff23fSmrg 724209ff23fSmrg while (h) { 725209ff23fSmrg int oldhpass = hpass, i = 0; 726209ff23fSmrg 727209ff23fSmrg src = (uint8_t*)scratch->address + scratch_off; 728209ff23fSmrg 729209ff23fSmrg y += oldhpass; 730209ff23fSmrg h -= oldhpass; 731209ff23fSmrg hpass = min(h, scratch->total/2 / scratch_pitch); 732209ff23fSmrg 733209ff23fSmrg /* Prepare next blit if anything's left */ 734209ff23fSmrg if (hpass) { 735209ff23fSmrg scratch_off = scratch->total/2 - scratch_off; 736f1bc02b7Smrg RADEONBlitChunk(pScrn, NULL, NULL, datatype, src_pitch_offset, 737f1bc02b7Smrg scratch_pitch_offset + (scratch_off >> 10), 738f1bc02b7Smrg x, y, 0, 0, w, hpass, 0, 0); 739209ff23fSmrg } 740209ff23fSmrg 741209ff23fSmrg /* 742209ff23fSmrg * Wait for previous blit to complete. 743209ff23fSmrg * 744209ff23fSmrg * XXX: Doing here essentially the same things this ioctl does in 745209ff23fSmrg * the DRM results in corruption with 'small' transfers, apparently 746209ff23fSmrg * because the data doesn't actually land in system RAM before the 747209ff23fSmrg * memcpy. I suspect the ioctl helps mostly due to its latency; what 748209ff23fSmrg * we'd really need is a way to reliably wait for the host interface 749209ff23fSmrg * to be done with pushing the data to the host. 750209ff23fSmrg */ 751b7e1c893Smrg while ((drmCommandNone(info->dri->drmFD, DRM_RADEON_CP_IDLE) == -EBUSY) 752209ff23fSmrg && (i++ < RADEON_TIMEOUT)) 753209ff23fSmrg ; 754209ff23fSmrg 755209ff23fSmrg /* Kick next blit */ 756209ff23fSmrg if (hpass) 757209ff23fSmrg FLUSH_RING(); 758209ff23fSmrg 759209ff23fSmrg /* Copy out data from previous blit */ 760209ff23fSmrg if (wpass == scratch_pitch && wpass == dst_pitch) { 761209ff23fSmrg RADEONCopySwap((uint8_t*)dst, src, wpass * oldhpass, swap); 762209ff23fSmrg dst += dst_pitch * oldhpass; 763209ff23fSmrg } else while (oldhpass--) { 764209ff23fSmrg RADEONCopySwap((uint8_t*)dst, src, wpass, swap); 765209ff23fSmrg src += scratch_pitch; 766209ff23fSmrg dst += dst_pitch; 767209ff23fSmrg } 768209ff23fSmrg } 769209ff23fSmrg 770209ff23fSmrg indirect.idx = scratch->idx; 771209ff23fSmrg indirect.start = indirect.end = 0; 772209ff23fSmrg indirect.discard = 1; 773209ff23fSmrg 774b7e1c893Smrg drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INDIRECT, 775b7e1c893Smrg &indirect, sizeof(drm_radeon_indirect_t)); 776209ff23fSmrg 777b7e1c893Smrg info->accel_state->exaMarkerSynced = info->accel_state->exaSyncMarker; 778209ff23fSmrg 779209ff23fSmrg return TRUE; 780209ff23fSmrg } 781209ff23fSmrg 782b7e1c893Smrg return FALSE; 783b7e1c893Smrg} 784209ff23fSmrg 785b7e1c893Smrg#endif /* def ACCEL_CP */ 786209ff23fSmrg 787209ff23fSmrg 788209ff23fSmrgBool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) 789209ff23fSmrg{ 790209ff23fSmrg RINFO_FROM_SCREEN(pScreen); 791209ff23fSmrg 792b7e1c893Smrg if (info->accel_state->exa == NULL) { 793209ff23fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); 794209ff23fSmrg return FALSE; 795209ff23fSmrg } 796209ff23fSmrg 797b7e1c893Smrg info->accel_state->exa->exa_major = EXA_VERSION_MAJOR; 798b7e1c893Smrg info->accel_state->exa->exa_minor = EXA_VERSION_MINOR; 799209ff23fSmrg 800b7e1c893Smrg info->accel_state->exa->PrepareSolid = FUNC_NAME(RADEONPrepareSolid); 801b7e1c893Smrg info->accel_state->exa->Solid = FUNC_NAME(RADEONSolid); 802f1bc02b7Smrg info->accel_state->exa->DoneSolid = FUNC_NAME(RADEONDone2D); 803209ff23fSmrg 804b7e1c893Smrg info->accel_state->exa->PrepareCopy = FUNC_NAME(RADEONPrepareCopy); 805b7e1c893Smrg info->accel_state->exa->Copy = FUNC_NAME(RADEONCopy); 806f1bc02b7Smrg info->accel_state->exa->DoneCopy = FUNC_NAME(RADEONDone2D); 807209ff23fSmrg 808b7e1c893Smrg info->accel_state->exa->MarkSync = FUNC_NAME(RADEONMarkSync); 809b7e1c893Smrg info->accel_state->exa->WaitMarker = FUNC_NAME(RADEONSync); 810b7e1c893Smrg#ifdef ACCEL_CP 811f1bc02b7Smrg if (!info->kms_enabled) { 812f1bc02b7Smrg info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP; 813f1bc02b7Smrg if (info->accelDFS) 814f1bc02b7Smrg info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP; 815f1bc02b7Smrg } 816f1bc02b7Smrg# if defined(XF86DRM_MODE) 817c73da4dbSmrg else if (info->cs) { 818f1bc02b7Smrg info->accel_state->exa->UploadToScreen = &RADEONUploadToScreenCS; 819f1bc02b7Smrg info->accel_state->exa->DownloadFromScreen = &RADEONDownloadFromScreenCS; 820f1bc02b7Smrg } 821f1bc02b7Smrg# endif 822b7e1c893Smrg#endif 823209ff23fSmrg 824209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 825f1bc02b7Smrg info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_BE; 826f1bc02b7Smrg info->accel_state->exa->FinishAccess = RADEONFinishAccess_BE; 827f1bc02b7Smrg#endif 828209ff23fSmrg 829b7e1c893Smrg info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS; 830b7e1c893Smrg#ifdef EXA_SUPPORTS_PREPARE_AUX 831b7e1c893Smrg info->accel_state->exa->flags |= EXA_SUPPORTS_PREPARE_AUX; 832b7e1c893Smrg#endif 833f1bc02b7Smrg#ifdef EXA_SUPPORTS_OFFSCREEN_OVERLAPS 834f1bc02b7Smrg /* The 2D engine supports overlapping memory areas */ 835f1bc02b7Smrg info->accel_state->exa->flags |= EXA_SUPPORTS_OFFSCREEN_OVERLAPS; 836f1bc02b7Smrg#endif 837f1bc02b7Smrg info->accel_state->exa->pixmapOffsetAlign = RADEON_GPU_PAGE_SIZE; 838b7e1c893Smrg info->accel_state->exa->pixmapPitchAlign = 64; 839209ff23fSmrg 840f1bc02b7Smrg#ifdef EXA_HANDLES_PIXMAPS 841f1bc02b7Smrg if (info->cs) { 842f1bc02b7Smrg info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS; 843f1bc02b7Smrg#ifdef EXA_MIXED_PIXMAPS 844f1bc02b7Smrg info->accel_state->exa->flags |= EXA_MIXED_PIXMAPS; 845f1bc02b7Smrg#endif 846f1bc02b7Smrg } 847f1bc02b7Smrg#endif 848f1bc02b7Smrg 849209ff23fSmrg#ifdef RENDER 850209ff23fSmrg if (info->RenderAccel) { 851f1bc02b7Smrg if (IS_R300_3D || IS_R500_3D) { 852209ff23fSmrg if ((info->ChipFamily < CHIP_FAMILY_RS400) 853209ff23fSmrg#ifdef XF86DRI 854209ff23fSmrg || (info->directRenderingEnabled) 855209ff23fSmrg#endif 856209ff23fSmrg ) { 857209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 858209ff23fSmrg "enabled for R300/R400/R500 type cards.\n"); 859b7e1c893Smrg info->accel_state->exa->CheckComposite = R300CheckComposite; 860b7e1c893Smrg info->accel_state->exa->PrepareComposite = 861209ff23fSmrg FUNC_NAME(R300PrepareComposite); 862b7e1c893Smrg info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite); 863b7e1c893Smrg info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite); 864209ff23fSmrg } else 865209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Composite requires CP on R5xx/IGP\n"); 866f1bc02b7Smrg } else if (IS_R200_3D) { 867209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 868209ff23fSmrg "enabled for R200 type cards.\n"); 869b7e1c893Smrg info->accel_state->exa->CheckComposite = R200CheckComposite; 870b7e1c893Smrg info->accel_state->exa->PrepareComposite = 871209ff23fSmrg FUNC_NAME(R200PrepareComposite); 872b7e1c893Smrg info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite); 873b7e1c893Smrg info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite); 874209ff23fSmrg } else { 875209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " 876209ff23fSmrg "enabled for R100 type cards.\n"); 877b7e1c893Smrg info->accel_state->exa->CheckComposite = R100CheckComposite; 878b7e1c893Smrg info->accel_state->exa->PrepareComposite = 879209ff23fSmrg FUNC_NAME(R100PrepareComposite); 880b7e1c893Smrg info->accel_state->exa->Composite = FUNC_NAME(RadeonComposite); 881b7e1c893Smrg info->accel_state->exa->DoneComposite = FUNC_NAME(RadeonDoneComposite); 882209ff23fSmrg } 883209ff23fSmrg } 884209ff23fSmrg#endif 885209ff23fSmrg 886f1bc02b7Smrg#ifdef XF86DRM_MODE 887f1bc02b7Smrg#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4) 888f1bc02b7Smrg if (info->cs) { 889f1bc02b7Smrg info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap; 890f1bc02b7Smrg info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; 891f1bc02b7Smrg info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; 892f1bc02b7Smrg info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; 893f1bc02b7Smrg info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS; 894f1bc02b7Smrg#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5) 895f1bc02b7Smrg info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2; 896f1bc02b7Smrg#endif 897f1bc02b7Smrg } 898f1bc02b7Smrg#endif 899f1bc02b7Smrg#endif 900f1bc02b7Smrg 901f1bc02b7Smrg 902209ff23fSmrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) 903209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n"); 904209ff23fSmrg 905b7e1c893Smrg info->accel_state->exa->maxPitchBytes = 16320; 906a4f79855Smrg info->accel_state->exa->maxX = 8191; 907209ff23fSmrg#else 908b7e1c893Smrg info->accel_state->exa->maxX = 16320 / 4; 909209ff23fSmrg#endif 910a4f79855Smrg info->accel_state->exa->maxY = 8191; 911b7e1c893Smrg 912b7e1c893Smrg if (xf86ReturnOptValBool(info->Options, OPTION_EXA_VSYNC, FALSE)) { 913b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA VSync enabled\n"); 914b7e1c893Smrg info->accel_state->vsync = TRUE; 915b7e1c893Smrg } else 916b7e1c893Smrg info->accel_state->vsync = FALSE; 917209ff23fSmrg 918209ff23fSmrg RADEONEngineInit(pScrn); 919209ff23fSmrg 920b7e1c893Smrg if (!exaDriverInit(pScreen, info->accel_state->exa)) { 92151b40f85Smrg free(info->accel_state->exa); 922209ff23fSmrg return FALSE; 923209ff23fSmrg } 924209ff23fSmrg exaMarkSync(pScreen); 925209ff23fSmrg 926209ff23fSmrg return TRUE; 927209ff23fSmrg} 928209ff23fSmrg 929209ff23fSmrg#undef FUNC_NAME 930