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