do_blt.c revision 533545b5
1264fa531Smrg/*****************************************************************************
2264fa531SmrgCopyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
3264fa531Smrg
4264fa531Smrg                        All Rights Reserved
5264fa531Smrg
6264fa531SmrgPermission to use, copy, modify, and distribute this software and its
7264fa531Smrgdocumentation for any purpose and without fee is hereby granted,
8264fa531Smrgprovided that the above copyright notice appear in all copies and that
9264fa531Smrgboth that copyright notice and this permission notice appear in
10264fa531Smrgsupporting documentation, and that the name of Digital not be
11264fa531Smrgused in advertising or publicity pertaining to distribution of the
12264fa531Smrgsoftware without specific, written prior permission.
13264fa531Smrg
14264fa531SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15264fa531SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16264fa531SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17264fa531SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18264fa531SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19264fa531SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20264fa531SmrgSOFTWARE.
21264fa531Smrg
22264fa531Smrg******************************************************************************/
23264fa531Smrg
24264fa531Smrg#include "x11perf.h"
25264fa531Smrg#include <stdio.h>
26264fa531Smrg
27264fa531Smrg#define NUMPOINTS 100
28264fa531Smrg
29264fa531Smrgstatic Pixmap   pix;
30264fa531Smrgstatic XImage   *image;
31264fa531Smrgstatic XPoint   points[NUMPOINTS];
32264fa531Smrgstatic XSegment *segsa, *segsb;
33533545b5Smrgstatic XSegment *segsa2, *segsb2;
34264fa531Smrg
35264fa531Smrg#define NegMod(x, y) ((y) - (((-x)-1) % (7)) - 1)
36264fa531Smrg
37264fa531Smrgstatic void
38264fa531SmrgInitBltLines(void)
39264fa531Smrg{
40264fa531Smrg    int i, x, y;
41264fa531Smrg
42264fa531Smrg    points[0].x = points[0].y = y = 0;
43264fa531Smrg    for (i = 1; i != NUMPOINTS/2; i++) {
44264fa531Smrg	if (i & 1) {
45264fa531Smrg	    points[i].x = WIDTH-1;
46264fa531Smrg	} else {
47264fa531Smrg	    points[i].x = 0;
48264fa531Smrg	}
49264fa531Smrg	y += HEIGHT / (NUMPOINTS/2);
50264fa531Smrg	points[i].y = y;
51264fa531Smrg    }
52264fa531Smrg
53264fa531Smrg    x = 0;
54264fa531Smrg    for (i = NUMPOINTS/2; i!= NUMPOINTS; i++) {
55264fa531Smrg	if (i & 1) {
56264fa531Smrg	    points[i].y = HEIGHT-1;
57264fa531Smrg	} else {
58264fa531Smrg	    points[i].y = 0;
59264fa531Smrg	}
60264fa531Smrg	x += WIDTH / (NUMPOINTS/2);
61264fa531Smrg	points[i].x = x;
62264fa531Smrg    }
63264fa531Smrg}
64264fa531Smrg
65264fa531Smrgint
66533545b5SmrgInitScroll(XParms xp, Parms p, int64_t reps)
67264fa531Smrg{
68264fa531Smrg    InitBltLines();
69264fa531Smrg    XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin);
70264fa531Smrg    return reps;
71264fa531Smrg}
72264fa531Smrg
73264fa531Smrgvoid
74533545b5SmrgDoScroll(XParms xp, Parms p, int64_t reps)
75264fa531Smrg{
76264fa531Smrg    int i, size, x, y, xorg, yorg, delta;
77264fa531Smrg
78264fa531Smrg    size = p->special;
79264fa531Smrg    xorg = 0;   yorg = 0;
80264fa531Smrg    x    = 0;   y    = 0;
81264fa531Smrg    if (xp->version == VERSION1_2) {
82264fa531Smrg	delta = 1;
83264fa531Smrg    } else {
84264fa531Smrg	/* Version 1.2 only scrolled up by 1 scanline, which made hardware
85264fa531Smrg	   using page-mode access to VRAM look better on paper than it would
86264fa531Smrg	   perform in a more realistic scroll.  So we've changed to scroll by
87264fa531Smrg	   the height of the 6x13 fonts. */
88264fa531Smrg	delta = 13;
89264fa531Smrg    }
90264fa531Smrg
91264fa531Smrg    for (i = 0; i != reps; i++) {
92264fa531Smrg	XCopyArea(xp->d, xp->w, xp->w, xp->fggc, x, y + delta,
93264fa531Smrg	    size, size, x, y);
94264fa531Smrg	y += size;
95264fa531Smrg	if (y + size + delta > HEIGHT) {
96264fa531Smrg	    yorg += delta;
97264fa531Smrg	    if (yorg >= size || yorg + size + delta > HEIGHT) {
98264fa531Smrg		yorg = 0;
99264fa531Smrg		xorg++;
100264fa531Smrg		if (xorg >= size || xorg + size > WIDTH) {
101264fa531Smrg		    xorg = 0;
102264fa531Smrg		}
103264fa531Smrg	    }
104264fa531Smrg	    y = yorg;
105264fa531Smrg	    x += size;
106264fa531Smrg	    if (x + size > WIDTH) {
107264fa531Smrg		x = xorg;
108264fa531Smrg	    }
109264fa531Smrg	}
110264fa531Smrg	CheckAbort ();
111264fa531Smrg    }
112264fa531Smrg}
113264fa531Smrg
114264fa531Smrgvoid
115264fa531SmrgMidScroll(XParms xp, Parms p)
116264fa531Smrg{
117264fa531Smrg    XClearWindow(xp->d, xp->w);
118264fa531Smrg    XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin);
119264fa531Smrg}
120264fa531Smrg
121264fa531Smrgvoid
122264fa531SmrgEndScroll(XParms xp, Parms p)
123264fa531Smrg{
124264fa531Smrg}
125264fa531Smrg
126264fa531Smrgstatic void
127533545b5SmrgInitCopyLocations(int size, int mul, int div,
128533545b5Smrg		  int64_t reps, XSegment **ap, XSegment **bp)
129264fa531Smrg{
130533545b5Smrg    int x1, y1, x2, y2, i;
131264fa531Smrg    int xinc, yinc;
132264fa531Smrg    int width, height;
133533545b5Smrg    XSegment *a, *b;
134264fa531Smrg
135533545b5Smrg    size = size * mul / div;
136264fa531Smrg    /* Try to exercise all alignments of src and destination equally, as well
137264fa531Smrg       as all 4 top-to-bottom/bottom-to-top, left-to-right, right-to-left
138264fa531Smrg       copying directions.  Computation done here just to make sure slow
139264fa531Smrg       machines aren't measuring anything but the XCopyArea calls.
140264fa531Smrg    */
141264fa531Smrg    xinc = (size & ~3) + 1;
142264fa531Smrg    yinc = xinc + 3;
143264fa531Smrg
144264fa531Smrg    width = (WIDTH - size) & ~31;
145264fa531Smrg    height = (HEIGHT - size) & ~31;
146264fa531Smrg
147264fa531Smrg    x1 = 0;
148264fa531Smrg    y1 = 0;
149264fa531Smrg    x2 = width;
150264fa531Smrg    y2 = height;
151264fa531Smrg
152533545b5Smrg    *ap = a = (XSegment *)malloc(reps * sizeof(XSegment));
153533545b5Smrg    *bp = b = (XSegment *)malloc(reps * sizeof(XSegment));
154264fa531Smrg    for (i = 0; i != reps; i++) {
155533545b5Smrg	a[i].x1 = x1 * div / mul;
156533545b5Smrg	a[i].y1 = y1 * div / mul;
157533545b5Smrg	a[i].x2 = x2 * div / mul;
158533545b5Smrg	a[i].y2 = y2 * div / mul;
159264fa531Smrg
160264fa531Smrg	/* Move x2, y2, location backward */
161264fa531Smrg	x2 -= xinc;
162264fa531Smrg	if (x2 < 0) {
163264fa531Smrg	    x2 = NegMod(x2, width);
164264fa531Smrg	    y2 -= yinc;
165264fa531Smrg	    if (y2 < 0) {
166264fa531Smrg		y2 = NegMod(y2, height);
167264fa531Smrg	    }
168264fa531Smrg	}
169264fa531Smrg
170533545b5Smrg	b[i].x1 = x1 * div / mul;
171533545b5Smrg	b[i].y1 = y1 * div / mul;
172533545b5Smrg	b[i].x2 = x2 * div / mul;
173533545b5Smrg	b[i].y2 = y2 * div / mul;
174264fa531Smrg
175264fa531Smrg	/* Move x1, y1 location forward */
176264fa531Smrg	x1 += xinc;
177264fa531Smrg	if (x1 > width) {
178264fa531Smrg	    x1 %= 32;
179264fa531Smrg	    y1 += yinc;
180264fa531Smrg	    if (y1 > height) {
181264fa531Smrg		y1 %= 32;
182264fa531Smrg	    }
183264fa531Smrg	}
184264fa531Smrg    } /* end for */
185264fa531Smrg}
186264fa531Smrg
187264fa531Smrg
188264fa531Smrgint
189533545b5SmrgInitCopyWin(XParms xp, Parms p, int64_t reps)
190264fa531Smrg{
191264fa531Smrg    (void) InitScroll(xp, p, reps);
192533545b5Smrg    InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb);
193264fa531Smrg    return reps;
194264fa531Smrg}
195264fa531Smrg
196264fa531Smrgint
197533545b5SmrgInitCopyPix(XParms xp, Parms p, int64_t reps)
198264fa531Smrg{
199264fa531Smrg    GC		pixgc;
200264fa531Smrg    (void) InitCopyWin(xp, p, reps);
201264fa531Smrg
202264fa531Smrg    /* Create pixmap to write stuff into, and initialize it */
203264fa531Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, xp->vinfo.depth);
204c37a63b8Smrg    pixgc = XCreateGC(xp->d, pix, 0, NULL);
205264fa531Smrg    /* need a gc with GXcopy cos pixmaps contain junk on creation. mmm */
206264fa531Smrg    XCopyArea(xp->d, xp->w, pix, pixgc, 0, 0, WIDTH, HEIGHT, 0, 0);
207264fa531Smrg    XFreeGC(xp->d, pixgc);
208264fa531Smrg    return reps;
209264fa531Smrg}
210264fa531Smrg
211264fa531Smrgint
212533545b5SmrgInitGetImage(XParms xp, Parms p, int64_t reps)
213264fa531Smrg{
214264fa531Smrg    (void) InitCopyWin(xp, p, reps);
215264fa531Smrg
216264fa531Smrg    /* Create image to stuff bits into */
217264fa531Smrg    image = XGetImage(xp->d, xp->w, 0, 0, WIDTH, HEIGHT, xp->planemask,
218c37a63b8Smrg		      p->font==NULL?ZPixmap:XYPixmap);
219c37a63b8Smrg    if(image==NULL){
220264fa531Smrg	printf("XGetImage failed\n");
221264fa531Smrg	return False;
222264fa531Smrg    }
223264fa531Smrg    return reps;
224264fa531Smrg}
225264fa531Smrg
226264fa531Smrgint
227533545b5SmrgInitPutImage(XParms xp, Parms p, int64_t reps)
228264fa531Smrg{
229264fa531Smrg    if(!InitGetImage(xp, p, reps))return False;
230264fa531Smrg    XClearWindow(xp->d, xp->w);
231264fa531Smrg    return reps;
232264fa531Smrg}
233264fa531Smrg
234264fa531Smrgstatic void
235533545b5SmrgCopyArea(XParms xp, Parms p, int64_t reps, Drawable src, Drawable dst)
236264fa531Smrg{
237264fa531Smrg    int i, size;
238264fa531Smrg    XSegment *sa, *sb;
239264fa531Smrg
240264fa531Smrg    size = p->special;
241264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
242264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
243264fa531Smrg	    sa->x1, sa->y1, size, size, sa->x2, sa->y2);
244264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
245264fa531Smrg	    sa->x2, sa->y2, size, size, sa->x1, sa->y1);
246264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
247264fa531Smrg	    sb->x2, sb->y2, size, size, sb->x1, sb->y1);
248264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
249264fa531Smrg	    sb->x1, sb->y1, size, size, sb->x2, sb->y2);
250264fa531Smrg	CheckAbort ();
251264fa531Smrg    }
252264fa531Smrg}
253264fa531Smrg
254264fa531Smrgvoid
255533545b5SmrgDoCopyWinWin(XParms xp, Parms p, int64_t reps)
256264fa531Smrg{
257264fa531Smrg    CopyArea(xp, p, reps, xp->w, xp->w);
258264fa531Smrg}
259264fa531Smrg
260264fa531Smrgvoid
261533545b5SmrgDoCopyPixWin(XParms xp, Parms p, int64_t reps)
262264fa531Smrg{
263264fa531Smrg    CopyArea(xp, p, reps, pix, xp->w);
264264fa531Smrg}
265264fa531Smrg
266264fa531Smrgvoid
267533545b5SmrgDoCopyWinPix(XParms xp, Parms p, int64_t reps)
268264fa531Smrg{
269264fa531Smrg    CopyArea(xp, p, reps, xp->w, pix);
270264fa531Smrg    xp->p = pix;	/* HardwareSync will now sync on pixmap */
271264fa531Smrg}
272264fa531Smrg
273264fa531Smrgvoid
274533545b5SmrgDoCopyPixPix(XParms xp, Parms p, int64_t reps)
275264fa531Smrg{
276264fa531Smrg    CopyArea(xp, p, reps, pix, pix);
277264fa531Smrg    xp->p = pix;	/* HardwareSync will now sync on pixmap */
278264fa531Smrg}
279264fa531Smrg
280264fa531Smrgvoid
281533545b5SmrgDoGetImage(XParms xp, Parms p, int64_t reps)
282264fa531Smrg{
283264fa531Smrg    int i, size;
284264fa531Smrg    XSegment *sa, *sb;
285264fa531Smrg    int format;
286264fa531Smrg
287264fa531Smrg    size = p->special;
288c37a63b8Smrg    format = (p->font == NULL) ? ZPixmap : XYPixmap;
289264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
290264fa531Smrg	XDestroyImage(image);
291264fa531Smrg	image = XGetImage(xp->d, xp->w, sa->x1, sa->y1, size, size,
292264fa531Smrg	    xp->planemask, format);
293264fa531Smrg	if (image) XDestroyImage(image);
294264fa531Smrg	image = XGetImage(xp->d, xp->w, sa->x2, sa->y2, size, size,
295264fa531Smrg	    xp->planemask, format);
296264fa531Smrg	if (image) XDestroyImage(image);
297264fa531Smrg	image = XGetImage(xp->d, xp->w, sb->x2, sb->y2, size, size,
298264fa531Smrg	    xp->planemask, format);
299264fa531Smrg	if (image) XDestroyImage(image);
300264fa531Smrg	image = XGetImage(xp->d, xp->w, sb->x1, sb->y1, size, size,
301264fa531Smrg	    xp->planemask, format);
302264fa531Smrg/*
303264fa531Smrg
304264fa531SmrgOne might expect XGetSubImage to be slightly faster than XGetImage.  Go look
305264fa531Smrgat the code in Xlib.  MIT X11R3 ran approximately 30 times slower for a 500x500
306264fa531Smrgrectangle.
307264fa531Smrg
308264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sa->x1, sa->y1, size, size,
309264fa531Smrg	    xp->planemask, ZPixmap, image, sa->x2, sa->y2);
310264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sa->x2, sa->y2, size, size,
311264fa531Smrg	    xp->planemask, ZPixmap, image, sa->x1, sa->y1);
312264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sb->x2, sb->y2, size, size,
313264fa531Smrg	    xp->planemask, ZPixmap, image, sb->x2, sb->y2);
314264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sb->x1, sb->y1, size, size,
315264fa531Smrg	    xp->planemask, ZPixmap, image, sb->x2, sb->y2);
316264fa531Smrg*/
317264fa531Smrg	CheckAbort ();
318264fa531Smrg    }
319264fa531Smrg}
320264fa531Smrg
321264fa531Smrgvoid
322533545b5SmrgDoPutImage(XParms xp, Parms p, int64_t reps)
323264fa531Smrg{
324264fa531Smrg    int i, size;
325264fa531Smrg    XSegment *sa, *sb;
326264fa531Smrg
327264fa531Smrg    size = p->special;
328264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
329264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
330264fa531Smrg	    sa->x1, sa->y1, sa->x2, sa->y2, size, size);
331264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
332264fa531Smrg	    sa->x2, sa->y2, sa->x1, sa->y1, size, size);
333264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
334264fa531Smrg	    sb->x2, sb->y2, sb->x2, sb->y2, size, size);
335264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
336264fa531Smrg	    sb->x1, sb->y1, sb->x2, sb->y2, size, size);
337264fa531Smrg	CheckAbort ();
338264fa531Smrg    }
339264fa531Smrg}
340264fa531Smrg
341264fa531Smrg#ifdef MITSHM
342264fa531Smrg
343264fa531Smrg#include <sys/types.h>
344264fa531Smrg#ifndef Lynx
345264fa531Smrg#include <sys/ipc.h>
346264fa531Smrg#include <sys/shm.h>
347264fa531Smrg#else
348264fa531Smrg#include <ipc.h>
349264fa531Smrg#include <shm.h>
350264fa531Smrg#endif
351264fa531Smrg#include <X11/extensions/XShm.h>
352264fa531Smrg
353264fa531Smrgstatic XImage		shm_image;
354264fa531Smrgstatic XShmSegmentInfo	shm_info;
355264fa531Smrg
356264fa531Smrgstatic int haderror;
357264fa531Smrgstatic int (*origerrorhandler)(Display *, XErrorEvent *);
358264fa531Smrg
359264fa531Smrgstatic int
360264fa531Smrgshmerrorhandler(Display *d, XErrorEvent *e)
361264fa531Smrg{
362264fa531Smrg    haderror++;
363264fa531Smrg    if(e->error_code==BadAccess) {
364264fa531Smrg	fprintf(stderr,"failed to attach shared memory\n");
365264fa531Smrg	return 0;
366264fa531Smrg    } else
367264fa531Smrg	return (*origerrorhandler)(d,e);
368264fa531Smrg}
369264fa531Smrg
370e4ee1255Smrgstatic int
371533545b5SmrgInitShmImage(XParms xp, Parms p, int64_t reps, Bool read_only)
372264fa531Smrg{
373264fa531Smrg    int	image_size;
374264fa531Smrg
375264fa531Smrg    if(!InitGetImage(xp, p, reps))return False;
376264fa531Smrg    if (!XShmQueryExtension(xp->d)) {
377264fa531Smrg	/*
378264fa531Smrg 	 * Clean up here because cleanup function is not called if this
379264fa531Smrg	 * function fails
380264fa531Smrg	 */
381264fa531Smrg       	if (image)
382264fa531Smrg      	    XDestroyImage(image);
383264fa531Smrg    	image = NULL;
384264fa531Smrg    	free(segsa);
385264fa531Smrg    	free(segsb);
386264fa531Smrg    	return False;
387264fa531Smrg    }
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    }
407c37a63b8Smrg    shm_info.shmaddr = (char *) shmat(shm_info.shmid, NULL, 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");
420c37a63b8Smrg	shmctl (shm_info.shmid, IPC_RMID, NULL);
421264fa531Smrg	return False;
422264fa531Smrg    }
423e4ee1255Smrg    shm_info.readOnly = read_only;
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:");
442c37a63b8Smrg	if(shmctl (shm_info.shmid, IPC_RMID, NULL)==-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
452e4ee1255Smrgint
453533545b5SmrgInitShmPutImage(XParms xp, Parms p, int64_t reps)
454e4ee1255Smrg{
455e4ee1255Smrg    if (!InitShmImage(xp, p, reps, True)) return False;
456e4ee1255Smrg    XClearWindow(xp->d, xp->w);
457e4ee1255Smrg    return reps;
458e4ee1255Smrg}
459e4ee1255Smrg
460e4ee1255Smrgint
461533545b5SmrgInitShmGetImage(XParms xp, Parms p, int64_t reps)
462e4ee1255Smrg{
463e4ee1255Smrg    return InitShmImage(xp, p, reps, False);
464e4ee1255Smrg}
465e4ee1255Smrg
466533545b5Smrgvoid
467533545b5SmrgDoShmPutImage(XParms xp, Parms p, int64_t reps)
468264fa531Smrg{
469264fa531Smrg    int i, size;
470264fa531Smrg    XSegment *sa, *sb;
471264fa531Smrg
472264fa531Smrg    size = p->special;
473264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
474264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
475264fa531Smrg	    sa->x1, sa->y1, sa->x2, sa->y2, size, size, False);
476264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
477264fa531Smrg	    sa->x2, sa->y2, sa->x1, sa->y1, size, size, False);
478264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
479264fa531Smrg	    sb->x2, sb->y2, sb->x2, sb->y2, size, size, False);
480264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
481264fa531Smrg	    sb->x1, sb->y1, sb->x2, sb->y2, size, size, False);
482264fa531Smrg	CheckAbort ();
483264fa531Smrg    }
484264fa531Smrg}
485264fa531Smrg
486e4ee1255Smrgvoid
487533545b5SmrgDoShmGetImage(XParms xp, Parms p, int64_t reps)
488264fa531Smrg{
489e4ee1255Smrg    int i, size;
490e4ee1255Smrg    XSegment *sa, *sb;
491e4ee1255Smrg
492e4ee1255Smrg    size = p->special;
493e4ee1255Smrg
494e4ee1255Smrg    shm_image.width = size;
495e4ee1255Smrg    shm_image.height = size;
496e4ee1255Smrg
497e4ee1255Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
498e4ee1255Smrg	/* compute offsets into image data? */
499e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sa->x1, sa->y1, xp->planemask);
500e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sa->x2, sa->y2, xp->planemask);
501e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sb->x2, sb->y2, xp->planemask);
502e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sb->x1, sb->y1, xp->planemask);
503e4ee1255Smrg	CheckAbort ();
504e4ee1255Smrg    }
505e4ee1255Smrg}
506264fa531Smrg
507e4ee1255Smrgstatic void
508e4ee1255SmrgEndShmImage(XParms xp, Parms p)
509e4ee1255Smrg{
510264fa531Smrg    EndGetImage (xp, p);
511264fa531Smrg    XShmDetach (xp->d, &shm_info);
512264fa531Smrg    XSync(xp->d, False);	/* need server to detach so can remove id */
513264fa531Smrg    if(shmdt (shm_info.shmaddr)==-1)
514264fa531Smrg	perror("shmdt:");
515c37a63b8Smrg    if(shmctl (shm_info.shmid, IPC_RMID, NULL)==-1)
516264fa531Smrg	perror("shmctl rmid:");
517264fa531Smrg}
518264fa531Smrg
519e4ee1255Smrgvoid
520e4ee1255SmrgEndShmGetImage(XParms xp, Parms p)
521e4ee1255Smrg{
522e4ee1255Smrg    EndShmImage(xp, p);
523e4ee1255Smrg}
524e4ee1255Smrg
525e4ee1255Smrgvoid
526e4ee1255SmrgEndShmPutImage(XParms xp, Parms p)
527e4ee1255Smrg{
528e4ee1255Smrg    EndShmImage(xp, p);
529e4ee1255Smrg}
530264fa531Smrg#endif
531264fa531Smrg
532264fa531Smrg
533264fa531Smrgvoid
534264fa531SmrgMidCopyPix(XParms xp, Parms p)
535264fa531Smrg{
536264fa531Smrg    XClearWindow(xp->d, xp->w);
537264fa531Smrg}
538264fa531Smrg
539264fa531Smrgvoid
540264fa531SmrgEndCopyWin(XParms xp, Parms p)
541264fa531Smrg{
542264fa531Smrg    EndScroll(xp, p);
543264fa531Smrg    free(segsa);
544264fa531Smrg    free(segsb);
545533545b5Smrg    if (segsa2)
546533545b5Smrg	free (segsa2);
547533545b5Smrg    if (segsb2)
548533545b5Smrg	free (segsb2);
549533545b5Smrg    segsa = segsb = segsa2 = segsb2 = NULL;
550264fa531Smrg}
551264fa531Smrg
552264fa531Smrgvoid
553264fa531SmrgEndCopyPix(XParms xp, Parms p)
554264fa531Smrg{
555264fa531Smrg    EndCopyWin(xp, p);
556264fa531Smrg    XFreePixmap(xp->d, pix);
557264fa531Smrg    /*
558264fa531Smrg     * Ensure that the next test doesn't try and sync on the pixmap
559264fa531Smrg     */
560264fa531Smrg    xp->p = (Pixmap)0;
561264fa531Smrg}
562264fa531Smrg
563264fa531Smrgvoid
564264fa531SmrgEndGetImage(XParms xp, Parms p)
565264fa531Smrg{
566264fa531Smrg    EndCopyWin(xp, p);
567264fa531Smrg    if (image) XDestroyImage(image);
568264fa531Smrg}
569264fa531Smrg
570264fa531Smrgint
571533545b5SmrgInitCopyPlane(XParms xp, Parms p, int64_t reps)
572264fa531Smrg{
573264fa531Smrg    XGCValues   gcv;
574264fa531Smrg    GC		pixgc;
575264fa531Smrg
576264fa531Smrg    InitBltLines();
577533545b5Smrg    InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb);
578264fa531Smrg
579264fa531Smrg    /* Create pixmap to write stuff into, and initialize it */
580264fa531Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT,
581c37a63b8Smrg	    p->font==NULL ? 1 : xp->vinfo.depth);
582264fa531Smrg    gcv.graphics_exposures = False;
583264fa531Smrg    gcv.foreground = 0;
584264fa531Smrg    gcv.background = 1;
585264fa531Smrg    pixgc = XCreateGC(xp->d, pix,
586264fa531Smrg		GCForeground | GCBackground | GCGraphicsExposures, &gcv);
587264fa531Smrg    XFillRectangle(xp->d, pix, pixgc, 0, 0, WIDTH, HEIGHT);
588264fa531Smrg    gcv.foreground = 1;
589264fa531Smrg    gcv.background = 0;
590264fa531Smrg    XChangeGC(xp->d, pixgc, GCForeground | GCBackground, &gcv);
591264fa531Smrg    XDrawLines(xp->d, pix, pixgc, points, NUMPOINTS, CoordModeOrigin);
592264fa531Smrg    XFreeGC(xp->d, pixgc);
593264fa531Smrg
594264fa531Smrg    return reps;
595264fa531Smrg}
596264fa531Smrg
597264fa531Smrgvoid
598533545b5SmrgDoCopyPlane(XParms xp, Parms p, int64_t reps)
599264fa531Smrg{
600264fa531Smrg    int		i, size;
601264fa531Smrg    XSegment    *sa, *sb;
602264fa531Smrg
603264fa531Smrg    size = p->special;
604264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
605264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
606264fa531Smrg	    sa->x1, sa->y1, size, size, sa->x2, sa->y2, 1);
607264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
608264fa531Smrg	    sa->x2, sa->y2, size, size, sa->x1, sa->y1, 1);
609264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
610264fa531Smrg	    sb->x2, sb->y2, size, size, sb->x1, sb->y1, 1);
611264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
612264fa531Smrg	    sb->x1, sb->y1, size, size, sb->x2, sb->y2, 1);
613264fa531Smrg	CheckAbort ();
614264fa531Smrg    }
615264fa531Smrg}
616264fa531Smrg
617c37a63b8Smrg#include <X11/extensions/Xrender.h>
618c37a63b8Smrg
619c37a63b8Smrgstatic Picture	winPict, pixPict;
620c37a63b8Smrg
621c37a63b8Smrgint
622533545b5SmrgInitCompositeWin(XParms xp, Parms p, int64_t reps)
623c37a63b8Smrg{
624c37a63b8Smrg    XRenderPictFormat	*format;
625533545b5Smrg
626c37a63b8Smrg    (void) InitScroll (xp, p, reps);
627533545b5Smrg    InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb);
628533545b5Smrg    if (p->fillStyle) {
629533545b5Smrg	int mul = 0x10000;
630533545b5Smrg	int div = p->fillStyle;
631533545b5Smrg	InitCopyLocations (p->special, mul, div, reps, &segsa2, &segsb2);
632533545b5Smrg    }
633c37a63b8Smrg    format = XRenderFindVisualFormat (xp->d, xp->vinfo.visual);
634c37a63b8Smrg    winPict = XRenderCreatePicture (xp->d, xp->w, format, 0, NULL);
635c37a63b8Smrg    return reps;
636c37a63b8Smrg}
637c37a63b8Smrg
638c37a63b8Smrgint
639533545b5SmrgInitCompositePix(XParms xp, Parms p, int64_t reps)
640c37a63b8Smrg{
641c37a63b8Smrg    XRenderPictFormat	*format = NULL;
642c37a63b8Smrg    int			depth;
643533545b5Smrg    static XRenderColor c = { 0xffff, 0x0000, 0xffff, 0xffff };
644c37a63b8Smrg
645c37a63b8Smrg    (void) InitCompositeWin (xp, p, reps);
646c37a63b8Smrg
647c37a63b8Smrg    /* Create pixmap to write stuff into, and initialize it */
648c37a63b8Smrg    switch (xp->planemask) {
649c37a63b8Smrg    case PictStandardNative:
650c37a63b8Smrg	depth = xp->vinfo.depth;
651c37a63b8Smrg	format = XRenderFindVisualFormat (xp->d, xp->vinfo.visual);
652c37a63b8Smrg	break;
653c37a63b8Smrg    case PictStandardRGB24:
654c37a63b8Smrg	depth = 24;
655c37a63b8Smrg	break;
656c37a63b8Smrg    case PictStandardARGB32:
657c37a63b8Smrg	depth = 32;
658c37a63b8Smrg	break;
659c37a63b8Smrg    case PictStandardA8:
660c37a63b8Smrg	depth = 8;
661c37a63b8Smrg	break;
662c37a63b8Smrg    case PictStandardA4:
663c37a63b8Smrg	depth = 4;
664c37a63b8Smrg	break;
665c37a63b8Smrg    case PictStandardA1:
666c37a63b8Smrg	depth = 1;
667c37a63b8Smrg	break;
668c37a63b8Smrg    default:
669c37a63b8Smrg	depth = 0;
670c37a63b8Smrg	break;
671c37a63b8Smrg    }
672c37a63b8Smrg    if (!format)
673c37a63b8Smrg	format = XRenderFindStandardFormat (xp->d, xp->planemask);
674c37a63b8Smrg
675c37a63b8Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, depth);
676c37a63b8Smrg    pixPict = XRenderCreatePicture (xp->d, pix, format, 0, NULL);
677c37a63b8Smrg
678c37a63b8Smrg    XRenderComposite (xp->d, PictOpClear,
679c37a63b8Smrg		      winPict, None, pixPict,
680c37a63b8Smrg		      0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
681c37a63b8Smrg
682533545b5Smrg    XRenderFillRectangle (xp->d, PictOpSrc,
683533545b5Smrg			  pixPict, &c, 0, 0, WIDTH, HEIGHT);
684c37a63b8Smrg#if 1
685533545b5Smrg    XRenderComposite (xp->d, PictOpSrc,
686c37a63b8Smrg		      winPict, None, pixPict,
687c37a63b8Smrg		      0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
688c37a63b8Smrg#endif
689533545b5Smrg    if (p->fillStyle) {
690533545b5Smrg	XTransform		transform;
691533545b5Smrg	memset (&transform, '\0', sizeof (transform));
692533545b5Smrg	transform.matrix[0][0] = ((long long) 0x10000 * 0x10000) / p->fillStyle;
693533545b5Smrg	transform.matrix[1][1] = ((long long) 0x10000 * 0x10000) / p->fillStyle;
694533545b5Smrg	transform.matrix[2][2] = 0x10000;
695533545b5Smrg	XRenderSetPictureTransform (xp->d, pixPict, &transform);
696533545b5Smrg	XRenderSetPictureFilter (xp->d, pixPict, FilterBilinear, NULL, 0);
697533545b5Smrg    }
698c37a63b8Smrg    return reps;
699c37a63b8Smrg}
700c37a63b8Smrg
701c37a63b8Smrgvoid
702c37a63b8SmrgEndCompositeWin (XParms xp, Parms p)
703c37a63b8Smrg{
704c37a63b8Smrg    if (winPict)
705c37a63b8Smrg    {
706c37a63b8Smrg	XRenderFreePicture (xp->d, winPict);
707c37a63b8Smrg	winPict = None;
708c37a63b8Smrg    }
709c37a63b8Smrg    if (pixPict)
710c37a63b8Smrg    {
711c37a63b8Smrg	XRenderFreePicture (xp->d, pixPict);
712c37a63b8Smrg	pixPict = None;
713c37a63b8Smrg    }
714c37a63b8Smrg}
715c37a63b8Smrg
716c37a63b8Smrgstatic void
717533545b5SmrgCompositeArea(XParms xp, Parms p, int64_t reps, Picture src, Picture dst)
718c37a63b8Smrg{
719c37a63b8Smrg    int i, size;
720c37a63b8Smrg    XSegment *sa, *sb;
721533545b5Smrg    XSegment *sa2, *sb2;
722533545b5Smrg
723c37a63b8Smrg
724c37a63b8Smrg    size = p->special;
725533545b5Smrg    sa = segsa;
726533545b5Smrg    sb = segsb;
727533545b5Smrg    sa2 = segsa2 ? segsa2 : segsa;
728533545b5Smrg    sb2 = segsb2 ? segsb2 : segsb;
729533545b5Smrg    for (i = 0; i < reps; i++) {
730c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
731c37a63b8Smrg			  src, None, dst,
732533545b5Smrg			  sa2->x1, sa2->y1, 0, 0, sa->x2, sa->y2, size, size);
733c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
734c37a63b8Smrg			  src, None, dst,
735533545b5Smrg			  sa2->x2, sa2->y2, 0, 0, sa->x1, sa->y1, size, size);
736c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
737c37a63b8Smrg			  src, None, dst,
738533545b5Smrg			  sb2->x2, sb2->y2, 0, 0, sb->x1, sb->y1, size, size);
739c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
740c37a63b8Smrg			  src, None, dst,
741533545b5Smrg			  sb2->x1, sb2->y1, 0, 0, sb->x2, sb->y2, size, size);
742c37a63b8Smrg	CheckAbort ();
743533545b5Smrg	sa++; sb++;
744533545b5Smrg	sa2++; sb2++;
745c37a63b8Smrg    }
746c37a63b8Smrg}
747c37a63b8Smrg
748c37a63b8Smrgvoid
749533545b5SmrgDoCompositeWinWin (XParms xp, Parms p, int64_t reps)
750c37a63b8Smrg{
751c37a63b8Smrg    CompositeArea (xp, p, reps, winPict, winPict);
752c37a63b8Smrg}
753c37a63b8Smrg
754c37a63b8Smrgvoid
755533545b5SmrgDoCompositePixWin (XParms xp, Parms p, int64_t reps)
756c37a63b8Smrg{
757c37a63b8Smrg    CompositeArea (xp, p, reps, pixPict, winPict);
758c37a63b8Smrg}
759