1374 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1374 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 | 
						|
   XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
 | 
						|
   Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
 | 
						|
 | 
						|
   Copyright (C) 2000, 2001 - Nokia Home Communications
 | 
						|
   Copyright (C) 1998, 1999 - The XFree86 Project Inc.
 | 
						|
 | 
						|
All rights reserved.
 | 
						|
 | 
						|
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, and/or sell copies of the Software, and to permit persons
 | 
						|
to whom the Software is furnished to do so, provided that the above
 | 
						|
copyright notice(s) and this permission notice appear in all copies of
 | 
						|
the Software and that both the above copyright notice(s) and this
 | 
						|
permission notice appear in supporting documentation.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
						|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
 | 
						|
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 | 
						|
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
 | 
						|
SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
 | 
						|
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
 | 
						|
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 | 
						|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of a copyright holder
 | 
						|
shall not be used in advertising or otherwise to promote the sale, use
 | 
						|
or other dealings in this Software without prior written authorization
 | 
						|
of the copyright holder.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
#include "kdrive.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 "kxv.h"
 | 
						|
#include "fourcc.h"
 | 
						|
 | 
						|
/* XvAdaptorRec fields */
 | 
						|
 | 
						|
static int KdXVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
 | 
						|
                        INT16, INT16, CARD16, CARD16,
 | 
						|
                        INT16, INT16, CARD16, CARD16);
 | 
						|
static int KdXVPutStill(DrawablePtr, XvPortPtr, GCPtr,
 | 
						|
                        INT16, INT16, CARD16, CARD16,
 | 
						|
                        INT16, INT16, CARD16, CARD16);
 | 
						|
static int KdXVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
 | 
						|
                        INT16, INT16, CARD16, CARD16,
 | 
						|
                        INT16, INT16, CARD16, CARD16);
 | 
						|
static int KdXVGetStill(DrawablePtr, XvPortPtr, GCPtr,
 | 
						|
                        INT16, INT16, CARD16, CARD16,
 | 
						|
                        INT16, INT16, CARD16, CARD16);
 | 
						|
static int KdXVStopVideo(XvPortPtr, DrawablePtr);
 | 
						|
static int KdXVSetPortAttribute(XvPortPtr, Atom, INT32);
 | 
						|
static int KdXVGetPortAttribute(XvPortPtr, Atom, INT32 *);
 | 
						|
static int KdXVQueryBestSize(XvPortPtr, CARD8,
 | 
						|
                             CARD16, CARD16, CARD16, CARD16,
 | 
						|
                             unsigned int *, unsigned int *);
 | 
						|
static int KdXVPutImage(DrawablePtr, XvPortPtr, GCPtr,
 | 
						|
                        INT16, INT16, CARD16, CARD16,
 | 
						|
                        INT16, INT16, CARD16, CARD16,
 | 
						|
                        XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
 | 
						|
static int KdXVQueryImageAttributes(XvPortPtr, XvImagePtr,
 | 
						|
                                    CARD16 *, CARD16 *, int *, int *);
 | 
						|
 | 
						|
/* ScreenRec fields */
 | 
						|
 | 
						|
static Bool KdXVDestroyWindow(WindowPtr pWin);
 | 
						|
static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1);
 | 
						|
static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
 | 
						|
static Bool KdXVCloseScreen(ScreenPtr);
 | 
						|
 | 
						|
/* misc */
 | 
						|
static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int);
 | 
						|
 | 
						|
static DevPrivateKeyRec KdXVWindowKeyRec;
 | 
						|
 | 
						|
#define KdXVWindowKey (&KdXVWindowKeyRec)
 | 
						|
static DevPrivateKey KdXvScreenKey;
 | 
						|
static DevPrivateKeyRec KdXVScreenPrivateKey;
 | 
						|
static unsigned long KdXVGeneration = 0;
 | 
						|
static unsigned long PortResource = 0;
 | 
						|
 | 
						|
#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \
 | 
						|
    dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey))
 | 
						|
 | 
						|
#define GET_KDXV_SCREEN(pScreen) \
 | 
						|
    ((KdXVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey)))
 | 
						|
 | 
						|
#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
 | 
						|
    dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
 | 
						|
 | 
						|
Bool
 | 
						|
KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr adaptors, int num)
 | 
						|
{
 | 
						|
    KdXVScreenPtr ScreenPriv;
 | 
						|
 | 
						|
/*   fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
 | 
						|
 | 
						|
    if (KdXVGeneration != serverGeneration)
 | 
						|
        KdXVGeneration = serverGeneration;
 | 
						|
 | 
						|
    if (noXvExtension)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&KdXVWindowKeyRec, PRIVATE_WINDOW, 0))
 | 
						|
        return FALSE;
 | 
						|
    if (!dixRegisterPrivateKey(&KdXVScreenPrivateKey, PRIVATE_SCREEN, 0))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (Success != XvScreenInit(pScreen))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    KdXvScreenKey = XvGetScreenKey();
 | 
						|
    PortResource = XvGetRTPort();
 | 
						|
 | 
						|
    ScreenPriv = malloc(sizeof(KdXVScreenRec));
 | 
						|
    dixSetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey, ScreenPriv);
 | 
						|
 | 
						|
    if (!ScreenPriv)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
 | 
						|
    ScreenPriv->WindowExposures = pScreen->WindowExposures;
 | 
						|
    ScreenPriv->ClipNotify = pScreen->ClipNotify;
 | 
						|
    ScreenPriv->CloseScreen = pScreen->CloseScreen;
 | 
						|
 | 
						|
/*   fprintf(stderr,"XV: Wrapping screen funcs\n"); */
 | 
						|
 | 
						|
    pScreen->DestroyWindow = KdXVDestroyWindow;
 | 
						|
    pScreen->WindowExposures = KdXVWindowExposures;
 | 
						|
    pScreen->ClipNotify = KdXVClipNotify;
 | 
						|
    pScreen->CloseScreen = KdXVCloseScreen;
 | 
						|
 | 
						|
    if (!KdXVInitAdaptors(pScreen, adaptors, num))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    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);
 | 
						|
                free(pPriv);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    XvFreeAdaptor(pAdaptor);
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr infoPtr, int number)
 | 
						|
{
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
 | 
						|
    XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
 | 
						|
    KdVideoAdaptorPtr adaptorPtr;
 | 
						|
    XvAdaptorPtr pAdaptor, pa;
 | 
						|
    XvAdaptorRecPrivatePtr adaptorPriv;
 | 
						|
    int na, numAdaptor;
 | 
						|
    XvPortRecPrivatePtr portPriv;
 | 
						|
    XvPortPtr pPort, pp;
 | 
						|
    int numPort;
 | 
						|
    KdVideoFormatPtr formatPtr;
 | 
						|
    XvFormatPtr pFormat, pf;
 | 
						|
    int numFormat, totFormat;
 | 
						|
    KdVideoEncodingPtr encodingPtr;
 | 
						|
    XvEncodingPtr pEncode, pe;
 | 
						|
    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;
 | 
						|
 | 
						|
        /* client libs expect at least one encoding */
 | 
						|
        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->ddPutVideo = KdXVPutVideo;
 | 
						|
        pa->ddPutStill = KdXVPutStill;
 | 
						|
        pa->ddGetVideo = KdXVGetVideo;
 | 
						|
        pa->ddGetStill = KdXVGetStill;
 | 
						|
        pa->ddStopVideo = KdXVStopVideo;
 | 
						|
        pa->ddPutImage = KdXVPutImage;
 | 
						|
        pa->ddSetPortAttribute = KdXVSetPortAttribute;
 | 
						|
        pa->ddGetPortAttribute = KdXVGetPortAttribute;
 | 
						|
        pa->ddQueryBestSize = KdXVQueryBestSize;
 | 
						|
        pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
 | 
						|
        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 &&
 | 
						|
            (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
 | 
						|
            memcpy(pa->pImages, adaptorPtr->pImages,
 | 
						|
                   adaptorPtr->nImages * sizeof(XvImageRec));
 | 
						|
            pa->nImages = adaptorPtr->nImages;
 | 
						|
        }
 | 
						|
 | 
						|
        if (adaptorPtr->nAttributes &&
 | 
						|
            (pa->pAttributes = calloc(adaptorPtr->nAttributes,
 | 
						|
                                      sizeof(XvAttributeRec)))) {
 | 
						|
            memcpy(pa->pAttributes, adaptorPtr->pAttributes,
 | 
						|
                   adaptorPtr->nAttributes * sizeof(XvAttributeRec));
 | 
						|
 | 
						|
            for (i = 0; i < adaptorPtr->nAttributes; i++) {
 | 
						|
                pa->pAttributes[i].name =
 | 
						|
                    strdup(adaptorPtr->pAttributes[i].name);
 | 
						|
            }
 | 
						|
 | 
						|
            pa->nAttributes = adaptorPtr->nAttributes;
 | 
						|
        }
 | 
						|
 | 
						|
        totFormat = adaptorPtr->nFormats;
 | 
						|
 | 
						|
        if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
 | 
						|
            KdXVFreeAdaptor(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 = reallocarray(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) {
 | 
						|
            KdXVFreeAdaptor(pa);
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
 | 
						|
            KdXVFreeAdaptor(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 = (void *) adaptorPriv;
 | 
						|
 | 
						|
        if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
 | 
						|
            KdXVFreeAdaptor(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->screen = screen;
 | 
						|
            portPriv->AdaptorRec = adaptorPriv;
 | 
						|
            portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
 | 
						|
 | 
						|
            pp++;
 | 
						|
            numPort++;
 | 
						|
        }
 | 
						|
        pa->nPorts = numPort;
 | 
						|
        pa->pPorts = pPort;
 | 
						|
        if (!numPort) {
 | 
						|
            KdXVFreeAdaptor(pa);
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
 | 
						|
        pa->base_id = pPort->id;
 | 
						|
 | 
						|
        pa++;
 | 
						|
        numAdaptor++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (numAdaptor) {
 | 
						|
        pxvs->nAdaptors = numAdaptor;
 | 
						|
        pxvs->pAdaptors = pAdaptor;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        free(pAdaptor);
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* Video should be clipped to the intersection of the window cliplist
 | 
						|
   and the client cliplist specified in the GC for which the video was
 | 
						|
   initialized.  When we need to reclip a window, the GC that started
 | 
						|
   the video may not even be around anymore.  That's why we save the
 | 
						|
   client clip from the GC when the video is initialized.  We then
 | 
						|
   use KdXVUpdateCompositeClip to calculate the new composite clip
 | 
						|
   when we need it.  This is different from what DEC did.  They saved
 | 
						|
   the GC and used it's clip list when they needed to reclip the window,
 | 
						|
   even if the client clip was different from the one the video was
 | 
						|
   initialized with.  If the original GC was destroyed, they had to stop
 | 
						|
   the video.  I like the new method better (MArk).
 | 
						|
 | 
						|
   This function only works for windows.  Will need to rewrite when
 | 
						|
   (if) we support pixmap rendering.
 | 
						|
*/
 | 
						|
 | 
						|
static void
 | 
						|
KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
 | 
						|
{
 | 
						|
    RegionPtr pregWin, pCompositeClip;
 | 
						|
    WindowPtr pWin;
 | 
						|
    Bool freeCompClip = FALSE;
 | 
						|
 | 
						|
    if (portPriv->pCompositeClip)
 | 
						|
        return;
 | 
						|
 | 
						|
    pWin = (WindowPtr) portPriv->pDraw;
 | 
						|
 | 
						|
    /* get window clip list */
 | 
						|
    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->clipOrg.x,
 | 
						|
                    portPriv->pDraw->y + portPriv->clipOrg.y);
 | 
						|
    RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
 | 
						|
 | 
						|
    portPriv->pCompositeClip = pCompositeClip;
 | 
						|
    portPriv->FreeCompositeClip = TRUE;
 | 
						|
 | 
						|
    if (freeCompClip) {
 | 
						|
        RegionDestroy(pregWin);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* Save the current clientClip and update the CompositeClip whenever
 | 
						|
   we have a fresh GC */
 | 
						|
 | 
						|
static void
 | 
						|
KdXVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
 | 
						|
{
 | 
						|
    /* copy the new clip if it exists */
 | 
						|
    if (pGC->clientClip) {
 | 
						|
        if (!portPriv->clientClip)
 | 
						|
            portPriv->clientClip = RegionCreate(NullBox, 1);
 | 
						|
        /* Note: this is in window coordinates */
 | 
						|
        RegionCopy(portPriv->clientClip, pGC->clientClip);
 | 
						|
    }
 | 
						|
    else if (portPriv->clientClip) {    /* free the old clientClip */
 | 
						|
        RegionDestroy(portPriv->clientClip);
 | 
						|
        portPriv->clientClip = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* get rid of the old clip list */
 | 
						|
    if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
 | 
						|
        RegionDestroy(portPriv->pCompositeClip);
 | 
						|
    }
 | 
						|
 | 
						|
    portPriv->clipOrg = pGC->clipOrg;
 | 
						|
    portPriv->pCompositeClip = pGC->pCompositeClip;
 | 
						|
    portPriv->FreeCompositeClip = FALSE;
 | 
						|
    portPriv->subWindowMode = pGC->subWindowMode;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVRegetVideo(XvPortRecPrivatePtr portPriv)
 | 
						|
{
 | 
						|
    RegionRec WinRegion;
 | 
						|
    RegionRec ClipRegion;
 | 
						|
    BoxRec WinBox;
 | 
						|
    int ret = Success;
 | 
						|
    Bool clippedAway = FALSE;
 | 
						|
 | 
						|
    KdXVUpdateCompositeClip(portPriv);
 | 
						|
 | 
						|
    /* translate the video region to the screen */
 | 
						|
    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;
 | 
						|
 | 
						|
    /* clip to the window composite clip */
 | 
						|
    RegionInit(&WinRegion, &WinBox, 1);
 | 
						|
    RegionInit(&ClipRegion, NullBox, 1);
 | 
						|
    RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
 | 
						|
 | 
						|
    /* that's all if it's totally obscured */
 | 
						|
    if (!RegionNotEmpty(&ClipRegion)) {
 | 
						|
        clippedAway = TRUE;
 | 
						|
        goto CLIP_VIDEO_BAILOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->screen, portPriv->pDraw,
 | 
						|
                                             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);
 | 
						|
 | 
						|
    if (ret == Success)
 | 
						|
        portPriv->isOn = XV_ON;
 | 
						|
 | 
						|
 CLIP_VIDEO_BAILOUT:
 | 
						|
 | 
						|
    if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, FALSE);
 | 
						|
        portPriv->isOn = XV_PENDING;
 | 
						|
    }
 | 
						|
 | 
						|
    /* This clip was copied and only good for one shot */
 | 
						|
    if (!portPriv->FreeCompositeClip)
 | 
						|
        portPriv->pCompositeClip = NULL;
 | 
						|
 | 
						|
    RegionUninit(&WinRegion);
 | 
						|
    RegionUninit(&ClipRegion);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVReputVideo(XvPortRecPrivatePtr portPriv)
 | 
						|
{
 | 
						|
    RegionRec WinRegion;
 | 
						|
    RegionRec ClipRegion;
 | 
						|
    BoxRec WinBox;
 | 
						|
    ScreenPtr pScreen = portPriv->pDraw->pScreen;
 | 
						|
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    int ret = Success;
 | 
						|
    Bool clippedAway = FALSE;
 | 
						|
 | 
						|
    KdXVUpdateCompositeClip(portPriv);
 | 
						|
 | 
						|
    /* translate the video region to the screen */
 | 
						|
    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;
 | 
						|
 | 
						|
    /* clip to the window composite clip */
 | 
						|
    RegionInit(&WinRegion, &WinBox, 1);
 | 
						|
    RegionInit(&ClipRegion, NullBox, 1);
 | 
						|
    RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
 | 
						|
 | 
						|
    /* clip and translate to the viewport */
 | 
						|
    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
 | 
						|
        RegionRec VPReg;
 | 
						|
        BoxRec VPBox;
 | 
						|
 | 
						|
        VPBox.x1 = 0;
 | 
						|
        VPBox.y1 = 0;
 | 
						|
        VPBox.x2 = screen->width;
 | 
						|
        VPBox.y2 = screen->height;
 | 
						|
 | 
						|
        RegionInit(&VPReg, &VPBox, 1);
 | 
						|
        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
 | 
						|
        RegionUninit(&VPReg);
 | 
						|
    }
 | 
						|
 | 
						|
    /* that's all if it's totally obscured */
 | 
						|
    if (!RegionNotEmpty(&ClipRegion)) {
 | 
						|
        clippedAway = TRUE;
 | 
						|
        goto CLIP_VIDEO_BAILOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->screen, portPriv->pDraw,
 | 
						|
                                             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);
 | 
						|
 | 
						|
    if (ret == Success)
 | 
						|
        portPriv->isOn = XV_ON;
 | 
						|
 | 
						|
 CLIP_VIDEO_BAILOUT:
 | 
						|
 | 
						|
    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, FALSE);
 | 
						|
        portPriv->isOn = XV_PENDING;
 | 
						|
    }
 | 
						|
 | 
						|
    /* This clip was copied and only good for one shot */
 | 
						|
    if (!portPriv->FreeCompositeClip)
 | 
						|
        portPriv->pCompositeClip = NULL;
 | 
						|
 | 
						|
    RegionUninit(&WinRegion);
 | 
						|
    RegionUninit(&ClipRegion);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVReputImage(XvPortRecPrivatePtr portPriv)
 | 
						|
{
 | 
						|
    RegionRec WinRegion;
 | 
						|
    RegionRec ClipRegion;
 | 
						|
    BoxRec WinBox;
 | 
						|
    ScreenPtr pScreen = portPriv->pDraw->pScreen;
 | 
						|
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    int ret = Success;
 | 
						|
    Bool clippedAway = FALSE;
 | 
						|
 | 
						|
    KdXVUpdateCompositeClip(portPriv);
 | 
						|
 | 
						|
    /* translate the video region to the screen */
 | 
						|
    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;
 | 
						|
 | 
						|
    /* clip to the window composite clip */
 | 
						|
    RegionInit(&WinRegion, &WinBox, 1);
 | 
						|
    RegionInit(&ClipRegion, NullBox, 1);
 | 
						|
    RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
 | 
						|
 | 
						|
    /* clip and translate to the viewport */
 | 
						|
    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
 | 
						|
        RegionRec VPReg;
 | 
						|
        BoxRec VPBox;
 | 
						|
 | 
						|
        VPBox.x1 = 0;
 | 
						|
        VPBox.y1 = 0;
 | 
						|
        VPBox.x2 = screen->width;
 | 
						|
        VPBox.y2 = screen->height;
 | 
						|
 | 
						|
        RegionInit(&VPReg, &VPBox, 1);
 | 
						|
        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
 | 
						|
        RegionUninit(&VPReg);
 | 
						|
    }
 | 
						|
 | 
						|
    /* that's all if it's totally obscured */
 | 
						|
    if (!RegionNotEmpty(&ClipRegion)) {
 | 
						|
        clippedAway = TRUE;
 | 
						|
        goto CLIP_VIDEO_BAILOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    ret =
 | 
						|
        (*portPriv->AdaptorRec->ReputImage) (portPriv->screen, portPriv->pDraw,
 | 
						|
                                             WinBox.x1, WinBox.y1, &ClipRegion,
 | 
						|
                                             portPriv->DevPriv.ptr);
 | 
						|
 | 
						|
    portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
 | 
						|
 | 
						|
 CLIP_VIDEO_BAILOUT:
 | 
						|
 | 
						|
    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, FALSE);
 | 
						|
        portPriv->isOn = XV_PENDING;
 | 
						|
    }
 | 
						|
 | 
						|
    /* This clip was copied and only good for one shot */
 | 
						|
    if (!portPriv->FreeCompositeClip)
 | 
						|
        portPriv->pCompositeClip = NULL;
 | 
						|
 | 
						|
    RegionUninit(&WinRegion);
 | 
						|
    RegionUninit(&ClipRegion);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
 | 
						|
{
 | 
						|
    KdXVWindowPtr winPriv, PrivRoot;
 | 
						|
 | 
						|
    winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
 | 
						|
 | 
						|
    /* Enlist our port in the window private */
 | 
						|
    while (winPriv) {
 | 
						|
        if (winPriv->PortRec == portPriv)       /* we're already listed */
 | 
						|
            break;
 | 
						|
        winPriv = winPriv->next;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!winPriv) {
 | 
						|
        winPriv = malloc(sizeof(KdXVWindowRec));
 | 
						|
        if (!winPriv)
 | 
						|
            return BadAlloc;
 | 
						|
        winPriv->PortRec = portPriv;
 | 
						|
        winPriv->next = PrivRoot;
 | 
						|
        dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv);
 | 
						|
    }
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
 | 
						|
{
 | 
						|
    KdXVWindowPtr winPriv, prevPriv = NULL;
 | 
						|
 | 
						|
    winPriv = GET_KDXV_WINDOW(pWin);
 | 
						|
 | 
						|
    while (winPriv) {
 | 
						|
        if (winPriv->PortRec == portPriv) {
 | 
						|
            if (prevPriv)
 | 
						|
                prevPriv->next = winPriv->next;
 | 
						|
            else
 | 
						|
                dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next);
 | 
						|
            free(winPriv);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        prevPriv = winPriv;
 | 
						|
        winPriv = winPriv->next;
 | 
						|
    }
 | 
						|
    portPriv->pDraw = NULL;
 | 
						|
}
 | 
						|
 | 
						|
/****  ScreenRec fields ****/
 | 
						|
 | 
						|
static Bool
 | 
						|
KdXVDestroyWindow(WindowPtr pWin)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
 | 
						|
    KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
 | 
						|
    int ret;
 | 
						|
 | 
						|
    while (WinPriv) {
 | 
						|
        XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
 | 
						|
 | 
						|
        if (pPriv->isOn > XV_OFF) {
 | 
						|
            (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, pPriv->DevPriv.ptr,
 | 
						|
                                             TRUE);
 | 
						|
            pPriv->isOn = XV_OFF;
 | 
						|
        }
 | 
						|
 | 
						|
        pPriv->pDraw = NULL;
 | 
						|
        tmp = WinPriv;
 | 
						|
        WinPriv = WinPriv->next;
 | 
						|
        free(tmp);
 | 
						|
    }
 | 
						|
 | 
						|
    dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
 | 
						|
 | 
						|
    pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
 | 
						|
    ret = (*pScreen->DestroyWindow) (pWin);
 | 
						|
    pScreen->DestroyWindow = KdXVDestroyWindow;
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
 | 
						|
    KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
 | 
						|
    KdXVWindowPtr pPrev;
 | 
						|
    XvPortRecPrivatePtr pPriv;
 | 
						|
    Bool AreasExposed;
 | 
						|
 | 
						|
    AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
 | 
						|
 | 
						|
    pScreen->WindowExposures = ScreenPriv->WindowExposures;
 | 
						|
    (*pScreen->WindowExposures) (pWin, reg1);
 | 
						|
    pScreen->WindowExposures = KdXVWindowExposures;
 | 
						|
 | 
						|
    /* filter out XClearWindow/Area */
 | 
						|
    if (!pWin->valdata)
 | 
						|
        return;
 | 
						|
 | 
						|
    pPrev = NULL;
 | 
						|
 | 
						|
    while (WinPriv) {
 | 
						|
        pPriv = WinPriv->PortRec;
 | 
						|
 | 
						|
        /* Reput anyone with a reput function */
 | 
						|
 | 
						|
        switch (pPriv->type) {
 | 
						|
        case XvInputMask:
 | 
						|
            KdXVReputVideo(pPriv);
 | 
						|
            break;
 | 
						|
        case XvOutputMask:
 | 
						|
            KdXVRegetVideo(pPriv);
 | 
						|
            break;
 | 
						|
        default:               /* overlaid still/image */
 | 
						|
            if (pPriv->AdaptorRec->ReputImage)
 | 
						|
                KdXVReputImage(pPriv);
 | 
						|
            else if (AreasExposed) {
 | 
						|
                KdXVWindowPtr tmp;
 | 
						|
 | 
						|
                if (pPriv->isOn == XV_ON) {
 | 
						|
                    (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
 | 
						|
                                                     pPriv->DevPriv.ptr, FALSE);
 | 
						|
                    pPriv->isOn = XV_PENDING;
 | 
						|
                }
 | 
						|
                pPriv->pDraw = NULL;
 | 
						|
 | 
						|
                if (!pPrev)
 | 
						|
                    dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
 | 
						|
                                  WinPriv->next);
 | 
						|
                else
 | 
						|
                    pPrev->next = WinPriv->next;
 | 
						|
                tmp = WinPriv;
 | 
						|
                WinPriv = WinPriv->next;
 | 
						|
                free(tmp);
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        pPrev = WinPriv;
 | 
						|
        WinPriv = WinPriv->next;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
KdXVClipNotify(WindowPtr pWin, int dx, int dy)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
 | 
						|
    KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
 | 
						|
    KdXVWindowPtr tmp, pPrev = NULL;
 | 
						|
    XvPortRecPrivatePtr pPriv;
 | 
						|
    Bool visible = (pWin->visibility == VisibilityUnobscured) ||
 | 
						|
        (pWin->visibility == VisibilityPartiallyObscured);
 | 
						|
 | 
						|
    while (WinPriv) {
 | 
						|
        pPriv = WinPriv->PortRec;
 | 
						|
 | 
						|
        if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
 | 
						|
            RegionDestroy(pPriv->pCompositeClip);
 | 
						|
 | 
						|
        pPriv->pCompositeClip = NULL;
 | 
						|
 | 
						|
        /* Stop everything except images, but stop them too if the
 | 
						|
           window isn't visible.  But we only remove the images. */
 | 
						|
 | 
						|
        if (pPriv->type || !visible) {
 | 
						|
            if (pPriv->isOn == XV_ON) {
 | 
						|
                (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
 | 
						|
                                                 pPriv->DevPriv.ptr, FALSE);
 | 
						|
                pPriv->isOn = XV_PENDING;
 | 
						|
            }
 | 
						|
 | 
						|
            if (!pPriv->type) { /* overlaid still/image */
 | 
						|
                pPriv->pDraw = NULL;
 | 
						|
 | 
						|
                if (!pPrev)
 | 
						|
                    dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
 | 
						|
                                  WinPriv->next);
 | 
						|
                else
 | 
						|
                    pPrev->next = WinPriv->next;
 | 
						|
                tmp = WinPriv;
 | 
						|
                WinPriv = WinPriv->next;
 | 
						|
                free(tmp);
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        pPrev = WinPriv;
 | 
						|
        WinPriv = WinPriv->next;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ScreenPriv->ClipNotify) {
 | 
						|
        pScreen->ClipNotify = ScreenPriv->ClipNotify;
 | 
						|
        (*pScreen->ClipNotify) (pWin, dx, dy);
 | 
						|
        pScreen->ClipNotify = KdXVClipNotify;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**** Required XvScreenRec fields ****/
 | 
						|
 | 
						|
static Bool
 | 
						|
KdXVCloseScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
 | 
						|
    KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
 | 
						|
    XvAdaptorPtr pa;
 | 
						|
    int c;
 | 
						|
 | 
						|
    if (!ScreenPriv)
 | 
						|
        return TRUE;
 | 
						|
 | 
						|
    pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
 | 
						|
    pScreen->WindowExposures = ScreenPriv->WindowExposures;
 | 
						|
    pScreen->ClipNotify = ScreenPriv->ClipNotify;
 | 
						|
    pScreen->CloseScreen = ScreenPriv->CloseScreen;
 | 
						|
 | 
						|
/*   fprintf(stderr,"XV: Unwrapping screen funcs\n"); */
 | 
						|
 | 
						|
    for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
 | 
						|
        KdXVFreeAdaptor(pa);
 | 
						|
    }
 | 
						|
 | 
						|
    free(pxvs->pAdaptors);
 | 
						|
    free(ScreenPriv);
 | 
						|
 | 
						|
    return pScreen->CloseScreen(pScreen);
 | 
						|
}
 | 
						|
 | 
						|
/**** XvAdaptorRec fields ****/
 | 
						|
 | 
						|
static int
 | 
						|
KdXVPutVideo(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);
 | 
						|
 | 
						|
    KdScreenPriv(portPriv->screen->pScreen);
 | 
						|
    int result;
 | 
						|
 | 
						|
    /* No dumping video to pixmaps... For now anyhow */
 | 
						|
    if (pDraw->type != DRAWABLE_WINDOW) {
 | 
						|
        pPort->pDraw = (DrawablePtr) NULL;
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
    /* If we are changing windows, unregister our port in the old window */
 | 
						|
    if (portPriv->pDraw && (portPriv->pDraw != pDraw))
 | 
						|
        KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
 | 
						|
 | 
						|
    /* Register our port with the new window */
 | 
						|
    result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
 | 
						|
    if (result != Success)
 | 
						|
        return result;
 | 
						|
 | 
						|
    portPriv->pDraw = pDraw;
 | 
						|
    portPriv->type = XvInputMask;
 | 
						|
 | 
						|
    /* save a copy of these parameters */
 | 
						|
    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;
 | 
						|
 | 
						|
    /* make sure we have the most recent copy of the clientClip */
 | 
						|
    KdXVCopyClip(portPriv, pGC);
 | 
						|
 | 
						|
    /* To indicate to the DI layer that we were successful */
 | 
						|
    pPort->pDraw = pDraw;
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        return Success;
 | 
						|
 | 
						|
    return (KdXVReputVideo(portPriv));
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVPutStill(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);
 | 
						|
    ScreenPtr pScreen = pDraw->pScreen;
 | 
						|
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    KdScreenInfo *screen = pScreenPriv->screen;
 | 
						|
    RegionRec WinRegion;
 | 
						|
    RegionRec ClipRegion;
 | 
						|
    BoxRec WinBox;
 | 
						|
    int ret = Success;
 | 
						|
    Bool clippedAway = FALSE;
 | 
						|
 | 
						|
    if (pDraw->type != DRAWABLE_WINDOW)
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        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);
 | 
						|
    RegionInit(&ClipRegion, NullBox, 1);
 | 
						|
    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
 | 
						|
 | 
						|
    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
 | 
						|
        RegionRec VPReg;
 | 
						|
        BoxRec VPBox;
 | 
						|
 | 
						|
        VPBox.x1 = 0;
 | 
						|
        VPBox.y1 = 0;
 | 
						|
        VPBox.x2 = screen->width;
 | 
						|
        VPBox.y2 = screen->height;
 | 
						|
 | 
						|
        RegionInit(&VPReg, &VPBox, 1);
 | 
						|
        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
 | 
						|
        RegionUninit(&VPReg);
 | 
						|
    }
 | 
						|
 | 
						|
    if (portPriv->pDraw) {
 | 
						|
        KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!RegionNotEmpty(&ClipRegion)) {
 | 
						|
        clippedAway = TRUE;
 | 
						|
        goto PUT_STILL_BAILOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*portPriv->AdaptorRec->PutStill) (portPriv->screen, pDraw,
 | 
						|
                                             vid_x, vid_y, WinBox.x1, WinBox.y1,
 | 
						|
                                             vid_w, vid_h, drw_w, drw_h,
 | 
						|
                                             &ClipRegion,
 | 
						|
                                             portPriv->DevPriv.ptr);
 | 
						|
 | 
						|
    if ((ret == Success) &&
 | 
						|
        (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
 | 
						|
 | 
						|
        KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
 | 
						|
        portPriv->isOn = XV_ON;
 | 
						|
        portPriv->pDraw = pDraw;
 | 
						|
        portPriv->drw_x = drw_x;
 | 
						|
        portPriv->drw_y = drw_y;
 | 
						|
        portPriv->drw_w = drw_w;
 | 
						|
        portPriv->drw_h = drw_h;
 | 
						|
        portPriv->type = 0;     /* no mask means it's transient and should
 | 
						|
                                   not be reput once it's removed */
 | 
						|
        pPort->pDraw = pDraw;   /* make sure we can get stop requests */
 | 
						|
    }
 | 
						|
 | 
						|
 PUT_STILL_BAILOUT:
 | 
						|
 | 
						|
    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, FALSE);
 | 
						|
        portPriv->isOn = XV_PENDING;
 | 
						|
    }
 | 
						|
 | 
						|
    RegionUninit(&WinRegion);
 | 
						|
    RegionUninit(&ClipRegion);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVGetVideo(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;
 | 
						|
 | 
						|
    KdScreenPriv(portPriv->screen->pScreen);
 | 
						|
 | 
						|
    /* No pixmaps... For now anyhow */
 | 
						|
    if (pDraw->type != DRAWABLE_WINDOW) {
 | 
						|
        pPort->pDraw = (DrawablePtr) NULL;
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
    /* If we are changing windows, unregister our port in the old window */
 | 
						|
    if (portPriv->pDraw && (portPriv->pDraw != pDraw))
 | 
						|
        KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
 | 
						|
 | 
						|
    /* Register our port with the new window */
 | 
						|
    result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
 | 
						|
    if (result != Success)
 | 
						|
        return result;
 | 
						|
 | 
						|
    portPriv->pDraw = pDraw;
 | 
						|
    portPriv->type = XvOutputMask;
 | 
						|
 | 
						|
    /* save a copy of these parameters */
 | 
						|
    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;
 | 
						|
 | 
						|
    /* make sure we have the most recent copy of the clientClip */
 | 
						|
    KdXVCopyClip(portPriv, pGC);
 | 
						|
 | 
						|
    /* To indicate to the DI layer that we were successful */
 | 
						|
    pPort->pDraw = pDraw;
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        return Success;
 | 
						|
 | 
						|
    return (KdXVRegetVideo(portPriv));
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVGetStill(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);
 | 
						|
    ScreenPtr pScreen = pDraw->pScreen;
 | 
						|
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    RegionRec WinRegion;
 | 
						|
    RegionRec ClipRegion;
 | 
						|
    BoxRec WinBox;
 | 
						|
    int ret = Success;
 | 
						|
    Bool clippedAway = FALSE;
 | 
						|
 | 
						|
    if (pDraw->type != DRAWABLE_WINDOW)
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        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);
 | 
						|
    RegionInit(&ClipRegion, NullBox, 1);
 | 
						|
    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
 | 
						|
 | 
						|
    if (portPriv->pDraw) {
 | 
						|
        KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!RegionNotEmpty(&ClipRegion)) {
 | 
						|
        clippedAway = TRUE;
 | 
						|
        goto GET_STILL_BAILOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*portPriv->AdaptorRec->GetStill) (portPriv->screen, pDraw,
 | 
						|
                                             vid_x, vid_y, WinBox.x1, WinBox.y1,
 | 
						|
                                             vid_w, vid_h, drw_w, drw_h,
 | 
						|
                                             &ClipRegion,
 | 
						|
                                             portPriv->DevPriv.ptr);
 | 
						|
 | 
						|
 GET_STILL_BAILOUT:
 | 
						|
 | 
						|
    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, FALSE);
 | 
						|
        portPriv->isOn = XV_PENDING;
 | 
						|
    }
 | 
						|
 | 
						|
    RegionUninit(&WinRegion);
 | 
						|
    RegionUninit(&ClipRegion);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
 | 
						|
{
 | 
						|
    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
 | 
						|
 | 
						|
    KdScreenPriv(portPriv->screen->pScreen);
 | 
						|
 | 
						|
    if (pDraw->type != DRAWABLE_WINDOW)
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    KdXVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        return Success;
 | 
						|
 | 
						|
    /* Must free resources. */
 | 
						|
 | 
						|
    if (portPriv->isOn > XV_OFF) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, TRUE);
 | 
						|
        portPriv->isOn = XV_OFF;
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
 | 
						|
{
 | 
						|
    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
 | 
						|
 | 
						|
    return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->screen,
 | 
						|
                                                       attribute, value,
 | 
						|
                                                       portPriv->DevPriv.ptr));
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
 | 
						|
{
 | 
						|
    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
 | 
						|
 | 
						|
    return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->screen,
 | 
						|
                                                       attribute,
 | 
						|
                                                       (int *) p_value,
 | 
						|
                                                       portPriv->DevPriv.ptr));
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVQueryBestSize(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->screen,
 | 
						|
                                            (Bool) motion, vid_w, vid_h, drw_w,
 | 
						|
                                            drw_h, p_w, p_h,
 | 
						|
                                            portPriv->DevPriv.ptr);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVPutImage(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);
 | 
						|
    ScreenPtr pScreen = pDraw->pScreen;
 | 
						|
 | 
						|
    KdScreenPriv(pScreen);
 | 
						|
    RegionRec WinRegion;
 | 
						|
    RegionRec ClipRegion;
 | 
						|
    BoxRec WinBox;
 | 
						|
    int ret = Success;
 | 
						|
    Bool clippedAway = FALSE;
 | 
						|
 | 
						|
    if (pDraw->type != DRAWABLE_WINDOW)
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    if (!pScreenPriv->enabled)
 | 
						|
        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);
 | 
						|
    RegionInit(&ClipRegion, NullBox, 1);
 | 
						|
    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
 | 
						|
 | 
						|
    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
 | 
						|
        RegionRec VPReg;
 | 
						|
        BoxRec VPBox;
 | 
						|
 | 
						|
        VPBox.x1 = 0;
 | 
						|
        VPBox.y1 = 0;
 | 
						|
        VPBox.x2 = pScreen->width;
 | 
						|
        VPBox.y2 = pScreen->height;
 | 
						|
 | 
						|
        RegionInit(&VPReg, &VPBox, 1);
 | 
						|
        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
 | 
						|
        RegionUninit(&VPReg);
 | 
						|
    }
 | 
						|
 | 
						|
    if (portPriv->pDraw) {
 | 
						|
        KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!RegionNotEmpty(&ClipRegion)) {
 | 
						|
        clippedAway = TRUE;
 | 
						|
        goto PUT_IMAGE_BAILOUT;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*portPriv->AdaptorRec->PutImage) (portPriv->screen, pDraw,
 | 
						|
                                             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);
 | 
						|
 | 
						|
    if ((ret == Success) &&
 | 
						|
        (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
 | 
						|
 | 
						|
        KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
 | 
						|
        portPriv->isOn = XV_ON;
 | 
						|
        portPriv->pDraw = pDraw;
 | 
						|
        portPriv->drw_x = drw_x;
 | 
						|
        portPriv->drw_y = drw_y;
 | 
						|
        portPriv->drw_w = drw_w;
 | 
						|
        portPriv->drw_h = drw_h;
 | 
						|
        portPriv->type = 0;     /* no mask means it's transient and should
 | 
						|
                                   not be reput once it's removed */
 | 
						|
        pPort->pDraw = pDraw;   /* make sure we can get stop requests */
 | 
						|
    }
 | 
						|
 | 
						|
 PUT_IMAGE_BAILOUT:
 | 
						|
 | 
						|
    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
 | 
						|
        (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
 | 
						|
                                            portPriv->DevPriv.ptr, FALSE);
 | 
						|
        portPriv->isOn = XV_PENDING;
 | 
						|
    }
 | 
						|
 | 
						|
    RegionUninit(&WinRegion);
 | 
						|
    RegionUninit(&ClipRegion);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
KdXVQueryImageAttributes(XvPortPtr pPort,
 | 
						|
                         XvImagePtr format,
 | 
						|
                         CARD16 *width,
 | 
						|
                         CARD16 *height, int *pitches, int *offsets)
 | 
						|
{
 | 
						|
    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
 | 
						|
 | 
						|
    return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->screen,
 | 
						|
                                                          format->id, width,
 | 
						|
                                                          height, pitches,
 | 
						|
                                                          offsets);
 | 
						|
}
 |