103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 1998 Keith Packard
303b705cfSriastradh * Copyright © 2012 Intel Corporation
403b705cfSriastradh *
503b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its
603b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that
703b705cfSriastradh * the above copyright notice appear in all copies and that both that
803b705cfSriastradh * copyright notice and this permission notice appear in supporting
903b705cfSriastradh * documentation, and that the name of Keith Packard not be used in
1003b705cfSriastradh * advertising or publicity pertaining to distribution of the software without
1103b705cfSriastradh * specific, written prior permission.  Keith Packard makes no
1203b705cfSriastradh * representations about the suitability of this software for any purpose.  It
1303b705cfSriastradh * is provided "as is" without express or implied warranty.
1403b705cfSriastradh *
1503b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1603b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1703b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1803b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1903b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2003b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2103b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE.
2203b705cfSriastradh */
2303b705cfSriastradh
2403b705cfSriastradh#include <string.h>
2503b705cfSriastradh
2603b705cfSriastradh#include "fb.h"
2703b705cfSriastradh#include "fbclip.h"
2803b705cfSriastradh
2903b705cfSriastradhstruct fbPutZImage {
3003b705cfSriastradh	FbStip *src, *dst;
3103b705cfSriastradh	FbStride src_stride, dst_stride;
3203b705cfSriastradh
3303b705cfSriastradh	int dst_x, dst_y;
3403b705cfSriastradh	int x0, y0;
3503b705cfSriastradh};
3603b705cfSriastradh
3703b705cfSriastradhinline static void
3803b705cfSriastradh_fbPutZImage(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
3903b705cfSriastradh{
4003b705cfSriastradh	struct fbPutZImage *data = _data;
4103b705cfSriastradh	int bpp = drawable->bitsPerPixel;
4203b705cfSriastradh
4303b705cfSriastradh	fbBltStip(data->src + (b->y1 - data->y0) * data->src_stride, data->src_stride,
4403b705cfSriastradh		  (b->x1 - data->x0) * bpp,
4503b705cfSriastradh		  data->dst + (b->y1 + data->dst_y) * data->dst_stride,
4603b705cfSriastradh		  data->dst_stride,
4703b705cfSriastradh		  (b->x1 + data->dst_x) * bpp,
4803b705cfSriastradh		  (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
4903b705cfSriastradh		  gc->alu, fb_gc(gc)->pm, bpp);
5003b705cfSriastradh}
5103b705cfSriastradh
5203b705cfSriastradhstatic void
5303b705cfSriastradhfbPutZImage(DrawablePtr drawable, GCPtr gc,
5403b705cfSriastradh            int x, int y, int width, int height,
5503b705cfSriastradh	    FbStip *src, FbStride srcStride)
5603b705cfSriastradh{
5703b705cfSriastradh	PixmapPtr pixmap;
5803b705cfSriastradh	struct fbPutZImage data;
5903b705cfSriastradh	BoxRec box;
6003b705cfSriastradh
6103b705cfSriastradh	box.x1 = data.x0 = x;
6203b705cfSriastradh	box.y1 = data.y0 = y;
6303b705cfSriastradh	box.x2 = x + width;
6403b705cfSriastradh	box.y2 = y + height;
6503b705cfSriastradh	data.src = src;
6603b705cfSriastradh	data.src_stride = srcStride;
6703b705cfSriastradh
6803b705cfSriastradh	fbGetDrawablePixmap(drawable, pixmap, data.dst_x, data.dst_y);
6903b705cfSriastradh	data.dst = pixmap->devPrivate.ptr;
7003b705cfSriastradh	data.dst_stride = pixmap->devKind / sizeof(FbStip);
7103b705cfSriastradh
7203b705cfSriastradh	fbDrawableRun(drawable, gc, &box, _fbPutZImage, &data);
7303b705cfSriastradh}
7403b705cfSriastradh
7503b705cfSriastradhstruct fbPutXYImage {
7603b705cfSriastradh	FbStip *src, *dst;
7703b705cfSriastradh	FbStride src_stride, dst_stride;
7803b705cfSriastradh
7903b705cfSriastradh	int dst_x, dst_y, src_x;
8003b705cfSriastradh	int x0, y0;
8103b705cfSriastradh
8203b705cfSriastradh	int alu, pm;
8303b705cfSriastradh	FbBits fgand, fgxor, bgand, bgxor;
8403b705cfSriastradh};
8503b705cfSriastradh
8603b705cfSriastradhinline static void
8703b705cfSriastradh_fbPutXYImage1(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
8803b705cfSriastradh{
8903b705cfSriastradh	struct fbPutXYImage *data = _data;
9003b705cfSriastradh	int bpp = drawable->bitsPerPixel;
9103b705cfSriastradh
9203b705cfSriastradh	fbBltStip(data->src + (b->y1 - data->y0) * data->src_stride, data->src_stride,
9303b705cfSriastradh		  (b->x1 - data->x0) + data->src_x,
9403b705cfSriastradh		  (FbStip *) (data->dst + (b->y1 + data->dst_y) * data->dst_stride),
9503b705cfSriastradh		  data->dst_stride,
9603b705cfSriastradh		  (b->x1 + data->dst_x) * bpp,
9703b705cfSriastradh		  (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
9803b705cfSriastradh		  data->alu, data->pm, bpp);
9903b705cfSriastradh}
10003b705cfSriastradh
10103b705cfSriastradhinline static void
10203b705cfSriastradh_fbPutXYImageN(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
10303b705cfSriastradh{
10403b705cfSriastradh	struct fbPutXYImage *data = _data;
10503b705cfSriastradh	int bpp = drawable->bitsPerPixel;
10603b705cfSriastradh
10703b705cfSriastradh	fbBltOne(data->src + (b->y1 - data->y0) * data->src_stride,
10803b705cfSriastradh		 data->src_stride,
10903b705cfSriastradh		 (b->x1 - data->x0) + data->src_x,
11003b705cfSriastradh		 data->dst + (b->y1 + data->dst_y) * data->dst_stride,
11103b705cfSriastradh		 data->dst_stride,
11203b705cfSriastradh		 (b->x1 + data->dst_x) * bpp, bpp,
11303b705cfSriastradh		 (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
11403b705cfSriastradh		 data->fgand, data->fgxor,
11503b705cfSriastradh		 data->bgand, data->bgxor);
11603b705cfSriastradh}
11703b705cfSriastradh
11803b705cfSriastradhvoid
11903b705cfSriastradhfbPutXYImage(DrawablePtr drawable, GCPtr gc,
12003b705cfSriastradh             FbBits fg, FbBits bg, FbBits pm, int alu, Bool opaque,
12103b705cfSriastradh             int x, int y, int width, int height,
12203b705cfSriastradh	     FbStip *src, FbStride srcStride, int srcX)
12303b705cfSriastradh{
12403b705cfSriastradh	PixmapPtr pixmap;
12503b705cfSriastradh	struct fbPutXYImage data;
12603b705cfSriastradh	BoxRec box;
12703b705cfSriastradh
12803b705cfSriastradh	box.x1 = data.x0 = x;
12903b705cfSriastradh	box.y1 = data.y0 = y;
13003b705cfSriastradh	box.x2 = x + width;
13103b705cfSriastradh	box.y2 = y + height;
13203b705cfSriastradh	data.src = src;
13303b705cfSriastradh	data.src_stride = srcStride;
13403b705cfSriastradh	data.src_x = srcX;
13503b705cfSriastradh
13603b705cfSriastradh	fbGetDrawablePixmap(drawable, pixmap, data.dst_x, data.dst_y);
13703b705cfSriastradh	data.dst = pixmap->devPrivate.ptr;
13803b705cfSriastradh	data.dst_stride = pixmap->devKind / sizeof(FbStip);
13903b705cfSriastradh
14003b705cfSriastradh	if (drawable->bitsPerPixel == 1) {
14103b705cfSriastradh		if (opaque)
14203b705cfSriastradh			data.alu = FbOpaqueStipple1Rop(alu, fg, bg);
14303b705cfSriastradh		else
14403b705cfSriastradh			data.alu = FbStipple1Rop(alu, fg);
14503b705cfSriastradh		data.pm = pm;
14603b705cfSriastradh
14703b705cfSriastradh		fbDrawableRun(drawable, gc, &box, _fbPutXYImage1, &data);
14803b705cfSriastradh	} else {
14903b705cfSriastradh		data.fgand = fbAnd(alu, fg, pm);
15003b705cfSriastradh		data.fgxor = fbXor(alu, fg, pm);
15103b705cfSriastradh		if (opaque) {
15203b705cfSriastradh			data.bgand = fbAnd(alu, bg, pm);
15303b705cfSriastradh			data.bgxor = fbXor(alu, bg, pm);
15403b705cfSriastradh		} else {
15503b705cfSriastradh			data.bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
15603b705cfSriastradh			data.bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
15703b705cfSriastradh		}
15803b705cfSriastradh
15903b705cfSriastradh		fbDrawableRun(drawable, gc, &box, _fbPutXYImageN, &data);
16003b705cfSriastradh	}
16103b705cfSriastradh}
16203b705cfSriastradh
16303b705cfSriastradhvoid
16403b705cfSriastradhfbPutImage(DrawablePtr drawable, GCPtr gc, int depth,
16503b705cfSriastradh           int x, int y, int w, int h,
16603b705cfSriastradh	   int leftPad, int format, char *image)
16703b705cfSriastradh{
16803b705cfSriastradh	FbGCPrivPtr pgc = fb_gc(gc);
16903b705cfSriastradh	unsigned long i;
17003b705cfSriastradh	FbStride srcStride;
17103b705cfSriastradh	FbStip *src = (FbStip *)image;
17203b705cfSriastradh
17303b705cfSriastradh	DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
17403b705cfSriastradh
17503b705cfSriastradh	x += drawable->x;
17603b705cfSriastradh	y += drawable->y;
17703b705cfSriastradh
17803b705cfSriastradh	switch (format) {
17903b705cfSriastradh	case XYBitmap:
18003b705cfSriastradh		srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
18103b705cfSriastradh		fbPutXYImage(drawable, gc,
18203b705cfSriastradh			     pgc->fg, pgc->bg, pgc->pm,
18303b705cfSriastradh			     gc->alu, TRUE,
18403b705cfSriastradh			     x, y, w, h,
18503b705cfSriastradh			     src, srcStride, leftPad);
18603b705cfSriastradh		break;
18703b705cfSriastradh	case XYPixmap:
18803b705cfSriastradh		srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
18903b705cfSriastradh		for (i = (unsigned long) 1 << (drawable->depth - 1); i; i >>= 1) {
19003b705cfSriastradh			if (i & gc->planemask) {
19103b705cfSriastradh				fbPutXYImage(drawable, gc,
19203b705cfSriastradh					     FB_ALLONES,
19303b705cfSriastradh					     0,
19403b705cfSriastradh					     fbReplicatePixel(i, drawable->bitsPerPixel),
19503b705cfSriastradh					     gc->alu,
19603b705cfSriastradh					     TRUE, x, y, w, h, src, srcStride, leftPad);
19703b705cfSriastradh				src += srcStride * h;
19803b705cfSriastradh			}
19903b705cfSriastradh		}
20003b705cfSriastradh		break;
20103b705cfSriastradh	case ZPixmap:
20203b705cfSriastradh		srcStride = PixmapBytePad(w, drawable->depth) / sizeof(FbStip);
20303b705cfSriastradh		fbPutZImage(drawable, gc,
20403b705cfSriastradh			    x, y, w, h, src, srcStride);
20503b705cfSriastradh	}
20603b705cfSriastradh}
20703b705cfSriastradh
20803b705cfSriastradhvoid
20903b705cfSriastradhfbGetImage(DrawablePtr drawable,
21003b705cfSriastradh           int x, int y, int w, int h,
21103b705cfSriastradh	   unsigned int format, unsigned long planeMask, char *d)
21203b705cfSriastradh{
21303b705cfSriastradh	FbBits *src;
21403b705cfSriastradh	FbStride srcStride;
21503b705cfSriastradh	int srcBpp;
21603b705cfSriastradh	int srcXoff, srcYoff;
21703b705cfSriastradh	FbStip *dst;
21803b705cfSriastradh	FbStride dstStride;
21903b705cfSriastradh
22003b705cfSriastradh	DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
22103b705cfSriastradh
22203b705cfSriastradh	fbGetDrawable(drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
22303b705cfSriastradh
22403b705cfSriastradh	x += drawable->x;
22503b705cfSriastradh	y += drawable->y;
22603b705cfSriastradh
22703b705cfSriastradh	dst = (FbStip *) d;
22803b705cfSriastradh	if (format == ZPixmap || srcBpp == 1) {
22903b705cfSriastradh		FbBits pm;
23003b705cfSriastradh
23103b705cfSriastradh		pm = fbReplicatePixel(planeMask, srcBpp);
232fe8aea9eSmrg
23303b705cfSriastradh		dstStride = PixmapBytePad(w, drawable->depth);
23403b705cfSriastradh		dstStride /= sizeof(FbStip);
235fe8aea9eSmrg
23603b705cfSriastradh		fbBltStip((FbStip *)(src + (y + srcYoff) * srcStride), srcStride,
23703b705cfSriastradh			  (x + srcXoff) * srcBpp,
238fe8aea9eSmrg			  dst, dstStride, 0, w * srcBpp, h, GXcopy, FB_ALLONES, srcBpp);
239fe8aea9eSmrg
240fe8aea9eSmrg		if (pm != FB_ALLONES) {
241fe8aea9eSmrg			int i = dstStride * h;
242fe8aea9eSmrg			while (i--)
243fe8aea9eSmrg				*dst++ &= pm;
244fe8aea9eSmrg		}
24503b705cfSriastradh	} else {
24603b705cfSriastradh		dstStride = BitmapBytePad(w) / sizeof(FbStip);
24703b705cfSriastradh		fbBltPlane(src + (y + srcYoff) * srcStride,
24803b705cfSriastradh			   srcStride,
24903b705cfSriastradh			   (x + srcXoff) * srcBpp,
25003b705cfSriastradh			   srcBpp,
25103b705cfSriastradh			   dst,
25203b705cfSriastradh			   dstStride,
25303b705cfSriastradh			   0,
25403b705cfSriastradh			   w * srcBpp, h,
25503b705cfSriastradh			   fbAndStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
25603b705cfSriastradh			   fbXorStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
25703b705cfSriastradh			   fbAndStip(GXcopy, 0, FB_STIP_ALLONES),
25803b705cfSriastradh			   fbXorStip(GXcopy, 0, FB_STIP_ALLONES), planeMask);
25903b705cfSriastradh	}
26003b705cfSriastradh}
261