1 /*****************************************************************
2 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software.
9 The above copyright notice and this permission notice shall be included in
10 all copies or substantial portions of the Software.
12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
16 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
17 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
18 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 Except as contained in this notice, the name of Digital Equipment Corporation
21 shall not be used in advertising or otherwise to promote the sale, use or other
22 dealings in this Software without prior written authorization from Digital
23 Equipment Corporation.
24 ******************************************************************/
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
30 #ifdef HAVE_DMX_CONFIG_H
31 #include <dmx-config.h>
36 #include <X11/Xproto.h>
37 #include <X11/Xarch.h>
40 #include "cursorstr.h"
41 #include "extnsionst.h"
42 #include "dixstruct.h"
45 #include "scrnintstr.h"
47 #include "windowstr.h"
48 #include "pixmapstr.h"
49 #include "panoramiX.h"
50 #include <X11/extensions/panoramiXproto.h>
51 #include "panoramiXsrv.h"
55 #include "picturestr.h"
56 #include "xfixesint.h"
57 #include "damageextint.h"
62 #include "protocol-versions.h"
65 extern VisualPtr
glxMatchVisual(ScreenPtr pScreen
,
66 VisualPtr pVisual
, ScreenPtr pMatchScreen
);
70 * PanoramiX data declarations
73 int PanoramiXPixWidth
= 0;
74 int PanoramiXPixHeight
= 0;
75 int PanoramiXNumScreens
= 0;
77 _X_EXPORT RegionRec PanoramiXScreenRegion
= { {0, 0, 0, 0}, NULL
};
79 static int PanoramiXNumDepths
;
80 static DepthPtr PanoramiXDepths
;
81 static int PanoramiXNumVisuals
;
82 static VisualPtr PanoramiXVisuals
;
90 static Bool
VisualsEqual(VisualPtr
, ScreenPtr
, VisualPtr
);
91 XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr
= &VisualsEqual
;
97 static int panoramiXGeneration
;
98 static int ProcPanoramiXDispatch(ClientPtr client
);
100 static void PanoramiXResetProc(ExtensionEntry
*);
103 * External references for functions and data variables
106 #include "panoramiXh.h"
108 int (*SavedProcVector
[256]) (ClientPtr client
) = {
111 static DevPrivateKeyRec PanoramiXGCKeyRec
;
113 #define PanoramiXGCKey (&PanoramiXGCKeyRec)
114 static DevPrivateKeyRec PanoramiXScreenKeyRec
;
116 #define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
122 } PanoramiXGCRec
, *PanoramiXGCPtr
;
125 CreateGCProcPtr CreateGC
;
126 CloseScreenProcPtr CloseScreen
;
127 } PanoramiXScreenRec
, *PanoramiXScreenPtr
;
129 static void XineramaValidateGC(GCPtr
, unsigned long, DrawablePtr
);
130 static void XineramaChangeGC(GCPtr
, unsigned long);
131 static void XineramaCopyGC(GCPtr
, unsigned long, GCPtr
);
132 static void XineramaDestroyGC(GCPtr
);
133 static void XineramaChangeClip(GCPtr
, int, pointer
, int);
134 static void XineramaDestroyClip(GCPtr
);
135 static void XineramaCopyClip(GCPtr
, GCPtr
);
137 static GCFuncs XineramaGCFuncs
= {
138 XineramaValidateGC
, XineramaChangeGC
, XineramaCopyGC
, XineramaDestroyGC
,
139 XineramaChangeClip
, XineramaDestroyClip
, XineramaCopyClip
142 #define Xinerama_GC_FUNC_PROLOGUE(pGC)\
143 PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \
144 dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
145 (pGC)->funcs = pGCPriv->wrapFuncs;
147 #define Xinerama_GC_FUNC_EPILOGUE(pGC)\
148 pGCPriv->wrapFuncs = (pGC)->funcs;\
149 (pGC)->funcs = &XineramaGCFuncs;
152 XineramaCloseScreen(ScreenPtr pScreen
)
154 PanoramiXScreenPtr pScreenPriv
= (PanoramiXScreenPtr
)
155 dixLookupPrivate(&pScreen
->devPrivates
, PanoramiXScreenKey
);
157 pScreen
->CloseScreen
= pScreenPriv
->CloseScreen
;
158 pScreen
->CreateGC
= pScreenPriv
->CreateGC
;
160 if (pScreen
->myNum
== 0)
161 RegionUninit(&PanoramiXScreenRegion
);
163 free((pointer
) pScreenPriv
);
165 return (*pScreen
->CloseScreen
) (pScreen
);
169 XineramaCreateGC(GCPtr pGC
)
171 ScreenPtr pScreen
= pGC
->pScreen
;
172 PanoramiXScreenPtr pScreenPriv
= (PanoramiXScreenPtr
)
173 dixLookupPrivate(&pScreen
->devPrivates
, PanoramiXScreenKey
);
176 pScreen
->CreateGC
= pScreenPriv
->CreateGC
;
177 if ((ret
= (*pScreen
->CreateGC
) (pGC
))) {
178 PanoramiXGCPtr pGCPriv
= (PanoramiXGCPtr
)
179 dixLookupPrivate(&pGC
->devPrivates
, PanoramiXGCKey
);
181 pGCPriv
->wrapFuncs
= pGC
->funcs
;
182 pGC
->funcs
= &XineramaGCFuncs
;
184 pGCPriv
->clipOrg
.x
= pGC
->clipOrg
.x
;
185 pGCPriv
->clipOrg
.y
= pGC
->clipOrg
.y
;
186 pGCPriv
->patOrg
.x
= pGC
->patOrg
.x
;
187 pGCPriv
->patOrg
.y
= pGC
->patOrg
.y
;
189 pScreen
->CreateGC
= XineramaCreateGC
;
195 XineramaValidateGC(GCPtr pGC
, unsigned long changes
, DrawablePtr pDraw
)
197 Xinerama_GC_FUNC_PROLOGUE(pGC
);
199 if ((pDraw
->type
== DRAWABLE_WINDOW
) && !(((WindowPtr
) pDraw
)->parent
)) {
200 /* the root window */
201 int x_off
= pGC
->pScreen
->x
;
202 int y_off
= pGC
->pScreen
->y
;
205 new_val
= pGCPriv
->clipOrg
.x
- x_off
;
206 if (pGC
->clipOrg
.x
!= new_val
) {
207 pGC
->clipOrg
.x
= new_val
;
208 changes
|= GCClipXOrigin
;
210 new_val
= pGCPriv
->clipOrg
.y
- y_off
;
211 if (pGC
->clipOrg
.y
!= new_val
) {
212 pGC
->clipOrg
.y
= new_val
;
213 changes
|= GCClipYOrigin
;
215 new_val
= pGCPriv
->patOrg
.x
- x_off
;
216 if (pGC
->patOrg
.x
!= new_val
) {
217 pGC
->patOrg
.x
= new_val
;
218 changes
|= GCTileStipXOrigin
;
220 new_val
= pGCPriv
->patOrg
.y
- y_off
;
221 if (pGC
->patOrg
.y
!= new_val
) {
222 pGC
->patOrg
.y
= new_val
;
223 changes
|= GCTileStipYOrigin
;
227 if (pGC
->clipOrg
.x
!= pGCPriv
->clipOrg
.x
) {
228 pGC
->clipOrg
.x
= pGCPriv
->clipOrg
.x
;
229 changes
|= GCClipXOrigin
;
231 if (pGC
->clipOrg
.y
!= pGCPriv
->clipOrg
.y
) {
232 pGC
->clipOrg
.y
= pGCPriv
->clipOrg
.y
;
233 changes
|= GCClipYOrigin
;
235 if (pGC
->patOrg
.x
!= pGCPriv
->patOrg
.x
) {
236 pGC
->patOrg
.x
= pGCPriv
->patOrg
.x
;
237 changes
|= GCTileStipXOrigin
;
239 if (pGC
->patOrg
.y
!= pGCPriv
->patOrg
.y
) {
240 pGC
->patOrg
.y
= pGCPriv
->patOrg
.y
;
241 changes
|= GCTileStipYOrigin
;
245 (*pGC
->funcs
->ValidateGC
) (pGC
, changes
, pDraw
);
246 Xinerama_GC_FUNC_EPILOGUE(pGC
);
250 XineramaDestroyGC(GCPtr pGC
)
252 Xinerama_GC_FUNC_PROLOGUE(pGC
);
253 (*pGC
->funcs
->DestroyGC
) (pGC
);
254 Xinerama_GC_FUNC_EPILOGUE(pGC
);
258 XineramaChangeGC(GCPtr pGC
, unsigned long mask
)
260 Xinerama_GC_FUNC_PROLOGUE(pGC
);
262 if (mask
& GCTileStipXOrigin
)
263 pGCPriv
->patOrg
.x
= pGC
->patOrg
.x
;
264 if (mask
& GCTileStipYOrigin
)
265 pGCPriv
->patOrg
.y
= pGC
->patOrg
.y
;
266 if (mask
& GCClipXOrigin
)
267 pGCPriv
->clipOrg
.x
= pGC
->clipOrg
.x
;
268 if (mask
& GCClipYOrigin
)
269 pGCPriv
->clipOrg
.y
= pGC
->clipOrg
.y
;
271 (*pGC
->funcs
->ChangeGC
) (pGC
, mask
);
272 Xinerama_GC_FUNC_EPILOGUE(pGC
);
276 XineramaCopyGC(GCPtr pGCSrc
, unsigned long mask
, GCPtr pGCDst
)
278 PanoramiXGCPtr pSrcPriv
= (PanoramiXGCPtr
)
279 dixLookupPrivate(&pGCSrc
->devPrivates
, PanoramiXGCKey
);
281 Xinerama_GC_FUNC_PROLOGUE(pGCDst
);
283 if (mask
& GCTileStipXOrigin
)
284 pGCPriv
->patOrg
.x
= pSrcPriv
->patOrg
.x
;
285 if (mask
& GCTileStipYOrigin
)
286 pGCPriv
->patOrg
.y
= pSrcPriv
->patOrg
.y
;
287 if (mask
& GCClipXOrigin
)
288 pGCPriv
->clipOrg
.x
= pSrcPriv
->clipOrg
.x
;
289 if (mask
& GCClipYOrigin
)
290 pGCPriv
->clipOrg
.y
= pSrcPriv
->clipOrg
.y
;
292 (*pGCDst
->funcs
->CopyGC
) (pGCSrc
, mask
, pGCDst
);
293 Xinerama_GC_FUNC_EPILOGUE(pGCDst
);
297 XineramaChangeClip(GCPtr pGC
, int type
, pointer pvalue
, int nrects
)
299 Xinerama_GC_FUNC_PROLOGUE(pGC
);
300 (*pGC
->funcs
->ChangeClip
) (pGC
, type
, pvalue
, nrects
);
301 Xinerama_GC_FUNC_EPILOGUE(pGC
);
305 XineramaCopyClip(GCPtr pgcDst
, GCPtr pgcSrc
)
307 Xinerama_GC_FUNC_PROLOGUE(pgcDst
);
308 (*pgcDst
->funcs
->CopyClip
) (pgcDst
, pgcSrc
);
309 Xinerama_GC_FUNC_EPILOGUE(pgcDst
);
313 XineramaDestroyClip(GCPtr pGC
)
315 Xinerama_GC_FUNC_PROLOGUE(pGC
);
316 (*pGC
->funcs
->DestroyClip
) (pGC
);
317 Xinerama_GC_FUNC_EPILOGUE(pGC
);
321 XineramaDeleteResource(pointer data
, XID id
)
330 } PanoramiXSearchData
;
333 XineramaFindIDByScrnum(pointer resource
, XID id
, pointer privdata
)
335 PanoramiXRes
*res
= (PanoramiXRes
*) resource
;
336 PanoramiXSearchData
*data
= (PanoramiXSearchData
*) privdata
;
338 return res
->info
[data
->screen
].id
== data
->id
;
342 PanoramiXFindIDByScrnum(RESTYPE type
, XID id
, int screen
)
344 PanoramiXSearchData data
;
348 dixLookupResourceByType(&val
, id
, type
, serverClient
, DixReadAccess
);
352 data
.screen
= screen
;
355 return LookupClientResourceComplex(clients
[CLIENT_ID(id
)], type
,
356 XineramaFindIDByScrnum
, &data
);
359 typedef struct _connect_callback_list
{
361 struct _connect_callback_list
*next
;
362 } XineramaConnectionCallbackList
;
364 static XineramaConnectionCallbackList
*ConnectionCallbackList
= NULL
;
367 XineramaRegisterConnectionBlockCallback(void (*func
) (void))
369 XineramaConnectionCallbackList
*newlist
;
371 if (!(newlist
= malloc(sizeof(XineramaConnectionCallbackList
))))
374 newlist
->next
= ConnectionCallbackList
;
375 newlist
->func
= func
;
376 ConnectionCallbackList
= newlist
;
382 XineramaInitData(void)
386 RegionNull(&PanoramiXScreenRegion
);
389 RegionRec ScreenRegion
;
391 ScreenPtr pScreen
= screenInfo
.screens
[i
];
393 TheBox
.x1
= pScreen
->x
;
394 TheBox
.x2
= TheBox
.x1
+ pScreen
->width
;
395 TheBox
.y1
= pScreen
->y
;
396 TheBox
.y2
= TheBox
.y1
+ pScreen
->height
;
398 RegionInit(&ScreenRegion
, &TheBox
, 1);
399 RegionUnion(&PanoramiXScreenRegion
, &PanoramiXScreenRegion
,
401 RegionUninit(&ScreenRegion
);
404 PanoramiXPixWidth
= screenInfo
.screens
[0]->x
+ screenInfo
.screens
[0]->width
;
406 screenInfo
.screens
[0]->y
+ screenInfo
.screens
[0]->height
;
408 FOR_NSCREENS_FORWARD_SKIP(i
) {
409 ScreenPtr pScreen
= screenInfo
.screens
[i
];
411 w
= pScreen
->x
+ pScreen
->width
;
412 h
= pScreen
->y
+ pScreen
->height
;
414 if (PanoramiXPixWidth
< w
)
415 PanoramiXPixWidth
= w
;
416 if (PanoramiXPixHeight
< h
)
417 PanoramiXPixHeight
= h
;
422 XineramaReinitData(void)
424 RegionUninit(&PanoramiXScreenRegion
);
429 * PanoramiXExtensionInit():
430 * Called from InitExtensions in main().
431 * Register PanoramiXeen Extension
432 * Initialize global variables.
436 PanoramiXExtensionInit(void)
439 Bool success
= FALSE
;
440 ExtensionEntry
*extEntry
;
441 ScreenPtr pScreen
= screenInfo
.screens
[0];
442 PanoramiXScreenPtr pScreenPriv
;
444 if (noPanoramiXExtension
)
447 if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec
, PRIVATE_SCREEN
, 0)) {
448 noPanoramiXExtension
= TRUE
;
452 if (!dixRegisterPrivateKey
453 (&PanoramiXGCKeyRec
, PRIVATE_GC
, sizeof(PanoramiXGCRec
))) {
454 noPanoramiXExtension
= TRUE
;
458 PanoramiXNumScreens
= screenInfo
.numScreens
;
459 if (PanoramiXNumScreens
== 1) { /* Only 1 screen */
460 noPanoramiXExtension
= TRUE
;
464 while (panoramiXGeneration
!= serverGeneration
) {
465 extEntry
= AddExtension(PANORAMIX_PROTOCOL_NAME
, 0, 0,
466 ProcPanoramiXDispatch
,
467 SProcPanoramiXDispatch
, PanoramiXResetProc
,
468 StandardMinorOpcode
);
473 * First make sure all the basic allocations succeed. If not,
474 * run in non-PanoramiXeen mode.
478 pScreen
= screenInfo
.screens
[i
];
479 pScreenPriv
= malloc(sizeof(PanoramiXScreenRec
));
480 dixSetPrivate(&pScreen
->devPrivates
, PanoramiXScreenKey
,
483 noPanoramiXExtension
= TRUE
;
487 pScreenPriv
->CreateGC
= pScreen
->CreateGC
;
488 pScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
490 pScreen
->CreateGC
= XineramaCreateGC
;
491 pScreen
->CloseScreen
= XineramaCloseScreen
;
494 XRC_DRAWABLE
= CreateNewResourceClass();
495 XRT_WINDOW
= CreateNewResourceType(XineramaDeleteResource
,
498 XRT_WINDOW
|= XRC_DRAWABLE
;
499 XRT_PIXMAP
= CreateNewResourceType(XineramaDeleteResource
,
502 XRT_PIXMAP
|= XRC_DRAWABLE
;
503 XRT_GC
= CreateNewResourceType(XineramaDeleteResource
, "XineramaGC");
504 XRT_COLORMAP
= CreateNewResourceType(XineramaDeleteResource
,
507 if (XRT_WINDOW
&& XRT_PIXMAP
&& XRT_GC
&& XRT_COLORMAP
) {
508 panoramiXGeneration
= serverGeneration
;
511 SetResourceTypeErrorValue(XRT_WINDOW
, BadWindow
);
512 SetResourceTypeErrorValue(XRT_PIXMAP
, BadPixmap
);
513 SetResourceTypeErrorValue(XRT_GC
, BadGC
);
514 SetResourceTypeErrorValue(XRT_COLORMAP
, BadColor
);
518 noPanoramiXExtension
= TRUE
;
519 ErrorF(PANORAMIX_PROTOCOL_NAME
" extension failed to initialize\n");
526 * Put our processes into the ProcVector
530 SavedProcVector
[i
] = ProcVector
[i
];
532 ProcVector
[X_CreateWindow
] = PanoramiXCreateWindow
;
533 ProcVector
[X_ChangeWindowAttributes
] = PanoramiXChangeWindowAttributes
;
534 ProcVector
[X_DestroyWindow
] = PanoramiXDestroyWindow
;
535 ProcVector
[X_DestroySubwindows
] = PanoramiXDestroySubwindows
;
536 ProcVector
[X_ChangeSaveSet
] = PanoramiXChangeSaveSet
;
537 ProcVector
[X_ReparentWindow
] = PanoramiXReparentWindow
;
538 ProcVector
[X_MapWindow
] = PanoramiXMapWindow
;
539 ProcVector
[X_MapSubwindows
] = PanoramiXMapSubwindows
;
540 ProcVector
[X_UnmapWindow
] = PanoramiXUnmapWindow
;
541 ProcVector
[X_UnmapSubwindows
] = PanoramiXUnmapSubwindows
;
542 ProcVector
[X_ConfigureWindow
] = PanoramiXConfigureWindow
;
543 ProcVector
[X_CirculateWindow
] = PanoramiXCirculateWindow
;
544 ProcVector
[X_GetGeometry
] = PanoramiXGetGeometry
;
545 ProcVector
[X_TranslateCoords
] = PanoramiXTranslateCoords
;
546 ProcVector
[X_CreatePixmap
] = PanoramiXCreatePixmap
;
547 ProcVector
[X_FreePixmap
] = PanoramiXFreePixmap
;
548 ProcVector
[X_CreateGC
] = PanoramiXCreateGC
;
549 ProcVector
[X_ChangeGC
] = PanoramiXChangeGC
;
550 ProcVector
[X_CopyGC
] = PanoramiXCopyGC
;
551 ProcVector
[X_SetDashes
] = PanoramiXSetDashes
;
552 ProcVector
[X_SetClipRectangles
] = PanoramiXSetClipRectangles
;
553 ProcVector
[X_FreeGC
] = PanoramiXFreeGC
;
554 ProcVector
[X_ClearArea
] = PanoramiXClearToBackground
;
555 ProcVector
[X_CopyArea
] = PanoramiXCopyArea
;
556 ProcVector
[X_CopyPlane
] = PanoramiXCopyPlane
;
557 ProcVector
[X_PolyPoint
] = PanoramiXPolyPoint
;
558 ProcVector
[X_PolyLine
] = PanoramiXPolyLine
;
559 ProcVector
[X_PolySegment
] = PanoramiXPolySegment
;
560 ProcVector
[X_PolyRectangle
] = PanoramiXPolyRectangle
;
561 ProcVector
[X_PolyArc
] = PanoramiXPolyArc
;
562 ProcVector
[X_FillPoly
] = PanoramiXFillPoly
;
563 ProcVector
[X_PolyFillRectangle
] = PanoramiXPolyFillRectangle
;
564 ProcVector
[X_PolyFillArc
] = PanoramiXPolyFillArc
;
565 ProcVector
[X_PutImage
] = PanoramiXPutImage
;
566 ProcVector
[X_GetImage
] = PanoramiXGetImage
;
567 ProcVector
[X_PolyText8
] = PanoramiXPolyText8
;
568 ProcVector
[X_PolyText16
] = PanoramiXPolyText16
;
569 ProcVector
[X_ImageText8
] = PanoramiXImageText8
;
570 ProcVector
[X_ImageText16
] = PanoramiXImageText16
;
571 ProcVector
[X_CreateColormap
] = PanoramiXCreateColormap
;
572 ProcVector
[X_FreeColormap
] = PanoramiXFreeColormap
;
573 ProcVector
[X_CopyColormapAndFree
] = PanoramiXCopyColormapAndFree
;
574 ProcVector
[X_InstallColormap
] = PanoramiXInstallColormap
;
575 ProcVector
[X_UninstallColormap
] = PanoramiXUninstallColormap
;
576 ProcVector
[X_AllocColor
] = PanoramiXAllocColor
;
577 ProcVector
[X_AllocNamedColor
] = PanoramiXAllocNamedColor
;
578 ProcVector
[X_AllocColorCells
] = PanoramiXAllocColorCells
;
579 ProcVector
[X_AllocColorPlanes
] = PanoramiXAllocColorPlanes
;
580 ProcVector
[X_FreeColors
] = PanoramiXFreeColors
;
581 ProcVector
[X_StoreColors
] = PanoramiXStoreColors
;
582 ProcVector
[X_StoreNamedColor
] = PanoramiXStoreNamedColor
;
584 PanoramiXRenderInit();
585 PanoramiXFixesInit();
586 PanoramiXDamageInit();
588 PanoramiXCompositeInit();
594 PanoramiXCreateConnectionBlock(void)
597 Bool disable_backing_store
= FALSE
;
598 int old_width
, old_height
;
599 float width_mult
, height_mult
;
607 * Do normal CreateConnectionBlock but faking it for only one screen
610 if (!PanoramiXNumDepths
) {
611 ErrorF("Xinerama error: No common visuals\n");
615 for (i
= 1; i
< screenInfo
.numScreens
; i
++) {
616 pScreen
= screenInfo
.screens
[i
];
617 if (pScreen
->rootDepth
!= screenInfo
.screens
[0]->rootDepth
) {
618 ErrorF("Xinerama error: Root window depths differ\n");
621 if (pScreen
->backingStoreSupport
!=
622 screenInfo
.screens
[0]->backingStoreSupport
)
623 disable_backing_store
= TRUE
;
626 if (disable_backing_store
) {
627 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
628 pScreen
= screenInfo
.screens
[i
];
629 pScreen
->backingStoreSupport
= NotUseful
;
633 i
= screenInfo
.numScreens
;
634 screenInfo
.numScreens
= 1;
635 if (!CreateConnectionBlock()) {
636 screenInfo
.numScreens
= i
;
640 screenInfo
.numScreens
= i
;
642 root
= (xWindowRoot
*) (ConnectionInfo
+ connBlockScreenStart
);
643 length
= connBlockScreenStart
+ sizeof(xWindowRoot
);
645 /* overwrite the connection block */
646 root
->nDepths
= PanoramiXNumDepths
;
648 for (i
= 0; i
< PanoramiXNumDepths
; i
++) {
649 depth
= (xDepth
*) (ConnectionInfo
+ length
);
650 depth
->depth
= PanoramiXDepths
[i
].depth
;
651 depth
->nVisuals
= PanoramiXDepths
[i
].numVids
;
652 length
+= sizeof(xDepth
);
653 visual
= (xVisualType
*) (ConnectionInfo
+ length
);
655 for (j
= 0; j
< depth
->nVisuals
; j
++, visual
++) {
656 visual
->visualID
= PanoramiXDepths
[i
].vids
[j
];
658 for (pVisual
= PanoramiXVisuals
;
659 pVisual
->vid
!= visual
->visualID
; pVisual
++);
661 visual
->class = pVisual
->class;
662 visual
->bitsPerRGB
= pVisual
->bitsPerRGBValue
;
663 visual
->colormapEntries
= pVisual
->ColormapEntries
;
664 visual
->redMask
= pVisual
->redMask
;
665 visual
->greenMask
= pVisual
->greenMask
;
666 visual
->blueMask
= pVisual
->blueMask
;
669 length
+= (depth
->nVisuals
* sizeof(xVisualType
));
672 connSetupPrefix
.length
= bytes_to_int32(length
);
674 for (i
= 0; i
< PanoramiXNumDepths
; i
++)
675 free(PanoramiXDepths
[i
].vids
);
676 free(PanoramiXDepths
);
677 PanoramiXDepths
= NULL
;
680 * OK, change some dimensions so it looks as if it were one big screen
683 old_width
= root
->pixWidth
;
684 old_height
= root
->pixHeight
;
686 root
->pixWidth
= PanoramiXPixWidth
;
687 root
->pixHeight
= PanoramiXPixHeight
;
688 width_mult
= (1.0 * root
->pixWidth
) / old_width
;
689 height_mult
= (1.0 * root
->pixHeight
) / old_height
;
690 root
->mmWidth
*= width_mult
;
691 root
->mmHeight
*= height_mult
;
693 while (ConnectionCallbackList
) {
696 tmp
= (pointer
) ConnectionCallbackList
;
697 (*ConnectionCallbackList
->func
) ();
698 ConnectionCallbackList
= ConnectionCallbackList
->next
;
706 * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that
707 * change way back before xf86 4.0, but the comment for _why_ is a bit
708 * opaque, so I'm not going to question it for now.
710 * This is probably better done as a screen hook so DBE/EVI/GLX can add
711 * their own tests, and adding privates to VisualRec so they don't have to
712 * do their own back-mapping.
715 VisualsEqual(VisualPtr a
, ScreenPtr pScreenB
, VisualPtr b
)
717 return ((a
->class == b
->class) &&
718 (a
->ColormapEntries
== b
->ColormapEntries
) &&
719 (a
->nplanes
== b
->nplanes
) &&
720 (a
->redMask
== b
->redMask
) &&
721 (a
->greenMask
== b
->greenMask
) &&
722 (a
->blueMask
== b
->blueMask
) &&
723 (a
->offsetRed
== b
->offsetRed
) &&
724 (a
->offsetGreen
== b
->offsetGreen
) &&
725 (a
->offsetBlue
== b
->offsetBlue
));
729 PanoramiXMaybeAddDepth(DepthPtr pDepth
)
735 FOR_NSCREENS_FORWARD_SKIP(j
) {
736 pScreen
= screenInfo
.screens
[j
];
737 for (k
= 0; k
< pScreen
->numDepths
; k
++) {
738 if (pScreen
->allowedDepths
[k
].depth
== pDepth
->depth
) {
748 j
= PanoramiXNumDepths
;
749 PanoramiXNumDepths
++;
750 PanoramiXDepths
= realloc(PanoramiXDepths
,
751 PanoramiXNumDepths
* sizeof(DepthRec
));
752 PanoramiXDepths
[j
].depth
= pDepth
->depth
;
753 PanoramiXDepths
[j
].numVids
= 0;
754 /* XXX suboptimal, should grow these dynamically */
756 PanoramiXDepths
[j
].vids
= malloc(sizeof(VisualID
) * pDepth
->numVids
);
758 PanoramiXDepths
[j
].vids
= NULL
;
762 PanoramiXMaybeAddVisual(VisualPtr pVisual
)
768 FOR_NSCREENS_FORWARD_SKIP(j
) {
769 pScreen
= screenInfo
.screens
[j
];
772 for (k
= 0; k
< pScreen
->numVisuals
; k
++) {
773 VisualPtr candidate
= &pScreen
->visuals
[k
];
775 if ((*XineramaVisualsEqualPtr
) (pVisual
, pScreen
, candidate
)
777 && glxMatchVisual(screenInfo
.screens
[0], pVisual
, pScreen
)
789 /* found a matching visual on all screens, add it to the subset list */
790 j
= PanoramiXNumVisuals
;
791 PanoramiXNumVisuals
++;
792 PanoramiXVisuals
= realloc(PanoramiXVisuals
,
793 PanoramiXNumVisuals
* sizeof(VisualRec
));
795 memcpy(&PanoramiXVisuals
[j
], pVisual
, sizeof(VisualRec
));
797 for (k
= 0; k
< PanoramiXNumDepths
; k
++) {
798 if (PanoramiXDepths
[k
].depth
== pVisual
->nplanes
) {
799 PanoramiXDepths
[k
].vids
[PanoramiXDepths
[k
].numVids
] = pVisual
->vid
;
800 PanoramiXDepths
[k
].numVids
++;
807 PanoramiXConsolidate(void)
810 PanoramiXRes
*root
, *defmap
, *saver
;
811 ScreenPtr pScreen
= screenInfo
.screens
[0];
812 DepthPtr pDepth
= pScreen
->allowedDepths
;
813 VisualPtr pVisual
= pScreen
->visuals
;
815 PanoramiXNumDepths
= 0;
816 PanoramiXNumVisuals
= 0;
818 for (i
= 0; i
< pScreen
->numDepths
; i
++)
819 PanoramiXMaybeAddDepth(pDepth
++);
821 for (i
= 0; i
< pScreen
->numVisuals
; i
++)
822 PanoramiXMaybeAddVisual(pVisual
++);
824 root
= malloc(sizeof(PanoramiXRes
));
825 root
->type
= XRT_WINDOW
;
826 defmap
= malloc(sizeof(PanoramiXRes
));
827 defmap
->type
= XRT_COLORMAP
;
828 saver
= malloc(sizeof(PanoramiXRes
));
829 saver
->type
= XRT_WINDOW
;
832 ScreenPtr scr
= screenInfo
.screens
[i
];
834 root
->info
[i
].id
= scr
->root
->drawable
.id
;
835 root
->u
.win
.class = InputOutput
;
836 root
->u
.win
.root
= TRUE
;
837 saver
->info
[i
].id
= scr
->screensaver
.wid
;
838 saver
->u
.win
.class = InputOutput
;
839 saver
->u
.win
.root
= TRUE
;
840 defmap
->info
[i
].id
= scr
->defColormap
;
843 AddResource(root
->info
[0].id
, XRT_WINDOW
, root
);
844 AddResource(saver
->info
[0].id
, XRT_WINDOW
, saver
);
845 AddResource(defmap
->info
[0].id
, XRT_COLORMAP
, defmap
);
849 PanoramiXTranslateVisualID(int screen
, VisualID orig
)
851 ScreenPtr pOtherScreen
= screenInfo
.screens
[screen
];
852 VisualPtr pVisual
= NULL
;
855 for (i
= 0; i
< PanoramiXNumVisuals
; i
++) {
856 if (orig
== PanoramiXVisuals
[i
].vid
) {
857 pVisual
= &PanoramiXVisuals
[i
];
865 /* if screen is 0, orig is already the correct visual ID */
869 /* found the original, now translate it relative to the backend screen */
870 for (i
= 0; i
< pOtherScreen
->numVisuals
; i
++) {
871 VisualPtr pOtherVisual
= &pOtherScreen
->visuals
[i
];
873 if ((*XineramaVisualsEqualPtr
) (pVisual
, pOtherScreen
, pOtherVisual
))
874 return pOtherVisual
->vid
;
881 * PanoramiXResetProc()
882 * Exit, deallocating as needed.
886 PanoramiXResetProc(ExtensionEntry
* extEntry
)
890 PanoramiXRenderReset();
891 PanoramiXFixesReset();
892 PanoramiXDamageReset();
894 PanoramiXCompositeReset ();
896 screenInfo
.numScreens
= PanoramiXNumScreens
;
898 ProcVector
[i
] = SavedProcVector
[i
];
902 ProcPanoramiXQueryVersion(ClientPtr client
)
904 /* REQUEST(xPanoramiXQueryVersionReq); */
905 xPanoramiXQueryVersionReply rep
= {
907 .sequenceNumber
= client
->sequence
,
909 .majorVersion
= SERVER_PANORAMIX_MAJOR_VERSION
,
910 .minorVersion
= SERVER_PANORAMIX_MINOR_VERSION
913 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
914 if (client
->swapped
) {
915 swaps(&rep
.sequenceNumber
);
917 swaps(&rep
.majorVersion
);
918 swaps(&rep
.minorVersion
);
920 WriteToClient(client
, sizeof(xPanoramiXQueryVersionReply
), &rep
);
925 ProcPanoramiXGetState(ClientPtr client
)
927 REQUEST(xPanoramiXGetStateReq
);
929 xPanoramiXGetStateReply rep
;
932 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
933 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
937 rep
= (xPanoramiXGetStateReply
) {
939 .state
= !noPanoramiXExtension
,
940 .sequenceNumber
= client
->sequence
,
942 .window
= stuff
->window
944 if (client
->swapped
) {
945 swaps(&rep
.sequenceNumber
);
949 WriteToClient(client
, sizeof(xPanoramiXGetStateReply
), &rep
);
955 ProcPanoramiXGetScreenCount(ClientPtr client
)
957 REQUEST(xPanoramiXGetScreenCountReq
);
959 xPanoramiXGetScreenCountReply rep
;
962 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
963 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
967 rep
= (xPanoramiXGetScreenCountReply
) {
969 .ScreenCount
= PanoramiXNumScreens
,
970 .sequenceNumber
= client
->sequence
,
972 .window
= stuff
->window
974 if (client
->swapped
) {
975 swaps(&rep
.sequenceNumber
);
979 WriteToClient(client
, sizeof(xPanoramiXGetScreenCountReply
), &rep
);
984 ProcPanoramiXGetScreenSize(ClientPtr client
)
986 REQUEST(xPanoramiXGetScreenSizeReq
);
988 xPanoramiXGetScreenSizeReply rep
;
991 if (stuff
->screen
>= PanoramiXNumScreens
)
994 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
995 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
999 rep
= (xPanoramiXGetScreenSizeReply
) {
1001 .sequenceNumber
= client
->sequence
,
1003 /* screen dimensions */
1004 .width
= screenInfo
.screens
[stuff
->screen
]->width
,
1005 .height
= screenInfo
.screens
[stuff
->screen
]->height
,
1006 .window
= stuff
->window
,
1007 .screen
= stuff
->screen
1009 if (client
->swapped
) {
1010 swaps(&rep
.sequenceNumber
);
1017 WriteToClient(client
, sizeof(xPanoramiXGetScreenSizeReply
), &rep
);
1022 ProcXineramaIsActive(ClientPtr client
)
1024 /* REQUEST(xXineramaIsActiveReq); */
1025 xXineramaIsActiveReply rep
;
1027 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
1029 rep
= (xXineramaIsActiveReply
) {
1031 .sequenceNumber
= client
->sequence
,
1034 /* The following hack fools clients into thinking that Xinerama
1035 * is disabled even though it is not. */
1036 .state
= !noPanoramiXExtension
&& !PanoramiXExtensionDisabledHack
1038 .state
= !noPanoramiXExtension
;
1041 if (client
->swapped
) {
1042 swaps(&rep
.sequenceNumber
);
1046 WriteToClient(client
, sizeof(xXineramaIsActiveReply
), &rep
);
1051 ProcXineramaQueryScreens(ClientPtr client
)
1053 /* REQUEST(xXineramaQueryScreensReq); */
1054 CARD32 number
= (noPanoramiXExtension
) ? 0 : PanoramiXNumScreens
;
1055 xXineramaQueryScreensReply rep
= {
1057 .sequenceNumber
= client
->sequence
,
1058 .length
= bytes_to_int32(number
* sz_XineramaScreenInfo
),
1062 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
1064 if (client
->swapped
) {
1065 swaps(&rep
.sequenceNumber
);
1069 WriteToClient(client
, sizeof(xXineramaQueryScreensReply
), &rep
);
1071 if (!noPanoramiXExtension
) {
1072 xXineramaScreenInfo scratch
;
1076 scratch
.x_org
= screenInfo
.screens
[i
]->x
;
1077 scratch
.y_org
= screenInfo
.screens
[i
]->y
;
1078 scratch
.width
= screenInfo
.screens
[i
]->width
;
1079 scratch
.height
= screenInfo
.screens
[i
]->height
;
1081 if (client
->swapped
) {
1082 swaps(&scratch
.x_org
);
1083 swaps(&scratch
.y_org
);
1084 swaps(&scratch
.width
);
1085 swaps(&scratch
.height
);
1087 WriteToClient(client
, sz_XineramaScreenInfo
, &scratch
);
1095 ProcPanoramiXDispatch(ClientPtr client
)
1098 switch (stuff
->data
) {
1099 case X_PanoramiXQueryVersion
:
1100 return ProcPanoramiXQueryVersion(client
);
1101 case X_PanoramiXGetState
:
1102 return ProcPanoramiXGetState(client
);
1103 case X_PanoramiXGetScreenCount
:
1104 return ProcPanoramiXGetScreenCount(client
);
1105 case X_PanoramiXGetScreenSize
:
1106 return ProcPanoramiXGetScreenSize(client
);
1107 case X_XineramaIsActive
:
1108 return ProcXineramaIsActive(client
);
1109 case X_XineramaQueryScreens
:
1110 return ProcXineramaQueryScreens(client
);
1115 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
1116 #define SHIFT_L(v,s) (v) << (s)
1117 #define SHIFT_R(v,s) (v) >> (s)
1119 #define SHIFT_L(v,s) (v) >> (s)
1120 #define SHIFT_R(v,s) (v) << (s)
1124 CopyBits(char *dst
, int shiftL
, char *src
, int bytes
)
1126 /* Just get it to work. Worry about speed later */
1127 int shiftR
= 8 - shiftL
;
1130 *dst
|= SHIFT_L(*src
, shiftL
);
1131 *(dst
+ 1) |= SHIFT_R(*src
, shiftR
);
1137 /* Caution. This doesn't support 2 and 4 bpp formats. We expect
1138 1 bpp and planar data to be already cleared when presented
1142 XineramaGetImageData(DrawablePtr
*pDrawables
,
1147 unsigned int format
,
1148 unsigned long planemask
,
1149 char *data
, int pitch
, Bool isRoot
)
1151 RegionRec SrcRegion
, ScreenRegion
, GrabRegion
;
1152 BoxRec SrcBox
, *pbox
;
1153 int x
, y
, w
, h
, i
, j
, nbox
, size
, sizeNeeded
, ScratchPitch
, inOut
, depth
;
1154 DrawablePtr pDraw
= pDrawables
[0];
1155 char *ScratchMem
= NULL
;
1159 /* find box in logical screen space */
1163 SrcBox
.x1
+= pDraw
->x
+ screenInfo
.screens
[0]->x
;
1164 SrcBox
.y1
+= pDraw
->y
+ screenInfo
.screens
[0]->y
;
1166 SrcBox
.x2
= SrcBox
.x1
+ width
;
1167 SrcBox
.y2
= SrcBox
.y1
+ height
;
1169 RegionInit(&SrcRegion
, &SrcBox
, 1);
1170 RegionNull(&GrabRegion
);
1172 depth
= (format
== XYPixmap
) ? 1 : pDraw
->depth
;
1178 pDraw
= pDrawables
[i
];
1179 pScreen
= pDraw
->pScreen
;
1181 TheBox
.x1
= pScreen
->x
;
1182 TheBox
.x2
= TheBox
.x1
+ pScreen
->width
;
1183 TheBox
.y1
= pScreen
->y
;
1184 TheBox
.y2
= TheBox
.y1
+ pScreen
->height
;
1186 RegionInit(&ScreenRegion
, &TheBox
, 1);
1187 inOut
= RegionContainsRect(&ScreenRegion
, &SrcBox
);
1188 if (inOut
== rgnPART
)
1189 RegionIntersect(&GrabRegion
, &SrcRegion
, &ScreenRegion
);
1190 RegionUninit(&ScreenRegion
);
1192 if (inOut
== rgnIN
) {
1193 (*pScreen
->GetImage
) (pDraw
,
1194 SrcBox
.x1
- pDraw
->x
-
1195 screenInfo
.screens
[i
]->x
,
1196 SrcBox
.y1
- pDraw
->y
-
1197 screenInfo
.screens
[i
]->y
, width
, height
,
1198 format
, planemask
, data
);
1201 else if (inOut
== rgnOUT
)
1204 nbox
= RegionNumRects(&GrabRegion
);
1207 pbox
= RegionRects(&GrabRegion
);
1210 w
= pbox
->x2
- pbox
->x1
;
1211 h
= pbox
->y2
- pbox
->y1
;
1212 ScratchPitch
= PixmapBytePad(w
, depth
);
1213 sizeNeeded
= ScratchPitch
* h
;
1215 if (sizeNeeded
> size
) {
1216 char *tmpdata
= ScratchMem
;
1218 ScratchMem
= realloc(ScratchMem
, sizeNeeded
);
1222 ScratchMem
= tmpdata
;
1227 x
= pbox
->x1
- pDraw
->x
- screenInfo
.screens
[i
]->x
;
1228 y
= pbox
->y1
- pDraw
->y
- screenInfo
.screens
[i
]->y
;
1230 (*pScreen
->GetImage
) (pDraw
, x
, y
, w
, h
,
1231 format
, planemask
, ScratchMem
);
1233 /* copy the memory over */
1236 int k
, shift
, leftover
, index
, index2
;
1238 x
= pbox
->x1
- SrcBox
.x1
;
1239 y
= pbox
->y1
- SrcBox
.y1
;
1245 /* clean up the edge */
1247 int mask
= (1 << leftover
) - 1;
1249 for (j
= h
, k
= w
; j
--; k
+= ScratchPitch
)
1250 ScratchMem
[k
] &= mask
;
1253 for (j
= 0, index
= (pitch
* y
) + x
, index2
= 0; j
< h
;
1254 j
++, index
+= pitch
, index2
+= ScratchPitch
) {
1257 memcpy(data
+ index
, ScratchMem
+ index2
, w
);
1259 CopyBits(data
+ index
, shift
,
1260 ScratchMem
+ index2
, w
);
1265 SHIFT_L(ScratchMem
[index2
+ w
], shift
);
1266 if ((shift
+ leftover
) > 8)
1267 data
[index
+ w
+ 1] |=
1268 SHIFT_R(ScratchMem
[index2
+ w
],
1274 j
= BitsPerPixel(depth
) >> 3;
1275 x
= (pbox
->x1
- SrcBox
.x1
) * j
;
1276 y
= pbox
->y1
- SrcBox
.y1
;
1279 for (j
= 0; j
< h
; j
++) {
1280 memcpy(data
+ (pitch
* (y
+ j
)) + x
,
1281 ScratchMem
+ (ScratchPitch
* j
), w
);
1287 RegionSubtract(&SrcRegion
, &SrcRegion
, &GrabRegion
);
1288 if (!RegionNotEmpty(&SrcRegion
))
1296 RegionUninit(&SrcRegion
);
1297 RegionUninit(&GrabRegion
);