dmxpict.c revision 706f2543
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 690 XRenderSetPictureFilter(dmxScreen->beDisplay, 691 pPictPriv->pict, 692 filter, 693 params, 694 nparams); 695 dmxSync(dmxScreen, FALSE); 696 } 697 698 return dmxSaveRenderVector[stuff->renderReqType](client); 699} 700 701 702/** Create a picture on the appropriate screen. This is the actual 703 * function that creates the picture. However, if the associated 704 * window has not yet been created due to lazy window creation, then 705 * delay the picture creation until the window is mapped. */ 706static Picture dmxDoCreatePicture(PicturePtr pPicture) 707{ 708 DrawablePtr pDraw = pPicture->pDrawable; 709 ScreenPtr pScreen = pDraw->pScreen; 710 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 711 XRenderPictFormat *pFormat; 712 Drawable draw; 713 714 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) { 715 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw)); 716 717 if (!(draw = pWinPriv->window)) { 718 /* Window has not been created yet due to the window 719 * optimization. Delay picture creation until window is 720 * mapped. 721 */ 722 pWinPriv->hasPict = TRUE; 723 return 0; 724 } 725 } else { 726 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw)); 727 728 if (!(draw = pPixPriv->pixmap)) { 729 /* FIXME: Zero width/height pixmap?? */ 730 return 0; 731 } 732 } 733 734 /* This should not be reached if the back-end display has been 735 * detached because the pWinPriv->window or the pPixPriv->pixmap 736 * will be NULL; however, we add it here for completeness 737 */ 738 if (!dmxScreen->beDisplay) 739 return 0; 740 741 pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat); 742 743 return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0); 744} 745 746/** Create a list of pictures. This function is called by 747 * dmxCreateAndRealizeWindow() during the lazy window creation 748 * realization process. It creates the entire list of pictures that 749 * are associated with the given window. */ 750void dmxCreatePictureList(WindowPtr pWindow) 751{ 752 PicturePtr pPicture = GetPictureWindow(pWindow); 753 754 while (pPicture) { 755 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 756 757 /* Create the picture for this window */ 758 pPictPriv->pict = dmxDoCreatePicture(pPicture); 759 760 /* ValidatePicture takes care of the state changes */ 761 762 pPicture = pPicture->pNext; 763 } 764} 765 766/** Create \a pPicture on the backend. */ 767int dmxBECreatePicture(PicturePtr pPicture) 768{ 769 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 770 771 /* Create picutre on BE */ 772 pPictPriv->pict = dmxDoCreatePicture(pPicture); 773 774 /* Flush changes to the backend server */ 775 dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1); 776 777 return Success; 778} 779 780/** Create a picture. This function handles the CreatePicture 781 * unwrapping/wrapping and calls dmxDoCreatePicture to actually create 782 * the picture on the appropriate screen. */ 783int dmxCreatePicture(PicturePtr pPicture) 784{ 785 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 786 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 787 PictureScreenPtr ps = GetPictureScreen(pScreen); 788 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 789 int ret = Success; 790 791 DMX_UNWRAP(CreatePicture, dmxScreen, ps); 792#if 1 793 if (ps->CreatePicture) 794 ret = ps->CreatePicture(pPicture); 795#endif 796 797 /* Create picture on back-end server */ 798 pPictPriv->pict = dmxDoCreatePicture(pPicture); 799 pPictPriv->savedMask = 0; 800 801 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps); 802 803 return ret; 804} 805 806/** Destroy \a pPicture on the back-end server. */ 807Bool dmxBEFreePicture(PicturePtr pPicture) 808{ 809 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 810 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 811 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 812 813 if (pPictPriv->pict) { 814 XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict); 815 pPictPriv->pict = (Picture)0; 816 return TRUE; 817 } 818 819 return FALSE; 820} 821 822/** Destroy a list of pictures that are associated with the window that 823 * is being destroyed. This function is called by #dmxDestroyWindow(). 824 * */ 825Bool dmxDestroyPictureList(WindowPtr pWindow) 826{ 827 PicturePtr pPicture = GetPictureWindow(pWindow); 828 Bool ret = FALSE; 829 830 while (pPicture) { 831 ret |= dmxBEFreePicture(pPicture); 832 pPicture = pPicture->pNext; 833 } 834 835 return ret; 836} 837 838/** Destroy a picture. This function calls the wrapped function that 839 * frees the resources in the DMX server associated with this 840 * picture. */ 841void dmxDestroyPicture(PicturePtr pPicture) 842{ 843 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 844 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 845 PictureScreenPtr ps = GetPictureScreen(pScreen); 846 847 DMX_UNWRAP(DestroyPicture, dmxScreen, ps); 848 849 /* Destroy picture on back-end server */ 850 if (dmxBEFreePicture(pPicture)) 851 dmxSync(dmxScreen, FALSE); 852 853#if 1 854 if (ps->DestroyPicture) 855 ps->DestroyPicture(pPicture); 856#endif 857 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps); 858} 859 860/** Change the picture's list of clip rectangles. */ 861int dmxChangePictureClip(PicturePtr pPicture, int clipType, 862 pointer value, int n) 863{ 864 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 865 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 866 PictureScreenPtr ps = GetPictureScreen(pScreen); 867 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 868 869 DMX_UNWRAP(ChangePictureClip, dmxScreen, ps); 870#if 1 871 if (ps->ChangePictureClip) 872 ps->ChangePictureClip(pPicture, clipType, value, n); 873#endif 874 875 /* Change picture clip rects on back-end server */ 876 if (pPictPriv->pict) { 877 /* The clip has already been changed into a region by the mi 878 * routine called above. 879 */ 880 if (clipType == CT_NONE) { 881 /* Disable clipping, show all */ 882 XFixesSetPictureClipRegion(dmxScreen->beDisplay, 883 pPictPriv->pict, 0, 0, None); 884 } else if (pPicture->clientClip) { 885 RegionPtr pClip = pPicture->clientClip; 886 BoxPtr pBox = RegionRects(pClip); 887 int nBox = RegionNumRects(pClip); 888 XRectangle *pRects; 889 XRectangle *pRect; 890 int nRects; 891 892 nRects = nBox; 893 pRects = pRect = malloc(nRects * sizeof(*pRect)); 894 895 while (nBox--) { 896 pRect->x = pBox->x1; 897 pRect->y = pBox->y1; 898 pRect->width = pBox->x2 - pBox->x1; 899 pRect->height = pBox->y2 - pBox->y1; 900 pBox++; 901 pRect++; 902 } 903 904 XRenderSetPictureClipRectangles(dmxScreen->beDisplay, 905 pPictPriv->pict, 906 0, 0, 907 pRects, 908 nRects); 909 free(pRects); 910 } else { 911 XRenderSetPictureClipRectangles(dmxScreen->beDisplay, 912 pPictPriv->pict, 913 0, 0, NULL, 0); 914 } 915 dmxSync(dmxScreen, FALSE); 916 } else { 917 /* FIXME: Handle saving clip region when offscreen */ 918 } 919 920 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps); 921 922 return Success; 923} 924 925/** Destroy the picture's list of clip rectangles. */ 926void dmxDestroyPictureClip(PicturePtr pPicture) 927{ 928 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 929 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 930 PictureScreenPtr ps = GetPictureScreen(pScreen); 931 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 932 933 DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps); 934#if 1 935 if (ps->DestroyPictureClip) 936 ps->DestroyPictureClip(pPicture); 937#endif 938 939 /* Destroy picture clip rects on back-end server */ 940 if (pPictPriv->pict) { 941 XRenderSetPictureClipRectangles(dmxScreen->beDisplay, 942 pPictPriv->pict, 943 0, 0, NULL, 0); 944 dmxSync(dmxScreen, FALSE); 945 } else { 946 /* FIXME: Handle destroying clip region when offscreen */ 947 } 948 949 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps); 950} 951 952/** Change the attributes of the pictures. If the picture has not yet 953 * been created due to lazy window creation, save the mask so that it 954 * can be used to appropriately initialize the picture's attributes 955 * when it is created later. */ 956void dmxChangePicture(PicturePtr pPicture, Mask mask) 957{ 958 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 959 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 960 PictureScreenPtr ps = GetPictureScreen(pScreen); 961 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 962 963 DMX_UNWRAP(ChangePicture, dmxScreen, ps); 964#if 1 965 if (ps->ChangePicture) 966 ps->ChangePicture(pPicture, mask); 967#endif 968 969 /* Picture attribute changes are handled in ValidatePicture */ 970 pPictPriv->savedMask |= mask; 971 972 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps); 973} 974 975/** Validate the picture's attributes before rendering to it. Update 976 * any picture attributes that have been changed by one of the higher 977 * layers. */ 978void dmxValidatePicture(PicturePtr pPicture, Mask mask) 979{ 980 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 981 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 982 PictureScreenPtr ps = GetPictureScreen(pScreen); 983 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); 984 985 DMX_UNWRAP(ValidatePicture, dmxScreen, ps); 986 987 /* Change picture attributes on back-end server */ 988 if (pPictPriv->pict) { 989 XRenderPictureAttributes attribs; 990 991 if (mask & CPRepeat) { 992 attribs.repeat = pPicture->repeatType; 993 } 994 if (mask & CPAlphaMap) { 995 if (pPicture->alphaMap) { 996 dmxPictPrivPtr pAlphaPriv; 997 pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap); 998 if (pAlphaPriv->pict) { 999 attribs.alpha_map = pAlphaPriv->pict; 1000 } else { 1001 /* FIXME: alpha picture drawable has not been created?? */ 1002 return; /* or should this be: attribs.alpha_map = None; */ 1003 } 1004 } else { 1005 attribs.alpha_map = None; 1006 } 1007 } 1008 if (mask & CPAlphaXOrigin) 1009 attribs.alpha_x_origin = pPicture->alphaOrigin.x; 1010 if (mask & CPAlphaYOrigin) 1011 attribs.alpha_y_origin = pPicture->alphaOrigin.y; 1012 if (mask & CPClipXOrigin) 1013 attribs.clip_x_origin = pPicture->clipOrigin.x; 1014 if (mask & CPClipYOrigin) 1015 attribs.clip_y_origin = pPicture->clipOrigin.y; 1016 if (mask & CPClipMask) 1017 mask &= ~CPClipMask; /* Handled in ChangePictureClip */ 1018 if (mask & CPGraphicsExposure) 1019 attribs.graphics_exposures = pPicture->graphicsExposures; 1020 if (mask & CPSubwindowMode) 1021 attribs.subwindow_mode = pPicture->subWindowMode; 1022 if (mask & CPPolyEdge) 1023 attribs.poly_edge = pPicture->polyEdge; 1024 if (mask & CPPolyMode) 1025 attribs.poly_mode = pPicture->polyMode; 1026 if (mask & CPComponentAlpha) 1027 attribs.component_alpha = pPicture->componentAlpha; 1028 1029 XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict, 1030 mask, &attribs); 1031 dmxSync(dmxScreen, FALSE); 1032 } else { 1033 pPictPriv->savedMask |= mask; 1034 } 1035 1036#if 1 1037 if (ps->ValidatePicture) 1038 ps->ValidatePicture(pPicture, mask); 1039#endif 1040 1041 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps); 1042} 1043 1044/** Composite a picture on the appropriate screen by combining the 1045 * specified rectangle of the transformed src and mask operands with 1046 * the specified rectangle of the dst using op as the compositing 1047 * operator. For a complete description see the protocol document of 1048 * the RENDER library. */ 1049void dmxComposite(CARD8 op, 1050 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 1051 INT16 xSrc, INT16 ySrc, 1052 INT16 xMask, INT16 yMask, 1053 INT16 xDst, INT16 yDst, 1054 CARD16 width, CARD16 height) 1055{ 1056 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1057 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1058 PictureScreenPtr ps = GetPictureScreen(pScreen); 1059 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1060 dmxPictPrivPtr pMaskPriv = NULL; 1061 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1062 1063 if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask); 1064 1065 DMX_UNWRAP(Composite, dmxScreen, ps); 1066#if 0 1067 if (ps->Composite) 1068 ps->Composite(op, pSrc, pMask, pDst, 1069 xSrc, ySrc, xMask, yMask, xDst, yDst, 1070 width, height); 1071#endif 1072 1073 /* Composite on back-end server */ 1074 if (pSrcPriv->pict && pDstPriv->pict && 1075 ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) { 1076 XRenderComposite(dmxScreen->beDisplay, 1077 op, 1078 pSrcPriv->pict, 1079 pMaskPriv ? pMaskPriv->pict : None, 1080 pDstPriv->pict, 1081 xSrc, ySrc, 1082 xMask, yMask, 1083 xDst, yDst, 1084 width, height); 1085 dmxSync(dmxScreen, FALSE); 1086 } 1087 1088 1089 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps); 1090} 1091 1092/** Null function to catch when/if RENDER calls lower level mi hooks. 1093 * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs(). 1094 * This function should never be called. */ 1095void dmxGlyphs(CARD8 op, 1096 PicturePtr pSrc, PicturePtr pDst, 1097 PictFormatPtr maskFormat, 1098 INT16 xSrc, INT16 ySrc, 1099 int nlists, GlyphListPtr lists, GlyphPtr *glyphs) 1100{ 1101 /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */ 1102} 1103 1104/** Fill a rectangle on the appropriate screen by combining the color 1105 * with the dest picture in the area specified by the list of 1106 * rectangles. For a complete description see the protocol document of 1107 * the RENDER library. */ 1108void dmxCompositeRects(CARD8 op, 1109 PicturePtr pDst, 1110 xRenderColor *color, 1111 int nRect, xRectangle *rects) 1112{ 1113 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1114 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1115 PictureScreenPtr ps = GetPictureScreen(pScreen); 1116 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst); 1117 1118 DMX_UNWRAP(CompositeRects, dmxScreen, ps); 1119#if 0 1120 if (ps->CompositeRects) 1121 ps->CompositeRects(op, pDst, color, nRect, rects); 1122#endif 1123 1124 /* CompositeRects on back-end server */ 1125 if (pPictPriv->pict) { 1126 XRenderFillRectangles(dmxScreen->beDisplay, 1127 op, 1128 pPictPriv->pict, 1129 (XRenderColor *)color, 1130 (XRectangle *)rects, 1131 nRect); 1132 dmxSync(dmxScreen, FALSE); 1133 } 1134 1135 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps); 1136} 1137 1138/** Indexed color visuals are not yet supported. */ 1139Bool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat) 1140{ 1141 return TRUE; 1142} 1143 1144/** Indexed color visuals are not yet supported. */ 1145void dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat) 1146{ 1147} 1148 1149/** Indexed color visuals are not yet supported. */ 1150void dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat, 1151 int ndef, xColorItem *pdef) 1152{ 1153} 1154 1155/** Composite a list of trapezoids on the appropriate screen. For a 1156 * complete description see the protocol document of the RENDER 1157 * library. */ 1158void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1159 PictFormatPtr maskFormat, 1160 INT16 xSrc, INT16 ySrc, 1161 int ntrap, xTrapezoid *traps) 1162{ 1163 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1164 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1165 PictureScreenPtr ps = GetPictureScreen(pScreen); 1166 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1167 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1168 1169 DMX_UNWRAP(Trapezoids, dmxScreen, ps); 1170#if 0 1171 if (ps->Trapezoids) 1172 ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps); 1173#endif 1174 1175 /* Draw trapezoids on back-end server */ 1176 if (pDstPriv->pict) { 1177 XRenderPictFormat *pFormat; 1178 1179 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1180 if (!pFormat) { 1181 /* FIXME: Error! */ 1182 } 1183 1184 XRenderCompositeTrapezoids(dmxScreen->beDisplay, 1185 op, 1186 pSrcPriv->pict, 1187 pDstPriv->pict, 1188 pFormat, 1189 xSrc, ySrc, 1190 (XTrapezoid *)traps, 1191 ntrap); 1192 dmxSync(dmxScreen, FALSE); 1193 } 1194 1195 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps); 1196} 1197 1198/** Composite a list of triangles on the appropriate screen. For a 1199 * complete description see the protocol document of the RENDER 1200 * library. */ 1201void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1202 PictFormatPtr maskFormat, 1203 INT16 xSrc, INT16 ySrc, 1204 int ntri, xTriangle *tris) 1205{ 1206 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1207 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1208 PictureScreenPtr ps = GetPictureScreen(pScreen); 1209 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1210 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1211 1212 DMX_UNWRAP(Triangles, dmxScreen, ps); 1213#if 0 1214 if (ps->Triangles) 1215 ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris); 1216#endif 1217 1218 /* Draw trapezoids on back-end server */ 1219 if (pDstPriv->pict) { 1220 XRenderPictFormat *pFormat; 1221 1222 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1223 if (!pFormat) { 1224 /* FIXME: Error! */ 1225 } 1226 1227 XRenderCompositeTriangles(dmxScreen->beDisplay, 1228 op, 1229 pSrcPriv->pict, 1230 pDstPriv->pict, 1231 pFormat, 1232 xSrc, ySrc, 1233 (XTriangle *)tris, 1234 ntri); 1235 dmxSync(dmxScreen, FALSE); 1236 } 1237 1238 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); 1239} 1240 1241/** Composite a triangle strip on the appropriate screen. For a 1242 * complete description see the protocol document of the RENDER 1243 * library. */ 1244void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1245 PictFormatPtr maskFormat, 1246 INT16 xSrc, INT16 ySrc, 1247 int npoint, xPointFixed *points) 1248{ 1249 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1250 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1251 PictureScreenPtr ps = GetPictureScreen(pScreen); 1252 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1253 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1254 1255 DMX_UNWRAP(TriStrip, dmxScreen, ps); 1256#if 0 1257 if (ps->TriStrip) 1258 ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); 1259#endif 1260 1261 /* Draw trapezoids on back-end server */ 1262 if (pDstPriv->pict) { 1263 XRenderPictFormat *pFormat; 1264 1265 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1266 if (!pFormat) { 1267 /* FIXME: Error! */ 1268 } 1269 1270 XRenderCompositeTriStrip(dmxScreen->beDisplay, 1271 op, 1272 pSrcPriv->pict, 1273 pDstPriv->pict, 1274 pFormat, 1275 xSrc, ySrc, 1276 (XPointFixed *)points, 1277 npoint); 1278 dmxSync(dmxScreen, FALSE); 1279 } 1280 1281 DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); 1282} 1283 1284/** Composite a triangle fan on the appropriate screen. For a complete 1285 * description see the protocol document of the RENDER library. */ 1286void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1287 PictFormatPtr maskFormat, 1288 INT16 xSrc, INT16 ySrc, 1289 int npoint, xPointFixed *points) 1290{ 1291 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1292 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1293 PictureScreenPtr ps = GetPictureScreen(pScreen); 1294 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); 1295 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); 1296 1297 DMX_UNWRAP(TriFan, dmxScreen, ps); 1298#if 0 1299 if (ps->TriFan) 1300 ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); 1301#endif 1302 1303 /* Draw trapezoids on back-end server */ 1304 if (pDstPriv->pict) { 1305 XRenderPictFormat *pFormat; 1306 1307 pFormat = dmxFindFormat(dmxScreen, maskFormat); 1308 if (!pFormat) { 1309 /* FIXME: Error! */ 1310 } 1311 1312 XRenderCompositeTriFan(dmxScreen->beDisplay, 1313 op, 1314 pSrcPriv->pict, 1315 pDstPriv->pict, 1316 pFormat, 1317 xSrc, ySrc, 1318 (XPointFixed *)points, 1319 npoint); 1320 dmxSync(dmxScreen, FALSE); 1321 } 1322 1323 DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); 1324} 1325