1578 lines
44 KiB
C
1578 lines
44 KiB
C
/* 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 "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>
|
|
#ifdef HAVE_XAA_H
|
|
#include "xaa.h"
|
|
#include "xaalocal.h"
|
|
#endif
|
|
#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(BLOCKHANDLER_ARGS_DECL);
|
|
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);
|
|
|
|
extern 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 = xf86ScreenToScrn(pScrn);
|
|
|
|
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 */
|
|
malloc((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)
|
|
free(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 = xf86ScreenToScrn(pScrn);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
XF86VideoAdaptorPtr adapt;
|
|
GeodePortPrivRec *pPriv;
|
|
|
|
if (!(adapt = calloc(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 = 0;
|
|
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 = xf86ScreenToScrn(pScreen);
|
|
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 = xf86ScrnToScreen(pScrni);
|
|
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();
|
|
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(BLOCKHANDLER_ARGS_DECL)
|
|
{
|
|
SCREEN_PTR(arg);
|
|
ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni);
|
|
|
|
pScrn->BlockHandler = pGeode->BlockHandler;
|
|
(*pScrn->BlockHandler) (BLOCKHANDLER_ARGS);
|
|
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 = malloc(sizeof(int))))
|
|
return BadAlloc;
|
|
|
|
if (!(surface->offsets = malloc(sizeof(int)))) {
|
|
free(surface->pitches);
|
|
return BadAlloc;
|
|
}
|
|
|
|
if (!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
|
|
free(surface->pitches);
|
|
free(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);
|
|
free(surface->pitches);
|
|
free(surface->offsets);
|
|
free(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 = malloc(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 */
|