Xrender.c revision 53bb355a
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 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 117static Bool 118XRenderHasDepths (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 */ 193static XRenderExtDisplayInfo * 194XRenderExtAddDisplay (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 */ 248static int 249XRenderExtRemoveDisplay (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 285XRenderExtDisplayInfo * 286XRenderFindDisplay (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 297static int 298XRenderCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED) 299{ 300 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 301 if (info && info->info) XFree (info->info); 302 303 return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy); 304} 305 306/**************************************************************************** 307 * * 308 * Render public interfaces * 309 * * 310 ****************************************************************************/ 311 312Bool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep) 313{ 314 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 315 316 if (RenderHasExtension(info)) { 317 *event_basep = info->codes->first_event; 318 *error_basep = info->codes->first_error; 319 return True; 320 } else { 321 return False; 322 } 323} 324 325 326Status XRenderQueryVersion (Display *dpy, 327 int *major_versionp, 328 int *minor_versionp) 329{ 330 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 331 XRenderInfo *xri; 332 333 if (!RenderHasExtension (info)) 334 return 0; 335 336 if (!XRenderQueryFormats (dpy)) 337 return 0; 338 339 xri = info->info; 340 *major_versionp = xri->major_version; 341 *minor_versionp = xri->minor_version; 342 return 1; 343} 344 345static XRenderPictFormat * 346_XRenderFindFormat (XRenderInfo *xri, PictFormat format) 347{ 348 int nf; 349 350 for (nf = 0; nf < xri->nformat; nf++) 351 if (xri->format[nf].id == format) 352 return &xri->format[nf]; 353 return NULL; 354} 355 356static Visual * 357_XRenderFindVisual (Display *dpy, VisualID vid) 358{ 359 return _XVIDtoVisual (dpy, vid); 360} 361 362typedef struct _renderVersionState { 363 unsigned long version_seq; 364 Bool error; 365 int major_version; 366 int minor_version; 367 368} _XrenderVersionState; 369 370static Bool 371_XRenderVersionHandler (Display *dpy, 372 xReply *rep, 373 char *buf, 374 int len, 375 XPointer data) 376{ 377 xRenderQueryVersionReply replbuf; 378 xRenderQueryVersionReply *repl; 379 _XrenderVersionState *state = (_XrenderVersionState *) data; 380 381 if (dpy->last_request_read != state->version_seq) 382 return False; 383 if (rep->generic.type == X_Error) 384 { 385 state->error = True; 386 return False; 387 } 388 repl = (xRenderQueryVersionReply *) 389 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, 390 (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2, 391 True); 392 state->major_version = (int) repl->majorVersion; 393 state->minor_version = (int) repl->minorVersion; 394 return True; 395} 396 397Status 398XRenderQueryFormats (Display *dpy) 399{ 400 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 401 _XAsyncHandler async; 402 _XrenderVersionState async_state; 403 xRenderQueryVersionReq *vreq; 404 xRenderQueryPictFormatsReply rep; 405 xRenderQueryPictFormatsReq *req; 406 XRenderInfo *xri; 407 XRenderPictFormat *format; 408 XRenderScreen *screen; 409 XRenderDepth *depth; 410 XRenderVisual *visual; 411 xPictFormInfo *xFormat; 412 xPictScreen *xScreen; 413 xPictDepth *xPDepth; 414 xPictVisual *xVisual; 415 CARD32 *xSubpixel; 416 void *xData; 417 int ns, nd; 418 unsigned nf; 419 unsigned long rlength; 420 unsigned long nbytes; 421 422 RenderCheckExtension (dpy, info, 0); 423 LockDisplay (dpy); 424 if (info->info) 425 { 426 UnlockDisplay (dpy); 427 return 1; 428 } 429 GetReq (RenderQueryVersion, vreq); 430 vreq->reqType = (CARD8) info->codes->major_opcode; 431 vreq->renderReqType = X_RenderQueryVersion; 432 vreq->majorVersion = RENDER_MAJOR; 433 vreq->minorVersion = RENDER_MINOR; 434 435 async_state.version_seq = dpy->request; 436 async_state.error = False; 437 async.next = dpy->async_handlers; 438 async.handler = _XRenderVersionHandler; 439 async.data = (XPointer) &async_state; 440 dpy->async_handlers = &async; 441 442 GetReq (RenderQueryPictFormats, req); 443 req->reqType = (CARD8) info->codes->major_opcode; 444 req->renderReqType = X_RenderQueryPictFormats; 445 446 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 447 { 448 DeqAsyncHandler (dpy, &async); 449 UnlockDisplay (dpy); 450 SyncHandle (); 451 return 0; 452 } 453 DeqAsyncHandler (dpy, &async); 454 if (async_state.error) 455 { 456 UnlockDisplay(dpy); 457 SyncHandle(); 458 return 0; 459 } 460 /* 461 * Check for the lack of sub-pixel data 462 */ 463 if (async_state.major_version == 0 && async_state.minor_version < 6) 464 rep.numSubpixel = 0; 465 466 if ((rep.numFormats < ((INT_MAX / 4) / sizeof (XRenderPictFormat))) && 467 (rep.numScreens < ((INT_MAX / 4) / sizeof (XRenderScreen))) && 468 (rep.numDepths < ((INT_MAX / 4) / sizeof (XRenderDepth))) && 469 (rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) && 470 (rep.numSubpixel < ((INT_MAX / 4) / 4)) && 471 (rep.length < (INT_MAX >> 2)) ) { 472 xri = Xmalloc (sizeof (XRenderInfo) + 473 (rep.numFormats * sizeof (XRenderPictFormat)) + 474 (rep.numScreens * sizeof (XRenderScreen)) + 475 (rep.numDepths * sizeof (XRenderDepth)) + 476 (rep.numVisuals * sizeof (XRenderVisual))); 477 rlength = ((rep.numFormats * sizeof (xPictFormInfo)) + 478 (rep.numScreens * sizeof (xPictScreen)) + 479 (rep.numDepths * sizeof (xPictDepth)) + 480 (rep.numVisuals * sizeof (xPictVisual)) + 481 (rep.numSubpixel * 4)); 482 xData = Xmalloc (rlength); 483 nbytes = (unsigned long) rep.length << 2; 484 } else { 485 xri = NULL; 486 xData = NULL; 487 rlength = nbytes = 0; 488 } 489 490 if (!xri || !xData || nbytes < rlength) 491 { 492 if (xri) Xfree (xri); 493 if (xData) Xfree (xData); 494 _XEatDataWords (dpy, rep.length); 495 UnlockDisplay (dpy); 496 SyncHandle (); 497 return 0; 498 } 499 xri->major_version = async_state.major_version; 500 xri->minor_version = async_state.minor_version; 501 xri->format = (XRenderPictFormat *) (xri + 1); 502 xri->nformat = (int) rep.numFormats; 503 xri->screen = (XRenderScreen *) (xri->format + rep.numFormats); 504 xri->nscreen = (int) rep.numScreens; 505 xri->depth = (XRenderDepth *) (xri->screen + rep.numScreens); 506 xri->ndepth = (int) rep.numDepths; 507 xri->visual = (XRenderVisual *) (xri->depth + rep.numDepths); 508 xri->nvisual = (int) rep.numVisuals; 509 _XRead (dpy, (char *) xData, (long) rlength); 510 format = xri->format; 511 xFormat = (xPictFormInfo *) xData; 512 for (nf = 0; nf < rep.numFormats; nf++) 513 { 514 format->id = xFormat->id; 515 format->type = xFormat->type; 516 format->depth = xFormat->depth; 517 format->direct.red = (short) xFormat->direct.red; 518 format->direct.redMask = (short) xFormat->direct.redMask; 519 format->direct.green = (short) xFormat->direct.green; 520 format->direct.greenMask = (short) xFormat->direct.greenMask; 521 format->direct.blue = (short) xFormat->direct.blue; 522 format->direct.blueMask = (short) xFormat->direct.blueMask; 523 format->direct.alpha = (short) xFormat->direct.alpha; 524 format->direct.alphaMask = (short) xFormat->direct.alphaMask; 525 format->colormap = xFormat->colormap; 526 format++; 527 xFormat++; 528 } 529 xScreen = (xPictScreen *) xFormat; 530 screen = xri->screen; 531 depth = xri->depth; 532 visual = xri->visual; 533 for (ns = 0; ns < xri->nscreen; ns++) 534 { 535 screen->depths = depth; 536 screen->ndepths = (int) xScreen->nDepth; 537 screen->fallback = _XRenderFindFormat (xri, xScreen->fallback); 538 screen->subpixel = SubPixelUnknown; 539 xPDepth = (xPictDepth *) (xScreen + 1); 540 if (screen->ndepths > rep.numDepths) { 541 Xfree (xri); 542 Xfree (xData); 543 _XEatDataWords (dpy, rep.length); 544 UnlockDisplay (dpy); 545 SyncHandle (); 546 return 0; 547 } 548 rep.numDepths -= (CARD32) screen->ndepths; 549 for (nd = 0; nd < screen->ndepths; nd++) 550 { 551 int nv; 552 553 depth->depth = xPDepth->depth; 554 depth->nvisuals = xPDepth->nPictVisuals; 555 depth->visuals = visual; 556 xVisual = (xPictVisual *) (xPDepth + 1); 557 if (depth->nvisuals > rep.numVisuals) { 558 Xfree (xri); 559 Xfree (xData); 560 _XEatDataWords (dpy, rep.length); 561 UnlockDisplay (dpy); 562 SyncHandle (); 563 return 0; 564 } 565 rep.numVisuals -= (CARD32) depth->nvisuals; 566 for (nv = 0; nv < depth->nvisuals; nv++) 567 { 568 visual->visual = _XRenderFindVisual (dpy, xVisual->visual); 569 visual->format = _XRenderFindFormat (xri, xVisual->format); 570 visual++; 571 xVisual++; 572 } 573 depth++; 574 xPDepth = (xPictDepth *) xVisual; 575 } 576 screen++; 577 xScreen = (xPictScreen *) xPDepth; 578 } 579 xSubpixel = (CARD32 *) xScreen; 580 screen = xri->screen; 581 for (ns = 0; ns < rep.numSubpixel; ns++) 582 { 583 screen->subpixel = (int) *xSubpixel; 584 xSubpixel++; 585 screen++; 586 } 587 info->info = xri; 588 /* 589 * Skip any extra data 590 */ 591 if (nbytes > rlength) 592 _XEatData (dpy, (unsigned long) (nbytes - rlength)); 593 594 UnlockDisplay (dpy); 595 SyncHandle (); 596 Xfree (xData); 597 return 1; 598} 599 600int 601XRenderQuerySubpixelOrder (Display *dpy, int screen) 602{ 603 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 604 XRenderInfo *xri; 605 606 if (!RenderHasExtension (info)) 607 return SubPixelUnknown; 608 609 if (!XRenderQueryFormats (dpy)) 610 return SubPixelUnknown; 611 612 xri = info->info; 613 return xri->screen[screen].subpixel; 614} 615 616Bool 617XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel) 618{ 619 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 620 XRenderInfo *xri; 621 622 if (!RenderHasExtension (info)) 623 return False; 624 625 if (!XRenderQueryFormats (dpy)) 626 return False; 627 628 xri = info->info; 629 xri->screen[screen].subpixel = subpixel; 630 return True; 631} 632 633XRenderPictFormat * 634XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual) 635{ 636 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 637 int nv; 638 XRenderInfo *xri; 639 XRenderVisual *xrv; 640 641 RenderCheckExtension (dpy, info, NULL); 642 if (!XRenderQueryFormats (dpy)) 643 return NULL; 644 xri = info->info; 645 for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++) 646 if (xrv->visual == visual) 647 return xrv->format; 648 return NULL; 649} 650 651XRenderPictFormat * 652XRenderFindFormat (Display *dpy, 653 unsigned long mask, 654 _Xconst XRenderPictFormat *template, 655 int count) 656{ 657 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 658 int nf; 659 XRenderInfo *xri; 660 661 RenderCheckExtension (dpy, info, NULL); 662 if (!XRenderQueryFormats (dpy)) 663 return NULL; 664 xri = info->info; 665 for (nf = 0; nf < xri->nformat; nf++) 666 { 667 if (mask & PictFormatID) 668 if (template->id != xri->format[nf].id) 669 continue; 670 if (mask & PictFormatType) 671 if (template->type != xri->format[nf].type) 672 continue; 673 if (mask & PictFormatDepth) 674 if (template->depth != xri->format[nf].depth) 675 continue; 676 if (mask & PictFormatRed) 677 if (template->direct.red != xri->format[nf].direct.red) 678 continue; 679 if (mask & PictFormatRedMask) 680 if (template->direct.redMask != xri->format[nf].direct.redMask) 681 continue; 682 if (mask & PictFormatGreen) 683 if (template->direct.green != xri->format[nf].direct.green) 684 continue; 685 if (mask & PictFormatGreenMask) 686 if (template->direct.greenMask != xri->format[nf].direct.greenMask) 687 continue; 688 if (mask & PictFormatBlue) 689 if (template->direct.blue != xri->format[nf].direct.blue) 690 continue; 691 if (mask & PictFormatBlueMask) 692 if (template->direct.blueMask != xri->format[nf].direct.blueMask) 693 continue; 694 if (mask & PictFormatAlpha) 695 if (template->direct.alpha != xri->format[nf].direct.alpha) 696 continue; 697 if (mask & PictFormatAlphaMask) 698 if (template->direct.alphaMask != xri->format[nf].direct.alphaMask) 699 continue; 700 if (mask & PictFormatColormap) 701 if (template->colormap != xri->format[nf].colormap) 702 continue; 703 if (count-- == 0) 704 return &xri->format[nf]; 705 } 706 return NULL; 707} 708 709XRenderPictFormat * 710XRenderFindStandardFormat (Display *dpy, 711 int format) 712{ 713 static struct { 714 XRenderPictFormat templ; 715 unsigned long mask; 716 } standardFormats[PictStandardNUM] = { 717 /* PictStandardARGB32 */ 718 { 719 { 720 0, /* id */ 721 PictTypeDirect, /* type */ 722 32, /* depth */ 723 { /* direct */ 724 16, /* direct.red */ 725 0xff, /* direct.redMask */ 726 8, /* direct.green */ 727 0xff, /* direct.greenMask */ 728 0, /* direct.blue */ 729 0xff, /* direct.blueMask */ 730 24, /* direct.alpha */ 731 0xff, /* direct.alphaMask */ 732 }, 733 0, /* colormap */ 734 }, 735 PictFormatType | 736 PictFormatDepth | 737 PictFormatRed | 738 PictFormatRedMask | 739 PictFormatGreen | 740 PictFormatGreenMask | 741 PictFormatBlue | 742 PictFormatBlueMask | 743 PictFormatAlpha | 744 PictFormatAlphaMask, 745 }, 746 /* PictStandardRGB24 */ 747 { 748 { 749 0, /* id */ 750 PictTypeDirect, /* type */ 751 24, /* depth */ 752 { /* direct */ 753 16, /* direct.red */ 754 0xff, /* direct.redMask */ 755 8, /* direct.green */ 756 0xff, /* direct.greenMask */ 757 0, /* direct.blue */ 758 0xff, /* direct.blueMask */ 759 0, /* direct.alpha */ 760 0x00, /* direct.alphaMask */ 761 }, 762 0, /* colormap */ 763 }, 764 PictFormatType | 765 PictFormatDepth | 766 PictFormatRed | 767 PictFormatRedMask | 768 PictFormatGreen | 769 PictFormatGreenMask | 770 PictFormatBlue | 771 PictFormatBlueMask | 772 PictFormatAlphaMask, 773 }, 774 /* PictStandardA8 */ 775 { 776 { 777 0, /* id */ 778 PictTypeDirect, /* type */ 779 8, /* depth */ 780 { /* direct */ 781 0, /* direct.red */ 782 0x00, /* direct.redMask */ 783 0, /* direct.green */ 784 0x00, /* direct.greenMask */ 785 0, /* direct.blue */ 786 0x00, /* direct.blueMask */ 787 0, /* direct.alpha */ 788 0xff, /* direct.alphaMask */ 789 }, 790 0, /* colormap */ 791 }, 792 PictFormatType | 793 PictFormatDepth | 794 PictFormatRedMask | 795 PictFormatGreenMask | 796 PictFormatBlueMask | 797 PictFormatAlpha | 798 PictFormatAlphaMask, 799 }, 800 /* PictStandardA4 */ 801 { 802 { 803 0, /* id */ 804 PictTypeDirect, /* type */ 805 4, /* depth */ 806 { /* direct */ 807 0, /* direct.red */ 808 0x00, /* direct.redMask */ 809 0, /* direct.green */ 810 0x00, /* direct.greenMask */ 811 0, /* direct.blue */ 812 0x00, /* direct.blueMask */ 813 0, /* direct.alpha */ 814 0x0f, /* direct.alphaMask */ 815 }, 816 0, /* colormap */ 817 }, 818 PictFormatType | 819 PictFormatDepth | 820 PictFormatRedMask | 821 PictFormatGreenMask | 822 PictFormatBlueMask | 823 PictFormatAlpha | 824 PictFormatAlphaMask, 825 }, 826 /* PictStandardA1 */ 827 { 828 { 829 0, /* id */ 830 PictTypeDirect, /* type */ 831 1, /* depth */ 832 { /* direct */ 833 0, /* direct.red */ 834 0x00, /* direct.redMask */ 835 0, /* direct.green */ 836 0x00, /* direct.greenMask */ 837 0, /* direct.blue */ 838 0x00, /* direct.blueMask */ 839 0, /* direct.alpha */ 840 0x01, /* direct.alphaMask */ 841 }, 842 0, /* colormap */ 843 }, 844 PictFormatType | 845 PictFormatDepth | 846 PictFormatRedMask | 847 PictFormatGreenMask | 848 PictFormatBlueMask | 849 PictFormatAlpha | 850 PictFormatAlphaMask, 851 }, 852 }; 853 854 if (0 <= format && format < PictStandardNUM) 855 return XRenderFindFormat (dpy, 856 standardFormats[format].mask, 857 &standardFormats[format].templ, 858 0); 859 return NULL; 860} 861 862XIndexValue * 863XRenderQueryPictIndexValues(Display *dpy, 864 _Xconst XRenderPictFormat *format, 865 int *num) 866{ 867 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 868 xRenderQueryPictIndexValuesReq *req; 869 xRenderQueryPictIndexValuesReply rep; 870 XIndexValue *values; 871 unsigned int nbytes, nread, i; 872 873 RenderCheckExtension (dpy, info, NULL); 874 875 LockDisplay (dpy); 876 GetReq (RenderQueryPictIndexValues, req); 877 req->reqType = (CARD8) info->codes->major_opcode; 878 req->renderReqType = X_RenderQueryPictIndexValues; 879 req->format = (CARD32) format->id; 880 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 881 { 882 UnlockDisplay (dpy); 883 SyncHandle (); 884 return NULL; 885 } 886 887 if ((rep.length < (INT_MAX >> 2)) && 888 (rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) { 889 unsigned int rlength; 890 /* request data length */ 891 nbytes = rep.length << 2; 892 /* bytes of actual data in the request */ 893 nread = rep.numIndexValues * SIZEOF (xIndexValue); 894 /* size of array returned to application */ 895 rlength = (unsigned) ((unsigned long) rep.numIndexValues * sizeof (XIndexValue)); 896 897 /* allocate returned data */ 898 values = Xmalloc (rlength); 899 } else { 900 nbytes = nread = 0; 901 values = NULL; 902 } 903 904 if (!values) 905 { 906 _XEatDataWords (dpy, rep.length); 907 UnlockDisplay (dpy); 908 SyncHandle (); 909 return NULL; 910 } 911 912 /* read the values one at a time and convert */ 913 *num = (int) rep.numIndexValues; 914 for (i = 0; i < rep.numIndexValues; i++) 915 { 916 xIndexValue value; 917 918 _XRead (dpy, (char *) &value, SIZEOF (xIndexValue)); 919 values[i].pixel = value.pixel; 920 values[i].red = value.red; 921 values[i].green = value.green; 922 values[i].blue = value.blue; 923 values[i].alpha = value.alpha; 924 } 925 /* skip any padding */ 926 if(nbytes > nread) 927 { 928 _XEatData (dpy, (unsigned long) (nbytes - nread)); 929 } 930 UnlockDisplay (dpy); 931 SyncHandle (); 932 return values; 933} 934