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