1 /* 2 * 3 * Copyright 2000 SuSE, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of SuSE not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. SuSE makes no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * without express or implied warranty. 14 * 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Keith Packard, SuSE, Inc. 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include <config.h> 27 #endif 28 #include "Xrenderint.h" 29 #include <limits.h> 30 31 XRenderExtInfo XRenderExtensionInfo; 32 char XRenderExtensionName[] = RENDER_NAME; 33 34 static int XRenderCloseDisplay (Display *dpy, XExtCodes *codes); 35 36 /* 37 * XRenderExtFindDisplay - look for a display in this extension; keeps a 38 * cache of the most-recently used for efficiency. (Replaces 39 * XextFindDisplay.) 40 */ 41 static XRenderExtDisplayInfo * 42 XRenderExtFindDisplay (XRenderExtInfo *extinfo, 43 Display *dpy) 44 { 45 XRenderExtDisplayInfo *dpyinfo; 46 47 /* 48 * see if this was the most recently accessed display 49 */ 50 if ((dpyinfo = extinfo->cur) && dpyinfo->display == dpy) 51 return dpyinfo; 52 53 /* 54 * look for display in list 55 */ 56 _XLockMutex(_Xglobal_lock); 57 for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) { 58 if (dpyinfo->display == dpy) { 59 extinfo->cur = dpyinfo; /* cache most recently used */ 60 _XUnlockMutex(_Xglobal_lock); 61 return dpyinfo; 62 } 63 } 64 _XUnlockMutex(_Xglobal_lock); 65 66 return NULL; 67 } 68 69 /* 70 * If the server is missing support for any of the required depths on 71 * any screen, tell the application that Render is not present. 72 */ 73 74 #define DEPTH_MASK(d) (1U << ((d) - 1)) 75 76 /* 77 * Render requires support for depth 1, 4, 8, 24 and 32 pixmaps 78 */ 79 80 #define REQUIRED_DEPTHS (DEPTH_MASK(1) | \ 81 DEPTH_MASK(4) | \ 82 DEPTH_MASK(8) | \ 83 DEPTH_MASK(24) | \ 84 DEPTH_MASK(32)) 85 86 typedef struct _DepthCheckRec { 87 struct _DepthCheckRec *next; 88 Display *dpy; 89 CARD32 missing; 90 unsigned long serial; 91 } DepthCheckRec, *DepthCheckPtr; 92 93 static DepthCheckPtr depthChecks; 94 95 static int 96 XRenderDepthCheckErrorHandler (Display *dpy, XErrorEvent *evt) 97 { 98 if (evt->request_code == X_CreatePixmap && evt->error_code == BadValue) 99 { 100 DepthCheckPtr d; 101 102 _XLockMutex(_Xglobal_lock); 103 for (d = depthChecks; d; d = d->next) 104 { 105 if (d->dpy == dpy) 106 { 107 if ((long) (evt->serial - d->serial) >= 0) 108 d->missing |= DEPTH_MASK(evt->resourceid); 109 break; 110 } 111 } 112 _XUnlockMutex (_Xglobal_lock); 113 } 114 return 0; 115 } 116 117 static Bool 118 XRenderHasDepths (Display *dpy) 119 { 120 int s; 121 122 for (s = 0; s < ScreenCount (dpy); s++) 123 { 124 CARD32 depths = 0; 125 CARD32 missing; 126 Screen *scr = ScreenOfDisplay (dpy, s); 127 int d; 128 129 for (d = 0; d < scr->ndepths; d++) 130 depths |= DEPTH_MASK(scr->depths[d].depth); 131 missing = ~depths & REQUIRED_DEPTHS; 132 if (missing) 133 { 134 DepthCheckRec dc, **dp; 135 XErrorHandler previousHandler; 136 137 /* 138 * Ok, this is ugly. It should be sufficient at this 139 * point to just return False, but Xinerama is broken at 140 * this point and only advertises depths which have an 141 * associated visual. Of course, the other depths still 142 * work, but the only way to find out is to try them. 143 */ 144 dc.dpy = dpy; 145 dc.missing = 0; 146 dc.serial = XNextRequest (dpy); 147 _XLockMutex(_Xglobal_lock); 148 dc.next = depthChecks; 149 depthChecks = &dc; 150 _XUnlockMutex (_Xglobal_lock); 151 /* 152 * I suspect this is not really thread safe, but Xlib doesn't 153 * provide a lot of options here 154 */ 155 previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler); 156 /* 157 * Try each missing depth and see if pixmap creation succeeds 158 */ 159 for (d = 1; d <= 32; d++) 160 /* don't check depth 1 == Xcursor recurses... */ 161 if ((missing & DEPTH_MASK(d)) && d != 1) 162 { 163 Pixmap p; 164 p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, (unsigned) d); 165 XFreePixmap (dpy, p); 166 } 167 XSync (dpy, False); 168 XSetErrorHandler (previousHandler); 169 /* 170 * Unhook from the list of depth check records 171 */ 172 _XLockMutex(_Xglobal_lock); 173 for (dp = &depthChecks; *dp; dp = &(*dp)->next) 174 { 175 if (*dp == &dc) 176 { 177 *dp = dc.next; 178 break; 179 } 180 } 181 _XUnlockMutex (_Xglobal_lock); 182 if (dc.missing) 183 return False; 184 } 185 } 186 return True; 187 } 188 189 /* 190 * XRenderExtAddDisplay - add a display to this extension. (Replaces 191 * XextAddDisplay) 192 */ 193 static XRenderExtDisplayInfo * 194 XRenderExtAddDisplay (XRenderExtInfo *extinfo, 195 Display *dpy, 196 char *ext_name) 197 { 198 XRenderExtDisplayInfo *dpyinfo; 199 200 dpyinfo = Xmalloc (sizeof (XRenderExtDisplayInfo)); 201 if (!dpyinfo) return NULL; 202 dpyinfo->display = dpy; 203 dpyinfo->info = NULL; 204 205 if (XRenderHasDepths (dpy)) 206 dpyinfo->codes = XInitExtension (dpy, ext_name); 207 else 208 dpyinfo->codes = NULL; 209 210 /* 211 * if the server has the extension, then we can initialize the 212 * appropriate function vectors 213 */ 214 if (dpyinfo->codes) { 215 XESetCloseDisplay (dpy, dpyinfo->codes->extension, 216 XRenderCloseDisplay); 217 } else { 218 /* The server doesn't have this extension. 219 * Use a private Xlib-internal extension to hang the close_display 220 * hook on so that the "cache" (extinfo->cur) is properly cleaned. 221 * (XBUG 7955) 222 */ 223 XExtCodes *codes = XAddExtension(dpy); 224 if (!codes) { 225 XFree(dpyinfo); 226 return NULL; 227 } 228 XESetCloseDisplay (dpy, codes->extension, XRenderCloseDisplay); 229 } 230 231 /* 232 * now, chain it onto the list 233 */ 234 _XLockMutex(_Xglobal_lock); 235 dpyinfo->next = extinfo->head; 236 extinfo->head = dpyinfo; 237 extinfo->cur = dpyinfo; 238 extinfo->ndisplays++; 239 _XUnlockMutex(_Xglobal_lock); 240 return dpyinfo; 241 } 242 243 244 /* 245 * XRenderExtRemoveDisplay - remove the indicated display from the 246 * extension object. (Replaces XextRemoveDisplay.) 247 */ 248 static int 249 XRenderExtRemoveDisplay (XRenderExtInfo *extinfo, Display *dpy) 250 { 251 XRenderExtDisplayInfo *dpyinfo, *prev; 252 253 /* 254 * locate this display and its back link so that it can be removed 255 */ 256 _XLockMutex(_Xglobal_lock); 257 prev = NULL; 258 for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) { 259 if (dpyinfo->display == dpy) break; 260 prev = dpyinfo; 261 } 262 if (!dpyinfo) { 263 _XUnlockMutex(_Xglobal_lock); 264 return 0; /* hmm, actually an error */ 265 } 266 267 /* 268 * remove the display from the list; handles going to zero 269 */ 270 if (prev) 271 prev->next = dpyinfo->next; 272 else 273 extinfo->head = dpyinfo->next; 274 275 extinfo->ndisplays--; 276 if (dpyinfo == extinfo->cur) extinfo->cur = NULL; /* flush cache */ 277 _XUnlockMutex(_Xglobal_lock); 278 279 Xfree (dpyinfo); 280 return 1; 281 } 282 283 284 285 XRenderExtDisplayInfo * 286 XRenderFindDisplay (Display *dpy) 287 { 288 XRenderExtDisplayInfo *dpyinfo; 289 290 dpyinfo = XRenderExtFindDisplay (&XRenderExtensionInfo, dpy); 291 if (!dpyinfo) 292 dpyinfo = XRenderExtAddDisplay (&XRenderExtensionInfo, dpy, 293 XRenderExtensionName); 294 return dpyinfo; 295 } 296 297 static void 298 XRenderFreeXRenderInfo (XRenderInfo *xri) 299 { 300 Xfree(xri->format); 301 Xfree(xri->screen); 302 Xfree(xri->depth); 303 Xfree(xri->visual); 304 Xfree(xri); 305 } 306 307 static int 308 XRenderCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED) 309 { 310 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 311 if (info && info->info) XRenderFreeXRenderInfo (info->info); 312 313 return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy); 314 } 315 316 /**************************************************************************** 317 * * 318 * Render public interfaces * 319 * * 320 ****************************************************************************/ 321 322 Bool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep) 323 { 324 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 325 326 if (RenderHasExtension(info)) { 327 *event_basep = info->codes->first_event; 328 *error_basep = info->codes->first_error; 329 return True; 330 } else { 331 return False; 332 } 333 } 334 335 336 Status XRenderQueryVersion (Display *dpy, 337 int *major_versionp, 338 int *minor_versionp) 339 { 340 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 341 XRenderInfo *xri; 342 343 if (!RenderHasExtension (info)) 344 return 0; 345 346 if (!XRenderQueryFormats (dpy)) 347 return 0; 348 349 xri = info->info; 350 *major_versionp = xri->major_version; 351 *minor_versionp = xri->minor_version; 352 return 1; 353 } 354 355 static XRenderPictFormat * 356 _XRenderFindFormat (XRenderInfo *xri, PictFormat format) 357 { 358 int nf; 359 360 for (nf = 0; nf < xri->nformat; nf++) 361 if (xri->format[nf].id == format) 362 return &xri->format[nf]; 363 return NULL; 364 } 365 366 static Visual * 367 _XRenderFindVisual (Display *dpy, VisualID vid) 368 { 369 return _XVIDtoVisual (dpy, vid); 370 } 371 372 typedef struct _renderVersionState { 373 unsigned long version_seq; 374 Bool error; 375 int major_version; 376 int minor_version; 377 378 } _XrenderVersionState; 379 380 static Bool 381 _XRenderVersionHandler (Display *dpy, 382 xReply *rep, 383 char *buf, 384 int len, 385 XPointer data) 386 { 387 xRenderQueryVersionReply replbuf; 388 xRenderQueryVersionReply *repl; 389 _XrenderVersionState *state = (_XrenderVersionState *) data; 390 391 if (dpy->last_request_read != state->version_seq) 392 return False; 393 if (rep->generic.type == X_Error) 394 { 395 state->error = True; 396 return False; 397 } 398 repl = (xRenderQueryVersionReply *) 399 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 400 (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2, 401 True); 402 state->major_version = (int) repl->majorVersion; 403 state->minor_version = (int) repl->minorVersion; 404 return True; 405 } 406 407 Status 408 XRenderQueryFormats (Display *dpy) 409 { 410 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 411 _XAsyncHandler async; 412 _XrenderVersionState async_state; 413 xRenderQueryVersionReq *vreq; 414 xRenderQueryPictFormatsReply rep; 415 xRenderQueryPictFormatsReq *req; 416 XRenderInfo *xri; 417 XRenderPictFormat *format; 418 XRenderScreen *screen; 419 XRenderDepth *depth; 420 XRenderVisual *visual; 421 xPictFormInfo *xFormat; 422 xPictScreen *xScreen; 423 xPictDepth *xPDepth; 424 xPictVisual *xVisual; 425 CARD32 *xSubpixel; 426 void *xData; 427 int ns, nd; 428 unsigned nf; 429 unsigned long rlength; 430 unsigned long nbytes; 431 432 RenderCheckExtension (dpy, info, 0); 433 LockDisplay (dpy); 434 if (info->info) 435 { 436 UnlockDisplay (dpy); 437 return 1; 438 } 439 GetReq (RenderQueryVersion, vreq); 440 vreq->reqType = (CARD8) info->codes->major_opcode; 441 vreq->renderReqType = X_RenderQueryVersion; 442 vreq->majorVersion = RENDER_MAJOR; 443 vreq->minorVersion = RENDER_MINOR; 444 445 async_state.version_seq = dpy->request; 446 async_state.error = False; 447 async.next = dpy->async_handlers; 448 async.handler = _XRenderVersionHandler; 449 async.data = (XPointer) &async_state; 450 dpy->async_handlers = &async; 451 452 GetReq (RenderQueryPictFormats, req); 453 req->reqType = (CARD8) info->codes->major_opcode; 454 req->renderReqType = X_RenderQueryPictFormats; 455 456 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 457 { 458 DeqAsyncHandler (dpy, &async); 459 UnlockDisplay (dpy); 460 SyncHandle (); 461 return 0; 462 } 463 DeqAsyncHandler (dpy, &async); 464 if (async_state.error) 465 { 466 UnlockDisplay(dpy); 467 SyncHandle(); 468 return 0; 469 } 470 /* 471 * Check for the lack of sub-pixel data 472 */ 473 if (async_state.major_version == 0 && async_state.minor_version < 6) 474 rep.numSubpixel = 0; 475 476 if ((rep.numFormats < ((INT_MAX / 4) / sizeof (XRenderPictFormat))) && 477 (rep.numScreens < ((INT_MAX / 4) / sizeof (XRenderScreen))) && 478 (rep.numDepths < ((INT_MAX / 4) / sizeof (XRenderDepth))) && 479 (rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) && 480 (rep.numSubpixel < ((INT_MAX / 4) / 4)) && 481 (rep.numSubpixel <= rep.numScreens) && 482 (rep.length < (INT_MAX >> 2)) ) { 483 /* Zero-initialize so that pointers are NULL if there is a failure. */ 484 xri = Xcalloc (1, sizeof (XRenderInfo)); 485 rlength = ((rep.numFormats * sizeof (xPictFormInfo)) + 486 (rep.numScreens * sizeof (xPictScreen)) + 487 (rep.numDepths * sizeof (xPictDepth)) + 488 (rep.numVisuals * sizeof (xPictVisual)) + 489 (rep.numSubpixel * 4)); 490 xData = Xmalloc (rlength); 491 nbytes = (unsigned long) rep.length << 2; 492 } else { 493 xri = NULL; 494 xData = NULL; 495 rlength = nbytes = 0; 496 } 497 498 if (!xri || !xData || nbytes < rlength) 499 { 500 if (xri) Xfree (xri); 501 if (xData) Xfree (xData); 502 _XEatDataWords (dpy, rep.length); 503 UnlockDisplay (dpy); 504 SyncHandle (); 505 return 0; 506 } 507 xri->major_version = async_state.major_version; 508 xri->minor_version = async_state.minor_version; 509 xri->format = Xcalloc(rep.numFormats, sizeof(XRenderPictFormat)); 510 xri->nformat = (int) rep.numFormats; 511 xri->screen = Xcalloc(rep.numScreens, sizeof(XRenderScreen)); 512 xri->nscreen = (int) rep.numScreens; 513 xri->depth = Xcalloc(rep.numDepths, sizeof(XRenderDepth)); 514 xri->ndepth = (int) rep.numDepths; 515 xri->visual = Xcalloc(rep.numVisuals, sizeof(XRenderVisual)); 516 xri->nvisual = (int) rep.numVisuals; 517 if (!xri->format || !xri->screen || !xri->depth || !xri->visual) 518 { 519 XRenderFreeXRenderInfo(xri); 520 Xfree (xData); 521 _XEatDataWords (dpy, rep.length); 522 UnlockDisplay (dpy); 523 SyncHandle (); 524 return 0; 525 } 526 _XRead (dpy, (char *) xData, (long) rlength); 527 format = xri->format; 528 xFormat = (xPictFormInfo *) xData; 529 for (nf = 0; nf < rep.numFormats; nf++) 530 { 531 format->id = xFormat->id; 532 format->type = xFormat->type; 533 format->depth = xFormat->depth; 534 format->direct.red = (short) xFormat->direct.red; 535 format->direct.redMask = (short) xFormat->direct.redMask; 536 format->direct.green = (short) xFormat->direct.green; 537 format->direct.greenMask = (short) xFormat->direct.greenMask; 538 format->direct.blue = (short) xFormat->direct.blue; 539 format->direct.blueMask = (short) xFormat->direct.blueMask; 540 format->direct.alpha = (short) xFormat->direct.alpha; 541 format->direct.alphaMask = (short) xFormat->direct.alphaMask; 542 format->colormap = xFormat->colormap; 543 format++; 544 xFormat++; 545 } 546 xScreen = (xPictScreen *) xFormat; 547 screen = xri->screen; 548 depth = xri->depth; 549 visual = xri->visual; 550 for (ns = 0; ns < xri->nscreen; ns++) 551 { 552 screen->depths = depth; 553 screen->ndepths = (int) xScreen->nDepth; 554 screen->fallback = _XRenderFindFormat (xri, xScreen->fallback); 555 screen->subpixel = SubPixelUnknown; 556 xPDepth = (xPictDepth *) (xScreen + 1); 557 if (screen->ndepths > rep.numDepths) { 558 XRenderFreeXRenderInfo(xri); 559 Xfree (xData); 560 _XEatDataWords (dpy, rep.length); 561 UnlockDisplay (dpy); 562 SyncHandle (); 563 return 0; 564 } 565 rep.numDepths -= (CARD32) screen->ndepths; 566 for (nd = 0; nd < screen->ndepths; nd++) 567 { 568 int nv; 569 570 depth->depth = xPDepth->depth; 571 depth->nvisuals = xPDepth->nPictVisuals; 572 depth->visuals = visual; 573 xVisual = (xPictVisual *) (xPDepth + 1); 574 if (depth->nvisuals > rep.numVisuals) { 575 XRenderFreeXRenderInfo (xri); 576 Xfree (xData); 577 _XEatDataWords (dpy, rep.length); 578 UnlockDisplay (dpy); 579 SyncHandle (); 580 return 0; 581 } 582 rep.numVisuals -= (CARD32) depth->nvisuals; 583 for (nv = 0; nv < depth->nvisuals; nv++) 584 { 585 visual->visual = _XRenderFindVisual (dpy, xVisual->visual); 586 visual->format = _XRenderFindFormat (xri, xVisual->format); 587 visual++; 588 xVisual++; 589 } 590 depth++; 591 xPDepth = (xPictDepth *) xVisual; 592 } 593 screen++; 594 xScreen = (xPictScreen *) xPDepth; 595 } 596 xSubpixel = (CARD32 *) xScreen; 597 screen = xri->screen; 598 for (ns = 0; ns < rep.numSubpixel; ns++) 599 { 600 screen->subpixel = (int) *xSubpixel; 601 xSubpixel++; 602 screen++; 603 } 604 info->info = xri; 605 /* 606 * Skip any extra data 607 */ 608 if (nbytes > rlength) 609 _XEatData (dpy, (unsigned long) (nbytes - rlength)); 610 611 UnlockDisplay (dpy); 612 SyncHandle (); 613 Xfree (xData); 614 return 1; 615 } 616 617 int 618 XRenderQuerySubpixelOrder (Display *dpy, int screen) 619 { 620 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 621 XRenderInfo *xri; 622 623 if (!RenderHasExtension (info)) 624 return SubPixelUnknown; 625 626 if (!XRenderQueryFormats (dpy)) 627 return SubPixelUnknown; 628 629 xri = info->info; 630 return xri->screen[screen].subpixel; 631 } 632 633 Bool 634 XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel) 635 { 636 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 637 XRenderInfo *xri; 638 639 if (!RenderHasExtension (info)) 640 return False; 641 642 if (!XRenderQueryFormats (dpy)) 643 return False; 644 645 xri = info->info; 646 xri->screen[screen].subpixel = subpixel; 647 return True; 648 } 649 650 XRenderPictFormat * 651 XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual) 652 { 653 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 654 int nv; 655 XRenderInfo *xri; 656 XRenderVisual *xrv; 657 658 RenderCheckExtension (dpy, info, NULL); 659 if (!XRenderQueryFormats (dpy)) 660 return NULL; 661 xri = info->info; 662 for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++) 663 if (xrv->visual == visual) 664 return xrv->format; 665 return NULL; 666 } 667 668 XRenderPictFormat * 669 XRenderFindFormat (Display *dpy, 670 unsigned long mask, 671 _Xconst XRenderPictFormat *template, 672 int count) 673 { 674 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 675 int nf; 676 XRenderInfo *xri; 677 678 RenderCheckExtension (dpy, info, NULL); 679 if (!XRenderQueryFormats (dpy)) 680 return NULL; 681 xri = info->info; 682 for (nf = 0; nf < xri->nformat; nf++) 683 { 684 if (mask & PictFormatID) 685 if (template->id != xri->format[nf].id) 686 continue; 687 if (mask & PictFormatType) 688 if (template->type != xri->format[nf].type) 689 continue; 690 if (mask & PictFormatDepth) 691 if (template->depth != xri->format[nf].depth) 692 continue; 693 if (mask & PictFormatRed) 694 if (template->direct.red != xri->format[nf].direct.red) 695 continue; 696 if (mask & PictFormatRedMask) 697 if (template->direct.redMask != xri->format[nf].direct.redMask) 698 continue; 699 if (mask & PictFormatGreen) 700 if (template->direct.green != xri->format[nf].direct.green) 701 continue; 702 if (mask & PictFormatGreenMask) 703 if (template->direct.greenMask != xri->format[nf].direct.greenMask) 704 continue; 705 if (mask & PictFormatBlue) 706 if (template->direct.blue != xri->format[nf].direct.blue) 707 continue; 708 if (mask & PictFormatBlueMask) 709 if (template->direct.blueMask != xri->format[nf].direct.blueMask) 710 continue; 711 if (mask & PictFormatAlpha) 712 if (template->direct.alpha != xri->format[nf].direct.alpha) 713 continue; 714 if (mask & PictFormatAlphaMask) 715 if (template->direct.alphaMask != xri->format[nf].direct.alphaMask) 716 continue; 717 if (mask & PictFormatColormap) 718 if (template->colormap != xri->format[nf].colormap) 719 continue; 720 if (count-- == 0) 721 return &xri->format[nf]; 722 } 723 return NULL; 724 } 725 726 XRenderPictFormat * 727 XRenderFindStandardFormat (Display *dpy, 728 int format) 729 { 730 static struct { 731 XRenderPictFormat templ; 732 unsigned long mask; 733 } standardFormats[PictStandardNUM] = { 734 /* PictStandardARGB32 */ 735 { 736 { 737 0, /* id */ 738 PictTypeDirect, /* type */ 739 32, /* depth */ 740 { /* direct */ 741 16, /* direct.red */ 742 0xff, /* direct.redMask */ 743 8, /* direct.green */ 744 0xff, /* direct.greenMask */ 745 0, /* direct.blue */ 746 0xff, /* direct.blueMask */ 747 24, /* direct.alpha */ 748 0xff, /* direct.alphaMask */ 749 }, 750 0, /* colormap */ 751 }, 752 PictFormatType | 753 PictFormatDepth | 754 PictFormatRed | 755 PictFormatRedMask | 756 PictFormatGreen | 757 PictFormatGreenMask | 758 PictFormatBlue | 759 PictFormatBlueMask | 760 PictFormatAlpha | 761 PictFormatAlphaMask, 762 }, 763 /* PictStandardRGB24 */ 764 { 765 { 766 0, /* id */ 767 PictTypeDirect, /* type */ 768 24, /* depth */ 769 { /* direct */ 770 16, /* direct.red */ 771 0xff, /* direct.redMask */ 772 8, /* direct.green */ 773 0xff, /* direct.greenMask */ 774 0, /* direct.blue */ 775 0xff, /* direct.blueMask */ 776 0, /* direct.alpha */ 777 0x00, /* direct.alphaMask */ 778 }, 779 0, /* colormap */ 780 }, 781 PictFormatType | 782 PictFormatDepth | 783 PictFormatRed | 784 PictFormatRedMask | 785 PictFormatGreen | 786 PictFormatGreenMask | 787 PictFormatBlue | 788 PictFormatBlueMask | 789 PictFormatAlphaMask, 790 }, 791 /* PictStandardA8 */ 792 { 793 { 794 0, /* id */ 795 PictTypeDirect, /* type */ 796 8, /* depth */ 797 { /* direct */ 798 0, /* direct.red */ 799 0x00, /* direct.redMask */ 800 0, /* direct.green */ 801 0x00, /* direct.greenMask */ 802 0, /* direct.blue */ 803 0x00, /* direct.blueMask */ 804 0, /* direct.alpha */ 805 0xff, /* direct.alphaMask */ 806 }, 807 0, /* colormap */ 808 }, 809 PictFormatType | 810 PictFormatDepth | 811 PictFormatRedMask | 812 PictFormatGreenMask | 813 PictFormatBlueMask | 814 PictFormatAlpha | 815 PictFormatAlphaMask, 816 }, 817 /* PictStandardA4 */ 818 { 819 { 820 0, /* id */ 821 PictTypeDirect, /* type */ 822 4, /* depth */ 823 { /* direct */ 824 0, /* direct.red */ 825 0x00, /* direct.redMask */ 826 0, /* direct.green */ 827 0x00, /* direct.greenMask */ 828 0, /* direct.blue */ 829 0x00, /* direct.blueMask */ 830 0, /* direct.alpha */ 831 0x0f, /* direct.alphaMask */ 832 }, 833 0, /* colormap */ 834 }, 835 PictFormatType | 836 PictFormatDepth | 837 PictFormatRedMask | 838 PictFormatGreenMask | 839 PictFormatBlueMask | 840 PictFormatAlpha | 841 PictFormatAlphaMask, 842 }, 843 /* PictStandardA1 */ 844 { 845 { 846 0, /* id */ 847 PictTypeDirect, /* type */ 848 1, /* depth */ 849 { /* direct */ 850 0, /* direct.red */ 851 0x00, /* direct.redMask */ 852 0, /* direct.green */ 853 0x00, /* direct.greenMask */ 854 0, /* direct.blue */ 855 0x00, /* direct.blueMask */ 856 0, /* direct.alpha */ 857 0x01, /* direct.alphaMask */ 858 }, 859 0, /* colormap */ 860 }, 861 PictFormatType | 862 PictFormatDepth | 863 PictFormatRedMask | 864 PictFormatGreenMask | 865 PictFormatBlueMask | 866 PictFormatAlpha | 867 PictFormatAlphaMask, 868 }, 869 }; 870 871 if (0 <= format && format < PictStandardNUM) 872 return XRenderFindFormat (dpy, 873 standardFormats[format].mask, 874 &standardFormats[format].templ, 875 0); 876 return NULL; 877 } 878 879 XIndexValue * 880 XRenderQueryPictIndexValues(Display *dpy, 881 _Xconst XRenderPictFormat *format, 882 int *num) 883 { 884 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 885 xRenderQueryPictIndexValuesReq *req; 886 xRenderQueryPictIndexValuesReply rep; 887 XIndexValue *values; 888 unsigned int nbytes, nread, i; 889 890 RenderCheckExtension (dpy, info, NULL); 891 892 LockDisplay (dpy); 893 GetReq (RenderQueryPictIndexValues, req); 894 req->reqType = (CARD8) info->codes->major_opcode; 895 req->renderReqType = X_RenderQueryPictIndexValues; 896 req->format = (CARD32) format->id; 897 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 898 { 899 UnlockDisplay (dpy); 900 SyncHandle (); 901 return NULL; 902 } 903 904 if ((rep.length < (INT_MAX >> 2)) && 905 (rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) { 906 unsigned int rlength; 907 /* request data length */ 908 nbytes = rep.length << 2; 909 /* bytes of actual data in the request */ 910 nread = rep.numIndexValues * SIZEOF (xIndexValue); 911 /* size of array returned to application */ 912 rlength = (unsigned) ((unsigned long) rep.numIndexValues * sizeof (XIndexValue)); 913 914 /* allocate returned data */ 915 values = Xmalloc (rlength); 916 } else { 917 nbytes = nread = 0; 918 values = NULL; 919 } 920 921 if (!values) 922 { 923 _XEatDataWords (dpy, rep.length); 924 UnlockDisplay (dpy); 925 SyncHandle (); 926 return NULL; 927 } 928 929 /* read the values one at a time and convert */ 930 *num = (int) rep.numIndexValues; 931 for (i = 0; i < rep.numIndexValues; i++) 932 { 933 xIndexValue value; 934 935 _XRead (dpy, (char *) &value, SIZEOF (xIndexValue)); 936 values[i].pixel = value.pixel; 937 values[i].red = value.red; 938 values[i].green = value.green; 939 values[i].blue = value.blue; 940 values[i].alpha = value.alpha; 941 } 942 /* skip any padding */ 943 if(nbytes > nread) 944 { 945 _XEatData (dpy, (unsigned long) (nbytes - nread)); 946 } 947 UnlockDisplay (dpy); 948 SyncHandle (); 949 return values; 950 } 951