diff options
Diffstat (limited to 'do_blt.c')
-rw-r--r-- | do_blt.c | 594 |
1 files changed, 594 insertions, 0 deletions
diff --git a/do_blt.c b/do_blt.c new file mode 100644 index 0000000..5182816 --- /dev/null +++ b/do_blt.c @@ -0,0 +1,594 @@ +/* $Xorg: do_blt.c,v 1.4 2000/11/30 12:16:31 pookie Exp $ */ +/***************************************************************************** +Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************************/ + +#include "x11perf.h" +#include <stdio.h> + +#define NUMPOINTS 100 + +static Pixmap pix; +static XImage *image; +static XPoint points[NUMPOINTS]; +static XSegment *segsa, *segsb; + +#define NegMod(x, y) ((y) - (((-x)-1) % (7)) - 1) + +void InitBltLines() +{ + int i, x, y; + + points[0].x = points[0].y = y = 0; + for (i = 1; i != NUMPOINTS/2; i++) { + if (i & 1) { + points[i].x = WIDTH-1; + } else { + points[i].x = 0; + } + y += HEIGHT / (NUMPOINTS/2); + points[i].y = y; + } + + x = 0; + for (i = NUMPOINTS/2; i!= NUMPOINTS; i++) { + if (i & 1) { + points[i].y = HEIGHT-1; + } else { + points[i].y = 0; + } + x += WIDTH / (NUMPOINTS/2); + points[i].x = x; + } +} + +int InitScroll(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + InitBltLines(); + XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin); + return reps; +} + +void DoScroll(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int i, size, x, y, xorg, yorg, delta; + + size = p->special; + xorg = 0; yorg = 0; + x = 0; y = 0; + if (xp->version == VERSION1_2) { + delta = 1; + } else { + /* Version 1.2 only scrolled up by 1 scanline, which made hardware + using page-mode access to VRAM look better on paper than it would + perform in a more realistic scroll. So we've changed to scroll by + the height of the 6x13 fonts. */ + delta = 13; + } + + for (i = 0; i != reps; i++) { + XCopyArea(xp->d, xp->w, xp->w, xp->fggc, x, y + delta, + size, size, x, y); + y += size; + if (y + size + delta > HEIGHT) { + yorg += delta; + if (yorg >= size || yorg + size + delta > HEIGHT) { + yorg = 0; + xorg++; + if (xorg >= size || xorg + size > WIDTH) { + xorg = 0; + } + } + y = yorg; + x += size; + if (x + size > WIDTH) { + x = xorg; + } + } + } +} + +void MidScroll(xp, p) + XParms xp; + Parms p; +{ + XClearWindow(xp->d, xp->w); + XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin); +} + +void EndScroll(xp, p) + XParms xp; + Parms p; +{ +} + +static void InitCopyLocations(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int x1, y1, x2, y2, size, i; + int xinc, yinc; + int width, height; + + /* Try to exercise all alignments of src and destination equally, as well + as all 4 top-to-bottom/bottom-to-top, left-to-right, right-to-left + copying directions. Computation done here just to make sure slow + machines aren't measuring anything but the XCopyArea calls. + */ + size = p->special; + xinc = (size & ~3) + 1; + yinc = xinc + 3; + + width = (WIDTH - size) & ~31; + height = (HEIGHT - size) & ~31; + + x1 = 0; + y1 = 0; + x2 = width; + y2 = height; + + segsa = (XSegment *)malloc(reps * sizeof(XSegment)); + segsb = (XSegment *)malloc(reps * sizeof(XSegment)); + for (i = 0; i != reps; i++) { + segsa[i].x1 = x1; + segsa[i].y1 = y1; + segsa[i].x2 = x2; + segsa[i].y2 = y2; + + /* Move x2, y2, location backward */ + x2 -= xinc; + if (x2 < 0) { + x2 = NegMod(x2, width); + y2 -= yinc; + if (y2 < 0) { + y2 = NegMod(y2, height); + } + } + + segsb[i].x1 = x1; + segsb[i].y1 = y1; + segsb[i].x2 = x2; + segsb[i].y2 = y2; + + /* Move x1, y1 location forward */ + x1 += xinc; + if (x1 > width) { + x1 %= 32; + y1 += yinc; + if (y1 > height) { + y1 %= 32; + } + } + } /* end for */ +} + + +int InitCopyWin(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + (void) InitScroll(xp, p, reps); + InitCopyLocations(xp, p, reps); + return reps; +} + +int InitCopyPix(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + GC pixgc; + (void) InitCopyWin(xp, p, reps); + + /* Create pixmap to write stuff into, and initialize it */ + pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, xp->vinfo.depth); + pixgc = XCreateGC(xp->d, pix, 0, 0); + /* need a gc with GXcopy cos pixmaps contain junk on creation. mmm */ + XCopyArea(xp->d, xp->w, pix, pixgc, 0, 0, WIDTH, HEIGHT, 0, 0); + XFreeGC(xp->d, pixgc); + return reps; +} + +Bool InitGetImage(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + (void) InitCopyWin(xp, p, reps); + + /* Create image to stuff bits into */ + image = XGetImage(xp->d, xp->w, 0, 0, WIDTH, HEIGHT, xp->planemask, + p->font==0?ZPixmap:XYPixmap); + if(image==0){ + printf("XGetImage failed\n"); + return False; + } + return reps; +} + +Bool InitPutImage(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + if(!InitGetImage(xp, p, reps))return False; + XClearWindow(xp->d, xp->w); + return reps; +} + +static void CopyArea(xp, p, reps, src, dst) + XParms xp; + Parms p; + int reps; + Drawable src, dst; +{ + int i, size; + XSegment *sa, *sb; + + size = p->special; + for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { + XCopyArea(xp->d, src, dst, xp->fggc, + sa->x1, sa->y1, size, size, sa->x2, sa->y2); + XCopyArea(xp->d, src, dst, xp->fggc, + sa->x2, sa->y2, size, size, sa->x1, sa->y1); + XCopyArea(xp->d, src, dst, xp->fggc, + sb->x2, sb->y2, size, size, sb->x1, sb->y1); + XCopyArea(xp->d, src, dst, xp->fggc, + sb->x1, sb->y1, size, size, sb->x2, sb->y2); + } +} + +void DoCopyWinWin(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + CopyArea(xp, p, reps, xp->w, xp->w); +} + +void DoCopyPixWin(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + CopyArea(xp, p, reps, pix, xp->w); +} + +void DoCopyWinPix(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + CopyArea(xp, p, reps, xp->w, pix); + xp->p = pix; /* HardwareSync will now sync on pixmap */ +} + +void DoCopyPixPix(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + CopyArea(xp, p, reps, pix, pix); + xp->p = pix; /* HardwareSync will now sync on pixmap */ +} + +void DoGetImage(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int i, size; + XSegment *sa, *sb; + int format; + + size = p->special; + format = (p->font == 0) ? ZPixmap : XYPixmap; + for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { + XDestroyImage(image); + image = XGetImage(xp->d, xp->w, sa->x1, sa->y1, size, size, + xp->planemask, format); + if (image) XDestroyImage(image); + image = XGetImage(xp->d, xp->w, sa->x2, sa->y2, size, size, + xp->planemask, format); + if (image) XDestroyImage(image); + image = XGetImage(xp->d, xp->w, sb->x2, sb->y2, size, size, + xp->planemask, format); + if (image) XDestroyImage(image); + image = XGetImage(xp->d, xp->w, sb->x1, sb->y1, size, size, + xp->planemask, format); +/* + +One might expect XGetSubImage to be slightly faster than XGetImage. Go look +at the code in Xlib. MIT X11R3 ran approximately 30 times slower for a 500x500 +rectangle. + + (void) XGetSubImage(xp->d, xp->w, sa->x1, sa->y1, size, size, + xp->planemask, ZPixmap, image, sa->x2, sa->y2); + (void) XGetSubImage(xp->d, xp->w, sa->x2, sa->y2, size, size, + xp->planemask, ZPixmap, image, sa->x1, sa->y1); + (void) XGetSubImage(xp->d, xp->w, sb->x2, sb->y2, size, size, + xp->planemask, ZPixmap, image, sb->x2, sb->y2); + (void) XGetSubImage(xp->d, xp->w, sb->x1, sb->y1, size, size, + xp->planemask, ZPixmap, image, sb->x2, sb->y2); +*/ + } +} + +void DoPutImage(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int i, size; + XSegment *sa, *sb; + + size = p->special; + for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { + XPutImage(xp->d, xp->w, xp->fggc, image, + sa->x1, sa->y1, sa->x2, sa->y2, size, size); + XPutImage(xp->d, xp->w, xp->fggc, image, + sa->x2, sa->y2, sa->x1, sa->y1, size, size); + XPutImage(xp->d, xp->w, xp->fggc, image, + sb->x2, sb->y2, sb->x2, sb->y2, size, size); + XPutImage(xp->d, xp->w, xp->fggc, image, + sb->x1, sb->y1, sb->x2, sb->y2, size, size); + } +} + +#ifdef MITSHM + +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> + +static XImage shm_image; +static XShmSegmentInfo shm_info; + +static int haderror; +static int (*origerrorhandler)(); +shmerrorhandler(d,e) +Display *d; +XErrorEvent *e; +{ + haderror++; + if(e->error_code==BadAccess)fprintf(stderr,"failed to attach shared memory\n"); + else (*origerrorhandler)(d,e); +} +int InitShmPutImage (xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int image_size; + + if(!InitGetImage(xp, p, reps))return False; + if (!XShmQueryExtension(xp->d)) { + /* + * Clean up here because cleanup function is not called if this + * function fails + */ + if (image) + XDestroyImage(image); + image = NULL; + free(segsa); + free(segsb); + return False; + } + XClearWindow(xp->d, xp->w); + shm_image = *image; + image_size = image->bytes_per_line * image->height; + /* allow XYPixmap choice: */ + if(p->font)image_size *= xp->vinfo.depth; + shm_info.shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777); + if (shm_info.shmid < 0) + { + /* + * Clean up here because cleanup function is not called if this + * function fails + */ + if (image) + XDestroyImage(image); + image = NULL; + free(segsa); + free(segsb); + perror ("shmget"); + return False; + } + shm_info.shmaddr = (char *) shmat(shm_info.shmid, 0, 0); + if (shm_info.shmaddr == ((char *) -1)) + { + /* + * Clean up here because cleanup function is not called if this + * function fails + */ + if (image) + XDestroyImage(image); + image = NULL; + free(segsa); + free(segsb); + perror ("shmat"); + shmctl (shm_info.shmid, IPC_RMID, 0); + return False; + } + shm_info.readOnly = True; + XSync(xp->d,True); + haderror = False; + origerrorhandler = XSetErrorHandler(shmerrorhandler); + XShmAttach (xp->d, &shm_info); + XSync(xp->d,True); /* wait for error or ok */ + XSetErrorHandler(origerrorhandler); + if(haderror){ + /* + * Clean up here because cleanup function is not called if this + * function fails + */ + if (image) + XDestroyImage(image); + image = NULL; + free(segsa); + free(segsb); + if(shmdt (shm_info.shmaddr)==-1) + perror("shmdt:"); + if(shmctl (shm_info.shmid, IPC_RMID, 0)==-1) + perror("shmctl rmid:"); + return False; + } + shm_image.data = shm_info.shmaddr; + memmove( shm_image.data, image->data, image_size); + shm_image.obdata = (char *) &shm_info; + return reps; +} + +void DoShmPutImage(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int i, size; + XSegment *sa, *sb; + + size = p->special; + for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { + XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, + sa->x1, sa->y1, sa->x2, sa->y2, size, size, False); + XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, + sa->x2, sa->y2, sa->x1, sa->y1, size, size, False); + XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, + sb->x2, sb->y2, sb->x2, sb->y2, size, size, False); + XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image, + sb->x1, sb->y1, sb->x2, sb->y2, size, size, False); + } +} + +void EndShmPutImage(xp, p) + XParms xp; + Parms p; +{ + void EndGetImage(); + + EndGetImage (xp, p); + XShmDetach (xp->d, &shm_info); + XSync(xp->d, False); /* need server to detach so can remove id */ + if(shmdt (shm_info.shmaddr)==-1) + perror("shmdt:"); + if(shmctl (shm_info.shmid, IPC_RMID, 0)==-1) + perror("shmctl rmid:"); +} + +#endif + + +void MidCopyPix(xp, p) + XParms xp; + Parms p; +{ + XClearWindow(xp->d, xp->w); +} + +void EndCopyWin(xp, p) + XParms xp; + Parms p; +{ + EndScroll(xp, p); + free(segsa); + free(segsb); +} + +void EndCopyPix(xp, p) + XParms xp; + Parms p; +{ + EndCopyWin(xp, p); + XFreePixmap(xp->d, pix); + /* + * Ensure that the next test doesn't try and sync on the pixmap + */ + xp->p = (Pixmap)0; +} + +void EndGetImage(xp, p) + XParms xp; + Parms p; +{ + EndCopyWin(xp, p); + if (image) XDestroyImage(image); +} + +Bool InitCopyPlane(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + XGCValues gcv; + GC pixgc; + + InitBltLines(); + InitCopyLocations(xp, p, reps); + + /* Create pixmap to write stuff into, and initialize it */ + pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, + p->font==0 ? 1 : xp->vinfo.depth); + gcv.graphics_exposures = False; + gcv.foreground = 0; + gcv.background = 1; + pixgc = XCreateGC(xp->d, pix, + GCForeground | GCBackground | GCGraphicsExposures, &gcv); + XFillRectangle(xp->d, pix, pixgc, 0, 0, WIDTH, HEIGHT); + gcv.foreground = 1; + gcv.background = 0; + XChangeGC(xp->d, pixgc, GCForeground | GCBackground, &gcv); + XDrawLines(xp->d, pix, pixgc, points, NUMPOINTS, CoordModeOrigin); + XFreeGC(xp->d, pixgc); + + return reps; +} + +void DoCopyPlane(xp, p, reps) + XParms xp; + Parms p; + int reps; +{ + int i, size; + XSegment *sa, *sb; + + size = p->special; + for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { + XCopyPlane(xp->d, pix, xp->w, xp->fggc, + sa->x1, sa->y1, size, size, sa->x2, sa->y2, 1); + XCopyPlane(xp->d, pix, xp->w, xp->fggc, + sa->x2, sa->y2, size, size, sa->x1, sa->y1, 1); + XCopyPlane(xp->d, pix, xp->w, xp->fggc, + sb->x2, sb->y2, size, size, sb->x1, sb->y1, 1); + XCopyPlane(xp->d, pix, xp->w, xp->fggc, + sb->x1, sb->y1, size, size, sb->x2, sb->y2, 1); + } +} + |