do_blt.c revision 264fa531
1264fa531Smrg/* $Xorg: do_blt.c,v 1.3 2000/08/17 19:54:09 cpqbld Exp $ */
2264fa531Smrg/*****************************************************************************
3264fa531SmrgCopyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
4264fa531Smrg
5264fa531Smrg                        All Rights Reserved
6264fa531Smrg
7264fa531SmrgPermission to use, copy, modify, and distribute this software and its
8264fa531Smrgdocumentation for any purpose and without fee is hereby granted,
9264fa531Smrgprovided that the above copyright notice appear in all copies and that
10264fa531Smrgboth that copyright notice and this permission notice appear in
11264fa531Smrgsupporting documentation, and that the name of Digital not be
12264fa531Smrgused in advertising or publicity pertaining to distribution of the
13264fa531Smrgsoftware without specific, written prior permission.
14264fa531Smrg
15264fa531SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16264fa531SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17264fa531SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18264fa531SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19264fa531SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20264fa531SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21264fa531SmrgSOFTWARE.
22264fa531Smrg
23264fa531Smrg******************************************************************************/
24264fa531Smrg/* $XFree86: xc/programs/x11perf/do_blt.c,v 1.8 2001/05/01 16:19:16 alanh Exp $ */
25264fa531Smrg
26264fa531Smrg#include "x11perf.h"
27264fa531Smrg#include <stdio.h>
28264fa531Smrg
29264fa531Smrg#define NUMPOINTS 100
30264fa531Smrg
31264fa531Smrgstatic Pixmap   pix;
32264fa531Smrgstatic XImage   *image;
33264fa531Smrgstatic XPoint   points[NUMPOINTS];
34264fa531Smrgstatic XSegment *segsa, *segsb;
35264fa531Smrg
36264fa531Smrg#define NegMod(x, y) ((y) - (((-x)-1) % (7)) - 1)
37264fa531Smrg
38264fa531Smrgstatic void
39264fa531SmrgInitBltLines(void)
40264fa531Smrg{
41264fa531Smrg    int i, x, y;
42264fa531Smrg
43264fa531Smrg    points[0].x = points[0].y = y = 0;
44264fa531Smrg    for (i = 1; i != NUMPOINTS/2; i++) {
45264fa531Smrg	if (i & 1) {
46264fa531Smrg	    points[i].x = WIDTH-1;
47264fa531Smrg	} else {
48264fa531Smrg	    points[i].x = 0;
49264fa531Smrg	}
50264fa531Smrg	y += HEIGHT / (NUMPOINTS/2);
51264fa531Smrg	points[i].y = y;
52264fa531Smrg    }
53264fa531Smrg
54264fa531Smrg    x = 0;
55264fa531Smrg    for (i = NUMPOINTS/2; i!= NUMPOINTS; i++) {
56264fa531Smrg	if (i & 1) {
57264fa531Smrg	    points[i].y = HEIGHT-1;
58264fa531Smrg	} else {
59264fa531Smrg	    points[i].y = 0;
60264fa531Smrg	}
61264fa531Smrg	x += WIDTH / (NUMPOINTS/2);
62264fa531Smrg	points[i].x = x;
63264fa531Smrg    }
64264fa531Smrg}
65264fa531Smrg
66264fa531Smrgint
67264fa531SmrgInitScroll(XParms xp, Parms p, int reps)
68264fa531Smrg{
69264fa531Smrg    InitBltLines();
70264fa531Smrg    XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin);
71264fa531Smrg    return reps;
72264fa531Smrg}
73264fa531Smrg
74264fa531Smrgvoid
75264fa531SmrgDoScroll(XParms xp, Parms p, int reps)
76264fa531Smrg{
77264fa531Smrg    int i, size, x, y, xorg, yorg, delta;
78264fa531Smrg
79264fa531Smrg    size = p->special;
80264fa531Smrg    xorg = 0;   yorg = 0;
81264fa531Smrg    x    = 0;   y    = 0;
82264fa531Smrg    if (xp->version == VERSION1_2) {
83264fa531Smrg	delta = 1;
84264fa531Smrg    } else {
85264fa531Smrg	/* Version 1.2 only scrolled up by 1 scanline, which made hardware
86264fa531Smrg	   using page-mode access to VRAM look better on paper than it would
87264fa531Smrg	   perform in a more realistic scroll.  So we've changed to scroll by
88264fa531Smrg	   the height of the 6x13 fonts. */
89264fa531Smrg	delta = 13;
90264fa531Smrg    }
91264fa531Smrg
92264fa531Smrg    for (i = 0; i != reps; i++) {
93264fa531Smrg	XCopyArea(xp->d, xp->w, xp->w, xp->fggc, x, y + delta,
94264fa531Smrg	    size, size, x, y);
95264fa531Smrg	y += size;
96264fa531Smrg	if (y + size + delta > HEIGHT) {
97264fa531Smrg	    yorg += delta;
98264fa531Smrg	    if (yorg >= size || yorg + size + delta > HEIGHT) {
99264fa531Smrg		yorg = 0;
100264fa531Smrg		xorg++;
101264fa531Smrg		if (xorg >= size || xorg + size > WIDTH) {
102264fa531Smrg		    xorg = 0;
103264fa531Smrg		}
104264fa531Smrg	    }
105264fa531Smrg	    y = yorg;
106264fa531Smrg	    x += size;
107264fa531Smrg	    if (x + size > WIDTH) {
108264fa531Smrg		x = xorg;
109264fa531Smrg	    }
110264fa531Smrg	}
111264fa531Smrg	CheckAbort ();
112264fa531Smrg    }
113264fa531Smrg}
114264fa531Smrg
115264fa531Smrgvoid
116264fa531SmrgMidScroll(XParms xp, Parms p)
117264fa531Smrg{
118264fa531Smrg    XClearWindow(xp->d, xp->w);
119264fa531Smrg    XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin);
120264fa531Smrg}
121264fa531Smrg
122264fa531Smrgvoid
123264fa531SmrgEndScroll(XParms xp, Parms p)
124264fa531Smrg{
125264fa531Smrg}
126264fa531Smrg
127264fa531Smrgstatic void
128264fa531SmrgInitCopyLocations(XParms xp, Parms p, int reps)
129264fa531Smrg{
130264fa531Smrg    int x1, y1, x2, y2, size, i;
131264fa531Smrg    int xinc, yinc;
132264fa531Smrg    int width, height;
133264fa531Smrg
134264fa531Smrg    /* Try to exercise all alignments of src and destination equally, as well
135264fa531Smrg       as all 4 top-to-bottom/bottom-to-top, left-to-right, right-to-left
136264fa531Smrg       copying directions.  Computation done here just to make sure slow
137264fa531Smrg       machines aren't measuring anything but the XCopyArea calls.
138264fa531Smrg    */
139264fa531Smrg    size = p->special;
140264fa531Smrg    xinc = (size & ~3) + 1;
141264fa531Smrg    yinc = xinc + 3;
142264fa531Smrg
143264fa531Smrg    width = (WIDTH - size) & ~31;
144264fa531Smrg    height = (HEIGHT - size) & ~31;
145264fa531Smrg
146264fa531Smrg    x1 = 0;
147264fa531Smrg    y1 = 0;
148264fa531Smrg    x2 = width;
149264fa531Smrg    y2 = height;
150264fa531Smrg
151264fa531Smrg    segsa = (XSegment *)malloc(reps * sizeof(XSegment));
152264fa531Smrg    segsb = (XSegment *)malloc(reps * sizeof(XSegment));
153264fa531Smrg    for (i = 0; i != reps; i++) {
154264fa531Smrg	segsa[i].x1 = x1;
155264fa531Smrg	segsa[i].y1 = y1;
156264fa531Smrg	segsa[i].x2 = x2;
157264fa531Smrg	segsa[i].y2 = y2;
158264fa531Smrg
159264fa531Smrg	/* Move x2, y2, location backward */
160264fa531Smrg	x2 -= xinc;
161264fa531Smrg	if (x2 < 0) {
162264fa531Smrg	    x2 = NegMod(x2, width);
163264fa531Smrg	    y2 -= yinc;
164264fa531Smrg	    if (y2 < 0) {
165264fa531Smrg		y2 = NegMod(y2, height);
166264fa531Smrg	    }
167264fa531Smrg	}
168264fa531Smrg
169264fa531Smrg	segsb[i].x1 = x1;
170264fa531Smrg	segsb[i].y1 = y1;
171264fa531Smrg	segsb[i].x2 = x2;
172264fa531Smrg	segsb[i].y2 = y2;
173264fa531Smrg
174264fa531Smrg	/* Move x1, y1 location forward */
175264fa531Smrg	x1 += xinc;
176264fa531Smrg	if (x1 > width) {
177264fa531Smrg	    x1 %= 32;
178264fa531Smrg	    y1 += yinc;
179264fa531Smrg	    if (y1 > height) {
180264fa531Smrg		y1 %= 32;
181264fa531Smrg	    }
182264fa531Smrg	}
183264fa531Smrg    } /* end for */
184264fa531Smrg}
185264fa531Smrg
186264fa531Smrg
187264fa531Smrgint
188264fa531SmrgInitCopyWin(XParms xp, Parms p, int reps)
189264fa531Smrg{
190264fa531Smrg    (void) InitScroll(xp, p, reps);
191264fa531Smrg    InitCopyLocations(xp, p, reps);
192264fa531Smrg    return reps;
193264fa531Smrg}
194264fa531Smrg
195264fa531Smrgint
196264fa531SmrgInitCopyPix(XParms xp, Parms p, int reps)
197264fa531Smrg{
198264fa531Smrg    GC		pixgc;
199264fa531Smrg    (void) InitCopyWin(xp, p, reps);
200264fa531Smrg
201264fa531Smrg    /* Create pixmap to write stuff into, and initialize it */
202264fa531Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, xp->vinfo.depth);
203264fa531Smrg    pixgc = XCreateGC(xp->d, pix, 0, 0);
204264fa531Smrg    /* need a gc with GXcopy cos pixmaps contain junk on creation. mmm */
205264fa531Smrg    XCopyArea(xp->d, xp->w, pix, pixgc, 0, 0, WIDTH, HEIGHT, 0, 0);
206264fa531Smrg    XFreeGC(xp->d, pixgc);
207264fa531Smrg    return reps;
208264fa531Smrg}
209264fa531Smrg
210264fa531Smrgint
211264fa531SmrgInitGetImage(XParms xp, Parms p, int reps)
212264fa531Smrg{
213264fa531Smrg    (void) InitCopyWin(xp, p, reps);
214264fa531Smrg
215264fa531Smrg    /* Create image to stuff bits into */
216264fa531Smrg    image = XGetImage(xp->d, xp->w, 0, 0, WIDTH, HEIGHT, xp->planemask,
217264fa531Smrg		      p->font==0?ZPixmap:XYPixmap);
218264fa531Smrg    if(image==0){
219264fa531Smrg	printf("XGetImage failed\n");
220264fa531Smrg	return False;
221264fa531Smrg    }
222264fa531Smrg    return reps;
223264fa531Smrg}
224264fa531Smrg
225264fa531Smrgint
226264fa531SmrgInitPutImage(XParms xp, Parms p, int reps)
227264fa531Smrg{
228264fa531Smrg    if(!InitGetImage(xp, p, reps))return False;
229264fa531Smrg    XClearWindow(xp->d, xp->w);
230264fa531Smrg    return reps;
231264fa531Smrg}
232264fa531Smrg
233264fa531Smrgstatic void
234264fa531SmrgCopyArea(XParms xp, Parms p, int reps, Drawable src, Drawable dst)
235264fa531Smrg{
236264fa531Smrg    int i, size;
237264fa531Smrg    XSegment *sa, *sb;
238264fa531Smrg
239264fa531Smrg    size = p->special;
240264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
241264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
242264fa531Smrg	    sa->x1, sa->y1, size, size, sa->x2, sa->y2);
243264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
244264fa531Smrg	    sa->x2, sa->y2, size, size, sa->x1, sa->y1);
245264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
246264fa531Smrg	    sb->x2, sb->y2, size, size, sb->x1, sb->y1);
247264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
248264fa531Smrg	    sb->x1, sb->y1, size, size, sb->x2, sb->y2);
249264fa531Smrg	CheckAbort ();
250264fa531Smrg    }
251264fa531Smrg}
252264fa531Smrg
253264fa531Smrgvoid
254264fa531SmrgDoCopyWinWin(XParms xp, Parms p, int reps)
255264fa531Smrg{
256264fa531Smrg    CopyArea(xp, p, reps, xp->w, xp->w);
257264fa531Smrg}
258264fa531Smrg
259264fa531Smrgvoid
260264fa531SmrgDoCopyPixWin(XParms xp, Parms p, int reps)
261264fa531Smrg{
262264fa531Smrg    CopyArea(xp, p, reps, pix, xp->w);
263264fa531Smrg}
264264fa531Smrg
265264fa531Smrgvoid
266264fa531SmrgDoCopyWinPix(XParms xp, Parms p, int reps)
267264fa531Smrg{
268264fa531Smrg    CopyArea(xp, p, reps, xp->w, pix);
269264fa531Smrg    xp->p = pix;	/* HardwareSync will now sync on pixmap */
270264fa531Smrg}
271264fa531Smrg
272264fa531Smrgvoid
273264fa531SmrgDoCopyPixPix(XParms xp, Parms p, int reps)
274264fa531Smrg{
275264fa531Smrg    CopyArea(xp, p, reps, pix, pix);
276264fa531Smrg    xp->p = pix;	/* HardwareSync will now sync on pixmap */
277264fa531Smrg}
278264fa531Smrg
279264fa531Smrgvoid
280264fa531SmrgDoGetImage(XParms xp, Parms p, int reps)
281264fa531Smrg{
282264fa531Smrg    int i, size;
283264fa531Smrg    XSegment *sa, *sb;
284264fa531Smrg    int format;
285264fa531Smrg
286264fa531Smrg    size = p->special;
287264fa531Smrg    format = (p->font == 0) ? ZPixmap : XYPixmap;
288264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
289264fa531Smrg	XDestroyImage(image);
290264fa531Smrg	image = XGetImage(xp->d, xp->w, sa->x1, sa->y1, size, size,
291264fa531Smrg	    xp->planemask, format);
292264fa531Smrg	if (image) XDestroyImage(image);
293264fa531Smrg	image = XGetImage(xp->d, xp->w, sa->x2, sa->y2, size, size,
294264fa531Smrg	    xp->planemask, format);
295264fa531Smrg	if (image) XDestroyImage(image);
296264fa531Smrg	image = XGetImage(xp->d, xp->w, sb->x2, sb->y2, size, size,
297264fa531Smrg	    xp->planemask, format);
298264fa531Smrg	if (image) XDestroyImage(image);
299264fa531Smrg	image = XGetImage(xp->d, xp->w, sb->x1, sb->y1, size, size,
300264fa531Smrg	    xp->planemask, format);
301264fa531Smrg/*
302264fa531Smrg
303264fa531SmrgOne might expect XGetSubImage to be slightly faster than XGetImage.  Go look
304264fa531Smrgat the code in Xlib.  MIT X11R3 ran approximately 30 times slower for a 500x500
305264fa531Smrgrectangle.
306264fa531Smrg
307264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sa->x1, sa->y1, size, size,
308264fa531Smrg	    xp->planemask, ZPixmap, image, sa->x2, sa->y2);
309264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sa->x2, sa->y2, size, size,
310264fa531Smrg	    xp->planemask, ZPixmap, image, sa->x1, sa->y1);
311264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sb->x2, sb->y2, size, size,
312264fa531Smrg	    xp->planemask, ZPixmap, image, sb->x2, sb->y2);
313264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sb->x1, sb->y1, size, size,
314264fa531Smrg	    xp->planemask, ZPixmap, image, sb->x2, sb->y2);
315264fa531Smrg*/
316264fa531Smrg	CheckAbort ();
317264fa531Smrg    }
318264fa531Smrg}
319264fa531Smrg
320264fa531Smrgvoid
321264fa531SmrgDoPutImage(XParms xp, Parms p, int reps)
322264fa531Smrg{
323264fa531Smrg    int i, size;
324264fa531Smrg    XSegment *sa, *sb;
325264fa531Smrg
326264fa531Smrg    size = p->special;
327264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
328264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
329264fa531Smrg	    sa->x1, sa->y1, sa->x2, sa->y2, size, size);
330264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
331264fa531Smrg	    sa->x2, sa->y2, sa->x1, sa->y1, size, size);
332264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
333264fa531Smrg	    sb->x2, sb->y2, sb->x2, sb->y2, size, size);
334264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
335264fa531Smrg	    sb->x1, sb->y1, sb->x2, sb->y2, size, size);
336264fa531Smrg	CheckAbort ();
337264fa531Smrg    }
338264fa531Smrg}
339264fa531Smrg
340264fa531Smrg#ifdef MITSHM
341264fa531Smrg
342264fa531Smrg#include <sys/types.h>
343264fa531Smrg#ifndef Lynx
344264fa531Smrg#include <sys/ipc.h>
345264fa531Smrg#include <sys/shm.h>
346264fa531Smrg#else
347264fa531Smrg#include <ipc.h>
348264fa531Smrg#include <shm.h>
349264fa531Smrg#endif
350264fa531Smrg#include <X11/extensions/XShm.h>
351264fa531Smrg
352264fa531Smrgstatic XImage		shm_image;
353264fa531Smrgstatic XShmSegmentInfo	shm_info;
354264fa531Smrg
355264fa531Smrgstatic int haderror;
356264fa531Smrgstatic int (*origerrorhandler)(Display *, XErrorEvent *);
357264fa531Smrg
358264fa531Smrgstatic int
359264fa531Smrgshmerrorhandler(Display *d, XErrorEvent *e)
360264fa531Smrg{
361264fa531Smrg    haderror++;
362264fa531Smrg    if(e->error_code==BadAccess) {
363264fa531Smrg	fprintf(stderr,"failed to attach shared memory\n");
364264fa531Smrg	return 0;
365264fa531Smrg    } else
366264fa531Smrg	return (*origerrorhandler)(d,e);
367264fa531Smrg}
368264fa531Smrg
369264fa531Smrgint
370264fa531SmrgInitShmPutImage(XParms xp, Parms p, int reps)
371264fa531Smrg{
372264fa531Smrg    int	image_size;
373264fa531Smrg
374264fa531Smrg    if(!InitGetImage(xp, p, reps))return False;
375264fa531Smrg    if (!XShmQueryExtension(xp->d)) {
376264fa531Smrg	/*
377264fa531Smrg 	 * Clean up here because cleanup function is not called if this
378264fa531Smrg	 * function fails
379264fa531Smrg	 */
380264fa531Smrg       	if (image)
381264fa531Smrg      	    XDestroyImage(image);
382264fa531Smrg    	image = NULL;
383264fa531Smrg    	free(segsa);
384264fa531Smrg    	free(segsb);
385264fa531Smrg    	return False;
386264fa531Smrg    }
387264fa531Smrg    XClearWindow(xp->d, xp->w);
388264fa531Smrg    shm_image = *image;
389264fa531Smrg    image_size = image->bytes_per_line * image->height;
390264fa531Smrg    /* allow XYPixmap choice: */
391264fa531Smrg    if(p->font)image_size *= xp->vinfo.depth;
392264fa531Smrg    shm_info.shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777);
393264fa531Smrg    if (shm_info.shmid < 0)
394264fa531Smrg    {
395264fa531Smrg	/*
396264fa531Smrg	 * Clean up here because cleanup function is not called if this
397264fa531Smrg	 * function fails
398264fa531Smrg	 */
399264fa531Smrg	if (image)
400264fa531Smrg	    XDestroyImage(image);
401264fa531Smrg	image = NULL;
402264fa531Smrg	free(segsa);
403264fa531Smrg	free(segsb);
404264fa531Smrg	perror ("shmget");
405264fa531Smrg	return False;
406264fa531Smrg    }
407264fa531Smrg    shm_info.shmaddr = (char *) shmat(shm_info.shmid, 0, 0);
408264fa531Smrg    if (shm_info.shmaddr == ((char *) -1))
409264fa531Smrg    {
410264fa531Smrg	/*
411264fa531Smrg	 * Clean up here because cleanup function is not called if this
412264fa531Smrg	 * function fails
413264fa531Smrg	 */
414264fa531Smrg	if (image)
415264fa531Smrg	    XDestroyImage(image);
416264fa531Smrg	image = NULL;
417264fa531Smrg	free(segsa);
418264fa531Smrg	free(segsb);
419264fa531Smrg	perror ("shmat");
420264fa531Smrg	shmctl (shm_info.shmid, IPC_RMID, 0);
421264fa531Smrg	return False;
422264fa531Smrg    }
423264fa531Smrg    shm_info.readOnly = True;
424264fa531Smrg    XSync(xp->d,True);
425264fa531Smrg    haderror = False;
426264fa531Smrg    origerrorhandler = XSetErrorHandler(shmerrorhandler);
427264fa531Smrg    XShmAttach (xp->d, &shm_info);
428264fa531Smrg    XSync(xp->d,True);	/* wait for error or ok */
429264fa531Smrg    XSetErrorHandler(origerrorhandler);
430264fa531Smrg    if(haderror){
431264fa531Smrg	/*
432264fa531Smrg	 * Clean up here because cleanup function is not called if this
433264fa531Smrg	 * function fails
434264fa531Smrg	 */
435264fa531Smrg	if (image)
436264fa531Smrg	    XDestroyImage(image);
437264fa531Smrg	image = NULL;
438264fa531Smrg	free(segsa);
439264fa531Smrg	free(segsb);
440264fa531Smrg	if(shmdt (shm_info.shmaddr)==-1)
441264fa531Smrg	    perror("shmdt:");
442264fa531Smrg	if(shmctl (shm_info.shmid, IPC_RMID, 0)==-1)
443264fa531Smrg	    perror("shmctl rmid:");
444264fa531Smrg	return False;
445264fa531Smrg    }
446264fa531Smrg    shm_image.data = shm_info.shmaddr;
447264fa531Smrg    memmove( shm_image.data, image->data, image_size);
448264fa531Smrg    shm_image.obdata = (char *) &shm_info;
449264fa531Smrg    return reps;
450264fa531Smrg}
451264fa531Smrg
452264fa531Smrgvoid
453264fa531SmrgDoShmPutImage(XParms xp, Parms p, int reps)
454264fa531Smrg{
455264fa531Smrg    int i, size;
456264fa531Smrg    XSegment *sa, *sb;
457264fa531Smrg
458264fa531Smrg    size = p->special;
459264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
460264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
461264fa531Smrg	    sa->x1, sa->y1, sa->x2, sa->y2, size, size, False);
462264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
463264fa531Smrg	    sa->x2, sa->y2, sa->x1, sa->y1, size, size, False);
464264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
465264fa531Smrg	    sb->x2, sb->y2, sb->x2, sb->y2, size, size, False);
466264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
467264fa531Smrg	    sb->x1, sb->y1, sb->x2, sb->y2, size, size, False);
468264fa531Smrg	CheckAbort ();
469264fa531Smrg    }
470264fa531Smrg}
471264fa531Smrg
472264fa531Smrgvoid
473264fa531SmrgEndShmPutImage(XParms xp, Parms p)
474264fa531Smrg{
475264fa531Smrg
476264fa531Smrg    EndGetImage (xp, p);
477264fa531Smrg    XShmDetach (xp->d, &shm_info);
478264fa531Smrg    XSync(xp->d, False);	/* need server to detach so can remove id */
479264fa531Smrg    if(shmdt (shm_info.shmaddr)==-1)
480264fa531Smrg	perror("shmdt:");
481264fa531Smrg    if(shmctl (shm_info.shmid, IPC_RMID, 0)==-1)
482264fa531Smrg	perror("shmctl rmid:");
483264fa531Smrg}
484264fa531Smrg
485264fa531Smrg#endif
486264fa531Smrg
487264fa531Smrg
488264fa531Smrgvoid
489264fa531SmrgMidCopyPix(XParms xp, Parms p)
490264fa531Smrg{
491264fa531Smrg    XClearWindow(xp->d, xp->w);
492264fa531Smrg}
493264fa531Smrg
494264fa531Smrgvoid
495264fa531SmrgEndCopyWin(XParms xp, Parms p)
496264fa531Smrg{
497264fa531Smrg    EndScroll(xp, p);
498264fa531Smrg    free(segsa);
499264fa531Smrg    free(segsb);
500264fa531Smrg}
501264fa531Smrg
502264fa531Smrgvoid
503264fa531SmrgEndCopyPix(XParms xp, Parms p)
504264fa531Smrg{
505264fa531Smrg    EndCopyWin(xp, p);
506264fa531Smrg    XFreePixmap(xp->d, pix);
507264fa531Smrg    /*
508264fa531Smrg     * Ensure that the next test doesn't try and sync on the pixmap
509264fa531Smrg     */
510264fa531Smrg    xp->p = (Pixmap)0;
511264fa531Smrg}
512264fa531Smrg
513264fa531Smrgvoid
514264fa531SmrgEndGetImage(XParms xp, Parms p)
515264fa531Smrg{
516264fa531Smrg    EndCopyWin(xp, p);
517264fa531Smrg    if (image) XDestroyImage(image);
518264fa531Smrg}
519264fa531Smrg
520264fa531Smrgint
521264fa531SmrgInitCopyPlane(XParms xp, Parms p, int reps)
522264fa531Smrg{
523264fa531Smrg    XGCValues   gcv;
524264fa531Smrg    GC		pixgc;
525264fa531Smrg
526264fa531Smrg    InitBltLines();
527264fa531Smrg    InitCopyLocations(xp, p, reps);
528264fa531Smrg
529264fa531Smrg    /* Create pixmap to write stuff into, and initialize it */
530264fa531Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT,
531264fa531Smrg	    p->font==0 ? 1 : xp->vinfo.depth);
532264fa531Smrg    gcv.graphics_exposures = False;
533264fa531Smrg    gcv.foreground = 0;
534264fa531Smrg    gcv.background = 1;
535264fa531Smrg    pixgc = XCreateGC(xp->d, pix,
536264fa531Smrg		GCForeground | GCBackground | GCGraphicsExposures, &gcv);
537264fa531Smrg    XFillRectangle(xp->d, pix, pixgc, 0, 0, WIDTH, HEIGHT);
538264fa531Smrg    gcv.foreground = 1;
539264fa531Smrg    gcv.background = 0;
540264fa531Smrg    XChangeGC(xp->d, pixgc, GCForeground | GCBackground, &gcv);
541264fa531Smrg    XDrawLines(xp->d, pix, pixgc, points, NUMPOINTS, CoordModeOrigin);
542264fa531Smrg    XFreeGC(xp->d, pixgc);
543264fa531Smrg
544264fa531Smrg    return reps;
545264fa531Smrg}
546264fa531Smrg
547264fa531Smrgvoid
548264fa531SmrgDoCopyPlane(XParms xp, Parms p, int reps)
549264fa531Smrg{
550264fa531Smrg    int		i, size;
551264fa531Smrg    XSegment    *sa, *sb;
552264fa531Smrg
553264fa531Smrg    size = p->special;
554264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
555264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
556264fa531Smrg	    sa->x1, sa->y1, size, size, sa->x2, sa->y2, 1);
557264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
558264fa531Smrg	    sa->x2, sa->y2, size, size, sa->x1, sa->y1, 1);
559264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
560264fa531Smrg	    sb->x2, sb->y2, size, size, sb->x1, sb->y1, 1);
561264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
562264fa531Smrg	    sb->x1, sb->y1, size, size, sb->x2, sb->y2, 1);
563264fa531Smrg	CheckAbort ();
564264fa531Smrg    }
565264fa531Smrg}
566264fa531Smrg
567