summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Verhaegen <libv@skynet.be>2008-09-23 22:39:43 +0200
committerLuc Verhaegen <libv@skynet.be>2008-10-13 19:54:09 +0200
commit7aa72401975395aa24a4d2d05d6a29063c99de6a (patch)
tree8cf8ed10ec4cf77f6199c73930fe36b45681e10b
parent13a6774a9394adcc69e6ec298c1254c0e077aab1 (diff)
CS: Xv: clean up memory handling.
This fixes a bug with FB Offset alignment, and, while at it, makes the whole thing saner.
-rw-r--r--src/radeon_textured_videofuncs.c14
-rw-r--r--src/rhd.h8
-rw-r--r--src/rhd_video.c268
-rw-r--r--src/rhd_video.h45
4 files changed, 184 insertions, 151 deletions
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index c33f858..247f7c2 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -70,7 +70,9 @@ do { \
# define VAR_PSCRN_PREAMBLE(pScrn) RHDPtr info = RHDPTR(pScrn)
# define THREEDSTATE_PREAMBLE() struct rhdAccel *accel_state = info->accel_state
-# define FB_OFFSET(x) (((char *)(x) - (char *)info->FbBase) + info->FbIntAddress)
+# define BUFFER_PITCH pPriv->src_pitch
+# define FB_BUFFER_OFFSET pPriv->src_offset
+# define FB_PIXMAP_OFFSET(x) (((char *)(x) - (char *)rhdPtr->FbBase) + rhdPtr->FbIntAddress)
# ifdef USE_EXA
# define EXA_ENABLED (info->AccelMethod == RHD_ACCEL_EXA)
@@ -182,7 +184,9 @@ RADEONTilingEnabled(ScrnInfoPtr pScrn, PixmapPtr pPix)
# define VAR_PSCRN_PREAMBLE(pScrn) RHDPtr rhdPtr = RHDPTR(pScrn)
# define THREEDSTATE_PREAMBLE() struct R5xx3D *accel_state = (struct R5xx3D *)rhdPtr->ThreeDPrivate
-# define FB_OFFSET(x) (((char *)(x) - (char *)rhdPtr->FbBase) + rhdPtr->FbIntAddress)
+# define BUFFER_PITCH pPriv->BufferPitch
+# define FB_BUFFER_OFFSET (pPriv->BufferOffset + rhdPtr->FbIntAddress)
+# define FB_PIXMAP_OFFSET(x) (((char *)(x) - (char *)rhdPtr->FbBase) + rhdPtr->FbIntAddress)
# ifdef USE_EXA
# define EXA_ENABLED (rhdPtr->AccelMethod == RHD_ACCEL_EXA)
@@ -225,7 +229,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
} else
#endif
{
- dst_offset = FB_OFFSET(pPixmap->devPrivate.ptr);
+ dst_offset = FB_PIXMAP_OFFSET(pPixmap->devPrivate.ptr);
dst_pitch = pPixmap->devKind;
}
@@ -307,7 +311,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR);
/* pitch is in pixels */
- txpitch = pPriv->src_pitch / 2;
+ txpitch = BUFFER_PITCH / 2;
txpitch -= 1;
if (IS_R500_3D && ((pPriv->w - 1) & 0x800))
@@ -322,7 +326,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
OUT_VIDEO_REG(R300_TX_FORMAT0_0, txformat0);
OUT_VIDEO_REG(R300_TX_FORMAT1_0, txformat1);
OUT_VIDEO_REG(R300_TX_FORMAT2_0, txpitch);
- OUT_VIDEO_REG(R300_TX_OFFSET_0, pPriv->src_offset);
+ OUT_VIDEO_REG(R300_TX_OFFSET_0, FB_BUFFER_OFFSET);
FINISH_VIDEO();
txenable = R300_TEX_0_ENABLE;
diff --git a/src/rhd.h b/src/rhd.h
index 9bc79d2..c8d7818 100644
--- a/src/rhd.h
+++ b/src/rhd.h
@@ -231,8 +231,9 @@ typedef struct RHDRec {
/* Some simplistic memory handling */
#define ALIGN(x,align) (((x)+(align)-1)&~((align)-1))
+#define RHD_FB_ALIGNMENT 0x1000
/* Use this macro to always chew up 4096byte aligned pieces. */
-#define RHD_FB_CHUNK(x) ALIGN((x),0x1000)
+#define RHD_FB_CHUNK(x) ALIGN((x), RHD_FB_ALIGNMENT)
unsigned int FbFreeStart;
unsigned int FbFreeSize;
@@ -305,11 +306,6 @@ typedef struct RHDRec {
/* DRI */
struct rhdDri *dri;
- /* XV */
-#ifdef USE_EXA
- void *adaptor; /* XF86VideoAdaptorPtr */
-#endif
-
/* BIOS Scratch registers */
struct rhdBiosScratchRegisters *BIOSScratch;
diff --git a/src/rhd_video.c b/src/rhd_video.c
index 26416f4..2f953ad 100644
--- a/src/rhd_video.c
+++ b/src/rhd_video.c
@@ -1,5 +1,8 @@
/*
- * Copyright 2008 Alex Deucher
+ * Copyright 2008 Luc Verhaegen <lverhaegen@novell.com>
+ * Copyright 2008 Matthias Hopf <mhopf@novell.com>
+ * Copyright 2008 Egbert Eich <eich@novell.com>
+ * Copyright 2008 Alex Deucher
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -60,117 +63,94 @@
#include "fourcc.h"
#ifdef USE_EXA
-static void
-ATIVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- RHDPtr rhdPtr = RHDPTR(pScrn);
- struct RHDPortPriv *pPriv =
- ((XF86VideoAdaptorPtr)(rhdPtr->adaptor))->pPortPrivates[0].ptr;
-
- if (pPriv->video_memory == area)
- pPriv->video_memory = NULL;
-}
-#endif /* USE_EXA */
-
-/* Allocates memory, either by resizing the allocation pointed to by mem_struct,
- * or by freeing mem_struct (if non-NULL) and allocating a new space. The size
- * is measured in bytes, and the offset from the beginning of card space is
- * returned.
+/*
+ *
*/
+static Bool
+rhdXvAllocateEXA(ScrnInfoPtr pScrn, struct RHDPortPriv *pPriv, int size)
+{
+ ExaOffscreenArea *area = pPriv->BufferHandle;
-static CARD32
-rhdAllocateMemory(
- ScrnInfoPtr pScrn,
- void **mem_struct,
- int size
- ){
- ScreenPtr pScreen;
- RHDPtr rhdPtr = RHDPTR(pScrn);
- int offset = 0;
-
- pScreen = screenInfo.screens[pScrn->scrnIndex];
-
-#ifdef USE_EXA
- if (rhdPtr->AccelMethod == RHD_ACCEL_EXA) {
- ExaOffscreenArea *area = *mem_struct;
-
- if (area != NULL) {
- if (area->size >= size)
- return area->offset;
+ if (area && (area->size == size))
+ return TRUE;
- exaOffscreenFree(pScrn->pScreen, area);
- }
+ if (area)
+ exaOffscreenFree(pScrn->pScreen, area);
- area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, ATIVideoSave,
- NULL);
- *mem_struct = area;
- if (area == NULL)
- return 0;
- offset = area->offset;
+ area = exaOffscreenAlloc(pScrn->pScreen, size, RHD_FB_ALIGNMENT,
+ TRUE, NULL, NULL);
+ if (!area) {
+ pPriv->BufferHandle = NULL;
+ pPriv->BufferOffset = 0;
+ return FALSE;
+ } else {
+ pPriv->BufferHandle = area;
+ pPriv->BufferOffset = area->offset + RHDPTR(pScrn)->FbScanoutStart;
+ return TRUE;
}
+}
#endif /* USE_EXA */
- if (rhdPtr->AccelMethod == RHD_ACCEL_XAA) {
- FBLinearPtr linear = *mem_struct;
- int cpp = pScrn->bitsPerPixel >> 3;
-
- /* XAA allocates in units of pixels at the screen bpp, so adjust size
- * appropriately.
- */
- size = (size + cpp - 1) / cpp;
- if (linear) {
- if (linear->size >= size)
- return linear->offset * cpp;
-
- if (xf86ResizeOffscreenLinear(linear, size))
- return linear->offset * cpp;
+/*
+ *
+ */
+static FBLinearPtr
+rhdXvAllocateXAAHelper(ScreenPtr pScreen, FBLinearPtr linear, int size)
+{
+ if (linear) {
+ if (linear->size == size)
+ return linear;
- xf86FreeOffscreenLinear(linear);
- }
+ if (xf86ResizeOffscreenLinear(linear, size))
+ return linear;
- linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
- NULL, NULL, NULL);
- *mem_struct = linear;
+ xf86FreeOffscreenLinear(linear);
+ }
- if (!linear) {
- int max_size;
+ linear = xf86AllocateOffscreenLinear(pScreen, size, 1,
+ NULL, NULL, NULL);
- xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
- PRIORITY_EXTREME);
+ if (!linear) {
+ int max_size;
- if (max_size < size)
- return 0;
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 1,
+ PRIORITY_EXTREME);
+ if (max_size < size)
+ return NULL;
- xf86PurgeUnlockedOffscreenAreas(pScreen);
- linear =
- xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL);
- *mem_struct = linear;
- if (!linear)
- return 0;
- }
- offset = linear->offset * cpp;
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ linear = xf86AllocateOffscreenLinear(pScreen, size, 1,
+ NULL, NULL, NULL);
}
- return offset;
+ return linear;
}
/*
*
*/
-void
-rhdFreeMemory(ScrnInfoPtr pScrn, void *mem_struct)
+static Bool
+rhdXvAllocateXAA(ScrnInfoPtr pScrn, struct RHDPortPriv *pPriv, int size)
{
- if (mem_struct) {
- RHDPtr rhdPtr = RHDPTR(pScrn);
+ int cpp = pScrn->bitsPerPixel >> 3;
+ FBLinearPtr linear;
-#ifdef USE_EXA
- if (rhdPtr->AccelMethod == RHD_ACCEL_EXA)
- exaOffscreenFree(pScrn->pScreen, (ExaOffscreenArea *) mem_struct);
-#endif /* USE_EXA */
+ /* We need to do FB alignment manually */
+ size += RHD_FB_ALIGNMENT - 1;
+
+ /* XAA allocates in units of pixels */
+ size = (size + cpp - 1) / cpp;
- if (rhdPtr->AccelMethod == RHD_ACCEL_XAA)
- xf86FreeOffscreenLinear((FBLinearPtr) mem_struct);
+ linear = rhdXvAllocateXAAHelper(pScrn->pScreen, pPriv->BufferHandle, size);
+ if (!linear) {
+ pPriv->BufferHandle = NULL;
+ pPriv->BufferOffset = 0;
+ return FALSE;
+ } else {
+ pPriv->BufferHandle = linear;
+ pPriv->BufferOffset = RHDPTR(pScrn)->FbScanoutStart +
+ RHD_FB_CHUNK(linear->offset * cpp + RHD_FB_ALIGNMENT - 1);
+ return TRUE;
}
}
@@ -180,6 +160,28 @@ rhdFreeMemory(ScrnInfoPtr pScrn, void *mem_struct)
static void
rhdStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
{
+ if (cleanup) {
+ struct RHDPortPriv *pPriv = data;
+
+ switch (RHDPTR(pScrn)->AccelMethod) {
+#ifdef USE_EXA
+ case RHD_ACCEL_EXA:
+ exaOffscreenFree(pScrn->pScreen,
+ (ExaOffscreenArea *) pPriv->BufferHandle);
+ break;
+#endif /* USE_EXA */
+ case RHD_ACCEL_XAA:
+ xf86FreeOffscreenLinear((FBLinearPtr) pPriv->BufferHandle);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "%s: cannot de-allocate memory!\n", __func__);
+ break;
+ }
+
+ pPriv->BufferHandle = NULL;
+ pPriv->BufferOffset = 0;
+ }
}
/*
@@ -388,6 +390,9 @@ R5xxXvCopyPacked(RHDPtr rhdPtr, CARD8 *src, CARD8 *dst,
#endif
}
+/*
+ *
+ */
static void
R5xxXvCopyPlanarToPacked(CARD8 *dst, CARD16 dstPitch,
CARD8 *src1, CARD16 src1Pitch,
@@ -483,6 +488,9 @@ R5xxXvCopyPlanarDMA(RHDPtr rhdPtr, CARD8 *src1, CARD8 *src2, CARD8 *src3,
RHDCSFlush(CS);
}
+/*
+ *
+ */
static void
R5xxXvCopyPlanar(RHDPtr rhdPtr, CARD8 *src1, CARD8 *src2, CARD8 *src3,
CARD8 *dst1, CARD16 srcPitch, CARD16 srcPitch2,
@@ -524,7 +532,6 @@ rhdPutImageTextured(ScrnInfoPtr pScrn,
RHDPtr rhdPtr = RHDPTR(pScrn);
struct RHDPortPriv *pPriv = data;
CARD8 *FBBuf;
- int dstPitch, size;
/*
* First, make sure we can render to the drawable.
@@ -557,44 +564,40 @@ rhdPutImageTextured(ScrnInfoPtr pScrn,
pPriv->pDraw = pDraw;
- /*
- * Now, find out whether we have enough memory available.
- */
- dstPitch = width << 1;
-
+ /* The upload blit only supports multiples of 64 bytes */
if (rhdPtr->CS->Type == RHD_CS_CPDMA)
- /* The upload blit only supports multiples of 64 bytes */
- dstPitch = (dstPitch + 63) & ~63;
+ pPriv->BufferPitch = ALIGN(2 * width, 64);
else
- dstPitch = (dstPitch + 15) & ~15;
+ pPriv->BufferPitch = ALIGN(2 * width, 16);
- size = dstPitch * height;
-
- if (pPriv->video_memory && (size != pPriv->size)) {
- rhdFreeMemory(pScrn, pPriv->video_memory);
- pPriv->video_memory = NULL;
- pPriv->size = 0;
+ /*
+ * Now, find out whether we have enough memory available.
+ */
+ switch (rhdPtr->AccelMethod) {
+#ifdef USE_EXA
+ case RHD_ACCEL_EXA:
+ rhdXvAllocateEXA(pScrn, pPriv, 2 * pPriv->BufferPitch * height);
+ break;
+#endif /* USE_EXA */
+ case RHD_ACCEL_XAA:
+ rhdXvAllocateXAA(pScrn, pPriv, 2 * pPriv->BufferPitch * height);
+ break;
+ default:
+ pPriv->BufferHandle = NULL;
+ pPriv->BufferOffset = 0;
+ break;
}
- if (!pPriv->video_memory)
- pPriv->video_offset =
- rhdAllocateMemory(pScrn, &pPriv->video_memory, size * 2);
-
- if (!pPriv->video_offset || !pPriv->video_memory) {
- pPriv->size = 0;
+ if (!pPriv->BufferHandle) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"%s: Failed to allocate framebuffer memory.\n", __func__);
return BadAlloc;
}
- pPriv->size = size;
-
/*
* Now copy the buffer to the framebuffer, and convert to planar when necessary.
*/
- pPriv->src_offset = pPriv->video_offset + rhdPtr->FbIntAddress + rhdPtr->FbScanoutStart;
- FBBuf = ((CARD8 *)rhdPtr->FbBase + rhdPtr->FbScanoutStart + pPriv->video_offset);
- pPriv->src_pitch = dstPitch;
+ FBBuf = (CARD8 *)rhdPtr->FbBase + pPriv->BufferOffset;
switch(id) {
case FOURCC_YV12:
@@ -607,18 +610,26 @@ rhdPutImageTextured(ScrnInfoPtr pScrn,
if (id == FOURCC_YV12) {
if (rhdPtr->CS->Type == RHD_CS_CPDMA)
- R5xxXvCopyPlanarDMA(rhdPtr, buf, buf + s2offset, buf + s3offset,
- FBBuf, srcPitch, srcPitch2, dstPitch, height, width);
+ R5xxXvCopyPlanarDMA(rhdPtr, buf, buf + s2offset,
+ buf + s3offset, FBBuf, srcPitch,
+ srcPitch2, pPriv->BufferPitch,
+ height, width);
else
- R5xxXvCopyPlanar(rhdPtr, buf, buf + s2offset, buf + s3offset,
- FBBuf, srcPitch, srcPitch2, dstPitch, height, width);
+ R5xxXvCopyPlanar(rhdPtr, buf, buf + s2offset,
+ buf + s3offset, FBBuf, srcPitch,
+ srcPitch2, pPriv->BufferPitch,
+ height, width);
} else {
if (rhdPtr->CS->Type == RHD_CS_CPDMA)
- R5xxXvCopyPlanarDMA(rhdPtr, buf, buf + s3offset, buf + s2offset,
- FBBuf, srcPitch, srcPitch2, dstPitch, height, width);
+ R5xxXvCopyPlanarDMA(rhdPtr, buf, buf + s3offset,
+ buf + s2offset, FBBuf, srcPitch,
+ srcPitch2, pPriv->BufferPitch,
+ height, width);
else
- R5xxXvCopyPlanar(rhdPtr, buf, buf + s3offset, buf + s2offset,
- FBBuf, srcPitch, srcPitch2, dstPitch, height, width);
+ R5xxXvCopyPlanar(rhdPtr, buf, buf + s3offset,
+ buf + s2offset, FBBuf, srcPitch,
+ srcPitch2, pPriv->BufferPitch,
+ height, width);
}
}
break;
@@ -626,9 +637,11 @@ rhdPutImageTextured(ScrnInfoPtr pScrn,
case FOURCC_YUY2:
default:
if (rhdPtr->CS->Type == RHD_CS_CPDMA)
- R5xxXvCopyPackedDMA(rhdPtr, buf, FBBuf, 2 * width, dstPitch, height);
+ R5xxXvCopyPackedDMA(rhdPtr, buf, FBBuf, 2 * width,
+ pPriv->BufferPitch, height);
else
- R5xxXvCopyPacked(rhdPtr, buf, FBBuf, 2 * width, dstPitch, height);
+ R5xxXvCopyPacked(rhdPtr, buf, FBBuf, 2 * width,
+ pPriv->BufferPitch, height);
break;
}
@@ -745,11 +758,10 @@ rhdSetupImageTexturedVideo(ScreenPtr pScreen)
/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
REGION_NULL(pScreen, &pPriv->clip);
+
adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
}
-#ifdef USE_EXA
- rhdPtr->adaptor = adapt; /* this is only needed for exaOffscreenAlloc */
-#endif
+
return adapt;
}
diff --git a/src/rhd_video.h b/src/rhd_video.h
index f14cd50..0c87ae9 100644
--- a/src/rhd_video.h
+++ b/src/rhd_video.h
@@ -1,20 +1,41 @@
-#ifndef __RADEON_VIDEO_H__
-#define __RADEON_VIDEO_H__
+/*
+ * Copyright 2008 Luc Verhaegen <lverhaegen@novell.com>
+ * Copyright 2008 Matthias Hopf <mhopf@novell.com>
+ * Copyright 2008 Egbert Eich <eich@novell.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RHD_VIDEO_H
+#define _RHD_VIDEO_H
/* Xvideo port struct */
struct RHDPortPriv {
- RegionRec clip;
-
- int size;
- void *video_memory;
- int video_offset;
-
- /* textured video */
DrawablePtr pDraw;
PixmapPtr pPixmap;
- CARD32 src_offset;
- CARD32 src_pitch;
+ RegionRec clip;
+
+ void *BufferHandle;
+ CARD32 BufferOffset;
+ CARD32 BufferPitch;
int id;
int src_w;
@@ -30,4 +51,4 @@ struct RHDPortPriv {
extern void RHDRADEONDisplayTexturedVideo(ScrnInfoPtr pScrn, struct RHDPortPriv *pPriv);
extern void RHDInitVideo(ScreenPtr pScreen);
-#endif
+#endif /* _RHD_VIDEO_H */