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