1264fa531Smrg/*****************************************************************************
2264fa531SmrgCopyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
3264fa531Smrg
4264fa531Smrg                        All Rights Reserved
5264fa531Smrg
6dfac8f13SmrgPermission to use, copy, modify, and distribute this software and its
7dfac8f13Smrgdocumentation for any purpose and without fee is hereby granted,
8264fa531Smrgprovided that the above copyright notice appear in all copies and that
9dfac8f13Smrgboth 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
12dfac8f13Smrgsoftware 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
37dfac8f13Smrgstatic void
38264fa531SmrgInitBltLines(void)
39264fa531Smrg{
40c9e4df9bSmrg    int x, y;
41264fa531Smrg
42264fa531Smrg    points[0].x = points[0].y = y = 0;
43c9e4df9bSmrg    for (int 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    }
52dfac8f13Smrg
53264fa531Smrg    x = 0;
54c9e4df9bSmrg    for (int 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
65dfac8f13Smrgint
66533545b5SmrgInitScroll(XParms xp, Parms p, int64_t reps)
67264fa531Smrg{
68264fa531Smrg    InitBltLines();
69dfac8f13Smrg    XSetFunction(xp->d, xp->fggc, GXcopy);
70264fa531Smrg    XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin);
71dfac8f13Smrg    XSetFunction(xp->d, xp->fggc, xp->func);
72264fa531Smrg    return reps;
73264fa531Smrg}
74264fa531Smrg
75dfac8f13Smrgvoid
76533545b5SmrgDoScroll(XParms xp, Parms p, int64_t reps)
77264fa531Smrg{
78c9e4df9bSmrg    int size, x, y, xorg, yorg, delta;
79264fa531Smrg
80264fa531Smrg    size = p->special;
81264fa531Smrg    xorg = 0;   yorg = 0;
82264fa531Smrg    x    = 0;   y    = 0;
83264fa531Smrg    if (xp->version == VERSION1_2) {
84264fa531Smrg	delta = 1;
85264fa531Smrg    } else {
86264fa531Smrg	/* Version 1.2 only scrolled up by 1 scanline, which made hardware
87264fa531Smrg	   using page-mode access to VRAM look better on paper than it would
88264fa531Smrg	   perform in a more realistic scroll.  So we've changed to scroll by
89264fa531Smrg	   the height of the 6x13 fonts. */
90264fa531Smrg	delta = 13;
91264fa531Smrg    }
92264fa531Smrg
93c9e4df9bSmrg    for (int i = 0; i != reps; i++) {
94264fa531Smrg	XCopyArea(xp->d, xp->w, xp->w, xp->fggc, x, y + delta,
95264fa531Smrg	    size, size, x, y);
96264fa531Smrg	y += size;
97264fa531Smrg	if (y + size + delta > HEIGHT) {
98264fa531Smrg	    yorg += delta;
99264fa531Smrg	    if (yorg >= size || yorg + size + delta > HEIGHT) {
100264fa531Smrg		yorg = 0;
101264fa531Smrg		xorg++;
102264fa531Smrg		if (xorg >= size || xorg + size > WIDTH) {
103264fa531Smrg		    xorg = 0;
104264fa531Smrg		}
105264fa531Smrg	    }
106264fa531Smrg	    y = yorg;
107264fa531Smrg	    x += size;
108264fa531Smrg	    if (x + size > WIDTH) {
109264fa531Smrg		x = xorg;
110264fa531Smrg	    }
111264fa531Smrg	}
112264fa531Smrg	CheckAbort ();
113264fa531Smrg    }
114264fa531Smrg}
115264fa531Smrg
116dfac8f13Smrgvoid
117264fa531SmrgMidScroll(XParms xp, Parms p)
118264fa531Smrg{
119264fa531Smrg    XClearWindow(xp->d, xp->w);
120264fa531Smrg    XDrawLines(xp->d, xp->w, xp->fggc, points, NUMPOINTS, CoordModeOrigin);
121264fa531Smrg}
122264fa531Smrg
123dfac8f13Smrgvoid
124264fa531SmrgEndScroll(XParms xp, Parms p)
125264fa531Smrg{
126264fa531Smrg}
127264fa531Smrg
128dfac8f13Smrgstatic void
129dfac8f13SmrgInitCopyLocations(int size, int mul, int div,
130533545b5Smrg		  int64_t reps, XSegment **ap, XSegment **bp)
131264fa531Smrg{
132c9e4df9bSmrg    int x1, y1, x2, y2;
133264fa531Smrg    int xinc, yinc;
134264fa531Smrg    int width, height;
135533545b5Smrg    XSegment *a, *b;
136264fa531Smrg
137533545b5Smrg    size = size * mul / div;
138264fa531Smrg    /* Try to exercise all alignments of src and destination equally, as well
139264fa531Smrg       as all 4 top-to-bottom/bottom-to-top, left-to-right, right-to-left
140264fa531Smrg       copying directions.  Computation done here just to make sure slow
141264fa531Smrg       machines aren't measuring anything but the XCopyArea calls.
142264fa531Smrg    */
143264fa531Smrg    xinc = (size & ~3) + 1;
144264fa531Smrg    yinc = xinc + 3;
145264fa531Smrg
146264fa531Smrg    width = (WIDTH - size) & ~31;
147264fa531Smrg    height = (HEIGHT - size) & ~31;
148dfac8f13Smrg
149264fa531Smrg    x1 = 0;
150264fa531Smrg    y1 = 0;
151264fa531Smrg    x2 = width;
152264fa531Smrg    y2 = height;
153dfac8f13Smrg
154c9e4df9bSmrg    *ap = a = malloc(reps * sizeof(XSegment));
155c9e4df9bSmrg    *bp = b = malloc(reps * sizeof(XSegment));
156c9e4df9bSmrg    for (int i = 0; i != reps; i++) {
157533545b5Smrg	a[i].x1 = x1 * div / mul;
158533545b5Smrg	a[i].y1 = y1 * div / mul;
159533545b5Smrg	a[i].x2 = x2 * div / mul;
160533545b5Smrg	a[i].y2 = y2 * div / mul;
161264fa531Smrg
162264fa531Smrg	/* Move x2, y2, location backward */
163264fa531Smrg	x2 -= xinc;
164264fa531Smrg	if (x2 < 0) {
165264fa531Smrg	    x2 = NegMod(x2, width);
166264fa531Smrg	    y2 -= yinc;
167264fa531Smrg	    if (y2 < 0) {
168264fa531Smrg		y2 = NegMod(y2, height);
169264fa531Smrg	    }
170264fa531Smrg	}
171264fa531Smrg
172533545b5Smrg	b[i].x1 = x1 * div / mul;
173533545b5Smrg	b[i].y1 = y1 * div / mul;
174533545b5Smrg	b[i].x2 = x2 * div / mul;
175533545b5Smrg	b[i].y2 = y2 * div / mul;
176264fa531Smrg
177264fa531Smrg	/* Move x1, y1 location forward */
178264fa531Smrg	x1 += xinc;
179264fa531Smrg	if (x1 > width) {
180264fa531Smrg	    x1 %= 32;
181264fa531Smrg	    y1 += yinc;
182264fa531Smrg	    if (y1 > height) {
183264fa531Smrg		y1 %= 32;
184264fa531Smrg	    }
185264fa531Smrg	}
186264fa531Smrg    } /* end for */
187264fa531Smrg}
188264fa531Smrg
189264fa531Smrg
190dfac8f13Smrgint
191533545b5SmrgInitCopyWin(XParms xp, Parms p, int64_t reps)
192264fa531Smrg{
193264fa531Smrg    (void) InitScroll(xp, p, reps);
194533545b5Smrg    InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb);
195264fa531Smrg    return reps;
196264fa531Smrg}
197264fa531Smrg
198dfac8f13Smrgint
199533545b5SmrgInitCopyPix(XParms xp, Parms p, int64_t reps)
200264fa531Smrg{
201264fa531Smrg    GC		pixgc;
202264fa531Smrg    (void) InitCopyWin(xp, p, reps);
203264fa531Smrg
204264fa531Smrg    /* Create pixmap to write stuff into, and initialize it */
205264fa531Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, xp->vinfo.depth);
206c37a63b8Smrg    pixgc = XCreateGC(xp->d, pix, 0, NULL);
207264fa531Smrg    /* need a gc with GXcopy cos pixmaps contain junk on creation. mmm */
208264fa531Smrg    XCopyArea(xp->d, xp->w, pix, pixgc, 0, 0, WIDTH, HEIGHT, 0, 0);
209264fa531Smrg    XFreeGC(xp->d, pixgc);
210264fa531Smrg    return reps;
211264fa531Smrg}
212264fa531Smrg
213dfac8f13Smrgstatic int
214dfac8f13SmrgInitImage(XParms xp, Parms p, int64_t reps, long pm)
215264fa531Smrg{
216264fa531Smrg    (void) InitCopyWin(xp, p, reps);
217264fa531Smrg
218264fa531Smrg    /* Create image to stuff bits into */
219dfac8f13Smrg    image = XGetImage(xp->d, xp->w, 0, 0, WIDTH, HEIGHT, pm,
220dfac8f13Smrg		      p->font==NULL ? ZPixmap : (strcmp(p->font, "XY") == 0? XYPixmap : ZPixmap));
221c37a63b8Smrg    if(image==NULL){
222264fa531Smrg	printf("XGetImage failed\n");
223264fa531Smrg	return False;
224dfac8f13Smrg    }
225dfac8f13Smrg    if (p->font && !strcmp(p->font, "XYBitmap")) {
226dfac8f13Smrg	    int		bytes_per_line = (WIDTH + 31) / 8;
227dfac8f13Smrg	    char	*data = malloc (bytes_per_line * HEIGHT);
228dfac8f13Smrg	    XImage	*new = XCreateImage(xp->d, xp->vinfo.visual, 1, XYBitmap, 0,
229dfac8f13Smrg					    data, WIDTH, HEIGHT, 32, bytes_per_line);
230dfac8f13Smrg	    int		x, y;
231dfac8f13Smrg	    unsigned long	zero_pixel;
232dfac8f13Smrg	    int		has_zero = 0;
233dfac8f13Smrg
234dfac8f13Smrg	    for (y = 0; y < HEIGHT; y++)
235dfac8f13Smrg		    for (x = 0; x < WIDTH; x++) {
236dfac8f13Smrg			    unsigned long src_pixel = XGetPixel(image, x, y);
237dfac8f13Smrg			    unsigned long dst_pixel = 0;
238dfac8f13Smrg			    if (!has_zero) {
239dfac8f13Smrg				    zero_pixel = src_pixel;
240dfac8f13Smrg				    has_zero = 1;
241dfac8f13Smrg			    }
242dfac8f13Smrg			    if (src_pixel == zero_pixel)
243dfac8f13Smrg				    dst_pixel = 0;
244dfac8f13Smrg			    else
245dfac8f13Smrg				    dst_pixel = 1;
246dfac8f13Smrg			    XPutPixel(new, x, y, dst_pixel);
247dfac8f13Smrg		    }
248dfac8f13Smrg	    XDestroyImage(image);
249dfac8f13Smrg	    image = new;
250dfac8f13Smrg    }
251264fa531Smrg    return reps;
252264fa531Smrg}
253264fa531Smrg
254dfac8f13Smrgint
255dfac8f13SmrgInitGetImage(XParms xp, Parms p, int64_t reps)
256dfac8f13Smrg{
257dfac8f13Smrg    return InitImage(xp, p, reps, xp->planemask);
258dfac8f13Smrg}
259dfac8f13Smrg
260dfac8f13Smrgint
261533545b5SmrgInitPutImage(XParms xp, Parms p, int64_t reps)
262264fa531Smrg{
263dfac8f13Smrg    if(!InitImage(xp, p, reps, 0xffffffff))return False;
264264fa531Smrg    XClearWindow(xp->d, xp->w);
265264fa531Smrg    return reps;
266264fa531Smrg}
267264fa531Smrg
268dfac8f13Smrgstatic void
269533545b5SmrgCopyArea(XParms xp, Parms p, int64_t reps, Drawable src, Drawable dst)
270264fa531Smrg{
271264fa531Smrg    int i, size;
272264fa531Smrg    XSegment *sa, *sb;
273264fa531Smrg
274264fa531Smrg    size = p->special;
275264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
276264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
277264fa531Smrg	    sa->x1, sa->y1, size, size, sa->x2, sa->y2);
278264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
279264fa531Smrg	    sa->x2, sa->y2, size, size, sa->x1, sa->y1);
280264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
281264fa531Smrg	    sb->x2, sb->y2, size, size, sb->x1, sb->y1);
282264fa531Smrg	XCopyArea(xp->d, src, dst, xp->fggc,
283264fa531Smrg	    sb->x1, sb->y1, size, size, sb->x2, sb->y2);
284264fa531Smrg	CheckAbort ();
285264fa531Smrg    }
286264fa531Smrg}
287264fa531Smrg
288dfac8f13Smrgvoid
289533545b5SmrgDoCopyWinWin(XParms xp, Parms p, int64_t reps)
290264fa531Smrg{
291264fa531Smrg    CopyArea(xp, p, reps, xp->w, xp->w);
292264fa531Smrg}
293264fa531Smrg
294dfac8f13Smrgvoid
295533545b5SmrgDoCopyPixWin(XParms xp, Parms p, int64_t reps)
296264fa531Smrg{
297264fa531Smrg    CopyArea(xp, p, reps, pix, xp->w);
298264fa531Smrg}
299264fa531Smrg
300dfac8f13Smrgvoid
301533545b5SmrgDoCopyWinPix(XParms xp, Parms p, int64_t reps)
302264fa531Smrg{
303264fa531Smrg    CopyArea(xp, p, reps, xp->w, pix);
304264fa531Smrg    xp->p = pix;	/* HardwareSync will now sync on pixmap */
305264fa531Smrg}
306264fa531Smrg
307dfac8f13Smrgvoid
308533545b5SmrgDoCopyPixPix(XParms xp, Parms p, int64_t reps)
309264fa531Smrg{
310264fa531Smrg    CopyArea(xp, p, reps, pix, pix);
311264fa531Smrg    xp->p = pix;	/* HardwareSync will now sync on pixmap */
312264fa531Smrg}
313264fa531Smrg
314dfac8f13Smrgvoid
315533545b5SmrgDoGetImage(XParms xp, Parms p, int64_t reps)
316264fa531Smrg{
317264fa531Smrg    int i, size;
318264fa531Smrg    XSegment *sa, *sb;
319264fa531Smrg    int format;
320264fa531Smrg
321264fa531Smrg    size = p->special;
322c37a63b8Smrg    format = (p->font == NULL) ? ZPixmap : XYPixmap;
323264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
324264fa531Smrg	XDestroyImage(image);
325264fa531Smrg	image = XGetImage(xp->d, xp->w, sa->x1, sa->y1, size, size,
326264fa531Smrg	    xp->planemask, format);
327264fa531Smrg	if (image) XDestroyImage(image);
328264fa531Smrg	image = XGetImage(xp->d, xp->w, sa->x2, sa->y2, size, size,
329264fa531Smrg	    xp->planemask, format);
330264fa531Smrg	if (image) XDestroyImage(image);
331264fa531Smrg	image = XGetImage(xp->d, xp->w, sb->x2, sb->y2, size, size,
332264fa531Smrg	    xp->planemask, format);
333264fa531Smrg	if (image) XDestroyImage(image);
334264fa531Smrg	image = XGetImage(xp->d, xp->w, sb->x1, sb->y1, size, size,
335264fa531Smrg	    xp->planemask, format);
336264fa531Smrg/*
337264fa531Smrg
338264fa531SmrgOne might expect XGetSubImage to be slightly faster than XGetImage.  Go look
339264fa531Smrgat the code in Xlib.  MIT X11R3 ran approximately 30 times slower for a 500x500
340264fa531Smrgrectangle.
341264fa531Smrg
342264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sa->x1, sa->y1, size, size,
343264fa531Smrg	    xp->planemask, ZPixmap, image, sa->x2, sa->y2);
344264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sa->x2, sa->y2, size, size,
345264fa531Smrg	    xp->planemask, ZPixmap, image, sa->x1, sa->y1);
346264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sb->x2, sb->y2, size, size,
347264fa531Smrg	    xp->planemask, ZPixmap, image, sb->x2, sb->y2);
348264fa531Smrg	(void) XGetSubImage(xp->d, xp->w, sb->x1, sb->y1, size, size,
349264fa531Smrg	    xp->planemask, ZPixmap, image, sb->x2, sb->y2);
350264fa531Smrg*/
351264fa531Smrg	CheckAbort ();
352264fa531Smrg    }
353264fa531Smrg}
354264fa531Smrg
355dfac8f13Smrgvoid
356533545b5SmrgDoPutImage(XParms xp, Parms p, int64_t reps)
357264fa531Smrg{
358264fa531Smrg    int i, size;
359264fa531Smrg    XSegment *sa, *sb;
360264fa531Smrg
361264fa531Smrg    size = p->special;
362264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
363264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
364264fa531Smrg	    sa->x1, sa->y1, sa->x2, sa->y2, size, size);
365264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
366264fa531Smrg	    sa->x2, sa->y2, sa->x1, sa->y1, size, size);
367264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
368264fa531Smrg	    sb->x2, sb->y2, sb->x2, sb->y2, size, size);
369264fa531Smrg	XPutImage(xp->d, xp->w, xp->fggc, image,
370264fa531Smrg	    sb->x1, sb->y1, sb->x2, sb->y2, size, size);
371264fa531Smrg	CheckAbort ();
372264fa531Smrg    }
373264fa531Smrg}
374264fa531Smrg
375264fa531Smrg#ifdef MITSHM
376264fa531Smrg
377264fa531Smrg#include <sys/types.h>
378264fa531Smrg#ifndef Lynx
379264fa531Smrg#include <sys/ipc.h>
380264fa531Smrg#include <sys/shm.h>
381264fa531Smrg#else
382264fa531Smrg#include <ipc.h>
383264fa531Smrg#include <shm.h>
384264fa531Smrg#endif
385264fa531Smrg#include <X11/extensions/XShm.h>
386264fa531Smrg
387264fa531Smrgstatic XImage		shm_image;
388264fa531Smrgstatic XShmSegmentInfo	shm_info;
389264fa531Smrg
390264fa531Smrgstatic int haderror;
391264fa531Smrgstatic int (*origerrorhandler)(Display *, XErrorEvent *);
392264fa531Smrg
393dfac8f13Smrgstatic int
394264fa531Smrgshmerrorhandler(Display *d, XErrorEvent *e)
395264fa531Smrg{
396264fa531Smrg    haderror++;
397264fa531Smrg    if(e->error_code==BadAccess) {
398264fa531Smrg	fprintf(stderr,"failed to attach shared memory\n");
399264fa531Smrg	return 0;
400dfac8f13Smrg    } else
401264fa531Smrg	return (*origerrorhandler)(d,e);
402264fa531Smrg}
403264fa531Smrg
404e4ee1255Smrgstatic int
405533545b5SmrgInitShmImage(XParms xp, Parms p, int64_t reps, Bool read_only)
406264fa531Smrg{
407264fa531Smrg    int	image_size;
408264fa531Smrg
409dfac8f13Smrg    if(!InitImage(xp, p, reps, 0xffffffff))return False;
410264fa531Smrg    if (!XShmQueryExtension(xp->d)) {
411264fa531Smrg	/*
412264fa531Smrg 	 * Clean up here because cleanup function is not called if this
413264fa531Smrg	 * function fails
414264fa531Smrg	 */
415264fa531Smrg       	if (image)
416264fa531Smrg      	    XDestroyImage(image);
417264fa531Smrg    	image = NULL;
418264fa531Smrg    	free(segsa);
419264fa531Smrg    	free(segsb);
420264fa531Smrg    	return False;
421dfac8f13Smrg    }
422264fa531Smrg    shm_image = *image;
423264fa531Smrg    image_size = image->bytes_per_line * image->height;
424264fa531Smrg    /* allow XYPixmap choice: */
425dfac8f13Smrg    if(p->font && strcmp(p->font, "XYBitmap") != 0) image_size *= xp->vinfo.depth;
426264fa531Smrg    shm_info.shmid = shmget(IPC_PRIVATE, image_size, IPC_CREAT|0777);
427264fa531Smrg    if (shm_info.shmid < 0)
428264fa531Smrg    {
429264fa531Smrg	/*
430264fa531Smrg	 * Clean up here because cleanup function is not called if this
431264fa531Smrg	 * function fails
432264fa531Smrg	 */
433264fa531Smrg	if (image)
434264fa531Smrg	    XDestroyImage(image);
435264fa531Smrg	image = NULL;
436264fa531Smrg	free(segsa);
437264fa531Smrg	free(segsb);
438264fa531Smrg	perror ("shmget");
439264fa531Smrg	return False;
440264fa531Smrg    }
441c37a63b8Smrg    shm_info.shmaddr = (char *) shmat(shm_info.shmid, NULL, 0);
442264fa531Smrg    if (shm_info.shmaddr == ((char *) -1))
443264fa531Smrg    {
444264fa531Smrg	/*
445264fa531Smrg	 * Clean up here because cleanup function is not called if this
446264fa531Smrg	 * function fails
447264fa531Smrg	 */
448264fa531Smrg	if (image)
449264fa531Smrg	    XDestroyImage(image);
450264fa531Smrg	image = NULL;
451264fa531Smrg	free(segsa);
452264fa531Smrg	free(segsb);
453264fa531Smrg	perror ("shmat");
454c37a63b8Smrg	shmctl (shm_info.shmid, IPC_RMID, NULL);
455264fa531Smrg	return False;
456264fa531Smrg    }
457e4ee1255Smrg    shm_info.readOnly = read_only;
458264fa531Smrg    XSync(xp->d,True);
459264fa531Smrg    haderror = False;
460264fa531Smrg    origerrorhandler = XSetErrorHandler(shmerrorhandler);
461264fa531Smrg    XShmAttach (xp->d, &shm_info);
462264fa531Smrg    XSync(xp->d,True);	/* wait for error or ok */
463264fa531Smrg    XSetErrorHandler(origerrorhandler);
464264fa531Smrg    if(haderror){
465264fa531Smrg	/*
466264fa531Smrg	 * Clean up here because cleanup function is not called if this
467264fa531Smrg	 * function fails
468264fa531Smrg	 */
469264fa531Smrg	if (image)
470264fa531Smrg	    XDestroyImage(image);
471264fa531Smrg	image = NULL;
472264fa531Smrg	free(segsa);
473264fa531Smrg	free(segsb);
474264fa531Smrg	if(shmdt (shm_info.shmaddr)==-1)
475264fa531Smrg	    perror("shmdt:");
476c37a63b8Smrg	if(shmctl (shm_info.shmid, IPC_RMID, NULL)==-1)
477264fa531Smrg	    perror("shmctl rmid:");
478264fa531Smrg	return False;
479264fa531Smrg    }
480264fa531Smrg    shm_image.data = shm_info.shmaddr;
481264fa531Smrg    memmove( shm_image.data, image->data, image_size);
482264fa531Smrg    shm_image.obdata = (char *) &shm_info;
483264fa531Smrg    return reps;
484264fa531Smrg}
485264fa531Smrg
486e4ee1255Smrgint
487533545b5SmrgInitShmPutImage(XParms xp, Parms p, int64_t reps)
488e4ee1255Smrg{
489e4ee1255Smrg    if (!InitShmImage(xp, p, reps, True)) return False;
490e4ee1255Smrg    XClearWindow(xp->d, xp->w);
491e4ee1255Smrg    return reps;
492e4ee1255Smrg}
493e4ee1255Smrg
494e4ee1255Smrgint
495533545b5SmrgInitShmGetImage(XParms xp, Parms p, int64_t reps)
496e4ee1255Smrg{
497e4ee1255Smrg    return InitShmImage(xp, p, reps, False);
498e4ee1255Smrg}
499e4ee1255Smrg
500dfac8f13Smrgvoid
501533545b5SmrgDoShmPutImage(XParms xp, Parms p, int64_t reps)
502264fa531Smrg{
503264fa531Smrg    int i, size;
504264fa531Smrg    XSegment *sa, *sb;
505264fa531Smrg
506264fa531Smrg    size = p->special;
507264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
508264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
509264fa531Smrg	    sa->x1, sa->y1, sa->x2, sa->y2, size, size, False);
510264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
511264fa531Smrg	    sa->x2, sa->y2, sa->x1, sa->y1, size, size, False);
512264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
513264fa531Smrg	    sb->x2, sb->y2, sb->x2, sb->y2, size, size, False);
514264fa531Smrg	XShmPutImage(xp->d, xp->w, xp->fggc, &shm_image,
515264fa531Smrg	    sb->x1, sb->y1, sb->x2, sb->y2, size, size, False);
516264fa531Smrg	CheckAbort ();
517264fa531Smrg    }
518264fa531Smrg}
519264fa531Smrg
520e4ee1255Smrgvoid
521533545b5SmrgDoShmGetImage(XParms xp, Parms p, int64_t reps)
522264fa531Smrg{
523e4ee1255Smrg    int i, size;
524e4ee1255Smrg    XSegment *sa, *sb;
525e4ee1255Smrg
526e4ee1255Smrg    size = p->special;
527e4ee1255Smrg
528e4ee1255Smrg    shm_image.width = size;
529e4ee1255Smrg    shm_image.height = size;
530e4ee1255Smrg
531e4ee1255Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
532e4ee1255Smrg	/* compute offsets into image data? */
533e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sa->x1, sa->y1, xp->planemask);
534e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sa->x2, sa->y2, xp->planemask);
535e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sb->x2, sb->y2, xp->planemask);
536e4ee1255Smrg	XShmGetImage(xp->d, xp->w, &shm_image, sb->x1, sb->y1, xp->planemask);
537e4ee1255Smrg	CheckAbort ();
538e4ee1255Smrg    }
539e4ee1255Smrg}
540264fa531Smrg
541e4ee1255Smrgstatic void
542e4ee1255SmrgEndShmImage(XParms xp, Parms p)
543e4ee1255Smrg{
544264fa531Smrg    EndGetImage (xp, p);
545264fa531Smrg    XShmDetach (xp->d, &shm_info);
546264fa531Smrg    XSync(xp->d, False);	/* need server to detach so can remove id */
547264fa531Smrg    if(shmdt (shm_info.shmaddr)==-1)
548264fa531Smrg	perror("shmdt:");
549c37a63b8Smrg    if(shmctl (shm_info.shmid, IPC_RMID, NULL)==-1)
550264fa531Smrg	perror("shmctl rmid:");
551264fa531Smrg}
552264fa531Smrg
553e4ee1255Smrgvoid
554e4ee1255SmrgEndShmGetImage(XParms xp, Parms p)
555e4ee1255Smrg{
556e4ee1255Smrg    EndShmImage(xp, p);
557e4ee1255Smrg}
558e4ee1255Smrg
559e4ee1255Smrgvoid
560e4ee1255SmrgEndShmPutImage(XParms xp, Parms p)
561e4ee1255Smrg{
562e4ee1255Smrg    EndShmImage(xp, p);
563e4ee1255Smrg}
564264fa531Smrg#endif
565264fa531Smrg
566264fa531Smrg
567dfac8f13Smrgvoid
568264fa531SmrgMidCopyPix(XParms xp, Parms p)
569264fa531Smrg{
570264fa531Smrg    XClearWindow(xp->d, xp->w);
571264fa531Smrg}
572264fa531Smrg
573dfac8f13Smrgvoid
574264fa531SmrgEndCopyWin(XParms xp, Parms p)
575264fa531Smrg{
576264fa531Smrg    EndScroll(xp, p);
577264fa531Smrg    free(segsa);
578264fa531Smrg    free(segsb);
579533545b5Smrg    if (segsa2)
580533545b5Smrg	free (segsa2);
581533545b5Smrg    if (segsb2)
582533545b5Smrg	free (segsb2);
583533545b5Smrg    segsa = segsb = segsa2 = segsb2 = NULL;
584264fa531Smrg}
585264fa531Smrg
586dfac8f13Smrgvoid
587264fa531SmrgEndCopyPix(XParms xp, Parms p)
588264fa531Smrg{
589264fa531Smrg    EndCopyWin(xp, p);
590264fa531Smrg    XFreePixmap(xp->d, pix);
591264fa531Smrg    /*
592264fa531Smrg     * Ensure that the next test doesn't try and sync on the pixmap
593264fa531Smrg     */
594264fa531Smrg    xp->p = (Pixmap)0;
595264fa531Smrg}
596264fa531Smrg
597dfac8f13Smrgvoid
598264fa531SmrgEndGetImage(XParms xp, Parms p)
599264fa531Smrg{
600264fa531Smrg    EndCopyWin(xp, p);
601264fa531Smrg    if (image) XDestroyImage(image);
602264fa531Smrg}
603264fa531Smrg
604264fa531Smrgint
605533545b5SmrgInitCopyPlane(XParms xp, Parms p, int64_t reps)
606264fa531Smrg{
607264fa531Smrg    XGCValues   gcv;
608264fa531Smrg    GC		pixgc;
609264fa531Smrg
610264fa531Smrg    InitBltLines();
611533545b5Smrg    InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb);
612264fa531Smrg
613264fa531Smrg    /* Create pixmap to write stuff into, and initialize it */
614dfac8f13Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT,
615c37a63b8Smrg	    p->font==NULL ? 1 : xp->vinfo.depth);
616264fa531Smrg    gcv.graphics_exposures = False;
617264fa531Smrg    gcv.foreground = 0;
618264fa531Smrg    gcv.background = 1;
619dfac8f13Smrg    pixgc = XCreateGC(xp->d, pix,
620264fa531Smrg		GCForeground | GCBackground | GCGraphicsExposures, &gcv);
621264fa531Smrg    XFillRectangle(xp->d, pix, pixgc, 0, 0, WIDTH, HEIGHT);
622264fa531Smrg    gcv.foreground = 1;
623264fa531Smrg    gcv.background = 0;
624264fa531Smrg    XChangeGC(xp->d, pixgc, GCForeground | GCBackground, &gcv);
625264fa531Smrg    XDrawLines(xp->d, pix, pixgc, points, NUMPOINTS, CoordModeOrigin);
626264fa531Smrg    XFreeGC(xp->d, pixgc);
627264fa531Smrg
628264fa531Smrg    return reps;
629264fa531Smrg}
630264fa531Smrg
631dfac8f13Smrgvoid
632533545b5SmrgDoCopyPlane(XParms xp, Parms p, int64_t reps)
633264fa531Smrg{
634264fa531Smrg    int		i, size;
635264fa531Smrg    XSegment    *sa, *sb;
636264fa531Smrg
637264fa531Smrg    size = p->special;
638264fa531Smrg    for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) {
639264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
640264fa531Smrg	    sa->x1, sa->y1, size, size, sa->x2, sa->y2, 1);
641264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
642264fa531Smrg	    sa->x2, sa->y2, size, size, sa->x1, sa->y1, 1);
643264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
644264fa531Smrg	    sb->x2, sb->y2, size, size, sb->x1, sb->y1, 1);
645264fa531Smrg	XCopyPlane(xp->d, pix, xp->w, xp->fggc,
646264fa531Smrg	    sb->x1, sb->y1, size, size, sb->x2, sb->y2, 1);
647264fa531Smrg	CheckAbort ();
648264fa531Smrg    }
649264fa531Smrg}
650264fa531Smrg
651c37a63b8Smrg#include <X11/extensions/Xrender.h>
652c37a63b8Smrg
653c37a63b8Smrgstatic Picture	winPict, pixPict;
654c37a63b8Smrg
655c37a63b8Smrgint
656533545b5SmrgInitCompositeWin(XParms xp, Parms p, int64_t reps)
657c37a63b8Smrg{
658c37a63b8Smrg    XRenderPictFormat	*format;
659533545b5Smrg
660c37a63b8Smrg    (void) InitScroll (xp, p, reps);
661533545b5Smrg    InitCopyLocations(p->special, 1, 1, reps, &segsa, &segsb);
662533545b5Smrg    if (p->fillStyle) {
663533545b5Smrg	int mul = 0x10000;
664533545b5Smrg	int div = p->fillStyle;
665533545b5Smrg	InitCopyLocations (p->special, mul, div, reps, &segsa2, &segsb2);
666533545b5Smrg    }
667c37a63b8Smrg    format = XRenderFindVisualFormat (xp->d, xp->vinfo.visual);
668c37a63b8Smrg    winPict = XRenderCreatePicture (xp->d, xp->w, format, 0, NULL);
669c37a63b8Smrg    return reps;
670c37a63b8Smrg}
671c37a63b8Smrg
672c37a63b8Smrgint
673533545b5SmrgInitCompositePix(XParms xp, Parms p, int64_t reps)
674c37a63b8Smrg{
675c37a63b8Smrg    XRenderPictFormat	*format = NULL;
676c37a63b8Smrg    int			depth;
677533545b5Smrg    static XRenderColor c = { 0xffff, 0x0000, 0xffff, 0xffff };
678c37a63b8Smrg
679c37a63b8Smrg    (void) InitCompositeWin (xp, p, reps);
680dfac8f13Smrg
681c37a63b8Smrg    /* Create pixmap to write stuff into, and initialize it */
682c37a63b8Smrg    switch (xp->planemask) {
683c37a63b8Smrg    case PictStandardNative:
684c37a63b8Smrg	depth = xp->vinfo.depth;
685c37a63b8Smrg	format = XRenderFindVisualFormat (xp->d, xp->vinfo.visual);
686c37a63b8Smrg	break;
687c37a63b8Smrg    case PictStandardRGB24:
688c37a63b8Smrg	depth = 24;
689c37a63b8Smrg	break;
690c37a63b8Smrg    case PictStandardARGB32:
691c37a63b8Smrg	depth = 32;
692c37a63b8Smrg	break;
693c37a63b8Smrg    case PictStandardA8:
694c37a63b8Smrg	depth = 8;
695c37a63b8Smrg	break;
696c37a63b8Smrg    case PictStandardA4:
697c37a63b8Smrg	depth = 4;
698c37a63b8Smrg	break;
699c37a63b8Smrg    case PictStandardA1:
700c37a63b8Smrg	depth = 1;
701c37a63b8Smrg	break;
702c37a63b8Smrg    default:
703c37a63b8Smrg	depth = 0;
704c37a63b8Smrg	break;
705c37a63b8Smrg    }
706c37a63b8Smrg    if (!format)
707c37a63b8Smrg	format = XRenderFindStandardFormat (xp->d, xp->planemask);
708dfac8f13Smrg
709c37a63b8Smrg    pix = XCreatePixmap(xp->d, xp->w, WIDTH, HEIGHT, depth);
710c37a63b8Smrg    pixPict = XRenderCreatePicture (xp->d, pix, format, 0, NULL);
711dfac8f13Smrg
712c37a63b8Smrg    XRenderComposite (xp->d, PictOpClear,
713c37a63b8Smrg		      winPict, None, pixPict,
714c37a63b8Smrg		      0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
715dfac8f13Smrg
716533545b5Smrg    XRenderFillRectangle (xp->d, PictOpSrc,
717533545b5Smrg			  pixPict, &c, 0, 0, WIDTH, HEIGHT);
718c37a63b8Smrg#if 1
719533545b5Smrg    XRenderComposite (xp->d, PictOpSrc,
720c37a63b8Smrg		      winPict, None, pixPict,
721c37a63b8Smrg		      0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
722c37a63b8Smrg#endif
723533545b5Smrg    if (p->fillStyle) {
724533545b5Smrg	XTransform		transform;
725533545b5Smrg	memset (&transform, '\0', sizeof (transform));
726533545b5Smrg	transform.matrix[0][0] = ((long long) 0x10000 * 0x10000) / p->fillStyle;
727533545b5Smrg	transform.matrix[1][1] = ((long long) 0x10000 * 0x10000) / p->fillStyle;
728533545b5Smrg	transform.matrix[2][2] = 0x10000;
729533545b5Smrg	XRenderSetPictureTransform (xp->d, pixPict, &transform);
730533545b5Smrg	XRenderSetPictureFilter (xp->d, pixPict, FilterBilinear, NULL, 0);
731533545b5Smrg    }
732c37a63b8Smrg    return reps;
733c37a63b8Smrg}
734c37a63b8Smrg
735c37a63b8Smrgvoid
736c37a63b8SmrgEndCompositeWin (XParms xp, Parms p)
737c37a63b8Smrg{
738c37a63b8Smrg    if (winPict)
739c37a63b8Smrg    {
740c37a63b8Smrg	XRenderFreePicture (xp->d, winPict);
741c37a63b8Smrg	winPict = None;
742c37a63b8Smrg    }
743c37a63b8Smrg    if (pixPict)
744c37a63b8Smrg    {
745c37a63b8Smrg	XRenderFreePicture (xp->d, pixPict);
746c37a63b8Smrg	pixPict = None;
747c37a63b8Smrg    }
748c37a63b8Smrg}
749c37a63b8Smrg
750dfac8f13Smrgstatic void
751533545b5SmrgCompositeArea(XParms xp, Parms p, int64_t reps, Picture src, Picture dst)
752c37a63b8Smrg{
753c9e4df9bSmrg    int size;
754c37a63b8Smrg    XSegment *sa, *sb;
755533545b5Smrg    XSegment *sa2, *sb2;
756dfac8f13Smrg
757c37a63b8Smrg
758c37a63b8Smrg    size = p->special;
759533545b5Smrg    sa = segsa;
760533545b5Smrg    sb = segsb;
761533545b5Smrg    sa2 = segsa2 ? segsa2 : segsa;
762533545b5Smrg    sb2 = segsb2 ? segsb2 : segsb;
763c9e4df9bSmrg    for (int i = 0; i < reps; i++) {
764c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
765c37a63b8Smrg			  src, None, dst,
766533545b5Smrg			  sa2->x1, sa2->y1, 0, 0, sa->x2, sa->y2, size, size);
767c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
768c37a63b8Smrg			  src, None, dst,
769533545b5Smrg			  sa2->x2, sa2->y2, 0, 0, sa->x1, sa->y1, size, size);
770c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
771c37a63b8Smrg			  src, None, dst,
772533545b5Smrg			  sb2->x2, sb2->y2, 0, 0, sb->x1, sb->y1, size, size);
773c37a63b8Smrg	XRenderComposite (xp->d, xp->func,
774c37a63b8Smrg			  src, None, dst,
775533545b5Smrg			  sb2->x1, sb2->y1, 0, 0, sb->x2, sb->y2, size, size);
776c37a63b8Smrg	CheckAbort ();
777533545b5Smrg	sa++; sb++;
778533545b5Smrg	sa2++; sb2++;
779c37a63b8Smrg    }
780c37a63b8Smrg}
781c37a63b8Smrg
782c37a63b8Smrgvoid
783533545b5SmrgDoCompositeWinWin (XParms xp, Parms p, int64_t reps)
784c37a63b8Smrg{
785c37a63b8Smrg    CompositeArea (xp, p, reps, winPict, winPict);
786c37a63b8Smrg}
787c37a63b8Smrg
788c37a63b8Smrgvoid
789533545b5SmrgDoCompositePixWin (XParms xp, Parms p, int64_t reps)
790c37a63b8Smrg{
791c37a63b8Smrg    CompositeArea (xp, p, reps, pixPict, winPict);
792c37a63b8Smrg}
793