XrrCrtc.c revision 8c4a8e55
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#ifdef HAVE_CONFIG_H 24#include <config.h> 25#endif 26 27#include <stdio.h> 28#include <X11/Xlib.h> 29/* we need to be able to manipulate the Display structure on events */ 30#include <X11/Xlibint.h> 31#include <X11/extensions/render.h> 32#include <X11/extensions/Xrender.h> 33#include "Xrandrint.h" 34 35XRRCrtcInfo * 36XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources, RRCrtc crtc) 37{ 38 XExtDisplayInfo *info = XRRFindDisplay(dpy); 39 xRRGetCrtcInfoReply rep; 40 xRRGetCrtcInfoReq *req; 41 int nbytes, nbytesRead, rbytes; 42 XRRCrtcInfo *xci; 43 44 RRCheckExtension (dpy, info, NULL); 45 46 LockDisplay (dpy); 47 GetReq (RRGetCrtcInfo, req); 48 req->reqType = info->codes->major_opcode; 49 req->randrReqType = X_RRGetCrtcInfo; 50 req->crtc = crtc; 51 req->configTimestamp = resources->configTimestamp; 52 53 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 54 { 55 UnlockDisplay (dpy); 56 SyncHandle (); 57 return NULL; 58 } 59 60 nbytes = (long) rep.length << 2; 61 62 nbytesRead = (long) (rep.nOutput * 4 + 63 rep.nPossibleOutput * 4); 64 65 /* 66 * first we must compute how much space to allocate for 67 * randr library's use; we'll allocate the structures in a single 68 * allocation, on cleanlyness grounds. 69 */ 70 71 rbytes = (sizeof (XRRCrtcInfo) + 72 rep.nOutput * sizeof (RROutput) + 73 rep.nPossibleOutput * sizeof (RROutput)); 74 75 xci = (XRRCrtcInfo *) Xmalloc(rbytes); 76 if (xci == NULL) { 77 _XEatData (dpy, (unsigned long) nbytes); 78 UnlockDisplay (dpy); 79 SyncHandle (); 80 return NULL; 81 } 82 83 xci->timestamp = rep.timestamp; 84 xci->x = rep.x; 85 xci->y = rep.y; 86 xci->width = rep.width; 87 xci->height = rep.height; 88 xci->mode = rep.mode; 89 xci->rotation = rep.rotation; 90 xci->noutput = rep.nOutput; 91 xci->outputs = (RROutput *) (xci + 1); 92 xci->rotations = rep.rotations; 93 xci->npossible = rep.nPossibleOutput; 94 xci->possible = (RROutput *) (xci->outputs + rep.nOutput); 95 96 _XRead32 (dpy, xci->outputs, rep.nOutput << 2); 97 _XRead32 (dpy, xci->possible, rep.nPossibleOutput << 2); 98 99 /* 100 * Skip any extra data 101 */ 102 if (nbytes > nbytesRead) 103 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 104 105 UnlockDisplay (dpy); 106 SyncHandle (); 107 return (XRRCrtcInfo *) xci; 108} 109 110void 111XRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo) 112{ 113 Xfree (crtcInfo); 114} 115 116Status 117XRRSetCrtcConfig (Display *dpy, 118 XRRScreenResources *resources, 119 RRCrtc crtc, 120 Time timestamp, 121 int x, int y, 122 RRMode mode, 123 Rotation rotation, 124 RROutput *outputs, 125 int noutputs) 126{ 127 XExtDisplayInfo *info = XRRFindDisplay(dpy); 128 xRRSetCrtcConfigReply rep; 129 xRRSetCrtcConfigReq *req; 130 131 RRCheckExtension (dpy, info, 0); 132 133 LockDisplay(dpy); 134 GetReq (RRSetCrtcConfig, req); 135 req->reqType = info->codes->major_opcode; 136 req->randrReqType = X_RRSetCrtcConfig; 137 req->length += noutputs; 138 req->crtc = crtc; 139 req->timestamp = timestamp; 140 req->configTimestamp = resources->configTimestamp; 141 req->x = x; 142 req->y = y; 143 req->mode = mode; 144 req->rotation = rotation; 145 Data32 (dpy, outputs, noutputs << 2); 146 147 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 148 rep.status = RRSetConfigFailed; 149 UnlockDisplay (dpy); 150 SyncHandle (); 151 return rep.status; 152} 153 154int 155XRRGetCrtcGammaSize (Display *dpy, RRCrtc crtc) 156{ 157 XExtDisplayInfo *info = XRRFindDisplay(dpy); 158 xRRGetCrtcGammaSizeReply rep; 159 xRRGetCrtcGammaSizeReq *req; 160 161 RRCheckExtension (dpy, info, 0); 162 163 LockDisplay(dpy); 164 GetReq (RRGetCrtcGammaSize, req); 165 req->reqType = info->codes->major_opcode; 166 req->randrReqType = X_RRGetCrtcGammaSize; 167 req->crtc = crtc; 168 169 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 170 rep.status = RRSetConfigFailed; 171 UnlockDisplay (dpy); 172 SyncHandle (); 173 return rep.size; 174} 175 176XRRCrtcGamma * 177XRRGetCrtcGamma (Display *dpy, RRCrtc crtc) 178{ 179 XExtDisplayInfo *info = XRRFindDisplay(dpy); 180 xRRGetCrtcGammaReply rep; 181 xRRGetCrtcGammaReq *req; 182 XRRCrtcGamma *crtc_gamma; 183 long nbytes; 184 long nbytesRead; 185 186 RRCheckExtension (dpy, info, NULL); 187 188 LockDisplay(dpy); 189 GetReq (RRGetCrtcGamma, req); 190 req->reqType = info->codes->major_opcode; 191 req->randrReqType = X_RRGetCrtcGamma; 192 req->crtc = crtc; 193 194 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 195 rep.status = RRSetConfigFailed; 196 197 nbytes = (long) rep.length << 2; 198 199 /* three channels of CARD16 data */ 200 nbytesRead = (rep.size * 2 * 3); 201 202 crtc_gamma = XRRAllocGamma (rep.size); 203 204 if (!crtc_gamma) 205 { 206 _XEatData (dpy, (unsigned long) nbytes); 207 UnlockDisplay (dpy); 208 SyncHandle (); 209 return NULL; 210 } 211 _XRead16 (dpy, crtc_gamma->red, rep.size * 2); 212 _XRead16 (dpy, crtc_gamma->green, rep.size * 2); 213 _XRead16 (dpy, crtc_gamma->blue, rep.size * 2); 214 215 if (nbytes > nbytesRead) 216 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 217 218 UnlockDisplay (dpy); 219 SyncHandle (); 220 return crtc_gamma; 221} 222 223XRRCrtcGamma * 224XRRAllocGamma (int size) 225{ 226 XRRCrtcGamma *crtc_gamma; 227 228 crtc_gamma = Xmalloc (sizeof (XRRCrtcGamma) + 229 sizeof (crtc_gamma->red[0]) * size * 3); 230 if (!crtc_gamma) 231 return NULL; 232 crtc_gamma->size = size; 233 crtc_gamma->red = (unsigned short *) (crtc_gamma + 1); 234 crtc_gamma->green = crtc_gamma->red + size; 235 crtc_gamma->blue = crtc_gamma->green + size; 236 return crtc_gamma; 237} 238 239void 240XRRSetCrtcGamma (Display *dpy, RRCrtc crtc, XRRCrtcGamma *crtc_gamma) 241{ 242 XExtDisplayInfo *info = XRRFindDisplay(dpy); 243 xRRSetCrtcGammaReq *req; 244 245 RRSimpleCheckExtension (dpy, info); 246 247 LockDisplay(dpy); 248 GetReq (RRSetCrtcGamma, req); 249 req->reqType = info->codes->major_opcode; 250 req->randrReqType = X_RRSetCrtcGamma; 251 req->crtc = crtc; 252 req->size = crtc_gamma->size; 253 req->length += (crtc_gamma->size * 2 * 3 + 3) >> 2; 254 /* 255 * Note this assumes the structure was allocated with XRRAllocGamma, 256 * otherwise the channels might not be contiguous 257 */ 258 Data16 (dpy, crtc_gamma->red, crtc_gamma->size * 2 * 3); 259 260 UnlockDisplay (dpy); 261 SyncHandle (); 262} 263 264void 265XRRFreeGamma (XRRCrtcGamma *crtc_gamma) 266{ 267 Xfree (crtc_gamma); 268} 269 270/* Version 1.3 additions */ 271 272static void 273XTransform_from_xRenderTransform (XTransform *x, 274 xRenderTransform *render) 275{ 276 x->matrix[0][0] = render->matrix11; 277 x->matrix[0][1] = render->matrix12; 278 x->matrix[0][2] = render->matrix13; 279 280 x->matrix[1][0] = render->matrix21; 281 x->matrix[1][1] = render->matrix22; 282 x->matrix[1][2] = render->matrix23; 283 284 x->matrix[2][0] = render->matrix31; 285 x->matrix[2][1] = render->matrix32; 286 x->matrix[2][2] = render->matrix33; 287} 288 289static void 290xRenderTransform_from_XTransform (xRenderTransform *render, 291 XTransform *x) 292{ 293 render->matrix11 = x->matrix[0][0]; 294 render->matrix12 = x->matrix[0][1]; 295 render->matrix13 = x->matrix[0][2]; 296 297 render->matrix21 = x->matrix[1][0]; 298 render->matrix22 = x->matrix[1][1]; 299 render->matrix23 = x->matrix[1][2]; 300 301 render->matrix31 = x->matrix[2][0]; 302 render->matrix32 = x->matrix[2][1]; 303 render->matrix33 = x->matrix[2][2]; 304} 305 306void 307XRRSetCrtcTransform (Display *dpy, 308 RRCrtc crtc, 309 XTransform *transform, 310 char *filter, 311 XFixed *params, 312 int nparams) 313{ 314 XExtDisplayInfo *info = XRRFindDisplay(dpy); 315 xRRSetCrtcTransformReq *req; 316 int nbytes = strlen (filter); 317 318 RRSimpleCheckExtension (dpy, info); 319 320 LockDisplay(dpy); 321 GetReq (RRSetCrtcTransform, req); 322 req->reqType = info->codes->major_opcode; 323 req->randrReqType = X_RRSetCrtcTransform; 324 req->crtc = crtc; 325 326 xRenderTransform_from_XTransform (&req->transform, transform); 327 328 req->nbytesFilter = nbytes; 329 req->length += ((nbytes + 3) >> 2) + nparams; 330 Data (dpy, filter, nbytes); 331 Data32 (dpy, params, nparams << 2); 332 333 UnlockDisplay (dpy); 334 SyncHandle (); 335} 336 337#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) 338 339static const xRenderTransform identity = { 340 0x10000, 0, 0, 341 0, 0x10000, 0, 342 0, 0, 0x10000, 343}; 344 345static Bool 346_XRRHasTransform (int major, int minor) 347{ 348 return major > 1 || (major == 1 && minor >= 3); 349} 350 351Status 352XRRGetCrtcTransform (Display *dpy, 353 RRCrtc crtc, 354 XRRCrtcTransformAttributes **attributes) 355{ 356 XExtDisplayInfo *info = XRRFindDisplay(dpy); 357 xRRGetCrtcTransformReply rep; 358 xRRGetCrtcTransformReq *req; 359 int major_version, minor_version; 360 XRRCrtcTransformAttributes *attr; 361 char *extra = NULL, *e; 362 int p; 363 364 *attributes = NULL; 365 366 RRCheckExtension (dpy, info, False); 367 368 if (!XRRQueryVersion (dpy, &major_version, &minor_version) || 369 !_XRRHasTransform (major_version, minor_version)) 370 { 371 /* For pre-1.3 servers, just report identity matrices everywhere */ 372 rep.pendingTransform = identity; 373 rep.pendingNbytesFilter = 0; 374 rep.pendingNparamsFilter = 0; 375 rep.currentTransform = identity; 376 rep.currentNbytesFilter = 0; 377 rep.currentNparamsFilter = 0; 378 } 379 else 380 { 381 LockDisplay (dpy); 382 GetReq (RRGetCrtcTransform, req); 383 req->reqType = info->codes->major_opcode; 384 req->randrReqType = X_RRGetCrtcTransform; 385 req->crtc = crtc; 386 387 if (!_XReply (dpy, (xReply *) &rep, CrtcTransformExtra >> 2, xFalse)) 388 { 389 rep.pendingTransform = identity; 390 rep.pendingNbytesFilter = 0; 391 rep.pendingNparamsFilter = 0; 392 rep.currentTransform = identity; 393 rep.currentNbytesFilter = 0; 394 rep.currentNparamsFilter = 0; 395 } 396 else 397 { 398 int extraBytes = rep.length * 4 - CrtcTransformExtra; 399 extra = Xmalloc (extraBytes); 400 if (!extra) { 401 _XEatData (dpy, extraBytes); 402 UnlockDisplay (dpy); 403 SyncHandle (); 404 return False; 405 } 406 _XRead (dpy, extra, extraBytes); 407 } 408 409 UnlockDisplay (dpy); 410 SyncHandle (); 411 } 412 413 attr = Xmalloc (sizeof (XRRCrtcTransformAttributes) + 414 rep.pendingNparamsFilter * sizeof (XFixed) + 415 rep.currentNparamsFilter * sizeof (XFixed) + 416 rep.pendingNbytesFilter + 1 + 417 rep.currentNbytesFilter + 1); 418 419 if (!attr) { 420 XFree (extra); 421 return False; 422 } 423 XTransform_from_xRenderTransform (&attr->pendingTransform, &rep.pendingTransform); 424 XTransform_from_xRenderTransform (&attr->currentTransform, &rep.currentTransform); 425 426 attr->pendingParams = (XFixed *) (attr + 1); 427 attr->currentParams = attr->pendingParams + rep.pendingNparamsFilter; 428 attr->pendingFilter = (char *) (attr->currentParams + rep.currentNparamsFilter); 429 attr->currentFilter = attr->pendingFilter + rep.pendingNbytesFilter + 1; 430 431 e = extra; 432 433 memcpy (attr->pendingFilter, e, rep.pendingNbytesFilter); 434 attr->pendingFilter[rep.pendingNbytesFilter] = '\0'; 435 e += (rep.pendingNbytesFilter + 3) & ~3; 436 for (p = 0; p < rep.pendingNparamsFilter; p++) { 437 INT32 f; 438 memcpy (&f, e, 4); 439 e += 4; 440 attr->pendingParams[p] = (XFixed) f; 441 } 442 attr->pendingNparams = rep.pendingNparamsFilter; 443 444 memcpy (attr->currentFilter, e, rep.currentNbytesFilter); 445 attr->currentFilter[rep.currentNbytesFilter] = '\0'; 446 e += (rep.currentNbytesFilter + 3) & ~3; 447 for (p = 0; p < rep.currentNparamsFilter; p++) { 448 INT32 f; 449 memcpy (&f, e, 4); 450 e += 4; 451 attr->currentParams[p] = (XFixed) f; 452 } 453 attr->currentNparams = rep.currentNparamsFilter; 454 455 if (extra) 456 XFree (extra); 457 *attributes = attr; 458 459 return True; 460} 461 462XRRPanning * 463XRRGetPanning (Display *dpy, XRRScreenResources *resources, RRCrtc crtc) 464{ 465 XExtDisplayInfo *info = XRRFindDisplay(dpy); 466 xRRGetPanningReply rep; 467 xRRGetPanningReq *req; 468 XRRPanning *xp; 469 470 RRCheckExtension (dpy, info, NULL); 471 472 LockDisplay (dpy); 473 GetReq (RRGetPanning, req); 474 req->reqType = info->codes->major_opcode; 475 req->randrReqType = X_RRGetPanning; 476 req->crtc = crtc; 477 478 if (!_XReply (dpy, (xReply *) &rep, 1, xFalse)) 479 { 480 UnlockDisplay (dpy); 481 SyncHandle (); 482 return NULL; 483 } 484 485 if (! (xp = (XRRPanning *) Xmalloc(sizeof(XRRPanning))) ) { 486 _XEatData (dpy, sizeof(XRRPanning)); 487 UnlockDisplay (dpy); 488 SyncHandle (); 489 return NULL; 490 } 491 492 xp->timestamp = rep.timestamp; 493 xp->left = rep.left; 494 xp->top = rep.top; 495 xp->width = rep.width; 496 xp->height = rep.height; 497 xp->track_left = rep.track_left; 498 xp->track_top = rep.track_top; 499 xp->track_width = rep.track_width; 500 xp->track_height = rep.track_height; 501 xp->border_left = rep.border_left; 502 xp->border_top = rep.border_top; 503 xp->border_right = rep.border_right; 504 xp->border_bottom = rep.border_bottom; 505 506 UnlockDisplay (dpy); 507 SyncHandle (); 508 return (XRRPanning *) xp; 509} 510 511void 512XRRFreePanning (XRRPanning *panning) 513{ 514 Xfree (panning); 515} 516 517Status 518XRRSetPanning (Display *dpy, 519 XRRScreenResources *resources, 520 RRCrtc crtc, 521 XRRPanning *panning) 522{ 523 XExtDisplayInfo *info = XRRFindDisplay(dpy); 524 xRRSetPanningReply rep; 525 xRRSetPanningReq *req; 526 527 RRCheckExtension (dpy, info, 0); 528 529 LockDisplay(dpy); 530 GetReq (RRSetPanning, req); 531 req->reqType = info->codes->major_opcode; 532 req->randrReqType = X_RRSetPanning; 533 req->crtc = crtc; 534 req->timestamp = panning->timestamp; 535 req->left = panning->left; 536 req->top = panning->top; 537 req->width = panning->width; 538 req->height = panning->height; 539 req->track_left = panning->track_left; 540 req->track_top = panning->track_top; 541 req->track_width = panning->track_width; 542 req->track_height = panning->track_height; 543 req->border_left = panning->border_left; 544 req->border_top = panning->border_top; 545 req->border_right = panning->border_right; 546 req->border_bottom = panning->border_bottom; 547 548 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 549 rep.status = RRSetConfigFailed; 550 UnlockDisplay (dpy); 551 SyncHandle (); 552 return rep.status; 553} 554 555