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