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 .sequenceNumber
= client
->sequence
,
96 .majorVersion
= SERVER_RRXINERAMA_MAJOR_VERSION
,
97 .minorVersion
= SERVER_RRXINERAMA_MINOR_VERSION
100 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
101 if (client
->swapped
) {
102 swaps(&rep
.sequenceNumber
);
104 swaps(&rep
.majorVersion
);
105 swaps(&rep
.minorVersion
);
107 WriteToClient(client
, sizeof(xPanoramiXQueryVersionReply
), &rep
);
112 ProcRRXineramaGetState(ClientPtr client
)
114 REQUEST(xPanoramiXGetStateReq
);
116 xPanoramiXGetStateReply rep
;
119 rrScrPrivPtr pScrPriv
;
122 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
123 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
127 pScreen
= pWin
->drawable
.pScreen
;
128 pScrPriv
= rrGetScrPriv(pScreen
);
130 /* XXX do we need more than this? */
134 rep
= (xPanoramiXGetStateReply
) {
137 .sequenceNumber
= client
->sequence
,
139 .window
= stuff
->window
141 if (client
->swapped
) {
142 swaps(&rep
.sequenceNumber
);
146 WriteToClient(client
, sizeof(xPanoramiXGetStateReply
), &rep
);
151 RRXineramaCrtcActive(RRCrtcPtr crtc
)
153 return crtc
->mode
!= NULL
&& crtc
->numOutputs
> 0;
157 RRXineramaScreenCount(ScreenPtr pScreen
)
163 if (rrGetScrPriv(pScreen
)) {
165 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++)
166 if (RRXineramaCrtcActive(pScrPriv
->crtcs
[i
]))
170 xorg_list_for_each_entry(slave
, &pScreen
->output_slave_list
, output_head
) {
171 rrScrPrivPtr pSlavePriv
;
172 pSlavePriv
= rrGetScrPriv(slave
);
173 for (i
= 0; i
< pSlavePriv
->numCrtcs
; i
++)
174 if (RRXineramaCrtcActive(pSlavePriv
->crtcs
[i
]))
182 RRXineramaScreenActive(ScreenPtr pScreen
)
184 return RRXineramaScreenCount(pScreen
) > 0;
188 ProcRRXineramaGetScreenCount(ClientPtr client
)
190 REQUEST(xPanoramiXGetScreenCountReq
);
192 xPanoramiXGetScreenCountReply rep
;
195 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
196 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
200 rep
= (xPanoramiXGetScreenCountReply
) {
202 .ScreenCount
= RRXineramaScreenCount(pWin
->drawable
.pScreen
),
203 .sequenceNumber
= client
->sequence
,
205 .window
= stuff
->window
207 if (client
->swapped
) {
208 swaps(&rep
.sequenceNumber
);
212 WriteToClient(client
, sizeof(xPanoramiXGetScreenCountReply
), &rep
);
217 ProcRRXineramaGetScreenSize(ClientPtr client
)
219 REQUEST(xPanoramiXGetScreenSizeReq
);
220 WindowPtr pWin
, pRoot
;
222 xPanoramiXGetScreenSizeReply rep
;
225 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
226 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
230 pScreen
= pWin
->drawable
.pScreen
;
231 pRoot
= pScreen
->root
;
233 rep
= (xPanoramiXGetScreenSizeReply
) {
235 .sequenceNumber
= client
->sequence
,
237 .width
= pRoot
->drawable
.width
,
238 .height
= pRoot
->drawable
.height
,
239 .window
= stuff
->window
,
240 .screen
= stuff
->screen
242 if (client
->swapped
) {
243 swaps(&rep
.sequenceNumber
);
250 WriteToClient(client
, sizeof(xPanoramiXGetScreenSizeReply
), &rep
);
255 ProcRRXineramaIsActive(ClientPtr client
)
257 xXineramaIsActiveReply rep
;
259 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
261 rep
= (xXineramaIsActiveReply
) {
264 .sequenceNumber
= client
->sequence
,
265 .state
= RRXineramaScreenActive(screenInfo
.screens
[RR_XINERAMA_SCREEN
])
267 if (client
->swapped
) {
268 swaps(&rep
.sequenceNumber
);
272 WriteToClient(client
, sizeof(xXineramaIsActiveReply
), &rep
);
277 RRXineramaWriteCrtc(ClientPtr client
, RRCrtcPtr crtc
)
279 xXineramaScreenInfo scratch
;
281 if (RRXineramaCrtcActive(crtc
)) {
282 ScreenPtr pScreen
= crtc
->pScreen
;
283 rrScrPrivPtr pScrPriv
= rrGetScrPriv(pScreen
);
286 /* Check to see if crtc is panned and return the full area when applicable. */
287 if (pScrPriv
&& pScrPriv
->rrGetPanning
&&
288 pScrPriv
->rrGetPanning(pScreen
, crtc
, &panned_area
, NULL
, NULL
) &&
289 (panned_area
.x2
> panned_area
.x1
) &&
290 (panned_area
.y2
> panned_area
.y1
)) {
291 scratch
.x_org
= panned_area
.x1
;
292 scratch
.y_org
= panned_area
.y1
;
293 scratch
.width
= panned_area
.x2
- panned_area
.x1
;
294 scratch
.height
= panned_area
.y2
- panned_area
.y1
;
299 RRCrtcGetScanoutSize(crtc
, &width
, &height
);
300 scratch
.x_org
= crtc
->x
;
301 scratch
.y_org
= crtc
->y
;
302 scratch
.width
= width
;
303 scratch
.height
= height
;
305 if (client
->swapped
) {
306 swaps(&scratch
.x_org
);
307 swaps(&scratch
.y_org
);
308 swaps(&scratch
.width
);
309 swaps(&scratch
.height
);
311 WriteToClient(client
, sz_XineramaScreenInfo
, &scratch
);
316 ProcRRXineramaQueryScreens(ClientPtr client
)
318 xXineramaQueryScreensReply rep
;
319 ScreenPtr pScreen
= screenInfo
.screens
[RR_XINERAMA_SCREEN
];
323 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
325 if (RRXineramaScreenActive(pScreen
)) {
326 RRGetInfo(pScreen
, FALSE
);
327 n
= RRXineramaScreenCount(pScreen
);
330 rep
= (xXineramaQueryScreensReply
) {
332 .sequenceNumber
= client
->sequence
,
333 .length
= bytes_to_int32(n
* sz_XineramaScreenInfo
),
336 if (client
->swapped
) {
337 swaps(&rep
.sequenceNumber
);
341 WriteToClient(client
, sizeof(xXineramaQueryScreensReply
), &rep
);
348 if (pScrPriv
->primaryOutput
&& pScrPriv
->primaryOutput
->crtc
) {
350 RRXineramaWriteCrtc(client
, pScrPriv
->primaryOutput
->crtc
);
353 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++) {
355 pScrPriv
->primaryOutput
->crtc
== pScrPriv
->crtcs
[i
]) {
359 RRXineramaWriteCrtc(client
, pScrPriv
->crtcs
[i
]);
362 xorg_list_for_each_entry(slave
, &pScreen
->output_slave_list
, output_head
) {
363 rrScrPrivPtr pSlavePriv
;
364 pSlavePriv
= rrGetScrPriv(slave
);
365 for (i
= 0; i
< pSlavePriv
->numCrtcs
; i
++)
366 RRXineramaWriteCrtc(client
, pSlavePriv
->crtcs
[i
]);
374 ProcRRXineramaDispatch(ClientPtr client
)
377 switch (stuff
->data
) {
378 case X_PanoramiXQueryVersion
:
379 return ProcRRXineramaQueryVersion(client
);
380 case X_PanoramiXGetState
:
381 return ProcRRXineramaGetState(client
);
382 case X_PanoramiXGetScreenCount
:
383 return ProcRRXineramaGetScreenCount(client
);
384 case X_PanoramiXGetScreenSize
:
385 return ProcRRXineramaGetScreenSize(client
);
386 case X_XineramaIsActive
:
387 return ProcRRXineramaIsActive(client
);
388 case X_XineramaQueryScreens
:
389 return ProcRRXineramaQueryScreens(client
);
397 SProcRRXineramaQueryVersion(ClientPtr client
)
399 REQUEST(xPanoramiXQueryVersionReq
);
400 swaps(&stuff
->length
);
401 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
402 return ProcRRXineramaQueryVersion(client
);
406 SProcRRXineramaGetState(ClientPtr client
)
408 REQUEST(xPanoramiXGetStateReq
);
409 swaps(&stuff
->length
);
410 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
411 swapl(&stuff
->window
);
412 return ProcRRXineramaGetState(client
);
416 SProcRRXineramaGetScreenCount(ClientPtr client
)
418 REQUEST(xPanoramiXGetScreenCountReq
);
419 swaps(&stuff
->length
);
420 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
421 swapl(&stuff
->window
);
422 return ProcRRXineramaGetScreenCount(client
);
426 SProcRRXineramaGetScreenSize(ClientPtr client
)
428 REQUEST(xPanoramiXGetScreenSizeReq
);
429 swaps(&stuff
->length
);
430 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
431 swapl(&stuff
->window
);
432 swapl(&stuff
->screen
);
433 return ProcRRXineramaGetScreenSize(client
);
437 SProcRRXineramaIsActive(ClientPtr client
)
439 REQUEST(xXineramaIsActiveReq
);
440 swaps(&stuff
->length
);
441 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
442 return ProcRRXineramaIsActive(client
);
446 SProcRRXineramaQueryScreens(ClientPtr client
)
448 REQUEST(xXineramaQueryScreensReq
);
449 swaps(&stuff
->length
);
450 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
451 return ProcRRXineramaQueryScreens(client
);
455 SProcRRXineramaDispatch(ClientPtr client
)
458 switch (stuff
->data
) {
459 case X_PanoramiXQueryVersion
:
460 return SProcRRXineramaQueryVersion(client
);
461 case X_PanoramiXGetState
:
462 return SProcRRXineramaGetState(client
);
463 case X_PanoramiXGetScreenCount
:
464 return SProcRRXineramaGetScreenCount(client
);
465 case X_PanoramiXGetScreenSize
:
466 return SProcRRXineramaGetScreenSize(client
);
467 case X_XineramaIsActive
:
468 return SProcRRXineramaIsActive(client
);
469 case X_XineramaQueryScreens
:
470 return SProcRRXineramaQueryScreens(client
);
476 RRXineramaExtensionInit(void)
479 if (!noPanoramiXExtension
)
484 * Xinerama isn't capable enough to have multiple protocol screens each
485 * with their own output geometry. So if there's more than one protocol
486 * screen, just don't even try.
488 if (screenInfo
.numScreens
> 1)
491 (void) AddExtension(PANORAMIX_PROTOCOL_NAME
, 0, 0,
492 ProcRRXineramaDispatch
,
493 SProcRRXineramaDispatch
, NULL
, StandardMinorOpcode
);