Add patch that contain Mali fixes.
[deb_xorg-server.git] / randr / rrxinerama.c
1 /*
2 * Copyright © 2006 Keith Packard
3 *
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.
13 *
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.
21 */
22 /*
23 * This Xinerama implementation comes from the SiS driver which has
24 * the following notice:
25 */
26 /*
27 * SiS driver main code
28 *
29 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
30 *
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.
41 *
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.
52 *
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)
58 *
59 * This notice covers the entire driver code unless indicated otherwise.
60 *
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>.
69 */
70
71 #include "randrstr.h"
72 #include "swaprep.h"
73 #include <X11/extensions/panoramiXproto.h>
74 #include "protocol-versions.h"
75
76 /* Xinerama is not multi-screen capable; just report about screen 0 */
77 #define RR_XINERAMA_SCREEN 0
78
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);
86
87 /* Proc */
88
89 int
90 ProcRRXineramaQueryVersion(ClientPtr client)
91 {
92 xPanoramiXQueryVersionReply rep = {
93 .type = X_Reply,
94 .sequenceNumber = client->sequence,
95 .length = 0,
96 .majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION,
97 .minorVersion = SERVER_RRXINERAMA_MINOR_VERSION
98 };
99
100 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
101 if (client->swapped) {
102 swaps(&rep.sequenceNumber);
103 swapl(&rep.length);
104 swaps(&rep.majorVersion);
105 swaps(&rep.minorVersion);
106 }
107 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep);
108 return Success;
109 }
110
111 int
112 ProcRRXineramaGetState(ClientPtr client)
113 {
114 REQUEST(xPanoramiXGetStateReq);
115 WindowPtr pWin;
116 xPanoramiXGetStateReply rep;
117 register int rc;
118 ScreenPtr pScreen;
119 rrScrPrivPtr pScrPriv;
120 Bool active = FALSE;
121
122 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
123 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
124 if (rc != Success)
125 return rc;
126
127 pScreen = pWin->drawable.pScreen;
128 pScrPriv = rrGetScrPriv(pScreen);
129 if (pScrPriv) {
130 /* XXX do we need more than this? */
131 active = TRUE;
132 }
133
134 rep = (xPanoramiXGetStateReply) {
135 .type = X_Reply,
136 .state = active,
137 .sequenceNumber = client->sequence,
138 .length = 0,
139 .window = stuff->window
140 };
141 if (client->swapped) {
142 swaps(&rep.sequenceNumber);
143 swapl(&rep.length);
144 swapl(&rep.window);
145 }
146 WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep);
147 return Success;
148 }
149
150 static Bool
151 RRXineramaCrtcActive(RRCrtcPtr crtc)
152 {
153 return crtc->mode != NULL && crtc->numOutputs > 0;
154 }
155
156 static int
157 RRXineramaScreenCount(ScreenPtr pScreen)
158 {
159 int i, n;
160 ScreenPtr slave;
161
162 n = 0;
163 if (rrGetScrPriv(pScreen)) {
164 rrScrPriv(pScreen);
165 for (i = 0; i < pScrPriv->numCrtcs; i++)
166 if (RRXineramaCrtcActive(pScrPriv->crtcs[i]))
167 n++;
168 }
169
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]))
175 n++;
176 }
177
178 return n;
179 }
180
181 static Bool
182 RRXineramaScreenActive(ScreenPtr pScreen)
183 {
184 return RRXineramaScreenCount(pScreen) > 0;
185 }
186
187 int
188 ProcRRXineramaGetScreenCount(ClientPtr client)
189 {
190 REQUEST(xPanoramiXGetScreenCountReq);
191 WindowPtr pWin;
192 xPanoramiXGetScreenCountReply rep;
193 register int rc;
194
195 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
196 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
197 if (rc != Success)
198 return rc;
199
200 rep = (xPanoramiXGetScreenCountReply) {
201 .type = X_Reply,
202 .ScreenCount = RRXineramaScreenCount(pWin->drawable.pScreen),
203 .sequenceNumber = client->sequence,
204 .length = 0,
205 .window = stuff->window
206 };
207 if (client->swapped) {
208 swaps(&rep.sequenceNumber);
209 swapl(&rep.length);
210 swapl(&rep.window);
211 }
212 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep);
213 return Success;
214 }
215
216 int
217 ProcRRXineramaGetScreenSize(ClientPtr client)
218 {
219 REQUEST(xPanoramiXGetScreenSizeReq);
220 WindowPtr pWin, pRoot;
221 ScreenPtr pScreen;
222 xPanoramiXGetScreenSizeReply rep;
223 register int rc;
224
225 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
226 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
227 if (rc != Success)
228 return rc;
229
230 pScreen = pWin->drawable.pScreen;
231 pRoot = pScreen->root;
232
233 rep = (xPanoramiXGetScreenSizeReply) {
234 .type = X_Reply,
235 .sequenceNumber = client->sequence,
236 .length = 0,
237 .width = pRoot->drawable.width,
238 .height = pRoot->drawable.height,
239 .window = stuff->window,
240 .screen = stuff->screen
241 };
242 if (client->swapped) {
243 swaps(&rep.sequenceNumber);
244 swapl(&rep.length);
245 swapl(&rep.width);
246 swapl(&rep.height);
247 swapl(&rep.window);
248 swapl(&rep.screen);
249 }
250 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep);
251 return Success;
252 }
253
254 int
255 ProcRRXineramaIsActive(ClientPtr client)
256 {
257 xXineramaIsActiveReply rep;
258
259 REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
260
261 rep = (xXineramaIsActiveReply) {
262 .type = X_Reply,
263 .length = 0,
264 .sequenceNumber = client->sequence,
265 .state = RRXineramaScreenActive(screenInfo.screens[RR_XINERAMA_SCREEN])
266 };
267 if (client->swapped) {
268 swaps(&rep.sequenceNumber);
269 swapl(&rep.length);
270 swapl(&rep.state);
271 }
272 WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep);
273 return Success;
274 }
275
276 static void
277 RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc)
278 {
279 xXineramaScreenInfo scratch;
280
281 if (RRXineramaCrtcActive(crtc)) {
282 ScreenPtr pScreen = crtc->pScreen;
283 rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
284 BoxRec panned_area;
285
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;
295 }
296 else {
297 int width, height;
298
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;
304 }
305 if (client->swapped) {
306 swaps(&scratch.x_org);
307 swaps(&scratch.y_org);
308 swaps(&scratch.width);
309 swaps(&scratch.height);
310 }
311 WriteToClient(client, sz_XineramaScreenInfo, &scratch);
312 }
313 }
314
315 int
316 ProcRRXineramaQueryScreens(ClientPtr client)
317 {
318 xXineramaQueryScreensReply rep;
319 ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
320 int n = 0;
321 int i;
322
323 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
324
325 if (RRXineramaScreenActive(pScreen)) {
326 RRGetInfo(pScreen, FALSE);
327 n = RRXineramaScreenCount(pScreen);
328 }
329
330 rep = (xXineramaQueryScreensReply) {
331 .type = X_Reply,
332 .sequenceNumber = client->sequence,
333 .length = bytes_to_int32(n * sz_XineramaScreenInfo),
334 .number = n
335 };
336 if (client->swapped) {
337 swaps(&rep.sequenceNumber);
338 swapl(&rep.length);
339 swapl(&rep.number);
340 }
341 WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
342
343 if (n) {
344 ScreenPtr slave;
345 rrScrPriv(pScreen);
346 int has_primary = 0;
347
348 if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
349 has_primary = 1;
350 RRXineramaWriteCrtc(client, pScrPriv->primaryOutput->crtc);
351 }
352
353 for (i = 0; i < pScrPriv->numCrtcs; i++) {
354 if (has_primary &&
355 pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) {
356 has_primary = 0;
357 continue;
358 }
359 RRXineramaWriteCrtc(client, pScrPriv->crtcs[i]);
360 }
361
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]);
367 }
368 }
369
370 return Success;
371 }
372
373 static int
374 ProcRRXineramaDispatch(ClientPtr client)
375 {
376 REQUEST(xReq);
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);
390 }
391 return BadRequest;
392 }
393
394 /* SProc */
395
396 static int
397 SProcRRXineramaQueryVersion(ClientPtr client)
398 {
399 REQUEST(xPanoramiXQueryVersionReq);
400 swaps(&stuff->length);
401 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
402 return ProcRRXineramaQueryVersion(client);
403 }
404
405 static int
406 SProcRRXineramaGetState(ClientPtr client)
407 {
408 REQUEST(xPanoramiXGetStateReq);
409 swaps(&stuff->length);
410 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
411 swapl(&stuff->window);
412 return ProcRRXineramaGetState(client);
413 }
414
415 static int
416 SProcRRXineramaGetScreenCount(ClientPtr client)
417 {
418 REQUEST(xPanoramiXGetScreenCountReq);
419 swaps(&stuff->length);
420 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
421 swapl(&stuff->window);
422 return ProcRRXineramaGetScreenCount(client);
423 }
424
425 static int
426 SProcRRXineramaGetScreenSize(ClientPtr client)
427 {
428 REQUEST(xPanoramiXGetScreenSizeReq);
429 swaps(&stuff->length);
430 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
431 swapl(&stuff->window);
432 swapl(&stuff->screen);
433 return ProcRRXineramaGetScreenSize(client);
434 }
435
436 static int
437 SProcRRXineramaIsActive(ClientPtr client)
438 {
439 REQUEST(xXineramaIsActiveReq);
440 swaps(&stuff->length);
441 REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
442 return ProcRRXineramaIsActive(client);
443 }
444
445 static int
446 SProcRRXineramaQueryScreens(ClientPtr client)
447 {
448 REQUEST(xXineramaQueryScreensReq);
449 swaps(&stuff->length);
450 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
451 return ProcRRXineramaQueryScreens(client);
452 }
453
454 int
455 SProcRRXineramaDispatch(ClientPtr client)
456 {
457 REQUEST(xReq);
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);
471 }
472 return BadRequest;
473 }
474
475 void
476 RRXineramaExtensionInit(void)
477 {
478 #ifdef PANORAMIX
479 if (!noPanoramiXExtension)
480 return;
481 #endif
482
483 /*
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.
487 */
488 if (screenInfo.numScreens > 1)
489 return;
490
491 (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
492 ProcRRXineramaDispatch,
493 SProcRRXineramaDispatch, NULL, StandardMinorOpcode);
494 }