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