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>
74 #include "protocol-versions.h"
76 /* Xinerama is not multi-screen capable; just report about screen 0 */
77 #define RR_XINERAMA_SCREEN 0
79 static int ProcRRXineramaQueryVersion(ClientPtr client
);
80 static int ProcRRXineramaGetState(ClientPtr client
);
81 static int ProcRRXineramaGetScreenCount(ClientPtr client
);
82 static int ProcRRXineramaGetScreenSize(ClientPtr client
);
83 static int ProcRRXineramaIsActive(ClientPtr client
);
84 static int ProcRRXineramaQueryScreens(ClientPtr client
);
85 static int SProcRRXineramaDispatch(ClientPtr client
);
90 ProcRRXineramaQueryVersion(ClientPtr client
)
92 xPanoramiXQueryVersionReply rep
;
94 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
97 rep
.sequenceNumber
= client
->sequence
;
98 rep
.majorVersion
= SERVER_RRXINERAMA_MAJOR_VERSION
;
99 rep
.minorVersion
= SERVER_RRXINERAMA_MINOR_VERSION
;
100 if (client
->swapped
) {
101 swaps(&rep
.sequenceNumber
);
103 swaps(&rep
.majorVersion
);
104 swaps(&rep
.minorVersion
);
106 WriteToClient(client
, sizeof(xPanoramiXQueryVersionReply
), (char *) &rep
);
111 ProcRRXineramaGetState(ClientPtr client
)
113 REQUEST(xPanoramiXGetStateReq
);
115 xPanoramiXGetStateReply rep
;
118 rrScrPrivPtr pScrPriv
;
121 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
122 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
126 pScreen
= pWin
->drawable
.pScreen
;
127 pScrPriv
= rrGetScrPriv(pScreen
);
129 /* XXX do we need more than this? */
135 rep
.sequenceNumber
= client
->sequence
;
137 rep
.window
= stuff
->window
;
138 if (client
->swapped
) {
139 swaps(&rep
.sequenceNumber
);
143 WriteToClient(client
, sizeof(xPanoramiXGetStateReply
), (char *) &rep
);
148 RRXineramaCrtcActive(RRCrtcPtr crtc
)
150 return crtc
->mode
!= NULL
&& crtc
->numOutputs
> 0;
154 RRXineramaScreenCount(ScreenPtr pScreen
)
159 if (rrGetScrPriv(pScreen
)) {
161 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++)
162 if (RRXineramaCrtcActive(pScrPriv
->crtcs
[i
]))
169 RRXineramaScreenActive(ScreenPtr pScreen
)
171 return RRXineramaScreenCount(pScreen
) > 0;
175 ProcRRXineramaGetScreenCount(ClientPtr client
)
177 REQUEST(xPanoramiXGetScreenCountReq
);
179 xPanoramiXGetScreenCountReply rep
;
182 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
183 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
189 rep
.sequenceNumber
= client
->sequence
;
190 rep
.ScreenCount
= RRXineramaScreenCount(pWin
->drawable
.pScreen
);
191 rep
.window
= stuff
->window
;
192 if (client
->swapped
) {
193 swaps(&rep
.sequenceNumber
);
197 WriteToClient(client
, sizeof(xPanoramiXGetScreenCountReply
), (char *) &rep
);
202 ProcRRXineramaGetScreenSize(ClientPtr client
)
204 REQUEST(xPanoramiXGetScreenSizeReq
);
205 WindowPtr pWin
, pRoot
;
207 xPanoramiXGetScreenSizeReply rep
;
210 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
211 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
215 pScreen
= pWin
->drawable
.pScreen
;
216 pRoot
= pScreen
->root
;
220 rep
.sequenceNumber
= client
->sequence
;
221 rep
.width
= pRoot
->drawable
.width
;
222 rep
.height
= pRoot
->drawable
.height
;
223 rep
.window
= stuff
->window
;
224 rep
.screen
= stuff
->screen
;
225 if (client
->swapped
) {
226 swaps(&rep
.sequenceNumber
);
233 WriteToClient(client
, sizeof(xPanoramiXGetScreenSizeReply
), (char *) &rep
);
238 ProcRRXineramaIsActive(ClientPtr client
)
240 xXineramaIsActiveReply rep
;
242 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
244 memset(&rep
, 0, sizeof(xXineramaIsActiveReply
));
247 rep
.sequenceNumber
= client
->sequence
;
248 rep
.state
= RRXineramaScreenActive(screenInfo
.screens
[RR_XINERAMA_SCREEN
]);
249 if (client
->swapped
) {
250 swaps(&rep
.sequenceNumber
);
254 WriteToClient(client
, sizeof(xXineramaIsActiveReply
), (char *) &rep
);
259 RRXineramaWriteCrtc(ClientPtr client
, RRCrtcPtr crtc
)
261 xXineramaScreenInfo scratch
;
263 if (RRXineramaCrtcActive(crtc
)) {
264 ScreenPtr pScreen
= crtc
->pScreen
;
265 rrScrPrivPtr pScrPriv
= rrGetScrPriv(pScreen
);
268 /* Check to see if crtc is panned and return the full area when applicable. */
269 if (pScrPriv
&& pScrPriv
->rrGetPanning
&&
270 pScrPriv
->rrGetPanning(pScreen
, crtc
, &panned_area
, NULL
, NULL
) &&
271 (panned_area
.x2
> panned_area
.x1
) &&
272 (panned_area
.y2
> panned_area
.y1
)) {
273 scratch
.x_org
= panned_area
.x1
;
274 scratch
.y_org
= panned_area
.y1
;
275 scratch
.width
= panned_area
.x2
- panned_area
.x1
;
276 scratch
.height
= panned_area
.y2
- panned_area
.y1
;
281 RRCrtcGetScanoutSize(crtc
, &width
, &height
);
282 scratch
.x_org
= crtc
->x
;
283 scratch
.y_org
= crtc
->y
;
284 scratch
.width
= width
;
285 scratch
.height
= height
;
287 if (client
->swapped
) {
288 swaps(&scratch
.x_org
);
289 swaps(&scratch
.y_org
);
290 swaps(&scratch
.width
);
291 swaps(&scratch
.height
);
293 WriteToClient(client
, sz_XineramaScreenInfo
, &scratch
);
298 ProcRRXineramaQueryScreens(ClientPtr client
)
300 xXineramaQueryScreensReply rep
;
301 ScreenPtr pScreen
= screenInfo
.screens
[RR_XINERAMA_SCREEN
];
303 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
305 if (RRXineramaScreenActive(pScreen
))
306 RRGetInfo(pScreen
, FALSE
);
309 rep
.sequenceNumber
= client
->sequence
;
310 rep
.number
= RRXineramaScreenCount(pScreen
);
311 rep
.length
= bytes_to_int32(rep
.number
* sz_XineramaScreenInfo
);
312 if (client
->swapped
) {
313 swaps(&rep
.sequenceNumber
);
317 WriteToClient(client
, sizeof(xXineramaQueryScreensReply
), (char *) &rep
);
324 if (pScrPriv
->primaryOutput
&& pScrPriv
->primaryOutput
->crtc
) {
326 RRXineramaWriteCrtc(client
, pScrPriv
->primaryOutput
->crtc
);
329 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++) {
331 pScrPriv
->primaryOutput
->crtc
== pScrPriv
->crtcs
[i
]) {
335 RRXineramaWriteCrtc(client
, pScrPriv
->crtcs
[i
]);
343 ProcRRXineramaDispatch(ClientPtr client
)
346 switch (stuff
->data
) {
347 case X_PanoramiXQueryVersion
:
348 return ProcRRXineramaQueryVersion(client
);
349 case X_PanoramiXGetState
:
350 return ProcRRXineramaGetState(client
);
351 case X_PanoramiXGetScreenCount
:
352 return ProcRRXineramaGetScreenCount(client
);
353 case X_PanoramiXGetScreenSize
:
354 return ProcRRXineramaGetScreenSize(client
);
355 case X_XineramaIsActive
:
356 return ProcRRXineramaIsActive(client
);
357 case X_XineramaQueryScreens
:
358 return ProcRRXineramaQueryScreens(client
);
366 SProcRRXineramaQueryVersion(ClientPtr client
)
368 REQUEST(xPanoramiXQueryVersionReq
);
369 swaps(&stuff
->length
);
370 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
371 return ProcRRXineramaQueryVersion(client
);
375 SProcRRXineramaGetState(ClientPtr client
)
377 REQUEST(xPanoramiXGetStateReq
);
378 swaps(&stuff
->length
);
379 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
380 swapl(&stuff
->window
);
381 return ProcRRXineramaGetState(client
);
385 SProcRRXineramaGetScreenCount(ClientPtr client
)
387 REQUEST(xPanoramiXGetScreenCountReq
);
388 swaps(&stuff
->length
);
389 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
390 swapl(&stuff
->window
);
391 return ProcRRXineramaGetScreenCount(client
);
395 SProcRRXineramaGetScreenSize(ClientPtr client
)
397 REQUEST(xPanoramiXGetScreenSizeReq
);
398 swaps(&stuff
->length
);
399 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
400 swapl(&stuff
->window
);
401 swapl(&stuff
->screen
);
402 return ProcRRXineramaGetScreenSize(client
);
406 SProcRRXineramaIsActive(ClientPtr client
)
408 REQUEST(xXineramaIsActiveReq
);
409 swaps(&stuff
->length
);
410 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
411 return ProcRRXineramaIsActive(client
);
415 SProcRRXineramaQueryScreens(ClientPtr client
)
417 REQUEST(xXineramaQueryScreensReq
);
418 swaps(&stuff
->length
);
419 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
420 return ProcRRXineramaQueryScreens(client
);
424 SProcRRXineramaDispatch(ClientPtr client
)
427 switch (stuff
->data
) {
428 case X_PanoramiXQueryVersion
:
429 return SProcRRXineramaQueryVersion(client
);
430 case X_PanoramiXGetState
:
431 return SProcRRXineramaGetState(client
);
432 case X_PanoramiXGetScreenCount
:
433 return SProcRRXineramaGetScreenCount(client
);
434 case X_PanoramiXGetScreenSize
:
435 return SProcRRXineramaGetScreenSize(client
);
436 case X_XineramaIsActive
:
437 return SProcRRXineramaIsActive(client
);
438 case X_XineramaQueryScreens
:
439 return SProcRRXineramaQueryScreens(client
);
445 RRXineramaExtensionInit(void)
448 if (!noPanoramiXExtension
)
453 * Xinerama isn't capable enough to have multiple protocol screens each
454 * with their own output geometry. So if there's more than one protocol
455 * screen, just don't even try.
457 if (screenInfo
.numScreens
> 1)
460 (void) AddExtension(PANORAMIX_PROTOCOL_NAME
, 0, 0,
461 ProcRRXineramaDispatch
,
462 SProcRRXineramaDispatch
, NULL
, StandardMinorOpcode
);