--- xf86-video-ati-6.13.1/src/radeon_exa.c.6.13.1 2010-08-14 22:59:28.000000000 +1200 +++ xf86-video-ati-6.13.1/src/radeon_exa.c 2010-08-16 17:07:10.000000000 +1200 @@ -310,31 +310,56 @@ static void RADEONFinishAccess_BE(Pixmap #ifdef XF86DRM_MODE Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_exa_pixmap_priv *driver_priv; + uint32_t possible_domains = ~0; + uint32_t current_domain = 0; + Bool can_fail = pPix->drawable.bitsPerPixel >= 8 && + pPix != pScreen->GetScreenPixmap(pScreen); + Bool flush = FALSE; int ret; #if X_BYTE_ORDER == X_BIG_ENDIAN /* May need to handle byte swapping in DownloadFrom/UploadToScreen */ - if (pPix->drawable.bitsPerPixel > 8 && - pPix != pScreen->GetScreenPixmap(pScreen)) + if (can_fail && pPix->drawable.bitsPerPixel > 8) return FALSE; #endif driver_priv = exaGetPixmapDriverPrivate(pPix); if (!driver_priv) return FALSE; /* if we have more refs than just the BO then flush */ - if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) + if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { + flush = TRUE; + + /* if the BO might end up in VRAM, prefer DownloadFromScreen */ + if (can_fail) { + possible_domains = radeon_bo_get_src_domain(driver_priv->bo); + if (possible_domains == RADEON_GEM_DOMAIN_VRAM) + return FALSE; + } + } + + if (can_fail) { + radeon_bo_is_busy(driver_priv->bo, ¤t_domain); + + if (current_domain & possible_domains) { + if (current_domain == RADEON_GEM_DOMAIN_VRAM) + return FALSE; + } else if (possible_domains & RADEON_GEM_DOMAIN_VRAM) + return FALSE; + } + + if (flush) radeon_cs_flush_indirect(pScrn); /* flush IB */ ret = radeon_bo_map(driver_priv->bo, 1); if (ret) { FatalError("failed to map pixmap %d\n", ret); return FALSE; } --- xf86-video-ati-6.13.1/src/radeon_exa_funcs.c.6.13.1 2010-08-14 22:59:40.000000000 +1200 +++ xf86-video-ati-6.13.1/src/radeon_exa_funcs.c 2010-08-16 15:25:39.000000000 +1200 @@ -454,25 +454,28 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, struc #if defined(XF86DRM_MODE) static Bool RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) { ScreenPtr pScreen = pDst->drawable.pScreen; RINFO_FROM_SCREEN(pScreen); struct radeon_exa_pixmap_priv *driver_priv; - struct radeon_bo *scratch; + struct radeon_bo *scratch = NULL; + struct radeon_bo *copy_dst; unsigned char *dst; unsigned size; uint32_t datatype = 0; uint32_t dst_domain; uint32_t dst_pitch_offset; unsigned bpp = pDst->drawable.bitsPerPixel; uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); + uint32_t copy_pitch = pDst->devKind; uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; + Bool flush = TRUE; Bool r; int i; if (bpp < 8) return FALSE; driver_priv = exaGetPixmapDriverPrivate(pDst); if (!driver_priv || !driver_priv->bo) @@ -484,94 +487,94 @@ RADEONUploadToScreenCS(PixmapPtr pDst, i swap = RADEON_HOST_DATA_SWAP_32BIT; break; case 16: swap = RADEON_HOST_DATA_SWAP_16BIT; break; } #endif - /* If we know the BO won't be busy, don't bother */ - if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs) && - !radeon_bo_is_busy(driver_priv->bo, &dst_domain)) { -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* Can't return FALSE here if we need to swap bytes */ - if (swap != RADEON_HOST_DATA_SWAP_NONE && - driver_priv->bo != info->front_bo) { - scratch = driver_priv->bo; - scratch_pitch = pDst->devKind; + /* If we know the BO won't be busy, don't bother with a scratch*/ + copy_dst = driver_priv->bo; + if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { + flush = FALSE; + if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain)) goto copy; - } -#endif - return FALSE; } size = scratch_pitch * h; scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); if (scratch == NULL) { - return FALSE; + goto copy; } radeon_cs_space_reset_bos(info->cs); radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM); radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0); r = radeon_cs_space_check(info->cs); if (r) { - r = FALSE; - goto out; + goto copy; } + flush = FALSE; + copy_dst = scratch; + copy_pitch = scratch_pitch; -#if X_BYTE_ORDER == X_BIG_ENDIAN copy: -#endif - r = radeon_bo_map(scratch, 0); + if (flush) + radeon_cs_flush_indirect(pScrn); + + r = radeon_bo_map(copy_dst, 0); if (r) { r = FALSE; goto out; } r = TRUE; size = w * bpp / 8; - dst = scratch->ptr; - if (scratch == driver_priv->bo) - dst += y * scratch_pitch + x * bpp / 8; + dst = copy_dst->ptr; + if (copy_dst == driver_priv->bo) + dst += y * copy_pitch + x * bpp / 8; for (i = 0; i < h; i++) { - RADEONCopySwap(dst + i * scratch_pitch, (uint8_t*)src, size, swap); + RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap); src += src_pitch; } - radeon_bo_unmap(scratch); + radeon_bo_unmap(copy_dst); - if (scratch != driver_priv->bo) { + if (copy_dst == scratch) { RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype); RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset); ACCEL_PREAMBLE(); RADEON_SWITCH_TO_2D(); RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16, dst_pitch_offset, 0, 0, x, y, w, h, RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM); } out: - if (scratch != driver_priv->bo) + if (scratch) radeon_bo_unref(scratch); return r; } static Bool RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch) { RINFO_FROM_SCREEN(pSrc->drawable.pScreen); struct radeon_exa_pixmap_priv *driver_priv; - struct radeon_bo *scratch; + struct radeon_bo *scratch = NULL; + struct radeon_bo *copy_src; unsigned size; uint32_t datatype = 0; uint32_t src_domain = 0; uint32_t src_pitch_offset; unsigned bpp = pSrc->drawable.bitsPerPixel; uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); + uint32_t copy_pitch = pSrc->devKind; uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; + int ret; + Bool flush = FALSE; Bool r; if (bpp < 8) return FALSE; driver_priv = exaGetPixmapDriverPrivate(pSrc); if (!driver_priv || !driver_priv->bo) return FALSE; @@ -582,84 +585,81 @@ RADEONDownloadFromScreenCS(PixmapPtr pSr swap = RADEON_HOST_DATA_SWAP_32BIT; break; case 16: swap = RADEON_HOST_DATA_SWAP_16BIT; break; } #endif - /* If we know the BO won't end up in VRAM anyway, don't bother */ + /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ + copy_src = driver_priv->bo; if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { src_domain = radeon_bo_get_src_domain(driver_priv->bo); if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) src_domain = 0; + else /* A write may be scheduled */ + flush = TRUE; } if (!src_domain) radeon_bo_is_busy(driver_priv->bo, &src_domain); - if (src_domain != RADEON_GEM_DOMAIN_VRAM) { -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* Can't return FALSE here if we need to swap bytes */ - if (swap != RADEON_HOST_DATA_SWAP_NONE) { - scratch = driver_priv->bo; - scratch_pitch = pSrc->devKind; - goto copy; - } -#endif - return FALSE; + if (src_domain & ~RADEON_GEM_DOMAIN_VRAM) { + goto copy; } size = scratch_pitch * h; scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); if (scratch == NULL) { - return FALSE; + goto copy; } radeon_cs_space_reset_bos(info->cs); radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT); - r = radeon_cs_space_check(info->cs); - if (r) { - r = FALSE; - goto out; + ret = radeon_cs_space_check(info->cs); + if (ret) { + goto copy; } RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype); RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); ACCEL_PREAMBLE(); RADEON_SWITCH_TO_2D(); RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset, scratch_pitch << 16, x, y, 0, 0, w, h, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_GTT); - FLUSH_RING(); - -#if X_BYTE_ORDER == X_BIG_ENDIAN + flush = TRUE; + copy_src = scratch; + copy_pitch = scratch_pitch; copy: -#endif - r = radeon_bo_map(scratch, 0); - if (r) { + if (flush) + FLUSH_RING(); + + ret = radeon_bo_map(copy_src, 0); + if (ret) { + FatalError("failed to map pixmap %d\n", ret); r = FALSE; goto out; } r = TRUE; w *= bpp / 8; - if (scratch == driver_priv->bo) - size = y * scratch_pitch + x * bpp / 8; + if (copy_src == driver_priv->bo) + size = y * copy_pitch + x * bpp / 8; else size = 0; while (h--) { - RADEONCopySwap((uint8_t*)dst, scratch->ptr + size, w, swap); - size += scratch_pitch; + RADEONCopySwap((uint8_t*)dst, copy_src->ptr + size, w, swap); + size += copy_pitch; dst += dst_pitch; } - radeon_bo_unmap(scratch); + radeon_bo_unmap(copy_src); out: - if (scratch != driver_priv->bo) + if (scratch) radeon_bo_unref(scratch); return r; } #endif static Bool RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch)