2 * Copyright © 2006 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 * This Xinerama implementation comes from the SiS driver which has
24 * the following notice:
27 * SiS driver main code
29 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1) Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2) Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3) The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 * Author: Thomas Winischhofer <thomas@winischhofer.net>
54 * - driver entirely rewritten since 2001, only basic structure taken from
55 * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of
56 * sis_dga.c; these were mostly taken over; sis_dri.c was changed for
57 * new versions of the DRI layer)
59 * This notice covers the entire driver code unless indicated otherwise.
61 * Formerly based on code which was
62 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
64 * Alan Hourihane <alanh@fairlite.demon.co.uk>,
65 * Mike Chapman <mike@paranoia.com>,
66 * Juanjo Santamarta <santamarta@ctv.es>,
67 * Mitani Hiroshi <hmitani@drl.mei.co.jp>,
68 * David Thomas <davtom@dream.org.uk>.
73 #include <X11/extensions/panoramiXproto.h>
75 #define RR_XINERAMA_MAJOR_VERSION 1
76 #define RR_XINERAMA_MINOR_VERSION 1
78 /* Xinerama is not multi-screen capable; just report about screen 0 */
79 #define RR_XINERAMA_SCREEN 0
81 static int ProcRRXineramaQueryVersion(ClientPtr client
);
82 static int ProcRRXineramaGetState(ClientPtr client
);
83 static int ProcRRXineramaGetScreenCount(ClientPtr client
);
84 static int ProcRRXineramaGetScreenSize(ClientPtr client
);
85 static int ProcRRXineramaIsActive(ClientPtr client
);
86 static int ProcRRXineramaQueryScreens(ClientPtr client
);
87 static int SProcRRXineramaDispatch(ClientPtr client
);
92 ProcRRXineramaQueryVersion(ClientPtr client
)
94 xPanoramiXQueryVersionReply rep
;
97 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
100 rep
.sequenceNumber
= client
->sequence
;
101 rep
.majorVersion
= RR_XINERAMA_MAJOR_VERSION
;
102 rep
.minorVersion
= RR_XINERAMA_MINOR_VERSION
;
103 if(client
->swapped
) {
104 swaps(&rep
.sequenceNumber
, n
);
105 swapl(&rep
.length
, n
);
106 swaps(&rep
.majorVersion
, n
);
107 swaps(&rep
.minorVersion
, n
);
109 WriteToClient(client
, sizeof(xPanoramiXQueryVersionReply
), (char *)&rep
);
110 return (client
->noClientException
);
114 ProcRRXineramaGetState(ClientPtr client
)
116 REQUEST(xPanoramiXGetStateReq
);
118 xPanoramiXGetStateReply rep
;
121 rrScrPrivPtr pScrPriv
;
124 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
125 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
129 pScreen
= pWin
->drawable
.pScreen
;
130 pScrPriv
= rrGetScrPriv(pScreen
);
133 /* XXX do we need more than this? */
139 rep
.sequenceNumber
= client
->sequence
;
141 if(client
->swapped
) {
142 swaps (&rep
.sequenceNumber
, n
);
143 swapl (&rep
.length
, n
);
144 swaps (&rep
.state
, n
);
146 WriteToClient(client
, sizeof(xPanoramiXGetStateReply
), (char *)&rep
);
147 return client
->noClientException
;
151 RRXineramaCrtcActive (RRCrtcPtr crtc
)
153 return crtc
->mode
!= NULL
&& crtc
->numOutputs
> 0;
157 RRXineramaScreenCount (ScreenPtr pScreen
)
162 if (rrGetScrPriv (pScreen
))
165 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++)
166 if (RRXineramaCrtcActive (pScrPriv
->crtcs
[i
]))
173 RRXineramaScreenActive (ScreenPtr pScreen
)
175 return RRXineramaScreenCount (pScreen
) > 0;
179 ProcRRXineramaGetScreenCount(ClientPtr client
)
181 REQUEST(xPanoramiXGetScreenCountReq
);
183 xPanoramiXGetScreenCountReply rep
;
186 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
187 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
193 rep
.sequenceNumber
= client
->sequence
;
194 rep
.ScreenCount
= RRXineramaScreenCount (pWin
->drawable
.pScreen
);
195 if(client
->swapped
) {
196 swaps(&rep
.sequenceNumber
, n
);
197 swapl(&rep
.length
, n
);
198 swaps(&rep
.ScreenCount
, n
);
200 WriteToClient(client
, sizeof(xPanoramiXGetScreenCountReply
), (char *)&rep
);
201 return client
->noClientException
;
205 ProcRRXineramaGetScreenSize(ClientPtr client
)
207 REQUEST(xPanoramiXGetScreenSizeReq
);
208 WindowPtr pWin
, pRoot
;
210 xPanoramiXGetScreenSizeReply rep
;
213 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
214 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
218 pScreen
= pWin
->drawable
.pScreen
;
219 pRoot
= WindowTable
[pScreen
->myNum
];
223 rep
.sequenceNumber
= client
->sequence
;
224 rep
.width
= pRoot
->drawable
.width
;
225 rep
.height
= pRoot
->drawable
.height
;
226 if(client
->swapped
) {
227 swaps(&rep
.sequenceNumber
, n
);
228 swapl(&rep
.length
, n
);
229 swaps(&rep
.width
, n
);
230 swaps(&rep
.height
, n
);
232 WriteToClient(client
, sizeof(xPanoramiXGetScreenSizeReply
), (char *)&rep
);
233 return client
->noClientException
;
237 ProcRRXineramaIsActive(ClientPtr client
)
239 xXineramaIsActiveReply rep
;
241 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
245 rep
.sequenceNumber
= client
->sequence
;
246 rep
.state
= RRXineramaScreenActive (screenInfo
.screens
[RR_XINERAMA_SCREEN
]);
247 if(client
->swapped
) {
249 swaps(&rep
.sequenceNumber
, n
);
250 swapl(&rep
.length
, n
);
251 swapl(&rep
.state
, n
);
253 WriteToClient(client
, sizeof(xXineramaIsActiveReply
), (char *) &rep
);
254 return client
->noClientException
;
258 ProcRRXineramaQueryScreens(ClientPtr client
)
260 xXineramaQueryScreensReply rep
;
261 ScreenPtr pScreen
= screenInfo
.screens
[RR_XINERAMA_SCREEN
];
263 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
265 if (RRXineramaScreenActive (pScreen
))
268 if (pScrPriv
->numCrtcs
== 0 || pScrPriv
->numOutputs
== 0)
273 rep
.sequenceNumber
= client
->sequence
;
274 rep
.number
= RRXineramaScreenCount (pScreen
);
275 rep
.length
= rep
.number
* sz_XineramaScreenInfo
>> 2;
276 if(client
->swapped
) {
278 swaps(&rep
.sequenceNumber
, n
);
279 swapl(&rep
.length
, n
);
280 swapl(&rep
.number
, n
);
282 WriteToClient(client
, sizeof(xXineramaQueryScreensReply
), (char *)&rep
);
286 xXineramaScreenInfo scratch
;
289 for(i
= 0; i
< pScrPriv
->numCrtcs
; i
++) {
290 RRCrtcPtr crtc
= pScrPriv
->crtcs
[i
];
291 if (RRXineramaCrtcActive (crtc
))
294 RRCrtcGetScanoutSize (crtc
, &width
, &height
);
295 scratch
.x_org
= crtc
->x
;
296 scratch
.y_org
= crtc
->y
;
297 scratch
.width
= width
;
298 scratch
.height
= height
;
299 if(client
->swapped
) {
301 swaps(&scratch
.x_org
, n
);
302 swaps(&scratch
.y_org
, n
);
303 swaps(&scratch
.width
, n
);
304 swaps(&scratch
.height
, n
);
306 WriteToClient(client
, sz_XineramaScreenInfo
, (char *)&scratch
);
311 return client
->noClientException
;
315 ProcRRXineramaDispatch(ClientPtr client
)
318 switch (stuff
->data
) {
319 case X_PanoramiXQueryVersion
:
320 return ProcRRXineramaQueryVersion(client
);
321 case X_PanoramiXGetState
:
322 return ProcRRXineramaGetState(client
);
323 case X_PanoramiXGetScreenCount
:
324 return ProcRRXineramaGetScreenCount(client
);
325 case X_PanoramiXGetScreenSize
:
326 return ProcRRXineramaGetScreenSize(client
);
327 case X_XineramaIsActive
:
328 return ProcRRXineramaIsActive(client
);
329 case X_XineramaQueryScreens
:
330 return ProcRRXineramaQueryScreens(client
);
338 SProcRRXineramaQueryVersion (ClientPtr client
)
340 REQUEST(xPanoramiXQueryVersionReq
);
342 swaps(&stuff
->length
,n
);
343 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq
);
344 return ProcRRXineramaQueryVersion(client
);
348 SProcRRXineramaGetState(ClientPtr client
)
350 REQUEST(xPanoramiXGetStateReq
);
352 swaps (&stuff
->length
, n
);
353 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
354 return ProcRRXineramaGetState(client
);
358 SProcRRXineramaGetScreenCount(ClientPtr client
)
360 REQUEST(xPanoramiXGetScreenCountReq
);
362 swaps (&stuff
->length
, n
);
363 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
364 return ProcRRXineramaGetScreenCount(client
);
368 SProcRRXineramaGetScreenSize(ClientPtr client
)
370 REQUEST(xPanoramiXGetScreenSizeReq
);
372 swaps (&stuff
->length
, n
);
373 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
374 return ProcRRXineramaGetScreenSize(client
);
378 SProcRRXineramaIsActive(ClientPtr client
)
380 REQUEST(xXineramaIsActiveReq
);
382 swaps (&stuff
->length
, n
);
383 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
384 return ProcRRXineramaIsActive(client
);
388 SProcRRXineramaQueryScreens(ClientPtr client
)
390 REQUEST(xXineramaQueryScreensReq
);
392 swaps (&stuff
->length
, n
);
393 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
394 return ProcRRXineramaQueryScreens(client
);
398 SProcRRXineramaDispatch(ClientPtr client
)
401 switch (stuff
->data
) {
402 case X_PanoramiXQueryVersion
:
403 return SProcRRXineramaQueryVersion(client
);
404 case X_PanoramiXGetState
:
405 return SProcRRXineramaGetState(client
);
406 case X_PanoramiXGetScreenCount
:
407 return SProcRRXineramaGetScreenCount(client
);
408 case X_PanoramiXGetScreenSize
:
409 return SProcRRXineramaGetScreenSize(client
);
410 case X_XineramaIsActive
:
411 return SProcRRXineramaIsActive(client
);
412 case X_XineramaQueryScreens
:
413 return SProcRRXineramaQueryScreens(client
);
419 RRXineramaResetProc(ExtensionEntry
* extEntry
)
424 RRXineramaExtensionInit(void)
427 if(!noPanoramiXExtension
)
432 * Xinerama isn't capable enough to have multiple protocol screens each
433 * with their own output geometry. So if there's more than one protocol
434 * screen, just don't even try.
436 if (screenInfo
.numScreens
> 1)
439 (void) AddExtension(PANORAMIX_PROTOCOL_NAME
, 0,0,
440 ProcRRXineramaDispatch
,
441 SProcRRXineramaDispatch
,
443 StandardMinorOpcode
);