fbgc.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. *
  3. * Copyright © 1998 Keith Packard
  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. #ifdef HAVE_DIX_CONFIG_H
  24. #include <dix-config.h>
  25. #endif
  26. #include <stdlib.h>
  27. #include "fb.h"
  28. const GCFuncs fbGCFuncs = {
  29. fbValidateGC,
  30. miChangeGC,
  31. miCopyGC,
  32. miDestroyGC,
  33. miChangeClip,
  34. miDestroyClip,
  35. miCopyClip,
  36. };
  37. const GCOps fbGCOps = {
  38. fbFillSpans,
  39. fbSetSpans,
  40. fbPutImage,
  41. fbCopyArea,
  42. fbCopyPlane,
  43. fbPolyPoint,
  44. fbPolyLine,
  45. fbPolySegment,
  46. fbPolyRectangle,
  47. fbPolyArc,
  48. miFillPolygon,
  49. fbPolyFillRect,
  50. fbPolyFillArc,
  51. miPolyText8,
  52. miPolyText16,
  53. miImageText8,
  54. miImageText16,
  55. fbImageGlyphBlt,
  56. fbPolyGlyphBlt,
  57. fbPushPixels
  58. };
  59. Bool
  60. fbCreateGC(GCPtr pGC)
  61. {
  62. pGC->clientClip = NULL;
  63. pGC->clientClipType = CT_NONE;
  64. pGC->ops = (GCOps *) & fbGCOps;
  65. pGC->funcs = (GCFuncs *) & fbGCFuncs;
  66. /* fb wants to translate before scan conversion */
  67. pGC->miTranslate = 1;
  68. fbGetRotatedPixmap(pGC) = 0;
  69. fbGetExpose(pGC) = 1;
  70. fbGetFreeCompClip(pGC) = 0;
  71. fbGetCompositeClip(pGC) = 0;
  72. fbGetGCPrivate(pGC)->bpp = BitsPerPixel(pGC->depth);
  73. return TRUE;
  74. }
  75. /*
  76. * Pad pixmap to FB_UNIT bits wide
  77. */
  78. void
  79. fbPadPixmap(PixmapPtr pPixmap)
  80. {
  81. int width;
  82. FbBits *bits;
  83. FbBits b;
  84. FbBits mask;
  85. int height;
  86. int w;
  87. int stride;
  88. int bpp;
  89. int xOff _X_UNUSED, yOff _X_UNUSED;
  90. fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
  91. width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
  92. height = pPixmap->drawable.height;
  93. mask = FbBitsMask(0, width);
  94. while (height--) {
  95. b = *bits & mask;
  96. w = width;
  97. while (w < FB_UNIT) {
  98. b = b | FbScrRight(b, w);
  99. w <<= 1;
  100. }
  101. *bits = b;
  102. bits += stride;
  103. }
  104. }
  105. /*
  106. * Verify that 'bits' repeats every 'len' bits
  107. */
  108. static Bool
  109. fbBitsRepeat(FbBits bits, int len, int width)
  110. {
  111. FbBits mask = FbBitsMask(0, len);
  112. FbBits orig = bits & mask;
  113. int i;
  114. if (width > FB_UNIT)
  115. width = FB_UNIT;
  116. for (i = 0; i < width / len; i++) {
  117. if ((bits & mask) != orig)
  118. return FALSE;
  119. bits = FbScrLeft(bits, len);
  120. }
  121. return TRUE;
  122. }
  123. /*
  124. * Check whether an entire bitmap line is a repetition of
  125. * the first 'len' bits
  126. */
  127. static Bool
  128. fbLineRepeat(FbBits * bits, int len, int width)
  129. {
  130. FbBits first = bits[0];
  131. if (!fbBitsRepeat(first, len, width))
  132. return FALSE;
  133. width = (width + FB_UNIT - 1) >> FB_SHIFT;
  134. bits++;
  135. while (--width)
  136. if (*bits != first)
  137. return FALSE;
  138. return TRUE;
  139. }
  140. /*
  141. * The even stipple code wants the first FB_UNIT/bpp bits on
  142. * each scanline to represent the entire stipple
  143. */
  144. static Bool
  145. fbCanEvenStipple(PixmapPtr pStipple, int bpp)
  146. {
  147. int len = FB_UNIT / bpp;
  148. FbBits *bits;
  149. int stride;
  150. int stip_bpp;
  151. int stipXoff _X_UNUSED, stipYoff _X_UNUSED;
  152. int h;
  153. /* can't even stipple 24bpp drawables */
  154. if ((bpp & (bpp - 1)) != 0)
  155. return FALSE;
  156. /* make sure the stipple width is a multiple of the even stipple width */
  157. if (pStipple->drawable.width % len != 0)
  158. return FALSE;
  159. fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff,
  160. stipYoff);
  161. h = pStipple->drawable.height;
  162. /* check to see that the stipple repeats horizontally */
  163. while (h--) {
  164. if (!fbLineRepeat(bits, len, pStipple->drawable.width))
  165. return FALSE;
  166. bits += stride;
  167. }
  168. return TRUE;
  169. }
  170. void
  171. fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
  172. {
  173. FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
  174. FbBits mask;
  175. pGC->lastWinOrg.x = pDrawable->x;
  176. pGC->lastWinOrg.y = pDrawable->y;
  177. /*
  178. * if the client clip is different or moved OR the subwindowMode has
  179. * changed OR the window's clip has changed since the last validation
  180. * we need to recompute the composite clip
  181. */
  182. if ((changes &
  183. (GCClipXOrigin | GCClipYOrigin | GCClipMask | GCSubwindowMode)) ||
  184. (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
  185. ) {
  186. miComputeCompositeClip(pGC, pDrawable);
  187. pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1;
  188. }
  189. if (pPriv->bpp != pDrawable->bitsPerPixel) {
  190. changes |= GCStipple | GCForeground | GCBackground | GCPlaneMask;
  191. pPriv->bpp = pDrawable->bitsPerPixel;
  192. }
  193. if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
  194. (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
  195. fbGetRotatedPixmap(pGC) = 0;
  196. }
  197. if (pGC->fillStyle == FillTiled) {
  198. PixmapPtr pOldTile, pNewTile;
  199. pOldTile = pGC->tile.pixmap;
  200. if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
  201. pNewTile = fbGetRotatedPixmap(pGC);
  202. if (!pNewTile ||
  203. pNewTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
  204. if (pNewTile)
  205. (*pGC->pScreen->DestroyPixmap) (pNewTile);
  206. pNewTile =
  207. fb24_32ReformatTile(pOldTile, pDrawable->bitsPerPixel);
  208. }
  209. if (pNewTile) {
  210. fbGetRotatedPixmap(pGC) = pOldTile;
  211. pGC->tile.pixmap = pNewTile;
  212. changes |= GCTile;
  213. }
  214. }
  215. }
  216. if (changes & GCTile) {
  217. if (!pGC->tileIsPixel &&
  218. FbEvenTile(pGC->tile.pixmap->drawable.width *
  219. pDrawable->bitsPerPixel))
  220. fbPadPixmap(pGC->tile.pixmap);
  221. }
  222. if (changes & GCStipple) {
  223. pPriv->evenStipple = FALSE;
  224. if (pGC->stipple) {
  225. /* can we do an even stipple ?? */
  226. if (FbEvenStip(pGC->stipple->drawable.width,
  227. pDrawable->bitsPerPixel) &&
  228. (fbCanEvenStipple(pGC->stipple, pDrawable->bitsPerPixel)))
  229. pPriv->evenStipple = TRUE;
  230. if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel <
  231. FB_UNIT)
  232. fbPadPixmap(pGC->stipple);
  233. }
  234. }
  235. /*
  236. * Recompute reduced rop values
  237. */
  238. if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
  239. int s;
  240. FbBits depthMask;
  241. mask = FbFullMask(pDrawable->bitsPerPixel);
  242. depthMask = FbFullMask(pDrawable->depth);
  243. pPriv->fg = pGC->fgPixel & mask;
  244. pPriv->bg = pGC->bgPixel & mask;
  245. if ((pGC->planemask & depthMask) == depthMask)
  246. pPriv->pm = mask;
  247. else
  248. pPriv->pm = pGC->planemask & mask;
  249. s = pDrawable->bitsPerPixel;
  250. while (s < FB_UNIT) {
  251. pPriv->fg |= pPriv->fg << s;
  252. pPriv->bg |= pPriv->bg << s;
  253. pPriv->pm |= pPriv->pm << s;
  254. s <<= 1;
  255. }
  256. pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
  257. pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
  258. pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
  259. pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
  260. }
  261. if (changes & GCDashList) {
  262. unsigned short n = pGC->numInDashList;
  263. unsigned char *dash = pGC->dash;
  264. unsigned int dashLength = 0;
  265. while (n--)
  266. dashLength += (unsigned int) *dash++;
  267. pPriv->dashLength = dashLength;
  268. }
  269. }