do_blt.c revision 264fa531
1/* $Xorg: do_blt.c,v 1.3 2000/08/17 19:54:09 cpqbld Exp $ */ 2/***************************************************************************** 3Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 4 5 All Rights Reserved 6 7Permission to use, copy, modify, and distribute this software and its 8documentation for any purpose and without fee is hereby granted, 9provided that the above copyright notice appear in all copies and that 10both that copyright notice and this permission notice appear in 11supporting documentation, and that the name of Digital not be 12used in advertising or publicity pertaining to distribution of the 13software without specific, written prior permission. 14 15DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 16ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 17DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 18ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 19WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 20ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 21SOFTWARE. 22 23******************************************************************************/ 24/* $XFree86: xc/programs/x11perf/do_blt.c,v 1.8 2001/05/01 16:19:16 alanh Exp $ */ 25 26#include "x11perf.h" 27#include <stdio.h> 28 29#define NUMPOINTS 100 30 31static Pixmap pix; 32static XImage *image; 33static XPoint points[NUMPOINTS]; 34static XSegment *segsa, *segsb; 35 36#define NegMod(x, y) ((y) - (((-x)-1) % (7)) - 1) 37 38static void 39InitBltLines(void) 40{ 41 int i, x, y; 42 43 points[0].x = points[0].y = y = 0; 44 for (i = 1; i != NUMPOINTS/2; i++) { 45 if (i & 1) { 46 points[i].x = WIDTH-1; 47 } else { 48 points[i].x = 0; 49 } 50 y += HEIGHT / (NUMPOINTS/2); 51 points[i].y = y; 52 } 53 54 x = 0; 55 for (i = NUMPOINTS/2; i!= NUMPOINTS; i++) { 56 if (i & 1) { 57 points[i].y = HEIGHT-1; 58 } else { 59 points[i].y = 0; 60 } 61 x += WIDTH / (NUMPOINTS/2); 62 points[i].x = x; 63 } 64} 65 66int 67InitScroll(XParms xp, Parms p, int reps) 68{ 69 InitBltLines(); 70 XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin); 71 return reps; 72} 73 74void 75DoScroll(XParms xp, Parms p, int reps) 76{ 77 int i, size, x, y, xorg, yorg, delta; 78 79 size = p->special; 80 xorg = 0; yorg = 0; 81 x = 0; y = 0; 82 if (xp->version == VERSION1_2) { 83 delta = 1; 84 } else { 85 /* Version 1.2 only scrolled up by 1 scanline, which made hardware 86 using page-mode access to VRAM look better on paper than it would 87 perform in a more realistic scroll. So we've changed to scroll by 88 the height of the 6x13 fonts. */ 89 delta = 13; 90 } 91 92 for (i = 0; i != reps; i++) { 93 XCopyArea(xp->d, xp->w, xp->w, xp->fggc, x, y + delta, 94 size, size, x, y); 95 y += size; 96 if (y + size + delta > HEIGHT) { 97 yorg += delta; 98 if (yorg >= size || yorg + size + delta > HEIGHT) { 99 yorg = 0; 100 xorg++; 101 if (xorg >= size || xorg + size > WIDTH) { 102 xorg = 0; 103 } 104 } 105 y = yorg; 106 x += size; 107 if (x + size > WIDTH) { 108 x = xorg; 109 } 110 } 111 CheckAbort (); 112 } 113} 114 115void 116MidScroll(XParms xp, Parms p) 117{ 118 XClearWindow(xp->d, xp->w); 119 XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin); 120} 121 122void 123EndScroll(XParms xp, Parms p) 124{ 125} 126 127static void 128InitCopyLocations(XParms xp, Parms p, int reps) 129{ 130 int x1, y1, x2, y2, size, i; 131 int xinc, yinc; 132 int width, height; 133 134 /* Try to exercise all alignments of src and destination equally, as well 135 as all 4 top-to-bottom/bottom-to-top, left-to-right, right-to-left 136 copying directions. Computation done here just to make sure slow 137 machines aren't measuring anything but the XCopyArea calls. 138 */ 139 size = p->special; 140 xinc = (size & ~3) + 1; 141 yinc = xinc + 3; 142 143 width = (WIDTH - size) & ~31; 144 height = (HEIGHT - size) & ~31; 145 146 x1 = 0; 147 y1 = 0; 148 x2 = width; 149 y2 = height; 150 151 segsa = (XSegment *)malloc(reps * sizeof(XSegment)); 152 segsb = (XSegment *)malloc(reps * sizeof(XSegment)); 153 for (i = 0; i != reps; i++) { 154 segsa[i].x1 = x1; 155 segsa[i].y1 = y1; 156 segsa[i].x2 = x2; 157 segsa[i].y2 = y2; 158 159 /* Move x2, y2, location backward */ 160 x2 -= xinc; 161 if (x2 < 0) { 162 x2 = NegMod(x2, width); 163 y2 -= yinc; 164 if (y2 < 0) { 165 y2 = NegMod(y2, height); 166 } 167 } 168 169 segsb[i].x1 = x1; 170 segsb[i].y1 = y1; 171 segsb[i].x2 = x2; 172 segsb[i].y2 = y2; 173 174 /* Move x1, y1 location forward */ 175 x1 += xinc; 176 if (x1 > width) { 177 x1 %= 32; 178 y1 += yinc; 179 if (y1 > height) { 180 y1 %= 32; 181 } 182 } 183 } /* end for */ 184} 185 186 187int 188InitCopyWin(XParms xp, Parms p, int reps) 189{ 190 (void) InitScroll(xp, p, reps); 191 InitCopyLocations(xp, p, reps); 192 return reps; 193} 194 195int 196InitCopyPix(XParms xp, Parms p, int reps) 197{ 198 GC pixgc; 199 (void) InitCopyWin(xp, p, reps); 200 201 /* Create pixmap to write stuff into, and initialize it */ 202 pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, xp->vinfo.depth); 203 pixgc = XCreateGC(xp->d, pix, 0, 0); 204 /* need a gc with GXcopy cos pixmaps contain junk on creation. mmm */ 205 XCopyArea(xp->d, xp->w, pix, pixgc, 0, 0, WIDTH, HEIGHT, 0, 0); 206 XFreeGC(xp->d, pixgc); 207 return reps; 208} 209 210int 211InitGetImage(XParms xp, Parms p, int reps) 212{ 213 (void) InitCopyWin(xp, p, reps); 214 215 /* Create image to stuff bits into */ 216 image = XGetImage(xp->d, xp->w, 0, 0, WIDTH, HEIGHT, xp->planemask, 217 p->font==0?ZPixmap:XYPixmap); 218 if(image==0){ 219 printf("XGetImage failed\n"); 220 return False; 221 } 222 return reps; 223} 224 225int 226InitPutImage(XParms xp, Parms p, int reps) 227{ 228 if(!InitGetImage(xp, p, reps))return False; 229 XClearWindow(xp->d, xp->w); 230 return reps; 231} 232 233static void 234CopyArea(XParms xp, Parms p, int reps, Drawable src, Drawable dst) 235{ 236 int i, size; 237 XSegment *sa, *sb; 238 239 size = p->special; 240 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 241 XCopyArea(xp->d, src, dst, xp->fggc, 242 sa->x1, sa->y1, size, size, sa->x2, sa->y2); 243 XCopyArea(xp->d, src, dst, xp->fggc, 244 sa->x2, sa->y2, size, size, sa->x1, sa->y1); 245 XCopyArea(xp->d, src, dst, xp->fggc, 246 sb->x2, sb->y2, size, size, sb->x1, sb->y1); 247 XCopyArea(xp->d, src, dst, xp->fggc, 248 sb->x1, sb->y1, size, size, sb->x2, sb->y2); 249 CheckAbort (); 250 } 251} 252 253void 254DoCopyWinWin(XParms xp, Parms p, int reps) 255{ 256 CopyArea(xp, p, reps, xp->w, xp->w); 257} 258 259void 260DoCopyPixWin(XParms xp, Parms p, int reps) 261{ 262 CopyArea(xp, p, reps, pix, xp->w); 263} 264 265void 266DoCopyWinPix(XParms xp, Parms p, int reps) 267{ 268 CopyArea(xp, p, reps, xp->w, pix); 269 xp->p = pix; /* HardwareSync will now sync on pixmap */ 270} 271 272void 273DoCopyPixPix(XParms xp, Parms p, int reps) 274{ 275 CopyArea(xp, p, reps, pix, pix); 276 xp->p = pix; /* HardwareSync will now sync on pixmap */ 277} 278 279void 280DoGetImage(XParms xp, Parms p, int reps) 281{ 282 int i, size; 283 XSegment *sa, *sb; 284 int format; 285 286 size = p->special; 287 format = (p->font == 0) ? ZPixmap : XYPixmap; 288 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 289 XDestroyImage(image); 290 image = XGetImage(xp->d, xp->w, sa->x1, sa->y1, size, size, 291 xp->planemask, format); 292 if (image) XDestroyImage(image); 293 image = XGetImage(xp->d, xp->w, sa->x2, sa->y2, size, size, 294 xp->planemask, format); 295 if (image) XDestroyImage(image); 296 image = XGetImage(xp->d, xp->w, sb->x2, sb->y2, size, size, 297 xp->planemask, format); 298 if (image) XDestroyImage(image); 299 image = XGetImage(xp->d, xp->w, sb->x1, sb->y1, size, size, 300 xp->planemask, format); 301/* 302 303One might expect XGetSubImage to be slightly faster than XGetImage. Go look 304at the code in Xlib. MIT X11R3 ran approximately 30 times slower for a 500x500 305rectangle. 306 307 (void) XGetSubImage(xp->d, xp->w, sa->x1, sa->y1, size, size, 308 xp->planemask, ZPixmap, image, sa->x2, sa->y2); 309 (void) XGetSubImage(xp->d, xp->w, sa->x2, sa->y2, size, size, 310 xp->planemask, ZPixmap, image, sa->x1, sa->y1); 311 (void) XGetSubImage(xp->d, xp->w, sb->x2, sb->y2, size, size, 312 xp->planemask, ZPixmap, image, sb->x2, sb->y2); 313 (void) XGetSubImage(xp->d, xp->w, sb->x1, sb->y1, size, size, 314 xp->planemask, ZPixmap, image, sb->x2, sb->y2); 315*/ 316 CheckAbort (); 317 } 318} 319 320void 321DoPutImage(XParms xp, Parms p, int reps) 322{ 323 int i, size; 324 XSegment *sa, *sb; 325 326 size = p->special; 327 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 328 XPutImage(xp->d, xp->w, xp->fggc, image, 329 sa->x1, sa->y1, sa->x2, sa->y2, size, size); 330 XPutImage(xp->d, xp->w, xp->fggc, image, 331 sa->x2, sa->y2, sa->x1, sa->y1, size, size); 332 XPutImage(xp->d, xp->w, xp->fggc, image, 333 sb->x2, sb->y2, sb->x2, sb->y2, size, size); 334 XPutImage(xp->d, xp->w, xp->fggc, image, 335 sb->x1, sb->y1, sb->x2, sb->y2, size, size); 336 CheckAbort (); 337 } 338} 339 340#ifdef MITSHM 341 342#include <sys/types.h> 343#ifndef Lynx 344#include <sys/ipc.h> 345#include <sys/shm.h> 346#else 347#include <ipc.h> 348#include <shm.h> 349#endif 350#include <X11/extensions/XShm.h> 351 352static XImage shm_image; 353static XShmSegmentInfo shm_info; 354 355static int haderror; 356static int (*origerrorhandler)(Display *, XErrorEvent *); 357 358static int 359shmerrorhandler(Display *d, XErrorEvent *e) 360{ 361 haderror++; 362 if(e->error_code==BadAccess) { 363 fprintf(stderr,"failed to attach shared memory\n"); 364 return 0; 365 } else 366 return (*origerrorhandler)(d,e); 367} 368 369int 370InitShmPutImage(XParms xp, Parms p, int reps) 371{ 372 int image_size; 373 374 if(!InitGetImage(xp, p, reps))return False; 375 if (!XShmQueryExtension(xp->d)) { 376 /* 377 * Clean up here because cleanup function is not called if this 378 * function fails 379 */ 380 if (image) 381 XDestroyImage(image); 382 image = NULL; 383 free(segsa); 384 free(segsb); 385 return False; 386 } 387 XClearWindow(xp->d, xp->w); 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, 0, 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, 0); 421 return False; 422 } 423 shm_info.readOnly = True; 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, 0)==-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 452void 453DoShmPutImage(XParms xp, Parms p, int reps) 454{ 455 int i, size; 456 XSegment *sa, *sb; 457 458 size = p->special; 459 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 460 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 461 sa->x1, sa->y1, sa->x2, sa->y2, size, size, False); 462 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 463 sa->x2, sa->y2, sa->x1, sa->y1, size, size, False); 464 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 465 sb->x2, sb->y2, sb->x2, sb->y2, size, size, False); 466 XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, 467 sb->x1, sb->y1, sb->x2, sb->y2, size, size, False); 468 CheckAbort (); 469 } 470} 471 472void 473EndShmPutImage(XParms xp, Parms p) 474{ 475 476 EndGetImage (xp, p); 477 XShmDetach (xp->d, &shm_info); 478 XSync(xp->d, False); /* need server to detach so can remove id */ 479 if(shmdt (shm_info.shmaddr)==-1) 480 perror("shmdt:"); 481 if(shmctl (shm_info.shmid, IPC_RMID, 0)==-1) 482 perror("shmctl rmid:"); 483} 484 485#endif 486 487 488void 489MidCopyPix(XParms xp, Parms p) 490{ 491 XClearWindow(xp->d, xp->w); 492} 493 494void 495EndCopyWin(XParms xp, Parms p) 496{ 497 EndScroll(xp, p); 498 free(segsa); 499 free(segsb); 500} 501 502void 503EndCopyPix(XParms xp, Parms p) 504{ 505 EndCopyWin(xp, p); 506 XFreePixmap(xp->d, pix); 507 /* 508 * Ensure that the next test doesn't try and sync on the pixmap 509 */ 510 xp->p = (Pixmap)0; 511} 512 513void 514EndGetImage(XParms xp, Parms p) 515{ 516 EndCopyWin(xp, p); 517 if (image) XDestroyImage(image); 518} 519 520int 521InitCopyPlane(XParms xp, Parms p, int reps) 522{ 523 XGCValues gcv; 524 GC pixgc; 525 526 InitBltLines(); 527 InitCopyLocations(xp, p, reps); 528 529 /* Create pixmap to write stuff into, and initialize it */ 530 pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, 531 p->font==0 ? 1 : xp->vinfo.depth); 532 gcv.graphics_exposures = False; 533 gcv.foreground = 0; 534 gcv.background = 1; 535 pixgc = XCreateGC(xp->d, pix, 536 GCForeground | GCBackground | GCGraphicsExposures, &gcv); 537 XFillRectangle(xp->d, pix, pixgc, 0, 0, WIDTH, HEIGHT); 538 gcv.foreground = 1; 539 gcv.background = 0; 540 XChangeGC(xp->d, pixgc, GCForeground | GCBackground, &gcv); 541 XDrawLines(xp->d, pix, pixgc, points, NUMPOINTS, CoordModeOrigin); 542 XFreeGC(xp->d, pixgc); 543 544 return reps; 545} 546 547void 548DoCopyPlane(XParms xp, Parms p, int reps) 549{ 550 int i, size; 551 XSegment *sa, *sb; 552 553 size = p->special; 554 for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { 555 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 556 sa->x1, sa->y1, size, size, sa->x2, sa->y2, 1); 557 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 558 sa->x2, sa->y2, size, size, sa->x1, sa->y1, 1); 559 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 560 sb->x2, sb->y2, size, size, sb->x1, sb->y1, 1); 561 XCopyPlane(xp->d, pix, xp->w, xp->fggc, 562 sb->x1, sb->y1, size, size, sb->x2, sb->y2, 1); 563 CheckAbort (); 564 } 565} 566 567