diff options
author | Luc Verhaegen <libv@skynet.be> | 2008-09-23 22:39:43 +0200 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2008-10-13 19:54:09 +0200 |
commit | 7aa72401975395aa24a4d2d05d6a29063c99de6a (patch) | |
tree | 8cf8ed10ec4cf77f6199c73930fe36b45681e10b | |
parent | 13a6774a9394adcc69e6ec298c1254c0e077aab1 (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.c | 14 | ||||
-rw-r--r-- | src/rhd.h | 8 | ||||
-rw-r--r-- | src/rhd_video.c | 268 | ||||
-rw-r--r-- | src/rhd_video.h | 45 |
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; @@ -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 */ |