1706f2543Smrg/* 2706f2543Smrg * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Authors: 30706f2543Smrg * Kevin E. Martin <kem@redhat.com> 31706f2543Smrg * 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg/** \file 35706f2543Smrg * This file provides support for GCs. */ 36706f2543Smrg 37706f2543Smrg#ifdef HAVE_DMX_CONFIG_H 38706f2543Smrg#include <dmx-config.h> 39706f2543Smrg#endif 40706f2543Smrg 41706f2543Smrg#include "dmx.h" 42706f2543Smrg#include "dmxsync.h" 43706f2543Smrg#include "dmxgc.h" 44706f2543Smrg#include "dmxgcops.h" 45706f2543Smrg#include "dmxpixmap.h" 46706f2543Smrg#include "dmxfont.h" 47706f2543Smrg 48706f2543Smrg#include "gcstruct.h" 49706f2543Smrg#include "pixmapstr.h" 50706f2543Smrg#include "migc.h" 51706f2543Smrg 52706f2543Smrgstatic GCFuncs dmxGCFuncs = { 53706f2543Smrg dmxValidateGC, 54706f2543Smrg dmxChangeGC, 55706f2543Smrg dmxCopyGC, 56706f2543Smrg dmxDestroyGC, 57706f2543Smrg dmxChangeClip, 58706f2543Smrg dmxDestroyClip, 59706f2543Smrg dmxCopyClip, 60706f2543Smrg}; 61706f2543Smrg 62706f2543Smrgstatic GCOps dmxGCOps = { 63706f2543Smrg dmxFillSpans, 64706f2543Smrg dmxSetSpans, 65706f2543Smrg dmxPutImage, 66706f2543Smrg dmxCopyArea, 67706f2543Smrg dmxCopyPlane, 68706f2543Smrg dmxPolyPoint, 69706f2543Smrg dmxPolylines, 70706f2543Smrg dmxPolySegment, 71706f2543Smrg dmxPolyRectangle, 72706f2543Smrg dmxPolyArc, 73706f2543Smrg dmxFillPolygon, 74706f2543Smrg dmxPolyFillRect, 75706f2543Smrg dmxPolyFillArc, 76706f2543Smrg dmxPolyText8, 77706f2543Smrg dmxPolyText16, 78706f2543Smrg dmxImageText8, 79706f2543Smrg dmxImageText16, 80706f2543Smrg dmxImageGlyphBlt, 81706f2543Smrg dmxPolyGlyphBlt, 82706f2543Smrg dmxPushPixels 83706f2543Smrg}; 84706f2543Smrg 85706f2543Smrg/** Initialize the GC on \a pScreen */ 86706f2543SmrgBool dmxInitGC(ScreenPtr pScreen) 87706f2543Smrg{ 88706f2543Smrg if (!dixRegisterPrivateKey(&dmxGCPrivateKeyRec, PRIVATE_GC, sizeof(dmxGCPrivRec))) 89706f2543Smrg return FALSE; 90706f2543Smrg return TRUE; 91706f2543Smrg} 92706f2543Smrg 93706f2543Smrg/** Create the GC on the back-end server. */ 94706f2543Smrgvoid dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC) 95706f2543Smrg{ 96706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 97706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 98706f2543Smrg int i; 99706f2543Smrg 100706f2543Smrg for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { 101706f2543Smrg if (pGC->depth == dmxScreen->bePixmapFormats[i].depth) { 102706f2543Smrg unsigned long mask; 103706f2543Smrg XGCValues gcvals; 104706f2543Smrg 105706f2543Smrg mask = GCGraphicsExposures; 106706f2543Smrg gcvals.graphics_exposures = FALSE; 107706f2543Smrg 108706f2543Smrg /* Create GC in the back-end servers */ 109706f2543Smrg pGCPriv->gc = XCreateGC(dmxScreen->beDisplay, 110706f2543Smrg dmxScreen->scrnDefDrawables[i], 111706f2543Smrg mask, &gcvals); 112706f2543Smrg break; 113706f2543Smrg } 114706f2543Smrg } 115706f2543Smrg} 116706f2543Smrg 117706f2543Smrg/** Create a graphics context on the back-end server associated /a pGC's 118706f2543Smrg * screen. */ 119706f2543SmrgBool dmxCreateGC(GCPtr pGC) 120706f2543Smrg{ 121706f2543Smrg ScreenPtr pScreen = pGC->pScreen; 122706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 123706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 124706f2543Smrg Bool ret; 125706f2543Smrg 126706f2543Smrg DMX_UNWRAP(CreateGC, dmxScreen, pScreen); 127706f2543Smrg if ((ret = pScreen->CreateGC(pGC))) { 128706f2543Smrg /* Save the old funcs */ 129706f2543Smrg pGCPriv->funcs = pGC->funcs; 130706f2543Smrg pGCPriv->ops = NULL; 131706f2543Smrg 132706f2543Smrg pGC->funcs = &dmxGCFuncs; 133706f2543Smrg 134706f2543Smrg if (dmxScreen->beDisplay) { 135706f2543Smrg dmxBECreateGC(pScreen, pGC); 136706f2543Smrg } else { 137706f2543Smrg pGCPriv->gc = NULL; 138706f2543Smrg } 139706f2543Smrg 140706f2543Smrg /* Check for "magic special case" 141706f2543Smrg * 1. see CreateGC in dix/gc.c for more info 142706f2543Smrg * 2. see dmxChangeGC for more info 143706f2543Smrg */ 144706f2543Smrg pGCPriv->msc = (!pGC->tileIsPixel && !pGC->tile.pixmap); 145706f2543Smrg } 146706f2543Smrg DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen); 147706f2543Smrg 148706f2543Smrg return ret; 149706f2543Smrg} 150706f2543Smrg 151706f2543Smrg/** Validate a graphics context, \a pGC, locally in the DMX server and 152706f2543Smrg * recompute the composite clip, if necessary. */ 153706f2543Smrgvoid dmxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 154706f2543Smrg{ 155706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 156706f2543Smrg 157706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGC); 158706f2543Smrg#if 0 159706f2543Smrg pGC->funcs->ValidateGC(pGC, changes, pDrawable); 160706f2543Smrg#endif 161706f2543Smrg 162706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW || 163706f2543Smrg pDrawable->type == DRAWABLE_PIXMAP) { 164706f2543Smrg /* Save the old ops, since we're about to change the ops in the 165706f2543Smrg * epilogue. 166706f2543Smrg */ 167706f2543Smrg pGCPriv->ops = pGC->ops; 168706f2543Smrg } else { 169706f2543Smrg pGCPriv->ops = NULL; 170706f2543Smrg } 171706f2543Smrg 172706f2543Smrg /* If the client clip is different or moved OR the subwindowMode has 173706f2543Smrg * changed OR the window's clip has changed since the last 174706f2543Smrg * validation, then we need to recompute the composite clip. 175706f2543Smrg */ 176706f2543Smrg if ((changes & (GCClipXOrigin | 177706f2543Smrg GCClipYOrigin | 178706f2543Smrg GCClipMask | 179706f2543Smrg GCSubwindowMode)) || 180706f2543Smrg (pDrawable->serialNumber != 181706f2543Smrg (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) { 182706f2543Smrg miComputeCompositeClip(pGC, pDrawable); 183706f2543Smrg } 184706f2543Smrg 185706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGC); 186706f2543Smrg} 187706f2543Smrg 188706f2543Smrg/** Set the values in the graphics context on the back-end server 189706f2543Smrg * associated with \a pGC's screen. */ 190706f2543Smrgvoid dmxChangeGC(GCPtr pGC, unsigned long mask) 191706f2543Smrg{ 192706f2543Smrg ScreenPtr pScreen = pGC->pScreen; 193706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 194706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 195706f2543Smrg XGCValues v; 196706f2543Smrg 197706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGC); 198706f2543Smrg#if 0 199706f2543Smrg pGC->funcs->ChangeGC(pGC, mask); 200706f2543Smrg#endif 201706f2543Smrg 202706f2543Smrg /* Handle "magic special case" from CreateGC */ 203706f2543Smrg if (pGCPriv->msc) { 204706f2543Smrg /* The "magic special case" is used to handle the case where a 205706f2543Smrg * foreground pixel is set when the GC is created so that a 206706f2543Smrg * "pseudo default-tile" can be created and used in case the 207706f2543Smrg * fillstyle was set to FillTiled. This specific case is tested 208706f2543Smrg * in xtest (XCreateGC test #3). What has happened in dix by 209706f2543Smrg * the time it reaches here is (1) the pGC->tile.pixel has been 210706f2543Smrg * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a 211706f2543Smrg * tile has also been set, then pGC->tileIsPixel is unset and 212706f2543Smrg * pGC->tile.pixmap is initialized; else, the default tile is 213706f2543Smrg * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is 214706f2543Smrg * initialized to the "pseudo default-tile". In either case, 215706f2543Smrg * pGC->tile.pixmap is set; however, in the "magic special case" 216706f2543Smrg * the mask is not updated to allow us to detect that we should 217706f2543Smrg * initialize the GCTile in the back-end server. Thus, we catch 218706f2543Smrg * this case in dmxCreateGC and add GCTile to the mask here. 219706f2543Smrg * Are there any cases that I've missed? 220706f2543Smrg */ 221706f2543Smrg 222706f2543Smrg /* Make sure that the tile.pixmap is set, just in case the user 223706f2543Smrg * set GCTile in the mask but forgot to set vals.pixmap 224706f2543Smrg */ 225706f2543Smrg if (pGC->tile.pixmap) mask |= GCTile; 226706f2543Smrg 227706f2543Smrg /* This only happens once when the GC is created */ 228706f2543Smrg pGCPriv->msc = FALSE; 229706f2543Smrg } 230706f2543Smrg 231706f2543Smrg /* Update back-end server's gc */ 232706f2543Smrg if (mask & GCFunction) v.function = pGC->alu; 233706f2543Smrg if (mask & GCPlaneMask) v.plane_mask = pGC->planemask; 234706f2543Smrg if (mask & GCForeground) v.foreground = pGC->fgPixel; 235706f2543Smrg if (mask & GCBackground) v.background = pGC->bgPixel; 236706f2543Smrg if (mask & GCLineWidth) v.line_width = pGC->lineWidth; 237706f2543Smrg if (mask & GCLineStyle) v.line_style = pGC->lineStyle; 238706f2543Smrg if (mask & GCCapStyle) v.cap_style = pGC->capStyle; 239706f2543Smrg if (mask & GCJoinStyle) v.join_style = pGC->joinStyle; 240706f2543Smrg if (mask & GCFillStyle) v.fill_style = pGC->fillStyle; 241706f2543Smrg if (mask & GCFillRule) v.fill_rule = pGC->fillRule; 242706f2543Smrg if (mask & GCTile) { 243706f2543Smrg if (pGC->tileIsPixel) { 244706f2543Smrg mask &= ~GCTile; 245706f2543Smrg } else { 246706f2543Smrg dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap); 247706f2543Smrg v.tile = (Drawable)pPixPriv->pixmap; 248706f2543Smrg } 249706f2543Smrg } 250706f2543Smrg if (mask & GCStipple) { 251706f2543Smrg dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple); 252706f2543Smrg v.stipple = (Drawable)pPixPriv->pixmap; 253706f2543Smrg } 254706f2543Smrg if (mask & GCTileStipXOrigin) v.ts_x_origin = pGC->patOrg.x; 255706f2543Smrg if (mask & GCTileStipYOrigin) v.ts_y_origin = pGC->patOrg.y; 256706f2543Smrg if (mask & GCFont) { 257706f2543Smrg if (dmxScreen->beDisplay) { 258706f2543Smrg dmxFontPrivPtr pFontPriv; 259706f2543Smrg pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex); 260706f2543Smrg v.font = pFontPriv->font[pScreen->myNum]->fid; 261706f2543Smrg } else { 262706f2543Smrg mask &= ~GCFont; 263706f2543Smrg } 264706f2543Smrg } 265706f2543Smrg if (mask & GCSubwindowMode) v.subwindow_mode = pGC->subWindowMode; 266706f2543Smrg 267706f2543Smrg /* Graphics exposures are not needed on the back-ends since they can 268706f2543Smrg be generated on the front-end thereby saving bandwidth. */ 269706f2543Smrg if (mask & GCGraphicsExposures) mask &= ~GCGraphicsExposures; 270706f2543Smrg 271706f2543Smrg if (mask & GCClipXOrigin) v.clip_x_origin = pGC->clipOrg.x; 272706f2543Smrg if (mask & GCClipYOrigin) v.clip_y_origin = pGC->clipOrg.y; 273706f2543Smrg if (mask & GCClipMask) mask &= ~GCClipMask; /* See ChangeClip */ 274706f2543Smrg if (mask & GCDashOffset) v.dash_offset = pGC->dashOffset; 275706f2543Smrg if (mask & GCDashList) { 276706f2543Smrg mask &= ~GCDashList; 277706f2543Smrg if (dmxScreen->beDisplay) 278706f2543Smrg XSetDashes(dmxScreen->beDisplay, pGCPriv->gc, 279706f2543Smrg pGC->dashOffset, (char *)pGC->dash, 280706f2543Smrg pGC->numInDashList); 281706f2543Smrg } 282706f2543Smrg if (mask & GCArcMode) v.arc_mode = pGC->arcMode; 283706f2543Smrg 284706f2543Smrg if (mask && dmxScreen->beDisplay) { 285706f2543Smrg XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v); 286706f2543Smrg dmxSync(dmxScreen, FALSE); 287706f2543Smrg } 288706f2543Smrg 289706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGC); 290706f2543Smrg} 291706f2543Smrg 292706f2543Smrg/** Copy \a pGCSrc to \a pGCDst on the back-end server associated with 293706f2543Smrg * \a pGCSrc's screen. */ 294706f2543Smrgvoid dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst) 295706f2543Smrg{ 296706f2543Smrg ScreenPtr pScreen = pGCSrc->pScreen; 297706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 298706f2543Smrg dmxGCPrivPtr pGCSrcPriv = DMX_GET_GC_PRIV(pGCSrc); 299706f2543Smrg dmxGCPrivPtr pGCDstPriv = DMX_GET_GC_PRIV(pGCDst); 300706f2543Smrg 301706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGCDst); 302706f2543Smrg pGCDst->funcs->CopyGC(pGCSrc, changes, pGCDst); 303706f2543Smrg 304706f2543Smrg /* Copy the GC on the back-end server */ 305706f2543Smrg if (dmxScreen->beDisplay) 306706f2543Smrg XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc); 307706f2543Smrg 308706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGCDst); 309706f2543Smrg} 310706f2543Smrg 311706f2543Smrg/** Free the \a pGC on the back-end server. */ 312706f2543SmrgBool dmxBEFreeGC(GCPtr pGC) 313706f2543Smrg{ 314706f2543Smrg ScreenPtr pScreen = pGC->pScreen; 315706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 316706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 317706f2543Smrg 318706f2543Smrg if (pGCPriv->gc) { 319706f2543Smrg XFreeGC(dmxScreen->beDisplay, pGCPriv->gc); 320706f2543Smrg pGCPriv->gc = NULL; 321706f2543Smrg return TRUE; 322706f2543Smrg } 323706f2543Smrg 324706f2543Smrg return FALSE; 325706f2543Smrg} 326706f2543Smrg 327706f2543Smrg/** Destroy the graphics context, \a pGC and free the corresponding GC 328706f2543Smrg * on the back-end server. */ 329706f2543Smrgvoid dmxDestroyGC(GCPtr pGC) 330706f2543Smrg{ 331706f2543Smrg ScreenPtr pScreen = pGC->pScreen; 332706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 333706f2543Smrg 334706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGC); 335706f2543Smrg 336706f2543Smrg /* Free the GC on the back-end server */ 337706f2543Smrg if (dmxScreen->beDisplay) 338706f2543Smrg dmxBEFreeGC(pGC); 339706f2543Smrg 340706f2543Smrg pGC->funcs->DestroyGC(pGC); 341706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGC); 342706f2543Smrg} 343706f2543Smrg 344706f2543Smrg/** Change the clip rects for a GC. */ 345706f2543Smrgvoid dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) 346706f2543Smrg{ 347706f2543Smrg ScreenPtr pScreen = pGC->pScreen; 348706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 349706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 350706f2543Smrg XRectangle *pRects; 351706f2543Smrg BoxPtr pBox; 352706f2543Smrg int i, nRects; 353706f2543Smrg 354706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGC); 355706f2543Smrg pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); 356706f2543Smrg 357706f2543Smrg /* Set the client clip on the back-end server */ 358706f2543Smrg switch (pGC->clientClipType) { 359706f2543Smrg case CT_NONE: 360706f2543Smrg if (dmxScreen->beDisplay) 361706f2543Smrg XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None); 362706f2543Smrg break; 363706f2543Smrg 364706f2543Smrg case CT_REGION: 365706f2543Smrg if (dmxScreen->beDisplay) { 366706f2543Smrg nRects = RegionNumRects((RegionPtr)pGC->clientClip); 367706f2543Smrg pRects = malloc(nRects * sizeof(*pRects)); 368706f2543Smrg pBox = RegionRects((RegionPtr)pGC->clientClip); 369706f2543Smrg 370706f2543Smrg for (i = 0; i < nRects; i++) { 371706f2543Smrg pRects[i].x = pBox[i].x1; 372706f2543Smrg pRects[i].y = pBox[i].y1; 373706f2543Smrg pRects[i].width = pBox[i].x2 - pBox[i].x1; 374706f2543Smrg pRects[i].height = pBox[i].y2 - pBox[i].y1; 375706f2543Smrg } 376706f2543Smrg 377706f2543Smrg XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc, 378706f2543Smrg pGC->clipOrg.x, pGC->clipOrg.y, 379706f2543Smrg pRects, nRects, Unsorted); 380706f2543Smrg 381706f2543Smrg free(pRects); 382706f2543Smrg } 383706f2543Smrg break; 384706f2543Smrg 385706f2543Smrg case CT_PIXMAP: 386706f2543Smrg /* Condensed down to REGION in the mi code */ 387706f2543Smrg break; 388706f2543Smrg } 389706f2543Smrg 390706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGC); 391706f2543Smrg} 392706f2543Smrg 393706f2543Smrg/** Destroy a GC's clip rects. */ 394706f2543Smrgvoid dmxDestroyClip(GCPtr pGC) 395706f2543Smrg{ 396706f2543Smrg ScreenPtr pScreen = pGC->pScreen; 397706f2543Smrg DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 398706f2543Smrg dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 399706f2543Smrg 400706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGC); 401706f2543Smrg pGC->funcs->DestroyClip(pGC); 402706f2543Smrg 403706f2543Smrg /* Set the client clip on the back-end server to None */ 404706f2543Smrg if (dmxScreen->beDisplay) 405706f2543Smrg XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None); 406706f2543Smrg 407706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGC); 408706f2543Smrg} 409706f2543Smrg 410706f2543Smrg/** Copy a GC's clip rects. */ 411706f2543Smrgvoid dmxCopyClip(GCPtr pGCDst, GCPtr pGCSrc) 412706f2543Smrg{ 413706f2543Smrg DMX_GC_FUNC_PROLOGUE(pGCDst); 414706f2543Smrg pGCDst->funcs->CopyClip(pGCDst, pGCSrc); 415706f2543Smrg DMX_GC_FUNC_EPILOGUE(pGCDst); 416706f2543Smrg} 417