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 void 298XRenderFreeXRenderInfo (XRenderInfo *xri) 299{ 300 Xfree(xri->format); 301 Xfree(xri->screen); 302 Xfree(xri->depth); 303 Xfree(xri->visual); 304 Xfree(xri); 305} 306 307static int 308XRenderCloseDisplay (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 322Bool 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 336Status 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 355static 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 366static Visual * 367_XRenderFindVisual (Display *dpy, VisualID vid) 368{ 369 return _XVIDtoVisual (dpy, vid); 370} 371 372typedef struct _renderVersionState { 373 unsigned long version_seq; 374 Bool error; 375 int major_version; 376 int minor_version; 377 378} _XrenderVersionState; 379 380static 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 407Status 408XRenderQueryFormats (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.length < (INT_MAX >> 2)) ) { 482 /* Zero-initialize so that pointers are NULL if there is a failure. */ 483 xri = Xcalloc (1, sizeof (XRenderInfo)); 484 rlength = ((rep.numFormats * sizeof (xPictFormInfo)) + 485 (rep.numScreens * sizeof (xPictScreen)) + 486 (rep.numDepths * sizeof (xPictDepth)) + 487 (rep.numVisuals * sizeof (xPictVisual)) + 488 (rep.numSubpixel * 4)); 489 xData = Xmalloc (rlength); 490 nbytes = (unsigned long) rep.length << 2; 491 } else { 492 xri = NULL; 493 xData = NULL; 494 rlength = nbytes = 0; 495 } 496 497 if (!xri || !xData || nbytes < rlength) 498 { 499 if (xri) Xfree (xri); 500 if (xData) Xfree (xData); 501 _XEatDataWords (dpy, rep.length); 502 UnlockDisplay (dpy); 503 SyncHandle (); 504 return 0; 505 } 506 xri->major_version = async_state.major_version; 507 xri->minor_version = async_state.minor_version; 508 xri->format = Xcalloc(rep.numFormats, sizeof(XRenderPictFormat)); 509 xri->nformat = (int) rep.numFormats; 510 xri->screen = Xcalloc(rep.numScreens, sizeof(XRenderScreen)); 511 xri->nscreen = (int) rep.numScreens; 512 xri->depth = Xcalloc(rep.numDepths, sizeof(XRenderDepth)); 513 xri->ndepth = (int) rep.numDepths; 514 xri->visual = Xcalloc(rep.numVisuals, sizeof(XRenderVisual)); 515 xri->nvisual = (int) rep.numVisuals; 516 if (!xri->format || !xri->screen || !xri->depth || !xri->visual) 517 { 518 XRenderFreeXRenderInfo(xri); 519 Xfree (xData); 520 _XEatDataWords (dpy, rep.length); 521 UnlockDisplay (dpy); 522 SyncHandle (); 523 return 0; 524 } 525 _XRead (dpy, (char *) xData, (long) rlength); 526 format = xri->format; 527 xFormat = (xPictFormInfo *) xData; 528 for (nf = 0; nf < rep.numFormats; nf++) 529 { 530 format->id = xFormat->id; 531 format->type = xFormat->type; 532 format->depth = xFormat->depth; 533 format->direct.red = (short) xFormat->direct.red; 534 format->direct.redMask = (short) xFormat->direct.redMask; 535 format->direct.green = (short) xFormat->direct.green; 536 format->direct.greenMask = (short) xFormat->direct.greenMask; 537 format->direct.blue = (short) xFormat->direct.blue; 538 format->direct.blueMask = (short) xFormat->direct.blueMask; 539 format->direct.alpha = (short) xFormat->direct.alpha; 540 format->direct.alphaMask = (short) xFormat->direct.alphaMask; 541 format->colormap = xFormat->colormap; 542 format++; 543 xFormat++; 544 } 545 xScreen = (xPictScreen *) xFormat; 546 screen = xri->screen; 547 depth = xri->depth; 548 visual = xri->visual; 549 for (ns = 0; ns < xri->nscreen; ns++) 550 { 551 screen->depths = depth; 552 screen->ndepths = (int) xScreen->nDepth; 553 screen->fallback = _XRenderFindFormat (xri, xScreen->fallback); 554 screen->subpixel = SubPixelUnknown; 555 xPDepth = (xPictDepth *) (xScreen + 1); 556 if (screen->ndepths > rep.numDepths) { 557 XRenderFreeXRenderInfo(xri); 558 Xfree (xData); 559 _XEatDataWords (dpy, rep.length); 560 UnlockDisplay (dpy); 561 SyncHandle (); 562 return 0; 563 } 564 rep.numDepths -= (CARD32) screen->ndepths; 565 for (nd = 0; nd < screen->ndepths; nd++) 566 { 567 int nv; 568 569 depth->depth = xPDepth->depth; 570 depth->nvisuals = xPDepth->nPictVisuals; 571 depth->visuals = visual; 572 xVisual = (xPictVisual *) (xPDepth + 1); 573 if (depth->nvisuals > rep.numVisuals) { 574 XRenderFreeXRenderInfo (xri); 575 Xfree (xData); 576 _XEatDataWords (dpy, rep.length); 577 UnlockDisplay (dpy); 578 SyncHandle (); 579 return 0; 580 } 581 rep.numVisuals -= (CARD32) depth->nvisuals; 582 for (nv = 0; nv < depth->nvisuals; nv++) 583 { 584 visual->visual = _XRenderFindVisual (dpy, xVisual->visual); 585 visual->format = _XRenderFindFormat (xri, xVisual->format); 586 visual++; 587 xVisual++; 588 } 589 depth++; 590 xPDepth = (xPictDepth *) xVisual; 591 } 592 screen++; 593 xScreen = (xPictScreen *) xPDepth; 594 } 595 xSubpixel = (CARD32 *) xScreen; 596 screen = xri->screen; 597 for (ns = 0; ns < rep.numSubpixel; ns++) 598 { 599 screen->subpixel = (int) *xSubpixel; 600 xSubpixel++; 601 screen++; 602 } 603 info->info = xri; 604 /* 605 * Skip any extra data 606 */ 607 if (nbytes > rlength) 608 _XEatData (dpy, (unsigned long) (nbytes - rlength)); 609 610 UnlockDisplay (dpy); 611 SyncHandle (); 612 Xfree (xData); 613 return 1; 614} 615 616int 617XRenderQuerySubpixelOrder (Display *dpy, int screen) 618{ 619 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 620 XRenderInfo *xri; 621 622 if (!RenderHasExtension (info)) 623 return SubPixelUnknown; 624 625 if (!XRenderQueryFormats (dpy)) 626 return SubPixelUnknown; 627 628 xri = info->info; 629 return xri->screen[screen].subpixel; 630} 631 632Bool 633XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel) 634{ 635 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 636 XRenderInfo *xri; 637 638 if (!RenderHasExtension (info)) 639 return False; 640 641 if (!XRenderQueryFormats (dpy)) 642 return False; 643 644 xri = info->info; 645 xri->screen[screen].subpixel = subpixel; 646 return True; 647} 648 649XRenderPictFormat * 650XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual) 651{ 652 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 653 int nv; 654 XRenderInfo *xri; 655 XRenderVisual *xrv; 656 657 RenderCheckExtension (dpy, info, NULL); 658 if (!XRenderQueryFormats (dpy)) 659 return NULL; 660 xri = info->info; 661 for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++) 662 if (xrv->visual == visual) 663 return xrv->format; 664 return NULL; 665} 666 667XRenderPictFormat * 668XRenderFindFormat (Display *dpy, 669 unsigned long mask, 670 _Xconst XRenderPictFormat *template, 671 int count) 672{ 673 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 674 int nf; 675 XRenderInfo *xri; 676 677 RenderCheckExtension (dpy, info, NULL); 678 if (!XRenderQueryFormats (dpy)) 679 return NULL; 680 xri = info->info; 681 for (nf = 0; nf < xri->nformat; nf++) 682 { 683 if (mask & PictFormatID) 684 if (template->id != xri->format[nf].id) 685 continue; 686 if (mask & PictFormatType) 687 if (template->type != xri->format[nf].type) 688 continue; 689 if (mask & PictFormatDepth) 690 if (template->depth != xri->format[nf].depth) 691 continue; 692 if (mask & PictFormatRed) 693 if (template->direct.red != xri->format[nf].direct.red) 694 continue; 695 if (mask & PictFormatRedMask) 696 if (template->direct.redMask != xri->format[nf].direct.redMask) 697 continue; 698 if (mask & PictFormatGreen) 699 if (template->direct.green != xri->format[nf].direct.green) 700 continue; 701 if (mask & PictFormatGreenMask) 702 if (template->direct.greenMask != xri->format[nf].direct.greenMask) 703 continue; 704 if (mask & PictFormatBlue) 705 if (template->direct.blue != xri->format[nf].direct.blue) 706 continue; 707 if (mask & PictFormatBlueMask) 708 if (template->direct.blueMask != xri->format[nf].direct.blueMask) 709 continue; 710 if (mask & PictFormatAlpha) 711 if (template->direct.alpha != xri->format[nf].direct.alpha) 712 continue; 713 if (mask & PictFormatAlphaMask) 714 if (template->direct.alphaMask != xri->format[nf].direct.alphaMask) 715 continue; 716 if (mask & PictFormatColormap) 717 if (template->colormap != xri->format[nf].colormap) 718 continue; 719 if (count-- == 0) 720 return &xri->format[nf]; 721 } 722 return NULL; 723} 724 725XRenderPictFormat * 726XRenderFindStandardFormat (Display *dpy, 727 int format) 728{ 729 static struct { 730 XRenderPictFormat templ; 731 unsigned long mask; 732 } standardFormats[PictStandardNUM] = { 733 /* PictStandardARGB32 */ 734 { 735 { 736 0, /* id */ 737 PictTypeDirect, /* type */ 738 32, /* depth */ 739 { /* direct */ 740 16, /* direct.red */ 741 0xff, /* direct.redMask */ 742 8, /* direct.green */ 743 0xff, /* direct.greenMask */ 744 0, /* direct.blue */ 745 0xff, /* direct.blueMask */ 746 24, /* direct.alpha */ 747 0xff, /* direct.alphaMask */ 748 }, 749 0, /* colormap */ 750 }, 751 PictFormatType | 752 PictFormatDepth | 753 PictFormatRed | 754 PictFormatRedMask | 755 PictFormatGreen | 756 PictFormatGreenMask | 757 PictFormatBlue | 758 PictFormatBlueMask | 759 PictFormatAlpha | 760 PictFormatAlphaMask, 761 }, 762 /* PictStandardRGB24 */ 763 { 764 { 765 0, /* id */ 766 PictTypeDirect, /* type */ 767 24, /* depth */ 768 { /* direct */ 769 16, /* direct.red */ 770 0xff, /* direct.redMask */ 771 8, /* direct.green */ 772 0xff, /* direct.greenMask */ 773 0, /* direct.blue */ 774 0xff, /* direct.blueMask */ 775 0, /* direct.alpha */ 776 0x00, /* direct.alphaMask */ 777 }, 778 0, /* colormap */ 779 }, 780 PictFormatType | 781 PictFormatDepth | 782 PictFormatRed | 783 PictFormatRedMask | 784 PictFormatGreen | 785 PictFormatGreenMask | 786 PictFormatBlue | 787 PictFormatBlueMask | 788 PictFormatAlphaMask, 789 }, 790 /* PictStandardA8 */ 791 { 792 { 793 0, /* id */ 794 PictTypeDirect, /* type */ 795 8, /* 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 0xff, /* direct.alphaMask */ 805 }, 806 0, /* colormap */ 807 }, 808 PictFormatType | 809 PictFormatDepth | 810 PictFormatRedMask | 811 PictFormatGreenMask | 812 PictFormatBlueMask | 813 PictFormatAlpha | 814 PictFormatAlphaMask, 815 }, 816 /* PictStandardA4 */ 817 { 818 { 819 0, /* id */ 820 PictTypeDirect, /* type */ 821 4, /* depth */ 822 { /* direct */ 823 0, /* direct.red */ 824 0x00, /* direct.redMask */ 825 0, /* direct.green */ 826 0x00, /* direct.greenMask */ 827 0, /* direct.blue */ 828 0x00, /* direct.blueMask */ 829 0, /* direct.alpha */ 830 0x0f, /* direct.alphaMask */ 831 }, 832 0, /* colormap */ 833 }, 834 PictFormatType | 835 PictFormatDepth | 836 PictFormatRedMask | 837 PictFormatGreenMask | 838 PictFormatBlueMask | 839 PictFormatAlpha | 840 PictFormatAlphaMask, 841 }, 842 /* PictStandardA1 */ 843 { 844 { 845 0, /* id */ 846 PictTypeDirect, /* type */ 847 1, /* depth */ 848 { /* direct */ 849 0, /* direct.red */ 850 0x00, /* direct.redMask */ 851 0, /* direct.green */ 852 0x00, /* direct.greenMask */ 853 0, /* direct.blue */ 854 0x00, /* direct.blueMask */ 855 0, /* direct.alpha */ 856 0x01, /* direct.alphaMask */ 857 }, 858 0, /* colormap */ 859 }, 860 PictFormatType | 861 PictFormatDepth | 862 PictFormatRedMask | 863 PictFormatGreenMask | 864 PictFormatBlueMask | 865 PictFormatAlpha | 866 PictFormatAlphaMask, 867 }, 868 }; 869 870 if (0 <= format && format < PictStandardNUM) 871 return XRenderFindFormat (dpy, 872 standardFormats[format].mask, 873 &standardFormats[format].templ, 874 0); 875 return NULL; 876} 877 878XIndexValue * 879XRenderQueryPictIndexValues(Display *dpy, 880 _Xconst XRenderPictFormat *format, 881 int *num) 882{ 883 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); 884 xRenderQueryPictIndexValuesReq *req; 885 xRenderQueryPictIndexValuesReply rep; 886 XIndexValue *values; 887 unsigned int nbytes, nread, i; 888 889 RenderCheckExtension (dpy, info, NULL); 890 891 LockDisplay (dpy); 892 GetReq (RenderQueryPictIndexValues, req); 893 req->reqType = (CARD8) info->codes->major_opcode; 894 req->renderReqType = X_RenderQueryPictIndexValues; 895 req->format = (CARD32) format->id; 896 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 897 { 898 UnlockDisplay (dpy); 899 SyncHandle (); 900 return NULL; 901 } 902 903 if ((rep.length < (INT_MAX >> 2)) && 904 (rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) { 905 unsigned int rlength; 906 /* request data length */ 907 nbytes = rep.length << 2; 908 /* bytes of actual data in the request */ 909 nread = rep.numIndexValues * SIZEOF (xIndexValue); 910 /* size of array returned to application */ 911 rlength = (unsigned) ((unsigned long) rep.numIndexValues * sizeof (XIndexValue)); 912 913 /* allocate returned data */ 914 values = Xmalloc (rlength); 915 } else { 916 nbytes = nread = 0; 917 values = NULL; 918 } 919 920 if (!values) 921 { 922 _XEatDataWords (dpy, rep.length); 923 UnlockDisplay (dpy); 924 SyncHandle (); 925 return NULL; 926 } 927 928 /* read the values one at a time and convert */ 929 *num = (int) rep.numIndexValues; 930 for (i = 0; i < rep.numIndexValues; i++) 931 { 932 xIndexValue value; 933 934 _XRead (dpy, (char *) &value, SIZEOF (xIndexValue)); 935 values[i].pixel = value.pixel; 936 values[i].red = value.red; 937 values[i].green = value.green; 938 values[i].blue = value.blue; 939 values[i].alpha = value.alpha; 940 } 941 /* skip any padding */ 942 if(nbytes > nread) 943 { 944 _XEatData (dpy, (unsigned long) (nbytes - nread)); 945 } 946 UnlockDisplay (dpy); 947 SyncHandle (); 948 return values; 949} 950