xref: /OK3568_Linux_fs/external/xserver/hw/dmx/dmxgc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * All Rights Reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining
7*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
8*4882a593Smuzhiyun  * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun  * without limitation on the rights to use, copy, modify, merge,
10*4882a593Smuzhiyun  * publish, distribute, sublicense, and/or sell copies of the Software,
11*4882a593Smuzhiyun  * and to permit persons to whom the Software is furnished to do so,
12*4882a593Smuzhiyun  * subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun  * next paragraph) shall be included in all copies or substantial
16*4882a593Smuzhiyun  * portions of the Software.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*4882a593Smuzhiyun  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*4882a593Smuzhiyun  * SOFTWARE.
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * Authors:
30*4882a593Smuzhiyun  *   Kevin E. Martin <kem@redhat.com>
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /** \file
35*4882a593Smuzhiyun  * This file provides support for GCs. */
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #ifdef HAVE_DMX_CONFIG_H
38*4882a593Smuzhiyun #include <dmx-config.h>
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include "dmx.h"
42*4882a593Smuzhiyun #include "dmxsync.h"
43*4882a593Smuzhiyun #include "dmxgc.h"
44*4882a593Smuzhiyun #include "dmxgcops.h"
45*4882a593Smuzhiyun #include "dmxpixmap.h"
46*4882a593Smuzhiyun #include "dmxfont.h"
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #include "gcstruct.h"
49*4882a593Smuzhiyun #include "pixmapstr.h"
50*4882a593Smuzhiyun #include "migc.h"
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun static const GCFuncs dmxGCFuncs = {
53*4882a593Smuzhiyun     dmxValidateGC,
54*4882a593Smuzhiyun     dmxChangeGC,
55*4882a593Smuzhiyun     dmxCopyGC,
56*4882a593Smuzhiyun     dmxDestroyGC,
57*4882a593Smuzhiyun     dmxChangeClip,
58*4882a593Smuzhiyun     dmxDestroyClip,
59*4882a593Smuzhiyun     dmxCopyClip,
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static const GCOps dmxGCOps = {
63*4882a593Smuzhiyun     dmxFillSpans,
64*4882a593Smuzhiyun     dmxSetSpans,
65*4882a593Smuzhiyun     dmxPutImage,
66*4882a593Smuzhiyun     dmxCopyArea,
67*4882a593Smuzhiyun     dmxCopyPlane,
68*4882a593Smuzhiyun     dmxPolyPoint,
69*4882a593Smuzhiyun     dmxPolylines,
70*4882a593Smuzhiyun     dmxPolySegment,
71*4882a593Smuzhiyun     dmxPolyRectangle,
72*4882a593Smuzhiyun     dmxPolyArc,
73*4882a593Smuzhiyun     dmxFillPolygon,
74*4882a593Smuzhiyun     dmxPolyFillRect,
75*4882a593Smuzhiyun     dmxPolyFillArc,
76*4882a593Smuzhiyun     dmxPolyText8,
77*4882a593Smuzhiyun     dmxPolyText16,
78*4882a593Smuzhiyun     dmxImageText8,
79*4882a593Smuzhiyun     dmxImageText16,
80*4882a593Smuzhiyun     dmxImageGlyphBlt,
81*4882a593Smuzhiyun     dmxPolyGlyphBlt,
82*4882a593Smuzhiyun     dmxPushPixels
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /** Initialize the GC on \a pScreen */
86*4882a593Smuzhiyun Bool
dmxInitGC(ScreenPtr pScreen)87*4882a593Smuzhiyun dmxInitGC(ScreenPtr pScreen)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun     if (!dixRegisterPrivateKey
90*4882a593Smuzhiyun         (&dmxGCPrivateKeyRec, PRIVATE_GC, sizeof(dmxGCPrivRec)))
91*4882a593Smuzhiyun         return FALSE;
92*4882a593Smuzhiyun     return TRUE;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /** Create the GC on the back-end server. */
96*4882a593Smuzhiyun void
dmxBECreateGC(ScreenPtr pScreen,GCPtr pGC)97*4882a593Smuzhiyun dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
100*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
101*4882a593Smuzhiyun     int i;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun     for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
104*4882a593Smuzhiyun         if (pGC->depth == dmxScreen->bePixmapFormats[i].depth) {
105*4882a593Smuzhiyun             unsigned long mask;
106*4882a593Smuzhiyun             XGCValues gcvals;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun             mask = GCGraphicsExposures;
109*4882a593Smuzhiyun             gcvals.graphics_exposures = FALSE;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun             /* Create GC in the back-end servers */
112*4882a593Smuzhiyun             pGCPriv->gc = XCreateGC(dmxScreen->beDisplay,
113*4882a593Smuzhiyun                                     dmxScreen->scrnDefDrawables[i],
114*4882a593Smuzhiyun                                     mask, &gcvals);
115*4882a593Smuzhiyun             break;
116*4882a593Smuzhiyun         }
117*4882a593Smuzhiyun     }
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun /** Create a graphics context on the back-end server associated /a pGC's
121*4882a593Smuzhiyun  *  screen. */
122*4882a593Smuzhiyun Bool
dmxCreateGC(GCPtr pGC)123*4882a593Smuzhiyun dmxCreateGC(GCPtr pGC)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun     ScreenPtr pScreen = pGC->pScreen;
126*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
127*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
128*4882a593Smuzhiyun     Bool ret;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun     DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
131*4882a593Smuzhiyun     if ((ret = pScreen->CreateGC(pGC))) {
132*4882a593Smuzhiyun         /* Save the old funcs */
133*4882a593Smuzhiyun         pGCPriv->funcs = pGC->funcs;
134*4882a593Smuzhiyun         pGCPriv->ops = NULL;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun         pGC->funcs = &dmxGCFuncs;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun         if (dmxScreen->beDisplay) {
139*4882a593Smuzhiyun             dmxBECreateGC(pScreen, pGC);
140*4882a593Smuzhiyun         }
141*4882a593Smuzhiyun         else {
142*4882a593Smuzhiyun             pGCPriv->gc = NULL;
143*4882a593Smuzhiyun         }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun         /* Check for "magic special case"
146*4882a593Smuzhiyun          * 1. see CreateGC in dix/gc.c for more info
147*4882a593Smuzhiyun          * 2. see dmxChangeGC for more info
148*4882a593Smuzhiyun          */
149*4882a593Smuzhiyun         pGCPriv->msc = (!pGC->tileIsPixel && !pGC->tile.pixmap);
150*4882a593Smuzhiyun     }
151*4882a593Smuzhiyun     DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun     return ret;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /** Validate a graphics context, \a pGC, locally in the DMX server and
157*4882a593Smuzhiyun  *  recompute the composite clip, if necessary. */
158*4882a593Smuzhiyun void
dmxValidateGC(GCPtr pGC,unsigned long changes,DrawablePtr pDrawable)159*4882a593Smuzhiyun dmxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGC);
164*4882a593Smuzhiyun #if 0
165*4882a593Smuzhiyun     pGC->funcs->ValidateGC(pGC, changes, pDrawable);
166*4882a593Smuzhiyun #endif
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun     if (pDrawable->type == DRAWABLE_WINDOW ||
169*4882a593Smuzhiyun         pDrawable->type == DRAWABLE_PIXMAP) {
170*4882a593Smuzhiyun         /* Save the old ops, since we're about to change the ops in the
171*4882a593Smuzhiyun          * epilogue.
172*4882a593Smuzhiyun          */
173*4882a593Smuzhiyun         pGCPriv->ops = pGC->ops;
174*4882a593Smuzhiyun     }
175*4882a593Smuzhiyun     else {
176*4882a593Smuzhiyun         pGCPriv->ops = NULL;
177*4882a593Smuzhiyun     }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun     /* If the client clip is different or moved OR the subwindowMode has
180*4882a593Smuzhiyun      * changed OR the window's clip has changed since the last
181*4882a593Smuzhiyun      * validation, then we need to recompute the composite clip.
182*4882a593Smuzhiyun      */
183*4882a593Smuzhiyun     if ((changes & (GCClipXOrigin |
184*4882a593Smuzhiyun                     GCClipYOrigin |
185*4882a593Smuzhiyun                     GCClipMask |
186*4882a593Smuzhiyun                     GCSubwindowMode)) ||
187*4882a593Smuzhiyun         (pDrawable->serialNumber !=
188*4882a593Smuzhiyun          (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) {
189*4882a593Smuzhiyun         miComputeCompositeClip(pGC, pDrawable);
190*4882a593Smuzhiyun     }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGC);
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun /** Set the values in the graphics context on the back-end server
196*4882a593Smuzhiyun  *  associated with \a pGC's screen. */
197*4882a593Smuzhiyun void
dmxChangeGC(GCPtr pGC,unsigned long mask)198*4882a593Smuzhiyun dmxChangeGC(GCPtr pGC, unsigned long mask)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun     ScreenPtr pScreen = pGC->pScreen;
201*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
202*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
203*4882a593Smuzhiyun     XGCValues v;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGC);
206*4882a593Smuzhiyun #if 0
207*4882a593Smuzhiyun     pGC->funcs->ChangeGC(pGC, mask);
208*4882a593Smuzhiyun #endif
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun     /* Handle "magic special case" from CreateGC */
211*4882a593Smuzhiyun     if (pGCPriv->msc) {
212*4882a593Smuzhiyun         /* The "magic special case" is used to handle the case where a
213*4882a593Smuzhiyun          * foreground pixel is set when the GC is created so that a
214*4882a593Smuzhiyun          * "pseudo default-tile" can be created and used in case the
215*4882a593Smuzhiyun          * fillstyle was set to FillTiled.  This specific case is tested
216*4882a593Smuzhiyun          * in xtest (XCreateGC test #3).  What has happened in dix by
217*4882a593Smuzhiyun          * the time it reaches here is (1) the pGC->tile.pixel has been
218*4882a593Smuzhiyun          * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a
219*4882a593Smuzhiyun          * tile has also been set, then pGC->tileIsPixel is unset and
220*4882a593Smuzhiyun          * pGC->tile.pixmap is initialized; else, the default tile is
221*4882a593Smuzhiyun          * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is
222*4882a593Smuzhiyun          * initialized to the "pseudo default-tile".  In either case,
223*4882a593Smuzhiyun          * pGC->tile.pixmap is set; however, in the "magic special case"
224*4882a593Smuzhiyun          * the mask is not updated to allow us to detect that we should
225*4882a593Smuzhiyun          * initialize the GCTile in the back-end server.  Thus, we catch
226*4882a593Smuzhiyun          * this case in dmxCreateGC and add GCTile to the mask here.
227*4882a593Smuzhiyun          * Are there any cases that I've missed?
228*4882a593Smuzhiyun          */
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun         /* Make sure that the tile.pixmap is set, just in case the user
231*4882a593Smuzhiyun          * set GCTile in the mask but forgot to set vals.pixmap
232*4882a593Smuzhiyun          */
233*4882a593Smuzhiyun         if (pGC->tile.pixmap)
234*4882a593Smuzhiyun             mask |= GCTile;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun         /* This only happens once when the GC is created */
237*4882a593Smuzhiyun         pGCPriv->msc = FALSE;
238*4882a593Smuzhiyun     }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun     /* Update back-end server's gc */
241*4882a593Smuzhiyun     if (mask & GCFunction)
242*4882a593Smuzhiyun         v.function = pGC->alu;
243*4882a593Smuzhiyun     if (mask & GCPlaneMask)
244*4882a593Smuzhiyun         v.plane_mask = pGC->planemask;
245*4882a593Smuzhiyun     if (mask & GCForeground)
246*4882a593Smuzhiyun         v.foreground = pGC->fgPixel;
247*4882a593Smuzhiyun     if (mask & GCBackground)
248*4882a593Smuzhiyun         v.background = pGC->bgPixel;
249*4882a593Smuzhiyun     if (mask & GCLineWidth)
250*4882a593Smuzhiyun         v.line_width = pGC->lineWidth;
251*4882a593Smuzhiyun     if (mask & GCLineStyle)
252*4882a593Smuzhiyun         v.line_style = pGC->lineStyle;
253*4882a593Smuzhiyun     if (mask & GCCapStyle)
254*4882a593Smuzhiyun         v.cap_style = pGC->capStyle;
255*4882a593Smuzhiyun     if (mask & GCJoinStyle)
256*4882a593Smuzhiyun         v.join_style = pGC->joinStyle;
257*4882a593Smuzhiyun     if (mask & GCFillStyle)
258*4882a593Smuzhiyun         v.fill_style = pGC->fillStyle;
259*4882a593Smuzhiyun     if (mask & GCFillRule)
260*4882a593Smuzhiyun         v.fill_rule = pGC->fillRule;
261*4882a593Smuzhiyun     if (mask & GCTile) {
262*4882a593Smuzhiyun         if (pGC->tileIsPixel) {
263*4882a593Smuzhiyun             mask &= ~GCTile;
264*4882a593Smuzhiyun         }
265*4882a593Smuzhiyun         else {
266*4882a593Smuzhiyun             dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun             v.tile = (Drawable) pPixPriv->pixmap;
269*4882a593Smuzhiyun         }
270*4882a593Smuzhiyun     }
271*4882a593Smuzhiyun     if (mask & GCStipple) {
272*4882a593Smuzhiyun         dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun         v.stipple = (Drawable) pPixPriv->pixmap;
275*4882a593Smuzhiyun     }
276*4882a593Smuzhiyun     if (mask & GCTileStipXOrigin)
277*4882a593Smuzhiyun         v.ts_x_origin = pGC->patOrg.x;
278*4882a593Smuzhiyun     if (mask & GCTileStipYOrigin)
279*4882a593Smuzhiyun         v.ts_y_origin = pGC->patOrg.y;
280*4882a593Smuzhiyun     if (mask & GCFont) {
281*4882a593Smuzhiyun         if (dmxScreen->beDisplay) {
282*4882a593Smuzhiyun             dmxFontPrivPtr pFontPriv;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun             pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex);
285*4882a593Smuzhiyun             v.font = pFontPriv->font[pScreen->myNum]->fid;
286*4882a593Smuzhiyun         }
287*4882a593Smuzhiyun         else {
288*4882a593Smuzhiyun             mask &= ~GCFont;
289*4882a593Smuzhiyun         }
290*4882a593Smuzhiyun     }
291*4882a593Smuzhiyun     if (mask & GCSubwindowMode)
292*4882a593Smuzhiyun         v.subwindow_mode = pGC->subWindowMode;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun     /* Graphics exposures are not needed on the back-ends since they can
295*4882a593Smuzhiyun        be generated on the front-end thereby saving bandwidth. */
296*4882a593Smuzhiyun     if (mask & GCGraphicsExposures)
297*4882a593Smuzhiyun         mask &= ~GCGraphicsExposures;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     if (mask & GCClipXOrigin)
300*4882a593Smuzhiyun         v.clip_x_origin = pGC->clipOrg.x;
301*4882a593Smuzhiyun     if (mask & GCClipYOrigin)
302*4882a593Smuzhiyun         v.clip_y_origin = pGC->clipOrg.y;
303*4882a593Smuzhiyun     if (mask & GCClipMask)
304*4882a593Smuzhiyun         mask &= ~GCClipMask;    /* See ChangeClip */
305*4882a593Smuzhiyun     if (mask & GCDashOffset)
306*4882a593Smuzhiyun         v.dash_offset = pGC->dashOffset;
307*4882a593Smuzhiyun     if (mask & GCDashList) {
308*4882a593Smuzhiyun         mask &= ~GCDashList;
309*4882a593Smuzhiyun         if (dmxScreen->beDisplay)
310*4882a593Smuzhiyun             XSetDashes(dmxScreen->beDisplay, pGCPriv->gc,
311*4882a593Smuzhiyun                        pGC->dashOffset, (char *) pGC->dash, pGC->numInDashList);
312*4882a593Smuzhiyun     }
313*4882a593Smuzhiyun     if (mask & GCArcMode)
314*4882a593Smuzhiyun         v.arc_mode = pGC->arcMode;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     if (mask && dmxScreen->beDisplay) {
317*4882a593Smuzhiyun         XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v);
318*4882a593Smuzhiyun         dmxSync(dmxScreen, FALSE);
319*4882a593Smuzhiyun     }
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGC);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun /** Copy \a pGCSrc to \a pGCDst on the back-end server associated with
325*4882a593Smuzhiyun  *  \a pGCSrc's screen. */
326*4882a593Smuzhiyun void
dmxCopyGC(GCPtr pGCSrc,unsigned long changes,GCPtr pGCDst)327*4882a593Smuzhiyun dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun     ScreenPtr pScreen = pGCSrc->pScreen;
330*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
331*4882a593Smuzhiyun     dmxGCPrivPtr pGCSrcPriv = DMX_GET_GC_PRIV(pGCSrc);
332*4882a593Smuzhiyun     dmxGCPrivPtr pGCDstPriv = DMX_GET_GC_PRIV(pGCDst);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGCDst);
335*4882a593Smuzhiyun     pGCDst->funcs->CopyGC(pGCSrc, changes, pGCDst);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun     /* Copy the GC on the back-end server */
338*4882a593Smuzhiyun     if (dmxScreen->beDisplay)
339*4882a593Smuzhiyun         XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGCDst);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun /** Free the \a pGC on the back-end server. */
345*4882a593Smuzhiyun Bool
dmxBEFreeGC(GCPtr pGC)346*4882a593Smuzhiyun dmxBEFreeGC(GCPtr pGC)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun     ScreenPtr pScreen = pGC->pScreen;
349*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
350*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun     if (pGCPriv->gc) {
353*4882a593Smuzhiyun         XFreeGC(dmxScreen->beDisplay, pGCPriv->gc);
354*4882a593Smuzhiyun         pGCPriv->gc = NULL;
355*4882a593Smuzhiyun         return TRUE;
356*4882a593Smuzhiyun     }
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun     return FALSE;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun /** Destroy the graphics context, \a pGC and free the corresponding GC
362*4882a593Smuzhiyun  *  on the back-end server. */
363*4882a593Smuzhiyun void
dmxDestroyGC(GCPtr pGC)364*4882a593Smuzhiyun dmxDestroyGC(GCPtr pGC)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun     ScreenPtr pScreen = pGC->pScreen;
367*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGC);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun     /* Free the GC on the back-end server */
372*4882a593Smuzhiyun     if (dmxScreen->beDisplay)
373*4882a593Smuzhiyun         dmxBEFreeGC(pGC);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun     pGC->funcs->DestroyGC(pGC);
376*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGC);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun /** Change the clip rects for a GC. */
380*4882a593Smuzhiyun void
dmxChangeClip(GCPtr pGC,int type,void * pvalue,int nrects)381*4882a593Smuzhiyun dmxChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun     ScreenPtr pScreen = pGC->pScreen;
384*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
385*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
386*4882a593Smuzhiyun     XRectangle *pRects;
387*4882a593Smuzhiyun     BoxPtr pBox;
388*4882a593Smuzhiyun     int i, nRects;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGC);
391*4882a593Smuzhiyun     pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     /* Set the client clip on the back-end server */
394*4882a593Smuzhiyun     if (!pGC->clientClip) {
395*4882a593Smuzhiyun         if (dmxScreen->beDisplay)
396*4882a593Smuzhiyun             XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
397*4882a593Smuzhiyun     } else {
398*4882a593Smuzhiyun         if (dmxScreen->beDisplay) {
399*4882a593Smuzhiyun             nRects = RegionNumRects((RegionPtr) pGC->clientClip);
400*4882a593Smuzhiyun             pRects = xallocarray(nRects, sizeof(*pRects));
401*4882a593Smuzhiyun             pBox = RegionRects((RegionPtr) pGC->clientClip);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun             for (i = 0; i < nRects; i++) {
404*4882a593Smuzhiyun                 pRects[i].x = pBox[i].x1;
405*4882a593Smuzhiyun                 pRects[i].y = pBox[i].y1;
406*4882a593Smuzhiyun                 pRects[i].width = pBox[i].x2 - pBox[i].x1;
407*4882a593Smuzhiyun                 pRects[i].height = pBox[i].y2 - pBox[i].y1;
408*4882a593Smuzhiyun             }
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun             XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc,
411*4882a593Smuzhiyun                                pGC->clipOrg.x, pGC->clipOrg.y,
412*4882a593Smuzhiyun                                pRects, nRects, Unsorted);
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun             free(pRects);
415*4882a593Smuzhiyun         }
416*4882a593Smuzhiyun     }
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGC);
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun /** Destroy a GC's clip rects. */
422*4882a593Smuzhiyun void
dmxDestroyClip(GCPtr pGC)423*4882a593Smuzhiyun dmxDestroyClip(GCPtr pGC)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun     ScreenPtr pScreen = pGC->pScreen;
426*4882a593Smuzhiyun     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
427*4882a593Smuzhiyun     dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGC);
430*4882a593Smuzhiyun     pGC->funcs->DestroyClip(pGC);
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun     /* Set the client clip on the back-end server to None */
433*4882a593Smuzhiyun     if (dmxScreen->beDisplay)
434*4882a593Smuzhiyun         XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGC);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun /** Copy a GC's clip rects. */
440*4882a593Smuzhiyun void
dmxCopyClip(GCPtr pGCDst,GCPtr pGCSrc)441*4882a593Smuzhiyun dmxCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun     DMX_GC_FUNC_PROLOGUE(pGCDst);
444*4882a593Smuzhiyun     pGCDst->funcs->CopyClip(pGCDst, pGCSrc);
445*4882a593Smuzhiyun     DMX_GC_FUNC_EPILOGUE(pGCDst);
446*4882a593Smuzhiyun }
447