summaryrefslogtreecommitdiff
path: root/src/radeon_exa_funcs.c
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-10-03 16:33:33 +0200
committerMichel Dänzer <daenzer@vmware.com>2009-10-03 16:33:33 +0200
commit9460ea864b12ec1fbd11c5d9a20bb5a4279d9d3d (patch)
treef5064ca63804da4240b0363441cfc1d73ca703ad /src/radeon_exa_funcs.c
parentaee6b6f2c120baf477b4845ddc1a94637c31db2f (diff)
Fix KMS on big endian machines.
Requires at least xserver 1.7 to work properly. Also make sure the front buffer is and stays tiled if colour tiling is enabled.
Diffstat (limited to 'src/radeon_exa_funcs.c')
-rw-r--r--src/radeon_exa_funcs.c91
1 files changed, 76 insertions, 15 deletions
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 98aca932..d5a3103b 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -450,15 +450,18 @@ static Bool
RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
char *src, int src_pitch)
{
- RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+ ScreenPtr pScreen = pDst->drawable.pScreen;
+ RINFO_FROM_SCREEN(pScreen);
struct radeon_exa_pixmap_priv *driver_priv;
struct radeon_bo *scratch;
+ 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 = (w * bpp / 8 + 63) & ~63;
+ uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
Bool r;
int i;
@@ -466,11 +469,34 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
return FALSE;
driver_priv = exaGetPixmapDriverPrivate(pDst);
+ if (!driver_priv || !driver_priv->bo)
+ return FALSE;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ switch (bpp) {
+ case 32:
+ 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 (driver_priv->bo->cref == 1 &&
- !radeon_bo_is_busy(driver_priv->bo, &dst_domain))
+ !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;
+ }
+#endif
return FALSE;
+ }
size = scratch_pitch * h;
scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
@@ -486,6 +512,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
goto out;
}
+copy:
r = radeon_bo_map(scratch, 0);
if (r) {
r = FALSE;
@@ -493,22 +520,28 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
}
r = TRUE;
size = w * bpp / 8;
+ dst = scratch->ptr;
+ if (scratch == driver_priv->bo)
+ dst += y * scratch_pitch + x * bpp / 8;
for (i = 0; i < h; i++) {
- memcpy(scratch->ptr + i * scratch_pitch, src, size);
+ RADEONCopySwap(dst + i * scratch_pitch, (uint8_t*)src, size, swap);
src += src_pitch;
}
radeon_bo_unmap(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);
+ if (scratch != driver_priv->bo) {
+ 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:
- radeon_bo_unref(scratch);
+ if (scratch != driver_priv->bo)
+ radeon_bo_unref(scratch);
return r;
}
@@ -525,12 +558,26 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
uint32_t src_pitch_offset;
unsigned bpp = pSrc->drawable.bitsPerPixel;
uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+ uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
Bool r;
if (bpp < 8)
return FALSE;
driver_priv = exaGetPixmapDriverPrivate(pSrc);
+ if (!driver_priv || !driver_priv->bo)
+ return FALSE;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ switch (bpp) {
+ case 32:
+ 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 (driver_priv->bo->cref > 1) {
@@ -546,8 +593,17 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
if (!src_domain)
radeon_bo_is_busy(driver_priv->bo, &src_domain);
- if (src_domain != RADEON_GEM_DOMAIN_VRAM)
+ 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;
+ }
size = scratch_pitch * h;
scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
@@ -572,6 +628,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
RADEON_GEM_DOMAIN_GTT);
FLUSH_RING();
+copy:
r = radeon_bo_map(scratch, 0);
if (r) {
r = FALSE;
@@ -579,15 +636,19 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
}
r = TRUE;
w *= bpp / 8;
- size = 0;
+ if (scratch == driver_priv->bo)
+ size = y * scratch_pitch + x * bpp / 8;
+ else
+ size = 0;
while (h--) {
- memcpy(dst, scratch->ptr + size, w);
+ RADEONCopySwap((uint8_t*)dst, scratch->ptr + size, w, swap);
size += scratch_pitch;
dst += dst_pitch;
}
radeon_bo_unmap(scratch);
out:
- radeon_bo_unref(scratch);
+ if (scratch != driver_priv->bo)
+ radeon_bo_unref(scratch);
return r;
}
#endif