1/*
2 * Copyright © 1998 Keith Packard
3 * Copyright © 2012 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Keith Packard makes no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#ifndef FB_H
25#define FB_H
26
27#include <xorg-server.h>
28#include <servermd.h>
29#include <gcstruct.h>
30#include <colormap.h>
31#include <windowstr.h>
32#include <regionstr.h>
33
34#include <stdbool.h>
35#include <pixman.h>
36
37#include "sfb.h"
38
39#include "../../compat-api.h"
40#include "../debug.h"
41
42#define WRITE(ptr, val) (*(ptr) = (val))
43#define READ(ptr) (*(ptr))
44
45/*
46 * This single define controls the basic size of data manipulated
47 * by this software; it must be log2(sizeof (FbBits) * 8)
48 */
49#define FB_SHIFT    LOG2_BITMAP_PAD
50
51#define FB_UNIT	    (1 << FB_SHIFT)
52#define FB_HALFUNIT (1 << (FB_SHIFT-1))
53#define FB_MASK	    (FB_UNIT - 1)
54#define FB_ALLONES  ((FbBits) -1)
55
56#if IMAGE_BYTE_ORDER != LSBFirst
57#error "IMAGE_BYTE_ORDER must be LSBFirst"
58#endif
59
60#if GLYPHPADBYTES != 4
61#error "GLYPHPADBYTES must be 4"
62#endif
63
64#if FB_SHIFT != 5
65#error "FB_SHIFT ala LOG2_BITMAP_PAD must be 5"
66#endif
67
68#define FB_STIP_SHIFT	LOG2_BITMAP_PAD
69#define FB_STIP_UNIT	(1 << FB_STIP_SHIFT)
70#define FB_STIP_MASK	(FB_STIP_UNIT - 1)
71#define FB_STIP_ALLONES	((FbStip) -1)
72#define FbFullMask(n)   ((n) == FB_UNIT ? FB_ALLONES : ((((FbBits) 1) << n) - 1))
73
74typedef uint32_t FbBits;
75typedef FbBits FbStip;
76typedef int FbStride;
77
78#include "fbrop.h"
79
80#define FbScrLeft(x,n)	((x) >> (n))
81#define FbScrRight(x,n)	((x) << (n))
82/* #define FbLeftBits(x,n)	((x) & ((((FbBits) 1) << (n)) - 1)) */
83#define FbLeftStipBits(x,n) ((x) & ((((FbStip) 1) << (n)) - 1))
84#define FbStipMoveLsb(x,s,n)	(FbStipRight (x,(s)-(n)))
85#define FbPatternOffsetBits	0
86
87#define FbStipLeft(x,n)	FbScrLeft(x,n)
88#define FbStipRight(x,n) FbScrRight(x,n)
89
90#define FbRotLeft(x,n)	FbScrLeft(x,n) | (n ? FbScrRight(x,FB_UNIT-n) : 0)
91#define FbRotRight(x,n)	FbScrRight(x,n) | (n ? FbScrLeft(x,FB_UNIT-n) : 0)
92
93#define FbRotStipLeft(x,n)  FbStipLeft(x,n) | (n ? FbStipRight(x,FB_STIP_UNIT-n) : 0)
94#define FbRotStipRight(x,n)  FbStipRight(x,n) | (n ? FbStipLeft(x,FB_STIP_UNIT-n) : 0)
95
96#define FbLeftMask(x)	    ( ((x) & FB_MASK) ? \
97			     FbScrRight(FB_ALLONES,(x) & FB_MASK) : 0)
98#define FbRightMask(x)	    ( ((FB_UNIT - (x)) & FB_MASK) ? \
99			     FbScrLeft(FB_ALLONES,(FB_UNIT - (x)) & FB_MASK) : 0)
100
101#define FbLeftStipMask(x)   ( ((x) & FB_STIP_MASK) ? \
102			     FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) : 0)
103#define FbRightStipMask(x)  ( ((FB_STIP_UNIT - (x)) & FB_STIP_MASK) ? \
104			     FbScrLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - (x)) & FB_STIP_MASK) : 0)
105
106#define FbBitsMask(x,w)	(FbScrRight(FB_ALLONES,(x) & FB_MASK) & \
107			 FbScrLeft(FB_ALLONES,(FB_UNIT - ((x) + (w))) & FB_MASK))
108
109#define FbStipMask(x,w)	(FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) & \
110			 FbStipLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - ((x)+(w))) & FB_STIP_MASK))
111
112#define FbMaskBits(x,w,l,n,r) { \
113    n = (w); \
114    r = FbRightMask((x)+n); \
115    l = FbLeftMask(x); \
116    if (l) { \
117	n -= FB_UNIT - ((x) & FB_MASK); \
118	if (n < 0) { \
119	    n = 0; \
120	    l &= r; \
121	    r = 0; \
122	} \
123    } \
124    n >>= FB_SHIFT; \
125}
126
127#define FbByteMaskInvalid   0x10
128
129#define FbPatternOffset(o,t)  ((o) ^ (FbPatternOffsetBits & ~(sizeof (t) - 1)))
130
131#define FbPtrOffset(p,o,t)		((t *) ((CARD8 *) (p) + (o)))
132#define FbSelectPatternPart(xor,o,t)	((xor) >> (FbPatternOffset (o,t) << 3))
133#define FbStorePart(dst,off,t,xor)	(WRITE(FbPtrOffset(dst,off,t), \
134					 FbSelectPart(xor,off,t)))
135#ifndef FbSelectPart
136#define FbSelectPart(x,o,t) FbSelectPatternPart(x,o,t)
137#endif
138
139#define FbMaskBitsBytes(x,w,copy,l,lb,n,r,rb) { \
140    n = (w); \
141    lb = 0; \
142    rb = 0; \
143    r = FbRightMask((x)+n); \
144    if (r) { \
145	/* compute right byte length */ \
146	if ((copy) && (((x) + n) & 7) == 0) { \
147	    rb = (((x) + n) & FB_MASK) >> 3; \
148	} else { \
149	    rb = FbByteMaskInvalid; \
150	} \
151    } \
152    l = FbLeftMask(x); \
153    if (l) { \
154	/* compute left byte length */ \
155	if ((copy) && ((x) & 7) == 0) { \
156	    lb = ((x) & FB_MASK) >> 3; \
157	} else { \
158	    lb = FbByteMaskInvalid; \
159	} \
160	/* subtract out the portion painted by leftMask */ \
161	n -= FB_UNIT - ((x) & FB_MASK); \
162	if (n < 0) { \
163	    if (lb != FbByteMaskInvalid) { \
164		if (rb == FbByteMaskInvalid) { \
165		    lb = FbByteMaskInvalid; \
166		} else if (rb) { \
167		    lb |= (rb - lb) << (FB_SHIFT - 3); \
168		    rb = 0; \
169		} \
170	    } \
171	    n = 0; \
172	    l &= r; \
173	    r = 0; \
174	}\
175    } \
176    n >>= FB_SHIFT; \
177}
178
179#define FbDoLeftMaskByteRRop(dst,lb,l,and,xor) { \
180    switch (lb) { \
181    case (sizeof (FbBits) - 3) | (1 << (FB_SHIFT - 3)): \
182	FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
183	break; \
184    case (sizeof (FbBits) - 3) | (2 << (FB_SHIFT - 3)): \
185	FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
186	FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \
187	break; \
188    case (sizeof (FbBits) - 2) | (1 << (FB_SHIFT - 3)): \
189	FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \
190	break; \
191    case sizeof (FbBits) - 3: \
192	FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
193    case sizeof (FbBits) - 2: \
194	FbStorePart(dst,sizeof (FbBits) - 2,CARD16,xor); \
195	break; \
196    case sizeof (FbBits) - 1: \
197	FbStorePart(dst,sizeof (FbBits) - 1,CARD8,xor); \
198	break; \
199    default: \
200	WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, l)); \
201	break; \
202    } \
203}
204
205#define FbDoRightMaskByteRRop(dst,rb,r,and,xor) { \
206    switch (rb) { \
207    case 1: \
208	FbStorePart(dst,0,CARD8,xor); \
209	break; \
210    case 2: \
211	FbStorePart(dst,0,CARD16,xor); \
212	break; \
213    case 3: \
214	FbStorePart(dst,0,CARD16,xor); \
215	FbStorePart(dst,2,CARD8,xor); \
216	break; \
217    default: \
218	WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, r)); \
219    } \
220}
221
222#define FbMaskStip(x,w,l,n,r) { \
223    n = (w); \
224    r = FbRightStipMask((x)+n); \
225    l = FbLeftStipMask(x); \
226    if (l) { \
227	n -= FB_STIP_UNIT - ((x) & FB_STIP_MASK); \
228	if (n < 0) { \
229	    n = 0; \
230	    l &= r; \
231	    r = 0; \
232	} \
233    } \
234    n >>= FB_STIP_SHIFT; \
235}
236
237/*
238 * These macros are used to transparently stipple
239 * in copy mode; the expected usage is with 'n' constant
240 * so all of the conditional parts collapse into a minimal
241 * sequence of partial word writes
242 *
243 * 'n' is the bytemask of which bytes to store, 'a' is the address
244 * of the FbBits base unit, 'o' is the offset within that unit
245 *
246 * The term "lane" comes from the hardware term "byte-lane" which
247 */
248
249#define FbLaneCase1(n,a,o)						\
250    if ((n) == 0x01) {							\
251	WRITE((CARD8 *) ((a)+FbPatternOffset(o,CARD8)), fgxor);		\
252    }
253
254#define FbLaneCase2(n,a,o)						\
255    if ((n) == 0x03) {							\
256	WRITE((CARD16 *) ((a)+FbPatternOffset(o,CARD16)), fgxor);	\
257    } else {								\
258	FbLaneCase1((n)&1,a,o)						\
259	FbLaneCase1((n)>>1,a,(o)+1)					\
260    }
261
262#define FbLaneCase4(n,a,o)						\
263    if ((n) == 0x0f) {							\
264	WRITE((CARD32 *) ((a)+FbPatternOffset(o,CARD32)), fgxor);	\
265    } else {								\
266	FbLaneCase2((n)&3,a,o)						\
267	FbLaneCase2((n)>>2,a,(o)+2)					\
268    }
269
270#define FbLaneCase(n,a)   FbLaneCase4(n,(CARD8 *) (a),0)
271
272typedef struct {
273	long changes;
274	long serial;
275	GCFuncs *old_funcs;
276	void *priv;
277
278	FbBits and, xor;            /* reduced rop values */
279	FbBits bgand, bgxor;        /* for stipples */
280	FbBits fg, bg, pm;          /* expanded and filled */
281	unsigned int dashLength;    /* total of all dash elements */
282	unsigned char evenStipple;  /* stipple is even */
283	unsigned char bpp;          /* current drawable bpp */
284} FbGCPrivate, *FbGCPrivPtr;
285
286extern DevPrivateKeyRec sna_gc_key;
287extern DevPrivateKeyRec sna_window_key;
288
289static inline FbGCPrivate *fb_gc(GCPtr gc)
290{
291	return (FbGCPrivate *)__get_private(gc, sna_gc_key);
292}
293
294static inline PixmapPtr fbGetWindowPixmap(WindowPtr window)
295{
296	return *(PixmapPtr *)__get_private(window, sna_window_key);
297}
298
299#ifdef ROOTLESS
300#define __fbPixDrawableX(p)	((p)->drawable.x)
301#define __fbPixDrawableY(p)	((p)->drawable.y)
302#else
303#define __fbPixDrawableX(p)	0
304#define __fbPixDrawableY(p)	0
305#endif
306
307#ifdef COMPOSITE
308#define __fbPixOffXWin(p)	(__fbPixDrawableX(p) - (p)->screen_x)
309#define __fbPixOffYWin(p)	(__fbPixDrawableY(p) - (p)->screen_y)
310#else
311#define __fbPixOffXWin(p)	(__fbPixDrawableX(p))
312#define __fbPixOffYWin(p)	(__fbPixDrawableY(p))
313#endif
314#define __fbPixOffXPix(p)	(__fbPixDrawableX(p))
315#define __fbPixOffYPix(p)	(__fbPixDrawableY(p))
316
317#define fbGetDrawablePixmap(drawable, pixmap, xoff, yoff) {		\
318    if ((drawable)->type != DRAWABLE_PIXMAP) {				\
319	(pixmap) = fbGetWindowPixmap((WindowPtr)drawable);		\
320	(xoff) = __fbPixOffXWin(pixmap);				\
321	(yoff) = __fbPixOffYWin(pixmap);				\
322    } else {								\
323	(pixmap) = (PixmapPtr) (drawable);				\
324	(xoff) = __fbPixOffXPix(pixmap);				\
325	(yoff) = __fbPixOffYPix(pixmap);				\
326    }									\
327}
328
329#define fbGetPixmapBitsData(pixmap, pointer, stride, bpp) {		\
330    (pointer) = (FbBits *) (pixmap)->devPrivate.ptr;			\
331    (stride) = ((int) (pixmap)->devKind) / sizeof (FbBits); (void)(stride);\
332    (bpp) = (pixmap)->drawable.bitsPerPixel;  (void)(bpp);		\
333}
334
335#define fbGetPixmapStipData(pixmap, pointer, stride, bpp) {		\
336    (pointer) = (FbStip *) (pixmap)->devPrivate.ptr;			\
337    (stride) = ((int) (pixmap)->devKind) / sizeof (FbStip); (void)(stride);\
338    (bpp) = (pixmap)->drawable.bitsPerPixel;  (void)(bpp);		\
339}
340
341#define fbGetDrawable(drawable, pointer, stride, bpp, xoff, yoff) {	\
342    PixmapPtr   _pPix;							\
343    fbGetDrawablePixmap(drawable, _pPix, xoff, yoff);			\
344    fbGetPixmapBitsData(_pPix, pointer, stride, bpp);			\
345}
346
347#define fbGetStipDrawable(drawable, pointer, stride, bpp, xoff, yoff) {	\
348    PixmapPtr   _pPix;							\
349    fbGetDrawablePixmap(drawable, _pPix, xoff, yoff);			\
350    fbGetPixmapStipData(_pPix, pointer, stride, bpp);			\
351}
352
353/*
354 * XFree86 empties the root BorderClip when the VT is inactive,
355 * here's a macro which uses that to disable GetImage and GetSpans
356 */
357
358#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)
359#define fbWindowEnabled(pWin) \
360	RegionNotEmpty(&(pWin)->drawable.pScreen->root->borderClip)
361#else
362#define fbWindowEnabled(pWin) \
363	RegionNotEmpty(&WindowTable[(pWin)->drawable.pScreen->myNum]->borderClip)
364#endif
365#define fbDrawableEnabled(drawable) \
366    ((drawable)->type == DRAWABLE_PIXMAP ? \
367     TRUE : fbWindowEnabled((WindowPtr) drawable))
368
369#define FbPowerOfTwo(w)	    (((w) & ((w) - 1)) == 0)
370/*
371 * Accelerated tiles are power of 2 width <= FB_UNIT
372 */
373#define FbEvenTile(w)	    ((w) <= FB_UNIT && FbPowerOfTwo(w))
374/*
375 * Accelerated stipples are power of 2 width and <= FB_UNIT/dstBpp
376 * with dstBpp a power of 2 as well
377 */
378#define FbEvenStip(w,bpp)   ((w) * (bpp) <= FB_UNIT && FbPowerOfTwo(w) && FbPowerOfTwo(bpp))
379
380inline static int16_t fbBound(int16_t a, uint16_t b)
381{
382	int v = (int)a + (int)b;
383	if (v > MAXSHORT)
384		return MAXSHORT;
385	return v;
386}
387
388extern void
389fbPolyArc(DrawablePtr drawable, GCPtr gc, int narcs, xArc * parcs);
390
391extern void
392fbBlt(FbBits *src, FbStride srcStride, int srcX,
393      FbBits *dst, FbStride dstStride, int dstX,
394      int width, int height,
395      int alu, FbBits pm, int bpp,
396      Bool reverse, Bool upsidedown);
397
398#if FB_STIP_SHIFT == FB_SHIFT
399static inline void
400fbBltStip(FbStip *src, FbStride srcStride, int srcX,
401	  FbStip *dst, FbStride dstStride, int dstX,
402	  int width, int height, int alu, FbBits pm, int bpp)
403{
404	fbBlt((FbBits *)src, srcStride, srcX,
405	      (FbBits *)dst, dstStride, dstX,
406	      width, height, alu, pm, bpp,
407	      FALSE, FALSE);
408}
409#else
410#error FB_STIP_SHIFT must equal FB_SHIFT
411#endif
412
413extern void
414fbBltOne(FbStip *src, FbStride srcStride, int srcX,
415         FbBits *dst, FbStride dstStride, int dstX,
416         int dstBpp, int width, int height,
417	 FbBits fgand, FbBits fbxor, FbBits bgand, FbBits bgxor);
418
419extern void
420fbBltPlane(FbBits *src, FbStride srcStride, int srcX, int srcBpp,
421           FbStip *dst, FbStride dstStride, int dstX,
422           int width, int height,
423           FbStip fgand, FbStip fgxor, FbStip bgand, FbStip bgxor,
424	   Pixel planeMask);
425
426extern void
427fbCopyNtoN(DrawablePtr src, DrawablePtr dst, GCPtr gc,
428           BoxPtr pbox, int nbox,
429           int dx, int dy,
430           Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
431
432extern void
433fbCopy1toN(DrawablePtr src, DrawablePtr dst, GCPtr gc,
434           BoxPtr pbox, int nbox,
435           int dx, int dy,
436           Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
437
438extern void
439fbCopyNto1(DrawablePtr src, DrawablePtr dst, GCPtr gc,
440           BoxPtr pbox, int nbox,
441           int dx, int dy,
442           Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
443
444extern RegionPtr
445fbCopyArea(DrawablePtr src, DrawablePtr dst, GCPtr gc,
446	   int sx, int sy,
447	   int width, int height,
448	   int dx, int dy);
449
450extern RegionPtr
451fbCopyPlane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
452	    int sx, int sy,
453	    int width, int height,
454	    int dx, int dy,
455	    unsigned long bitplane);
456
457extern void
458fbFill(DrawablePtr drawable, GCPtr gc, int x, int y, int width, int height);
459
460extern void
461fbSolidBoxClipped(DrawablePtr drawable, GCPtr gc,
462                  int x1, int y1, int x2, int y2);
463
464extern void
465fbPolyFillRect(DrawablePtr drawable, GCPtr gc, int n, xRectangle *rec);
466
467extern void
468fbFillSpans(DrawablePtr drawable, GCPtr gc,
469            int n, DDXPointPtr pt, int *width, int fSorted);
470
471extern void
472fbPadPixmap(PixmapPtr pPixmap);
473
474extern void
475fbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable);
476
477extern void
478fbGetSpans(DrawablePtr drawable, int wMax,
479           DDXPointPtr pt, int *width, int n, char *dst);
480
481extern void
482fbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc, int x, int y,
483               unsigned int n, CharInfoPtr *info, pointer glyphs);
484
485extern void
486fbImageGlyphBlt(DrawablePtr drawable, GCPtr gc, int x, int y,
487                unsigned int n, CharInfoPtr *info, pointer glyphs);
488
489extern void
490fbPutImage(DrawablePtr drawable, GCPtr gc, int depth,
491           int x, int y, int w, int h,
492	   int leftPad, int format, char *image);
493
494extern void
495fbPutXYImage(DrawablePtr drawable, GCPtr gc,
496             FbBits fg, FbBits bg, FbBits pm,
497             int alu, Bool opaque,
498             int x, int y, int width, int height,
499	     FbStip * src, FbStride srcStride, int srcX);
500
501extern void
502fbGetImage(DrawablePtr drawable,
503           int x, int y, int w, int h,
504	   unsigned int format, unsigned long planeMask, char *d);
505
506extern void
507fbPolyLine(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr pt);
508
509extern void
510fbFixCoordModePrevious(int n, DDXPointPtr pt);
511
512extern void
513fbPolySegment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg);
514
515extern RegionPtr
516fbBitmapToRegion(PixmapPtr pixmap);
517
518extern void
519fbPolyPoint(DrawablePtr drawable, GCPtr gc,
520	    int mode, int n, xPoint *pt,
521	    unsigned flags);
522
523extern void
524fbPushImage(DrawablePtr drawable, GCPtr gc,
525            FbStip *src, FbStride srcStride, int srcX,
526	    int x, int y, int width, int height);
527
528extern void
529fbPushPixels(GCPtr gc, PixmapPtr pBitmap, DrawablePtr drawable,
530	     int dx, int dy, int xOrg, int yOrg);
531
532extern void
533fbSetSpans(DrawablePtr drawable, GCPtr gc,
534           char *src, DDXPointPtr pt, int *width, int n, int fSorted);
535
536extern void
537fbSegment(DrawablePtr drawable, GCPtr gc,
538          int xa, int ya, int xb, int yb,
539	  bool drawLast, int *dashOffset);
540
541extern void
542fbSegment1(DrawablePtr drawable, GCPtr gc, const BoxRec *clip,
543          int xa, int ya, int xb, int yb,
544	  bool drawLast, int *dashOffset);
545
546extern void
547fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n);
548
549extern void
550fbStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
551          int width, int height,
552          FbStip *stip, FbStride stipStride,
553          int stipWidth, int stipHeight,
554          Bool even,
555          FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
556	  int xRot, int yRot);
557
558extern void
559fbTile(FbBits *dst, FbStride dstStride, int dstX, int width, int height,
560       FbBits *tile, FbStride tileStride, int tileWidth, int tileHeight,
561       int alu, FbBits pm, int bpp,
562       int xRot, int yRot);
563
564extern FbBits fbReplicatePixel(Pixel p, int bpp);
565
566#endif  /* FB_H */
567