Initial commit
[xorg_rtime.git] / xorg-server-1.4 / randr / rrxinerama.c
blob896f61fb56ad0c899c005210ee8cfd33ea6f9018
1 /*
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
20 * OF THIS SOFTWARE.
23 * This Xinerama implementation comes from the SiS driver which has
24 * the following notice:
26 /*
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
33 * are met:
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.
63 * Written by:
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>.
71 #include "randrstr.h"
72 #include "swaprep.h"
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);
89 /* Proc */
91 int
92 ProcRRXineramaQueryVersion(ClientPtr client)
94 xPanoramiXQueryVersionReply rep;
95 register int n;
97 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
98 rep.type = X_Reply;
99 rep.length = 0;
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);
117 WindowPtr pWin;
118 xPanoramiXGetStateReply rep;
119 register int n, rc;
120 ScreenPtr pScreen;
121 rrScrPrivPtr pScrPriv;
122 Bool active = FALSE;
124 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
125 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
126 if(rc != Success)
127 return rc;
129 pScreen = pWin->drawable.pScreen;
130 pScrPriv = rrGetScrPriv(pScreen);
131 if (pScrPriv)
133 /* XXX do we need more than this? */
134 active = TRUE;
137 rep.type = X_Reply;
138 rep.length = 0;
139 rep.sequenceNumber = client->sequence;
140 rep.state = active;
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;
150 static Bool
151 RRXineramaCrtcActive (RRCrtcPtr crtc)
153 return crtc->mode != NULL && crtc->numOutputs > 0;
156 static int
157 RRXineramaScreenCount (ScreenPtr pScreen)
159 int i, n;
161 n = 0;
162 if (rrGetScrPriv (pScreen))
164 rrScrPriv(pScreen);
165 for (i = 0; i < pScrPriv->numCrtcs; i++)
166 if (RRXineramaCrtcActive (pScrPriv->crtcs[i]))
167 n++;
169 return n;
172 static Bool
173 RRXineramaScreenActive (ScreenPtr pScreen)
175 return RRXineramaScreenCount (pScreen) > 0;
179 ProcRRXineramaGetScreenCount(ClientPtr client)
181 REQUEST(xPanoramiXGetScreenCountReq);
182 WindowPtr pWin;
183 xPanoramiXGetScreenCountReply rep;
184 register int n, rc;
186 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
187 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
188 if (rc != Success)
189 return rc;
191 rep.type = X_Reply;
192 rep.length = 0;
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;
209 ScreenPtr pScreen;
210 xPanoramiXGetScreenSizeReply rep;
211 register int n, rc;
213 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
214 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
215 if (rc != Success)
216 return rc;
218 pScreen = pWin->drawable.pScreen;
219 pRoot = WindowTable[pScreen->myNum];
221 rep.type = X_Reply;
222 rep.length = 0;
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);
243 rep.type = X_Reply;
244 rep.length = 0;
245 rep.sequenceNumber = client->sequence;
246 rep.state = RRXineramaScreenActive (screenInfo.screens[RR_XINERAMA_SCREEN]);
247 if(client->swapped) {
248 register int n;
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))
267 rrScrPriv(pScreen);
268 if (pScrPriv->numCrtcs == 0 || pScrPriv->numOutputs == 0)
269 RRGetInfo (pScreen);
272 rep.type = X_Reply;
273 rep.sequenceNumber = client->sequence;
274 rep.number = RRXineramaScreenCount (pScreen);
275 rep.length = rep.number * sz_XineramaScreenInfo >> 2;
276 if(client->swapped) {
277 register int n;
278 swaps(&rep.sequenceNumber, n);
279 swapl(&rep.length, n);
280 swapl(&rep.number, n);
282 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep);
284 if(rep.number) {
285 rrScrPriv(pScreen);
286 xXineramaScreenInfo scratch;
287 int i;
289 for(i = 0; i < pScrPriv->numCrtcs; i++) {
290 RRCrtcPtr crtc = pScrPriv->crtcs[i];
291 if (RRXineramaCrtcActive (crtc))
293 int width, height;
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) {
300 register int n;
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;
314 static int
315 ProcRRXineramaDispatch(ClientPtr client)
317 REQUEST(xReq);
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);
332 return BadRequest;
335 /* SProc */
337 static int
338 SProcRRXineramaQueryVersion (ClientPtr client)
340 REQUEST(xPanoramiXQueryVersionReq);
341 register int n;
342 swaps(&stuff->length,n);
343 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
344 return ProcRRXineramaQueryVersion(client);
347 static int
348 SProcRRXineramaGetState(ClientPtr client)
350 REQUEST(xPanoramiXGetStateReq);
351 register int n;
352 swaps (&stuff->length, n);
353 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
354 return ProcRRXineramaGetState(client);
357 static int
358 SProcRRXineramaGetScreenCount(ClientPtr client)
360 REQUEST(xPanoramiXGetScreenCountReq);
361 register int n;
362 swaps (&stuff->length, n);
363 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
364 return ProcRRXineramaGetScreenCount(client);
367 static int
368 SProcRRXineramaGetScreenSize(ClientPtr client)
370 REQUEST(xPanoramiXGetScreenSizeReq);
371 register int n;
372 swaps (&stuff->length, n);
373 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
374 return ProcRRXineramaGetScreenSize(client);
377 static int
378 SProcRRXineramaIsActive(ClientPtr client)
380 REQUEST(xXineramaIsActiveReq);
381 register int n;
382 swaps (&stuff->length, n);
383 REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
384 return ProcRRXineramaIsActive(client);
387 static int
388 SProcRRXineramaQueryScreens(ClientPtr client)
390 REQUEST(xXineramaQueryScreensReq);
391 register int n;
392 swaps (&stuff->length, n);
393 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
394 return ProcRRXineramaQueryScreens(client);
398 SProcRRXineramaDispatch(ClientPtr client)
400 REQUEST(xReq);
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);
415 return BadRequest;
418 static void
419 RRXineramaResetProc(ExtensionEntry* extEntry)
423 void
424 RRXineramaExtensionInit(void)
426 #ifdef PANORAMIX
427 if(!noPanoramiXExtension)
428 return;
429 #endif
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)
437 return;
439 (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
440 ProcRRXineramaDispatch,
441 SProcRRXineramaDispatch,
442 RRXineramaResetProc,
443 StandardMinorOpcode);