rrxinerama.c revision 05b261ec
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 75#define RR_XINERAMA_MAJOR_VERSION 1 76#define RR_XINERAMA_MINOR_VERSION 1 77 78/* Xinerama is not multi-screen capable; just report about screen 0 */ 79#define RR_XINERAMA_SCREEN 0 80 81static int ProcRRXineramaQueryVersion(ClientPtr client); 82static int ProcRRXineramaGetState(ClientPtr client); 83static int ProcRRXineramaGetScreenCount(ClientPtr client); 84static int ProcRRXineramaGetScreenSize(ClientPtr client); 85static int ProcRRXineramaIsActive(ClientPtr client); 86static int ProcRRXineramaQueryScreens(ClientPtr client); 87static int SProcRRXineramaDispatch(ClientPtr client); 88 89/* Proc */ 90 91int 92ProcRRXineramaQueryVersion(ClientPtr client) 93{ 94 xPanoramiXQueryVersionReply rep; 95 register int n; 96 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); 108 } 109 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 110 return (client->noClientException); 111} 112 113int 114ProcRRXineramaGetState(ClientPtr client) 115{ 116 REQUEST(xPanoramiXGetStateReq); 117 WindowPtr pWin; 118 xPanoramiXGetStateReply rep; 119 register int n, rc; 120 ScreenPtr pScreen; 121 rrScrPrivPtr pScrPriv; 122 Bool active = FALSE; 123 124 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 125 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); 126 if(rc != Success) 127 return rc; 128 129 pScreen = pWin->drawable.pScreen; 130 pScrPriv = rrGetScrPriv(pScreen); 131 if (pScrPriv) 132 { 133 /* XXX do we need more than this? */ 134 active = TRUE; 135 } 136 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); 145 } 146 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 147 return client->noClientException; 148} 149 150static Bool 151RRXineramaCrtcActive (RRCrtcPtr crtc) 152{ 153 return crtc->mode != NULL && crtc->numOutputs > 0; 154} 155 156static int 157RRXineramaScreenCount (ScreenPtr pScreen) 158{ 159 int i, n; 160 161 n = 0; 162 if (rrGetScrPriv (pScreen)) 163 { 164 rrScrPriv(pScreen); 165 for (i = 0; i < pScrPriv->numCrtcs; i++) 166 if (RRXineramaCrtcActive (pScrPriv->crtcs[i])) 167 n++; 168 } 169 return n; 170} 171 172static Bool 173RRXineramaScreenActive (ScreenPtr pScreen) 174{ 175 return RRXineramaScreenCount (pScreen) > 0; 176} 177 178int 179ProcRRXineramaGetScreenCount(ClientPtr client) 180{ 181 REQUEST(xPanoramiXGetScreenCountReq); 182 WindowPtr pWin; 183 xPanoramiXGetScreenCountReply rep; 184 register int n, rc; 185 186 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 187 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); 188 if (rc != Success) 189 return rc; 190 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); 199 } 200 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 201 return client->noClientException; 202} 203 204int 205ProcRRXineramaGetScreenSize(ClientPtr client) 206{ 207 REQUEST(xPanoramiXGetScreenSizeReq); 208 WindowPtr pWin, pRoot; 209 ScreenPtr pScreen; 210 xPanoramiXGetScreenSizeReply rep; 211 register int n, rc; 212 213 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 214 rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess); 215 if (rc != Success) 216 return rc; 217 218 pScreen = pWin->drawable.pScreen; 219 pRoot = WindowTable[pScreen->myNum]; 220 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); 231 } 232 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 233 return client->noClientException; 234} 235 236int 237ProcRRXineramaIsActive(ClientPtr client) 238{ 239 xXineramaIsActiveReply rep; 240 241 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 242 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); 252 } 253 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 254 return client->noClientException; 255} 256 257int 258ProcRRXineramaQueryScreens(ClientPtr client) 259{ 260 xXineramaQueryScreensReply rep; 261 ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN]; 262 263 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 264 265 if (RRXineramaScreenActive (pScreen)) 266 { 267 rrScrPriv(pScreen); 268 if (pScrPriv->numCrtcs == 0 || pScrPriv->numOutputs == 0) 269 RRGetInfo (pScreen); 270 } 271 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); 281 } 282 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 283 284 if(rep.number) { 285 rrScrPriv(pScreen); 286 xXineramaScreenInfo scratch; 287 int i; 288 289 for(i = 0; i < pScrPriv->numCrtcs; i++) { 290 RRCrtcPtr crtc = pScrPriv->crtcs[i]; 291 if (RRXineramaCrtcActive (crtc)) 292 { 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); 305 } 306 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 307 } 308 } 309 } 310 311 return client->noClientException; 312} 313 314static int 315ProcRRXineramaDispatch(ClientPtr client) 316{ 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); 331 } 332 return BadRequest; 333} 334 335/* SProc */ 336 337static int 338SProcRRXineramaQueryVersion (ClientPtr client) 339{ 340 REQUEST(xPanoramiXQueryVersionReq); 341 register int n; 342 swaps(&stuff->length,n); 343 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 344 return ProcRRXineramaQueryVersion(client); 345} 346 347static int 348SProcRRXineramaGetState(ClientPtr client) 349{ 350 REQUEST(xPanoramiXGetStateReq); 351 register int n; 352 swaps (&stuff->length, n); 353 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 354 return ProcRRXineramaGetState(client); 355} 356 357static int 358SProcRRXineramaGetScreenCount(ClientPtr client) 359{ 360 REQUEST(xPanoramiXGetScreenCountReq); 361 register int n; 362 swaps (&stuff->length, n); 363 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 364 return ProcRRXineramaGetScreenCount(client); 365} 366 367static int 368SProcRRXineramaGetScreenSize(ClientPtr client) 369{ 370 REQUEST(xPanoramiXGetScreenSizeReq); 371 register int n; 372 swaps (&stuff->length, n); 373 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 374 return ProcRRXineramaGetScreenSize(client); 375} 376 377static int 378SProcRRXineramaIsActive(ClientPtr client) 379{ 380 REQUEST(xXineramaIsActiveReq); 381 register int n; 382 swaps (&stuff->length, n); 383 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 384 return ProcRRXineramaIsActive(client); 385} 386 387static int 388SProcRRXineramaQueryScreens(ClientPtr client) 389{ 390 REQUEST(xXineramaQueryScreensReq); 391 register int n; 392 swaps (&stuff->length, n); 393 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 394 return ProcRRXineramaQueryScreens(client); 395} 396 397int 398SProcRRXineramaDispatch(ClientPtr client) 399{ 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); 414 } 415 return BadRequest; 416} 417 418static void 419RRXineramaResetProc(ExtensionEntry* extEntry) 420{ 421} 422 423void 424RRXineramaExtensionInit(void) 425{ 426#ifdef PANORAMIX 427 if(!noPanoramiXExtension) 428 return; 429#endif 430 431 /* 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. 435 */ 436 if (screenInfo.numScreens > 1) 437 return; 438 439 (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 440 ProcRRXineramaDispatch, 441 SProcRRXineramaDispatch, 442 RRXineramaResetProc, 443 StandardMinorOpcode); 444} 445