xref: /OK3568_Linux_fs/external/xserver/mi/miexpose.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1987, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun                         All Rights Reserved
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun ******************************************************************/
46*4882a593Smuzhiyun /*****************************************************************
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun Permission is hereby granted, free of charge, to any person obtaining a copy
51*4882a593Smuzhiyun of this software and associated documentation files (the "Software"), to deal
52*4882a593Smuzhiyun in the Software without restriction, including without limitation the rights
53*4882a593Smuzhiyun to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
54*4882a593Smuzhiyun copies of the Software.
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
57*4882a593Smuzhiyun all copies or substantial portions of the Software.
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
62*4882a593Smuzhiyun DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
63*4882a593Smuzhiyun BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
64*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
65*4882a593Smuzhiyun IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun Except as contained in this notice, the name of Digital Equipment Corporation
68*4882a593Smuzhiyun shall not be used in advertising or otherwise to promote the sale, use or other
69*4882a593Smuzhiyun dealings in this Software without prior written authorization from Digital
70*4882a593Smuzhiyun Equipment Corporation.
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun ******************************************************************/
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
75*4882a593Smuzhiyun #include <dix-config.h>
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun #include <X11/X.h>
79*4882a593Smuzhiyun #include <X11/Xproto.h>
80*4882a593Smuzhiyun #include <X11/Xprotostr.h>
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun #include "misc.h"
83*4882a593Smuzhiyun #include "regionstr.h"
84*4882a593Smuzhiyun #include "scrnintstr.h"
85*4882a593Smuzhiyun #include "gcstruct.h"
86*4882a593Smuzhiyun #include "windowstr.h"
87*4882a593Smuzhiyun #include "pixmap.h"
88*4882a593Smuzhiyun #include "input.h"
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun #include "dixstruct.h"
91*4882a593Smuzhiyun #include "mi.h"
92*4882a593Smuzhiyun #include <X11/Xmd.h>
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #include "globals.h"
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun #ifdef PANORAMIX
97*4882a593Smuzhiyun #include "panoramiX.h"
98*4882a593Smuzhiyun #include "panoramiXsrv.h"
99*4882a593Smuzhiyun #endif
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun /*
102*4882a593Smuzhiyun     machine-independent graphics exposure code.  any device that uses
103*4882a593Smuzhiyun the region package can call this.
104*4882a593Smuzhiyun */
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun #ifndef RECTLIMIT
107*4882a593Smuzhiyun #define RECTLIMIT 25            /* pick a number, any number > 8 */
108*4882a593Smuzhiyun #endif
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /* miHandleExposures
111*4882a593Smuzhiyun     generate a region for exposures for areas that were copied from obscured or
112*4882a593Smuzhiyun non-existent areas to non-obscured areas of the destination.  Paint the
113*4882a593Smuzhiyun background for the region, if the destination is a window.
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun NOTE:
116*4882a593Smuzhiyun      this should generally be called, even if graphicsExposures is false,
117*4882a593Smuzhiyun because this is where bits get recovered from backing store.
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun RegionPtr
miHandleExposures(DrawablePtr pSrcDrawable,DrawablePtr pDstDrawable,GCPtr pGC,int srcx,int srcy,int width,int height,int dstx,int dsty)122*4882a593Smuzhiyun miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
123*4882a593Smuzhiyun                   GCPtr pGC, int srcx, int srcy, int width, int height,
124*4882a593Smuzhiyun                   int dstx, int dsty)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun     RegionPtr prgnSrcClip;      /* drawable-relative source clip */
127*4882a593Smuzhiyun     RegionRec rgnSrcRec;
128*4882a593Smuzhiyun     RegionPtr prgnDstClip;      /* drawable-relative dest clip */
129*4882a593Smuzhiyun     RegionRec rgnDstRec;
130*4882a593Smuzhiyun     BoxRec srcBox;              /* unclipped source */
131*4882a593Smuzhiyun     RegionRec rgnExposed;       /* exposed region, calculated source-
132*4882a593Smuzhiyun                                    relative, made dst relative to
133*4882a593Smuzhiyun                                    intersect with visible parts of
134*4882a593Smuzhiyun                                    dest and send events to client,
135*4882a593Smuzhiyun                                    and then screen relative to paint
136*4882a593Smuzhiyun                                    the window background
137*4882a593Smuzhiyun                                  */
138*4882a593Smuzhiyun     WindowPtr pSrcWin;
139*4882a593Smuzhiyun     BoxRec expBox = { 0, };
140*4882a593Smuzhiyun     Bool extents;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun     /* avoid work if we can */
143*4882a593Smuzhiyun     if (!pGC->graphicsExposures &&
144*4882a593Smuzhiyun         (pDstDrawable->type == DRAWABLE_PIXMAP) &&
145*4882a593Smuzhiyun         ((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
146*4882a593Smuzhiyun          (((WindowPtr) pSrcDrawable)->backStorage == 0)))
147*4882a593Smuzhiyun         return NULL;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun     srcBox.x1 = srcx;
150*4882a593Smuzhiyun     srcBox.y1 = srcy;
151*4882a593Smuzhiyun     srcBox.x2 = srcx + width;
152*4882a593Smuzhiyun     srcBox.y2 = srcy + height;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun     if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
155*4882a593Smuzhiyun         BoxRec TsrcBox;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun         TsrcBox.x1 = srcx + pSrcDrawable->x;
158*4882a593Smuzhiyun         TsrcBox.y1 = srcy + pSrcDrawable->y;
159*4882a593Smuzhiyun         TsrcBox.x2 = TsrcBox.x1 + width;
160*4882a593Smuzhiyun         TsrcBox.y2 = TsrcBox.y1 + height;
161*4882a593Smuzhiyun         pSrcWin = (WindowPtr) pSrcDrawable;
162*4882a593Smuzhiyun         if (pGC->subWindowMode == IncludeInferiors) {
163*4882a593Smuzhiyun             prgnSrcClip = NotClippedByChildren(pSrcWin);
164*4882a593Smuzhiyun             if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) {
165*4882a593Smuzhiyun                 RegionDestroy(prgnSrcClip);
166*4882a593Smuzhiyun                 return NULL;
167*4882a593Smuzhiyun             }
168*4882a593Smuzhiyun         }
169*4882a593Smuzhiyun         else {
170*4882a593Smuzhiyun             if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
171*4882a593Smuzhiyun                 return NULL;
172*4882a593Smuzhiyun             prgnSrcClip = &rgnSrcRec;
173*4882a593Smuzhiyun             RegionNull(prgnSrcClip);
174*4882a593Smuzhiyun             RegionCopy(prgnSrcClip, &pSrcWin->clipList);
175*4882a593Smuzhiyun         }
176*4882a593Smuzhiyun         RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y);
177*4882a593Smuzhiyun     }
178*4882a593Smuzhiyun     else {
179*4882a593Smuzhiyun         BoxRec box;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun         if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
182*4882a593Smuzhiyun             (srcBox.x2 <= pSrcDrawable->width) &&
183*4882a593Smuzhiyun             (srcBox.y2 <= pSrcDrawable->height))
184*4882a593Smuzhiyun             return NULL;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun         box.x1 = 0;
187*4882a593Smuzhiyun         box.y1 = 0;
188*4882a593Smuzhiyun         box.x2 = pSrcDrawable->width;
189*4882a593Smuzhiyun         box.y2 = pSrcDrawable->height;
190*4882a593Smuzhiyun         prgnSrcClip = &rgnSrcRec;
191*4882a593Smuzhiyun         RegionInit(prgnSrcClip, &box, 1);
192*4882a593Smuzhiyun         pSrcWin = NULL;
193*4882a593Smuzhiyun     }
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun     if (pDstDrawable == pSrcDrawable) {
196*4882a593Smuzhiyun         prgnDstClip = prgnSrcClip;
197*4882a593Smuzhiyun     }
198*4882a593Smuzhiyun     else if (pDstDrawable->type != DRAWABLE_PIXMAP) {
199*4882a593Smuzhiyun         if (pGC->subWindowMode == IncludeInferiors) {
200*4882a593Smuzhiyun             prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable);
201*4882a593Smuzhiyun         }
202*4882a593Smuzhiyun         else {
203*4882a593Smuzhiyun             prgnDstClip = &rgnDstRec;
204*4882a593Smuzhiyun             RegionNull(prgnDstClip);
205*4882a593Smuzhiyun             RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList);
206*4882a593Smuzhiyun         }
207*4882a593Smuzhiyun         RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y);
208*4882a593Smuzhiyun     }
209*4882a593Smuzhiyun     else {
210*4882a593Smuzhiyun         BoxRec box;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun         box.x1 = 0;
213*4882a593Smuzhiyun         box.y1 = 0;
214*4882a593Smuzhiyun         box.x2 = pDstDrawable->width;
215*4882a593Smuzhiyun         box.y2 = pDstDrawable->height;
216*4882a593Smuzhiyun         prgnDstClip = &rgnDstRec;
217*4882a593Smuzhiyun         RegionInit(prgnDstClip, &box, 1);
218*4882a593Smuzhiyun     }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun     /* drawable-relative source region */
221*4882a593Smuzhiyun     RegionInit(&rgnExposed, &srcBox, 1);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun     /* now get the hidden parts of the source box */
224*4882a593Smuzhiyun     RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun     /* move them over the destination */
227*4882a593Smuzhiyun     RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun     /* intersect with visible areas of dest */
230*4882a593Smuzhiyun     RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun     /* intersect with client clip region. */
233*4882a593Smuzhiyun     if (pGC->clientClip)
234*4882a593Smuzhiyun         RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     /*
237*4882a593Smuzhiyun      * If we have LOTS of rectangles, we decide to take the extents
238*4882a593Smuzhiyun      * and force an exposure on that.  This should require much less
239*4882a593Smuzhiyun      * work overall, on both client and server.  This is cheating, but
240*4882a593Smuzhiyun      * isn't prohibited by the protocol ("spontaneous combustion" :-)
241*4882a593Smuzhiyun      * for windows.
242*4882a593Smuzhiyun      */
243*4882a593Smuzhiyun     extents = pGC->graphicsExposures &&
244*4882a593Smuzhiyun         (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
245*4882a593Smuzhiyun         (pDstDrawable->type != DRAWABLE_PIXMAP);
246*4882a593Smuzhiyun     if (pSrcWin) {
247*4882a593Smuzhiyun         RegionPtr region;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun         if (!(region = wClipShape(pSrcWin)))
250*4882a593Smuzhiyun             region = wBoundingShape(pSrcWin);
251*4882a593Smuzhiyun         /*
252*4882a593Smuzhiyun          * If you try to CopyArea the extents of a shaped window, compacting the
253*4882a593Smuzhiyun          * exposed region will undo all our work!
254*4882a593Smuzhiyun          */
255*4882a593Smuzhiyun         if (extents && pSrcWin && region &&
256*4882a593Smuzhiyun             (RegionContainsRect(region, &srcBox) != rgnIN))
257*4882a593Smuzhiyun             extents = FALSE;
258*4882a593Smuzhiyun     }
259*4882a593Smuzhiyun     if (extents) {
260*4882a593Smuzhiyun         expBox = *RegionExtents(&rgnExposed);
261*4882a593Smuzhiyun         RegionReset(&rgnExposed, &expBox);
262*4882a593Smuzhiyun     }
263*4882a593Smuzhiyun     if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
264*4882a593Smuzhiyun         (((WindowPtr) pDstDrawable)->backgroundState != None)) {
265*4882a593Smuzhiyun         WindowPtr pWin = (WindowPtr) pDstDrawable;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun         /* make the exposed area screen-relative */
268*4882a593Smuzhiyun         RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun         if (extents) {
271*4882a593Smuzhiyun             /* PaintWindow doesn't clip, so we have to */
272*4882a593Smuzhiyun             RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
273*4882a593Smuzhiyun         }
274*4882a593Smuzhiyun         pDstDrawable->pScreen->PaintWindow((WindowPtr) pDstDrawable,
275*4882a593Smuzhiyun                                            &rgnExposed, PW_BACKGROUND);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun         if (extents) {
278*4882a593Smuzhiyun             RegionReset(&rgnExposed, &expBox);
279*4882a593Smuzhiyun         }
280*4882a593Smuzhiyun         else
281*4882a593Smuzhiyun             RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y);
282*4882a593Smuzhiyun     }
283*4882a593Smuzhiyun     if (prgnDstClip == &rgnDstRec) {
284*4882a593Smuzhiyun         RegionUninit(prgnDstClip);
285*4882a593Smuzhiyun     }
286*4882a593Smuzhiyun     else if (prgnDstClip != prgnSrcClip) {
287*4882a593Smuzhiyun         RegionDestroy(prgnDstClip);
288*4882a593Smuzhiyun     }
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     if (prgnSrcClip == &rgnSrcRec) {
291*4882a593Smuzhiyun         RegionUninit(prgnSrcClip);
292*4882a593Smuzhiyun     }
293*4882a593Smuzhiyun     else {
294*4882a593Smuzhiyun         RegionDestroy(prgnSrcClip);
295*4882a593Smuzhiyun     }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     if (pGC->graphicsExposures) {
298*4882a593Smuzhiyun         /* don't look */
299*4882a593Smuzhiyun         RegionPtr exposed = RegionCreate(NullBox, 0);
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun         *exposed = rgnExposed;
302*4882a593Smuzhiyun         return exposed;
303*4882a593Smuzhiyun     }
304*4882a593Smuzhiyun     else {
305*4882a593Smuzhiyun         RegionUninit(&rgnExposed);
306*4882a593Smuzhiyun         return NULL;
307*4882a593Smuzhiyun     }
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun void
miSendExposures(WindowPtr pWin,RegionPtr pRgn,int dx,int dy)311*4882a593Smuzhiyun miSendExposures(WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun     BoxPtr pBox;
314*4882a593Smuzhiyun     int numRects;
315*4882a593Smuzhiyun     xEvent *pEvent, *pe;
316*4882a593Smuzhiyun     int i;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun     pBox = RegionRects(pRgn);
319*4882a593Smuzhiyun     numRects = RegionNumRects(pRgn);
320*4882a593Smuzhiyun     if (!(pEvent = calloc(1, numRects * sizeof(xEvent))))
321*4882a593Smuzhiyun         return;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun     for (i = numRects, pe = pEvent; --i >= 0; pe++, pBox++) {
324*4882a593Smuzhiyun         pe->u.u.type = Expose;
325*4882a593Smuzhiyun         pe->u.expose.window = pWin->drawable.id;
326*4882a593Smuzhiyun         pe->u.expose.x = pBox->x1 - dx;
327*4882a593Smuzhiyun         pe->u.expose.y = pBox->y1 - dy;
328*4882a593Smuzhiyun         pe->u.expose.width = pBox->x2 - pBox->x1;
329*4882a593Smuzhiyun         pe->u.expose.height = pBox->y2 - pBox->y1;
330*4882a593Smuzhiyun         pe->u.expose.count = i;
331*4882a593Smuzhiyun     }
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun #ifdef PANORAMIX
334*4882a593Smuzhiyun     if (!noPanoramiXExtension) {
335*4882a593Smuzhiyun         int scrnum = pWin->drawable.pScreen->myNum;
336*4882a593Smuzhiyun         int x = 0, y = 0;
337*4882a593Smuzhiyun         XID realWin = 0;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun         if (!pWin->parent) {
340*4882a593Smuzhiyun             x = screenInfo.screens[scrnum]->x;
341*4882a593Smuzhiyun             y = screenInfo.screens[scrnum]->y;
342*4882a593Smuzhiyun             pWin = screenInfo.screens[0]->root;
343*4882a593Smuzhiyun             realWin = pWin->drawable.id;
344*4882a593Smuzhiyun         }
345*4882a593Smuzhiyun         else if (scrnum) {
346*4882a593Smuzhiyun             PanoramiXRes *win;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun             win = PanoramiXFindIDByScrnum(XRT_WINDOW,
349*4882a593Smuzhiyun                                           pWin->drawable.id, scrnum);
350*4882a593Smuzhiyun             if (!win) {
351*4882a593Smuzhiyun                 free(pEvent);
352*4882a593Smuzhiyun                 return;
353*4882a593Smuzhiyun             }
354*4882a593Smuzhiyun             realWin = win->info[0].id;
355*4882a593Smuzhiyun             dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
356*4882a593Smuzhiyun         }
357*4882a593Smuzhiyun         if (x || y || scrnum)
358*4882a593Smuzhiyun             for (i = 0; i < numRects; i++) {
359*4882a593Smuzhiyun                 pEvent[i].u.expose.window = realWin;
360*4882a593Smuzhiyun                 pEvent[i].u.expose.x += x;
361*4882a593Smuzhiyun                 pEvent[i].u.expose.y += y;
362*4882a593Smuzhiyun             }
363*4882a593Smuzhiyun     }
364*4882a593Smuzhiyun #endif
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun     DeliverEvents(pWin, pEvent, numRects, NullWindow);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun     free(pEvent);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun void
miWindowExposures(WindowPtr pWin,RegionPtr prgn)372*4882a593Smuzhiyun miWindowExposures(WindowPtr pWin, RegionPtr prgn)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun     RegionPtr exposures = prgn;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun     if (prgn && !RegionNil(prgn)) {
377*4882a593Smuzhiyun         RegionRec expRec;
378*4882a593Smuzhiyun         int clientInterested =
379*4882a593Smuzhiyun             (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
380*4882a593Smuzhiyun         if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) {
381*4882a593Smuzhiyun             /*
382*4882a593Smuzhiyun              * If we have LOTS of rectangles, we decide to take the extents
383*4882a593Smuzhiyun              * and force an exposure on that.  This should require much less
384*4882a593Smuzhiyun              * work overall, on both client and server.  This is cheating, but
385*4882a593Smuzhiyun              * isn't prohibited by the protocol ("spontaneous combustion" :-).
386*4882a593Smuzhiyun              */
387*4882a593Smuzhiyun             BoxRec box = *RegionExtents(prgn);
388*4882a593Smuzhiyun             exposures = &expRec;
389*4882a593Smuzhiyun             RegionInit(exposures, &box, 1);
390*4882a593Smuzhiyun             RegionReset(prgn, &box);
391*4882a593Smuzhiyun             /* miPaintWindow doesn't clip, so we have to */
392*4882a593Smuzhiyun             RegionIntersect(prgn, prgn, &pWin->clipList);
393*4882a593Smuzhiyun         }
394*4882a593Smuzhiyun         pWin->drawable.pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND);
395*4882a593Smuzhiyun         if (clientInterested)
396*4882a593Smuzhiyun             miSendExposures(pWin, exposures,
397*4882a593Smuzhiyun                             pWin->drawable.x, pWin->drawable.y);
398*4882a593Smuzhiyun         if (exposures == &expRec)
399*4882a593Smuzhiyun             RegionUninit(exposures);
400*4882a593Smuzhiyun         RegionEmpty(prgn);
401*4882a593Smuzhiyun     }
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun void
miPaintWindow(WindowPtr pWin,RegionPtr prgn,int what)405*4882a593Smuzhiyun miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
408*4882a593Smuzhiyun     ChangeGCVal gcval[6];
409*4882a593Smuzhiyun     BITS32 gcmask;
410*4882a593Smuzhiyun     GCPtr pGC;
411*4882a593Smuzhiyun     int i;
412*4882a593Smuzhiyun     BoxPtr pbox;
413*4882a593Smuzhiyun     xRectangle *prect;
414*4882a593Smuzhiyun     int numRects;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun     /*
417*4882a593Smuzhiyun      * Distance from screen to destination drawable, use this
418*4882a593Smuzhiyun      * to adjust rendering coordinates which come in in screen space
419*4882a593Smuzhiyun      */
420*4882a593Smuzhiyun     int draw_x_off, draw_y_off;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun     /*
423*4882a593Smuzhiyun      * Tile offset for drawing; these need to align the tile
424*4882a593Smuzhiyun      * to the appropriate window origin
425*4882a593Smuzhiyun      */
426*4882a593Smuzhiyun     int tile_x_off, tile_y_off;
427*4882a593Smuzhiyun     PixUnion fill;
428*4882a593Smuzhiyun     Bool solid = TRUE;
429*4882a593Smuzhiyun     DrawablePtr drawable = &pWin->drawable;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun     if (what == PW_BACKGROUND) {
432*4882a593Smuzhiyun         while (pWin->backgroundState == ParentRelative)
433*4882a593Smuzhiyun             pWin = pWin->parent;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun         draw_x_off = drawable->x;
436*4882a593Smuzhiyun         draw_y_off = drawable->y;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun         tile_x_off = pWin->drawable.x - draw_x_off;
439*4882a593Smuzhiyun         tile_y_off = pWin->drawable.y - draw_y_off;
440*4882a593Smuzhiyun         fill = pWin->background;
441*4882a593Smuzhiyun #ifdef COMPOSITE
442*4882a593Smuzhiyun         if (pWin->inhibitBGPaint)
443*4882a593Smuzhiyun             return;
444*4882a593Smuzhiyun #endif
445*4882a593Smuzhiyun         switch (pWin->backgroundState) {
446*4882a593Smuzhiyun         case None:
447*4882a593Smuzhiyun             return;
448*4882a593Smuzhiyun         case BackgroundPixmap:
449*4882a593Smuzhiyun             solid = FALSE;
450*4882a593Smuzhiyun             break;
451*4882a593Smuzhiyun         }
452*4882a593Smuzhiyun     }
453*4882a593Smuzhiyun     else {
454*4882a593Smuzhiyun         PixmapPtr pixmap;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun         fill = pWin->border;
457*4882a593Smuzhiyun         solid = pWin->borderIsPixel;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun         /* servers without pixmaps draw their own borders */
460*4882a593Smuzhiyun         if (!pScreen->GetWindowPixmap)
461*4882a593Smuzhiyun             return;
462*4882a593Smuzhiyun         pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
463*4882a593Smuzhiyun         drawable = &pixmap->drawable;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun         while (pWin->backgroundState == ParentRelative)
466*4882a593Smuzhiyun             pWin = pWin->parent;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun         tile_x_off = pWin->drawable.x;
469*4882a593Smuzhiyun         tile_y_off = pWin->drawable.y;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun #ifdef COMPOSITE
472*4882a593Smuzhiyun         draw_x_off = pixmap->screen_x;
473*4882a593Smuzhiyun         draw_y_off = pixmap->screen_y;
474*4882a593Smuzhiyun         tile_x_off -= draw_x_off;
475*4882a593Smuzhiyun         tile_y_off -= draw_y_off;
476*4882a593Smuzhiyun #else
477*4882a593Smuzhiyun         draw_x_off = 0;
478*4882a593Smuzhiyun         draw_y_off = 0;
479*4882a593Smuzhiyun #endif
480*4882a593Smuzhiyun     }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun     gcval[0].val = GXcopy;
483*4882a593Smuzhiyun     gcmask = GCFunction;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun #ifdef ROOTLESS_SAFEALPHA
486*4882a593Smuzhiyun /* Bit mask for alpha channel with a particular number of bits per
487*4882a593Smuzhiyun  * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
488*4882a593Smuzhiyun  * alpha for 16bpp.
489*4882a593Smuzhiyun  */
490*4882a593Smuzhiyun #define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
491*4882a593Smuzhiyun #endif
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun     if (solid) {
494*4882a593Smuzhiyun #ifdef ROOTLESS_SAFEALPHA
495*4882a593Smuzhiyun         gcval[1].val =
496*4882a593Smuzhiyun             fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
497*4882a593Smuzhiyun #else
498*4882a593Smuzhiyun         gcval[1].val = fill.pixel;
499*4882a593Smuzhiyun #endif
500*4882a593Smuzhiyun         gcval[2].val = FillSolid;
501*4882a593Smuzhiyun         gcmask |= GCForeground | GCFillStyle;
502*4882a593Smuzhiyun     }
503*4882a593Smuzhiyun     else {
504*4882a593Smuzhiyun         int c = 1;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun #ifdef ROOTLESS_SAFEALPHA
507*4882a593Smuzhiyun         gcval[c++].val =
508*4882a593Smuzhiyun             ((CARD32) -1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
509*4882a593Smuzhiyun         gcmask |= GCPlaneMask;
510*4882a593Smuzhiyun #endif
511*4882a593Smuzhiyun         gcval[c++].val = FillTiled;
512*4882a593Smuzhiyun         gcval[c++].ptr = (void *) fill.pixmap;
513*4882a593Smuzhiyun         gcval[c++].val = tile_x_off;
514*4882a593Smuzhiyun         gcval[c++].val = tile_y_off;
515*4882a593Smuzhiyun         gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
516*4882a593Smuzhiyun     }
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun     prect = xallocarray(RegionNumRects(prgn), sizeof(xRectangle));
519*4882a593Smuzhiyun     if (!prect)
520*4882a593Smuzhiyun         return;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun     pGC = GetScratchGC(drawable->depth, drawable->pScreen);
523*4882a593Smuzhiyun     if (!pGC) {
524*4882a593Smuzhiyun         free(prect);
525*4882a593Smuzhiyun         return;
526*4882a593Smuzhiyun     }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, gcmask, gcval);
529*4882a593Smuzhiyun     ValidateGC(drawable, pGC);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun     numRects = RegionNumRects(prgn);
532*4882a593Smuzhiyun     pbox = RegionRects(prgn);
533*4882a593Smuzhiyun     for (i = numRects; --i >= 0; pbox++, prect++) {
534*4882a593Smuzhiyun         prect->x = pbox->x1 - draw_x_off;
535*4882a593Smuzhiyun         prect->y = pbox->y1 - draw_y_off;
536*4882a593Smuzhiyun         prect->width = pbox->x2 - pbox->x1;
537*4882a593Smuzhiyun         prect->height = pbox->y2 - pbox->y1;
538*4882a593Smuzhiyun     }
539*4882a593Smuzhiyun     prect -= numRects;
540*4882a593Smuzhiyun     (*pGC->ops->PolyFillRect) (drawable, pGC, numRects, prect);
541*4882a593Smuzhiyun     free(prect);
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun     FreeScratchGC(pGC);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun /* MICLEARDRAWABLE -- sets the entire drawable to the background color of
547*4882a593Smuzhiyun  * the GC.  Useful when we have a scratch drawable and need to initialize
548*4882a593Smuzhiyun  * it. */
549*4882a593Smuzhiyun void
miClearDrawable(DrawablePtr pDraw,GCPtr pGC)550*4882a593Smuzhiyun miClearDrawable(DrawablePtr pDraw, GCPtr pGC)
551*4882a593Smuzhiyun {
552*4882a593Smuzhiyun     ChangeGCVal fg, bg;
553*4882a593Smuzhiyun     xRectangle rect;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun     fg.val = pGC->fgPixel;
556*4882a593Smuzhiyun     bg.val = pGC->bgPixel;
557*4882a593Smuzhiyun     rect.x = 0;
558*4882a593Smuzhiyun     rect.y = 0;
559*4882a593Smuzhiyun     rect.width = pDraw->width;
560*4882a593Smuzhiyun     rect.height = pDraw->height;
561*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, GCForeground, &bg);
562*4882a593Smuzhiyun     ValidateGC(pDraw, pGC);
563*4882a593Smuzhiyun     (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
564*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, GCForeground, &fg);
565*4882a593Smuzhiyun     ValidateGC(pDraw, pGC);
566*4882a593Smuzhiyun }
567