panoramiX.c revision 05b261ec
1/***************************************************************** 2Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 3Permission is hereby granted, free of charge, to any person obtaining a copy 4of this software and associated documentation files (the "Software"), to deal 5in the Software without restriction, including without limitation the rights 6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7copies of the Software. 8 9The above copyright notice and this permission notice shall be included in 10all copies or substantial portions of the Software. 11 12THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 16BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 17WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 18IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 20Except as contained in this notice, the name of Digital Equipment Corporation 21shall not be used in advertising or otherwise to promote the sale, use or other 22dealings in this Software without prior written authorization from Digital 23Equipment Corporation. 24******************************************************************/ 25 26#ifdef HAVE_DIX_CONFIG_H 27#include <dix-config.h> 28#endif 29 30#ifdef HAVE_DMX_CONFIG_H 31#include <dmx-config.h> 32#endif 33 34#define NEED_REPLIES 35#include <stdio.h> 36#include <X11/X.h> 37#include <X11/Xproto.h> 38#include <X11/Xarch.h> 39#include "misc.h" 40#include "cursor.h" 41#include "cursorstr.h" 42#include "extnsionst.h" 43#include "dixstruct.h" 44#include "gc.h" 45#include "gcstruct.h" 46#include "scrnintstr.h" 47#include "window.h" 48#include "windowstr.h" 49#include "pixmapstr.h" 50#include "panoramiX.h" 51#include <X11/extensions/panoramiXproto.h> 52#include "panoramiXsrv.h" 53#include "globals.h" 54#include "servermd.h" 55#include "resource.h" 56#ifdef RENDER 57#include "picturestr.h" 58#endif 59#include "modinit.h" 60 61 62#ifdef GLXPROXY 63extern VisualPtr glxMatchVisual(ScreenPtr pScreen, 64 VisualPtr pVisual, 65 ScreenPtr pMatchScreen); 66#endif 67 68#if 0 69static unsigned char PanoramiXReqCode = 0; 70#endif 71/* 72 * PanoramiX data declarations 73 */ 74 75int PanoramiXPixWidth = 0; 76int PanoramiXPixHeight = 0; 77_X_EXPORT int PanoramiXNumScreens = 0; 78 79_X_EXPORT PanoramiXData *panoramiXdataPtr = NULL; 80static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL}; 81 82static int PanoramiXNumDepths; 83static DepthPtr PanoramiXDepths; 84static int PanoramiXNumVisuals; 85static VisualPtr PanoramiXVisuals; 86 87/* We support at most 256 visuals */ 88_X_EXPORT XID *PanoramiXVisualTable = NULL; 89 90_X_EXPORT unsigned long XRC_DRAWABLE; 91_X_EXPORT unsigned long XRT_WINDOW; 92_X_EXPORT unsigned long XRT_PIXMAP; 93_X_EXPORT unsigned long XRT_GC; 94_X_EXPORT unsigned long XRT_COLORMAP; 95 96/* 97 * Function prototypes 98 */ 99 100static int panoramiXGeneration; 101static int ProcPanoramiXDispatch(ClientPtr client); 102 103static void PanoramiXResetProc(ExtensionEntry*); 104 105/* 106 * External references for functions and data variables 107 */ 108 109#include "panoramiXh.h" 110 111int (* SavedProcVector[256]) (ClientPtr client) = { NULL, }; 112 113static int PanoramiXGCIndex = -1; 114static int PanoramiXScreenIndex = -1; 115 116typedef struct { 117 DDXPointRec clipOrg; 118 DDXPointRec patOrg; 119 GCFuncs *wrapFuncs; 120} PanoramiXGCRec, *PanoramiXGCPtr; 121 122typedef struct { 123 CreateGCProcPtr CreateGC; 124 CloseScreenProcPtr CloseScreen; 125} PanoramiXScreenRec, *PanoramiXScreenPtr; 126 127RegionRec XineramaScreenRegions[MAXSCREENS]; 128 129static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr); 130static void XineramaChangeGC(GCPtr, unsigned long); 131static void XineramaCopyGC(GCPtr, unsigned long, GCPtr); 132static void XineramaDestroyGC(GCPtr); 133static void XineramaChangeClip(GCPtr, int, pointer, int); 134static void XineramaDestroyClip(GCPtr); 135static void XineramaCopyClip(GCPtr, GCPtr); 136 137static GCFuncs XineramaGCFuncs = { 138 XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, 139 XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip 140}; 141 142#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ 143 PanoramiXGCPtr pGCPriv = \ 144 (PanoramiXGCPtr) (pGC)->devPrivates[PanoramiXGCIndex].ptr;\ 145 (pGC)->funcs = pGCPriv->wrapFuncs; 146 147#define Xinerama_GC_FUNC_EPILOGUE(pGC)\ 148 pGCPriv->wrapFuncs = (pGC)->funcs;\ 149 (pGC)->funcs = &XineramaGCFuncs; 150 151 152static Bool 153XineramaCloseScreen (int i, ScreenPtr pScreen) 154{ 155 PanoramiXScreenPtr pScreenPriv = 156 (PanoramiXScreenPtr) pScreen->devPrivates[PanoramiXScreenIndex].ptr; 157 158 pScreen->CloseScreen = pScreenPriv->CloseScreen; 159 pScreen->CreateGC = pScreenPriv->CreateGC; 160 161 REGION_UNINIT(pScreen, &XineramaScreenRegions[pScreen->myNum]); 162 if (pScreen->myNum == 0) 163 REGION_UNINIT(pScreen, &PanoramiXScreenRegion); 164 165 xfree ((pointer) pScreenPriv); 166 167 return (*pScreen->CloseScreen) (i, pScreen); 168} 169 170static Bool 171XineramaCreateGC(GCPtr pGC) 172{ 173 ScreenPtr pScreen = pGC->pScreen; 174 PanoramiXScreenPtr pScreenPriv = 175 (PanoramiXScreenPtr) pScreen->devPrivates[PanoramiXScreenIndex].ptr; 176 Bool ret; 177 178 pScreen->CreateGC = pScreenPriv->CreateGC; 179 if((ret = (*pScreen->CreateGC)(pGC))) { 180 PanoramiXGCPtr pGCPriv = 181 (PanoramiXGCPtr) pGC->devPrivates[PanoramiXGCIndex].ptr; 182 183 pGCPriv->wrapFuncs = pGC->funcs; 184 pGC->funcs = &XineramaGCFuncs; 185 186 pGCPriv->clipOrg.x = pGC->clipOrg.x; 187 pGCPriv->clipOrg.y = pGC->clipOrg.y; 188 pGCPriv->patOrg.x = pGC->patOrg.x; 189 pGCPriv->patOrg.y = pGC->patOrg.y; 190 } 191 pScreen->CreateGC = XineramaCreateGC; 192 193 return ret; 194} 195 196static void 197XineramaValidateGC( 198 GCPtr pGC, 199 unsigned long changes, 200 DrawablePtr pDraw 201){ 202 Xinerama_GC_FUNC_PROLOGUE (pGC); 203 204 if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) { 205 /* the root window */ 206 int x_off = panoramiXdataPtr[pGC->pScreen->myNum].x; 207 int y_off = panoramiXdataPtr[pGC->pScreen->myNum].y; 208 int new_val; 209 210 new_val = pGCPriv->clipOrg.x - x_off; 211 if(pGC->clipOrg.x != new_val) { 212 pGC->clipOrg.x = new_val; 213 changes |= GCClipXOrigin; 214 } 215 new_val = pGCPriv->clipOrg.y - y_off; 216 if(pGC->clipOrg.y != new_val) { 217 pGC->clipOrg.y = new_val; 218 changes |= GCClipYOrigin; 219 } 220 new_val = pGCPriv->patOrg.x - x_off; 221 if(pGC->patOrg.x != new_val) { 222 pGC->patOrg.x = new_val; 223 changes |= GCTileStipXOrigin; 224 } 225 new_val = pGCPriv->patOrg.y - y_off; 226 if(pGC->patOrg.y != new_val) { 227 pGC->patOrg.y = new_val; 228 changes |= GCTileStipYOrigin; 229 } 230 } else { 231 if(pGC->clipOrg.x != pGCPriv->clipOrg.x) { 232 pGC->clipOrg.x = pGCPriv->clipOrg.x; 233 changes |= GCClipXOrigin; 234 } 235 if(pGC->clipOrg.y != pGCPriv->clipOrg.y) { 236 pGC->clipOrg.y = pGCPriv->clipOrg.y; 237 changes |= GCClipYOrigin; 238 } 239 if(pGC->patOrg.x != pGCPriv->patOrg.x) { 240 pGC->patOrg.x = pGCPriv->patOrg.x; 241 changes |= GCTileStipXOrigin; 242 } 243 if(pGC->patOrg.y != pGCPriv->patOrg.y) { 244 pGC->patOrg.y = pGCPriv->patOrg.y; 245 changes |= GCTileStipYOrigin; 246 } 247 } 248 249 (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); 250 Xinerama_GC_FUNC_EPILOGUE (pGC); 251} 252 253static void 254XineramaDestroyGC(GCPtr pGC) 255{ 256 Xinerama_GC_FUNC_PROLOGUE (pGC); 257 (*pGC->funcs->DestroyGC)(pGC); 258 Xinerama_GC_FUNC_EPILOGUE (pGC); 259} 260 261static void 262XineramaChangeGC ( 263 GCPtr pGC, 264 unsigned long mask 265){ 266 Xinerama_GC_FUNC_PROLOGUE (pGC); 267 268 if(mask & GCTileStipXOrigin) 269 pGCPriv->patOrg.x = pGC->patOrg.x; 270 if(mask & GCTileStipYOrigin) 271 pGCPriv->patOrg.y = pGC->patOrg.y; 272 if(mask & GCClipXOrigin) 273 pGCPriv->clipOrg.x = pGC->clipOrg.x; 274 if(mask & GCClipYOrigin) 275 pGCPriv->clipOrg.y = pGC->clipOrg.y; 276 277 (*pGC->funcs->ChangeGC) (pGC, mask); 278 Xinerama_GC_FUNC_EPILOGUE (pGC); 279} 280 281static void 282XineramaCopyGC ( 283 GCPtr pGCSrc, 284 unsigned long mask, 285 GCPtr pGCDst 286){ 287 PanoramiXGCPtr pSrcPriv = 288 (PanoramiXGCPtr) pGCSrc->devPrivates[PanoramiXGCIndex].ptr; 289 Xinerama_GC_FUNC_PROLOGUE (pGCDst); 290 291 if(mask & GCTileStipXOrigin) 292 pGCPriv->patOrg.x = pSrcPriv->patOrg.x; 293 if(mask & GCTileStipYOrigin) 294 pGCPriv->patOrg.y = pSrcPriv->patOrg.y; 295 if(mask & GCClipXOrigin) 296 pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x; 297 if(mask & GCClipYOrigin) 298 pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y; 299 300 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 301 Xinerama_GC_FUNC_EPILOGUE (pGCDst); 302} 303 304static void 305XineramaChangeClip ( 306 GCPtr pGC, 307 int type, 308 pointer pvalue, 309 int nrects 310){ 311 Xinerama_GC_FUNC_PROLOGUE (pGC); 312 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 313 Xinerama_GC_FUNC_EPILOGUE (pGC); 314} 315 316static void 317XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc) 318{ 319 Xinerama_GC_FUNC_PROLOGUE (pgcDst); 320 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); 321 Xinerama_GC_FUNC_EPILOGUE (pgcDst); 322} 323 324static void 325XineramaDestroyClip(GCPtr pGC) 326{ 327 Xinerama_GC_FUNC_PROLOGUE (pGC); 328 (* pGC->funcs->DestroyClip)(pGC); 329 Xinerama_GC_FUNC_EPILOGUE (pGC); 330} 331 332_X_EXPORT int 333XineramaDeleteResource(pointer data, XID id) 334{ 335 xfree(data); 336 return 1; 337} 338 339typedef struct { 340 int screen; 341 int id; 342} PanoramiXSearchData; 343 344static Bool 345XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata) 346{ 347 PanoramiXRes *res = (PanoramiXRes*)resource; 348 PanoramiXSearchData *data = (PanoramiXSearchData*)privdata; 349 350 return (res->info[data->screen].id == data->id); 351} 352 353PanoramiXRes * 354PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen) 355{ 356 PanoramiXSearchData data; 357 358 if(!screen) 359 return LookupIDByType(id, type); 360 361 data.screen = screen; 362 data.id = id; 363 364 return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, 365 XineramaFindIDByScrnum, &data); 366} 367 368typedef struct _connect_callback_list { 369 void (*func)(void); 370 struct _connect_callback_list *next; 371} XineramaConnectionCallbackList; 372 373static XineramaConnectionCallbackList *ConnectionCallbackList = NULL; 374 375_X_EXPORT Bool 376XineramaRegisterConnectionBlockCallback(void (*func)(void)) 377{ 378 XineramaConnectionCallbackList *newlist; 379 380 if(!(newlist = xalloc(sizeof(XineramaConnectionCallbackList)))) 381 return FALSE; 382 383 newlist->next = ConnectionCallbackList; 384 newlist->func = func; 385 ConnectionCallbackList = newlist; 386 387 return TRUE; 388} 389 390static void XineramaInitData(ScreenPtr pScreen) 391{ 392 int i, w, h; 393 394 REGION_NULL(pScreen, &PanoramiXScreenRegion) 395 for (i = 0; i < PanoramiXNumScreens; i++) { 396 BoxRec TheBox; 397 398 pScreen = screenInfo.screens[i]; 399 400 panoramiXdataPtr[i].x = dixScreenOrigins[i].x; 401 panoramiXdataPtr[i].y = dixScreenOrigins[i].y; 402 panoramiXdataPtr[i].width = pScreen->width; 403 panoramiXdataPtr[i].height = pScreen->height; 404 405 TheBox.x1 = panoramiXdataPtr[i].x; 406 TheBox.x2 = TheBox.x1 + panoramiXdataPtr[i].width; 407 TheBox.y1 = panoramiXdataPtr[i].y; 408 TheBox.y2 = TheBox.y1 + panoramiXdataPtr[i].height; 409 410 REGION_INIT(pScreen, &XineramaScreenRegions[i], &TheBox, 1); 411 REGION_UNION(pScreen, &PanoramiXScreenRegion, &PanoramiXScreenRegion, 412 &XineramaScreenRegions[i]); 413 } 414 415 PanoramiXPixWidth = panoramiXdataPtr[0].x + panoramiXdataPtr[0].width; 416 PanoramiXPixHeight = panoramiXdataPtr[0].y + panoramiXdataPtr[0].height; 417 418 for (i = 1; i < PanoramiXNumScreens; i++) { 419 w = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; 420 h = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; 421 422 if (PanoramiXPixWidth < w) 423 PanoramiXPixWidth = w; 424 if (PanoramiXPixHeight < h) 425 PanoramiXPixHeight = h; 426 } 427} 428 429void XineramaReinitData(ScreenPtr pScreen) 430{ 431 int i; 432 433 REGION_UNINIT(pScreen, &PanoramiXScreenRegion); 434 for (i = 0; i < PanoramiXNumScreens; i++) 435 REGION_UNINIT(pScreen, &XineramaScreenRegions[i]); 436 437 XineramaInitData(pScreen); 438} 439 440/* 441 * PanoramiXExtensionInit(): 442 * Called from InitExtensions in main(). 443 * Register PanoramiXeen Extension 444 * Initialize global variables. 445 */ 446 447void PanoramiXExtensionInit(int argc, char *argv[]) 448{ 449 int i; 450 Bool success = FALSE; 451 ExtensionEntry *extEntry; 452 ScreenPtr pScreen = screenInfo.screens[0]; 453 PanoramiXScreenPtr pScreenPriv; 454 455 if (noPanoramiXExtension) 456 return; 457 458 PanoramiXNumScreens = screenInfo.numScreens; 459 if (PanoramiXNumScreens == 1) { /* Only 1 screen */ 460 noPanoramiXExtension = TRUE; 461 return; 462 } 463 464 while (panoramiXGeneration != serverGeneration) { 465 extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 466 ProcPanoramiXDispatch, 467 SProcPanoramiXDispatch, PanoramiXResetProc, 468 StandardMinorOpcode); 469 if (!extEntry) { 470 ErrorF("PanoramiXExtensionInit(): failed to AddExtension\n"); 471 break; 472 } 473 474#if 0 475 PanoramiXReqCode = (unsigned char)extEntry->base; 476#endif 477 478 /* 479 * First make sure all the basic allocations succeed. If not, 480 * run in non-PanoramiXeen mode. 481 */ 482 483 panoramiXdataPtr = (PanoramiXData *) 484 xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData)); 485 486 BREAK_IF(!panoramiXdataPtr); 487 BREAK_IF((PanoramiXGCIndex = AllocateGCPrivateIndex()) < 0); 488 BREAK_IF((PanoramiXScreenIndex = AllocateScreenPrivateIndex()) < 0); 489 490 for (i = 0; i < PanoramiXNumScreens; i++) { 491 pScreen = screenInfo.screens[i]; 492 if(!AllocateGCPrivate(pScreen, PanoramiXGCIndex, 493 sizeof(PanoramiXGCRec))) { 494 noPanoramiXExtension = TRUE; 495 return; 496 } 497 498 pScreenPriv = xalloc(sizeof(PanoramiXScreenRec)); 499 pScreen->devPrivates[PanoramiXScreenIndex].ptr = 500 (pointer)pScreenPriv; 501 if(!pScreenPriv) { 502 noPanoramiXExtension = TRUE; 503 return; 504 } 505 506 pScreenPriv->CreateGC = pScreen->CreateGC; 507 pScreenPriv->CloseScreen = pScreen->CloseScreen; 508 509 pScreen->CreateGC = XineramaCreateGC; 510 pScreen->CloseScreen = XineramaCloseScreen; 511 } 512 513 XRC_DRAWABLE = CreateNewResourceClass(); 514 XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource) | 515 XRC_DRAWABLE; 516 XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource) | 517 XRC_DRAWABLE; 518 XRT_GC = CreateNewResourceType(XineramaDeleteResource); 519 XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource); 520 521 panoramiXGeneration = serverGeneration; 522 success = TRUE; 523 } 524 525 if (!success) { 526 noPanoramiXExtension = TRUE; 527 ErrorF("%s Extension failed to initialize\n", PANORAMIX_PROTOCOL_NAME); 528 return; 529 } 530 531 XineramaInitData(pScreen); 532 533 /* 534 * Put our processes into the ProcVector 535 */ 536 537 for (i = 256; i--; ) 538 SavedProcVector[i] = ProcVector[i]; 539 540 ProcVector[X_CreateWindow] = PanoramiXCreateWindow; 541 ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; 542 ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; 543 ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; 544 ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; 545 ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; 546 ProcVector[X_MapWindow] = PanoramiXMapWindow; 547 ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; 548 ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; 549 ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; 550 ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; 551 ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; 552 ProcVector[X_GetGeometry] = PanoramiXGetGeometry; 553 ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords; 554 ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; 555 ProcVector[X_FreePixmap] = PanoramiXFreePixmap; 556 ProcVector[X_CreateGC] = PanoramiXCreateGC; 557 ProcVector[X_ChangeGC] = PanoramiXChangeGC; 558 ProcVector[X_CopyGC] = PanoramiXCopyGC; 559 ProcVector[X_SetDashes] = PanoramiXSetDashes; 560 ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; 561 ProcVector[X_FreeGC] = PanoramiXFreeGC; 562 ProcVector[X_ClearArea] = PanoramiXClearToBackground; 563 ProcVector[X_CopyArea] = PanoramiXCopyArea;; 564 ProcVector[X_CopyPlane] = PanoramiXCopyPlane;; 565 ProcVector[X_PolyPoint] = PanoramiXPolyPoint; 566 ProcVector[X_PolyLine] = PanoramiXPolyLine; 567 ProcVector[X_PolySegment] = PanoramiXPolySegment; 568 ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; 569 ProcVector[X_PolyArc] = PanoramiXPolyArc; 570 ProcVector[X_FillPoly] = PanoramiXFillPoly; 571 ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; 572 ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; 573 ProcVector[X_PutImage] = PanoramiXPutImage; 574 ProcVector[X_GetImage] = PanoramiXGetImage; 575 ProcVector[X_PolyText8] = PanoramiXPolyText8; 576 ProcVector[X_PolyText16] = PanoramiXPolyText16; 577 ProcVector[X_ImageText8] = PanoramiXImageText8; 578 ProcVector[X_ImageText16] = PanoramiXImageText16; 579 ProcVector[X_CreateColormap] = PanoramiXCreateColormap; 580 ProcVector[X_FreeColormap] = PanoramiXFreeColormap; 581 ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree; 582 ProcVector[X_InstallColormap] = PanoramiXInstallColormap; 583 ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; 584 ProcVector[X_AllocColor] = PanoramiXAllocColor; 585 ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; 586 ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; 587 ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes; 588 ProcVector[X_FreeColors] = PanoramiXFreeColors; 589 ProcVector[X_StoreColors] = PanoramiXStoreColors; 590 ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; 591 592#ifdef RENDER 593 PanoramiXRenderInit (); 594#endif 595} 596 597extern Bool CreateConnectionBlock(void); 598 599Bool PanoramiXCreateConnectionBlock(void) 600{ 601 int i, j, length; 602 Bool disableBackingStore = FALSE; 603 Bool disableSaveUnders = FALSE; 604 int old_width, old_height; 605 float width_mult, height_mult; 606 xWindowRoot *root; 607 xVisualType *visual; 608 xDepth *depth; 609 VisualPtr pVisual; 610 ScreenPtr pScreen; 611 612 /* 613 * Do normal CreateConnectionBlock but faking it for only one screen 614 */ 615 616 if(!PanoramiXNumDepths) { 617 ErrorF("PanoramiX error: Incompatible screens. No common visuals\n"); 618 return FALSE; 619 } 620 621 for(i = 1; i < screenInfo.numScreens; i++) { 622 pScreen = screenInfo.screens[i]; 623 if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) { 624 ErrorF("PanoramiX error: Incompatible screens. Root window depths differ\n"); 625 return FALSE; 626 } 627 if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) 628 disableBackingStore = TRUE; 629 if(pScreen->saveUnderSupport != screenInfo.screens[0]->saveUnderSupport) 630 disableSaveUnders = TRUE; 631 } 632 633 if(disableBackingStore || disableSaveUnders) { 634 for(i = 0; i < screenInfo.numScreens; i++) { 635 pScreen = screenInfo.screens[i]; 636 if(disableBackingStore) 637 pScreen->backingStoreSupport = NotUseful; 638 if(disableSaveUnders) 639 pScreen->saveUnderSupport = NotUseful; 640 } 641 } 642 643 i = screenInfo.numScreens; 644 screenInfo.numScreens = 1; 645 if (!CreateConnectionBlock()) { 646 screenInfo.numScreens = i; 647 return FALSE; 648 } 649 650 screenInfo.numScreens = i; 651 652 root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); 653 length = connBlockScreenStart + sizeof(xWindowRoot); 654 655 /* overwrite the connection block */ 656 root->nDepths = PanoramiXNumDepths; 657 658 for (i = 0; i < PanoramiXNumDepths; i++) { 659 depth = (xDepth *) (ConnectionInfo + length); 660 depth->depth = PanoramiXDepths[i].depth; 661 depth->nVisuals = PanoramiXDepths[i].numVids; 662 length += sizeof(xDepth); 663 visual = (xVisualType *)(ConnectionInfo + length); 664 665 for (j = 0; j < depth->nVisuals; j++, visual++) { 666 visual->visualID = PanoramiXDepths[i].vids[j]; 667 668 for (pVisual = PanoramiXVisuals; 669 pVisual->vid != visual->visualID; 670 pVisual++) 671 ; 672 673 visual->class = pVisual->class; 674 visual->bitsPerRGB = pVisual->bitsPerRGBValue; 675 visual->colormapEntries = pVisual->ColormapEntries; 676 visual->redMask = pVisual->redMask; 677 visual->greenMask = pVisual->greenMask; 678 visual->blueMask = pVisual->blueMask; 679 } 680 681 length += (depth->nVisuals * sizeof(xVisualType)); 682 } 683 684 connSetupPrefix.length = length >> 2; 685 686 xfree(PanoramiXVisuals); 687 for (i = 0; i < PanoramiXNumDepths; i++) 688 xfree(PanoramiXDepths[i].vids); 689 xfree(PanoramiXDepths); 690 691 /* 692 * OK, change some dimensions so it looks as if it were one big screen 693 */ 694 695 old_width = root->pixWidth; 696 old_height = root->pixHeight; 697 698 root->pixWidth = PanoramiXPixWidth; 699 root->pixHeight = PanoramiXPixHeight; 700 width_mult = (1.0 * root->pixWidth) / old_width; 701 height_mult = (1.0 * root->pixHeight) / old_height; 702 root->mmWidth *= width_mult; 703 root->mmHeight *= height_mult; 704 705 while(ConnectionCallbackList) { 706 pointer tmp; 707 708 tmp = (pointer)ConnectionCallbackList; 709 (*ConnectionCallbackList->func)(); 710 ConnectionCallbackList = ConnectionCallbackList->next; 711 xfree(tmp); 712 } 713 714 return TRUE; 715} 716 717extern 718void PanoramiXConsolidate(void) 719{ 720 int i, j, k; 721 VisualPtr pVisual, pVisual2; 722 ScreenPtr pScreen, pScreen2; 723 DepthPtr pDepth, pDepth2; 724 PanoramiXRes *root, *defmap, *saver; 725 Bool foundDepth, missingDepth; 726 727 if(!PanoramiXVisualTable) 728 PanoramiXVisualTable = xcalloc(256 * MAXSCREENS, sizeof(XID)); 729 730 pScreen = screenInfo.screens[0]; 731 pVisual = pScreen->visuals; 732 pDepth = pScreen->allowedDepths; 733 734 PanoramiXNumDepths = 0; 735 PanoramiXDepths = xcalloc(pScreen->numDepths,sizeof(DepthRec)); 736 PanoramiXNumVisuals = 0; 737 PanoramiXVisuals = xcalloc(pScreen->numVisuals,sizeof(VisualRec)); 738 739 for (i = 0; i < pScreen->numDepths; i++, pDepth++) { 740 missingDepth = FALSE; 741 for (j = 1; j < PanoramiXNumScreens; j++) { 742 pScreen2 = screenInfo.screens[j]; 743 pDepth2 = pScreen2->allowedDepths; 744 745 foundDepth = FALSE; 746 for (k = 0; k < pScreen2->numDepths; k++, pDepth2++) { 747 if(pDepth2->depth == pDepth->depth) { 748 foundDepth = TRUE; 749 break; 750 } 751 } 752 753 if(!foundDepth) { 754 missingDepth = TRUE; 755 break; 756 } 757 } 758 759 if(!missingDepth) { 760 PanoramiXDepths[PanoramiXNumDepths].depth = pDepth->depth; 761 PanoramiXDepths[PanoramiXNumDepths].numVids = 0; 762 if(pDepth->numVids) 763 PanoramiXDepths[PanoramiXNumDepths].vids = 764 xalloc(sizeof(VisualID) * pDepth->numVids); 765 else 766 PanoramiXDepths[PanoramiXNumDepths].vids = NULL; 767 PanoramiXNumDepths++; 768 } 769 } 770 771 for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { 772 PanoramiXVisualTable[pVisual->vid * MAXSCREENS] = pVisual->vid; 773 774 /* check if the visual exists on all screens */ 775 for (j = 1; j < PanoramiXNumScreens; j++) { 776 pScreen2 = screenInfo.screens[j]; 777 778#ifdef GLXPROXY 779 pVisual2 = glxMatchVisual(pScreen, pVisual, pScreen2); 780 if (pVisual2) { 781 PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = 782 pVisual2->vid; 783 continue; 784 } else if (glxMatchVisual(pScreen, pVisual, pScreen)) { 785 PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = 0; 786 break; 787 } 788#endif 789 pVisual2 = pScreen2->visuals; 790 791 for (k = 0; k < pScreen2->numVisuals; k++, pVisual2++) { 792 if ((pVisual->class == pVisual2->class) && 793 (pVisual->ColormapEntries == pVisual2->ColormapEntries) && 794 (pVisual->nplanes == pVisual2->nplanes) && 795 (pVisual->redMask == pVisual2->redMask) && 796 (pVisual->greenMask == pVisual2->greenMask) && 797 (pVisual->blueMask == pVisual2->blueMask) && 798 (pVisual->offsetRed == pVisual2->offsetRed) && 799 (pVisual->offsetGreen == pVisual2->offsetGreen) && 800 (pVisual->offsetBlue == pVisual2->offsetBlue)) 801 { 802 /* We merely assign the first visual that matches. OpenGL 803 will need to get involved at some point if you want 804 match GLX visuals */ 805 PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = 806 pVisual2->vid; 807 break; 808 } 809 } 810 } 811 812 /* if it doesn't exist on all screens we can't use it */ 813 for (j = 0; j < PanoramiXNumScreens; j++) { 814 if (!PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j]) { 815 PanoramiXVisualTable[pVisual->vid * MAXSCREENS] = 0; 816 break; 817 } 818 } 819 820 /* if it does, make sure it's in the list of supported depths and visuals */ 821 if(PanoramiXVisualTable[pVisual->vid * MAXSCREENS]) { 822 PanoramiXVisuals[PanoramiXNumVisuals].vid = pVisual->vid; 823 PanoramiXVisuals[PanoramiXNumVisuals].class = pVisual->class; 824 PanoramiXVisuals[PanoramiXNumVisuals].bitsPerRGBValue = pVisual->bitsPerRGBValue; 825 PanoramiXVisuals[PanoramiXNumVisuals].ColormapEntries = pVisual->ColormapEntries; 826 PanoramiXVisuals[PanoramiXNumVisuals].nplanes = pVisual->nplanes; 827 PanoramiXVisuals[PanoramiXNumVisuals].redMask = pVisual->redMask; 828 PanoramiXVisuals[PanoramiXNumVisuals].greenMask = pVisual->greenMask; 829 PanoramiXVisuals[PanoramiXNumVisuals].blueMask = pVisual->blueMask; 830 PanoramiXVisuals[PanoramiXNumVisuals].offsetRed = pVisual->offsetRed; 831 PanoramiXVisuals[PanoramiXNumVisuals].offsetGreen = pVisual->offsetGreen; 832 PanoramiXVisuals[PanoramiXNumVisuals].offsetBlue = pVisual->offsetBlue; 833 PanoramiXNumVisuals++; 834 835 for (j = 0; j < PanoramiXNumDepths; j++) { 836 if (PanoramiXDepths[j].depth == pVisual->nplanes) { 837 PanoramiXDepths[j].vids[PanoramiXDepths[j].numVids] = pVisual->vid; 838 PanoramiXDepths[j].numVids++; 839 break; 840 } 841 } 842 } 843 } 844 845 846 root = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); 847 root->type = XRT_WINDOW; 848 defmap = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); 849 defmap->type = XRT_COLORMAP; 850 saver = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); 851 saver->type = XRT_WINDOW; 852 853 854 for (i = 0; i < PanoramiXNumScreens; i++) { 855 root->info[i].id = WindowTable[i]->drawable.id; 856 root->u.win.class = InputOutput; 857 root->u.win.root = TRUE; 858 saver->info[i].id = savedScreenInfo[i].wid; 859 saver->u.win.class = InputOutput; 860 saver->u.win.root = TRUE; 861 defmap->info[i].id = (screenInfo.screens[i])->defColormap; 862 } 863 864 AddResource(root->info[0].id, XRT_WINDOW, root); 865 AddResource(saver->info[0].id, XRT_WINDOW, saver); 866 AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); 867} 868 869 870/* 871 * PanoramiXResetProc() 872 * Exit, deallocating as needed. 873 */ 874 875static void PanoramiXResetProc(ExtensionEntry* extEntry) 876{ 877 int i; 878 879#ifdef RENDER 880 PanoramiXRenderReset (); 881#endif 882 screenInfo.numScreens = PanoramiXNumScreens; 883 for (i = 256; i--; ) 884 ProcVector[i] = SavedProcVector[i]; 885 886 Xfree(panoramiXdataPtr); 887} 888 889 890int 891ProcPanoramiXQueryVersion (ClientPtr client) 892{ 893 /* REQUEST(xPanoramiXQueryVersionReq); */ 894 xPanoramiXQueryVersionReply rep; 895 register int n; 896 897 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 898 rep.type = X_Reply; 899 rep.length = 0; 900 rep.sequenceNumber = client->sequence; 901 rep.majorVersion = PANORAMIX_MAJOR_VERSION; 902 rep.minorVersion = PANORAMIX_MINOR_VERSION; 903 if (client->swapped) { 904 swaps(&rep.sequenceNumber, n); 905 swapl(&rep.length, n); 906 swaps(&rep.majorVersion, n); 907 swaps(&rep.minorVersion, n); 908 } 909 WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); 910 return (client->noClientException); 911} 912 913int 914ProcPanoramiXGetState(ClientPtr client) 915{ 916 REQUEST(xPanoramiXGetStateReq); 917 WindowPtr pWin; 918 xPanoramiXGetStateReply rep; 919 register int n, rc; 920 921 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 922 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); 923 if (rc != Success) 924 return rc; 925 926 rep.type = X_Reply; 927 rep.length = 0; 928 rep.sequenceNumber = client->sequence; 929 rep.state = !noPanoramiXExtension; 930 if (client->swapped) { 931 swaps (&rep.sequenceNumber, n); 932 swapl (&rep.length, n); 933 swaps (&rep.state, n); 934 } 935 WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); 936 return client->noClientException; 937 938} 939 940int 941ProcPanoramiXGetScreenCount(ClientPtr client) 942{ 943 REQUEST(xPanoramiXGetScreenCountReq); 944 WindowPtr pWin; 945 xPanoramiXGetScreenCountReply rep; 946 register int n, rc; 947 948 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 949 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); 950 if (rc != Success) 951 return rc; 952 953 rep.type = X_Reply; 954 rep.length = 0; 955 rep.sequenceNumber = client->sequence; 956 rep.ScreenCount = PanoramiXNumScreens; 957 if (client->swapped) { 958 swaps (&rep.sequenceNumber, n); 959 swapl (&rep.length, n); 960 swaps (&rep.ScreenCount, n); 961 } 962 WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); 963 return client->noClientException; 964} 965 966int 967ProcPanoramiXGetScreenSize(ClientPtr client) 968{ 969 REQUEST(xPanoramiXGetScreenSizeReq); 970 WindowPtr pWin; 971 xPanoramiXGetScreenSizeReply rep; 972 register int n, rc; 973 974 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 975 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); 976 if (rc != Success) 977 return rc; 978 979 rep.type = X_Reply; 980 rep.length = 0; 981 rep.sequenceNumber = client->sequence; 982 /* screen dimensions */ 983 rep.width = panoramiXdataPtr[stuff->screen].width; 984 rep.height = panoramiXdataPtr[stuff->screen].height; 985 if (client->swapped) { 986 swaps (&rep.sequenceNumber, n); 987 swapl (&rep.length, n); 988 swaps (&rep.width, n); 989 swaps (&rep.height, n); 990 } 991 WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); 992 return client->noClientException; 993} 994 995 996int 997ProcXineramaIsActive(ClientPtr client) 998{ 999 /* REQUEST(xXineramaIsActiveReq); */ 1000 xXineramaIsActiveReply rep; 1001 1002 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 1003 1004 rep.type = X_Reply; 1005 rep.length = 0; 1006 rep.sequenceNumber = client->sequence; 1007#if 1 1008 { 1009 /* The following hack fools clients into thinking that Xinerama 1010 * is disabled even though it is not. */ 1011 rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack; 1012 } 1013#else 1014 rep.state = !noPanoramiXExtension; 1015#endif 1016 if (client->swapped) { 1017 register int n; 1018 swaps (&rep.sequenceNumber, n); 1019 swapl (&rep.length, n); 1020 swapl (&rep.state, n); 1021 } 1022 WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); 1023 return client->noClientException; 1024} 1025 1026 1027int 1028ProcXineramaQueryScreens(ClientPtr client) 1029{ 1030 /* REQUEST(xXineramaQueryScreensReq); */ 1031 xXineramaQueryScreensReply rep; 1032 1033 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 1034 1035 rep.type = X_Reply; 1036 rep.sequenceNumber = client->sequence; 1037 rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; 1038 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 1039 if (client->swapped) { 1040 register int n; 1041 swaps (&rep.sequenceNumber, n); 1042 swapl (&rep.length, n); 1043 swapl (&rep.number, n); 1044 } 1045 WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); 1046 1047 if(!noPanoramiXExtension) { 1048 xXineramaScreenInfo scratch; 1049 int i; 1050 1051 for(i = 0; i < PanoramiXNumScreens; i++) { 1052 scratch.x_org = panoramiXdataPtr[i].x; 1053 scratch.y_org = panoramiXdataPtr[i].y; 1054 scratch.width = panoramiXdataPtr[i].width; 1055 scratch.height = panoramiXdataPtr[i].height; 1056 1057 if(client->swapped) { 1058 register int n; 1059 swaps (&scratch.x_org, n); 1060 swaps (&scratch.y_org, n); 1061 swaps (&scratch.width, n); 1062 swaps (&scratch.height, n); 1063 } 1064 WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); 1065 } 1066 } 1067 1068 return client->noClientException; 1069} 1070 1071 1072static int 1073ProcPanoramiXDispatch (ClientPtr client) 1074{ REQUEST(xReq); 1075 switch (stuff->data) 1076 { 1077 case X_PanoramiXQueryVersion: 1078 return ProcPanoramiXQueryVersion(client); 1079 case X_PanoramiXGetState: 1080 return ProcPanoramiXGetState(client); 1081 case X_PanoramiXGetScreenCount: 1082 return ProcPanoramiXGetScreenCount(client); 1083 case X_PanoramiXGetScreenSize: 1084 return ProcPanoramiXGetScreenSize(client); 1085 case X_XineramaIsActive: 1086 return ProcXineramaIsActive(client); 1087 case X_XineramaQueryScreens: 1088 return ProcXineramaQueryScreens(client); 1089 } 1090 return BadRequest; 1091} 1092 1093 1094#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1095#define SHIFT_L(v,s) (v) << (s) 1096#define SHIFT_R(v,s) (v) >> (s) 1097#else 1098#define SHIFT_L(v,s) (v) >> (s) 1099#define SHIFT_R(v,s) (v) << (s) 1100#endif 1101 1102static void 1103CopyBits(char *dst, int shiftL, char *src, int bytes) 1104{ 1105 /* Just get it to work. Worry about speed later */ 1106 int shiftR = 8 - shiftL; 1107 1108 while(bytes--) { 1109 *dst |= SHIFT_L(*src, shiftL); 1110 *(dst + 1) |= SHIFT_R(*src, shiftR); 1111 dst++; src++; 1112 } 1113} 1114 1115 1116/* Caution. This doesn't support 2 and 4 bpp formats. We expect 1117 1 bpp and planar data to be already cleared when presented 1118 to this function */ 1119 1120void 1121XineramaGetImageData( 1122 DrawablePtr *pDrawables, 1123 int left, 1124 int top, 1125 int width, 1126 int height, 1127 unsigned int format, 1128 unsigned long planemask, 1129 char *data, 1130 int pitch, 1131 Bool isRoot 1132){ 1133 RegionRec SrcRegion, GrabRegion; 1134 BoxRec SrcBox, *pbox; 1135 int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth; 1136 DrawablePtr pDraw = pDrawables[0]; 1137 char *ScratchMem = NULL; 1138 1139 size = 0; 1140 1141 /* find box in logical screen space */ 1142 SrcBox.x1 = left; 1143 SrcBox.y1 = top; 1144 if(!isRoot) { 1145 SrcBox.x1 += pDraw->x + panoramiXdataPtr[0].x; 1146 SrcBox.y1 += pDraw->y + panoramiXdataPtr[0].y; 1147 } 1148 SrcBox.x2 = SrcBox.x1 + width; 1149 SrcBox.y2 = SrcBox.y1 + height; 1150 1151 REGION_INIT(pScreen, &SrcRegion, &SrcBox, 1); 1152 REGION_NULL(pScreen, &GrabRegion); 1153 1154 depth = (format == XYPixmap) ? 1 : pDraw->depth; 1155 1156 for(i = 0; i < PanoramiXNumScreens; i++) { 1157 pDraw = pDrawables[i]; 1158 1159 inOut = RECT_IN_REGION(pScreen,&XineramaScreenRegions[i],&SrcBox); 1160 1161 if(inOut == rgnIN) { 1162 (*pDraw->pScreen->GetImage)(pDraw, 1163 SrcBox.x1 - pDraw->x - panoramiXdataPtr[i].x, 1164 SrcBox.y1 - pDraw->y - panoramiXdataPtr[i].y, 1165 width, height, format, planemask, data); 1166 break; 1167 } else if (inOut == rgnOUT) 1168 continue; 1169 1170 REGION_INTERSECT(pScreen, &GrabRegion, &SrcRegion, 1171 &XineramaScreenRegions[i]); 1172 1173 nbox = REGION_NUM_RECTS(&GrabRegion); 1174 1175 if(nbox) { 1176 pbox = REGION_RECTS(&GrabRegion); 1177 1178 while(nbox--) { 1179 w = pbox->x2 - pbox->x1; 1180 h = pbox->y2 - pbox->y1; 1181 ScratchPitch = PixmapBytePad(w, depth); 1182 sizeNeeded = ScratchPitch * h; 1183 1184 if(sizeNeeded > size) { 1185 char *tmpdata = ScratchMem; 1186 ScratchMem = xrealloc(ScratchMem, sizeNeeded); 1187 if(ScratchMem) 1188 size = sizeNeeded; 1189 else { 1190 ScratchMem = tmpdata; 1191 break; 1192 } 1193 } 1194 1195 x = pbox->x1 - pDraw->x - panoramiXdataPtr[i].x; 1196 y = pbox->y1 - pDraw->y - panoramiXdataPtr[i].y; 1197 1198 (*pDraw->pScreen->GetImage)(pDraw, x, y, w, h, 1199 format, planemask, ScratchMem); 1200 1201 /* copy the memory over */ 1202 1203 if(depth == 1) { 1204 int k, shift, leftover, index, index2; 1205 1206 x = pbox->x1 - SrcBox.x1; 1207 y = pbox->y1 - SrcBox.y1; 1208 shift = x & 7; 1209 x >>= 3; 1210 leftover = w & 7; 1211 w >>= 3; 1212 1213 /* clean up the edge */ 1214 if(leftover) { 1215 int mask = (1 << leftover) - 1; 1216 for(j = h, k = w; j--; k += ScratchPitch) 1217 ScratchMem[k] &= mask; 1218 } 1219 1220 for(j = 0, index = (pitch * y) + x, index2 = 0; j < h; 1221 j++, index += pitch, index2 += ScratchPitch) 1222 { 1223 if(w) { 1224 if(!shift) 1225 memcpy(data + index, ScratchMem + index2, w); 1226 else 1227 CopyBits(data + index, shift, 1228 ScratchMem + index2, w); 1229 } 1230 1231 if(leftover) { 1232 data[index + w] |= 1233 SHIFT_L(ScratchMem[index2 + w], shift); 1234 if((shift + leftover) > 8) 1235 data[index + w + 1] |= 1236 SHIFT_R(ScratchMem[index2 + w],(8 - shift)); 1237 } 1238 } 1239 } else { 1240 j = BitsPerPixel(depth) >> 3; 1241 x = (pbox->x1 - SrcBox.x1) * j; 1242 y = pbox->y1 - SrcBox.y1; 1243 w *= j; 1244 1245 for(j = 0; j < h; j++) { 1246 memcpy(data + (pitch * (y + j)) + x, 1247 ScratchMem + (ScratchPitch * j), w); 1248 } 1249 } 1250 pbox++; 1251 } 1252 1253 REGION_SUBTRACT(pScreen, &SrcRegion, &SrcRegion, &GrabRegion); 1254 if(!REGION_NOTEMPTY(pScreen, &SrcRegion)) 1255 break; 1256 } 1257 1258 } 1259 1260 if(ScratchMem) 1261 xfree(ScratchMem); 1262 1263 REGION_UNINIT(pScreen, &SrcRegion); 1264 REGION_UNINIT(pScreen, &GrabRegion); 1265} 1266