Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / src / kxv.c
CommitLineData
a09e091a
JB
1/*
2
3 XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
4 Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
5
6 Copyright (C) 2000, 2001 - Nokia Home Communications
7 Copyright (C) 1998, 1999 - The XFree86 Project Inc.
8
9All rights reserved.
10
11Permission is hereby granted, free of charge, to any person obtaining
12a copy of this software and associated documentation files (the
13"Software"), to deal in the Software without restriction, including
14without limitation the rights to use, copy, modify, merge, publish,
15distribute, and/or sell copies of the Software, and to permit persons
16to whom the Software is furnished to do so, provided that the above
17copyright notice(s) and this permission notice appear in all copies of
18the Software and that both the above copyright notice(s) and this
19permission notice appear in supporting documentation.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
24OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
26SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
27RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
28CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30
31Except as contained in this notice, the name of a copyright holder
32shall not be used in advertising or otherwise to promote the sale, use
33or other dealings in this Software without prior written authorization
34of the copyright holder.
35
36*/
37
38#ifdef HAVE_CONFIG_H
39#include <kdrive-config.h>
40#endif
41#include "kdrive.h"
42
43#include "scrnintstr.h"
44#include "regionstr.h"
45#include "windowstr.h"
46#include "pixmapstr.h"
47#include "mivalidate.h"
48#include "validate.h"
49#include "resource.h"
50#include "gcstruct.h"
51#include "dixstruct.h"
52
53#include <X11/extensions/Xv.h>
54#include <X11/extensions/Xvproto.h>
55
56#include "kxv.h"
57#include "fourcc.h"
58
59/* XvScreenRec fields */
60
61static Bool KdXVCloseScreen(ScreenPtr);
62static int KdXVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
63
64/* XvAdaptorRec fields */
65
66static int KdXVAllocatePort(unsigned long, XvPortPtr, XvPortPtr *);
67static int KdXVFreePort(XvPortPtr);
68static int KdXVPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
69 INT16, INT16, CARD16, CARD16,
70 INT16, INT16, CARD16, CARD16);
71static int KdXVPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
72 INT16, INT16, CARD16, CARD16,
73 INT16, INT16, CARD16, CARD16);
74static int KdXVGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
75 INT16, INT16, CARD16, CARD16,
76 INT16, INT16, CARD16, CARD16);
77static int KdXVGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
78 INT16, INT16, CARD16, CARD16,
79 INT16, INT16, CARD16, CARD16);
80static int KdXVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
81static int KdXVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
82static int KdXVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32 *);
83static int KdXVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
84 CARD16, CARD16, CARD16, CARD16,
85 unsigned int *, unsigned int *);
86static int KdXVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
87 INT16, INT16, CARD16, CARD16,
88 INT16, INT16, CARD16, CARD16,
89 XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
90static int KdXVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
91 CARD16 *, CARD16 *, int *, int *);
92
93/* ScreenRec fields */
94
95static Bool KdXVCreateWindow(WindowPtr pWin);
96static Bool KdXVDestroyWindow(WindowPtr pWin);
97static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
98static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
99
100/* misc */
101static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr *, int);
102
103static DevPrivateKeyRec KdXVWindowKeyRec;
104
105#define KdXVWindowKey (&KdXVWindowKeyRec)
106static DevPrivateKey KdXvScreenKey;
107static unsigned long KdXVGeneration = 0;
108static unsigned long PortResource = 0;
109
110#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \
111 dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey))
112
113#define GET_KDXV_SCREEN(pScreen) \
114 ((KdXVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
115
116#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
117 dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
118
119static KdXVInitGenericAdaptorPtr *GenDrivers = NULL;
120static int NumGenDrivers = 0;
121
122int
123KdXVRegisterGenericAdaptorDriver(KdXVInitGenericAdaptorPtr InitFunc)
124{
125 KdXVInitGenericAdaptorPtr *newdrivers;
126
127/* fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */
128
129 newdrivers = realloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) *
130 (1 + NumGenDrivers));
131 if (!newdrivers)
132 return 0;
133 GenDrivers = newdrivers;
134
135 GenDrivers[NumGenDrivers++] = InitFunc;
136
137 return 1;
138}
139
140int
141KdXVListGenericAdaptors(KdScreenInfo * screen, KdVideoAdaptorPtr ** adaptors)
142{
143 int i, j, n, num;
144 KdVideoAdaptorPtr *DrivAdap, *new;
145
146 num = 0;
147 *adaptors = NULL;
148 for (i = 0; i < NumGenDrivers; i++) {
149 n = GenDrivers[i] (screen, &DrivAdap);
150 if (0 == n)
151 continue;
152 new = realloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num + n));
153 if (NULL == new)
154 continue;
155 *adaptors = new;
156 for (j = 0; j < n; j++, num++)
157 (*adaptors)[num] = DrivAdap[j];
158 }
159 return num;
160}
161
162KdVideoAdaptorPtr
163KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen)
164{
165 return calloc(1, sizeof(KdVideoAdaptorRec));
166}
167
168void
169KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr)
170{
171 free(ptr);
172}
173
174Bool
175KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr * adaptors, int num)
176{
177 KdXVScreenPtr ScreenPriv;
178 XvScreenPtr pxvs;
179
180/* fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
181
182 if (KdXVGeneration != serverGeneration)
183 KdXVGeneration = serverGeneration;
184
185 if (noXvExtension)
186 return FALSE;
187
188 if (!dixRegisterPrivateKey(&KdXVWindowKeyRec, PRIVATE_WINDOW, 0))
189 return FALSE;
190
191 if (Success != XvScreenInit(pScreen))
192 return FALSE;
193
194 KdXvScreenKey = XvGetScreenKey();
195 PortResource = XvGetRTPort();
196
197 pxvs = GET_XV_SCREEN(pScreen);
198
199 /* Anyone initializing the Xv layer must provide these two.
200 The Xv di layer calls them without even checking if they exist! */
201
202 pxvs->ddCloseScreen = KdXVCloseScreen;
203 pxvs->ddQueryAdaptors = KdXVQueryAdaptors;
204
205 /* The Xv di layer provides us with a private hook so that we don't
206 have to allocate our own screen private. They also provide
207 a CloseScreen hook so that we don't have to wrap it. I'm not
208 sure that I appreciate that. */
209
210 ScreenPriv = malloc(sizeof(KdXVScreenRec));
211 pxvs->devPriv.ptr = (pointer) ScreenPriv;
212
213 if (!ScreenPriv)
214 return FALSE;
215
216 ScreenPriv->CreateWindow = pScreen->CreateWindow;
217 ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
218 ScreenPriv->WindowExposures = pScreen->WindowExposures;
219 ScreenPriv->ClipNotify = pScreen->ClipNotify;
220
221/* fprintf(stderr,"XV: Wrapping screen funcs\n"); */
222
223 pScreen->CreateWindow = KdXVCreateWindow;
224 pScreen->DestroyWindow = KdXVDestroyWindow;
225 pScreen->WindowExposures = KdXVWindowExposures;
226 pScreen->ClipNotify = KdXVClipNotify;
227
228 if (!KdXVInitAdaptors(pScreen, adaptors, num))
229 return FALSE;
230
231 return TRUE;
232}
233
234static void
235KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
236{
237 int i;
238
239 free(pAdaptor->name);
240
241 if (pAdaptor->pEncodings) {
242 XvEncodingPtr pEncode = pAdaptor->pEncodings;
243
244 for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++) {
245 free(pEncode->name);
246 }
247 free(pAdaptor->pEncodings);
248 }
249
250 free(pAdaptor->pFormats);
251
252 if (pAdaptor->pPorts) {
253 XvPortPtr pPort = pAdaptor->pPorts;
254 XvPortRecPrivatePtr pPriv;
255
256 for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
257 pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
258 if (pPriv) {
259 if (pPriv->clientClip)
260 RegionDestroy(pPriv->clientClip);
261 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
262 RegionDestroy(pPriv->pCompositeClip);
263 free(pPriv);
264 }
265 }
266 free(pAdaptor->pPorts);
267 }
268
269 if (pAdaptor->nAttributes) {
270 XvAttributePtr pAttribute = pAdaptor->pAttributes;
271
272 for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) {
273 free(pAttribute->name);
274 }
275
276 free(pAdaptor->pAttributes);
277 }
278
279 free(pAdaptor->pImages);
280
281 free(pAdaptor->devPriv.ptr);
282}
283
284static Bool
285KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
286{
287 KdScreenPriv(pScreen);
288 KdScreenInfo *screen = pScreenPriv->screen;
289
290 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
291 KdVideoAdaptorPtr adaptorPtr;
292 XvAdaptorPtr pAdaptor, pa;
293 XvAdaptorRecPrivatePtr adaptorPriv;
294 int na, numAdaptor;
295 XvPortRecPrivatePtr portPriv;
296 XvPortPtr pPort, pp;
297 int numPort;
298 KdAttributePtr attributePtr;
299 XvAttributePtr pAttribute, pat;
300 KdVideoFormatPtr formatPtr;
301 XvFormatPtr pFormat, pf;
302 int numFormat, totFormat;
303 KdVideoEncodingPtr encodingPtr;
304 XvEncodingPtr pEncode, pe;
305 KdImagePtr imagePtr;
306 XvImagePtr pImage, pi;
307 int numVisuals;
308 VisualPtr pVisual;
309 int i;
310
311 pxvs->nAdaptors = 0;
312 pxvs->pAdaptors = NULL;
313
314 if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
315 return FALSE;
316
317 for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
318 adaptorPtr = infoPtr[na];
319
320 if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
321 !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
322 continue;
323
324 /* client libs expect at least one encoding */
325 if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
326 continue;
327
328 pa->type = adaptorPtr->type;
329
330 if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
331 pa->type &= ~XvVideoMask;
332
333 if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
334 pa->type &= ~XvStillMask;
335
336 if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
337 pa->type &= ~XvImageMask;
338
339 if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
340 !adaptorPtr->PutStill)
341 pa->type &= ~XvInputMask;
342
343 if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
344 pa->type &= ~XvOutputMask;
345
346 if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
347 continue;
348 if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
349 continue;
350
351 pa->pScreen = pScreen;
352 pa->ddAllocatePort = KdXVAllocatePort;
353 pa->ddFreePort = KdXVFreePort;
354 pa->ddPutVideo = KdXVPutVideo;
355 pa->ddPutStill = KdXVPutStill;
356 pa->ddGetVideo = KdXVGetVideo;
357 pa->ddGetStill = KdXVGetStill;
358 pa->ddStopVideo = KdXVStopVideo;
359 pa->ddPutImage = KdXVPutImage;
360 pa->ddSetPortAttribute = KdXVSetPortAttribute;
361 pa->ddGetPortAttribute = KdXVGetPortAttribute;
362 pa->ddQueryBestSize = KdXVQueryBestSize;
363 pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
364 pa->name = strdup(adaptorPtr->name);
365
366 if (adaptorPtr->nEncodings &&
367 (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
368
369 for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
370 i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
371 pe->id = encodingPtr->id;
372 pe->pScreen = pScreen;
373 pe->name = strdup(encodingPtr->name);
374 pe->width = encodingPtr->width;
375 pe->height = encodingPtr->height;
376 pe->rate.numerator = encodingPtr->rate.numerator;
377 pe->rate.denominator = encodingPtr->rate.denominator;
378 }
379 pa->nEncodings = adaptorPtr->nEncodings;
380 pa->pEncodings = pEncode;
381 }
382
383 if (adaptorPtr->nImages &&
384 (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
385
386 for (i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
387 i < adaptorPtr->nImages; i++, pi++, imagePtr++) {
388 pi->id = imagePtr->id;
389 pi->type = imagePtr->type;
390 pi->byte_order = imagePtr->byte_order;
391 memcpy(pi->guid, imagePtr->guid, 16);
392 pi->bits_per_pixel = imagePtr->bits_per_pixel;
393 pi->format = imagePtr->format;
394 pi->num_planes = imagePtr->num_planes;
395 pi->depth = imagePtr->depth;
396 pi->red_mask = imagePtr->red_mask;
397 pi->green_mask = imagePtr->green_mask;
398 pi->blue_mask = imagePtr->blue_mask;
399 pi->y_sample_bits = imagePtr->y_sample_bits;
400 pi->u_sample_bits = imagePtr->u_sample_bits;
401 pi->v_sample_bits = imagePtr->v_sample_bits;
402 pi->horz_y_period = imagePtr->horz_y_period;
403 pi->horz_u_period = imagePtr->horz_u_period;
404 pi->horz_v_period = imagePtr->horz_v_period;
405 pi->vert_y_period = imagePtr->vert_y_period;
406 pi->vert_u_period = imagePtr->vert_u_period;
407 pi->vert_v_period = imagePtr->vert_v_period;
408 memcpy(pi->component_order, imagePtr->component_order, 32);
409 pi->scanline_order = imagePtr->scanline_order;
410 }
411 pa->nImages = adaptorPtr->nImages;
412 pa->pImages = pImage;
413 }
414
415 if (adaptorPtr->nAttributes &&
416 (pAttribute =
417 calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) {
418 for (pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i =
419 0; i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) {
420 pat->flags = attributePtr->flags;
421 pat->min_value = attributePtr->min_value;
422 pat->max_value = attributePtr->max_value;
423 pat->name = strdup(attributePtr->name);
424 }
425 pa->nAttributes = adaptorPtr->nAttributes;
426 pa->pAttributes = pAttribute;
427 }
428
429 totFormat = adaptorPtr->nFormats;
430
431 if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
432 KdXVFreeAdaptor(pa);
433 continue;
434 }
435 for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
436 adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
437 numVisuals = pScreen->numVisuals;
438 pVisual = pScreen->visuals;
439
440 while (numVisuals--) {
441 if ((pVisual->class == formatPtr->class) &&
442 (pVisual->nplanes == formatPtr->depth)) {
443
444 if (numFormat >= totFormat) {
445 void *moreSpace;
446
447 totFormat *= 2;
448 moreSpace = realloc(pFormat,
449 totFormat * sizeof(XvFormatRec));
450 if (!moreSpace)
451 break;
452 pFormat = moreSpace;
453 pf = pFormat + numFormat;
454 }
455
456 pf->visual = pVisual->vid;
457 pf->depth = formatPtr->depth;
458
459 pf++;
460 numFormat++;
461 }
462 pVisual++;
463 }
464 }
465 pa->nFormats = numFormat;
466 pa->pFormats = pFormat;
467 if (!numFormat) {
468 KdXVFreeAdaptor(pa);
469 continue;
470 }
471
472 if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
473 KdXVFreeAdaptor(pa);
474 continue;
475 }
476
477 adaptorPriv->flags = adaptorPtr->flags;
478 adaptorPriv->PutVideo = adaptorPtr->PutVideo;
479 adaptorPriv->PutStill = adaptorPtr->PutStill;
480 adaptorPriv->GetVideo = adaptorPtr->GetVideo;
481 adaptorPriv->GetStill = adaptorPtr->GetStill;
482 adaptorPriv->StopVideo = adaptorPtr->StopVideo;
483 adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
484 adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
485 adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
486 adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
487 adaptorPriv->PutImage = adaptorPtr->PutImage;
488 adaptorPriv->ReputImage = adaptorPtr->ReputImage;
489
490 pa->devPriv.ptr = (pointer) adaptorPriv;
491
492 if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
493 KdXVFreeAdaptor(pa);
494 continue;
495 }
496 for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
497
498 if (!(pp->id = FakeClientID(0)))
499 continue;
500
501 if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
502 continue;
503
504 if (!AddResource(pp->id, PortResource, pp)) {
505 free(portPriv);
506 continue;
507 }
508
509 pp->pAdaptor = pa;
510 pp->pNotify = (XvPortNotifyPtr) NULL;
511 pp->pDraw = (DrawablePtr) NULL;
512 pp->client = (ClientPtr) NULL;
513 pp->grab.client = (ClientPtr) NULL;
514 pp->time = currentTime;
515 pp->devPriv.ptr = portPriv;
516
517 portPriv->screen = screen;
518 portPriv->AdaptorRec = adaptorPriv;
519 portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
520
521 pp++;
522 numPort++;
523 }
524 pa->nPorts = numPort;
525 pa->pPorts = pPort;
526 if (!numPort) {
527 KdXVFreeAdaptor(pa);
528 continue;
529 }
530
531 pa->base_id = pPort->id;
532
533 pa++;
534 numAdaptor++;
535 }
536
537 if (numAdaptor) {
538 pxvs->nAdaptors = numAdaptor;
539 pxvs->pAdaptors = pAdaptor;
540 }
541 else {
542 free(pAdaptor);
543 return FALSE;
544 }
545
546 return TRUE;
547}
548
549/* Video should be clipped to the intersection of the window cliplist
550 and the client cliplist specified in the GC for which the video was
551 initialized. When we need to reclip a window, the GC that started
552 the video may not even be around anymore. That's why we save the
553 client clip from the GC when the video is initialized. We then
554 use KdXVUpdateCompositeClip to calculate the new composite clip
555 when we need it. This is different from what DEC did. They saved
556 the GC and used it's clip list when they needed to reclip the window,
557 even if the client clip was different from the one the video was
558 initialized with. If the original GC was destroyed, they had to stop
559 the video. I like the new method better (MArk).
560
561 This function only works for windows. Will need to rewrite when
562 (if) we support pixmap rendering.
563*/
564
565static void
566KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
567{
568 RegionPtr pregWin, pCompositeClip;
569 WindowPtr pWin;
570 Bool freeCompClip = FALSE;
571
572 if (portPriv->pCompositeClip)
573 return;
574
575 pWin = (WindowPtr) portPriv->pDraw;
576
577 /* get window clip list */
578 if (portPriv->subWindowMode == IncludeInferiors) {
579 pregWin = NotClippedByChildren(pWin);
580 freeCompClip = TRUE;
581 }
582 else
583 pregWin = &pWin->clipList;
584
585 if (!portPriv->clientClip) {
586 portPriv->pCompositeClip = pregWin;
587 portPriv->FreeCompositeClip = freeCompClip;
588 return;
589 }
590
591 pCompositeClip = RegionCreate(NullBox, 1);
592 RegionCopy(pCompositeClip, portPriv->clientClip);
593 RegionTranslate(pCompositeClip,
594 portPriv->pDraw->x + portPriv->clipOrg.x,
595 portPriv->pDraw->y + portPriv->clipOrg.y);
596 RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
597
598 portPriv->pCompositeClip = pCompositeClip;
599 portPriv->FreeCompositeClip = TRUE;
600
601 if (freeCompClip) {
602 RegionDestroy(pregWin);
603 }
604}
605
606/* Save the current clientClip and update the CompositeClip whenever
607 we have a fresh GC */
608
609static void
610KdXVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
611{
612 /* copy the new clip if it exists */
613 if ((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
614 if (!portPriv->clientClip)
615 portPriv->clientClip = RegionCreate(NullBox, 1);
616 /* Note: this is in window coordinates */
617 RegionCopy(portPriv->clientClip, pGC->clientClip);
618 }
619 else if (portPriv->clientClip) { /* free the old clientClip */
620 RegionDestroy(portPriv->clientClip);
621 portPriv->clientClip = NULL;
622 }
623
624 /* get rid of the old clip list */
625 if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
626 RegionDestroy(portPriv->pCompositeClip);
627 }
628
629 portPriv->clipOrg = pGC->clipOrg;
630 portPriv->pCompositeClip = pGC->pCompositeClip;
631 portPriv->FreeCompositeClip = FALSE;
632 portPriv->subWindowMode = pGC->subWindowMode;
633}
634
635static int
636KdXVRegetVideo(XvPortRecPrivatePtr portPriv)
637{
638 RegionRec WinRegion;
639 RegionRec ClipRegion;
640 BoxRec WinBox;
641 int ret = Success;
642 Bool clippedAway = FALSE;
643
644 KdXVUpdateCompositeClip(portPriv);
645
646 /* translate the video region to the screen */
647 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
648 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
649 WinBox.x2 = WinBox.x1 + portPriv->drw_w;
650 WinBox.y2 = WinBox.y1 + portPriv->drw_h;
651
652 /* clip to the window composite clip */
653 RegionInit(&WinRegion, &WinBox, 1);
654 RegionInit(&ClipRegion, NullBox, 1);
655 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
656
657 /* that's all if it's totally obscured */
658 if (!RegionNotEmpty(&ClipRegion)) {
659 clippedAway = TRUE;
660 goto CLIP_VIDEO_BAILOUT;
661 }
662
663 if (portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
664 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
665 }
666
667 ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->screen, portPriv->pDraw,
668 portPriv->vid_x, portPriv->vid_y,
669 WinBox.x1, WinBox.y1,
670 portPriv->vid_w, portPriv->vid_h,
671 portPriv->drw_w, portPriv->drw_h,
672 &ClipRegion,
673 portPriv->DevPriv.ptr);
674
675 if (ret == Success)
676 portPriv->isOn = XV_ON;
677
678 CLIP_VIDEO_BAILOUT:
679
680 if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
681 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
682 portPriv->DevPriv.ptr, FALSE);
683 portPriv->isOn = XV_PENDING;
684 }
685
686 /* This clip was copied and only good for one shot */
687 if (!portPriv->FreeCompositeClip)
688 portPriv->pCompositeClip = NULL;
689
690 RegionUninit(&WinRegion);
691 RegionUninit(&ClipRegion);
692
693 return ret;
694}
695
696static int
697KdXVReputVideo(XvPortRecPrivatePtr portPriv)
698{
699 RegionRec WinRegion;
700 RegionRec ClipRegion;
701 BoxRec WinBox;
702 ScreenPtr pScreen = portPriv->pDraw->pScreen;
703
704 KdScreenPriv(pScreen);
705 KdScreenInfo *screen = pScreenPriv->screen;
706 int ret = Success;
707 Bool clippedAway = FALSE;
708
709 KdXVUpdateCompositeClip(portPriv);
710
711 /* translate the video region to the screen */
712 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
713 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
714 WinBox.x2 = WinBox.x1 + portPriv->drw_w;
715 WinBox.y2 = WinBox.y1 + portPriv->drw_h;
716
717 /* clip to the window composite clip */
718 RegionInit(&WinRegion, &WinBox, 1);
719 RegionInit(&ClipRegion, NullBox, 1);
720 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
721
722 /* clip and translate to the viewport */
723 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
724 RegionRec VPReg;
725 BoxRec VPBox;
726
727 VPBox.x1 = 0;
728 VPBox.y1 = 0;
729 VPBox.x2 = screen->width;
730 VPBox.y2 = screen->height;
731
732 RegionInit(&VPReg, &VPBox, 1);
733 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
734 RegionUninit(&VPReg);
735 }
736
737 /* that's all if it's totally obscured */
738 if (!RegionNotEmpty(&ClipRegion)) {
739 clippedAway = TRUE;
740 goto CLIP_VIDEO_BAILOUT;
741 }
742
743 /* bailout if we have to clip but the hardware doesn't support it */
744 if (portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
745 BoxPtr clipBox = RegionRects(&ClipRegion);
746
747 if ((RegionNumRects(&ClipRegion) != 1) ||
748 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
749 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) {
750 clippedAway = TRUE;
751 goto CLIP_VIDEO_BAILOUT;
752 }
753 }
754
755 if (portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
756 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
757 }
758
759 ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->screen, portPriv->pDraw,
760 portPriv->vid_x, portPriv->vid_y,
761 WinBox.x1, WinBox.y1,
762 portPriv->vid_w, portPriv->vid_h,
763 portPriv->drw_w, portPriv->drw_h,
764 &ClipRegion,
765 portPriv->DevPriv.ptr);
766
767 if (ret == Success)
768 portPriv->isOn = XV_ON;
769
770 CLIP_VIDEO_BAILOUT:
771
772 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
773 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
774 portPriv->DevPriv.ptr, FALSE);
775 portPriv->isOn = XV_PENDING;
776 }
777
778 /* This clip was copied and only good for one shot */
779 if (!portPriv->FreeCompositeClip)
780 portPriv->pCompositeClip = NULL;
781
782 RegionUninit(&WinRegion);
783 RegionUninit(&ClipRegion);
784
785 return ret;
786}
787
788static int
789KdXVReputImage(XvPortRecPrivatePtr portPriv)
790{
791 RegionRec WinRegion;
792 RegionRec ClipRegion;
793 BoxRec WinBox;
794 ScreenPtr pScreen = portPriv->pDraw->pScreen;
795
796 KdScreenPriv(pScreen);
797 KdScreenInfo *screen = pScreenPriv->screen;
798 int ret = Success;
799 Bool clippedAway = FALSE;
800
801 KdXVUpdateCompositeClip(portPriv);
802
803 /* translate the video region to the screen */
804 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
805 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
806 WinBox.x2 = WinBox.x1 + portPriv->drw_w;
807 WinBox.y2 = WinBox.y1 + portPriv->drw_h;
808
809 /* clip to the window composite clip */
810 RegionInit(&WinRegion, &WinBox, 1);
811 RegionInit(&ClipRegion, NullBox, 1);
812 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
813
814 /* clip and translate to the viewport */
815 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
816 RegionRec VPReg;
817 BoxRec VPBox;
818
819 VPBox.x1 = 0;
820 VPBox.y1 = 0;
821 VPBox.x2 = screen->width;
822 VPBox.y2 = screen->height;
823
824 RegionInit(&VPReg, &VPBox, 1);
825 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
826 RegionUninit(&VPReg);
827 }
828
829 /* that's all if it's totally obscured */
830 if (!RegionNotEmpty(&ClipRegion)) {
831 clippedAway = TRUE;
832 goto CLIP_VIDEO_BAILOUT;
833 }
834
835 /* bailout if we have to clip but the hardware doesn't support it */
836 if (portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
837 BoxPtr clipBox = RegionRects(&ClipRegion);
838
839 if ((RegionNumRects(&ClipRegion) != 1) ||
840 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
841 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) {
842 clippedAway = TRUE;
843 goto CLIP_VIDEO_BAILOUT;
844 }
845 }
846
847 if (portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
848 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
849 }
850
851 ret =
852 (*portPriv->AdaptorRec->ReputImage) (portPriv->screen, portPriv->pDraw,
853 WinBox.x1, WinBox.y1, &ClipRegion,
854 portPriv->DevPriv.ptr);
855
856 portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
857
858 CLIP_VIDEO_BAILOUT:
859
860 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
861 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
862 portPriv->DevPriv.ptr, FALSE);
863 portPriv->isOn = XV_PENDING;
864 }
865
866 /* This clip was copied and only good for one shot */
867 if (!portPriv->FreeCompositeClip)
868 portPriv->pCompositeClip = NULL;
869
870 RegionUninit(&WinRegion);
871 RegionUninit(&ClipRegion);
872
873 return ret;
874}
875
876static int
877KdXVReputAllVideo(WindowPtr pWin, pointer data)
878{
879 KdXVWindowPtr WinPriv;
880
881 if (pWin->drawable.type != DRAWABLE_WINDOW)
882 return WT_DONTWALKCHILDREN;
883
884 WinPriv = GET_KDXV_WINDOW(pWin);
885
886 while (WinPriv) {
887 if (WinPriv->PortRec->type == XvInputMask)
888 KdXVReputVideo(WinPriv->PortRec);
889 else
890 KdXVRegetVideo(WinPriv->PortRec);
891 WinPriv = WinPriv->next;
892 }
893
894 return WT_WALKCHILDREN;
895}
896
897static int
898KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
899{
900 KdXVWindowPtr winPriv, PrivRoot;
901
902 winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
903
904 /* Enlist our port in the window private */
905 while (winPriv) {
906 if (winPriv->PortRec == portPriv) /* we're already listed */
907 break;
908 winPriv = winPriv->next;
909 }
910
911 if (!winPriv) {
912 winPriv = malloc(sizeof(KdXVWindowRec));
913 if (!winPriv)
914 return BadAlloc;
915 winPriv->PortRec = portPriv;
916 winPriv->next = PrivRoot;
917 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv);
918 }
919 return Success;
920}
921
922static void
923KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
924{
925 KdXVWindowPtr winPriv, prevPriv = NULL;
926
927 winPriv = GET_KDXV_WINDOW(pWin);
928
929 while (winPriv) {
930 if (winPriv->PortRec == portPriv) {
931 if (prevPriv)
932 prevPriv->next = winPriv->next;
933 else
934 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next);
935 free(winPriv);
936 break;
937 }
938 prevPriv = winPriv;
939 winPriv = winPriv->next;
940 }
941 portPriv->pDraw = NULL;
942}
943
944/**** ScreenRec fields ****/
945
946static Bool
947KdXVCreateWindow(WindowPtr pWin)
948{
949 ScreenPtr pScreen = pWin->drawable.pScreen;
950 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
951 int ret;
952
953 pScreen->CreateWindow = ScreenPriv->CreateWindow;
954 ret = (*pScreen->CreateWindow) (pWin);
955 pScreen->CreateWindow = KdXVCreateWindow;
956
957 if (ret)
958 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
959
960 return ret;
961}
962
963static Bool
964KdXVDestroyWindow(WindowPtr pWin)
965{
966 ScreenPtr pScreen = pWin->drawable.pScreen;
967 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
968 KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
969 int ret;
970
971 while (WinPriv) {
972 XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
973
974 if (pPriv->isOn > XV_OFF) {
975 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, pPriv->DevPriv.ptr,
976 TRUE);
977 pPriv->isOn = XV_OFF;
978 }
979
980 pPriv->pDraw = NULL;
981 tmp = WinPriv;
982 WinPriv = WinPriv->next;
983 free(tmp);
984 }
985
986 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
987
988 pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
989 ret = (*pScreen->DestroyWindow) (pWin);
990 pScreen->DestroyWindow = KdXVDestroyWindow;
991
992 return ret;
993}
994
995static void
996KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
997{
998 ScreenPtr pScreen = pWin->drawable.pScreen;
999 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1000 KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
1001 KdXVWindowPtr pPrev;
1002 XvPortRecPrivatePtr pPriv;
1003 Bool AreasExposed;
1004
1005 AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
1006
1007 pScreen->WindowExposures = ScreenPriv->WindowExposures;
1008 (*pScreen->WindowExposures) (pWin, reg1, reg2);
1009 pScreen->WindowExposures = KdXVWindowExposures;
1010
1011 /* filter out XClearWindow/Area */
1012 if (!pWin->valdata)
1013 return;
1014
1015 pPrev = NULL;
1016
1017 while (WinPriv) {
1018 pPriv = WinPriv->PortRec;
1019
1020 /* Reput anyone with a reput function */
1021
1022 switch (pPriv->type) {
1023 case XvInputMask:
1024 KdXVReputVideo(pPriv);
1025 break;
1026 case XvOutputMask:
1027 KdXVRegetVideo(pPriv);
1028 break;
1029 default: /* overlaid still/image */
1030 if (pPriv->AdaptorRec->ReputImage)
1031 KdXVReputImage(pPriv);
1032 else if (AreasExposed) {
1033 KdXVWindowPtr tmp;
1034
1035 if (pPriv->isOn == XV_ON) {
1036 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
1037 pPriv->DevPriv.ptr, FALSE);
1038 pPriv->isOn = XV_PENDING;
1039 }
1040 pPriv->pDraw = NULL;
1041
1042 if (!pPrev)
1043 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
1044 WinPriv->next);
1045 else
1046 pPrev->next = WinPriv->next;
1047 tmp = WinPriv;
1048 WinPriv = WinPriv->next;
1049 free(tmp);
1050 continue;
1051 }
1052 break;
1053 }
1054 pPrev = WinPriv;
1055 WinPriv = WinPriv->next;
1056 }
1057}
1058
1059static void
1060KdXVClipNotify(WindowPtr pWin, int dx, int dy)
1061{
1062 ScreenPtr pScreen = pWin->drawable.pScreen;
1063 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1064 KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
1065 KdXVWindowPtr tmp, pPrev = NULL;
1066 XvPortRecPrivatePtr pPriv;
1067 Bool visible = (pWin->visibility == VisibilityUnobscured) ||
1068 (pWin->visibility == VisibilityPartiallyObscured);
1069
1070 while (WinPriv) {
1071 pPriv = WinPriv->PortRec;
1072
1073 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1074 RegionDestroy(pPriv->pCompositeClip);
1075
1076 pPriv->pCompositeClip = NULL;
1077
1078 /* Stop everything except images, but stop them too if the
1079 window isn't visible. But we only remove the images. */
1080
1081 if (pPriv->type || !visible) {
1082 if (pPriv->isOn == XV_ON) {
1083 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
1084 pPriv->DevPriv.ptr, FALSE);
1085 pPriv->isOn = XV_PENDING;
1086 }
1087
1088 if (!pPriv->type) { /* overlaid still/image */
1089 pPriv->pDraw = NULL;
1090
1091 if (!pPrev)
1092 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
1093 WinPriv->next);
1094 else
1095 pPrev->next = WinPriv->next;
1096 tmp = WinPriv;
1097 WinPriv = WinPriv->next;
1098 free(tmp);
1099 continue;
1100 }
1101 }
1102
1103 pPrev = WinPriv;
1104 WinPriv = WinPriv->next;
1105 }
1106
1107 if (ScreenPriv->ClipNotify) {
1108 pScreen->ClipNotify = ScreenPriv->ClipNotify;
1109 (*pScreen->ClipNotify) (pWin, dx, dy);
1110 pScreen->ClipNotify = KdXVClipNotify;
1111 }
1112}
1113
1114/**** Required XvScreenRec fields ****/
1115
1116static Bool
1117KdXVCloseScreen(ScreenPtr pScreen)
1118{
1119 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1120 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1121 XvAdaptorPtr pa;
1122 int c;
1123
1124 if (!ScreenPriv)
1125 return TRUE;
1126
1127 pScreen->CreateWindow = ScreenPriv->CreateWindow;
1128 pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1129 pScreen->WindowExposures = ScreenPriv->WindowExposures;
1130 pScreen->ClipNotify = ScreenPriv->ClipNotify;
1131
1132/* fprintf(stderr,"XV: Unwrapping screen funcs\n"); */
1133
1134 for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
1135 KdXVFreeAdaptor(pa);
1136 }
1137
1138 free(pxvs->pAdaptors);
1139 free(ScreenPriv);
1140
1141 return TRUE;
1142}
1143
1144static int
1145KdXVQueryAdaptors(ScreenPtr pScreen,
1146 XvAdaptorPtr * p_pAdaptors, int *p_nAdaptors)
1147{
1148 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1149
1150 *p_nAdaptors = pxvs->nAdaptors;
1151 *p_pAdaptors = pxvs->pAdaptors;
1152
1153 return Success;
1154}
1155
1156static Bool
1157KdXVRunning(ScreenPtr pScreen)
1158{
1159 return (KdXVGeneration == serverGeneration && GET_XV_SCREEN(pScreen) != 0);
1160}
1161
1162Bool
1163KdXVEnable(ScreenPtr pScreen)
1164{
1165 if (!KdXVRunning(pScreen))
1166 return TRUE;
1167
1168 WalkTree(pScreen, KdXVReputAllVideo, 0);
1169
1170 return TRUE;
1171}
1172
1173void
1174KdXVDisable(ScreenPtr pScreen)
1175{
1176 XvScreenPtr pxvs;
1177 XvAdaptorPtr pAdaptor;
1178 XvPortPtr pPort;
1179 XvPortRecPrivatePtr pPriv;
1180 int i, j;
1181
1182 if (!KdXVRunning(pScreen))
1183 return;
1184
1185 pxvs = GET_XV_SCREEN(pScreen);
1186
1187 for (i = 0; i < pxvs->nAdaptors; i++) {
1188 pAdaptor = &pxvs->pAdaptors[i];
1189 for (j = 0; j < pAdaptor->nPorts; j++) {
1190 pPort = &pAdaptor->pPorts[j];
1191 pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
1192 if (pPriv->isOn > XV_OFF) {
1193
1194 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
1195 pPriv->DevPriv.ptr, TRUE);
1196 pPriv->isOn = XV_OFF;
1197
1198 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1199 RegionDestroy(pPriv->pCompositeClip);
1200
1201 pPriv->pCompositeClip = NULL;
1202
1203 if (!pPriv->type && pPriv->pDraw) { /* still */
1204 KdXVRemovePortFromWindow((WindowPtr) pPriv->pDraw, pPriv);
1205 }
1206 }
1207 }
1208 }
1209}
1210
1211/**** XvAdaptorRec fields ****/
1212
1213static int
1214KdXVAllocatePort(unsigned long port, XvPortPtr pPort, XvPortPtr * ppPort)
1215{
1216 *ppPort = pPort;
1217 return Success;
1218}
1219
1220static int
1221KdXVFreePort(XvPortPtr pPort)
1222{
1223 return Success;
1224}
1225
1226static int
1227KdXVPutVideo(ClientPtr client,
1228 DrawablePtr pDraw,
1229 XvPortPtr pPort,
1230 GCPtr pGC,
1231 INT16 vid_x, INT16 vid_y,
1232 CARD16 vid_w, CARD16 vid_h,
1233 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1234{
1235 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1236
1237 KdScreenPriv(portPriv->screen->pScreen);
1238 int result;
1239
1240 /* No dumping video to pixmaps... For now anyhow */
1241 if (pDraw->type != DRAWABLE_WINDOW) {
1242 pPort->pDraw = (DrawablePtr) NULL;
1243 return BadAlloc;
1244 }
1245
1246 /* If we are changing windows, unregister our port in the old window */
1247 if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1248 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1249
1250 /* Register our port with the new window */
1251 result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1252 if (result != Success)
1253 return result;
1254
1255 portPriv->pDraw = pDraw;
1256 portPriv->type = XvInputMask;
1257
1258 /* save a copy of these parameters */
1259 portPriv->vid_x = vid_x;
1260 portPriv->vid_y = vid_y;
1261 portPriv->vid_w = vid_w;
1262 portPriv->vid_h = vid_h;
1263 portPriv->drw_x = drw_x;
1264 portPriv->drw_y = drw_y;
1265 portPriv->drw_w = drw_w;
1266 portPriv->drw_h = drw_h;
1267
1268 /* make sure we have the most recent copy of the clientClip */
1269 KdXVCopyClip(portPriv, pGC);
1270
1271 /* To indicate to the DI layer that we were successful */
1272 pPort->pDraw = pDraw;
1273
1274 if (!pScreenPriv->enabled)
1275 return Success;
1276
1277 return (KdXVReputVideo(portPriv));
1278}
1279
1280static int
1281KdXVPutStill(ClientPtr client,
1282 DrawablePtr pDraw,
1283 XvPortPtr pPort,
1284 GCPtr pGC,
1285 INT16 vid_x, INT16 vid_y,
1286 CARD16 vid_w, CARD16 vid_h,
1287 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1288{
1289 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1290 ScreenPtr pScreen = pDraw->pScreen;
1291
1292 KdScreenPriv(pScreen);
1293 KdScreenInfo *screen = pScreenPriv->screen;
1294 RegionRec WinRegion;
1295 RegionRec ClipRegion;
1296 BoxRec WinBox;
1297 int ret = Success;
1298 Bool clippedAway = FALSE;
1299
1300 if (pDraw->type != DRAWABLE_WINDOW)
1301 return BadAlloc;
1302
1303 if (!pScreenPriv->enabled)
1304 return Success;
1305
1306 WinBox.x1 = pDraw->x + drw_x;
1307 WinBox.y1 = pDraw->y + drw_y;
1308 WinBox.x2 = WinBox.x1 + drw_w;
1309 WinBox.y2 = WinBox.y1 + drw_h;
1310
1311 RegionInit(&WinRegion, &WinBox, 1);
1312 RegionInit(&ClipRegion, NullBox, 1);
1313 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1314
1315 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1316 RegionRec VPReg;
1317 BoxRec VPBox;
1318
1319 VPBox.x1 = 0;
1320 VPBox.y1 = 0;
1321 VPBox.x2 = screen->width;
1322 VPBox.y2 = screen->height;
1323
1324 RegionInit(&VPReg, &VPBox, 1);
1325 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1326 RegionUninit(&VPReg);
1327 }
1328
1329 if (portPriv->pDraw) {
1330 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1331 }
1332
1333 if (!RegionNotEmpty(&ClipRegion)) {
1334 clippedAway = TRUE;
1335 goto PUT_STILL_BAILOUT;
1336 }
1337
1338 if (portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
1339 BoxPtr clipBox = RegionRects(&ClipRegion);
1340
1341 if ((RegionNumRects(&ClipRegion) != 1) ||
1342 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
1343 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) {
1344 clippedAway = TRUE;
1345 goto PUT_STILL_BAILOUT;
1346 }
1347 }
1348
1349 if (portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1350 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
1351 }
1352
1353 ret = (*portPriv->AdaptorRec->PutStill) (portPriv->screen, pDraw,
1354 vid_x, vid_y, WinBox.x1, WinBox.y1,
1355 vid_w, vid_h, drw_w, drw_h,
1356 &ClipRegion,
1357 portPriv->DevPriv.ptr);
1358
1359 if ((ret == Success) &&
1360 (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
1361
1362 KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1363 portPriv->isOn = XV_ON;
1364 portPriv->pDraw = pDraw;
1365 portPriv->drw_x = drw_x;
1366 portPriv->drw_y = drw_y;
1367 portPriv->drw_w = drw_w;
1368 portPriv->drw_h = drw_h;
1369 portPriv->type = 0; /* no mask means it's transient and should
1370 not be reput once it's removed */
1371 pPort->pDraw = pDraw; /* make sure we can get stop requests */
1372 }
1373
1374 PUT_STILL_BAILOUT:
1375
1376 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1377 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1378 portPriv->DevPriv.ptr, FALSE);
1379 portPriv->isOn = XV_PENDING;
1380 }
1381
1382 RegionUninit(&WinRegion);
1383 RegionUninit(&ClipRegion);
1384
1385 return ret;
1386}
1387
1388static int
1389KdXVGetVideo(ClientPtr client,
1390 DrawablePtr pDraw,
1391 XvPortPtr pPort,
1392 GCPtr pGC,
1393 INT16 vid_x, INT16 vid_y,
1394 CARD16 vid_w, CARD16 vid_h,
1395 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1396{
1397 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1398 int result;
1399
1400 KdScreenPriv(portPriv->screen->pScreen);
1401
1402 /* No pixmaps... For now anyhow */
1403 if (pDraw->type != DRAWABLE_WINDOW) {
1404 pPort->pDraw = (DrawablePtr) NULL;
1405 return BadAlloc;
1406 }
1407
1408 /* If we are changing windows, unregister our port in the old window */
1409 if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1410 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1411
1412 /* Register our port with the new window */
1413 result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1414 if (result != Success)
1415 return result;
1416
1417 portPriv->pDraw = pDraw;
1418 portPriv->type = XvOutputMask;
1419
1420 /* save a copy of these parameters */
1421 portPriv->vid_x = vid_x;
1422 portPriv->vid_y = vid_y;
1423 portPriv->vid_w = vid_w;
1424 portPriv->vid_h = vid_h;
1425 portPriv->drw_x = drw_x;
1426 portPriv->drw_y = drw_y;
1427 portPriv->drw_w = drw_w;
1428 portPriv->drw_h = drw_h;
1429
1430 /* make sure we have the most recent copy of the clientClip */
1431 KdXVCopyClip(portPriv, pGC);
1432
1433 /* To indicate to the DI layer that we were successful */
1434 pPort->pDraw = pDraw;
1435
1436 if (!pScreenPriv->enabled)
1437 return Success;
1438
1439 return (KdXVRegetVideo(portPriv));
1440}
1441
1442static int
1443KdXVGetStill(ClientPtr client,
1444 DrawablePtr pDraw,
1445 XvPortPtr pPort,
1446 GCPtr pGC,
1447 INT16 vid_x, INT16 vid_y,
1448 CARD16 vid_w, CARD16 vid_h,
1449 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1450{
1451 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1452 ScreenPtr pScreen = pDraw->pScreen;
1453
1454 KdScreenPriv(pScreen);
1455 RegionRec WinRegion;
1456 RegionRec ClipRegion;
1457 BoxRec WinBox;
1458 int ret = Success;
1459 Bool clippedAway = FALSE;
1460
1461 if (pDraw->type != DRAWABLE_WINDOW)
1462 return BadAlloc;
1463
1464 if (!pScreenPriv->enabled)
1465 return Success;
1466
1467 WinBox.x1 = pDraw->x + drw_x;
1468 WinBox.y1 = pDraw->y + drw_y;
1469 WinBox.x2 = WinBox.x1 + drw_w;
1470 WinBox.y2 = WinBox.y1 + drw_h;
1471
1472 RegionInit(&WinRegion, &WinBox, 1);
1473 RegionInit(&ClipRegion, NullBox, 1);
1474 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1475
1476 if (portPriv->pDraw) {
1477 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1478 }
1479
1480 if (!RegionNotEmpty(&ClipRegion)) {
1481 clippedAway = TRUE;
1482 goto GET_STILL_BAILOUT;
1483 }
1484
1485 if (portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1486 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
1487 }
1488
1489 ret = (*portPriv->AdaptorRec->GetStill) (portPriv->screen, pDraw,
1490 vid_x, vid_y, WinBox.x1, WinBox.y1,
1491 vid_w, vid_h, drw_w, drw_h,
1492 &ClipRegion,
1493 portPriv->DevPriv.ptr);
1494
1495 GET_STILL_BAILOUT:
1496
1497 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1498 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1499 portPriv->DevPriv.ptr, FALSE);
1500 portPriv->isOn = XV_PENDING;
1501 }
1502
1503 RegionUninit(&WinRegion);
1504 RegionUninit(&ClipRegion);
1505
1506 return ret;
1507}
1508
1509static int
1510KdXVStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
1511{
1512 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1513
1514 KdScreenPriv(portPriv->screen->pScreen);
1515
1516 if (pDraw->type != DRAWABLE_WINDOW)
1517 return BadAlloc;
1518
1519 KdXVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
1520
1521 if (!pScreenPriv->enabled)
1522 return Success;
1523
1524 /* Must free resources. */
1525
1526 if (portPriv->isOn > XV_OFF) {
1527 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1528 portPriv->DevPriv.ptr, TRUE);
1529 portPriv->isOn = XV_OFF;
1530 }
1531
1532 return Success;
1533}
1534
1535static int
1536KdXVSetPortAttribute(ClientPtr client,
1537 XvPortPtr pPort, Atom attribute, INT32 value)
1538{
1539 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1540
1541 return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->screen,
1542 attribute, value,
1543 portPriv->DevPriv.ptr));
1544}
1545
1546static int
1547KdXVGetPortAttribute(ClientPtr client,
1548 XvPortPtr pPort, Atom attribute, INT32 *p_value)
1549{
1550 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1551
1552 return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->screen,
1553 attribute,
1554 (int *) p_value,
1555 portPriv->DevPriv.ptr));
1556}
1557
1558static int
1559KdXVQueryBestSize(ClientPtr client,
1560 XvPortPtr pPort,
1561 CARD8 motion,
1562 CARD16 vid_w, CARD16 vid_h,
1563 CARD16 drw_w, CARD16 drw_h,
1564 unsigned int *p_w, unsigned int *p_h)
1565{
1566 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1567
1568 (*portPriv->AdaptorRec->QueryBestSize) (portPriv->screen,
1569 (Bool) motion, vid_w, vid_h, drw_w,
1570 drw_h, p_w, p_h,
1571 portPriv->DevPriv.ptr);
1572
1573 return Success;
1574}
1575
1576static int
1577KdXVPutImage(ClientPtr client,
1578 DrawablePtr pDraw,
1579 XvPortPtr pPort,
1580 GCPtr pGC,
1581 INT16 src_x, INT16 src_y,
1582 CARD16 src_w, CARD16 src_h,
1583 INT16 drw_x, INT16 drw_y,
1584 CARD16 drw_w, CARD16 drw_h,
1585 XvImagePtr format,
1586 unsigned char *data, Bool sync, CARD16 width, CARD16 height)
1587{
1588 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1589 ScreenPtr pScreen = pDraw->pScreen;
1590
1591 KdScreenPriv(pScreen);
1592 RegionRec WinRegion;
1593 RegionRec ClipRegion;
1594 BoxRec WinBox;
1595 int ret = Success;
1596 Bool clippedAway = FALSE;
1597
1598 if (pDraw->type != DRAWABLE_WINDOW)
1599 return BadAlloc;
1600
1601 if (!pScreenPriv->enabled)
1602 return Success;
1603
1604 WinBox.x1 = pDraw->x + drw_x;
1605 WinBox.y1 = pDraw->y + drw_y;
1606 WinBox.x2 = WinBox.x1 + drw_w;
1607 WinBox.y2 = WinBox.y1 + drw_h;
1608
1609 RegionInit(&WinRegion, &WinBox, 1);
1610 RegionInit(&ClipRegion, NullBox, 1);
1611 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1612
1613 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1614 RegionRec VPReg;
1615 BoxRec VPBox;
1616
1617 VPBox.x1 = 0;
1618 VPBox.y1 = 0;
1619 VPBox.x2 = pScreen->width;
1620 VPBox.y2 = pScreen->height;
1621
1622 RegionInit(&VPReg, &VPBox, 1);
1623 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1624 RegionUninit(&VPReg);
1625 }
1626
1627 if (portPriv->pDraw) {
1628 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1629 }
1630
1631 if (!RegionNotEmpty(&ClipRegion)) {
1632 clippedAway = TRUE;
1633 goto PUT_IMAGE_BAILOUT;
1634 }
1635
1636 if (portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
1637 BoxPtr clipBox = RegionRects(&ClipRegion);
1638
1639 if ((RegionNumRects(&ClipRegion) != 1) ||
1640 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
1641 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) {
1642 clippedAway = TRUE;
1643 goto PUT_IMAGE_BAILOUT;
1644 }
1645 }
1646
1647 if (portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1648 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
1649 }
1650
1651 ret = (*portPriv->AdaptorRec->PutImage) (portPriv->screen, pDraw,
1652 src_x, src_y, WinBox.x1, WinBox.y1,
1653 src_w, src_h, drw_w, drw_h,
1654 format->id, data, width, height,
1655 sync, &ClipRegion,
1656 portPriv->DevPriv.ptr);
1657
1658 if ((ret == Success) &&
1659 (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
1660
1661 KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1662 portPriv->isOn = XV_ON;
1663 portPriv->pDraw = pDraw;
1664 portPriv->drw_x = drw_x;
1665 portPriv->drw_y = drw_y;
1666 portPriv->drw_w = drw_w;
1667 portPriv->drw_h = drw_h;
1668 portPriv->type = 0; /* no mask means it's transient and should
1669 not be reput once it's removed */
1670 pPort->pDraw = pDraw; /* make sure we can get stop requests */
1671 }
1672
1673 PUT_IMAGE_BAILOUT:
1674
1675 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1676 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1677 portPriv->DevPriv.ptr, FALSE);
1678 portPriv->isOn = XV_PENDING;
1679 }
1680
1681 RegionUninit(&WinRegion);
1682 RegionUninit(&ClipRegion);
1683
1684 return ret;
1685}
1686
1687static int
1688KdXVQueryImageAttributes(ClientPtr client,
1689 XvPortPtr pPort,
1690 XvImagePtr format,
1691 CARD16 *width,
1692 CARD16 *height, int *pitches, int *offsets)
1693{
1694 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1695
1696 return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->screen,
1697 format->id, width,
1698 height, pitches,
1699 offsets);
1700}
1701
1702/**************** Common video manipulation functions *******************/
1703
1704void
1705KdXVCopyPackedData(KdScreenInfo * screen, CARD8 *src, CARD8 *dst, int randr,
1706 int srcPitch, int dstPitch, int srcW, int srcH, int top,
1707 int left, int h, int w)
1708{
1709 int srcDown = srcPitch, srcRight = 2, srcNext;
1710 int p;
1711
1712 switch (randr & RR_Rotate_All) {
1713 case RR_Rotate_0:
1714 srcDown = srcPitch;
1715 srcRight = 2;
1716 break;
1717 case RR_Rotate_90:
1718 src += (srcH - 1) * 2;
1719 srcDown = -2;
1720 srcRight = srcPitch;
1721 break;
1722 case RR_Rotate_180:
1723 src += srcPitch * (srcH - 1) + (srcW - 1) * 2;
1724 srcDown = -srcPitch;
1725 srcRight = -2;
1726 break;
1727 case RR_Rotate_270:
1728 src += srcPitch * (srcW - 1);
1729 srcDown = 2;
1730 srcRight = -srcPitch;
1731 break;
1732 }
1733
1734 src = src + top * srcDown + left * srcRight;
1735
1736 w >>= 1;
1737 /* srcRight >>= 1; */
1738 srcNext = srcRight >> 1;
1739 while (h--) {
1740 CARD16 *s = (CARD16 *) src;
1741 CARD32 *d = (CARD32 *) dst;
1742
1743 p = w;
1744 while (p--) {
1745 *d++ = s[0] | (s[srcNext] << 16);
1746 s += srcRight;
1747 }
1748 src += srcPitch;
1749 dst += dstPitch;
1750 }
1751}
1752
1753void
1754KdXVCopyPlanarData(KdScreenInfo * screen, CARD8 *src, CARD8 *dst, int randr,
1755 int srcPitch, int srcPitch2, int dstPitch, int srcW,
1756 int srcH, int height, int top, int left, int h, int w,
1757 int id)
1758{
1759 int i, j;
1760 CARD8 *src1, *src2, *src3, *dst1;
1761 int srcDown = srcPitch, srcDown2 = srcPitch2;
1762 int srcRight = 2, srcRight2 = 1, srcNext = 1;
1763
1764 /* compute source data pointers */
1765 src1 = src;
1766 src2 = src1 + height * srcPitch;
1767 src3 = src2 + (height >> 1) * srcPitch2;
1768 switch (randr & RR_Rotate_All) {
1769 case RR_Rotate_0:
1770 srcDown = srcPitch;
1771 srcDown2 = srcPitch2;
1772 srcRight = 2;
1773 srcRight2 = 1;
1774 srcNext = 1;
1775 break;
1776 case RR_Rotate_90:
1777 src1 = src1 + srcH - 1;
1778 src2 = src2 + (srcH >> 1) - 1;
1779 src3 = src3 + (srcH >> 1) - 1;
1780 srcDown = -1;
1781 srcDown2 = -1;
1782 srcRight = srcPitch * 2;
1783 srcRight2 = srcPitch2;
1784 srcNext = srcPitch;
1785 break;
1786 case RR_Rotate_180:
1787 src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1);
1788 src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
1789 src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
1790 srcDown = -srcPitch;
1791 srcDown2 = -srcPitch2;
1792 srcRight = -2;
1793 srcRight2 = -1;
1794 srcNext = -1;
1795 break;
1796 case RR_Rotate_270:
1797 src1 = src1 + srcPitch * (srcW - 1);
1798 src2 = src2 + srcPitch2 * ((srcW >> 1) - 1);
1799 src3 = src3 + srcPitch2 * ((srcW >> 1) - 1);
1800 srcDown = 1;
1801 srcDown2 = 1;
1802 srcRight = -srcPitch * 2;
1803 srcRight2 = -srcPitch2;
1804 srcNext = -srcPitch;
1805 break;
1806 }
1807
1808 /* adjust for origin */
1809 src1 += top * srcDown + left * srcNext;
1810 src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
1811 src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
1812
1813 if (id == FOURCC_I420) {
1814 CARD8 *srct = src2;
1815
1816 src2 = src3;
1817 src3 = srct;
1818 }
1819
1820 dst1 = dst;
1821
1822 w >>= 1;
1823 for (j = 0; j < h; j++) {
1824 CARD32 *dst = (CARD32 *) dst1;
1825 CARD8 *s1l = src1;
1826 CARD8 *s1r = src1 + srcNext;
1827 CARD8 *s2 = src2;
1828 CARD8 *s3 = src3;
1829
1830 for (i = 0; i < w; i++) {
1831 *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24);
1832 s1l += srcRight;
1833 s1r += srcRight;
1834 s2 += srcRight2;
1835 s3 += srcRight2;
1836 }
1837 src1 += srcDown;
1838 dst1 += dstPitch;
1839 if (j & 1) {
1840 src2 += srcDown2;
1841 src3 += srcDown2;
1842 }
1843 }
1844}
1845
1846void
1847KXVPaintRegion(DrawablePtr pDraw, RegionPtr pRgn, Pixel fg)
1848{
1849 GCPtr pGC;
1850 ChangeGCVal val[2];
1851 xRectangle *rects, *r;
1852 BoxPtr pBox = RegionRects(pRgn);
1853 int nBox = RegionNumRects(pRgn);
1854
1855 rects = malloc(nBox * sizeof(xRectangle));
1856 if (!rects)
1857 goto bail0;
1858 r = rects;
1859 while (nBox--) {
1860 r->x = pBox->x1 - pDraw->x;
1861 r->y = pBox->y1 - pDraw->y;
1862 r->width = pBox->x2 - pBox->x1;
1863 r->height = pBox->y2 - pBox->y1;
1864 r++;
1865 pBox++;
1866 }
1867
1868 pGC = GetScratchGC(pDraw->depth, pDraw->pScreen);
1869 if (!pGC)
1870 goto bail1;
1871
1872 val[0].val = fg;
1873 val[1].val = IncludeInferiors;
1874 ChangeGC(NullClient, pGC, GCForeground | GCSubwindowMode, val);
1875
1876 ValidateGC(pDraw, pGC);
1877
1878 (*pGC->ops->PolyFillRect) (pDraw, pGC, RegionNumRects(pRgn), rects);
1879
1880 FreeScratchGC(pGC);
1881 bail1:
1882 free(rects);
1883 bail0:
1884 ;
1885}