summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/radeon_exa_funcs.c120
1 files changed, 84 insertions, 36 deletions
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index d02c787d..f629c8ed 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -459,7 +459,8 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
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;
@@ -467,7 +468,12 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
uint32_t dst_pitch_offset;
unsigned bpp = pDst->drawable.bitsPerPixel;
uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64);
+ uint32_t copy_pitch;
uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
+ int ret;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ Bool flush = TRUE;
+#endif
Bool r;
int i;
@@ -490,54 +496,78 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
#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;
- goto copy;
- }
+ copy_dst = driver_priv->bo;
+ copy_pitch = pDst->devKind;
#endif
- return FALSE;
+ if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ flush = FALSE;
+#endif
+ if (!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) {
+ 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) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ if (swap != RADEON_HOST_DATA_SWAP_NONE &&
+ driver_priv->bo != info->front_bo) {
+ goto copy;
+ }
+#endif
return FALSE;
}
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) {
+ ret = radeon_cs_space_check(info->cs);
+ if (ret) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ if (swap != RADEON_HOST_DATA_SWAP_NONE &&
+ driver_priv->bo != info->front_bo) {
+ goto copy;
+ }
+#endif
r = FALSE;
goto out;
}
-
+ copy_dst = scratch;
+ copy_pitch = scratch_pitch;
#if X_BYTE_ORDER == X_BIG_ENDIAN
+ flush = FALSE;
+
copy:
+ if (flush)
+ radeon_cs_flush_indirect(pScrn);
#endif
- r = radeon_bo_map(scratch, 0);
- if (r) {
+
+ ret = radeon_bo_map(copy_dst, 0);
+ if (ret) {
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();
@@ -548,7 +578,7 @@ copy:
}
out:
- if (scratch != driver_priv->bo)
+ if (scratch)
radeon_bo_unref(scratch);
return r;
}
@@ -559,14 +589,17 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
{
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;
uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
+ int ret;
#if X_BYTE_ORDER == X_BIG_ENDIAN
Bool flush = FALSE;
#endif
@@ -591,6 +624,10 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
#endif
/* If we know the BO won't end up in VRAM anyway, don't bother */
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ copy_src = driver_priv->bo;
+ copy_pitch = pSrc->devKind;
+#endif
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)) ==
@@ -609,8 +646,6 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
#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
@@ -620,13 +655,23 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
size = scratch_pitch * h;
scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
if (scratch == NULL) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ if (swap != RADEON_HOST_DATA_SWAP_NONE) {
+ goto copy;
+ }
+#endif
return FALSE;
}
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) {
+ ret = radeon_cs_space_check(info->cs);
+ if (ret) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ if (swap != RADEON_HOST_DATA_SWAP_NONE) {
+ goto copy;
+ }
+#endif
r = FALSE;
goto out;
}
@@ -638,6 +683,8 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
scratch_pitch << 16, x, y, 0, 0, w, h,
RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT,
RADEON_GEM_DOMAIN_GTT);
+ copy_src = scratch;
+ copy_pitch = scratch_pitch;
#if X_BYTE_ORDER == X_BIG_ENDIAN
flush = TRUE;
@@ -646,25 +693,26 @@ copy:
#endif
FLUSH_RING();
- r = radeon_bo_map(scratch, 0);
- if (r) {
+ ret = radeon_bo_map(copy_src, 0);
+ if (ret) {
+ ErrorF("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;
}