#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "misc.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include <X11/X.h>
#include <X11/Xproto.h>
#include "scrnintstr.h"
#include "regionstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "mivalidate.h"
#include "validate.h"
#include "resource.h"
#include "gcstruct.h"
#include "dixstruct.h"
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvproto.h>
#include "xvdix.h"
#include "xvmodproc.h"
#include "xf86xvpriv.h"
static Bool xf86XVCloseScreen(int, ScreenPtr);
static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*);
static int xf86XVFreePort(XvPortPtr);
static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*);
static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
CARD16, CARD16,CARD16, CARD16,
unsigned int*, unsigned int*);
static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16,
XvImagePtr, unsigned char*, Bool,
CARD16, CARD16);
static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
CARD16*, CARD16*, int*, int*);
static Bool xf86XVDestroyWindow(WindowPtr pWin);
static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind);
static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1)
static Bool xf86XVEnterVT(int, int);
static void xf86XVLeaveVT(int, int);
static void xf86XVAdjustFrame(int index, int x, int y, int flags);
static void xf86XVModeSet(ScrnInfoPtr pScrn);
static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int);
static DevPrivateKeyRec XF86XVWindowKeyRec;
#define XF86XVWindowKey (&XF86XVWindowKeyRec)
DevPrivateKey XF86XvScreenKey;
static unsigned long PortResource = 0;
DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL;
unsigned long (*XvGetRTPortProc)(void) = NULL;
int (*XvScreenInitProc)(ScreenPtr) = NULL;
#define GET_XV_SCREEN(pScreen) \
((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey))
#define GET_XF86XV_SCREEN(pScreen) \
((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
#define GET_XF86XV_WINDOW(pWin) \
((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey))
static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
static int NumGenDrivers = 0;
int
xf86XVRegisterGenericAdaptorDriver(
xf86XVInitGenericAdaptorPtr InitFunc
){
xf86XVInitGenericAdaptorPtr *newdrivers;
newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) *
(1 + NumGenDrivers));
if (!newdrivers)
return 0;
GenDrivers = newdrivers;
GenDrivers[NumGenDrivers++] = InitFunc;
return 1;
}
int
xf86XVListGenericAdaptors(
ScrnInfoPtr pScrn,
XF86VideoAdaptorPtr **adaptors
){
int i,j,n,num;
XF86VideoAdaptorPtr *DrivAdap,*new;
num = 0;
*adaptors = NULL;
for (i = NumGenDrivers; --i >= 0; ) {
DrivAdap = NULL;
n = (*GenDrivers[i])(pScrn, &DrivAdap);
if (0 == n)
continue;
new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n));
if (NULL == new)
continue;
*adaptors = new;
for (j = 0; j < n; j++, num++)
(*adaptors)[num] = DrivAdap[j];
}
return num;
}
typedef struct {
XF86OffscreenImagePtr images;
int num;
} OffscreenImageRec;
static DevPrivateKeyRec OffscreenPrivateKeyRec;
#define OffscreenPrivateKey (&OffscreenPrivateKeyRec)
#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey))
Bool
xf86XVRegisterOffscreenImages(
ScreenPtr pScreen,
XF86OffscreenImagePtr images,
int num
){
OffscreenImageRec *OffscreenImage;
if(!dixRegisterPrivateKey(OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) ||
!(OffscreenImage = GetOffscreenImage(pScreen)))
FatalError("Could not allocate private storage for XV offscreen images.\n");
OffscreenImage->num = num;
OffscreenImage->images = images;
return TRUE;
}
XF86OffscreenImagePtr
xf86XVQueryOffscreenImages(
ScreenPtr pScreen,
int *num
){
OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen);
*num = OffscreenImage->num;
return OffscreenImage->images;
}
XF86VideoAdaptorPtr
xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
{
return calloc(1, sizeof(XF86VideoAdaptorRec));
}
void
xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
{
free(ptr);
}
Bool
xf86XVScreenInit(
ScreenPtr pScreen,
XF86VideoAdaptorPtr *adaptors,
int num
){
ScrnInfoPtr pScrn;
XF86XVScreenPtr ScreenPriv;
XvScreenPtr pxvs;
if(num <= 0 ||
!XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc)
return FALSE;
if(Success != (*XvScreenInitProc)(pScreen)) return FALSE;
if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0))
return FALSE;
XF86XvScreenKey = (*XvGetScreenKeyProc)();
PortResource = (*XvGetRTPortProc)();
pxvs = GET_XV_SCREEN(pScreen);
pxvs->ddCloseScreen = xf86XVCloseScreen;
pxvs->ddQueryAdaptors = xf86XVQueryAdaptors;
ScreenPriv = malloc(sizeof(XF86XVScreenRec));
pxvs->devPriv.ptr = (pointer)ScreenPriv;
if(!ScreenPriv) return FALSE;
pScrn = xf86Screens[pScreen->myNum];
ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
ScreenPriv->WindowExposures = pScreen->WindowExposures;
ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
ScreenPriv->ClipNotify = pScreen->ClipNotify;
ScreenPriv->EnterVT = pScrn->EnterVT;
ScreenPriv->LeaveVT = pScrn->LeaveVT;
ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
ScreenPriv->ModeSet = pScrn->ModeSet;
pScreen->DestroyWindow = xf86XVDestroyWindow;
pScreen->WindowExposures = xf86XVWindowExposures;
pScreen->ClipNotify = xf86XVClipNotify;
pScrn->EnterVT = xf86XVEnterVT;
pScrn->LeaveVT = xf86XVLeaveVT;
if(pScrn->AdjustFrame)
pScrn->AdjustFrame = xf86XVAdjustFrame;
pScrn->ModeSet = xf86XVModeSet;
if(!xf86XVInitAdaptors(pScreen, adaptors, num))
return FALSE;
return TRUE;
}
static void
xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
{
int i;
free(pAdaptor->name);
if(pAdaptor->pEncodings) {
XvEncodingPtr pEncode = pAdaptor->pEncodings;
for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
free(pEncode->name);
free(pAdaptor->pEncodings);
}
free(pAdaptor->pFormats);
if(pAdaptor->pPorts) {
XvPortPtr pPort = pAdaptor->pPorts;
XvPortRecPrivatePtr pPriv;
for(i = 0; i < pAdaptor->nPorts; i++, pPort++) {
pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
if(pPriv) {
if(pPriv->clientClip)
RegionDestroy(pPriv->clientClip);
if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
RegionDestroy(pPriv->pCompositeClip);
if (pPriv->ckeyFilled)
RegionDestroy(pPriv->ckeyFilled);
free(pPriv);
}
}
free(pAdaptor->pPorts);
}
if(pAdaptor->nAttributes) {
XvAttributePtr pAttribute = pAdaptor->pAttributes;
for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
free(pAttribute->name);
free(pAdaptor->pAttributes);
}
free(pAdaptor->pImages);
free(pAdaptor->devPriv.ptr);
}
static Bool
xf86XVInitAdaptors(
ScreenPtr pScreen,
XF86VideoAdaptorPtr *infoPtr,
int number
) {
XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
XF86VideoAdaptorPtr adaptorPtr;
XvAdaptorPtr pAdaptor, pa;
XvAdaptorRecPrivatePtr adaptorPriv;
int na, numAdaptor;
XvPortRecPrivatePtr portPriv;
XvPortPtr pPort, pp;
int numPort;
XF86AttributePtr attributePtr;
XvAttributePtr pAttribute, pat;
XF86VideoFormatPtr formatPtr;
XvFormatPtr pFormat, pf;
int numFormat, totFormat;
XF86VideoEncodingPtr encodingPtr;
XvEncodingPtr pEncode, pe;
XF86ImagePtr imagePtr;
XvImagePtr pImage, pi;
int numVisuals;
VisualPtr pVisual;
int i;
pxvs->nAdaptors = 0;
pxvs->pAdaptors = NULL;
if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
return FALSE;
for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
adaptorPtr = infoPtr[na];
if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
!adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
continue;
if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
continue;
pa->type = adaptorPtr->type;
if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
pa->type &= ~XvVideoMask;
if(!adaptorPtr->PutStill && !adaptorPtr->GetStill)
pa->type &= ~XvStillMask;
if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
pa->type &= ~XvImageMask;
if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
!adaptorPtr->PutStill)
pa->type &= ~XvInputMask;
if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
pa->type &= ~XvOutputMask;
if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
continue;
if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
continue;
pa->pScreen = pScreen;
pa->ddAllocatePort = xf86XVAllocatePort;
pa->ddFreePort = xf86XVFreePort;
pa->ddPutVideo = xf86XVPutVideo;
pa->ddPutStill = xf86XVPutStill;
pa->ddGetVideo = xf86XVGetVideo;
pa->ddGetStill = xf86XVGetStill;
pa->ddStopVideo = xf86XVStopVideo;
pa->ddPutImage = xf86XVPutImage;
pa->ddSetPortAttribute = xf86XVSetPortAttribute;
pa->ddGetPortAttribute = xf86XVGetPortAttribute;
pa->ddQueryBestSize = xf86XVQueryBestSize;
pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
pa->name = strdup(adaptorPtr->name);
if(adaptorPtr->nEncodings &&
(pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++)
{
pe->id = encodingPtr->id;
pe->pScreen = pScreen;
pe->name = strdup(encodingPtr->name);
pe->width = encodingPtr->width;
pe->height = encodingPtr->height;
pe->rate.numerator = encodingPtr->rate.numerator;
pe->rate.denominator = encodingPtr->rate.denominator;
}
pa->nEncodings = adaptorPtr->nEncodings;
pa->pEncodings = pEncode;
}
if(adaptorPtr->nImages &&
(pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
i < adaptorPtr->nImages; i++, pi++, imagePtr++)
{
pi->id = imagePtr->id;
pi->type = imagePtr->type;
pi->byte_order = imagePtr->byte_order;
memcpy(pi->guid, imagePtr->guid, 16);
pi->bits_per_pixel = imagePtr->bits_per_pixel;
pi->format = imagePtr->format;
pi->num_planes = imagePtr->num_planes;
pi->depth = imagePtr->depth;
pi->red_mask = imagePtr->red_mask;
pi->green_mask = imagePtr->green_mask;
pi->blue_mask = imagePtr->blue_mask;
pi->y_sample_bits = imagePtr->y_sample_bits;
pi->u_sample_bits = imagePtr->u_sample_bits;
pi->v_sample_bits = imagePtr->v_sample_bits;
pi->horz_y_period = imagePtr->horz_y_period;
pi->horz_u_period = imagePtr->horz_u_period;
pi->horz_v_period = imagePtr->horz_v_period;
pi->vert_y_period = imagePtr->vert_y_period;
pi->vert_u_period = imagePtr->vert_u_period;
pi->vert_v_period = imagePtr->vert_v_period;
memcpy(pi->component_order, imagePtr->component_order, 32);
pi->scanline_order = imagePtr->scanline_order;
}
pa->nImages = adaptorPtr->nImages;
pa->pImages = pImage;
}
if(adaptorPtr->nAttributes &&
(pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec))))
{
for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0;
i < adaptorPtr->nAttributes; pat++, i++, attributePtr++)
{
pat->flags = attributePtr->flags;
pat->min_value = attributePtr->min_value;
pat->max_value = attributePtr->max_value;
pat->name = strdup(attributePtr->name);
}
pa->nAttributes = adaptorPtr->nAttributes;
pa->pAttributes = pAttribute;
}
totFormat = adaptorPtr->nFormats;
if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
xf86XVFreeAdaptor(pa);
continue;
}
for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats;
i < adaptorPtr->nFormats; i++, formatPtr++)
{
numVisuals = pScreen->numVisuals;
pVisual = pScreen->visuals;
while(numVisuals--) {
if((pVisual->class == formatPtr->class) &&
(pVisual->nplanes == formatPtr->depth)) {
if(numFormat >= totFormat) {
void *moreSpace;
totFormat *= 2;
moreSpace = realloc(pFormat,
totFormat * sizeof(XvFormatRec));
if(!moreSpace) break;
pFormat = moreSpace;
pf = pFormat + numFormat;
}
pf->visual = pVisual->vid;
pf->depth = formatPtr->depth;
pf++;
numFormat++;
}
pVisual++;
}
}
pa->nFormats = numFormat;
pa->pFormats = pFormat;
if(!numFormat) {
xf86XVFreeAdaptor(pa);
continue;
}
if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
xf86XVFreeAdaptor(pa);
continue;
}
adaptorPriv->flags = adaptorPtr->flags;
adaptorPriv->PutVideo = adaptorPtr->PutVideo;
adaptorPriv->PutStill = adaptorPtr->PutStill;
adaptorPriv->GetVideo = adaptorPtr->GetVideo;
adaptorPriv->GetStill = adaptorPtr->GetStill;
adaptorPriv->StopVideo = adaptorPtr->StopVideo;
adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
adaptorPriv->PutImage = adaptorPtr->PutImage;
adaptorPriv->ReputImage = adaptorPtr->ReputImage;
pa->devPriv.ptr = (pointer)adaptorPriv;
if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
xf86XVFreeAdaptor(pa);
continue;
}
for(pp = pPort, i = 0, numPort = 0;
i < adaptorPtr->nPorts; i++) {
if(!(pp->id = FakeClientID(0)))
continue;
if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
continue;
if(!AddResource(pp->id, PortResource, pp)) {
free(portPriv);
continue;
}
pp->pAdaptor = pa;
pp->pNotify = (XvPortNotifyPtr)NULL;
pp->pDraw = (DrawablePtr)NULL;
pp->client = (ClientPtr)NULL;
pp->grab.client = (ClientPtr)NULL;
pp->time = currentTime;
pp->devPriv.ptr = portPriv;
portPriv->pScrn = pScrn;
portPriv->AdaptorRec = adaptorPriv;
portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
pp++;
numPort++;
}
pa->nPorts = numPort;
pa->pPorts = pPort;
if(!numPort) {
xf86XVFreeAdaptor(pa);
continue;
}
pa->base_id = pPort->id;
pa++;
numAdaptor++;
}
if(numAdaptor) {
pxvs->nAdaptors = numAdaptor;
pxvs->pAdaptors = pAdaptor;
} else {
free(pAdaptor);
return FALSE;
}
return TRUE;
}
static void
xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
{
RegionPtr pregWin, pCompositeClip;
WindowPtr pWin;
Bool freeCompClip = FALSE;
if(portPriv->pCompositeClip)
return;
pWin = (WindowPtr)portPriv->pDraw;
if(portPriv->subWindowMode == IncludeInferiors) {
pregWin = NotClippedByChildren(pWin);
freeCompClip = TRUE;
} else
pregWin = &pWin->clipList;
if(!portPriv->clientClip) {
portPriv->pCompositeClip = pregWin;
portPriv->FreeCompositeClip = freeCompClip;
return;
}
pCompositeClip = RegionCreate(NullBox, 1);
RegionCopy(pCompositeClip, portPriv->clientClip);
RegionTranslate(pCompositeClip,
portPriv->pDraw->x, portPriv->pDraw->y);
RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
portPriv->pCompositeClip = pCompositeClip;
portPriv->FreeCompositeClip = TRUE;
if(freeCompClip) {
RegionDestroy(pregWin);
}
}
static void
xf86XVCopyClip(
XvPortRecPrivatePtr portPriv,
GCPtr pGC
){
if((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
if(!portPriv->clientClip)
portPriv->clientClip = RegionCreate(NullBox, 1);
RegionCopy(portPriv->clientClip, pGC->clientClip);
RegionTranslate(portPriv->clientClip,
pGC->clipOrg.x, pGC->clipOrg.y);
} else if(portPriv->clientClip) {
RegionDestroy(portPriv->clientClip);
portPriv->clientClip = NULL;
}
if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
RegionDestroy(portPriv->pCompositeClip);
}
portPriv->pCompositeClip = pGC->pCompositeClip;
portPriv->FreeCompositeClip = FALSE;
portPriv->subWindowMode = pGC->subWindowMode;
}
static void
xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,
GCPtr pGC,
DrawablePtr pDraw)
{
if (!portPriv->clientClip)
portPriv->clientClip = RegionCreate(NullBox, 1);
RegionCopy(portPriv->clientClip, pGC->pCompositeClip);
RegionTranslate(portPriv->clientClip,
-pDraw->x, -pDraw->y);
if (portPriv->pCompositeClip && portPriv->FreeCompositeClip)
RegionDestroy(portPriv->pCompositeClip);
portPriv->pCompositeClip = pGC->pCompositeClip;
portPriv->FreeCompositeClip = FALSE;
portPriv->subWindowMode = pGC->subWindowMode;
}
static int
xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
{
RegionRec WinRegion;
RegionRec ClipRegion;
BoxRec WinBox;
int ret = Success;
Bool clippedAway = FALSE;
xf86XVUpdateCompositeClip(portPriv);
WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
WinBox.x2 = WinBox.x1 + portPriv->drw_w;
WinBox.y2 = WinBox.y1 + portPriv->drw_h;
RegionInit(&WinRegion, &WinBox, 1);
RegionNull(&ClipRegion);
RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
if(!RegionNotEmpty(&ClipRegion)) {
clippedAway = TRUE;
goto CLIP_VIDEO_BAILOUT;
}
if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
}
ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn,
portPriv->vid_x, portPriv->vid_y,
WinBox.x1, WinBox.y1,
portPriv->vid_w, portPriv->vid_h,
portPriv->drw_w, portPriv->drw_h,
&ClipRegion, portPriv->DevPriv.ptr,
portPriv->pDraw);
if(ret == Success)
portPriv->isOn = XV_ON;
CLIP_VIDEO_BAILOUT:
if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
portPriv->isOn = XV_PENDING;
}
if(!portPriv->FreeCompositeClip)
portPriv->pCompositeClip = NULL;
RegionUninit(&WinRegion);
RegionUninit(&ClipRegion);
return ret;
}
static int
xf86XVReputVideo(XvPortRecPrivatePtr portPriv)
{
RegionRec WinRegion;
RegionRec ClipRegion;
BoxRec WinBox;
int ret = Success;
Bool clippedAway = FALSE;
xf86XVUpdateCompositeClip(portPriv);
WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
WinBox.x2 = WinBox.x1 + portPriv->drw_w;
WinBox.y2 = WinBox.y1 + portPriv->drw_h;
RegionInit(&WinRegion, &WinBox, 1);
RegionNull(&ClipRegion);
RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
RegionRec VPReg;
BoxRec VPBox;
VPBox.x1 = portPriv->pScrn->frameX0;
VPBox.y1 = portPriv->pScrn->frameY0;
VPBox.x2 = portPriv->pScrn->frameX1 + 1;
VPBox.y2 = portPriv->pScrn->frameY1 + 1;
RegionInit(&VPReg, &VPBox, 1);
RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
RegionUninit(&VPReg);
}
if(!RegionNotEmpty(&ClipRegion)) {
clippedAway = TRUE;
goto CLIP_VIDEO_BAILOUT;
}
if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
BoxPtr clipBox = RegionRects(&ClipRegion);
if( (RegionNumRects(&ClipRegion) != 1) ||
(clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
(clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
{
clippedAway = TRUE;
goto CLIP_VIDEO_BAILOUT;
}
}
if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
}
ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn,
portPriv->vid_x, portPriv->vid_y,
WinBox.x1, WinBox.y1,
portPriv->vid_w, portPriv->vid_h,
portPriv->drw_w, portPriv->drw_h,
&ClipRegion, portPriv->DevPriv.ptr,
portPriv->pDraw);
if(ret == Success) portPriv->isOn = XV_ON;
CLIP_VIDEO_BAILOUT:
if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
portPriv->isOn = XV_PENDING;
}
if(!portPriv->FreeCompositeClip)
portPriv->pCompositeClip = NULL;
RegionUninit(&WinRegion);
RegionUninit(&ClipRegion);
return ret;
}
static int
xf86XVReputImage(XvPortRecPrivatePtr portPriv)
{
RegionRec WinRegion;
RegionRec ClipRegion;
BoxRec WinBox;
int ret = Success;
Bool clippedAway = FALSE;
xf86XVUpdateCompositeClip(portPriv);
RegionCopy(portPriv->clientClip, portPriv->pCompositeClip);
RegionTranslate(portPriv->clientClip,
-portPriv->pDraw->x, -portPriv->pDraw->y);
WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
WinBox.x2 = WinBox.x1 + portPriv->drw_w;
WinBox.y2 = WinBox.y1 + portPriv->drw_h;
RegionInit(&WinRegion, &WinBox, 1);
RegionNull(&ClipRegion);
RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
RegionRec VPReg;
BoxRec VPBox;
VPBox.x1 = portPriv->pScrn->frameX0;
VPBox.y1 = portPriv->pScrn->frameY0;
VPBox.x2 = portPriv->pScrn->frameX1 + 1;
VPBox.y2 = portPriv->pScrn->frameY1 + 1;
RegionInit(&VPReg, &VPBox, 1);
RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
RegionUninit(&VPReg);
}
if(!RegionNotEmpty(&ClipRegion)) {
clippedAway = TRUE;
goto CLIP_VIDEO_BAILOUT;
}
if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
BoxPtr clipBox = RegionRects(&ClipRegion);
if( (RegionNumRects(&ClipRegion) != 1) ||
(clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
(clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
{
clippedAway = TRUE;
goto CLIP_VIDEO_BAILOUT;
}
}
if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
}
ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn,
portPriv->vid_x, portPriv->vid_y,
WinBox.x1, WinBox.y1,
portPriv->vid_w, portPriv->vid_h,
portPriv->drw_w, portPriv->drw_h,
&ClipRegion, portPriv->DevPriv.ptr,
portPriv->pDraw);
portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
CLIP_VIDEO_BAILOUT:
if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
portPriv->isOn = XV_PENDING;
}
if(!portPriv->FreeCompositeClip)
portPriv->pCompositeClip = NULL;
RegionUninit(&WinRegion);
RegionUninit(&ClipRegion);
return ret;
}
static int
xf86XVReputAllVideo(WindowPtr pWin, pointer data)
{
XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
while(WinPriv) {
if(WinPriv->PortRec->type == XvInputMask)
xf86XVReputVideo(WinPriv->PortRec);
else
xf86XVRegetVideo(WinPriv->PortRec);
WinPriv = WinPriv->next;
}
return WT_WALKCHILDREN;
}
static int
xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
{
XF86XVWindowPtr winPriv, PrivRoot;
winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
while(winPriv) {
if(winPriv->PortRec == portPriv)
break;
winPriv = winPriv->next;
}
if(!winPriv) {
winPriv = calloc(1, sizeof(XF86XVWindowRec));
if(!winPriv) return BadAlloc;
winPriv->PortRec = portPriv;
winPriv->next = PrivRoot;
dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv);
}
portPriv->pDraw = (DrawablePtr)pWin;
return Success;
}
static void
xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
{
XF86XVWindowPtr winPriv, prevPriv = NULL;
winPriv = GET_XF86XV_WINDOW(pWin);
while(winPriv) {
if(winPriv->PortRec == portPriv) {
if(prevPriv)
prevPriv->next = winPriv->next;
else
dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey,
winPriv->next);
free(winPriv);
break;
}
prevPriv = winPriv;
winPriv = winPriv->next;
}
portPriv->pDraw = NULL;
if (portPriv->ckeyFilled) {
RegionDestroy(portPriv->ckeyFilled);
portPriv->ckeyFilled = NULL;
}
portPriv->clipChanged = FALSE;
}
static void
xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv,
WindowPtr pWin,
Bool visible)
{
if (!visible) {
if (pPriv->isOn == XV_ON) {
(*pPriv->AdaptorRec->StopVideo)(pPriv->pScrn, pPriv->DevPriv.ptr, FALSE);
pPriv->isOn = XV_PENDING;
}
if (!pPriv->type)
xf86XVRemovePortFromWindow(pWin, pPriv);
return;
}
switch (pPriv->type) {
case XvInputMask:
xf86XVReputVideo(pPriv);
break;
case XvOutputMask:
xf86XVRegetVideo(pPriv);
break;
default:
if (pPriv->AdaptorRec->ReputImage)
xf86XVReputImage(pPriv);
break;
}
}
static void
xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
{
ScreenPtr pScreen = pScrn->pScreen;
XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
XvAdaptorPtr pa;
int c, i;
for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
XvPortPtr pPort = pa->pPorts;
for (i = pa->nPorts; i > 0; i--, pPort++) {
XvPortRecPrivatePtr pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
WindowPtr pWin = (WindowPtr)pPriv->pDraw;
Bool visible;
if (pPriv->isOn == XV_OFF || !pWin)
continue;
if (onlyChanged && !pPriv->clipChanged)
continue;
visible = pWin->visibility == VisibilityUnobscured ||
pWin->visibility == VisibilityPartiallyObscured;
if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
visible = FALSE;
xf86XVReputOrStopPort(pPriv, pWin, visible);
pPriv->clipChanged = FALSE;
}
}
}
static Bool
xf86XVDestroyWindow(WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
int ret;
while(WinPriv) {
XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
if(pPriv->isOn > XV_OFF) {
(*pPriv->AdaptorRec->StopVideo)(
pPriv->pScrn, pPriv->DevPriv.ptr, TRUE);
pPriv->isOn = XV_OFF;
}
pPriv->pDraw = NULL;
tmp = WinPriv;
WinPriv = WinPriv->next;
free(tmp);
}
dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL);
pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
ret = (*pScreen->DestroyWindow)(pWin);
pScreen->DestroyWindow = xf86XVDestroyWindow;
return ret;
}
static void
xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind)
{
ScreenPtr pScreen;
XF86XVScreenPtr ScreenPriv;
ScrnInfoPtr pScrn;
if (pWin)
pScreen = pWin->drawable.pScreen;
else
pScreen = pLayerWin->drawable.pScreen;
ScreenPriv = GET_XF86XV_SCREEN(pScreen);
pScrn = xf86Screens[pScreen->myNum];
xf86XVReputOrStopAllPorts(pScrn, TRUE);
pScreen->PostValidateTree = ScreenPriv->PostValidateTree;
if (pScreen->PostValidateTree) {
(*pScreen->PostValidateTree)(pWin, pLayerWin, kind);
}
ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
}
static void
xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
XvPortRecPrivatePtr pPriv;
Bool AreasExposed;
AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
pScreen->WindowExposures = ScreenPriv->WindowExposures;
(*pScreen->WindowExposures)(pWin, reg1, reg2);
pScreen->WindowExposures = xf86XVWindowExposures;
if (!pWin->valdata) return;
while(WinPriv) {
Bool visible = TRUE;
pPriv = WinPriv->PortRec;
if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
visible = !AreasExposed;
if (!pPriv->type && pPriv->clientClip)
RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1);
if (visible && pPriv->ckeyFilled) {
RegionRec tmp;
RegionNull(&tmp);
RegionCopy(&tmp, reg1);
RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y);
RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp);
}
WinPriv = WinPriv->next;
xf86XVReputOrStopPort(pPriv, pWin, visible);
pPriv->clipChanged = FALSE;
}
}
static void
xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
XvPortRecPrivatePtr pPriv;
while(WinPriv) {
pPriv = WinPriv->PortRec;
if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
RegionDestroy(pPriv->pCompositeClip);
pPriv->pCompositeClip = NULL;
if (pPriv->AdaptorRec->ClipNotify)
(*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr,
pWin, dx, dy);
pPriv->clipChanged = TRUE;
if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
pScreen->PostValidateTree = xf86XVPostValidateTree;
}
WinPriv = WinPriv->next;
}
if(ScreenPriv->ClipNotify) {
pScreen->ClipNotify = ScreenPriv->ClipNotify;
(*pScreen->ClipNotify)(pWin, dx, dy);
pScreen->ClipNotify = xf86XVClipNotify;
}
}
static Bool
xf86XVCloseScreen(int i, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
XvAdaptorPtr pa;
int c;
if(!ScreenPriv) return TRUE;
pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
pScreen->WindowExposures = ScreenPriv->WindowExposures;
pScreen->ClipNotify = ScreenPriv->ClipNotify;
pScrn->EnterVT = ScreenPriv->EnterVT;
pScrn->LeaveVT = ScreenPriv->LeaveVT;
pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
pScrn->ModeSet = ScreenPriv->ModeSet;
for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
xf86XVFreeAdaptor(pa);
}
free(pxvs->pAdaptors);
free(ScreenPriv);
return TRUE;
}
static int
xf86XVQueryAdaptors(
ScreenPtr pScreen,
XvAdaptorPtr *p_pAdaptors,
int *p_nAdaptors
){
XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
*p_nAdaptors = pxvs->nAdaptors;
*p_pAdaptors = pxvs->pAdaptors;
return Success;
}
static Bool
xf86XVEnterVT(int index, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[index];
ScreenPtr pScreen = screenInfo.screens[index];
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
Bool ret;
pScrn->EnterVT = ScreenPriv->EnterVT;
ret = (*ScreenPriv->EnterVT)(index, flags);
ScreenPriv->EnterVT = pScrn->EnterVT;
pScrn->EnterVT = xf86XVEnterVT;
if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0);
return ret;
}
static void
xf86XVLeaveVT(int index, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[index];
ScreenPtr pScreen = screenInfo.screens[index];
XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
XvAdaptorPtr pAdaptor;
XvPortPtr pPort;
XvPortRecPrivatePtr pPriv;
int i, j;
for(i = 0; i < pxvs->nAdaptors; i++) {
pAdaptor = &pxvs->pAdaptors[i];
for(j = 0; j < pAdaptor->nPorts; j++) {
pPort = &pAdaptor->pPorts[j];
pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
if(pPriv->isOn > XV_OFF) {
(*pPriv->AdaptorRec->StopVideo)(
pPriv->pScrn, pPriv->DevPriv.ptr, TRUE);
pPriv->isOn = XV_OFF;
if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
RegionDestroy(pPriv->pCompositeClip);
pPriv->pCompositeClip = NULL;
if(!pPriv->type && pPriv->pDraw) {
xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv);
}
}
}
}
pScrn->LeaveVT = ScreenPriv->LeaveVT;
(*ScreenPriv->LeaveVT)(index, flags);
ScreenPriv->LeaveVT = pScrn->LeaveVT;
pScrn->LeaveVT = xf86XVLeaveVT;
}
static void
xf86XVAdjustFrame(int index, int x, int y, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[index];
ScreenPtr pScreen = pScrn->pScreen;
XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
if(ScreenPriv->AdjustFrame) {
pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
(*pScrn->AdjustFrame)(index, x, y, flags);
pScrn->AdjustFrame = xf86XVAdjustFrame;
}
xf86XVReputOrStopAllPorts(pScrn, FALSE);
}
static void
xf86XVModeSet(ScrnInfoPtr pScrn)
{
ScreenPtr pScreen = pScrn->pScreen;
XF86XVScreenPtr ScreenPriv;
if (!pScreen)
return;
ScreenPriv = GET_XF86XV_SCREEN(pScreen);
if (ScreenPriv->ModeSet) {
pScrn->ModeSet = ScreenPriv->ModeSet;
(*pScrn->ModeSet)(pScrn);
pScrn->ModeSet = xf86XVModeSet;
}
xf86XVReputOrStopAllPorts(pScrn, FALSE);
}
static int
xf86XVAllocatePort(
unsigned long port,
XvPortPtr pPort,
XvPortPtr *ppPort
){
*ppPort = pPort;
return Success;
}
static int
xf86XVFreePort(XvPortPtr pPort)
{
return Success;
}
static int
xf86XVPutVideo(
ClientPtr client,
DrawablePtr pDraw,
XvPortPtr pPort,
GCPtr pGC,
INT16 vid_x, INT16 vid_y,
CARD16 vid_w, CARD16 vid_h,
INT16 drw_x, INT16 drw_y,
CARD16 drw_w, CARD16 drw_h
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
int result;
if(pDraw->type != DRAWABLE_WINDOW) {
pPort->pDraw = (DrawablePtr)NULL;
return BadAlloc;
}
if(portPriv->pDraw && (portPriv->pDraw != pDraw))
xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
if(result != Success) return result;
portPriv->type = XvInputMask;
portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
xf86XVCopyClip(portPriv, pGC);
pPort->pDraw = pDraw;
if(!portPriv->pScrn->vtSema) return Success;
return(xf86XVReputVideo(portPriv));
}
static int
xf86XVPutStill(
ClientPtr client,
DrawablePtr pDraw,
XvPortPtr pPort,
GCPtr pGC,
INT16 vid_x, INT16 vid_y,
CARD16 vid_w, CARD16 vid_h,
INT16 drw_x, INT16 drw_y,
CARD16 drw_w, CARD16 drw_h
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
RegionRec WinRegion;
RegionRec ClipRegion;
BoxRec WinBox;
int ret = Success;
Bool clippedAway = FALSE;
if (pDraw->type != DRAWABLE_WINDOW)
return BadAlloc;
if(!portPriv->pScrn->vtSema) return Success;
WinBox.x1 = pDraw->x + drw_x;
WinBox.y1 = pDraw->y + drw_y;
WinBox.x2 = WinBox.x1 + drw_w;
WinBox.y2 = WinBox.y1 + drw_h;
xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
RegionInit(&WinRegion, &WinBox, 1);
RegionNull(&ClipRegion);
RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
RegionRec VPReg;
BoxRec VPBox;
VPBox.x1 = portPriv->pScrn->frameX0;
VPBox.y1 = portPriv->pScrn->frameY0;
VPBox.x2 = portPriv->pScrn->frameX1 + 1;
VPBox.y2 = portPriv->pScrn->frameY1 + 1;
RegionInit(&VPReg, &VPBox, 1);
RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
RegionUninit(&VPReg);
}
if(portPriv->pDraw) {
xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
}
if(!RegionNotEmpty(&ClipRegion)) {
clippedAway = TRUE;
goto PUT_STILL_BAILOUT;
}
if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
BoxPtr clipBox = RegionRects(&ClipRegion);
if( (RegionNumRects(&ClipRegion) != 1) ||
(clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
(clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
{
clippedAway = TRUE;
goto PUT_STILL_BAILOUT;
}
}
if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
}
ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn,
vid_x, vid_y, WinBox.x1, WinBox.y1,
vid_w, vid_h, drw_w, drw_h,
&ClipRegion, portPriv->DevPriv.ptr,
pDraw);
if((ret == Success) &&
(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
portPriv->isOn = XV_ON;
portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
portPriv->type = 0;
pPort->pDraw = pDraw;
}
PUT_STILL_BAILOUT:
if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
portPriv->isOn = XV_PENDING;
}
if(!portPriv->FreeCompositeClip)
portPriv->pCompositeClip = NULL;
RegionUninit(&WinRegion);
RegionUninit(&ClipRegion);
return ret;
}
static int
xf86XVGetVideo(
ClientPtr client,
DrawablePtr pDraw,
XvPortPtr pPort,
GCPtr pGC,
INT16 vid_x, INT16 vid_y,
CARD16 vid_w, CARD16 vid_h,
INT16 drw_x, INT16 drw_y,
CARD16 drw_w, CARD16 drw_h
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
int result;
if(pDraw->type != DRAWABLE_WINDOW) {
pPort->pDraw = (DrawablePtr)NULL;
return BadAlloc;
}
if(portPriv->pDraw && (portPriv->pDraw != pDraw))
xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
if(result != Success) return result;
portPriv->type = XvOutputMask;
portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
xf86XVCopyClip(portPriv, pGC);
pPort->pDraw = pDraw;
if(!portPriv->pScrn->vtSema) return Success;
return(xf86XVRegetVideo(portPriv));
}
static int
xf86XVGetStill(
ClientPtr client,
DrawablePtr pDraw,
XvPortPtr pPort,
GCPtr pGC,
INT16 vid_x, INT16 vid_y,
CARD16 vid_w, CARD16 vid_h,
INT16 drw_x, INT16 drw_y,
CARD16 drw_w, CARD16 drw_h
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
RegionRec WinRegion;
RegionRec ClipRegion;
BoxRec WinBox;
int ret = Success;
Bool clippedAway = FALSE;
if (pDraw->type != DRAWABLE_WINDOW)
return BadAlloc;
if(!portPriv->pScrn->vtSema) return Success;
WinBox.x1 = pDraw->x + drw_x;
WinBox.y1 = pDraw->y + drw_y;
WinBox.x2 = WinBox.x1 + drw_w;
WinBox.y2 = WinBox.y1 + drw_h;
RegionInit(&WinRegion, &WinBox, 1);
RegionNull(&ClipRegion);
RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
if(portPriv->pDraw) {
xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
}
if(!RegionNotEmpty(&ClipRegion)) {
clippedAway = TRUE;
goto GET_STILL_BAILOUT;
}
if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
}
ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn,
vid_x, vid_y, WinBox.x1, WinBox.y1,
vid_w, vid_h, drw_w, drw_h,
&ClipRegion, portPriv->DevPriv.ptr,
pDraw);
GET_STILL_BAILOUT:
if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
portPriv->isOn = XV_PENDING;
}
RegionUninit(&WinRegion);
RegionUninit(&ClipRegion);
return ret;
}
static int
xf86XVStopVideo(
ClientPtr client,
XvPortPtr pPort,
DrawablePtr pDraw
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
if(pDraw->type != DRAWABLE_WINDOW)
return BadAlloc;
xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv);
if(!portPriv->pScrn->vtSema) return Success;
if(portPriv->isOn > XV_OFF) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, TRUE);
portPriv->isOn = XV_OFF;
}
return Success;
}
static int
xf86XVSetPortAttribute(
ClientPtr client,
XvPortPtr pPort,
Atom attribute,
INT32 value
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn,
attribute, value, portPriv->DevPriv.ptr));
}
static int
xf86XVGetPortAttribute(
ClientPtr client,
XvPortPtr pPort,
Atom attribute,
INT32 *p_value
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn,
attribute, p_value, portPriv->DevPriv.ptr));
}
static int
xf86XVQueryBestSize(
ClientPtr client,
XvPortPtr pPort,
CARD8 motion,
CARD16 vid_w, CARD16 vid_h,
CARD16 drw_w, CARD16 drw_h,
unsigned int *p_w, unsigned int *p_h
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
(*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn,
(Bool)motion, vid_w, vid_h, drw_w, drw_h,
p_w, p_h, portPriv->DevPriv.ptr);
return Success;
}
static int
xf86XVPutImage(
ClientPtr client,
DrawablePtr pDraw,
XvPortPtr pPort,
GCPtr pGC,
INT16 src_x, INT16 src_y,
CARD16 src_w, CARD16 src_h,
INT16 drw_x, INT16 drw_y,
CARD16 drw_w, CARD16 drw_h,
XvImagePtr format,
unsigned char* data,
Bool sync,
CARD16 width, CARD16 height
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
RegionRec WinRegion;
RegionRec ClipRegion;
BoxRec WinBox;
int ret = Success;
Bool clippedAway = FALSE;
if (pDraw->type != DRAWABLE_WINDOW)
return BadAlloc;
if(!portPriv->pScrn->vtSema) return Success;
xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
WinBox.x1 = pDraw->x + drw_x;
WinBox.y1 = pDraw->y + drw_y;
WinBox.x2 = WinBox.x1 + drw_w;
WinBox.y2 = WinBox.y1 + drw_h;
RegionInit(&WinRegion, &WinBox, 1);
RegionNull(&ClipRegion);
RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
RegionRec VPReg;
BoxRec VPBox;
VPBox.x1 = portPriv->pScrn->frameX0;
VPBox.y1 = portPriv->pScrn->frameY0;
VPBox.x2 = portPriv->pScrn->frameX1 + 1;
VPBox.y2 = portPriv->pScrn->frameY1 + 1;
RegionInit(&VPReg, &VPBox, 1);
RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
RegionUninit(&VPReg);
}
if(portPriv->pDraw && (portPriv->pDraw != pDraw))
xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
if(ret != Success) goto PUT_IMAGE_BAILOUT;
if(!RegionNotEmpty(&ClipRegion)) {
clippedAway = TRUE;
goto PUT_IMAGE_BAILOUT;
}
if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
BoxPtr clipBox = RegionRects(&ClipRegion);
if( (RegionNumRects(&ClipRegion) != 1) ||
(clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
(clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
{
clippedAway = TRUE;
goto PUT_IMAGE_BAILOUT;
}
}
if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
}
ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn,
src_x, src_y, WinBox.x1, WinBox.y1,
src_w, src_h, drw_w, drw_h, format->id, data, width, height,
sync, &ClipRegion, portPriv->DevPriv.ptr,
pDraw);
if((ret == Success) &&
(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
portPriv->isOn = XV_ON;
portPriv->vid_x = src_x; portPriv->vid_y = src_y;
portPriv->vid_w = src_w; portPriv->vid_h = src_h;
portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
portPriv->type = 0;
pPort->pDraw = pDraw;
}
PUT_IMAGE_BAILOUT:
if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
(*portPriv->AdaptorRec->StopVideo)(
portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
portPriv->isOn = XV_PENDING;
}
if(!portPriv->FreeCompositeClip)
portPriv->pCompositeClip = NULL;
RegionUninit(&WinRegion);
RegionUninit(&ClipRegion);
return ret;
}
static int
xf86XVQueryImageAttributes(
ClientPtr client,
XvPortPtr pPort,
XvImagePtr format,
CARD16 *width,
CARD16 *height,
int *pitches,
int *offsets
){
XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn,
format->id, width, height, pitches, offsets);
}
void
xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
{
ScreenPtr pScreen = pDraw->pScreen;
ChangeGCVal pval[2];
BoxPtr pbox = RegionRects(fillboxes);
int i, nbox = RegionNumRects(fillboxes);
xRectangle *rects;
GCPtr gc;
if(!xf86Screens[pScreen->myNum]->vtSema) return;
gc = GetScratchGC(pDraw->depth, pScreen);
pval[0].val = key;
pval[1].val = IncludeInferiors;
(void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval);
ValidateGC(pDraw, gc);
rects = malloc(nbox * sizeof(xRectangle));
for(i = 0; i < nbox; i++, pbox++)
{
rects[i].x = pbox->x1 - pDraw->x;
rects[i].y = pbox->y1 - pDraw->y;
rects[i].width = pbox->x2 - pbox->x1;
rects[i].height = pbox->y2 - pbox->y1;
}
(*gc->ops->PolyFillRect)(pDraw, gc, nbox, rects);
free(rects);
FreeScratchGC (gc);
}
void
xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes)
{
xf86XVFillKeyHelperDrawable (&pScreen->root->drawable, key, fillboxes);
}
void
xf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything)
{
WindowPtr pWin = (WindowPtr)pDraw;
XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
XvPortRecPrivatePtr portPriv = NULL;
RegionRec reg;
RegionPtr fillboxes;
while (WinPriv) {
XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
if (data == pPriv->DevPriv.ptr) {
portPriv = pPriv;
break;
}
WinPriv = WinPriv->next;
}
if (!portPriv)
return;
if (!portPriv->ckeyFilled)
portPriv->ckeyFilled = RegionCreate(NULL, 0);
if (!fillEverything) {
RegionNull(®);
fillboxes = ®
RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled);
if (!RegionNotEmpty(fillboxes))
goto out;
} else
fillboxes = clipboxes;
RegionCopy(portPriv->ckeyFilled, clipboxes);
xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes);
out:
if (!fillEverything)
RegionUninit(®);
}
Bool
xf86XVClipVideoHelper(
BoxPtr dst,
INT32 *xa,
INT32 *xb,
INT32 *ya,
INT32 *yb,
RegionPtr reg,
INT32 width,
INT32 height
){
double xsw, xdw, ysw, ydw;
INT32 delta;
BoxPtr extents = RegionExtents(reg);
int diff;
xsw = (*xb - *xa) << 16;
xdw = dst->x2 - dst->x1;
ysw = (*yb - *ya) << 16;
ydw = 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 * xsw) / xdw;
}
diff = dst->x2 - extents->x2;
if (diff > 0) {
dst->x2 = extents->x2;
*xb -= (diff * xsw) / xdw;
}
diff = extents->y1 - dst->y1;
if (diff > 0) {
dst->y1 = extents->y1;
*ya += (diff * ysw) / ydw;
}
diff = dst->y2 - extents->y2;
if (diff > 0) {
dst->y2 = extents->y2;
*yb -= (diff * ysw) / ydw;
}
if (*xa < 0) {
diff = (((-*xa) * xdw) + xsw - 1) / xsw;
dst->x1 += diff;
*xa += (diff * xsw) / xdw;
}
delta = *xb - (width << 16);
if (delta > 0) {
diff = ((delta * xdw) + xsw - 1) / xsw;
dst->x2 -= diff;
*xb -= (diff * xsw) / xdw;
}
if (*xa >= *xb) return FALSE;
if (*ya < 0) {
diff = (((-*ya) * ydw) + ysw - 1) / ysw;
dst->y1 += diff;
*ya += (diff * ysw) / ydw;
}
delta = *yb - (height << 16);
if (delta > 0) {
diff = ((delta * ydw) + ysw - 1) / ysw;
dst->y2 -= diff;
*yb -= (diff * ysw) / ydw;
}
if (*ya >= *yb) return FALSE;
if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) ||
(dst->y1 > extents->y1) || (dst->y2 < extents->y2))
{
RegionRec clipReg;
RegionInit(&clipReg, dst, 1);
RegionIntersect(reg, reg, &clipReg);
RegionUninit(&clipReg);
}
return TRUE;
}
void
xf86XVCopyYUV12ToPacked(
const void *srcy,
const void *srcv,
const void *srcu,
void *dst,
int srcPitchy,
int srcPitchuv,
int dstPitch,
int h,
int w
){
CARD32 *Dst;
const CARD8 *Y, *U, *V;
int i, j;
w >>= 1;
for (j = 0; j < h; j++) {
Dst = dst;
Y = srcy; V = srcv; U = srcu;
i = w;
while (i >= 4) {
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24);
Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24);
Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24);
#else
Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1];
Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2];
Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3];
#endif
Dst += 4; Y += 8; V += 4; U += 4;
i -= 4;
}
while (i--) {
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
#else
Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
#endif
Dst++; Y += 2; V++; U++;
}
dst = (CARD8 *)dst + dstPitch;
srcy = (const CARD8 *)srcy + srcPitchy;
if (j & 1) {
srcu = (const CARD8 *)srcu + srcPitchuv;
srcv = (const CARD8 *)srcv + srcPitchuv;
}
}
}
void
xf86XVCopyPacked(
const void *src,
void *dst,
int srcPitch,
int dstPitch,
int h,
int w
){
const CARD32 *Src;
CARD32 *Dst;
int i;
w >>= 1;
while (--h >= 0) {
do {
Dst = dst; Src = src;
i = w;
while (i >= 4) {
Dst[0] = Src[0];
Dst[1] = Src[1];
Dst[2] = Src[2];
Dst[3] = Src[3];
Dst += 4; Src += 4; i -= 4;
}
if (!i) break;
Dst[0] = Src[0];
if (i == 1) break;
Dst[1] = Src[1];
if (i == 2) break;
Dst[2] = Src[2];
} while (0);
src = (const CARD8 *)src + srcPitch;
dst = (CARD8 *)dst + dstPitch;
}
}