dmxpict.c revision 48a68b89
1/* 2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation on the rights to use, copy, modify, merge, 10 * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 28/* 29 * Authors: 30 * Kevin E. Martin <kem@redhat.com> 31 * 32 */ 33 34/** \file 35 * Provide support for the RENDER extension (version 0.8). 36 */ 37 38#ifdef HAVE_DMX_CONFIG_H 39#include <dmx-config.h> 40#endif 41 42#include "dmx.h" 43#include "dmxsync.h" 44#include "dmxpict.h" 45#include "dmxwindow.h" 46#include "dmxpixmap.h" 47 48#include "fb.h" 49#include "pixmapstr.h" 50#include "dixstruct.h" 51 52#include <X11/extensions/render.h> 53#include <X11/extensions/renderproto.h> 54#include <X11/extensions/Xfixes.h> 55#include "picture.h" 56#include "picturestr.h" 57#include "mipict.h" 58#include "fbpict.h" 59 60 61extern int RenderErrBase; 62extern int (*ProcRenderVector[RenderNumberRequests])(ClientPtr); 63 64static int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr); 65 66 67static int dmxProcRenderCreateGlyphSet(ClientPtr client); 68static int dmxProcRenderFreeGlyphSet(ClientPtr client); 69static int dmxProcRenderAddGlyphs(ClientPtr client); 70static int dmxProcRenderFreeGlyphs(ClientPtr client); 71static int dmxProcRenderCompositeGlyphs(ClientPtr client); 72static int dmxProcRenderSetPictureTransform(ClientPtr client); 73static int dmxProcRenderSetPictureFilter(ClientPtr client); 74#if 0 75/* FIXME: Not (yet) supported */ 76static int dmxProcRenderCreateCursor(ClientPtr client); 77static int dmxProcRenderCreateAnimCursor(ClientPtr client); 78#endif 79 80/** Catch errors that might occur when allocating Glyph Sets. Errors 81 * are saved in dmxGlyphLastError for later handling. */ 82static int dmxGlyphLastError; 83static int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev) 84{ 85 dmxGlyphLastError = ev->error_code; 86 return 0; 87} 88 89 90/** Initialize the Proc Vector for the RENDER extension. The functions 91 * here cannot be handled by the mi layer RENDER hooks either because 92 * the required information is no longer available when it reaches the 93 * mi layer or no mi layer hooks exist. This function is called from 94 * InitOutput() since it should be initialized only once per server 95 * generation. */ 96void dmxInitRender(void) 97{ 98 int i; 99 100 for (i = 0; i < RenderNumberRequests; i++) 101 dmxSaveRenderVector[i] = ProcRenderVector[i]; 102 103 ProcRenderVector[X_RenderCreateGlyphSet] 104 = dmxProcRenderCreateGlyphSet; 105 ProcRenderVector[X_RenderFreeGlyphSet] 106 = dmxProcRenderFreeGlyphSet; 107 ProcRenderVector[X_RenderAddGlyphs] 108 = dmxProcRenderAddGlyphs; 109 ProcRenderVector[X_RenderFreeGlyphs] 110 = dmxProcRenderFreeGlyphs; 111 ProcRenderVector[X_RenderCompositeGlyphs8] 112 = dmxProcRenderCompositeGlyphs; 113 ProcRenderVector[X_RenderCompositeGlyphs16] 114 = dmxProcRenderCompositeGlyphs; 115 ProcRenderVector[X_RenderCompositeGlyphs32] 116 = dmxProcRenderCompositeGlyphs; 117 ProcRenderVector[X_RenderSetPictureTransform] 118 = dmxProcRenderSetPictureTransform; 119 ProcRenderVector[X_RenderSetPictureFilter] 120 = dmxProcRenderSetPictureFilter; 121} 122 123/** Reset the Proc Vector for the RENDER extension back to the original 124 * functions. This function is called from dmxCloseScreen() during the 125 * server reset (only for screen #0). */ 126void dmxResetRender(void) 127{ 128 int i; 129 130 for (i = 0; i < RenderNumberRequests; i++) 131 ProcRenderVector[i] = dmxSaveRenderVector[i]; 132} 133 134/** Initialize the RENDER extension, allocate the picture privates and 135 * wrap mi function hooks. If the shadow frame buffer is used, then 136 * call the appropriate fb initialization function. */ 137Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) 138{ 139 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 140 PictureScreenPtr ps; 141 142 /* The shadow framebuffer only relies on FB to be initialized */ 143 if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats); 144 145 if (!miPictureInit(pScreen, formats, nformats)) 146 return FALSE; 147 148 if (!dixRegisterPrivateKey(&dmxPictPrivateKeyRec, PRIVATE_PICTURE, sizeof(dmxPictPrivRec))) 149 return FALSE; 150 151 ps = GetPictureScreen(pScreen); 152 153 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps); 154 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps); 155 156 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps); 157 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps); 158 159 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps); 160 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps); 161 162 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps); 163 DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps); 164 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps); 165 166 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps); 167 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); 168 DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); 169 DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); 170 171 return TRUE; 172} 173 174 175/** Find the appropriate format on the requested screen given the 176 * internal format requested. The list of formats is searched 177 * sequentially as the XRenderFindFormat() function does not always 178 * find the appropriate format when a specific format is requested. */ 179static XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen, 180 PictFormatPtr pFmt) 181{ 182 XRenderPictFormat *pFormat = NULL; 183 int i = 0; 184 185 if (!pFmt || !dmxScreen->beDisplay) return pFormat; 186 187 while (1) { 188 pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++); 189 if (!pFormat) break; 190 191 if (pFormat->type != pFmt->type) continue; 192 if (pFormat->depth != pFmt->depth) continue; 193 if (pFormat->direct.red != pFmt->direct.red) continue; 194 if (pFormat->direct.redMask != pFmt->direct.redMask) continue; 195 if (pFormat->direct.green != pFmt->direct.green) continue; 196 if (pFormat->direct.greenMask != pFmt->direct.greenMask) continue; 197 if (pFormat->direct.blue != pFmt->direct.blue) continue; 198 if (pFormat->direct.blueMask != pFmt->direct.blueMask) continue; 199 if (pFormat->direct.alpha != pFmt->direct.alpha) continue; 200 if (pFormat->direct.alphaMask != pFmt->direct.alphaMask) continue; 201 202 /* We have a match! */ 203 break; 204 } 205 206 return pFormat; 207} 208 209/** Free \a glyphSet on back-end screen number \a idx. */ 210Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet) 211{ 212 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 213 int idx = pScreen->myNum; 214 DMXScreenInfo *dmxScreen = &dmxScreens[idx]; 215 216 if (glyphPriv->glyphSets[idx]) { 217 XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]); 218 glyphPriv->glyphSets[idx] = (GlyphSet)0; 219 return TRUE; 220 } 221 222 return FALSE; 223} 224 225/** Create \a glyphSet on the backend screen number \a idx. */ 226int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet) 227{ 228 XRenderPictFormat *pFormat; 229 DMXScreenInfo *dmxScreen = &dmxScreens[idx]; 230 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 231 PictFormatPtr pFmt = glyphSet->format; 232 int (*oldErrorHandler)(Display *, XErrorEvent *); 233 234 pFormat = dmxFindFormat(dmxScreen, pFmt); 235 if (!pFormat) { 236 return BadMatch; 237 } 238 239 dmxGlyphLastError = 0; 240 oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler); 241 242 /* Catch when this fails */ 243 glyphPriv->glyphSets[idx] 244 = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat); 245 246 XSetErrorHandler(oldErrorHandler); 247 248 if (dmxGlyphLastError) { 249 return dmxGlyphLastError; 250 } 251 252 return Success; 253} 254 255/** Create a Glyph Set on each screen. Save the glyphset ID from each 256 * screen in the Glyph Set's private structure. Fail if the format 257 * requested is not available or if the Glyph Set cannot be created on 258 * the screen. */ 259static int dmxProcRenderCreateGlyphSet(ClientPtr client) 260{ 261 int ret; 262 REQUEST(xRenderCreateGlyphSetReq); 263 264 ret = dmxSaveRenderVector[stuff->renderReqType](client); 265 266 if (ret == Success) { 267 GlyphSetPtr glyphSet; 268 dmxGlyphPrivPtr glyphPriv; 269 int i; 270 271 /* Look up glyphSet that was just created ???? */ 272 /* Store glyphsets from backends in glyphSet->devPrivate ????? */ 273 /* Make sure we handle all errors here!! */ 274 275 dixLookupResourceByType((pointer*) &glyphSet, 276 stuff->gsid, GlyphSetType, 277 client, DixDestroyAccess); 278 279 glyphPriv = malloc(sizeof(dmxGlyphPrivRec)); 280 if (!glyphPriv) return BadAlloc; 281 glyphPriv->glyphSets = NULL; 282 MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc); 283 DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv); 284 285 for (i = 0; i < dmxNumScreens; i++) { 286 DMXScreenInfo *dmxScreen = &dmxScreens[i]; 287 int beret; 288 289 if (!dmxScreen->beDisplay) { 290 glyphPriv->glyphSets[i] = 0; 291 continue; 292 } 293 294 if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) { 295 int j; 296 297 /* Free the glyph sets we've allocated thus far */ 298 for (j = 0; j < i; j++) 299 dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet); 300 301 /* Free the resource created by render */ 302 FreeResource(stuff->gsid, RT_NONE); 303 304 return beret; 305 } 306 } 307 } 308 309 return ret; 310} 311 312/** Free the previously allocated Glyph Sets for each screen. */ 313static int dmxProcRenderFreeGlyphSet(ClientPtr client) 314{ 315 GlyphSetPtr glyphSet; 316 REQUEST(xRenderFreeGlyphSetReq); 317 318 REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); 319 dixLookupResourceByType((pointer*) &glyphSet, 320 stuff->glyphset, GlyphSetType, 321 client, DixDestroyAccess); 322 323 if (glyphSet && glyphSet->refcnt == 1) { 324 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 325 int i; 326 327 for (i = 0; i < dmxNumScreens; i++) { 328 DMXScreenInfo *dmxScreen = &dmxScreens[i]; 329 330 if (dmxScreen->beDisplay) { 331 if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet)) 332 dmxSync(dmxScreen, FALSE); 333 } 334 } 335 336 MAXSCREENSFREE(glyphPriv->glyphSets); 337 free(glyphPriv); 338 DMX_SET_GLYPH_PRIV(glyphSet, NULL); 339 } 340 341 return dmxSaveRenderVector[stuff->renderReqType](client); 342} 343 344/** Add glyphs to the Glyph Set on each screen. */ 345static int dmxProcRenderAddGlyphs(ClientPtr client) 346{ 347 int ret; 348 REQUEST(xRenderAddGlyphsReq); 349 350 ret = dmxSaveRenderVector[stuff->renderReqType](client); 351 352 if (ret == Success) { 353 GlyphSetPtr glyphSet; 354 dmxGlyphPrivPtr glyphPriv; 355 int i; 356 int nglyphs; 357 CARD32 *gids; 358 Glyph *gidsCopy; 359 xGlyphInfo *gi; 360 CARD8 *bits; 361 int nbytes; 362 363 dixLookupResourceByType((pointer*) &glyphSet, 364 stuff->glyphset, GlyphSetType, 365 client, DixReadAccess); 366 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 367 368 nglyphs = stuff->nglyphs; 369 gids = (CARD32 *)(stuff + 1); 370 gi = (xGlyphInfo *)(gids + nglyphs); 371 bits = (CARD8 *)(gi + nglyphs); 372 nbytes = ((stuff->length << 2) - 373 sizeof(xRenderAddGlyphsReq) - 374 (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs); 375 376 gidsCopy = malloc(sizeof(*gidsCopy) * nglyphs); 377 for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i]; 378 379 /* FIXME: Will this ever fail? */ 380 for (i = 0; i < dmxNumScreens; i++) { 381 DMXScreenInfo *dmxScreen = &dmxScreens[i]; 382 383 if (dmxScreen->beDisplay) { 384 XRenderAddGlyphs(dmxScreen->beDisplay, 385 glyphPriv->glyphSets[i], 386 gidsCopy, 387 (XGlyphInfo *)gi, 388 nglyphs, 389 (char *)bits, 390 nbytes); 391 dmxSync(dmxScreen, FALSE); 392 } 393 } 394 free(gidsCopy); 395 } 396 397 return ret; 398} 399 400/** Free glyphs from the Glyph Set for each screen. */ 401static int dmxProcRenderFreeGlyphs(ClientPtr client) 402{ 403 GlyphSetPtr glyphSet; 404 REQUEST(xRenderFreeGlyphsReq); 405 406 REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); 407 dixLookupResourceByType((pointer*) &glyphSet, 408 stuff->glyphset, GlyphSetType, 409 client, DixWriteAccess); 410 411 if (glyphSet) { 412 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 413 int i; 414 int nglyphs; 415 Glyph *gids; 416 417 nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2; 418 if (nglyphs) { 419 gids = malloc(sizeof(*gids) * nglyphs); 420 for (i = 0; i < nglyphs; i++) 421 gids[i] = ((CARD32 *)(stuff + 1))[i]; 422 423 for (i = 0; i < dmxNumScreens; i++) { 424 DMXScreenInfo *dmxScreen = &dmxScreens[i]; 425 426 if (dmxScreen->beDisplay) { 427 XRenderFreeGlyphs(dmxScreen->beDisplay, 428 glyphPriv->glyphSets[i], gids, nglyphs); 429 dmxSync(dmxScreen, FALSE); 430 } 431 } 432 free(gids); 433 } 434 } 435 436 return dmxSaveRenderVector[stuff->renderReqType](client); 437} 438 439/** Composite glyphs on each screen into the requested picture. If 440 * either the src or dest picture has not been allocated due to lazy 441 * window creation, this request will gracefully return. */ 442static int dmxProcRenderCompositeGlyphs(ClientPtr client) 443{ 444 int ret; 445 REQUEST(xRenderCompositeGlyphsReq); 446 447 ret = dmxSaveRenderVector[stuff->renderReqType](client); 448 449 /* For the following to work with PanoramiX, it assumes that Render 450 * wraps the ProcRenderVector after dmxRenderInit has been called. 451 */ 452 if (ret == Success) { 453 PicturePtr pSrc; 454 dmxPictPrivPtr pSrcPriv; 455 PicturePtr pDst; 456 dmxPictPrivPtr pDstPriv; 457 PictFormatPtr pFmt; 458 XRenderPictFormat *pFormat; 459 int size; 460 461 int scrnNum; 462 DMXScreenInfo *dmxScreen; 463 464 CARD8 *buffer; 465 CARD8 *end; 466 int space; 467 468 int nglyph; 469 char *glyphs; 470 char *curGlyph; 471 472 xGlyphElt *elt; 473 int nelt; 474 XGlyphElt8 *elts; 475 XGlyphElt8 *curElt; 476 477 GlyphSetPtr glyphSet; 478 dmxGlyphPrivPtr glyphPriv; 479 480 dixLookupResourceByType((pointer*) &pSrc, 481 stuff->src, PictureType, 482 client, DixReadAccess); 483 484 pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 485 if (!pSrcPriv->pict) 486 return ret; 487 488 dixLookupResourceByType((pointer*) &pDst, 489 stuff->dst, PictureType, 490 client, DixWriteAccess); 491 492 pDstPriv = DMX_GET_PICT_PRIV(pDst); 493 if (!pDstPriv->pict) 494 return ret; 495 496 scrnNum = pDst->pDrawable->pScreen->myNum; 497 dmxScreen = &dmxScreens[scrnNum]; 498 499 /* Note: If the back-end display has been detached, then it 500 * should not be possible to reach here since the pSrcPriv->pict 501 * and pDstPriv->pict will have already been set to 0. 502 */ 503 if (!dmxScreen->beDisplay) 504 return ret; 505 506 if (stuff->maskFormat) 507 dixLookupResourceByType((pointer*) &pFmt, 508 stuff->maskFormat, PictFormatType, 509 client, DixReadAccess); 510 else 511 pFmt = NULL; 512 513 pFormat = dmxFindFormat(dmxScreen, pFmt); 514 515 switch (stuff->renderReqType) { 516 case X_RenderCompositeGlyphs8: size = sizeof(CARD8); break; 517 case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break; 518 case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break; 519 default: return BadPictOp; /* Can't happen */ 520 } 521 522 buffer = (CARD8 *)(stuff + 1); 523 end = (CARD8 *)stuff + (stuff->length << 2); 524 nelt = 0; 525 nglyph = 0; 526 while (buffer + sizeof(xGlyphElt) < end) { 527 elt = (xGlyphElt *)buffer; 528 buffer += sizeof(xGlyphElt); 529 530 if (elt->len == 0xff) { 531 buffer += 4; 532 } else { 533 nelt++; 534 nglyph += elt->len; 535 space = size * elt->len; 536 if (space & 3) space += 4 - (space & 3); 537 buffer += space; 538 } 539 } 540 541 /* The following only works for Render version > 0.2 */ 542 543 /* All of the XGlyphElt* structure sizes are identical */ 544 elts = malloc(nelt * sizeof(XGlyphElt8)); 545 if (!elts) 546 return BadAlloc; 547 548 glyphs = malloc(nglyph * size); 549 if (!glyphs) { 550 free(elts); 551 return BadAlloc; 552 } 553 554 buffer = (CARD8 *)(stuff + 1); 555 end = (CARD8 *)stuff + (stuff->length << 2); 556 curGlyph = glyphs; 557 curElt = elts; 558 559 dixLookupResourceByType((pointer*) &glyphSet, 560 stuff->glyphset, GlyphSetType, 561 client, DixReadAccess); 562 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 563 564 while (buffer + sizeof(xGlyphElt) < end) { 565 elt = (xGlyphElt *)buffer; 566 buffer += sizeof(xGlyphElt); 567 568 if (elt->len == 0xff) { 569 dixLookupResourceByType((pointer*) &glyphSet, 570 *((CARD32 *)buffer), 571 GlyphSetType, 572 client, 573 DixReadAccess); 574 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); 575 buffer += 4; 576 } else { 577 curElt->glyphset = glyphPriv->glyphSets[scrnNum]; 578 curElt->xOff = elt->deltax; 579 curElt->yOff = elt->deltay; 580 curElt->nchars = elt->len; 581 curElt->chars = curGlyph; 582 583 memcpy(curGlyph, buffer, size*elt->len); 584 curGlyph += size * elt->len; 585 586 curElt++; 587 588 space = size * elt->len; 589 if (space & 3) space += 4 - (space & 3); 590 buffer += space; 591 } 592 } 593 594 switch (stuff->renderReqType) { 595 case X_RenderCompositeGlyphs8: 596 XRenderCompositeText8(dmxScreen->beDisplay, stuff->op, 597 pSrcPriv->pict, pDstPriv->pict, 598 pFormat, 599 stuff->xSrc, stuff->ySrc, 600 0, 0, elts, nelt); 601 break; 602 case X_RenderCompositeGlyphs16: 603 XRenderCompositeText16(dmxScreen->beDisplay, stuff->op, 604 pSrcPriv->pict, pDstPriv->pict, 605 pFormat, 606 stuff->xSrc, stuff->ySrc, 607 0, 0, (XGlyphElt16 *)elts, nelt); 608 break; 609 case X_RenderCompositeGlyphs32: 610 XRenderCompositeText32(dmxScreen->beDisplay, stuff->op, 611 pSrcPriv->pict, pDstPriv->pict, 612 pFormat, 613 stuff->xSrc, stuff->ySrc, 614 0, 0, (XGlyphElt32 *)elts, nelt); 615 break; 616 } 617 618 dmxSync(dmxScreen, FALSE); 619 620 free(elts); 621 free(glyphs); 622 } 623 624 return ret; 625} 626 627/** Set the picture transform on each screen. */ 628static int dmxProcRenderSetPictureTransform(ClientPtr client) 629{ 630 DMXScreenInfo *dmxScreen; 631 PicturePtr pPicture; 632 dmxPictPrivPtr pPictPriv; 633 XTransform xform; 634 REQUEST(xRenderSetPictureTransformReq); 635 636 REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); 637 VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess); 638 639 /* For the following to work with PanoramiX, it assumes that Render 640 * wraps the ProcRenderVector after dmxRenderInit has been called. 641 */ 642 dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum]; 643 pPictPriv = DMX_GET_PICT_PRIV(pPicture); 644 645 if (pPictPriv->pict) { 646 xform.matrix[0][0] = stuff->transform.matrix11; 647 xform.matrix[0][1] = stuff->transform.matrix12; 648 xform.matrix[0][2] = stuff->transform.matrix13; 649 xform.matrix[1][0] = stuff->transform.matrix21; 650 xform.matrix[1][1] = stuff->transform.matrix22; 651 xform.matrix[1][2] = stuff->transform.matrix23; 652 xform.matrix[2][0] = stuff->transform.matrix31; 653 xform.matrix[2][1] = stuff->transform.matrix32; 654 xform.matrix[2][2] = stuff->transform.matrix33; 655 656 XRenderSetPictureTransform(dmxScreen->beDisplay, 657 pPictPriv->pict, 658 &xform); 659 dmxSync(dmxScreen, FALSE); 660 } 661 662 return dmxSaveRenderVector[stuff->renderReqType](client); 663} 664 665/** Set the picture filter on each screen. */ 666static int dmxProcRenderSetPictureFilter(ClientPtr client) 667{ 668 DMXScreenInfo *dmxScreen; 669 PicturePtr pPicture; 670 dmxPictPrivPtr pPictPriv; 671 char *filter; 672 XFixed *params; 673 int nparams; 674 REQUEST(xRenderSetPictureFilterReq); 675 676 REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); 677 VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess); 678 679 /* For the following to work with PanoramiX, it assumes that Render 680 * wraps the ProcRenderVector after dmxRenderInit has been called. 681 */ 682 dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum]; 683 pPictPriv = DMX_GET_PICT_PRIV(pPicture); 684 685 if (pPictPriv->pict) { 686 filter = (char *)(stuff + 1); 687 params = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3)); 688 nparams = ((XFixed *)stuff + client->req_len) - params; 689 if (nparams < 0) 690 return BadLength; 691 692 XRenderSetPictureFilter(dmxScreen->beDisplay, 693 pPictPriv->pict, 694 filter, 695 params, 696 nparams); 697 dmxSync(dmxScreen, FALSE); 698 } 699 700 return dmxSaveRenderVector[stuff->renderReqType](client); 701} 702 703 704/** Create a picture on the appropriate screen. This is the actual 705 * function that creates the picture. However, if the associated 706 * window has not yet been created due to lazy window creation, then 707 * delay the picture creation until the window is mapped. */ 708static Picture dmxDoCreatePicture(PicturePtr pPicture) 709{ 710 DrawablePtr pDraw = pPicture->pDrawable; 711 ScreenPtr pScreen = pDraw->pScreen; 712 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 713 XRenderPictFormat *pFormat; 714 Drawable draw; 715 716 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) { 717 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw)); 718 719 if (!(draw = pWinPriv->window)) { 720 /* Window has not been created yet due to the window 721 * optimization. Delay picture creation until window is 722 * mapped. 723 */ 724 pWinPriv->hasPict = TRUE; 725 return 0; 726 } 727 } else { 728 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw)); 729 730 if (!(draw = pPixPriv->pixmap)) { 731 /* FIXME: Zero width/height pixmap?? */ 732 return 0; 733 } 734 } 735 736 /* This should not be reached if the back-end display has been 737 * detached because the pWinPriv->window or the pPixPriv->pixmap 738 * will be NULL; however, we add it here for completeness 739 */ 740 if (!dmxScreen->beDisplay) 741 return 0; 742 743 pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat); 744 745 return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0); 746} 747 748/** Create a list of pictures. This function is called by 749 * dmxCreateAndRealizeWindow() during the lazy window creation 750 * realization process. It creates the entire list of pictures that 751 * are associated with the given window. */ 752void dmxCreatePictureList(WindowPtr pWindow) 753{ 754 PicturePtr pPicture = GetPictureWindow(pWindow); 755 756 while (pPicture) { 757 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 758 759 /* Create the picture for this window */ 760 pPictPriv->pict = dmxDoCreatePicture(pPicture); 761 762 /* ValidatePicture takes care of the state changes */ 763 764 pPicture = pPicture->pNext; 765 } 766} 767 768/** Create \a pPicture on the backend. */ 769int dmxBECreatePicture(PicturePtr pPicture) 770{ 771 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 772 773 /* Create picutre on BE */ 774 pPictPriv->pict = dmxDoCreatePicture(pPicture); 775 776 /* Flush changes to the backend server */ 777 dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1); 778 779 return Success; 780} 781 782/** Create a picture. This function handles the CreatePicture 783 * unwrapping/wrapping and calls dmxDoCreatePicture to actually create 784 * the picture on the appropriate screen. */ 785int dmxCreatePicture(PicturePtr pPicture) 786{ 787 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 788 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 789 PictureScreenPtr ps = GetPictureScreen(pScreen); 790 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 791 int ret = Success; 792 793 DMX_UNWRAP(CreatePicture, dmxScreen, ps); 794#if 1 795 if (ps->CreatePicture) 796 ret = ps->CreatePicture(pPicture); 797#endif 798 799 /* Create picture on back-end server */ 800 pPictPriv->pict = dmxDoCreatePicture(pPicture); 801 pPictPriv->savedMask = 0; 802 803 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps); 804 805 return ret; 806} 807 808/** Destroy \a pPicture on the back-end server. */ 809Bool dmxBEFreePicture(PicturePtr pPicture) 810{ 811 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 812 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 813 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 814 815 if (pPictPriv->pict) { 816 XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict); 817 pPictPriv->pict = (Picture)0; 818 return TRUE; 819 } 820 821 return FALSE; 822} 823 824/** Destroy a list of pictures that are associated with the window that 825 * is being destroyed. This function is called by #dmxDestroyWindow(). 826 * */ 827Bool dmxDestroyPictureList(WindowPtr pWindow) 828{ 829 PicturePtr pPicture = GetPictureWindow(pWindow); 830 Bool ret = FALSE; 831 832 while (pPicture) { 833 ret |= dmxBEFreePicture(pPicture); 834 pPicture = pPicture->pNext; 835 } 836 837 return ret; 838} 839 840/** Destroy a picture. This function calls the wrapped function that 841 * frees the resources in the DMX server associated with this 842 * picture. */ 843void dmxDestroyPicture(PicturePtr pPicture) 844{ 845 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 846 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 847 PictureScreenPtr ps = GetPictureScreen(pScreen); 848 849 DMX_UNWRAP(DestroyPicture, dmxScreen, ps); 850 851 /* Destroy picture on back-end server */ 852 if (dmxBEFreePicture(pPicture)) 853 dmxSync(dmxScreen, FALSE); 854 855#if 1 856 if (ps->DestroyPicture) 857 ps->DestroyPicture(pPicture); 858#endif 859 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps); 860} 861 862/** Change the picture's list of clip rectangles. */ 863int dmxChangePictureClip(PicturePtr pPicture, int clipType, 864 pointer value, int n) 865{ 866 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 867 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 868 PictureScreenPtr ps = GetPictureScreen(pScreen); 869 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 870 871 DMX_UNWRAP(ChangePictureClip, dmxScreen, ps); 872#if 1 873 if (ps->ChangePictureClip) 874 ps->ChangePictureClip(pPicture, clipType, value, n); 875#endif 876 877 /* Change picture clip rects on back-end server */ 878 if (pPictPriv->pict) { 879 /* The clip has already been changed into a region by the mi 880 * routine called above. 881 */ 882 if (clipType == CT_NONE) { 883 /* Disable clipping, show all */ 884 XFixesSetPictureClipRegion(dmxScreen->beDisplay, 885 pPictPriv->pict, 0, 0, None); 886 } else if (pPicture->clientClip) { 887 RegionPtr pClip = pPicture->clientClip; 888 BoxPtr pBox = RegionRects(pClip); 889 int nBox = RegionNumRects(pClip); 890 XRectangle *pRects; 891 XRectangle *pRect; 892 int nRects; 893 894 nRects = nBox; 895 pRects = pRect = malloc(nRects * sizeof(*pRect)); 896 897 while (nBox--) { 898 pRect->x = pBox->x1; 899 pRect->y = pBox->y1; 900 pRect->width = pBox->x2 - pBox->x1; 901 pRect->height = pBox->y2 - pBox->y1; 902 pBox++; 903 pRect++; 904 } 905 906 XRenderSetPictureClipRectangles(dmxScreen->beDisplay, 907 pPictPriv->pict, 908 0, 0, 909 pRects, 910 nRects); 911 free(pRects); 912 } else { 913 XRenderSetPictureClipRectangles(dmxScreen->beDisplay, 914 pPictPriv->pict, 915 0, 0, NULL, 0); 916 } 917 dmxSync(dmxScreen, FALSE); 918 } else { 919 /* FIXME: Handle saving clip region when offscreen */ 920 } 921 922 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps); 923 924 return Success; 925} 926 927/** Destroy the picture's list of clip rectangles. */ 928void dmxDestroyPictureClip(PicturePtr pPicture) 929{ 930 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 931 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 932 PictureScreenPtr ps = GetPictureScreen(pScreen); 933 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 934 935 DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps); 936#if 1 937 if (ps->DestroyPictureClip) 938 ps->DestroyPictureClip(pPicture); 939#endif 940 941 /* Destroy picture clip rects on back-end server */ 942 if (pPictPriv->pict) { 943 XRenderSetPictureClipRectangles(dmxScreen->beDisplay, 944 pPictPriv->pict, 945 0, 0, NULL, 0); 946 dmxSync(dmxScreen, FALSE); 947 } else { 948 /* FIXME: Handle destroying clip region when offscreen */ 949 } 950 951 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps); 952} 953 954/** Change the attributes of the pictures. If the picture has not yet 955 * been created due to lazy window creation, save the mask so that it 956 * can be used to appropriately initialize the picture's attributes 957 * when it is created later. */ 958void dmxChangePicture(PicturePtr pPicture, Mask mask) 959{ 960 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 961 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 962 PictureScreenPtr ps = GetPictureScreen(pScreen); 963 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 964 965 DMX_UNWRAP(ChangePicture, dmxScreen, ps); 966#if 1 967 if (ps->ChangePicture) 968 ps->ChangePicture(pPicture, mask); 969#endif 970 971 /* Picture attribute changes are handled in ValidatePicture */ 972 pPictPriv->savedMask |= mask; 973 974 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps); 975} 976 977/** Validate the picture's attributes before rendering to it. Update 978 * any picture attributes that have been changed by one of the higher 979 * layers. */ 980void dmxValidatePicture(PicturePtr pPicture, Mask mask) 981{ 982 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 983 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 984 PictureScreenPtr ps = GetPictureScreen(pScreen); 985 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 986 987 DMX_UNWRAP(ValidatePicture, dmxScreen, ps); 988 989 /* Change picture attributes on back-end server */ 990 if (pPictPriv->pict) { 991 XRenderPictureAttributes attribs; 992 993 if (mask & CPRepeat) { 994 attribs.repeat = pPicture->repeatType; 995 } 996 if (mask & CPAlphaMap) { 997 if (pPicture->alphaMap) { 998 dmxPictPrivPtr pAlphaPriv; 999 pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap); 1000 if (pAlphaPriv->pict) { 1001 attribs.alpha_map = pAlphaPriv->pict; 1002 } else { 1003 /* FIXME: alpha picture drawable has not been created?? */ 1004 return; /* or should this be: attribs.alpha_map = None; */ 1005 } 1006 } else { 1007 attribs.alpha_map = None; 1008 } 1009 } 1010 if (mask & CPAlphaXOrigin) 1011 attribs.alpha_x_origin = pPicture->alphaOrigin.x; 1012 if (mask & CPAlphaYOrigin) 1013 attribs.alpha_y_origin = pPicture->alphaOrigin.y; 1014 if (mask & CPClipXOrigin) 1015 attribs.clip_x_origin = pPicture->clipOrigin.x; 1016 if (mask & CPClipYOrigin) 1017 attribs.clip_y_origin = pPicture->clipOrigin.y; 1018 if (mask & CPClipMask) 1019 mask &= ~CPClipMask; /* Handled in ChangePictureClip */ 1020 if (mask & CPGraphicsExposure) 1021 attribs.graphics_exposures = pPicture->graphicsExposures; 1022 if (mask & CPSubwindowMode) 1023 attribs.subwindow_mode = pPicture->subWindowMode; 1024 if (mask & CPPolyEdge) 1025 attribs.poly_edge = pPicture->polyEdge; 1026 if (mask & CPPolyMode) 1027 attribs.poly_mode = pPicture->polyMode; 1028 if (mask & CPComponentAlpha) 1029 attribs.component_alpha = pPicture->componentAlpha; 1030 1031 XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict, 1032 mask, &attribs); 1033 dmxSync(dmxScreen, FALSE); 1034 } else { 1035 pPictPriv->savedMask |= mask; 1036 } 1037 1038#if 1 1039 if (ps->ValidatePicture) 1040 ps->ValidatePicture(pPicture, mask); 1041#endif 1042 1043 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps); 1044} 1045 1046/** Composite a picture on the appropriate screen by combining the 1047 * specified rectangle of the transformed src and mask operands with 1048 * the specified rectangle of the dst using op as the compositing 1049 * operator. For a complete description see the protocol document of 1050 * the RENDER library. */ 1051void dmxComposite(CARD8 op, 1052 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 1053 INT16 xSrc, INT16 ySrc, 1054 INT16 xMask, INT16 yMask, 1055 INT16 xDst, INT16 yDst, 1056 CARD16 width, CARD16 height) 1057{ 1058 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1059 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1060 PictureScreenPtr ps = GetPictureScreen(pScreen); 1061 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1062 dmxPictPrivPtr pMaskPriv = NULL; 1063 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1064 1065 if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask); 1066 1067 DMX_UNWRAP(Composite, dmxScreen, ps); 1068#if 0 1069 if (ps->Composite) 1070 ps->Composite(op, pSrc, pMask, pDst, 1071 xSrc, ySrc, xMask, yMask, xDst, yDst, 1072 width, height); 1073#endif 1074 1075 /* Composite on back-end server */ 1076 if (pSrcPriv->pict && pDstPriv->pict && 1077 ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) { 1078 XRenderComposite(dmxScreen->beDisplay, 1079 op, 1080 pSrcPriv->pict, 1081 pMaskPriv ? pMaskPriv->pict : None, 1082 pDstPriv->pict, 1083 xSrc, ySrc, 1084 xMask, yMask, 1085 xDst, yDst, 1086 width, height); 1087 dmxSync(dmxScreen, FALSE); 1088 } 1089 1090 1091 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps); 1092} 1093 1094/** Null function to catch when/if RENDER calls lower level mi hooks. 1095 * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs(). 1096 * This function should never be called. */ 1097void dmxGlyphs(CARD8 op, 1098 PicturePtr pSrc, PicturePtr pDst, 1099 PictFormatPtr maskFormat, 1100 INT16 xSrc, INT16 ySrc, 1101 int nlists, GlyphListPtr lists, GlyphPtr *glyphs) 1102{ 1103 /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */ 1104} 1105 1106/** Fill a rectangle on the appropriate screen by combining the color 1107 * with the dest picture in the area specified by the list of 1108 * rectangles. For a complete description see the protocol document of 1109 * the RENDER library. */ 1110void dmxCompositeRects(CARD8 op, 1111 PicturePtr pDst, 1112 xRenderColor *color, 1113 int nRect, xRectangle *rects) 1114{ 1115 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1116 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1117 PictureScreenPtr ps = GetPictureScreen(pScreen); 1118 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst); 1119 1120 DMX_UNWRAP(CompositeRects, dmxScreen, ps); 1121#if 0 1122 if (ps->CompositeRects) 1123 ps->CompositeRects(op, pDst, color, nRect, rects); 1124#endif 1125 1126 /* CompositeRects on back-end server */ 1127 if (pPictPriv->pict) { 1128 XRenderFillRectangles(dmxScreen->beDisplay, 1129 op, 1130 pPictPriv->pict, 1131 (XRenderColor *)color, 1132 (XRectangle *)rects, 1133 nRect); 1134 dmxSync(dmxScreen, FALSE); 1135 } 1136 1137 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps); 1138} 1139 1140/** Indexed color visuals are not yet supported. */ 1141Bool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat) 1142{ 1143 return TRUE; 1144} 1145 1146/** Indexed color visuals are not yet supported. */ 1147void dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat) 1148{ 1149} 1150 1151/** Indexed color visuals are not yet supported. */ 1152void dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat, 1153 int ndef, xColorItem *pdef) 1154{ 1155} 1156 1157/** Composite a list of trapezoids on the appropriate screen. For a 1158 * complete description see the protocol document of the RENDER 1159 * library. */ 1160void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1161 PictFormatPtr maskFormat, 1162 INT16 xSrc, INT16 ySrc, 1163 int ntrap, xTrapezoid *traps) 1164{ 1165 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1166 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1167 PictureScreenPtr ps = GetPictureScreen(pScreen); 1168 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1169 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1170 1171 DMX_UNWRAP(Trapezoids, dmxScreen, ps); 1172#if 0 1173 if (ps->Trapezoids) 1174 ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps); 1175#endif 1176 1177 /* Draw trapezoids on back-end server */ 1178 if (pDstPriv->pict) { 1179 XRenderPictFormat *pFormat; 1180 1181 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1182 if (!pFormat) { 1183 /* FIXME: Error! */ 1184 } 1185 1186 XRenderCompositeTrapezoids(dmxScreen->beDisplay, 1187 op, 1188 pSrcPriv->pict, 1189 pDstPriv->pict, 1190 pFormat, 1191 xSrc, ySrc, 1192 (XTrapezoid *)traps, 1193 ntrap); 1194 dmxSync(dmxScreen, FALSE); 1195 } 1196 1197 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps); 1198} 1199 1200/** Composite a list of triangles on the appropriate screen. For a 1201 * complete description see the protocol document of the RENDER 1202 * library. */ 1203void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1204 PictFormatPtr maskFormat, 1205 INT16 xSrc, INT16 ySrc, 1206 int ntri, xTriangle *tris) 1207{ 1208 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1209 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1210 PictureScreenPtr ps = GetPictureScreen(pScreen); 1211 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1212 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1213 1214 DMX_UNWRAP(Triangles, dmxScreen, ps); 1215#if 0 1216 if (ps->Triangles) 1217 ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris); 1218#endif 1219 1220 /* Draw trapezoids on back-end server */ 1221 if (pDstPriv->pict) { 1222 XRenderPictFormat *pFormat; 1223 1224 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1225 if (!pFormat) { 1226 /* FIXME: Error! */ 1227 } 1228 1229 XRenderCompositeTriangles(dmxScreen->beDisplay, 1230 op, 1231 pSrcPriv->pict, 1232 pDstPriv->pict, 1233 pFormat, 1234 xSrc, ySrc, 1235 (XTriangle *)tris, 1236 ntri); 1237 dmxSync(dmxScreen, FALSE); 1238 } 1239 1240 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); 1241} 1242 1243/** Composite a triangle strip on the appropriate screen. For a 1244 * complete description see the protocol document of the RENDER 1245 * library. */ 1246void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1247 PictFormatPtr maskFormat, 1248 INT16 xSrc, INT16 ySrc, 1249 int npoint, xPointFixed *points) 1250{ 1251 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1252 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1253 PictureScreenPtr ps = GetPictureScreen(pScreen); 1254 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1255 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1256 1257 DMX_UNWRAP(TriStrip, dmxScreen, ps); 1258#if 0 1259 if (ps->TriStrip) 1260 ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); 1261#endif 1262 1263 /* Draw trapezoids on back-end server */ 1264 if (pDstPriv->pict) { 1265 XRenderPictFormat *pFormat; 1266 1267 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1268 if (!pFormat) { 1269 /* FIXME: Error! */ 1270 } 1271 1272 XRenderCompositeTriStrip(dmxScreen->beDisplay, 1273 op, 1274 pSrcPriv->pict, 1275 pDstPriv->pict, 1276 pFormat, 1277 xSrc, ySrc, 1278 (XPointFixed *)points, 1279 npoint); 1280 dmxSync(dmxScreen, FALSE); 1281 } 1282 1283 DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); 1284} 1285 1286/** Composite a triangle fan on the appropriate screen. For a complete 1287 * description see the protocol document of the RENDER library. */ 1288void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1289 PictFormatPtr maskFormat, 1290 INT16 xSrc, INT16 ySrc, 1291 int npoint, xPointFixed *points) 1292{ 1293 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1294 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1295 PictureScreenPtr ps = GetPictureScreen(pScreen); 1296 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1297 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1298 1299 DMX_UNWRAP(TriFan, dmxScreen, ps); 1300#if 0 1301 if (ps->TriFan) 1302 ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); 1303#endif 1304 1305 /* Draw trapezoids on back-end server */ 1306 if (pDstPriv->pict) { 1307 XRenderPictFormat *pFormat; 1308 1309 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1310 if (!pFormat) { 1311 /* FIXME: Error! */ 1312 } 1313 1314 XRenderCompositeTriFan(dmxScreen->beDisplay, 1315 op, 1316 pSrcPriv->pict, 1317 pDstPriv->pict, 1318 pFormat, 1319 xSrc, ySrc, 1320 (XPointFixed *)points, 1321 npoint); 1322 dmxSync(dmxScreen, FALSE); 1323 } 1324 1325 DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); 1326} 1327