summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c')
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c1587
1 files changed, 974 insertions, 613 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c
index 8480de20a..d63592085 100644
--- a/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c
+++ b/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c
@@ -1,85 +1,134 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c,v 1.5 2000/12/08 21:53:37 mvojkovi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c,v 1.2 2000/12/02 15:30:57 tsi Exp $ */
-/* Adapted from ../mga/mga_video.c */
+#ifndef XvExtension
+void TDFXInitVideo(ScreenPtr pScreen) {}
+void TDFXCloseVideo(ScreenPtr pScreen) {}
+#else
#include "xf86.h"
-#include "xf86_OSproc.h"
-#include "xf86Resources.h"
-#include "xf86_ansic.h"
-#include "compiler.h"
-#include "xf86PciInfo.h"
-#include "xf86Pci.h"
-#include "xf86fbman.h"
-#include "regionstr.h"
-
#include "tdfx.h"
+#include "dixstruct.h"
-#include "xf86xv.h"
#include "Xv.h"
-#include "xaa.h"
-#include "xaalocal.h"
-#include "dixstruct.h"
#include "fourcc.h"
+static Atom xvColorKey, xvFilterQuality;
+
/* These should move into tdfxdefs.h with better names */
-#define YUV_Y_BASE 0xC00000
-#define YUV_U_BASE 0xD00000
-#define YUV_V_BASE 0xE00000
+#define YUV_Y_BASE 0xC00000
+#define YUV_U_BASE 0xD00000
+#define YUV_V_BASE 0xE00000
-#define SST_2D_FORMAT_YUYV 0x8
-#define SST_2D_FORMAT_UYVY 0x9
+#define SST_2D_FORMAT_YUYV 0x8
+#define SST_2D_FORMAT_UYVY 0x9
#define YUVBASEADDR 0x80100
-/* This should move to tdfx.h
- * Only one port for now due to need for better memory allocation. */
-#define TDFX_MAX_PORTS 1
-
#define YUVSTRIDE 0x80104
+#define VIDPROCCFGMASK 0xa2e3eb6c
-#ifndef XvExtension
-void TDFXInitVideo(ScreenPtr pScreen) {}
-#else
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+#define TDFX_MAX_OVERLAY_PORTS 1
+#define TDFX_MAX_TEXTURE_PORTS 32
+
+/* Doesn't matter what screen we use */
+#define DummyScreen screenInfo.screens[0]
+/* Needed for attribute atoms */
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+/*
+ * PROTOTYPES
+ */
void TDFXInitVideo(ScreenPtr pScreen);
-void TDFXCloseVideo (ScreenPtr pScreen);
-
-static XF86VideoAdaptorPtr TDFXSetupImageVideo(ScreenPtr);
-static int TDFXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
-static int TDFXGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
-
-static void TDFXStopVideo(ScrnInfoPtr, pointer, Bool);
-static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
- unsigned int *, unsigned int *, pointer);
-static int TDFXPutImage(ScrnInfoPtr, short, short, short, short, short,
- short, short, short, int, unsigned char*, short,
- short, Bool, RegionPtr, pointer);
-#if 0
-/* This isn't done yet, but eventually it will put images to the
- * video overlay. */
-static int TDFXPutImageOverlay(ScrnInfoPtr pScrn, short, short,
- short, short, short, short,
- short, short, int, unsigned char*,
- short, short, Bool, RegionPtr , pointer);
-#endif
-
-static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
- unsigned short *, int *, int *);
-
-/* These function is from tdfx_accel.c */
-extern void TDFXFirstSync(ScrnInfoPtr pScrn);
+void TDFXCloseVideo(ScreenPtr pScreen);
-static FBAreaPtr
-TDFXAllocateOffscreenBuffer (ScrnInfoPtr pScrn, int id, int width, int height);
+static FBAreaPtr TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height);
+static FBLinearPtr TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
+static void TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
-static void
-TDFXDeallocateOffscreenBuffer (ScrnInfoPtr pScrn, int id);
+static XF86VideoAdaptorPtr TDFXSetupImageVideoTexture(ScreenPtr);
+static int TDFXSetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer);
+static int TDFXGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static int TDFXPutImageTexture(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+static void TDFXStopVideoTexture(ScrnInfoPtr, pointer, Bool);
+
+static XF86VideoAdaptorPtr TDFXSetupImageVideoOverlay(ScreenPtr);
+static int TDFXSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
+static int TDFXGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static int TDFXPutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+static void TDFXStopVideoOverlay(ScrnInfoPtr, pointer, Bool);
+static void TDFXResetVideoOverlay(ScrnInfoPtr);
+
+static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
+static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);
+
+/*
+ * ADAPTOR INFORMATION
+ */
+
+static XF86VideoEncodingRec OverlayEncoding[] =
+{
+ { 0, "XV_IMAGE", 2048, 2048, {1, 1} }
+};
+
+static XF86VideoEncodingRec TextureEncoding[] =
+{
+ { 0, "XV_IMAGE", 1024, 1024, {1, 1} }
+};
+
+static XF86VideoFormatRec OverlayFormats[] =
+{
+ {8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
+ {8, GrayScale}, {8, StaticGray}, {8, StaticColor},
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
+ {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
+};
+
+static XF86VideoFormatRec TextureFormats[] =
+{
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86AttributeRec OverlayAttributes[] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
+};
+
+static XF86AttributeRec TextureAttributes[] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
+};
+
+static XF86ImageRec OverlayImages[] =
+{
+ XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420
+};
+
+static XF86ImageRec TextureImages[] =
+{
+ XVIMAGE_YV12, XVIMAGE_I420
+};
+
+/*
+ * COMMON SETUP FUNCTIONS
+ */
void TDFXInitVideo(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
- XF86VideoAdaptorPtr newAdaptor = NULL;
+ XF86VideoAdaptorPtr newOverlayAdaptor = NULL;
+ XF86VideoAdaptorPtr newTextureAdaptor = NULL;
TDFXPtr pTDFX = TDFXPTR(pScrn);
int num_adaptors;
@@ -87,685 +136,997 @@ void TDFXInitVideo(ScreenPtr pScreen)
if(pTDFX->cpp == 1)
return;
- newAdaptor = TDFXSetupImageVideo(pScreen);
-
- /* Initialize the offscreen buffer */
- pTDFX->offscreenYUVBuf = 0;
-
+ /* Start with the generic adaptors */
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
- if(newAdaptor) {
- if(!num_adaptors) {
- num_adaptors = 1;
- adaptors = &newAdaptor;
- } else {
- newAdaptors = /* need to free this someplace */
- xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
- if(newAdaptors) {
- memcpy(newAdaptors, adaptors, num_adaptors *
- sizeof(XF86VideoAdaptorPtr));
- newAdaptors[num_adaptors] = newAdaptor;
- adaptors = newAdaptors;
- num_adaptors++;
- }
- }
+ /* Overlay adaptor */
+ if(pTDFX->AccelInfoRec && pTDFX->AccelInfoRec->FillSolidRects)
+ newOverlayAdaptor = TDFXSetupImageVideoOverlay(pScreen);
+
+ /* Texture adaptor */
+ if(pTDFX->AccelInfoRec && pTDFX->AccelInfoRec->FillSolidRects)
+ newTextureAdaptor = TDFXSetupImageVideoTexture(pScreen);
+
+ /* Add the overlay adaptor to the list */
+ if(newOverlayAdaptor) {
+ newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ if (num_adaptors) memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newOverlayAdaptor;
+ adaptors = newAdaptors; /* FIXME: leak? */
+ num_adaptors++;
+ }
}
- if(num_adaptors)
- {
- xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+ /* Add the texture adaptor to the list */
+ if(newTextureAdaptor) {
+ newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ if (num_adaptors) memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newTextureAdaptor;
+ adaptors = newAdaptors; /* FIXME: leak? */
+ num_adaptors++;
+ }
}
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
if(newAdaptors)
- xfree(newAdaptors);
+ xfree(newAdaptors);
}
+
void TDFXCloseVideo (ScreenPtr pScreen)
{
-
}
-/* client libraries expect an encoding */
-static XF86VideoEncodingRec DummyEncoding[1] =
+
+static XF86VideoAdaptorPtr
+TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts)
{
- { /* blit limit */
- 0,
- "XV_IMAGE",
- 1024, 0, /* Height is a limitation of pixmap space, and filled in later. */
- {1, 1}
- }
-};
+ XF86VideoAdaptorPtr adapt;
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv;
+ int i;
-#define NUM_FORMATS_OVERLAY 3
+ if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
+ return NULL;
-static XF86VideoFormatRec Formats[NUM_FORMATS_OVERLAY] =
-{
- {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
-};
+ if(!(pPriv = xcalloc(1, sizeof(TDFXPortPrivRec) + numberPorts * sizeof(DevUnion))))
+ {
+ xfree(adapt);
+ return NULL;
+ }
-/* #define NUM_IMAGES 4*/
-#define NUM_IMAGES 2
+ adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
+ for(i = 0; i < numberPorts; i++)
+ adapt->pPortPrivates[i].val = i;
-static XF86ImageRec Images[NUM_IMAGES] =
-{
- XVIMAGE_YV12, /* YVU planar */
- XVIMAGE_I420 /* YUV planar */
-#if 0
- /* These could be supported (without a temp bufer) using the
- * host-to-screen-stretch */
- XVIMAGE_YUY2, /* YUYV packed */
- XVIMAGE_UYVY /* UYVY packed */
-#endif
-};
+ xvColorKey = MAKE_ATOM("XV_COLORKEY"); /* FIXME: twice, leak */
+ xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY"); /* FIXME: twice, leak */
+
+ pPriv->colorKey = pTDFX->videoKey;
+ pPriv->videoStatus = 0;
+ pPriv->filterQuality = 1;
+
+ return adapt;
+}
static XF86VideoAdaptorPtr
-TDFXAllocAdaptor(ScrnInfoPtr pScrn)
+TDFXSetupImageVideoOverlay(ScreenPtr pScreen)
{
- DevUnion *devUnions;
- int i;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv;
XF86VideoAdaptorPtr adapt;
- if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
- return NULL;
- /* Allocate a TDFX private structure */
- /* There is no need for a TDFX private structure at this time. But a
- * DevUnion has to be provided to the core Xv code. */
- if (!(devUnions = xcalloc (1, sizeof (DevUnion) * TDFX_MAX_PORTS)))
- {
- xfree (adapt);
- return NULL;
- }
- adapt->pPortPrivates = &devUnions[0];
-
- /* Fill in some of the DevUnion */
- for (i = 0; i < TDFX_MAX_PORTS; i++)
- {
- adapt->pPortPrivates[i].val = i;
- adapt->pPortPrivates[i].ptr = NULL; /* No private data */
- }
-
- return adapt;
-}
+ if (!pTDFX->OverlayXvideo)
+ return NULL;
+ if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS)))
+ return NULL;
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "3dfx Video Overlay";
+ adapt->nPorts = TDFX_MAX_OVERLAY_PORTS;
+ adapt->nEncodings = sizeof(OverlayEncoding) / sizeof(XF86VideoEncodingRec);
+ adapt->pEncodings = OverlayEncoding;
+ adapt->nFormats = sizeof(OverlayFormats) / sizeof(XF86VideoFormatRec);
+ adapt->pFormats = OverlayFormats;
+ adapt->nAttributes = sizeof(OverlayAttributes) / sizeof(XF86AttributeRec);
+ adapt->pAttributes = OverlayAttributes;
+ adapt->nImages = sizeof(OverlayImages) / sizeof(XF86ImageRec);
+ adapt->pImages = OverlayImages;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = TDFXStopVideoOverlay;
+ adapt->SetPortAttribute = TDFXSetPortAttributeOverlay;
+ adapt->GetPortAttribute = TDFXGetPortAttributeOverlay;
+ adapt->QueryBestSize = TDFXQueryBestSize;
+ adapt->PutImage = TDFXPutImageOverlay;
+ adapt->QueryImageAttributes = TDFXQueryImageAttributes;
-static XF86VideoAdaptorPtr
-TDFXSetupImageVideo(ScreenPtr pScreen)
+ pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr);
+ REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0);
+
+ pTDFX->overlayAdaptor = adapt;
+
+ TDFXResetVideoOverlay(pScrn);
+
+ return adapt;
+}
+
+static XF86VideoAdaptorPtr
+TDFXSetupImageVideoTexture(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- XF86VideoAdaptorPtr adapt;
TDFXPtr pTDFX = TDFXPTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
- DummyEncoding[0].height = pTDFX->pixmapCacheLines;
+ if (!pTDFX->TextureXvideo)
+ return NULL;
- adapt = TDFXAllocAdaptor(pScrn);
+ if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS)))
+ return NULL;
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
- /* Add VIDEO_OVERLAID_IMAGES if using the overlay */
adapt->flags = 0;
- adapt->name = "3dfx Accelerated Video Engine";
- adapt->nEncodings = 1;
- adapt->pEncodings = &DummyEncoding[0];
- adapt->nFormats = NUM_FORMATS_OVERLAY;
- adapt->pFormats = Formats;
- adapt->nPorts = TDFX_MAX_PORTS;
- adapt->nAttributes = 0;
- adapt->pAttributes = NULL;
- adapt->nImages = NUM_IMAGES;
- adapt->pImages = Images;
-
- /* XXX For now all I'm implementing is PutImage so that programs like OMS
- * will work. More will follow as I have time and need. */
+ adapt->name = "3dfx Video Texture";
+ adapt->nPorts = TDFX_MAX_TEXTURE_PORTS;
+ adapt->nEncodings = sizeof(TextureEncoding) / sizeof(XF86VideoEncodingRec);
+ adapt->pEncodings = TextureEncoding;
+ adapt->nFormats = sizeof(TextureFormats) / sizeof(XF86VideoFormatRec);
+ adapt->pFormats = TextureFormats;
+ adapt->nAttributes = sizeof(TextureAttributes) / sizeof(XF86AttributeRec);
+ adapt->pAttributes = TextureAttributes;
+ adapt->nImages = sizeof(TextureImages) / sizeof(XF86ImageRec);
+ adapt->pImages = TextureImages;
adapt->PutVideo = NULL;
adapt->PutStill = NULL;
adapt->GetVideo = NULL;
adapt->GetStill = NULL;
- adapt->StopVideo = TDFXStopVideo;
- adapt->SetPortAttribute = TDFXSetPortAttribute;
- adapt->GetPortAttribute = TDFXGetPortAttribute;
+ adapt->StopVideo = TDFXStopVideoTexture;
+ adapt->SetPortAttribute = TDFXSetPortAttributeTexture;
+ adapt->GetPortAttribute = TDFXGetPortAttributeTexture;
adapt->QueryBestSize = TDFXQueryBestSize;
- adapt->PutImage = TDFXPutImage;
- /*adapt->PutImage = TDFXPutImageOverlay; */
+ adapt->PutImage = TDFXPutImageTexture;
adapt->QueryImageAttributes = TDFXQueryImageAttributes;
+ pTDFX->textureAdaptor = adapt;
+
return adapt;
}
-static void
-TDFXStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
-{
- if (cleanup)
- {
- /* Deallocate the offscreen temporary buffer. */
- TDFXDeallocateOffscreenBuffer (pScrn, 0);
- }
+/*
+ * MISCELLANEOUS ROUTINES
+ */
+
+
+static int
+TDFXQueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > 1024) *w = 1024;
+ if(*h > 1024) *h = 1024;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
}
-static int
-TDFXSetPortAttribute (ScrnInfoPtr pScrn,
- Atom attribute,
- INT32 value,
- pointer data)
-{
- return BadMatch;
+static int
+TDFXSetPortAttributeOverlay(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+){
+
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
+ pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else if(attribute == xvFilterQuality) {
+ if((value < 0) || (value > 1))
+ return BadValue;
+ pPriv->filterQuality = value;
+ } else return BadMatch;
+
+ return Success;
+}
+
+static int
+TDFXGetPortAttributeOverlay(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else if(attribute == xvFilterQuality) {
+ *value = pPriv->filterQuality;
+ } else return BadMatch;
+
+ return Success;
}
static int
-TDFXGetPortAttribute(ScrnInfoPtr pScrn,
- Atom attribute,
- INT32 *value,
- pointer data)
-{
- return BadMatch;
+TDFXSetPortAttributeTexture(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+) {
+ return Success;
}
+static int
+TDFXGetPortAttributeTexture(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ return Success;
+}
-static void
-TDFXQueryBestSize(ScrnInfoPtr pScrn,
- Bool motion,
- short vid_w, short vid_h,
- short drw_w, short drw_h,
- unsigned int *p_w, unsigned int *p_h,
- pointer data)
-{
- /* No alignment restrictions */
+
+static void
+TDFXQueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ if(vid_w > drw_w) drw_w = vid_w;
+ if(vid_h > drw_h) drw_h = vid_h;
+
*p_w = drw_w;
- *p_h = drw_h;
+ *p_h = drw_h;
}
-
-/* This performs a screen to screen stretch blit. All coordinates are
- * in screen memory. This function assumes that the src and dst format
- * registers have been setup already. This function does not save
- * the registers it trashes. */
static void
-TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn,
- short src_x1, short src_y1,
- short src_x2, short src_y2,
- short dst_x1, short dst_y1,
- short dst_x2, short dst_y2)
-{
- TDFXPtr pTDFX = TDFXPTR(pScrn);
+TDFXCopyData(
+ unsigned char *src,
+ unsigned char *dst,
+ int srcPitch,
+ int dstPitch,
+ int h,
+ int w
+){
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
- /* reformulate the paramaters the way the hardware wants them */
- INT32
- src_x = src_x1 & 0x1FFF,
- src_y = src_y1 & 0x1FFF,
- dst_x = dst_x1 & 0x1FFF,
- dst_y = dst_y1 & 0x1FFF,
- src_w = (src_x2 - src_x) & 0x1FFF,
- src_h = (src_y2 - src_y) & 0x1FFF,
- dst_w = (dst_x2 - dst_x) & 0x1FFF,
- dst_h = (dst_y2 - dst_y) & 0x1FFF;
-
- /* Setup for blit src and dest */
- TDFXMakeRoom(pTDFX, 5);
- DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|
- SSTCP_COMMAND|SSTCP_COMMANDEXTRA);
- /* We want the blit to wait for vsync. */
- TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, 4);
- TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16));
- TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16));
- TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16));
- /* XXX find the ROP table and figure out why CC is the right choice. */
- TDFXWriteLong(pTDFX, SST_2D_COMMAND,
- (0xCC<<24)|SST_2D_SCRNTOSCRNSTRETCH);
- /* Write to the launch area to start the blit */
- TDFXMakeRoom(pTDFX, 1);
- DECLARE_LAUNCH (1, 0);
- TDFXWriteLong(pTDFX, SST_2D_LAUNCH, src_x | (src_y<<16));
+static void
+TDFXCopyMungedData(
+ unsigned char *src1,
+ unsigned char *src2,
+ unsigned char *src3,
+ unsigned char *dst1,
+ int srcPitch,
+ int srcPitch2,
+ int dstPitch,
+ int h,
+ int w
+){
+ CARD32 *dst;
+ CARD8 *s1, *s2, *s3;
+ int i, j;
+
+ w >>= 1;
+
+ for(j = 0; j < h; j++) {
+ dst = (CARD32*)dst1;
+ s1 = src1; s2 = src2; s3 = src3;
+ i = w;
+ while(i > 4) {
+ dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
+ dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
+ dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
+ dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
+ dst += 4; s2 += 4; s3 += 4; s1 += 8;
+ i -= 4;
+ }
+ while(i--) {
+ dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
+ dst++; s2++; s3++;
+ s1 += 2;
+ }
+
+ dst1 += dstPitch;
+ src1 += srcPitch;
+ if(j & 1) {
+ src2 += srcPitch2;
+ src3 += srcPitch2;
+ }
+ }
}
+
+/*
+ * TEXTURE DRAWING FUNCTIONS
+ */
+
+
static void
-YUVPlanarToPacked (ScrnInfoPtr pScrn,
- short src_x, short src_y,
- short src_h, short src_w,
- int id, char *buf,
- short width, short height,
- FBAreaPtr fbarea)
+TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
{
TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
- INT32 y;
- void *dst;
- char *psrc = buf,
- *pdst = 0;
- int count = 0;
-
- /* Register saves */
- INT32
- yuvBaseAddr,
- yuvStride;
-
- /* Save these registers so I can restore them when we are done. */
- yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR);
- yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE);
-
-
- dst = 0;
-
- /* Set yuvBaseAddress register to point to the buffer. */
- TDFXWriteLongMMIO (pTDFX, YUVBASEADDR, pTDFX->fbOffset +
- pTDFX->stride * (fbarea->box.y1 + pScrn->virtualY)
- + fbarea->box.x1);
- /* Set yuvStride register to reflect stride of U and V planes */
- /* There is a subtle issue involved with copying the Y plane. Y is
- * sampled at twice the rate of the U and V data, in both
- * directions. But when packing their needs to be two Y values for
- * each U,V pair. So if src_x is odd we will end up missing on
- * of the Y values. To correct for this we will always adjust the src
- * x value. This adjust is done both in computing the address of the
- * pixels to copy and when determining the amount of pixels to copy.
- * Note that care needs to be taken to insure that the offscreen
- * temporary buffer is allocated with enough space to hold the possible
- * extra column of data.
- */
- TDFXWriteLongMMIO (pTDFX, YUVSTRIDE, pTDFX->stride);
- psrc = (char*)buf;
-
- /* psrc points to the base of the Y plane, move out to src_x, src_y */
- psrc += (src_x & ~0x1) + src_y * width;
- pdst = (char *)pTDFX->MMIOBase[0] + YUV_Y_BASE;
- for (y = 0; y < src_h; y++)
- {
- memcpy (pdst, psrc, src_w + (src_x & 0x1));
- psrc += width;
- /* YUV planar region is always 1024 bytes wide */
- pdst += 1024;
- }
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
- /* The difference between FOURCC_YV12 and FOURCC_I420 is the order
- * that the U and V planes appear in the buffer. But at this point
- * I just send the second buffer as V and the third buffer as U.
- * Depending on the format, the packing will be different and we
- * handle it in the the way we pick the source format for the blit
- * later on. */
-
- pdst = (char *)pTDFX->MMIOBase[0] + YUV_V_BASE;
- psrc = (char*)buf + width * height;
- /* psrc now points to the base of the V plane, move out to src_x/2,
- * src_y/2 */
- psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
- for (y = 0; y < src_h >> 1; y++)
- {
- /* YUV planar region is always 1024 bytes wide */
- memcpy (pdst, psrc, src_w >> 1);
- psrc += width >> 1;
- pdst += 1024;
- }
- pdst = (char *)pTDFX->MMIOBase[0] + YUV_U_BASE;
- psrc = (char*)buf + width * height + (width >> 1) * (height >> 1);
- /* psrc now points to the base of the U plane, move out to src_x/2,
- * src_y/2 */
- psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
- for (y = 0; y < src_h >> 1; y++)
- {
- /* YUV planar region is always 1024 bytes wide */
- memcpy (pdst, psrc, src_w >> 1);
- psrc += width >> 1;
- pdst += 1024;
+ if (cleanup) {
+ if(pTDFX->textureBuffer) {
+ xf86FreeOffscreenArea(pTDFX->textureBuffer);
+ pTDFX->textureBuffer = NULL;
+ }
}
+}
- /* Before restoring trashed registers we have to wait for the conversion
- * to finish. We aren't using the FIFO for this but the hardware can
- * take a little extra time even after we finish all the writes. If we
- * restore the registers before it finishes it can store some of the YUV
- * data to the wrong place. One particular wrong place is often on top
- * of the hardware cursor data. So we wait for the status register
- * to go idle. */
- /* XXX Right now wait for the whole chip to go idle. This is more than
- * is required. Find out which subsystem is handles the YUV packing and
- * wait only on that status bit. */
- count = 0;
- do
- {
- count++;
- } while ((TDFXReadLongMMIO(pTDFX, 0) & SST_BUSY) && count < 1000);
-
- /* Restore trashed registers */
- TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr);
- TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride);
+
+static void
+TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn,
+ short src_x1, short src_y1,
+ short src_x2, short src_y2,
+ short dst_x1, short dst_y1,
+ short dst_x2, short dst_y2)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ /* reformulate the paramaters the way the hardware wants them */
+ INT32 src_x = src_x1 & 0x1FFF;
+ INT32 src_y = src_y1 & 0x1FFF;
+ INT32 dst_x = dst_x1 & 0x1FFF;
+ INT32 dst_y = dst_y1 & 0x1FFF;
+ INT32 src_w = (src_x2 - src_x1) & 0x1FFF;
+ INT32 src_h = (src_y2 - src_y1) & 0x1FFF;
+ INT32 dst_w = (dst_x2 - dst_x1) & 0x1FFF;
+ INT32 dst_h = (dst_y2 - dst_y1) & 0x1FFF;
+ /* Setup for blit src and dest */
+ TDFXMakeRoom(pTDFX, 4);
+ DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|SSTCP_COMMAND/*|SSTCP_COMMANDEXTRA*/);
+ /* TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_COMMANDEXTRA_VSYNC);*/
+ TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, SST_2D_SCRNTOSCRNSTRETCH | 0xCC000000);
+ /* Write to the launch area to start the blit */
+ TDFXMakeRoom(pTDFX, 1);
+ DECLARE_LAUNCH(1, 0);
+ TDFXWriteLong(pTDFX, SST_2D_LAUNCH, (src_x<<1) | (src_y<<16));
+ /* Wait for it to happen */
+ TDFXSendNOPFifo2D(pScrn);
}
-static int
-TDFXPutImage(
- ScrnInfoPtr pScrn,
- short src_x, short src_y,
- short drw_x, short drw_y,
- short src_w, short src_h,
- short drw_w, short drw_h,
- int id, unsigned char* buf,
- short width, short height,
- Bool sync,
- RegionPtr clipBoxes, pointer data
- )
+
+static void
+YUVPlanarToPacked (ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short src_h, short src_w,
+ int id, char *buf,
+ short width, short height,
+ FBAreaPtr fbarea)
{
TDFXPtr pTDFX = TDFXPTR(pScrn);
+ char *psrc, *pdst;
+ int count;
+ int baseaddr;
+ INT32 yuvBaseAddr, yuvStride;
+
+ /* Save these registers so I can restore them when we are done. */
+ yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR);
+ yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE);
+
+ /* Set yuvBaseAddress and yuvStride. */
+ baseaddr = pTDFX->fbOffset + pTDFX->cpp * fbarea->box.x1 + pTDFX->stride * fbarea->box.y1;
+ TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, pTDFX->stride);
+ TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, baseaddr);
+
+ /* Copy Y plane (twice as much Y as U or V) */
+ psrc = (char *)buf;
+ psrc += (src_x & ~0x1) + src_y * width;
+ pdst = (char *)pTDFX->MMIOBase[0] + YUV_Y_BASE;
+ TDFXCopyData(psrc, pdst, width, 1024, src_h, src_w + (src_x & 0x1));
+
+ /* Copy V plane */
+ psrc = (char*)buf + width * height;
+ psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
+ pdst = (char *)pTDFX->MMIOBase[0] + YUV_V_BASE;
+ TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
+
+ /* Copy U plane */
+ psrc = (char*)buf + width * height + (width >> 1) * (height >> 1);
+ psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
+ pdst = (char *)pTDFX->MMIOBase[0] + YUV_U_BASE;
+ TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
+
+ /* IDLE until the copy finished, timeout for safety */
+ for (count = 0; count < 1000; count++)
+ if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY)))
+ break;
+
+ /* Restore trashed registers */
+ TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr);
+ TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride);
+
+ /* Wait for it to happen */
+ TDFXSendNOPFifo2D(pScrn);
+}
+
+static int
+TDFXPutImageTexture(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool sync,
+ RegionPtr clipBoxes, pointer data
+ )
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
BoxPtr pbox;
int nbox;
+ int format;
+
+ /* Check the source format */
+ if (id == FOURCC_YV12) format = SST_2D_FORMAT_YUYV;
+ else if (id == FOURCC_UYVY) format = SST_2D_FORMAT_UYVY;
+ else return BadAlloc;
+
+ /* Get a buffer to store the packed YUV data */
+ if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h)))
+ return BadAlloc;
+
+ /* Pack the YUV data in offscreen memory using YUV framebuffer (0x[CDE]0000) */
+ YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w,
+ id, (char *)buf, width, height,
+ pTDFX->textureBuffer);
+
+ /* Setup source and destination pixel formats (yuv -> rgb) */
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->stride|((pTDFX->cpp+1)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->stride|((format)<<16));
+
+ /* Blit packed YUV data from offscreen memory, respecting clips */
+#define SRC_X1 (pTDFX->textureBuffer->box.x1)
+#define SRC_Y1 (pTDFX->textureBuffer->box.y1)
+#define SCALEX(dx) ((int)(((dx) * src_w) / drw_w))
+#define SCALEY(dy) ((int)(((dy) * src_h) / drw_h))
+ for (nbox = REGION_NUM_RECTS(clipBoxes),
+ pbox = REGION_RECTS(clipBoxes); nbox > 0; nbox--, pbox++)
+ {
+ TDFXScreenToScreenYUVStretchBlit (pScrn,
+ SRC_X1 + SCALEX(pbox->x1 - drw_x),
+ SRC_Y1 + SCALEY(pbox->y1 - drw_y),
+ SRC_X1 + SCALEX(pbox->x2 - drw_x),
+ SRC_Y1 + SCALEY(pbox->y2 - drw_y),
+ pbox->x1, pbox->y1,
+ pbox->x2, pbox->y2);
+ }
- FBAreaPtr fbarea;
+ /* Restore the WAX registers we trashed */
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow);
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow);
- /* Make sure we are synced up (this really means, lock and find the
- * fifo pointer. */
- TDFXFirstSync (pScrn);
+ /* Wait for it to happen */
+ TDFXSendNOPFifo2D(pScrn);
- /* Do the right thing for the given format */
- switch (id)
- {
- case FOURCC_YV12:
- case FOURCC_I420:
- /* Get a buffer to use to store the packed YUV data */
- fbarea = TDFXAllocateOffscreenBuffer (pScrn, id, src_w, src_h);
-
- if (!fbarea)
- {
- return Success;
- }
+ return Success;
+}
- YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w,
- id, (char *)buf, width, height,
- fbarea);
- /* Don't know what executed last so we need to send a NOP */
- TDFXSendNOP(pScrn);
-
- /* Setup the dst and src format once, they don't change for all the
- * blits. */
- TDFXMakeRoom(pTDFX, 2);
- DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
- TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT,
- pTDFX->stride|((pTDFX->cpp+1)<<16));
- if (id == FOURCC_YV12)
- {
- /* Packed format is YUYV */
- TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT,
- pTDFX->stride|((SST_2D_FORMAT_YUYV)<<16));
- }
- else
- {
- /* Packed format is UYVY */
- TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT,
- pTDFX->stride|((SST_2D_FORMAT_UYVY)<<16));
- }
- /* Traverse the clip boxes */
- nbox = REGION_NUM_RECTS(clipBoxes);
- pbox = REGION_RECTS(clipBoxes);
-
- while (nbox--)
- {
- /* The destination clip regions come with the clip boxes, but
- * the src coordinates have to be computed because we are doing
- * a stretch blit. These macros perform that compuation, but
- * they could use some work. When testing with still images these
- * computations caused some jitter in the resulting output, but
- * with actual video playback I haven't noticed any problems. */
-#define SRC_X1 (fbarea->box.x1)
-#define SRC_Y1 (fbarea->box.y1 + pScrn->virtualY)
-#define SCALEX(dx) ((int)(((dx) * src_w + (drw_w>>1)) / drw_w))
-#define SCALEY(dy) ((int)(((dy) * src_h + (drw_h>>1)) / drw_h))
-
- /* Do the screen-to-screen blit clipped to the clip boxes. */
- TDFXScreenToScreenYUVStretchBlit
- (pScrn,
- SRC_X1 + SCALEX(pbox->x1 - drw_x),
- SRC_Y1 + SCALEY(pbox->y1 - drw_y),
- SRC_X1 + SCALEX(pbox->x2 - drw_x),
- SRC_Y1 + SCALEY(pbox->y2 - drw_y),
- /* these destination coordinates come
- * right from the clip box. */
- pbox->x1, pbox->y1,
- pbox->x2, pbox->y2);
- pbox++;
- }
+/*
+ * COMMON DRAWING FUNCTIONS
+ */
- /* Restore the WAX registers we trashed */
- TDFXMakeRoom(pTDFX, 2);
- DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
- TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow);
- TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow);
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int*)REGION_RECTS(A);
+ dataB = (int*)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
- /* The rest of the driver won't know what I have done so I do a stall to
- * make sure the next command sent will work. */
- TDFXSendNOP(pScrn);
- break;
- /* XXX What am I supposed to do about the sync flag? */
+ return TRUE;
+}
- }
- return Success;
+static Bool
+TDFXClipVideo(
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ BoxPtr extents = REGION_EXTENTS(DummyScreen, reg);
+ int diff;
+
+ hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1);
+
+ *xa <<= 16; *xb <<= 16;
+ *ya <<= 16; *yb <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *xa += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *xb -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *ya += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *yb -= diff * vscale;
+ }
+
+ if(*xa < 0) {
+ diff = (- *xa + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *xa += diff * hscale;
+ }
+ delta = *xb - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *xb -= diff * hscale;
+ }
+ if(*xa >= *xb) return FALSE;
+
+ if(*ya < 0) {
+ diff = (- *ya + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *ya += diff * vscale;
+ }
+ delta = *yb - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *yb -= diff * vscale;
+ }
+ if(*ya >= *yb) return FALSE;
+
+ if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) ||
+ (dst->y1 != extents->y1) || (dst->y2 != extents->y2))
+ {
+ RegionRec clipReg;
+ REGION_INIT(DummyScreen, &clipReg, dst, 1);
+ REGION_INTERSECT(DummyScreen, reg, reg, &clipReg);
+ REGION_UNINIT(DummyScreen, &clipReg);
+ }
+ return TRUE;
}
-/* This code doesn't work yet. Eventually this should use the video overlay
- * instead of the YUV-stretch-blit. The overlay is better because it uses
- * bilinear filtering when scaling. */
-#if 0
-static int
-TDFXPutImageOverlay(
- ScrnInfoPtr pScrn,
- short src_x, short src_y,
- short drw_x, short drw_y,
- short src_w, short src_h,
- short drw_w, short drw_h,
- int id, unsigned char* buf,
- short width, short height,
- Bool sync,
- RegionPtr clipBoxes, pointer data
- )
-{
- TDFXPtr pTDFX = TDFXPTR(pScrn);
- BoxPtr pbox;
- int nbox;
+/*
+ * OVERLAY DRAWING FUNCTIONS
+ */
- /* Computed Register values */
- INT32
- vidInFormat;
- static FBAreaPtr fbarea;
+static void
+TDFXResetVideoOverlay(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+
+ /* reset the video */
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+ pTDFX->writeLong(pTDFX, RGBMAXDELTA, 0x0080808);
+ pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
+ pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
+}
- /* Do the right thing for the given format */
- switch (id)
- {
- case FOURCC_YV12:
- case FOURCC_I420:
-
- /* Get a buffer to use to store the packed YUV data */
- fbarea = TDFXAllocateOffscreenBuffer (pScrn, id, src_w, src_h);
-
- if (!fbarea)
- return Success;
-
- YUVPlanarToPacked (pScrn,
- src_x, src_y, src_h, src_w,
- id, buf, width, height,
- fbarea);
-
- /* Setup the overlay */
- TDFXWriteLongMMIO(pTDFX, VIDOVERLAYSTARTCOORDS,
- (drw_x&0x7FF) | ((drw_y & 0x7FF) << 12)
- /* XXX Lower 2 bits of X and Y? */);
- TDFXWriteLongMMIO(pTDFX, VIDOVERLAYENDSCREENCOORDS,
- ((drw_x+drw_w)&0x7FF) | (((drw_y+drw_h)&0x7FF) << 12));
-
- /* Set the Video in format */
- vidInFormat = 0;
- /* These magic numbers come from the spec on page 151 */
- if (id == FOURCC_YV12)
- {
- /* Packed format is YUYV */
- vidInFormat = 0x9 << 1;
- }
- else
- {
- /* Packed format is UYVY */
- vidInFormat = 0xA << 1;
- }
+static void
+TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
- TDFXWriteLongMMIO (pTDFX, VIDINFORMAT, vidInFormat);
- TDFXWriteLongMMIO (pTDFX, VIDINSTRIDE, src_w);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
- /* Use magenta as the chroma color */
- if (pTDFX->cpp == 2)
- {
- TDFXWriteLongMMIO(pTDFX, VIDCHROMAMIN,
- 0x0000F71F);
- TDFXWriteLongMMIO(pTDFX, VIDCHROMAMAX,
- 0x0000F71F);
+ if(cleanup) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
}
- else /* (pTDFX->cpp == 3) */
- {
- TDFXWriteLongMMIO(pTDFX, VIDCHROMAMIN,
- 0x00FF00FF);
- TDFXWriteLongMMIO(pTDFX, VIDCHROMAMAX,
- 0x00FF00FF);
+ if(pTDFX->overlayBuffer) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
+ pTDFX->overlayBuffer = NULL;
}
-
- /* Set the src address */
- TDFXWriteLongMMIO (pTDFX, VIDINADDR0,
- pTDFX->fbOffset
- + pTDFX->stride * (fbarea->box.y1 + pScrn->virtualY)
- + fbarea->box.x1);
-
- /* Traverse the clip boxes */
- nbox = REGION_NUM_RECTS(clipBoxes);
- pbox = REGION_RECTS(clipBoxes);
-
- while (nbox--)
- {
- pbox++;
+ pPriv->videoStatus = 0;
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
}
- break;
+ }
+}
+
+
+static void
+TDFXDisplayVideoOverlay(
+ ScrnInfoPtr pScrn,
+ int id,
+ int offset,
+ short width, short height,
+ int pitch,
+ int left, int right, int top,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+ int dudx, dvdy;
+
+ dudx = (src_w << 20) / drw_w;
+ dvdy = (src_h << 20) / drw_h;
+
+ offset += ((left >> 16) & ~1) << 1;
+ left = (left & 0x0001ffff) << 3;
+
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->ModeReg.vidcfg |= 0x00000320;
+
+ if(drw_w != src_w) pTDFX->ModeReg.vidcfg |= (1 << 14);
+ if(drw_h != src_h) pTDFX->ModeReg.vidcfg |= (1 << 15);
+ if(id == FOURCC_UYVY) pTDFX->ModeReg.vidcfg |= (6 << 21);
+ else pTDFX->ModeReg.vidcfg |= (5 << 21);
+ if(pScrn->depth == 8) pTDFX->ModeReg.vidcfg |= (1 << 11);
+ if(pPriv->filterQuality) pTDFX->ModeReg.vidcfg |= (3 << 16);
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+
+ pTDFX->writeLong(pTDFX, VIDOVERLAYSTARTCOORDS, dstBox->x1 | (dstBox->y1 << 12));
+ pTDFX->writeLong(pTDFX, VIDOVERLAYENDSCREENCOORDS, (dstBox->x2 - 1) | ((dstBox->y2 - 1) << 12));
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDUDX, dudx);
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDUDXOFFSETSRCWIDTH, left | (src_w << 20));
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDVDY, dvdy);
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDVDYOFFSET, (top & 0x0000ffff) << 3);
+
+ pTDFX->ModeReg.stride &= 0x0000ffff;
+ pTDFX->ModeReg.stride |= pitch << 16;
+ pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, pTDFX->ModeReg.stride);
+ pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
+ pTDFX->writeLong(pTDFX, VIDINADDR0, offset & ~3);
+}
+
+
+static int
+TDFXPutImageOverlay(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool Sync,
+ RegionPtr clipBoxes, pointer data
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+ INT32 xa, xb, ya, yb;
+ unsigned char *dst_start;
+ int pitch, new_size, offset;
+ int s2offset = 0, s3offset = 0;
+ int srcPitch = 0, srcPitch2 = 0;
+ int dstPitch;
+ int top, left, npixels, nlines, bpp;
+ BoxRec dstBox;
+ CARD32 tmp;
+
+ /*
+ * s2offset, s3offset - byte offsets into U and V plane of the
+ * source where copying starts. Y plane is
+ * done by editing "buf".
+ *
+ * offset - byte offset to the first line of the destination.
+ *
+ * dst_start - byte address to the first displayed pel.
+ *
+ */
+
+ if(src_w > drw_w) drw_w = src_w;
+ if(src_h > drw_h) drw_h = src_h;
+
+ /* Clip */
+ xa = src_x;
+ xb = src_x + src_w;
+ ya = src_y;
+ yb = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if(!TDFXClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ bpp = pScrn->bitsPerPixel >> 3;
+ pitch = bpp * pScrn->displayWidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ dstPitch = ((width << 1) + 3) & ~3;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ srcPitch = (width + 3) & ~3;
+ s2offset = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ s3offset = (srcPitch2 * (height >> 1)) + s2offset;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ dstPitch = ((width << 1) + 3) & ~3;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ srcPitch = (width << 1);
+ break;
}
- return Success;
+
+ if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size)))
+ return BadAlloc;
+
+ /* copy data */
+ top = ya >> 16;
+ left = (xa >> 16) & ~1;
+ npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
+
+ offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
+ dst_start = pTDFX->FbBase + offset;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ dst_start += left << 1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 1);
+ s2offset += tmp;
+ s3offset += tmp;
+ if(id == FOURCC_I420) {
+ tmp = s2offset;
+ s2offset = s3offset;
+ s3offset = tmp;
+ }
+ nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
+ TDFXCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
+ buf + s3offset, dst_start, srcPitch, srcPitch2,
+ dstPitch, nlines, npixels);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ left <<= 1;
+ buf += (top * srcPitch) + left;
+ nlines = ((yb + 0xffff) >> 16) - top;
+ dst_start += left;
+ TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels << 1);
+ break;
+ }
+
+ if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ (*pTDFX->AccelInfoRec->FillSolidRects)(pScrn, pPriv->colorKey,
+ GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ }
+
+ TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
+
+ return Success;
}
-#endif
static void
-TDFXDeallocateOffscreenBuffer (ScrnInfoPtr pScrn, int id)
+TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
{
- TDFXPtr pTDFX = TDFXPTR(pScrn);
-
- /* There is only one buffer so just deallocate it */
- if (pTDFX->offscreenYUVBuf)
- xf86FreeOffscreenArea (pTDFX->offscreenYUVBuf);
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < time) {
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = time + FREE_DELAY;
+ }
+ } else
+ if(pPriv->videoStatus & FREE_TIMER) {
+ if(pPriv->freeTime < time) {
+ if(pTDFX->overlayBuffer) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
+ pTDFX->overlayBuffer = NULL;
+ }
+ pPriv->videoStatus = 0;
+ pTDFX->VideoTimerCallback = NULL;
+ }
+ }
+ } else /* shouldn't get here */
+ pTDFX->VideoTimerCallback = NULL;
}
+
+/*
+ * MEMORY MANAGEMENT
+ */
+
+
static FBAreaPtr
-TDFXAllocateOffscreenBuffer (ScrnInfoPtr pScrn, int id, int width, int height)
+TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
{
- int myWidth;
TDFXPtr pTDFX = TDFXPTR(pScrn);
+ ScreenPtr pScreen;
+ FBAreaPtr new_area;
- if (!pTDFX)
- return NULL;
-
- /* We tweak the width slightly */
- myWidth = width;
- /* We tweak the width slightly */
- myWidth = width;
-
- /* width is measured in pixels. The pixels in the YUV image are alway
- * 8 bit YUV data. But, the xf86 offscreen manager allocates in terms of
- * desktop pixels, so we adjust. */
- myWidth = myWidth / pTDFX->cpp;
- if (width % pTDFX->cpp)
- myWidth++;
-
- /* If we are putting up a subimage then we need an extra column of data
- * if the source width is odd, instead of checkin the width just always
- * allocate an extra column. */
- /* XXX is this really necessary? */
- myWidth++;
-
- if (pTDFX->offscreenYUVBuf != NULL &&
- myWidth == pTDFX->offscreenYUVBufWidth &&
- height == pTDFX->offscreenYUVBufHeight)
- {
- /* we already have a buffer, don't do anything. */
- return pTDFX->offscreenYUVBuf;
- }
-
- /* We have a buffer, but its not the right size so resize it */
- if (pTDFX->offscreenYUVBuf != NULL)
- {
- if (!xf86ResizeOffscreenArea (pTDFX->offscreenYUVBuf,
- myWidth,
- height))
- {
- return (NULL);
- }
+ if (area) {
+ if ((area->box.x2 - area->box.x1 >= width) &&
+ (area->box.y2 - area->box.y1 >= height))
+ return area;
+
+ if (xf86ResizeOffscreenArea(area, width, height))
+ return area;
+
+ xf86FreeOffscreenArea(area);
}
- else
- {
- /* Allocate a brand new buffer */
- pTDFX->offscreenYUVBuf =
- xf86AllocateOffscreenArea (pScrn->pScreen,
- myWidth,
- height,
- 0,
- NULL, NULL, NULL);
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
+
+ if (!new_area) {
+ int max_width, max_height;
+
+ xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME);
+
+ if (max_width < width || max_height < height)
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
}
- /* Return the buffer */
- pTDFX->offscreenYUVBufWidth = myWidth;
- pTDFX->offscreenYUVBufHeight = height;
- return (pTDFX->offscreenYUVBuf);
+ return new_area;
}
-static int
-TDFXQueryImageAttributes(
- ScrnInfoPtr pScrn,
- int id,
- unsigned short *w, unsigned short *h,
- int *pitches, int *offsets)
+static FBLinearPtr
+TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
{
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
- int size;
- TDFXPtr pTDFX = TDFXPTR(pScrn);
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
- /* The Maximum size for 3dfx YUV planar space
- * but our temporary buffer has to fit in the pixmap region which
- * is the same width as the desktop and pTDFX->pixmapCacheLines
- * pixels high.
- */
- if(*w > 1024) *w = 1024;
- if (*w > pTDFX->stride) *w = pTDFX->stride;
- if(*h > pTDFX->pixmapCacheLines) *h = pTDFX->pixmapCacheLines;
+ if(xf86ResizeOffscreenLinear(linear, size))
+ return linear;
+ xf86FreeOffscreenLinear(linear);
+ }
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
- if (offsets) offsets[0] = 0;
- switch(id) {
- case FOURCC_YV12:
- case FOURCC_I420:
- if (pitches) pitches[0] = *w;
- /* Size of Y plane plus the size of U and V planes */
- size = *w * *h;
- if (offsets) offsets[1] = size;
- size += ((*w >> 1) * (*h >> 1));
- if (offsets) offsets[2] = size;
- size += ((*w >> 1) * (*h >> 1));
- break;
- case FOURCC_UYVY:
- case FOURCC_YUY2:
- default:
- size = *w << 1;
- if(pitches) pitches[0] = size;
- size *= *h;
- break;
- }
- return size;
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
+
+ if(!new_linear) {
+ int max_size;
+
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
+
+ if(max_size < size)
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
+ }
+
+ return new_linear;
}
#endif /* !XvExtension */