do_blt.c revision 533545b5
1/***************************************************************************** 2Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, and distribute this software and its 7documentation for any purpose and without fee is hereby granted, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Digital not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. 13 14DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20SOFTWARE. 21 22******************************************************************************/ 23 24#include "x11perf.h" 25#include <stdio.h> 26 27#define NUMPOINTS 100 28 29static Pixmap pix; 30static XImage *image; 31static XPoint points[NUMPOINTS]; 32static XSegment *segsa, *segsb; 33static XSegment *segsa2, *segsb2; 34 35#define NegMod(x, y) ((y) - (((-x)-1) % (7)) - 1) 36 37static void 38InitBltLines(void) 39{ 40 int i, x, y; 41 42 points[0].x = points[0].y = y = 0; 43 for (i = 1; i != NUMPOINTS/2; i++) { 44 if (i & 1) { 45 points[i].x = WIDTH-1; 46 } else { 47 points[i].x = 0; 48 } 49 y += HEIGHT / (NUMPOINTS/2); 50 points[i].y = y; 51 } 52 53 x = 0; 54 for (i = NUMPOINTS/2; i!= NUMPOINTS; i++) { 55 if (i & 1) { 56 points[i].y = HEIGHT-1; 57 } else { 58 points[i].y = 0; 59 } 60 x += WIDTH / (NUMPOINTS/2); 61 points[i].x = x; 62 } 63} 64 65int 66InitScroll(XParms xp, Parms p, int64_t reps) 67{ 68 InitBltLines(); 69 XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin); 70 return reps; 71} 72 73void 74DoScroll(XParms xp, Parms p, int64_t reps) 75{ 76 int i, size, x, y, xorg, yorg, delta; 77 78 size = p->special; 79 xorg = 0; yorg = 0; 80 x = 0; y = 0; 81 if (xp->version == VERSION1_2) { 82 delta = 1; 83 } else { 84 /* Version 1.2 only scrolled up by 1 scanline, which made hardware 85 using page-mode access to VRAM look better on paper than it would 86 perform in a more realistic scroll. So we've changed to scroll by 87 the height of the 6x13 fonts. */ 88 delta = 13; 89 } 90 91 for (i = 0; i != reps; i++) { 92 XCopyArea(xp->d, xp->w, xp->w, xp->fggc, x, y + delta, 93 size, size, x, y); 94 y += size; 95 if (y + size + delta > HEIGHT) { 96 yorg += delta; 97 if (yorg >= size || yorg + size + delta > HEIGHT) { 98 yorg = 0; 99 xorg++; 100 if (xorg >= size || xorg + size > WIDTH) { 101 xorg = 0; 102 } 103 } 104 y = yorg; 105 x += size; 106 if (x + size > WIDTH) { 107 x = xorg; 108 } 109 } 110 CheckAbort (); 111 } 112} 113 114void 115MidScroll(XParms xp, Parms p) 116{ 117 XClearWindow(xp->d, xp->w); 118 XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin); 119} 120 121void 122EndScroll(XParms xp, Parms p) 123{ 124} 125 126static void 127InitCopyLocations(int size, int mul, int div, 128 int64_t reps, XSegment **ap, XSegment **bp) 129{ 130 int x1, y1, x2, y2, i; 131 int xinc, yinc; 132 int width, height; 133 XSegment *a, *b; 134 135 size = size * mul / div; 136 /* Try to exercise all alignments of src and destination equally, as well 137 as all 4 top-to-bottom/bottom-to-top, left-to-right, right-to-left 138 copying directions. Computation done here just to make sure slow 139 machines aren't measuring anything but the XCopyArea calls. 140 */ 141 xinc = (size & ~3) + 1; 142 yinc = xinc + 3; 143 144 width = (WIDTH - size) & ~31; 145 height = (HEIGHT - size) & ~31; 146 147 x1 = 0; 148 y1 = 0; 149 x2 = width; 150 y2 = height; 151 152 *ap = a = (XSegment *)malloc(reps * sizeof(XSegment)); 153 *bp = b = (XSegment *)malloc(reps * sizeof(XSegment)); 154 for (i = 0; i != reps; i++) { 155 a[i].x1 = x1 * div / mul; 156 a[i].y1 = y1 * div / mul; 157 a[i].x2 = x2 * div / mul; 158 a[i].y2 = y2 * div / mul; 159 160 /* Move x2, y2, location backward */ 161 x2 -= xinc; 162 if (x2 < 0) { 163 x2 = NegMod(x2, width); 164 y2 -= yinc; 165 if (y2 < 0) { 166 y2 = NegMod(y2, height); 167 } 168 } 169 170 b[i].x1 = x1 * div / mul; 171 b[i].y1 = y1 * div / mul; 172 b[i].x2 = x2 * div / mul; 173 b[i].y2 = y2 * div / mul; 174 175 /* Move x1, y1 location forward */ 176 x1 += xinc; 177 if (x1 > width) { 178 x1 %= 32; 179 y1 += yinc; 180 if (y1 > height) { 181 y1 %= 32; 182 } 183 } 184 } /* end for */ 185} 186 187 188int 189InitCopyWin(XParms xp, Parms p, int64_t reps) 190{ 191 (void) InitScroll(xp, p, reps); 192 InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb); 193 return reps; 194} 195 196int 197InitCopyPix(XParms xp, Parms p, int64_t reps) 198{ 199 GC pixgc; 200 (void) InitCopyWin(xp, p, reps); 201 202 /* Create pixmap to write stuff into, and initialize it */ 203 pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, xp->vinfo.depth); 204 pixgc = XCreateGC(xp->d, pix, 0, NULL); 205 /* need a gc with GXcopy cos pixmaps contain junk on creation. mmm */ 206 XCopyArea(xp->d, xp->w, pix, pixgc, 0, 0, WIDTH, HEIGHT, 0, 0); 207 XFreeGC(xp->d, pixgc); 208 return reps; 209} 210 211int 212InitGetImage(XParms xp, Parms p, int64_t reps) 213{ 214 (void) InitCopyWin(xp, p, reps); 215 216 /* Create image to stuff bits into */ 217 image = XGetImage(xp->d, xp->w, 0, 0, WIDTH, HEIGHT, xp->planemask, 218 p->font==NULL?ZPixmap:XYPixmap); 219 if(image==NULL){ 220 printf("XGetImage failed\n"); 221 return False; 222 } 223 return reps; 224} 225 226int 227InitPutImage(XParms xp, Parms p, int64_t reps) 228{ 229 if(!InitGetImage(xp, p, reps))return False; 230 XClearWindow(xp->d, xp->w); 231 return reps; 232} 233 234static void 235CopyArea(XParms xp, Parms p, int64_t reps, Drawable src, Drawable dst) 236{ 237 int i, size; 238 XSegment *sa, *sb; 239 240 size = p->special; 241 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 242 XCopyArea(xp->d, src, dst, xp->fggc, 243 sa->x1, sa->y1, size, size, sa->x2, sa->y2); 244 XCopyArea(xp->d, src, dst, xp->fggc, 245 sa->x2, sa->y2, size, size, sa->x1, sa->y1); 246 XCopyArea(xp->d, src, dst, xp->fggc, 247 sb->x2, sb->y2, size, size, sb->x1, sb->y1); 248 XCopyArea(xp->d, src, dst, xp->fggc, 249 sb->x1, sb->y1, size, size, sb->x2, sb->y2); 250 CheckAbort (); 251 } 252} 253 254void 255DoCopyWinWin(XParms xp, Parms p, int64_t reps) 256{ 257 CopyArea(xp, p, reps, xp->w, xp->w); 258} 259 260void 261DoCopyPixWin(XParms xp, Parms p, int64_t reps) 262{ 263 CopyArea(xp, p, reps, pix, xp->w); 264} 265 266void 267DoCopyWinPix(XParms xp, Parms p, int64_t reps) 268{ 269 CopyArea(xp, p, reps, xp->w, pix); 270 xp->p = pix; /* HardwareSync will now sync on pixmap */ 271} 272 273void 274DoCopyPixPix(XParms xp, Parms p, int64_t reps) 275{ 276 CopyArea(xp, p, reps, pix, pix); 277 xp->p = pix; /* HardwareSync will now sync on pixmap */ 278} 279 280void 281DoGetImage(XParms xp, Parms p, int64_t reps) 282{ 283 int i, size; 284 XSegment *sa, *sb; 285 int format; 286 287 size = p->special; 288 format = (p->font == NULL) ? ZPixmap : XYPixmap; 289 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 290 XDestroyImage(image); 291 image = XGetImage(xp->d, xp->w, sa->x1, sa->y1, size, size, 292 xp->planemask, format); 293 if (image) XDestroyImage(image); 294 image = XGetImage(xp->d, xp->w, sa->x2, sa->y2, size, size, 295 xp->planemask, format); 296 if (image) XDestroyImage(image); 297 image = XGetImage(xp->d, xp->w, sb->x2, sb->y2, size, size, 298 xp->planemask, format); 299 if (image) XDestroyImage(image); 300 image = XGetImage(xp->d, xp->w, sb->x1, sb->y1, size, size, 301 xp->planemask, format); 302/* 303 304One might expect XGetSubImage to be slightly faster than XGetImage. Go look 305at the code in Xlib. MIT X11R3 ran approximately 30 times slower for a 500x500 306rectangle. 307 308 (void) XGetSubImage(xp->d, xp->w, sa->x1, sa->y1, size, size, 309 xp->planemask, ZPixmap, image, sa->x2, sa->y2); 310 (void) XGetSubImage(xp->d, xp->w, sa->x2, sa->y2, size, size, 311 xp->planemask, ZPixmap, image, sa->x1, sa->y1); 312 (void) XGetSubImage(xp->d, xp->w, sb->x2, sb->y2, size, size, 313 xp->planemask, ZPixmap, image, sb->x2, sb->y2); 314 (void) XGetSubImage(xp->d, xp->w, sb->x1, sb->y1, size, size, 315 xp->planemask, ZPixmap, image, sb->x2, sb->y2); 316*/ 317 CheckAbort (); 318 } 319} 320 321void 322DoPutImage(XParms xp, Parms p, int64_t reps) 323{ 324 int i, size; 325 XSegment *sa, *sb; 326 327 size = p->special; 328 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 329 XPutImage(xp->d, xp->w, xp->fggc, image, 330 sa->x1, sa->y1, sa->x2, sa->y2, size, size); 331 XPutImage(xp->d, xp->w, xp->fggc, image, 332 sa->x2, sa->y2, sa->x1, sa->y1, size, size); 333 XPutImage(xp->d, xp->w, xp->fggc, image, 334 sb->x2, sb->y2, sb->x2, sb->y2, size, size); 335 XPutImage(xp->d, xp->w, xp->fggc, image, 336 sb->x1, sb->y1, sb->x2, sb->y2, size, size); 337 CheckAbort (); 338 } 339} 340 341#ifdef MITSHM 342 343#include <sys/types.h> 344#ifndef Lynx 345#include <sys/ipc.h> 346#include <sys/shm.h> 347#else 348#include <ipc.h> 349#include <shm.h> 350#endif 351#include <X11/extensions/XShm.h> 352 353static XImage shm_image; 354static XShmSegmentInfo shm_info; 355 356static int haderror; 357static int (*origerrorhandler)(Display *, XErrorEvent *); 358 359static int 360shmerrorhandler(Display *d, XErrorEvent *e) 361{ 362 haderror++; 363 if(e->error_code==BadAccess) { 364 fprintf(stderr,"failed to attach shared memory\n"); 365 return 0; 366 } else 367 return (*origerrorhandler)(d,e); 368} 369 370static int 371InitShmImage(XParms xp, Parms p, int64_t reps, Bool read_only) 372{ 373 int image_size; 374 375 if(!InitGetImage(xp, p, reps))return False; 376 if (!XShmQueryExtension(xp->d)) { 377 /* 378 * Clean up here because cleanup function is not called if this 379 * function fails 380 */ 381 if (image) 382 XDestroyImage(image); 383 image = NULL; 384 free(segsa); 385 free(segsb); 386 return False; 387 } 388 shm_image = *image; 389 image_size = image->bytes_per_line * image->height; 390 /* allow XYPixmap choice: */ 391 if(p->font)image_size *= xp->vinfo.depth; 392 shm_info.shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777); 393 if (shm_info.shmid < 0) 394 { 395 /* 396 * Clean up here because cleanup function is not called if this 397 * function fails 398 */ 399 if (image) 400 XDestroyImage(image); 401 image = NULL; 402 free(segsa); 403 free(segsb); 404 perror ("shmget"); 405 return False; 406 } 407 shm_info.shmaddr = (char *) shmat(shm_info.shmid, NULL, 0); 408 if (shm_info.shmaddr == ((char *) -1)) 409 { 410 /* 411 * Clean up here because cleanup function is not called if this 412 * function fails 413 */ 414 if (image) 415 XDestroyImage(image); 416 image = NULL; 417 free(segsa); 418 free(segsb); 419 perror ("shmat"); 420 shmctl (shm_info.shmid, IPC_RMID, NULL); 421 return False; 422 } 423 shm_info.readOnly = read_only; 424 XSync(xp->d,True); 425 haderror = False; 426 origerrorhandler = XSetErrorHandler(shmerrorhandler); 427 XShmAttach (xp->d, &shm_info); 428 XSync(xp->d,True); /* wait for error or ok */ 429 XSetErrorHandler(origerrorhandler); 430 if(haderror){ 431 /* 432 * Clean up here because cleanup function is not called if this 433 * function fails 434 */ 435 if (image) 436 XDestroyImage(image); 437 image = NULL; 438 free(segsa); 439 free(segsb); 440 if(shmdt (shm_info.shmaddr)==-1) 441 perror("shmdt:"); 442 if(shmctl (shm_info.shmid, IPC_RMID, NULL)==-1) 443 perror("shmctl rmid:"); 444 return False; 445 } 446 shm_image.data = shm_info.shmaddr; 447 memmove( shm_image.data, image->data, image_size); 448 shm_image.obdata = (char *) &shm_info; 449 return reps; 450} 451 452int 453InitShmPutImage(XParms xp, Parms p, int64_t reps) 454{ 455 if (!InitShmImage(xp, p, reps, True)) return False; 456 XClearWindow(xp->d, xp->w); 457 return reps; 458} 459 460int 461InitShmGetImage(XParms xp, Parms p, int64_t reps) 462{ 463 return InitShmImage(xp, p, reps, False); 464} 465 466void 467DoShmPutImage(XParms xp, Parms p, int64_t reps) 468{ 469 int i, size; 470 XSegment *sa, *sb; 471 472 size = p->special; 473 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 474 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 475 sa->x1, sa->y1, sa->x2, sa->y2, size, size, False); 476 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 477 sa->x2, sa->y2, sa->x1, sa->y1, size, size, False); 478 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 479 sb->x2, sb->y2, sb->x2, sb->y2, size, size, False); 480 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 481 sb->x1, sb->y1, sb->x2, sb->y2, size, size, False); 482 CheckAbort (); 483 } 484} 485 486void 487DoShmGetImage(XParms xp, Parms p, int64_t reps) 488{ 489 int i, size; 490 XSegment *sa, *sb; 491 492 size = p->special; 493 494 shm_image.width = size; 495 shm_image.height = size; 496 497 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 498 /* compute offsets into image data? */ 499 XShmGetImage(xp->d, xp->w, &shm_image, sa->x1, sa->y1, xp->planemask); 500 XShmGetImage(xp->d, xp->w, &shm_image, sa->x2, sa->y2, xp->planemask); 501 XShmGetImage(xp->d, xp->w, &shm_image, sb->x2, sb->y2, xp->planemask); 502 XShmGetImage(xp->d, xp->w, &shm_image, sb->x1, sb->y1, xp->planemask); 503 CheckAbort (); 504 } 505} 506 507static void 508EndShmImage(XParms xp, Parms p) 509{ 510 EndGetImage (xp, p); 511 XShmDetach (xp->d, &shm_info); 512 XSync(xp->d, False); /* need server to detach so can remove id */ 513 if(shmdt (shm_info.shmaddr)==-1) 514 perror("shmdt:"); 515 if(shmctl (shm_info.shmid, IPC_RMID, NULL)==-1) 516 perror("shmctl rmid:"); 517} 518 519void 520EndShmGetImage(XParms xp, Parms p) 521{ 522 EndShmImage(xp, p); 523} 524 525void 526EndShmPutImage(XParms xp, Parms p) 527{ 528 EndShmImage(xp, p); 529} 530#endif 531 532 533void 534MidCopyPix(XParms xp, Parms p) 535{ 536 XClearWindow(xp->d, xp->w); 537} 538 539void 540EndCopyWin(XParms xp, Parms p) 541{ 542 EndScroll(xp, p); 543 free(segsa); 544 free(segsb); 545 if (segsa2) 546 free (segsa2); 547 if (segsb2) 548 free (segsb2); 549 segsa = segsb = segsa2 = segsb2 = NULL; 550} 551 552void 553EndCopyPix(XParms xp, Parms p) 554{ 555 EndCopyWin(xp, p); 556 XFreePixmap(xp->d, pix); 557 /* 558 * Ensure that the next test doesn't try and sync on the pixmap 559 */ 560 xp->p = (Pixmap)0; 561} 562 563void 564EndGetImage(XParms xp, Parms p) 565{ 566 EndCopyWin(xp, p); 567 if (image) XDestroyImage(image); 568} 569 570int 571InitCopyPlane(XParms xp, Parms p, int64_t reps) 572{ 573 XGCValues gcv; 574 GC pixgc; 575 576 InitBltLines(); 577 InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb); 578 579 /* Create pixmap to write stuff into, and initialize it */ 580 pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, 581 p->font==NULL ? 1 : xp->vinfo.depth); 582 gcv.graphics_exposures = False; 583 gcv.foreground = 0; 584 gcv.background = 1; 585 pixgc = XCreateGC(xp->d, pix, 586 GCForeground | GCBackground | GCGraphicsExposures, &gcv); 587 XFillRectangle(xp->d, pix, pixgc, 0, 0, WIDTH, HEIGHT); 588 gcv.foreground = 1; 589 gcv.background = 0; 590 XChangeGC(xp->d, pixgc, GCForeground | GCBackground, &gcv); 591 XDrawLines(xp->d, pix, pixgc, points, NUMPOINTS, CoordModeOrigin); 592 XFreeGC(xp->d, pixgc); 593 594 return reps; 595} 596 597void 598DoCopyPlane(XParms xp, Parms p, int64_t reps) 599{ 600 int i, size; 601 XSegment *sa, *sb; 602 603 size = p->special; 604 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 605 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 606 sa->x1, sa->y1, size, size, sa->x2, sa->y2, 1); 607 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 608 sa->x2, sa->y2, size, size, sa->x1, sa->y1, 1); 609 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 610 sb->x2, sb->y2, size, size, sb->x1, sb->y1, 1); 611 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 612 sb->x1, sb->y1, size, size, sb->x2, sb->y2, 1); 613 CheckAbort (); 614 } 615} 616 617#include <X11/extensions/Xrender.h> 618 619static Picture winPict, pixPict; 620 621int 622InitCompositeWin(XParms xp, Parms p, int64_t reps) 623{ 624 XRenderPictFormat *format; 625 626 (void) InitScroll (xp, p, reps); 627 InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb); 628 if (p->fillStyle) { 629 int mul = 0x10000; 630 int div = p->fillStyle; 631 InitCopyLocations (p->special, mul, div, reps, &segsa2, &segsb2); 632 } 633 format = XRenderFindVisualFormat (xp->d, xp->vinfo.visual); 634 winPict = XRenderCreatePicture (xp->d, xp->w, format, 0, NULL); 635 return reps; 636} 637 638int 639InitCompositePix(XParms xp, Parms p, int64_t reps) 640{ 641 XRenderPictFormat *format = NULL; 642 int depth; 643 static XRenderColor c = { 0xffff, 0x0000, 0xffff, 0xffff }; 644 645 (void) InitCompositeWin (xp, p, reps); 646 647 /* Create pixmap to write stuff into, and initialize it */ 648 switch (xp->planemask) { 649 case PictStandardNative: 650 depth = xp->vinfo.depth; 651 format = XRenderFindVisualFormat (xp->d, xp->vinfo.visual); 652 break; 653 case PictStandardRGB24: 654 depth = 24; 655 break; 656 case PictStandardARGB32: 657 depth = 32; 658 break; 659 case PictStandardA8: 660 depth = 8; 661 break; 662 case PictStandardA4: 663 depth = 4; 664 break; 665 case PictStandardA1: 666 depth = 1; 667 break; 668 default: 669 depth = 0; 670 break; 671 } 672 if (!format) 673 format = XRenderFindStandardFormat (xp->d, xp->planemask); 674 675 pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, depth); 676 pixPict = XRenderCreatePicture (xp->d, pix, format, 0, NULL); 677 678 XRenderComposite (xp->d, PictOpClear, 679 winPict, None, pixPict, 680 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); 681 682 XRenderFillRectangle (xp->d, PictOpSrc, 683 pixPict, &c, 0, 0, WIDTH, HEIGHT); 684#if 1 685 XRenderComposite (xp->d, PictOpSrc, 686 winPict, None, pixPict, 687 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); 688#endif 689 if (p->fillStyle) { 690 XTransform transform; 691 memset (&transform, '\0', sizeof (transform)); 692 transform.matrix[0][0] = ((long long) 0x10000 * 0x10000) / p->fillStyle; 693 transform.matrix[1][1] = ((long long) 0x10000 * 0x10000) / p->fillStyle; 694 transform.matrix[2][2] = 0x10000; 695 XRenderSetPictureTransform (xp->d, pixPict, &transform); 696 XRenderSetPictureFilter (xp->d, pixPict, FilterBilinear, NULL, 0); 697 } 698 return reps; 699} 700 701void 702EndCompositeWin (XParms xp, Parms p) 703{ 704 if (winPict) 705 { 706 XRenderFreePicture (xp->d, winPict); 707 winPict = None; 708 } 709 if (pixPict) 710 { 711 XRenderFreePicture (xp->d, pixPict); 712 pixPict = None; 713 } 714} 715 716static void 717CompositeArea(XParms xp, Parms p, int64_t reps, Picture src, Picture dst) 718{ 719 int i, size; 720 XSegment *sa, *sb; 721 XSegment *sa2, *sb2; 722 723 724 size = p->special; 725 sa = segsa; 726 sb = segsb; 727 sa2 = segsa2 ? segsa2 : segsa; 728 sb2 = segsb2 ? segsb2 : segsb; 729 for (i = 0; i < reps; i++) { 730 XRenderComposite (xp->d, xp->func, 731 src, None, dst, 732 sa2->x1, sa2->y1, 0, 0, sa->x2, sa->y2, size, size); 733 XRenderComposite (xp->d, xp->func, 734 src, None, dst, 735 sa2->x2, sa2->y2, 0, 0, sa->x1, sa->y1, size, size); 736 XRenderComposite (xp->d, xp->func, 737 src, None, dst, 738 sb2->x2, sb2->y2, 0, 0, sb->x1, sb->y1, size, size); 739 XRenderComposite (xp->d, xp->func, 740 src, None, dst, 741 sb2->x1, sb2->y1, 0, 0, sb->x2, sb->y2, size, size); 742 CheckAbort (); 743 sa++; sb++; 744 sa2++; sb2++; 745 } 746} 747 748void 749DoCompositeWinWin (XParms xp, Parms p, int64_t reps) 750{ 751 CompositeArea (xp, p, reps, winPict, winPict); 752} 753 754void 755DoCompositePixWin (XParms xp, Parms p, int64_t reps) 756{ 757 CompositeArea (xp, p, reps, pixPict, winPict); 758} 759