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