summaryrefslogtreecommitdiff
path: root/src/gx_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gx_video.c')
-rw-r--r--src/gx_video.c1558
1 files changed, 1558 insertions, 0 deletions
diff --git a/src/gx_video.c b/src/gx_video.c
new file mode 100644
index 0000000..7d2f0f4
--- /dev/null
+++ b/src/gx_video.c
@@ -0,0 +1,1558 @@
+/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc.
+ *
+ * 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 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
+ * IMPDIs2IED, 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.
+ *
+ * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * */
+
+/*
+ * File Contents: This file consists of main Xfree video supported routines.
+ *
+ * Project: Geode Xfree Frame buffer device driver.
+ * */
+
+/*
+ * Fixes & Extensions to support Y800 greyscale modes
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+
+ * code to allocate offscreen memory from EXA - is borrowed from Radeon
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "geode.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+#include "geode_fourcc.h"
+
+#define OFF_DELAY 200 /* milliseconds */
+#define FREE_DELAY 60000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+#define XV_PROFILE 0
+#define REINIT 1
+
+#ifndef XvExtension
+#error "It didn't work!"
+void
+GXInitVideo(ScreenPtr pScrn)
+{
+}
+
+void
+GXResetVideo(ScrnInfoPtr pScrni)
+{
+}
+
+void
+GXSetVideoPosition()
+{
+}
+#else
+
+#define DBUF 1
+void GXResetVideo(ScrnInfoPtr pScrni);
+static XF86VideoAdaptorPtr GXSetupImageVideo(ScreenPtr);
+static void GXInitOffscreenImages(ScreenPtr);
+static void GXStopVideo(ScrnInfoPtr, pointer, Bool);
+static int GXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int GXGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
+static void GXQueryBestSize(ScrnInfoPtr, Bool,
+ short, short, short, short, unsigned int *, unsigned int *, pointer);
+static int GXPutImage(ScrnInfoPtr, short, short, short, short, short, short,
+ short, short, int, unsigned char *, short, short, Bool,
+ RegionPtr, pointer, DrawablePtr pDraw);
+
+static void GXBlockHandler(int, pointer, pointer, pointer);
+void GXSetVideoPosition(int x, int y, int width, int height,
+ short src_w, short src_h, short drw_w,
+ short drw_h, int id, int offset, ScrnInfoPtr pScrni);
+
+extern void GXAccelSync(ScrnInfoPtr pScrni);
+
+int DeltaX, DeltaY;
+
+unsigned long graphics_lut[256];
+static int lutflag = 0;
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvColorKey, xvColorKeyMode, xvFilter
+#if DBUF
+ , xvDoubleBuffer
+#endif
+ ;
+
+#define PALETTE_ADDRESS 0x038
+#define PALETTE_DATA 0x040
+#define DISPLAY_CONFIG 0x008
+#define MISC 0x050
+
+static void get_gamma_ram(unsigned long *lut) {
+
+ int i;
+
+ gfx_write_vid32(PALETTE_ADDRESS, 0);
+
+ for(i = 0; i < 256; i++)
+ lut[i] = gfx_read_vid32(PALETTE_DATA);
+}
+
+/*----------------------------------------------------------------------------
+ * GXInitVideo
+ *
+ * Description :This is the initialization routine.It creates a new video
+ * adapter and calls GXSetupImageVideo to initialize the adaptor
+ * by filling XF86VideoAdaptorREc.Then it lists the existing
+ * adaptors and adds the new one to it. Finally the list of
+ * XF86VideoAdaptorPtr pointers are passed to the
+ * xf86XVScreenInit().
+ *
+ * Parameters.
+ * pScrn :Screen handler pointer having screen information.
+ *
+ * Returns :none
+ *
+ * Comments :none
+ *----------------------------------------------------------------------------
+ */
+void
+GXInitVideo(ScreenPtr pScrn)
+{
+ GeodeRec *pGeode;
+ ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
+
+ pGeode = GEODEPTR(pScrni);
+
+ if (!pGeode->NoAccel) {
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+
+ int num_adaptors;
+
+ newAdaptor = GXSetupImageVideo(pScrn);
+ GXInitOffscreenImages(pScrn);
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrni, &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++;
+ }
+ }
+ }
+
+ if (num_adaptors)
+ xf86XVScreenInit(pScrn, adaptors, num_adaptors);
+
+ if (newAdaptors)
+ xfree(newAdaptors);
+ }
+}
+
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding[1] = {
+ {
+ 0,
+ "XV_IMAGE",
+ 1024, 1024,
+ {1, 1}
+ }
+};
+
+#define NUM_FORMATS 4
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] = {
+ {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+#if DBUF
+#define NUM_ATTRIBUTES 4
+#else
+#define NUM_ATTRIBUTES 3
+#endif
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
+#if DBUF
+ {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
+#endif
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, 0, 1, "XV_FILTER"},
+ {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"}
+};
+
+#define NUM_IMAGES 8
+
+static XF86ImageRec Images[NUM_IMAGES] = {
+ XVIMAGE_UYVY,
+ XVIMAGE_YUY2,
+ XVIMAGE_Y2YU,
+ XVIMAGE_YVYU,
+ XVIMAGE_Y800,
+ XVIMAGE_I420,
+ XVIMAGE_YV12,
+ XVIMAGE_RGB565
+};
+
+typedef struct
+{
+ void *area;
+ int offset;
+ RegionRec clip;
+ CARD32 filter;
+ CARD32 colorKey;
+ CARD32 colorKeyMode;
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+#if DBUF
+ Bool doubleBuffer;
+ int currentBuffer;
+#endif
+} GeodePortPrivRec, *GeodePortPrivPtr;
+
+#define GET_PORT_PRIVATE(pScrni) \
+ (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr)
+
+/*----------------------------------------------------------------------------
+ * GXSetColorKey
+ *
+ * Description :This function reads the color key for the pallete and
+ * sets the video color key register.
+ *
+ * Parameters.
+ * ScreenInfoPtr
+ * pScrni :Screen pointer having screen information.
+ * pPriv :Video port private data
+ *
+ * Returns :none
+ *
+ * Comments :none
+ *
+ *----------------------------------------------------------------------------
+ */
+static INT32
+GXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv)
+{
+ int red, green, blue;
+ unsigned long key;
+
+ switch (pScrni->depth) {
+ case 8:
+ GFX(get_display_palette_entry(pPriv->colorKey & 0xFF, &key));
+ red = ((key >> 16) & 0xFF);
+ green = ((key >> 8) & 0xFF);
+ blue = (key & 0xFF);
+ break;
+ case 16:
+ red = (pPriv->colorKey & pScrni->mask.red) >>
+ pScrni->offset.red << (8 - pScrni->weight.red);
+ green = (pPriv->colorKey & pScrni->mask.green) >>
+ pScrni->offset.green << (8 - pScrni->weight.green);
+ blue = (pPriv->colorKey & pScrni->mask.blue) >>
+ pScrni->offset.blue << (8 - pScrni->weight.blue);
+ break;
+ default:
+ /* for > 16 bpp we send in the mask in xf86SetWeight. This
+ * function is providing the offset by 1 more. So we take
+ * this as a special case and subtract 1 for > 16
+ */
+ red = (pPriv->colorKey & pScrni->mask.red) >>
+ (pScrni->offset.red - 1) << (8 - pScrni->weight.red);
+ green = (pPriv->colorKey & pScrni->mask.green) >>
+ (pScrni->offset.green - 1) << (8 - pScrni->weight.green);
+ blue = (pPriv->colorKey & pScrni->mask.blue) >>
+ (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue);
+ break;
+ }
+
+ GFX(set_video_color_key((blue | (green << 8) | (red << 16)), 0xFFFFFF,
+ (pPriv->colorKeyMode == 0)));
+ REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * GXResetVideo
+ *
+ * Description : This function resets the video
+ *
+ * Parameters.
+ * pScrni :Screen pointer having screen information.
+ *
+ * Returns :None
+ *
+ * Comments :none
+ *
+ *----------------------------------------------------------------------------
+ */
+void
+GXResetVideo(ScrnInfoPtr pScrni)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ if (!pGeode->NoAccel) {
+ GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr;
+
+ GXAccelSync(pScrni);
+ GXSetColorkey(pScrni, pPriv);
+ GFX(set_video_filter(pPriv->filter, pPriv->filter));
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * GXSetupImageVideo
+ *
+ * Description : This function allocates space for a Videoadaptor and
+ * initializes the XF86VideoAdaptorPtr record.
+ *
+ * Parameters.
+ * pScrn :Screen handler pointer having screen information.
+ *
+ * Returns :pointer to the initialized video adaptor record.
+ *
+ * Comments :none
+ *----------------------------------------------------------------------------
+ */
+static XF86VideoAdaptorPtr
+GXSetupImageVideo(ScreenPtr pScrn)
+{
+ ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ XF86VideoAdaptorPtr adapt;
+ GeodePortPrivRec *pPriv;
+
+ if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+ sizeof(GeodePortPrivRec) + sizeof(DevUnion))))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "Advanced Micro Devices";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
+ pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]);
+ adapt->pPortPrivates[0].ptr = (pointer) (pPriv);
+ adapt->pAttributes = Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo= GXStopVideo;
+ adapt->SetPortAttribute = GXSetPortAttribute;
+ adapt->GetPortAttribute = GXGetPortAttribute;
+ adapt->QueryBestSize = GXQueryBestSize;
+ adapt->PutImage = GXPutImage;
+ adapt->QueryImageAttributes = GeodeQueryImageAttributes;
+
+ pPriv->filter = 0;
+ pPriv->colorKey = pGeode->videoKey;
+ pPriv->colorKeyMode = 0;
+ pPriv->videoStatus = 0;
+#if DBUF
+ pPriv->doubleBuffer = TRUE;
+ pPriv->currentBuffer = 0; /* init to first buffer */
+#endif
+
+ /* gotta uninit this someplace */
+#if defined(REGION_NULL)
+ REGION_NULL(pScrn, &pPriv->clip);
+#else
+ REGION_INIT(pScrn, &pPriv->clip, NullBox, 0);
+#endif
+
+ pGeode->adaptor = adapt;
+
+ pGeode->BlockHandler = pScrn->BlockHandler;
+ pScrn->BlockHandler = GXBlockHandler;
+
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+ xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE");
+ xvFilter = MAKE_ATOM("XV_FILTER");
+#if DBUF
+ xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
+#endif
+
+ GXResetVideo(pScrni);
+
+ return adapt;
+}
+
+/*----------------------------------------------------------------------------
+ * GXStopVideo
+ *
+ * Description :This function is used to stop input and output video
+ *
+ * Parameters.
+ * pScrni :Screen handler pointer having screen information.
+ * data :Pointer to the video port's private data
+ * exit :Flag indicating whether the offscreen areas used for
+ * video to be deallocated or not.
+ *
+ * Returns :none
+ *
+ * Comments :none
+ *----------------------------------------------------------------------------
+ */
+static void
+GXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit)
+{
+ GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ REGION_EMPTY(pScrni->pScreen, &pPriv->clip);
+
+ GXAccelSync(pScrni);
+ if (exit) {
+ if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ GFX(set_video_enable(0));
+
+ /* If we have saved graphics LUT data - restore it */
+ /* Otherwise, turn bypass on */
+
+ if (lutflag)
+ GFX(set_graphics_palette(graphics_lut));
+ else
+ GFX(set_video_palette_bypass(1));
+
+ lutflag = 0;
+ }
+
+ if (pPriv->area) {
+#ifdef XF86EXA
+ if (pGeode->useEXA)
+ exaOffscreenFree(pScrni->pScreen, pPriv->area);
+#endif
+
+ if (!pGeode->useEXA)
+ xf86FreeOffscreenArea(pPriv->area);
+
+ pPriv->area = NULL;
+ }
+
+ pPriv->videoStatus = 0;
+ pGeode->OverlayON = FALSE;
+ } else {
+ if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * GXSetPortAttribute
+ *
+ * Description :This function is used to set the attributes of a port
+ * like colorkeymode, double buffer support and filter.
+ *
+ * Parameters.
+ * pScrni :Screen handler pointer having screen information.
+ * data :Pointer to the video port's private data
+ * attribute :The port attribute to be set
+ * value :Value of the attribute to be set.
+ *
+ * Returns :Sucess if the attribute is supported, else BadMatch
+ *
+ * Comments :none
+ *----------------------------------------------------------------------------
+ */
+static int
+GXSetPortAttribute(ScrnInfoPtr pScrni,
+ Atom attribute, INT32 value, pointer data)
+{
+ GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
+
+ GXAccelSync(pScrni);
+ if (attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ GXSetColorkey(pScrni, pPriv);
+ }
+#if DBUF
+ else if (attribute == xvDoubleBuffer) {
+ if ((value < 0) || (value > 1))
+ return BadValue;
+ pPriv->doubleBuffer = value;
+ }
+#endif
+ else if (attribute == xvColorKeyMode) {
+ pPriv->colorKeyMode = value;
+ GXSetColorkey(pScrni, pPriv);
+ } else if (attribute == xvFilter) {
+ if ((value < 0) || (value > 1))
+ return BadValue;
+ pPriv->filter = value;
+ } else
+ return BadMatch;
+
+ return Success;
+}
+
+/*----------------------------------------------------------------------------
+ * GXGetPortAttribute
+ *
+ * Description :This function is used to get the attributes of a port
+ * like hue, saturation,brightness or contrast.
+ *
+ * Parameters.
+ * pScrni :Screen handler pointer having screen information.
+ * data :Pointer to the video port's private data
+ * attribute :The port attribute to be read
+ * value :Pointer to the value of the attribute to be read.
+ *
+ * Returns :Sucess if the attribute is supported, else BadMatch
+ *
+ * Comments :none
+ *----------------------------------------------------------------------------
+ */
+static int
+GXGetPortAttribute(ScrnInfoPtr pScrni,
+ Atom attribute, INT32 * value, pointer data)
+{
+ GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
+
+ if (attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ }
+#if DBUF
+ else if (attribute == xvDoubleBuffer) {
+ *value = (pPriv->doubleBuffer) ? 1 : 0;
+ }
+#endif
+ else if (attribute == xvColorKeyMode) {
+ *value = pPriv->colorKeyMode;
+ } else if (attribute == xvFilter) {
+ *value = pPriv->filter;
+ } else
+ return BadMatch;
+
+ return Success;
+}
+
+/*----------------------------------------------------------------------------
+ * GXQueryBestSize
+ *
+ * Description :This function provides a way to query what the
+ * destination dimensions would end up being if they were to
+ * request that an area vid_w by vid_h from the video stream
+ * be scaled to rectangle of drw_w by drw_h on the screen.
+ *
+ * Parameters.
+ * pScrni :Screen handler pointer having screen information.
+ * data :Pointer to the video port's private data
+ * vid_w,vid_h :Width and height of the video data.
+ * drw_w,drw_h :Width and height of the scaled rectangle.
+ * p_w,p_h :Width and height of the destination rectangle.
+ *
+ * Returns :None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+static void
+GXQueryBestSize(ScrnInfoPtr pScrni,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h, pointer data)
+{
+ *p_w = drw_w;
+ *p_h = drw_h;
+
+ if (*p_w > 16384)
+ *p_w = 16384;
+}
+
+/*----------------------------------------------------------------------------
+ * GXCopyData420
+ *
+ * Description : Copies data from src to destination
+ *
+ * Parameters.
+ * src : pointer to the source data
+ * dst : pointer to destination data
+ * srcPitch : pitch of the srcdata
+ * dstPitch : pitch of the destination data
+ * h & w : height and width of source data
+ *
+ * Returns :None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+static void
+GXCopyData420(unsigned char *src, unsigned char *dst,
+ int srcPitch, int dstPitch, int h, int w)
+{
+ while (h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * GXCopyData422
+ *
+ * Description : Copies data from src to destination
+ *
+ * Parameters.
+ * src : pointer to the source data
+ * dst : pointer to destination data
+ * srcPitch : pitch of the srcdata
+ * dstPitch : pitch of the destination data
+ * h & w : height and width of source data
+ *
+ * Returns :None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+static void
+GXCopyData422(unsigned char *src, unsigned char *dst,
+ int srcPitch, int dstPitch, int h, int w)
+{
+ w <<= 1;
+ while (h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+#ifdef XF86EXA
+static void
+GXVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) {
+ ScrnInfoPtr pScrni = xf86Screens[pScreen->myNum];
+ GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
+
+ if (area == pPriv->area)
+ pPriv->area = NULL;
+}
+#endif
+
+static int
+GXAllocateMemory(ScrnInfoPtr pScrni, void **memp, int numlines)
+{
+ ScreenPtr pScrn = screenInfo.screens[pScrni->scrnIndex];
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ //long displayWidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
+ int size = numlines * pGeode->displayWidth;
+
+#if XF86EXA
+ if (pGeode->useEXA) {
+ ExaOffscreenArea *area = *memp;
+
+ if (area != NULL) {
+ if (area->size >= size)
+ return area->offset;
+
+ exaOffscreenFree(pScrni->pScreen, area);
+ }
+
+ area = exaOffscreenAlloc(pScrni->pScreen, size, 16,
+ TRUE, GXVideoSave, NULL);
+ *memp = area;
+
+ return area == NULL ? 0 : area->offset;
+ }
+#endif
+
+ if (!pGeode->useEXA) {
+ FBAreaPtr area = *memp;
+ FBAreaPtr new_area;
+
+ if (area) {
+ if ((area->box.y2 - area->box.y1) >= numlines)
+ return (area->box.y1 * pGeode->Pitch);
+
+
+ if (xf86ResizeOffscreenArea(area, pGeode->displayWidth, numlines))
+ return (area->box.y1 * pGeode->Pitch);
+
+ xf86FreeOffscreenArea(area);
+ }
+
+ new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
+ numlines, 0, NULL, NULL, NULL);
+
+ if (!new_area) {
+ int max_w, max_h;
+
+ xf86QueryLargestOffscreenArea(pScrn, &max_w, &max_h, 0,
+ FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
+
+ if ((max_w < pGeode->displayWidth) || (max_h < numlines)) {
+ xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No room - how sad %x, %x, %x, %x\n", max_w, pGeode->displayWidth, max_h, numlines);
+ return 0;
+ }
+
+ xf86PurgeUnlockedOffscreenAreas(pScrn);
+ new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth,
+ numlines, 0, NULL, NULL, NULL);
+ }
+
+ return (new_area->box.y1 * pGeode->Pitch);
+ }
+
+ return 0;
+}
+
+static BoxRec dstBox;
+static int srcPitch = 0, srcPitch2 = 0, dstPitch = 0, dstPitch2 = 0;
+static INT32 Bx1, Bx2, By1, By2;
+static int top, left, npixels, nlines;
+static int offset, s1offset = 0, s2offset = 0, s3offset = 0;
+static unsigned char *dst_start;
+static int d2offset = 0, d3offset = 0;
+
+#if 0
+static Bool
+RegionsIntersect(BoxPtr pRcl1, BoxPtr pRcl2, BoxPtr pRclResult)
+{
+ pRclResult->x1 = max(pRcl1->x1, pRcl2->x1);
+ pRclResult->x2 = min(pRcl1->x2, pRcl2->x2);
+
+ if (pRclResult->x1 <= pRclResult->x2) {
+ pRclResult->y1 = max(pRcl1->y1, pRcl2->y1);
+ pRclResult->y2 = min(pRcl1->y2, pRcl2->y2);
+
+ if (pRclResult->y1 <= pRclResult->y2) {
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+#endif
+
+void
+GXSetVideoPosition(int x, int y, int width, int height,
+ short src_w, short src_h, short drw_w, short drw_h,
+ int id, int offset, ScrnInfoPtr pScrni)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ long ystart, xend, yend;
+ unsigned long lines = 0;
+ unsigned long y_extra, uv_extra = 0;
+ unsigned long startAddress;
+#if 0
+ BoxRec ovly, display, result;
+#endif
+
+ xend = x + drw_w;
+ yend = y + drw_h;
+
+ /* Take care of panning when panel is present */
+
+ startAddress = gfx_get_display_offset() - pGeode->FBOffset;
+ DeltaY = startAddress / pGeode->Pitch;
+ DeltaX = startAddress & (pGeode->Pitch - 1);
+ DeltaX /= (pScrni->bitsPerPixel >> 3);
+
+#if 0
+ /* Thhis code is pretty dang broken - comment it out for now */
+
+ if (pGeode->Panel) {
+ ovly.x1 = x;
+ ovly.x2 = x + pGeode->video_dstw;
+ ovly.y1 = y;
+ ovly.y2 = y + pGeode->video_dsth;
+
+ display.x1 = DeltaX;
+ display.x2 = DeltaX + pGeode->FPBX;
+ display.y1 = DeltaY;
+ display.y2 = DeltaY + pGeode->FPBY;
+ x = xend = 0;
+ if (RegionsIntersect(&display, &ovly, &result)) {
+ x = ovly.x1 - DeltaX;
+ xend = ovly.x2 - DeltaX;
+ y = ovly.y1 - DeltaY;
+ yend = ovly.y2 - DeltaY;
+ }
+ }
+#endif
+
+ /* TOP CLIPPING */
+
+ if (y < 0) {
+ if (src_h < drw_h)
+ lines = (-y) * src_h / drw_h;
+ else
+ lines = (-y);
+ ystart = 0;
+ drw_h += y;
+ y_extra = lines * dstPitch;
+ uv_extra = (lines >> 1) * (dstPitch2);
+ } else {
+ ystart = y;
+ lines = 0;
+ y_extra = 0;
+ }
+
+ GFX(set_video_window(x, ystart, xend - x, yend - ystart));
+
+ if ((id == FOURCC_Y800) || (id == FOURCC_I420) || (id == FOURCC_YV12)) {
+ GFX(set_video_yuv_offsets(offset + y_extra,
+ offset + d3offset + uv_extra, offset + d2offset + uv_extra));
+ } else {
+ GFX(set_video_offset(offset + y_extra));
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * GXDisplayVideo
+ *
+ * Description :This function sets up the video registers for playing video
+ * It sets up the video format,width, height & position of the
+ * video window ,video offsets( y,u,v) and video pitches(y,u,v)
+ *
+ * Parameters
+ *
+ * Returns :None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+
+static void
+GXDisplayVideo(ScrnInfoPtr pScrni,
+ int id,
+ int offset,
+ short width, short height,
+ int pitch,
+ int x1, int y1, int x2, int y2,
+ BoxPtr dstBox, short src_w, short src_h, short drw_w, short drw_h)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ unsigned long dcfg, misc;
+
+ GXAccelSync(pScrni);
+
+ /* If the gamma LUT is already loaded with graphics data, then save it
+ * off
+ */
+
+
+ if (id != FOURCC_RGB565) {
+ dcfg = gfx_read_vid32(DISPLAY_CONFIG);
+ misc = gfx_read_vid32(MISC);
+
+ lutflag = (!(misc & 1) && (dcfg & (1 << 21)));
+
+ if (lutflag)
+ get_gamma_ram(graphics_lut);
+
+ /* Set the video gamma ram */
+ GFX(set_video_palette(NULL));
+ }
+
+ GFX(set_video_enable(1));
+
+ switch (id) {
+ case FOURCC_UYVY: /* UYVY */
+ GFX(set_video_format(VIDEO_FORMAT_UYVY));
+ GFX(set_video_size(width, height));
+ break;
+ case FOURCC_Y800: /* Y800 - greyscale - we munge it! */
+ case FOURCC_YV12: /* YV12 */
+ case FOURCC_I420: /* I420 */
+ GFX(set_video_format(VIDEO_FORMAT_Y0Y1Y2Y3));
+ GFX(set_video_size(width, height));
+ GFX(set_video_yuv_pitch(dstPitch, dstPitch2));
+ break;
+ case FOURCC_YUY2: /* YUY2 */
+ GFX(set_video_format(VIDEO_FORMAT_YUYV));
+ GFX(set_video_size(width, height));
+ break;
+ case FOURCC_Y2YU: /* Y2YU */
+ GFX(set_video_format(VIDEO_FORMAT_Y2YU));
+ GFX(set_video_size(width, height));
+ break;
+ case FOURCC_YVYU: /* YVYU */
+ GFX(set_video_format(VIDEO_FORMAT_YVYU));
+ GFX(set_video_size(width, height));
+ break;
+ case FOURCC_RGB565:
+ GFX(set_video_format(VIDEO_FORMAT_RGB));
+ GFX(set_video_size(width, height));
+ break;
+
+ }
+
+ if (pGeode->Panel) {
+ pGeode->video_x = dstBox->x1;
+ pGeode->video_y = dstBox->y1;
+ pGeode->video_w = width;
+ pGeode->video_h = height;
+ pGeode->video_srcw = src_w;
+ pGeode->video_srch = src_h;
+ pGeode->video_dstw = drw_w;
+ pGeode->video_dsth = drw_h;
+ pGeode->video_offset = offset;
+ pGeode->video_id = id;
+ pGeode->video_scrnptr = pScrni;
+ }
+
+ if ((drw_w >= src_w) && (drw_h >= src_h))
+ GFX(set_video_scale(width, height, drw_w, drw_h));
+ else if (drw_w < src_w)
+ GFX(set_video_scale(drw_w, height, drw_w, drw_h));
+ else if (drw_h < src_h)
+ GFX(set_video_scale(width, drw_h, drw_w, drw_h));
+
+ GXSetVideoPosition(dstBox->x1, dstBox->y1, width, height, src_w,
+ src_h, drw_w, drw_h, id, offset, pScrni);
+}
+
+/* Used by LX as well */
+
+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;
+ }
+
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * GXPutImage :This function writes a single frame of video into a
+ * drawable. The position and size of the source rectangle is
+ * specified by src_x,src_y, src_w and src_h. This data is
+ * stored in a system memory buffer at buf. The position and
+ * size of the destination rectangle is specified by drw_x,
+ * drw_y,drw_w,drw_h.The data is in the format indicated by the
+ * image descriptor and represents a source of size width by
+ * height. If sync is TRUE the driver should not return from
+ * this function until it is through reading the data from buf.
+ * Returning when sync is TRUE indicates that it is safe for the
+ * data at buf to be replaced,freed, or modified.
+ *
+ * Parameters.
+ *
+ * Returns :None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+
+static int
+GXPutImage(ScrnInfoPtr pScrni,
+ 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, DrawablePtr pDraw)
+{
+ GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data;
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ int new_h;
+
+#if REINIT
+ BOOL ReInitVideo = FALSE;
+ static BOOL DoReinitAgain = 0;
+#endif
+
+#if XV_PROFILE
+ long oldtime, newtime;
+
+ UpdateCurrentTime();
+ oldtime = currentTime.milliseconds;
+#endif
+
+#if REINIT
+/* update cliplist */
+ if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ ReInitVideo = TRUE;
+ }
+
+ if (DoReinitAgain)
+ ReInitVideo = TRUE;
+
+ if (ReInitVideo) {
+ DEBUGMSG(1, (0, X_NONE, "Regional Not Equal - Init\n"));
+#endif
+ DoReinitAgain = ~DoReinitAgain;
+ if (drw_w > 16384)
+ drw_w = 16384;
+
+ /* Clip */
+ Bx1 = src_x;
+ Bx2 = src_x + src_w;
+ By1 = src_y;
+ By2 = src_y + src_h;
+
+ if ((Bx1 >= Bx2) || (By1 >= By2))
+ return Success;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ dstBox.x1 -= pScrni->frameX0;
+ dstBox.x2 -= pScrni->frameX0;
+ dstBox.y1 -= pScrni->frameY0;
+ dstBox.y2 -= pScrni->frameY0;
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3; /* of luma */
+ dstPitch = (width + 31) & ~31;
+
+ s2offset = srcPitch * height;
+ d2offset = dstPitch * height;
+
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ dstPitch2 = ((width >> 1) + 15) & ~15;
+
+ s3offset = (srcPitch2 * (height >> 1)) + s2offset;
+ d3offset = (dstPitch2 * (height >> 1)) + d2offset;
+
+ new_h = dstPitch * height; /* Y */
+ new_h += (dstPitch2 * height); /* U+V */
+ new_h += pGeode->Pitch - 1;
+ new_h /= pGeode->Pitch;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ case FOURCC_Y800:
+ case FOURCC_RGB565:
+ default:
+ dstPitch = ((width << 1) + 3) & ~3;
+ srcPitch = (width << 1);
+ new_h = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch;
+ break;
+ }
+#if DBUF
+ if (pPriv->doubleBuffer)
+ new_h <<= 1;
+#endif
+
+ if (!(pPriv->offset = GXAllocateMemory(pScrni, &pPriv->area, new_h))) {
+ xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
+ "Could not allocate area of size %d\n", new_h);
+ return BadAlloc;
+ }
+
+ /* copy data */
+ top = By1;
+ left = Bx1 & ~1;
+ npixels = ((Bx2 + 1) & ~1) - left;
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ {
+ int tmp;
+
+ top &= ~1;
+
+ offset = pPriv->offset + (top * dstPitch);
+
+#if DBUF
+ if (pPriv->doubleBuffer && pPriv->currentBuffer)
+ offset += (new_h >> 1) * pGeode->Pitch;
+#endif
+ dst_start = pGeode->FBBase + offset + left;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 1);
+ s2offset += tmp;
+ s3offset += tmp;
+ if (id == FOURCC_I420) {
+ tmp = s2offset;
+ s2offset = s3offset;
+ s3offset = tmp;
+ }
+ nlines = ((By2 + 1) & ~1) - top;
+ }
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ case FOURCC_Y800:
+ case FOURCC_RGB565:
+ default:
+ left <<= 1;
+ buf += (top * srcPitch) + left;
+ nlines = By2 - top;
+ offset = (pPriv->offset) + (top * dstPitch);
+
+#if DBUF
+ if (pPriv->doubleBuffer && pPriv->currentBuffer)
+ offset += (new_h >> 1) * pGeode->Pitch;
+#endif
+ dst_start = pGeode->FBBase + offset + left;
+ break;
+ }
+ s1offset = (top * srcPitch) + left;
+#if REINIT
+ /* update cliplist */
+ REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
+
+ if (pPriv->colorKeyMode == 0) {
+ xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes);
+ }
+
+ GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
+ Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
+ }
+#endif
+ switch (id) {
+ case FOURCC_Y800:
+ /* This is shared between LX and GX, so it lives in amd_common.c */
+ GeodeCopyGreyscale(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ GXCopyData420(buf + s1offset, dst_start, srcPitch, dstPitch, nlines,
+ npixels);
+ GXCopyData420(buf + s2offset, dst_start + d2offset, srcPitch2,
+ dstPitch2, nlines >> 1, npixels >> 1);
+ GXCopyData420(buf + s3offset, dst_start + d3offset, srcPitch2,
+ dstPitch2, nlines >> 1, npixels >> 1);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ case FOURCC_RGB565:
+ default:
+ GXCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+#if !REINIT
+ /* update cliplist */
+ REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes);
+ if (pPriv->colorKeyMode == 0) {
+ /* draw these */
+ XAAFillSolidRects(pScrni, pPriv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
+ }
+
+ GXDisplayVideo(pScrni, id, offset, width, height, dstPitch,
+ Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h);
+#endif
+
+#if XV_PROFILE
+ UpdateCurrentTime();
+ newtime = currentTime.milliseconds;
+ DEBUGMSG(1, (0, X_NONE, "PI %d\n", newtime - oldtime));
+#endif
+
+#if DBUF
+ pPriv->currentBuffer ^= 1;
+#endif
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+ pGeode->OverlayON = TRUE;
+ return Success;
+}
+
+/*----------------------------------------------------------------------------
+ * GXQueryImageAttributes
+ *
+ * Description :This function is called to let the driver specify how data
+ * for a particular image of size width by height should be
+ * stored.
+ *
+ * Parameters.
+ * pScrni :Screen handler pointer having screen information.
+ * id :Id for the video format
+ * width :width of the image (can be modified by the driver)
+ * height :height of the image (can be modified by the driver)
+ * Returns : Size of the memory required for storing this image
+ *
+ * Comments :None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int
+GeodeQueryImageAttributes(ScrnInfoPtr pScrni,
+ int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets)
+{
+ int size;
+ int tmp;
+
+ DEBUGMSG(0, (0, X_NONE, "QueryImageAttributes %X\n", id));
+
+ 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:
+ case FOURCC_Y800:
+ default:
+ size = *w << 1;
+ if (pitches)
+ pitches[0] = size;
+
+ size *= *h;
+ break;
+ }
+ return size;
+}
+
+static void
+GXBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScrn = screenInfo.screens[i];
+ ScrnInfoPtr pScrni = xf86Screens[i];
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
+
+ pScrn->BlockHandler = pGeode->BlockHandler;
+ (*pScrn->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ pScrn->BlockHandler = GXBlockHandler;
+
+ if (pPriv->videoStatus & TIMER_MASK) {
+ GXAccelSync(pScrni);
+ UpdateCurrentTime();
+ if (pPriv->videoStatus & OFF_TIMER) {
+ if (pPriv->offTime < currentTime.milliseconds) {
+ GFX(set_video_enable(0));
+
+ /* If we have saved graphics LUT data - restore it */
+ /* Otherwise, turn bypass on */
+
+ if (lutflag)
+ GFX(set_graphics_palette(graphics_lut));
+ else
+ GFX(set_video_palette_bypass(1));
+
+ lutflag = 0;
+
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+ } else { /* FREE_TIMER */
+ if (pPriv->freeTime < currentTime.milliseconds) {
+
+ if (pPriv->area) {
+#ifdef XF86EXA
+ if (pGeode->useEXA)
+ exaOffscreenFree(pScrn, pPriv->area);
+#endif
+ if (!pGeode->useEXA)
+ xf86FreeOffscreenArea(pPriv->area);
+
+ pPriv->area = NULL;
+ }
+
+ pPriv->videoStatus = 0;
+ }
+ }
+ }
+}
+
+/****************** Offscreen stuff ***************/
+
+typedef struct
+{
+ void * area;
+ int offset;
+ Bool isOn;
+} OffscreenPrivRec, *OffscreenPrivPtr;
+
+/*----------------------------------------------------------------------------
+ * GXAllocateSurface
+ *
+ * Description :This function allocates an area of w by h in the offscreen
+ *
+ * Parameters.
+ * pScrni :Screen handler pointer having screen information.
+ *
+ * Returns :None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+static int
+GXAllocateSurface(ScrnInfoPtr pScrni,
+ int id, unsigned short w, unsigned short h, XF86SurfacePtr surface)
+{
+ void * area = NULL;
+ int pitch, fbpitch, numlines;
+ OffscreenPrivRec *pPriv;
+
+ if ((w > 1024) || (h > 1024))
+ return BadAlloc;
+
+ w = (w + 1) & ~1;
+ pitch = ((w << 1) + 15) & ~15;
+ fbpitch = pScrni->bitsPerPixel * pScrni->displayWidth >> 3;
+ numlines = ((pitch * h) + fbpitch - 1) / fbpitch;
+
+ if (!(offset = GXAllocateMemory(pScrni, &area, numlines)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if (!(surface->pitches = xalloc(sizeof(int))))
+ return BadAlloc;
+
+ if (!(surface->offsets = xalloc(sizeof(int)))) {
+ xfree(surface->pitches);
+ return BadAlloc;
+ }
+
+ if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ return BadAlloc;
+ }
+
+ pPriv->area = area;
+ pPriv->offset = offset;
+
+ pPriv->isOn = FALSE;
+
+ surface->pScrn = pScrni;
+ surface->id = id;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = offset;
+ surface->devPrivate.ptr = (pointer) pPriv;
+
+ return Success;
+}
+
+static int
+GXStopSurface(XF86SurfacePtr surface)
+{
+ OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
+
+ if (pPriv->isOn) {
+ pPriv->isOn = FALSE;
+ }
+
+ return Success;
+}
+
+static int
+GXFreeSurface(XF86SurfacePtr surface)
+{
+ OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
+
+ if (pPriv->isOn)
+ GXStopSurface(surface);
+
+ xf86FreeOffscreenArea(pPriv->area);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int
+GXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value)
+{
+ return GXGetPortAttribute(pScrni, attribute, value,
+ (pointer) (GET_PORT_PRIVATE(pScrni)));
+}
+
+static int
+GXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value)
+{
+ return GXSetPortAttribute(pScrni, attribute, value,
+ (pointer) (GET_PORT_PRIVATE(pScrni)));
+}
+
+static int
+GXDisplaySurface(XF86SurfacePtr surface,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h, short drw_w, short drw_h, RegionPtr clipBoxes)
+{
+ OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr;
+ ScrnInfoPtr pScrni = surface->pScrn;
+ GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni);
+ INT32 x1, y1, x2, y2;
+ BoxRec dstBox;
+
+ DEBUGMSG(0, (0, X_NONE, "DisplaySuface\n"));
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = 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 ((x1 >= x2) || (y1 >= y2))
+ return Success;
+
+ dstBox.x1 -= pScrni->frameX0;
+ dstBox.x2 -= pScrni->frameX0;
+ dstBox.y1 -= pScrni->frameY0;
+ dstBox.y2 -= pScrni->frameY0;
+
+ xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes);
+
+ GXDisplayVideo(pScrni, surface->id, surface->offsets[0],
+ surface->width, surface->height, surface->pitches[0],
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->isOn = TRUE;
+ if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrni->pScreen, &portPriv->clip);
+ UpdateCurrentTime();
+ portPriv->videoStatus = FREE_TIMER;
+ portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+
+ return Success;
+}
+
+/*----------------------------------------------------------------------------
+ * GXInitOffscreenImages
+ *
+ * Description :This function sets up the offscreen memory management. It
+ * fills in the XF86OffscreenImagePtr structure with functions to
+ * handle offscreen memory operations.
+ *
+ * Parameters.
+ * pScrn :Screen handler pointer having screen information.
+ *
+ * Returns : None
+ *
+ * Comments :None
+ *----------------------------------------------------------------------------
+ */
+static void
+GXInitOffscreenImages(ScreenPtr pScrn)
+{
+ XF86OffscreenImagePtr offscreenImages;
+
+ /* need to free this someplace */
+ if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
+ return;
+
+ offscreenImages[0].image = &Images[0];
+ offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages[0].alloc_surface = GXAllocateSurface;
+ offscreenImages[0].free_surface = GXFreeSurface;
+ offscreenImages[0].display = GXDisplaySurface;
+ offscreenImages[0].stop = GXStopSurface;
+ offscreenImages[0].setAttribute = GXSetSurfaceAttribute;
+ offscreenImages[0].getAttribute = GXGetSurfaceAttribute;
+ offscreenImages[0].max_width = 1024;
+ offscreenImages[0].max_height = 1024;
+ offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
+ offscreenImages[0].attributes = Attributes;
+
+ xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1);
+}
+
+#endif /* !XvExtension */