xref: /OK3568_Linux_fs/external/xserver/Xext/xvmain.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3*4882a593Smuzhiyun and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun                         All Rights Reserved
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
8*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
9*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
10*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
11*4882a593Smuzhiyun supporting documentation, and that the names of Digital or MIT not be
12*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
13*4882a593Smuzhiyun software without specific, written prior permission.
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21*4882a593Smuzhiyun SOFTWARE.
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun ******************************************************************/
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun ** File:
27*4882a593Smuzhiyun **
28*4882a593Smuzhiyun **   xvmain.c --- Xv server extension main device independent module.
29*4882a593Smuzhiyun **
30*4882a593Smuzhiyun ** Author:
31*4882a593Smuzhiyun **
32*4882a593Smuzhiyun **   David Carver (Digital Workstation Engineering/Project Athena)
33*4882a593Smuzhiyun **
34*4882a593Smuzhiyun ** Revisions:
35*4882a593Smuzhiyun **
36*4882a593Smuzhiyun **   04.09.91 Carver
37*4882a593Smuzhiyun **     - change: stop video always generates an event even when video
38*4882a593Smuzhiyun **       wasn't active
39*4882a593Smuzhiyun **
40*4882a593Smuzhiyun **   29.08.91 Carver
41*4882a593Smuzhiyun **     - change: unrealizing windows no longer preempts video
42*4882a593Smuzhiyun **
43*4882a593Smuzhiyun **   11.06.91 Carver
44*4882a593Smuzhiyun **     - changed SetPortControl to SetPortAttribute
45*4882a593Smuzhiyun **     - changed GetPortControl to GetPortAttribute
46*4882a593Smuzhiyun **     - changed QueryBestSize
47*4882a593Smuzhiyun **
48*4882a593Smuzhiyun **   28.05.91 Carver
49*4882a593Smuzhiyun **     - fixed Put and Get requests to not preempt operations to same drawable
50*4882a593Smuzhiyun **
51*4882a593Smuzhiyun **   15.05.91 Carver
52*4882a593Smuzhiyun **     - version 2.0 upgrade
53*4882a593Smuzhiyun **
54*4882a593Smuzhiyun **   19.03.91 Carver
55*4882a593Smuzhiyun **     - fixed Put and Get requests to honor grabbed ports.
56*4882a593Smuzhiyun **     - fixed Video requests to update di structure with new drawable, and
57*4882a593Smuzhiyun **       client after calling ddx.
58*4882a593Smuzhiyun **
59*4882a593Smuzhiyun **   24.01.91 Carver
60*4882a593Smuzhiyun **     - version 1.4 upgrade
61*4882a593Smuzhiyun **
62*4882a593Smuzhiyun ** Notes:
63*4882a593Smuzhiyun **
64*4882a593Smuzhiyun **   Port structures reference client structures in a two different
65*4882a593Smuzhiyun **   ways: when grabs, or video is active.  Each reference is encoded
66*4882a593Smuzhiyun **   as fake client resources and thus when the client is goes away so
67*4882a593Smuzhiyun **   does the reference (it is zeroed).  No other action is taken, so
68*4882a593Smuzhiyun **   video doesn't necessarily stop.  It probably will as a result of
69*4882a593Smuzhiyun **   other resources going away, but if a client starts video using
70*4882a593Smuzhiyun **   none of its own resources, then the video will continue to play
71*4882a593Smuzhiyun **   after the client disappears.
72*4882a593Smuzhiyun **
73*4882a593Smuzhiyun **
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
77*4882a593Smuzhiyun #include <dix-config.h>
78*4882a593Smuzhiyun #endif
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #include <string.h>
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun #include <X11/X.h>
83*4882a593Smuzhiyun #include <X11/Xproto.h>
84*4882a593Smuzhiyun #include "misc.h"
85*4882a593Smuzhiyun #include "os.h"
86*4882a593Smuzhiyun #include "scrnintstr.h"
87*4882a593Smuzhiyun #include "windowstr.h"
88*4882a593Smuzhiyun #include "pixmapstr.h"
89*4882a593Smuzhiyun #include "gcstruct.h"
90*4882a593Smuzhiyun #include "extnsionst.h"
91*4882a593Smuzhiyun #include "extinit.h"
92*4882a593Smuzhiyun #include "dixstruct.h"
93*4882a593Smuzhiyun #include "resource.h"
94*4882a593Smuzhiyun #include "opaque.h"
95*4882a593Smuzhiyun #include "input.h"
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun #define GLOBAL
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #include <X11/extensions/Xv.h>
100*4882a593Smuzhiyun #include <X11/extensions/Xvproto.h>
101*4882a593Smuzhiyun #include "xvdix.h"
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #ifdef PANORAMIX
104*4882a593Smuzhiyun #include "panoramiX.h"
105*4882a593Smuzhiyun #include "panoramiXsrv.h"
106*4882a593Smuzhiyun #endif
107*4882a593Smuzhiyun #include "xvdisp.h"
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun static DevPrivateKeyRec XvScreenKeyRec;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define XvScreenKey (&XvScreenKeyRec)
112*4882a593Smuzhiyun unsigned long XvExtensionGeneration = 0;
113*4882a593Smuzhiyun unsigned long XvScreenGeneration = 0;
114*4882a593Smuzhiyun unsigned long XvResourceGeneration = 0;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun int XvReqCode;
117*4882a593Smuzhiyun int XvEventBase;
118*4882a593Smuzhiyun int XvErrorBase;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun RESTYPE XvRTPort;
121*4882a593Smuzhiyun RESTYPE XvRTEncoding;
122*4882a593Smuzhiyun RESTYPE XvRTGrab;
123*4882a593Smuzhiyun RESTYPE XvRTVideoNotify;
124*4882a593Smuzhiyun RESTYPE XvRTVideoNotifyList;
125*4882a593Smuzhiyun RESTYPE XvRTPortNotify;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun /* EXTERNAL */
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
130*4882a593Smuzhiyun static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
131*4882a593Smuzhiyun static Bool CreateResourceTypes(void);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun static Bool XvCloseScreen(ScreenPtr);
134*4882a593Smuzhiyun static Bool XvDestroyPixmap(PixmapPtr);
135*4882a593Smuzhiyun static Bool XvDestroyWindow(WindowPtr);
136*4882a593Smuzhiyun static void XvResetProc(ExtensionEntry *);
137*4882a593Smuzhiyun static int XvdiDestroyGrab(void *, XID);
138*4882a593Smuzhiyun static int XvdiDestroyEncoding(void *, XID);
139*4882a593Smuzhiyun static int XvdiDestroyVideoNotify(void *, XID);
140*4882a593Smuzhiyun static int XvdiDestroyPortNotify(void *, XID);
141*4882a593Smuzhiyun static int XvdiDestroyVideoNotifyList(void *, XID);
142*4882a593Smuzhiyun static int XvdiDestroyPort(void *, XID);
143*4882a593Smuzhiyun static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /*
146*4882a593Smuzhiyun ** XvExtensionInit
147*4882a593Smuzhiyun **
148*4882a593Smuzhiyun **
149*4882a593Smuzhiyun */
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun void
XvExtensionInit(void)152*4882a593Smuzhiyun XvExtensionInit(void)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun     ExtensionEntry *extEntry;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
157*4882a593Smuzhiyun         return;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun     /* Look to see if any screens were initialized; if not then
160*4882a593Smuzhiyun        init global variables so the extension can function */
161*4882a593Smuzhiyun     if (XvScreenGeneration != serverGeneration) {
162*4882a593Smuzhiyun         if (!CreateResourceTypes()) {
163*4882a593Smuzhiyun             ErrorF("XvExtensionInit: Unable to allocate resource types\n");
164*4882a593Smuzhiyun             return;
165*4882a593Smuzhiyun         }
166*4882a593Smuzhiyun #ifdef PANORAMIX
167*4882a593Smuzhiyun         XineramaRegisterConnectionBlockCallback(XineramifyXv);
168*4882a593Smuzhiyun #endif
169*4882a593Smuzhiyun         XvScreenGeneration = serverGeneration;
170*4882a593Smuzhiyun     }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun     if (XvExtensionGeneration != serverGeneration) {
173*4882a593Smuzhiyun         XvExtensionGeneration = serverGeneration;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun         extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
176*4882a593Smuzhiyun                                 ProcXvDispatch, SProcXvDispatch,
177*4882a593Smuzhiyun                                 XvResetProc, StandardMinorOpcode);
178*4882a593Smuzhiyun         if (!extEntry) {
179*4882a593Smuzhiyun             FatalError("XvExtensionInit: AddExtensions failed\n");
180*4882a593Smuzhiyun         }
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun         XvReqCode = extEntry->base;
183*4882a593Smuzhiyun         XvEventBase = extEntry->eventBase;
184*4882a593Smuzhiyun         XvErrorBase = extEntry->errorBase;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun         EventSwapVector[XvEventBase + XvVideoNotify] =
187*4882a593Smuzhiyun             (EventSwapPtr) WriteSwappedVideoNotifyEvent;
188*4882a593Smuzhiyun         EventSwapVector[XvEventBase + XvPortNotify] =
189*4882a593Smuzhiyun             (EventSwapPtr) WriteSwappedPortNotifyEvent;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun         SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
192*4882a593Smuzhiyun         (void) MakeAtom(XvName, strlen(XvName), xTrue);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun     }
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static Bool
CreateResourceTypes(void)198*4882a593Smuzhiyun CreateResourceTypes(void)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun     if (XvResourceGeneration == serverGeneration)
202*4882a593Smuzhiyun         return TRUE;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun     XvResourceGeneration = serverGeneration;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun     if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) {
207*4882a593Smuzhiyun         ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
208*4882a593Smuzhiyun         return FALSE;
209*4882a593Smuzhiyun     }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun     if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) {
212*4882a593Smuzhiyun         ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
213*4882a593Smuzhiyun         return FALSE;
214*4882a593Smuzhiyun     }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun     if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
217*4882a593Smuzhiyun                                                "XvRTEncoding"))) {
218*4882a593Smuzhiyun         ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
219*4882a593Smuzhiyun         return FALSE;
220*4882a593Smuzhiyun     }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun     if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
223*4882a593Smuzhiyun                                                   "XvRTVideoNotify"))) {
224*4882a593Smuzhiyun         ErrorF
225*4882a593Smuzhiyun             ("CreateResourceTypes: failed to allocate video notify resource.\n");
226*4882a593Smuzhiyun         return FALSE;
227*4882a593Smuzhiyun     }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun     if (!
230*4882a593Smuzhiyun         (XvRTVideoNotifyList =
231*4882a593Smuzhiyun          CreateNewResourceType(XvdiDestroyVideoNotifyList,
232*4882a593Smuzhiyun                                "XvRTVideoNotifyList"))) {
233*4882a593Smuzhiyun         ErrorF
234*4882a593Smuzhiyun             ("CreateResourceTypes: failed to allocate video notify list resource.\n");
235*4882a593Smuzhiyun         return FALSE;
236*4882a593Smuzhiyun     }
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun     if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
239*4882a593Smuzhiyun                                                  "XvRTPortNotify"))) {
240*4882a593Smuzhiyun         ErrorF
241*4882a593Smuzhiyun             ("CreateResourceTypes: failed to allocate port notify resource.\n");
242*4882a593Smuzhiyun         return FALSE;
243*4882a593Smuzhiyun     }
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun     return TRUE;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun int
XvScreenInit(ScreenPtr pScreen)250*4882a593Smuzhiyun XvScreenInit(ScreenPtr pScreen)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun     XvScreenPtr pxvs;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun     if (XvScreenGeneration != serverGeneration) {
255*4882a593Smuzhiyun         if (!CreateResourceTypes()) {
256*4882a593Smuzhiyun             ErrorF("XvScreenInit: Unable to allocate resource types\n");
257*4882a593Smuzhiyun             return BadAlloc;
258*4882a593Smuzhiyun         }
259*4882a593Smuzhiyun #ifdef PANORAMIX
260*4882a593Smuzhiyun         XineramaRegisterConnectionBlockCallback(XineramifyXv);
261*4882a593Smuzhiyun #endif
262*4882a593Smuzhiyun         XvScreenGeneration = serverGeneration;
263*4882a593Smuzhiyun     }
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
266*4882a593Smuzhiyun         return BadAlloc;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) {
269*4882a593Smuzhiyun         ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
270*4882a593Smuzhiyun     }
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     /* ALLOCATE SCREEN PRIVATE RECORD */
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun     pxvs = malloc(sizeof(XvScreenRec));
275*4882a593Smuzhiyun     if (!pxvs) {
276*4882a593Smuzhiyun         ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
277*4882a593Smuzhiyun         return BadAlloc;
278*4882a593Smuzhiyun     }
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     pxvs->DestroyPixmap = pScreen->DestroyPixmap;
283*4882a593Smuzhiyun     pxvs->DestroyWindow = pScreen->DestroyWindow;
284*4882a593Smuzhiyun     pxvs->CloseScreen = pScreen->CloseScreen;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     pScreen->DestroyPixmap = XvDestroyPixmap;
287*4882a593Smuzhiyun     pScreen->DestroyWindow = XvDestroyWindow;
288*4882a593Smuzhiyun     pScreen->CloseScreen = XvCloseScreen;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     return Success;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun static Bool
XvCloseScreen(ScreenPtr pScreen)294*4882a593Smuzhiyun XvCloseScreen(ScreenPtr pScreen)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     XvScreenPtr pxvs;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     pScreen->DestroyPixmap = pxvs->DestroyPixmap;
302*4882a593Smuzhiyun     pScreen->DestroyWindow = pxvs->DestroyWindow;
303*4882a593Smuzhiyun     pScreen->CloseScreen = pxvs->CloseScreen;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     free(pxvs);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun     return (*pScreen->CloseScreen) (pScreen);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun static void
XvResetProc(ExtensionEntry * extEntry)313*4882a593Smuzhiyun XvResetProc(ExtensionEntry * extEntry)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun     XvResetProcVector();
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun DevPrivateKey
XvGetScreenKey(void)319*4882a593Smuzhiyun XvGetScreenKey(void)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun     return XvScreenKey;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun unsigned long
XvGetRTPort(void)325*4882a593Smuzhiyun XvGetRTPort(void)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun     return XvRTPort;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun static void
XvStopAdaptors(DrawablePtr pDrawable)331*4882a593Smuzhiyun XvStopAdaptors(DrawablePtr pDrawable)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun     ScreenPtr pScreen = pDrawable->pScreen;
334*4882a593Smuzhiyun     XvScreenPtr pxvs = dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
335*4882a593Smuzhiyun     XvAdaptorPtr pa = pxvs->pAdaptors;
336*4882a593Smuzhiyun     int na = pxvs->nAdaptors;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun     /* CHECK TO SEE IF THIS PORT IS IN USE */
339*4882a593Smuzhiyun     while (na--) {
340*4882a593Smuzhiyun         XvPortPtr pp = pa->pPorts;
341*4882a593Smuzhiyun         int np = pa->nPorts;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun         while (np--) {
344*4882a593Smuzhiyun             if (pp->pDraw == pDrawable) {
345*4882a593Smuzhiyun                 XvdiSendVideoNotify(pp, pDrawable, XvPreempted);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun                 (void) (*pp->pAdaptor->ddStopVideo) (pp, pDrawable);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun                 pp->pDraw = NULL;
350*4882a593Smuzhiyun                 pp->client = NULL;
351*4882a593Smuzhiyun                 pp->time = currentTime;
352*4882a593Smuzhiyun             }
353*4882a593Smuzhiyun             pp++;
354*4882a593Smuzhiyun         }
355*4882a593Smuzhiyun         pa++;
356*4882a593Smuzhiyun     }
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun static Bool
XvDestroyPixmap(PixmapPtr pPix)360*4882a593Smuzhiyun XvDestroyPixmap(PixmapPtr pPix)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun     ScreenPtr pScreen = pPix->drawable.pScreen;
363*4882a593Smuzhiyun     Bool status;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     if (pPix->refcnt == 1)
366*4882a593Smuzhiyun         XvStopAdaptors(&pPix->drawable);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun     SCREEN_PROLOGUE(pScreen, DestroyPixmap);
369*4882a593Smuzhiyun     status = (*pScreen->DestroyPixmap) (pPix);
370*4882a593Smuzhiyun     SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun     return status;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun static Bool
XvDestroyWindow(WindowPtr pWin)377*4882a593Smuzhiyun XvDestroyWindow(WindowPtr pWin)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
380*4882a593Smuzhiyun     Bool status;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun     XvStopAdaptors(&pWin->drawable);
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun     SCREEN_PROLOGUE(pScreen, DestroyWindow);
385*4882a593Smuzhiyun     status = (*pScreen->DestroyWindow) (pWin);
386*4882a593Smuzhiyun     SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun     return status;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static int
XvdiDestroyPort(void * pPort,XID id)393*4882a593Smuzhiyun XvdiDestroyPort(void *pPort, XID id)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun     return Success;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun static int
XvdiDestroyGrab(void * pGrab,XID id)399*4882a593Smuzhiyun XvdiDestroyGrab(void *pGrab, XID id)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun     ((XvGrabPtr) pGrab)->client = NULL;
402*4882a593Smuzhiyun     return Success;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun static int
XvdiDestroyVideoNotify(void * pn,XID id)406*4882a593Smuzhiyun XvdiDestroyVideoNotify(void *pn, XID id)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun     /* JUST CLEAR OUT THE client POINTER FIELD */
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun     ((XvVideoNotifyPtr) pn)->client = NULL;
411*4882a593Smuzhiyun     return Success;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun static int
XvdiDestroyPortNotify(void * pn,XID id)415*4882a593Smuzhiyun XvdiDestroyPortNotify(void *pn, XID id)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun     /* JUST CLEAR OUT THE client POINTER FIELD */
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun     ((XvPortNotifyPtr) pn)->client = NULL;
420*4882a593Smuzhiyun     return Success;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun static int
XvdiDestroyVideoNotifyList(void * pn,XID id)424*4882a593Smuzhiyun XvdiDestroyVideoNotifyList(void *pn, XID id)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun     XvVideoNotifyPtr npn, cpn;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun     /* ACTUALLY DESTROY THE NOTITY LIST */
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun     cpn = (XvVideoNotifyPtr) pn;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun     while (cpn) {
433*4882a593Smuzhiyun         npn = cpn->next;
434*4882a593Smuzhiyun         if (cpn->client)
435*4882a593Smuzhiyun             FreeResource(cpn->id, XvRTVideoNotify);
436*4882a593Smuzhiyun         free(cpn);
437*4882a593Smuzhiyun         cpn = npn;
438*4882a593Smuzhiyun     }
439*4882a593Smuzhiyun     return Success;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun static int
XvdiDestroyEncoding(void * value,XID id)443*4882a593Smuzhiyun XvdiDestroyEncoding(void *value, XID id)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun     return Success;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun static int
XvdiSendVideoNotify(XvPortPtr pPort,DrawablePtr pDraw,int reason)449*4882a593Smuzhiyun XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun     XvVideoNotifyPtr pn;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun     dixLookupResourceByType((void **) &pn, pDraw->id, XvRTVideoNotifyList,
454*4882a593Smuzhiyun                             serverClient, DixReadAccess);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     while (pn) {
457*4882a593Smuzhiyun         xvEvent event = {
458*4882a593Smuzhiyun             .u.videoNotify.reason = reason,
459*4882a593Smuzhiyun             .u.videoNotify.time = currentTime.milliseconds,
460*4882a593Smuzhiyun             .u.videoNotify.drawable = pDraw->id,
461*4882a593Smuzhiyun             .u.videoNotify.port = pPort->id
462*4882a593Smuzhiyun         };
463*4882a593Smuzhiyun         event.u.u.type = XvEventBase + XvVideoNotify;
464*4882a593Smuzhiyun         WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
465*4882a593Smuzhiyun         pn = pn->next;
466*4882a593Smuzhiyun     }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun     return Success;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun int
XvdiSendPortNotify(XvPortPtr pPort,Atom attribute,INT32 value)473*4882a593Smuzhiyun XvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun     XvPortNotifyPtr pn;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun     pn = pPort->pNotify;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun     while (pn) {
480*4882a593Smuzhiyun         xvEvent event = {
481*4882a593Smuzhiyun             .u.portNotify.time = currentTime.milliseconds,
482*4882a593Smuzhiyun             .u.portNotify.port = pPort->id,
483*4882a593Smuzhiyun             .u.portNotify.attribute = attribute,
484*4882a593Smuzhiyun             .u.portNotify.value = value
485*4882a593Smuzhiyun         };
486*4882a593Smuzhiyun         event.u.u.type = XvEventBase + XvPortNotify;
487*4882a593Smuzhiyun         WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
488*4882a593Smuzhiyun         pn = pn->next;
489*4882a593Smuzhiyun     }
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun     return Success;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun #define CHECK_SIZE(dw, dh, sw, sh) {                                  \
496*4882a593Smuzhiyun   if(!dw || !dh || !sw || !sh)  return Success;                       \
497*4882a593Smuzhiyun   /* The region code will break these if they are too large */        \
498*4882a593Smuzhiyun   if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
499*4882a593Smuzhiyun         return BadValue;                                              \
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun int
XvdiPutVideo(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)503*4882a593Smuzhiyun XvdiPutVideo(ClientPtr client,
504*4882a593Smuzhiyun              DrawablePtr pDraw,
505*4882a593Smuzhiyun              XvPortPtr pPort,
506*4882a593Smuzhiyun              GCPtr pGC,
507*4882a593Smuzhiyun              INT16 vid_x, INT16 vid_y,
508*4882a593Smuzhiyun              CARD16 vid_w, CARD16 vid_h,
509*4882a593Smuzhiyun              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun     DrawablePtr pOldDraw;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun     UpdateCurrentTime();
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
520*4882a593Smuzhiyun        INFORM CLIENT OF ITS FAILURE */
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun     if (pPort->grab.client && (pPort->grab.client != client)) {
523*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
524*4882a593Smuzhiyun         return Success;
525*4882a593Smuzhiyun     }
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun     /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
528*4882a593Smuzhiyun        EVENTS TO ANY CLIENTS WHO WANT THEM */
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun     pOldDraw = pPort->pDraw;
531*4882a593Smuzhiyun     if ((pOldDraw) && (pOldDraw != pDraw)) {
532*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
533*4882a593Smuzhiyun     }
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun     (void) (*pPort->pAdaptor->ddPutVideo) (pDraw, pPort, pGC,
536*4882a593Smuzhiyun                                            vid_x, vid_y, vid_w, vid_h,
537*4882a593Smuzhiyun                                            drw_x, drw_y, drw_w, drw_h);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun     if ((pPort->pDraw) && (pOldDraw != pDraw)) {
540*4882a593Smuzhiyun         pPort->client = client;
541*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
542*4882a593Smuzhiyun     }
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun     pPort->time = currentTime;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun     return Success;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun int
XvdiPutStill(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)551*4882a593Smuzhiyun XvdiPutStill(ClientPtr client,
552*4882a593Smuzhiyun              DrawablePtr pDraw,
553*4882a593Smuzhiyun              XvPortPtr pPort,
554*4882a593Smuzhiyun              GCPtr pGC,
555*4882a593Smuzhiyun              INT16 vid_x, INT16 vid_y,
556*4882a593Smuzhiyun              CARD16 vid_w, CARD16 vid_h,
557*4882a593Smuzhiyun              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun     int status;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun     UpdateCurrentTime();
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
568*4882a593Smuzhiyun        INFORM CLIENT OF ITS FAILURE */
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun     if (pPort->grab.client && (pPort->grab.client != client)) {
571*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
572*4882a593Smuzhiyun         return Success;
573*4882a593Smuzhiyun     }
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun     pPort->time = currentTime;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun     status = (*pPort->pAdaptor->ddPutStill) (pDraw, pPort, pGC,
578*4882a593Smuzhiyun                                              vid_x, vid_y, vid_w, vid_h,
579*4882a593Smuzhiyun                                              drw_x, drw_y, drw_w, drw_h);
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun     return status;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun int
XvdiPutImage(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 image,unsigned char * data,Bool sync,CARD16 width,CARD16 height)586*4882a593Smuzhiyun XvdiPutImage(ClientPtr client,
587*4882a593Smuzhiyun              DrawablePtr pDraw,
588*4882a593Smuzhiyun              XvPortPtr pPort,
589*4882a593Smuzhiyun              GCPtr pGC,
590*4882a593Smuzhiyun              INT16 src_x, INT16 src_y,
591*4882a593Smuzhiyun              CARD16 src_w, CARD16 src_h,
592*4882a593Smuzhiyun              INT16 drw_x, INT16 drw_y,
593*4882a593Smuzhiyun              CARD16 drw_w, CARD16 drw_h,
594*4882a593Smuzhiyun              XvImagePtr image,
595*4882a593Smuzhiyun              unsigned char *data, Bool sync, CARD16 width, CARD16 height)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun     CHECK_SIZE(drw_w, drw_h, src_w, src_h);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun     UpdateCurrentTime();
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
604*4882a593Smuzhiyun        INFORM CLIENT OF ITS FAILURE */
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun     if (pPort->grab.client && (pPort->grab.client != client)) {
607*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
608*4882a593Smuzhiyun         return Success;
609*4882a593Smuzhiyun     }
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun     pPort->time = currentTime;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun     return (*pPort->pAdaptor->ddPutImage) (pDraw, pPort, pGC,
614*4882a593Smuzhiyun                                            src_x, src_y, src_w, src_h,
615*4882a593Smuzhiyun                                            drw_x, drw_y, drw_w, drw_h,
616*4882a593Smuzhiyun                                            image, data, sync, width, height);
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun int
XvdiGetVideo(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)620*4882a593Smuzhiyun XvdiGetVideo(ClientPtr client,
621*4882a593Smuzhiyun              DrawablePtr pDraw,
622*4882a593Smuzhiyun              XvPortPtr pPort,
623*4882a593Smuzhiyun              GCPtr pGC,
624*4882a593Smuzhiyun              INT16 vid_x, INT16 vid_y,
625*4882a593Smuzhiyun              CARD16 vid_w, CARD16 vid_h,
626*4882a593Smuzhiyun              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun     DrawablePtr pOldDraw;
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun     UpdateCurrentTime();
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
637*4882a593Smuzhiyun        INFORM CLIENT OF ITS FAILURE */
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun     if (pPort->grab.client && (pPort->grab.client != client)) {
640*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
641*4882a593Smuzhiyun         return Success;
642*4882a593Smuzhiyun     }
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun     /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
645*4882a593Smuzhiyun        EVENTS TO ANY CLIENTS WHO WANT THEM */
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun     pOldDraw = pPort->pDraw;
648*4882a593Smuzhiyun     if ((pOldDraw) && (pOldDraw != pDraw)) {
649*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
650*4882a593Smuzhiyun     }
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     (void) (*pPort->pAdaptor->ddGetVideo) (pDraw, pPort, pGC,
653*4882a593Smuzhiyun                                            vid_x, vid_y, vid_w, vid_h,
654*4882a593Smuzhiyun                                            drw_x, drw_y, drw_w, drw_h);
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun     if ((pPort->pDraw) && (pOldDraw != pDraw)) {
657*4882a593Smuzhiyun         pPort->client = client;
658*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
659*4882a593Smuzhiyun     }
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun     pPort->time = currentTime;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun     return Success;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun int
XvdiGetStill(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)668*4882a593Smuzhiyun XvdiGetStill(ClientPtr client,
669*4882a593Smuzhiyun              DrawablePtr pDraw,
670*4882a593Smuzhiyun              XvPortPtr pPort,
671*4882a593Smuzhiyun              GCPtr pGC,
672*4882a593Smuzhiyun              INT16 vid_x, INT16 vid_y,
673*4882a593Smuzhiyun              CARD16 vid_w, CARD16 vid_h,
674*4882a593Smuzhiyun              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
675*4882a593Smuzhiyun {
676*4882a593Smuzhiyun     int status;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun     UpdateCurrentTime();
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
685*4882a593Smuzhiyun        INFORM CLIENT OF ITS FAILURE */
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun     if (pPort->grab.client && (pPort->grab.client != client)) {
688*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
689*4882a593Smuzhiyun         return Success;
690*4882a593Smuzhiyun     }
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun     status = (*pPort->pAdaptor->ddGetStill) (pDraw, pPort, pGC,
693*4882a593Smuzhiyun                                              vid_x, vid_y, vid_w, vid_h,
694*4882a593Smuzhiyun                                              drw_x, drw_y, drw_w, drw_h);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun     pPort->time = currentTime;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun     return status;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun int
XvdiGrabPort(ClientPtr client,XvPortPtr pPort,Time ctime,int * p_result)703*4882a593Smuzhiyun XvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun     unsigned long id;
706*4882a593Smuzhiyun     TimeStamp time;
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun     UpdateCurrentTime();
709*4882a593Smuzhiyun     time = ClientTimeToServerTime(ctime);
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun     if (pPort->grab.client && (client != pPort->grab.client)) {
712*4882a593Smuzhiyun         *p_result = XvAlreadyGrabbed;
713*4882a593Smuzhiyun         return Success;
714*4882a593Smuzhiyun     }
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun     if ((CompareTimeStamps(time, currentTime) == LATER) ||
717*4882a593Smuzhiyun         (CompareTimeStamps(time, pPort->time) == EARLIER)) {
718*4882a593Smuzhiyun         *p_result = XvInvalidTime;
719*4882a593Smuzhiyun         return Success;
720*4882a593Smuzhiyun     }
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun     if (client == pPort->grab.client) {
723*4882a593Smuzhiyun         *p_result = Success;
724*4882a593Smuzhiyun         return Success;
725*4882a593Smuzhiyun     }
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun     id = FakeClientID(client->index);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun     if (!AddResource(id, XvRTGrab, &pPort->grab)) {
730*4882a593Smuzhiyun         return BadAlloc;
731*4882a593Smuzhiyun     }
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun     /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun     if ((pPort->pDraw) && (client != pPort->client)) {
736*4882a593Smuzhiyun         XvdiStopVideo(NULL, pPort, pPort->pDraw);
737*4882a593Smuzhiyun     }
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun     pPort->grab.client = client;
740*4882a593Smuzhiyun     pPort->grab.id = id;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun     pPort->time = currentTime;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun     *p_result = Success;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun     return Success;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun int
XvdiUngrabPort(ClientPtr client,XvPortPtr pPort,Time ctime)751*4882a593Smuzhiyun XvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun     TimeStamp time;
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun     UpdateCurrentTime();
756*4882a593Smuzhiyun     time = ClientTimeToServerTime(ctime);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun     if ((!pPort->grab.client) || (client != pPort->grab.client)) {
759*4882a593Smuzhiyun         return Success;
760*4882a593Smuzhiyun     }
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun     if ((CompareTimeStamps(time, currentTime) == LATER) ||
763*4882a593Smuzhiyun         (CompareTimeStamps(time, pPort->time) == EARLIER)) {
764*4882a593Smuzhiyun         return Success;
765*4882a593Smuzhiyun     }
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun     /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun     FreeResource(pPort->grab.id, XvRTGrab);
770*4882a593Smuzhiyun     pPort->grab.client = NULL;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun     pPort->time = currentTime;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun     return Success;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun int
XvdiSelectVideoNotify(ClientPtr client,DrawablePtr pDraw,BOOL onoff)779*4882a593Smuzhiyun XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun     XvVideoNotifyPtr pn, tpn, fpn;
782*4882a593Smuzhiyun     int rc;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun     /* FIND VideoNotify LIST */
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun     rc = dixLookupResourceByType((void **) &pn, pDraw->id,
787*4882a593Smuzhiyun                                  XvRTVideoNotifyList, client, DixWriteAccess);
788*4882a593Smuzhiyun     if (rc != Success && rc != BadValue)
789*4882a593Smuzhiyun         return rc;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun     /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun     if (!onoff && !pn)
794*4882a593Smuzhiyun         return Success;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun     /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
797*4882a593Smuzhiyun        WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun     if (!pn) {
800*4882a593Smuzhiyun         if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
801*4882a593Smuzhiyun             return BadAlloc;
802*4882a593Smuzhiyun         tpn->next = NULL;
803*4882a593Smuzhiyun         tpn->client = NULL;
804*4882a593Smuzhiyun         if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
805*4882a593Smuzhiyun             return BadAlloc;
806*4882a593Smuzhiyun     }
807*4882a593Smuzhiyun     else {
808*4882a593Smuzhiyun         /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun         fpn = NULL;
811*4882a593Smuzhiyun         tpn = pn;
812*4882a593Smuzhiyun         while (tpn) {
813*4882a593Smuzhiyun             if (tpn->client == client) {
814*4882a593Smuzhiyun                 if (!onoff)
815*4882a593Smuzhiyun                     tpn->client = NULL;
816*4882a593Smuzhiyun                 return Success;
817*4882a593Smuzhiyun             }
818*4882a593Smuzhiyun             if (!tpn->client)
819*4882a593Smuzhiyun                 fpn = tpn;      /* TAKE NOTE OF FREE ENTRY */
820*4882a593Smuzhiyun             tpn = tpn->next;
821*4882a593Smuzhiyun         }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun         /* IF TUNNING OFF, THEN JUST RETURN */
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun         if (!onoff)
826*4882a593Smuzhiyun             return Success;
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun         /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun         if (fpn) {
831*4882a593Smuzhiyun             tpn = fpn;
832*4882a593Smuzhiyun         }
833*4882a593Smuzhiyun         else {
834*4882a593Smuzhiyun             if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
835*4882a593Smuzhiyun                 return BadAlloc;
836*4882a593Smuzhiyun             tpn->next = pn->next;
837*4882a593Smuzhiyun             pn->next = tpn;
838*4882a593Smuzhiyun         }
839*4882a593Smuzhiyun     }
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun     /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
842*4882a593Smuzhiyun     /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun     tpn->client = NULL;
845*4882a593Smuzhiyun     tpn->id = FakeClientID(client->index);
846*4882a593Smuzhiyun     if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
847*4882a593Smuzhiyun         return BadAlloc;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun     tpn->client = client;
850*4882a593Smuzhiyun     return Success;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun int
XvdiSelectPortNotify(ClientPtr client,XvPortPtr pPort,BOOL onoff)855*4882a593Smuzhiyun XvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
856*4882a593Smuzhiyun {
857*4882a593Smuzhiyun     XvPortNotifyPtr pn, tpn;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun     /* SEE IF CLIENT IS ALREADY IN LIST */
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun     tpn = NULL;
862*4882a593Smuzhiyun     pn = pPort->pNotify;
863*4882a593Smuzhiyun     while (pn) {
864*4882a593Smuzhiyun         if (!pn->client)
865*4882a593Smuzhiyun             tpn = pn;           /* TAKE NOTE OF FREE ENTRY */
866*4882a593Smuzhiyun         if (pn->client == client)
867*4882a593Smuzhiyun             break;
868*4882a593Smuzhiyun         pn = pn->next;
869*4882a593Smuzhiyun     }
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun     /* IS THE CLIENT ALREADY ON THE LIST? */
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun     if (pn) {
874*4882a593Smuzhiyun         /* REMOVE IT? */
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun         if (!onoff) {
877*4882a593Smuzhiyun             pn->client = NULL;
878*4882a593Smuzhiyun             FreeResource(pn->id, XvRTPortNotify);
879*4882a593Smuzhiyun         }
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun         return Success;
882*4882a593Smuzhiyun     }
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun     /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
885*4882a593Smuzhiyun        CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun     if (!tpn) {
888*4882a593Smuzhiyun         if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
889*4882a593Smuzhiyun             return BadAlloc;
890*4882a593Smuzhiyun         tpn->next = pPort->pNotify;
891*4882a593Smuzhiyun         pPort->pNotify = tpn;
892*4882a593Smuzhiyun     }
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun     tpn->client = client;
895*4882a593Smuzhiyun     tpn->id = FakeClientID(client->index);
896*4882a593Smuzhiyun     if (!AddResource(tpn->id, XvRTPortNotify, tpn))
897*4882a593Smuzhiyun         return BadAlloc;
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun     return Success;
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun int
XvdiStopVideo(ClientPtr client,XvPortPtr pPort,DrawablePtr pDraw)904*4882a593Smuzhiyun XvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
905*4882a593Smuzhiyun {
906*4882a593Smuzhiyun     int status;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun     /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun     if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
911*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvStopped);
912*4882a593Smuzhiyun         return Success;
913*4882a593Smuzhiyun     }
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
916*4882a593Smuzhiyun        INFORM CLIENT OF ITS FAILURE */
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun     if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
919*4882a593Smuzhiyun         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
920*4882a593Smuzhiyun         return Success;
921*4882a593Smuzhiyun     }
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun     XvdiSendVideoNotify(pPort, pDraw, XvStopped);
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun     status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun     pPort->pDraw = NULL;
928*4882a593Smuzhiyun     pPort->client = (ClientPtr) client;
929*4882a593Smuzhiyun     pPort->time = currentTime;
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun     return status;
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun int
XvdiMatchPort(XvPortPtr pPort,DrawablePtr pDraw)936*4882a593Smuzhiyun XvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
937*4882a593Smuzhiyun {
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun     XvAdaptorPtr pa;
940*4882a593Smuzhiyun     XvFormatPtr pf;
941*4882a593Smuzhiyun     int nf;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun     pa = pPort->pAdaptor;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun     if (pa->pScreen != pDraw->pScreen)
946*4882a593Smuzhiyun         return BadMatch;
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun     nf = pa->nFormats;
949*4882a593Smuzhiyun     pf = pa->pFormats;
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun     while (nf--) {
952*4882a593Smuzhiyun         if (pf->depth == pDraw->depth)
953*4882a593Smuzhiyun             return Success;
954*4882a593Smuzhiyun         pf++;
955*4882a593Smuzhiyun     }
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun     return BadMatch;
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun int
XvdiSetPortAttribute(ClientPtr client,XvPortPtr pPort,Atom attribute,INT32 value)962*4882a593Smuzhiyun XvdiSetPortAttribute(ClientPtr client,
963*4882a593Smuzhiyun                      XvPortPtr pPort, Atom attribute, INT32 value)
964*4882a593Smuzhiyun {
965*4882a593Smuzhiyun     int status;
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun     status =
968*4882a593Smuzhiyun         (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
969*4882a593Smuzhiyun                                                 value);
970*4882a593Smuzhiyun     if (status == Success)
971*4882a593Smuzhiyun         XvdiSendPortNotify(pPort, attribute, value);
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun     return status;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun int
XvdiGetPortAttribute(ClientPtr client,XvPortPtr pPort,Atom attribute,INT32 * p_value)977*4882a593Smuzhiyun XvdiGetPortAttribute(ClientPtr client,
978*4882a593Smuzhiyun                      XvPortPtr pPort, Atom attribute, INT32 *p_value)
979*4882a593Smuzhiyun {
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun     return
982*4882a593Smuzhiyun         (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
983*4882a593Smuzhiyun                                                 p_value);
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun 
987*4882a593Smuzhiyun static void _X_COLD
WriteSwappedVideoNotifyEvent(xvEvent * from,xvEvent * to)988*4882a593Smuzhiyun WriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
989*4882a593Smuzhiyun {
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun     to->u.u.type = from->u.u.type;
992*4882a593Smuzhiyun     to->u.u.detail = from->u.u.detail;
993*4882a593Smuzhiyun     cpswaps(from->u.videoNotify.sequenceNumber,
994*4882a593Smuzhiyun             to->u.videoNotify.sequenceNumber);
995*4882a593Smuzhiyun     cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
996*4882a593Smuzhiyun     cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
997*4882a593Smuzhiyun     cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun static void _X_COLD
WriteSwappedPortNotifyEvent(xvEvent * from,xvEvent * to)1002*4882a593Smuzhiyun WriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
1003*4882a593Smuzhiyun {
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun     to->u.u.type = from->u.u.type;
1006*4882a593Smuzhiyun     to->u.u.detail = from->u.u.detail;
1007*4882a593Smuzhiyun     cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
1008*4882a593Smuzhiyun     cpswapl(from->u.portNotify.time, to->u.portNotify.time);
1009*4882a593Smuzhiyun     cpswapl(from->u.portNotify.port, to->u.portNotify.port);
1010*4882a593Smuzhiyun     cpswapl(from->u.portNotify.value, to->u.portNotify.value);
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun void
XvFreeAdaptor(XvAdaptorPtr pAdaptor)1015*4882a593Smuzhiyun XvFreeAdaptor(XvAdaptorPtr pAdaptor)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun     int i;
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun     free(pAdaptor->name);
1020*4882a593Smuzhiyun     pAdaptor->name = NULL;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun     if (pAdaptor->pEncodings) {
1023*4882a593Smuzhiyun         XvEncodingPtr pEncode = pAdaptor->pEncodings;
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun         for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
1026*4882a593Smuzhiyun             free(pEncode->name);
1027*4882a593Smuzhiyun         free(pAdaptor->pEncodings);
1028*4882a593Smuzhiyun         pAdaptor->pEncodings = NULL;
1029*4882a593Smuzhiyun     }
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun     free(pAdaptor->pFormats);
1032*4882a593Smuzhiyun     pAdaptor->pFormats = NULL;
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun     free(pAdaptor->pPorts);
1035*4882a593Smuzhiyun     pAdaptor->pPorts = NULL;
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun     if (pAdaptor->pAttributes) {
1038*4882a593Smuzhiyun         XvAttributePtr pAttribute = pAdaptor->pAttributes;
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun         for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
1041*4882a593Smuzhiyun             free(pAttribute->name);
1042*4882a593Smuzhiyun         free(pAdaptor->pAttributes);
1043*4882a593Smuzhiyun         pAdaptor->pAttributes = NULL;
1044*4882a593Smuzhiyun     }
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun     free(pAdaptor->pImages);
1047*4882a593Smuzhiyun     pAdaptor->pImages = NULL;
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun     free(pAdaptor->devPriv.ptr);
1050*4882a593Smuzhiyun     pAdaptor->devPriv.ptr = NULL;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun void
XvFillColorKey(DrawablePtr pDraw,CARD32 key,RegionPtr region)1054*4882a593Smuzhiyun XvFillColorKey(DrawablePtr pDraw, CARD32 key, RegionPtr region)
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1057*4882a593Smuzhiyun     ChangeGCVal pval[2];
1058*4882a593Smuzhiyun     BoxPtr pbox = RegionRects(region);
1059*4882a593Smuzhiyun     int i, nbox = RegionNumRects(region);
1060*4882a593Smuzhiyun     xRectangle *rects;
1061*4882a593Smuzhiyun     GCPtr gc;
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun     gc = GetScratchGC(pDraw->depth, pScreen);
1064*4882a593Smuzhiyun     if (!gc)
1065*4882a593Smuzhiyun         return;
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun     pval[0].val = key;
1068*4882a593Smuzhiyun     pval[1].val = IncludeInferiors;
1069*4882a593Smuzhiyun     (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
1070*4882a593Smuzhiyun     ValidateGC(pDraw, gc);
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun     rects = xallocarray(nbox, sizeof(xRectangle));
1073*4882a593Smuzhiyun     if (rects) {
1074*4882a593Smuzhiyun         for (i = 0; i < nbox; i++, pbox++) {
1075*4882a593Smuzhiyun             rects[i].x = pbox->x1 - pDraw->x;
1076*4882a593Smuzhiyun             rects[i].y = pbox->y1 - pDraw->y;
1077*4882a593Smuzhiyun             rects[i].width = pbox->x2 - pbox->x1;
1078*4882a593Smuzhiyun             rects[i].height = pbox->y2 - pbox->y1;
1079*4882a593Smuzhiyun         }
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun         (*gc->ops->PolyFillRect) (pDraw, gc, nbox, rects);
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun         free(rects);
1084*4882a593Smuzhiyun     }
1085*4882a593Smuzhiyun     FreeScratchGC(gc);
1086*4882a593Smuzhiyun }
1087