fbedge.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. *
  3. * Copyright © 2004 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. #include <string.h>
  24. #ifdef HAVE_DIX_CONFIG_H
  25. #include <dix-config.h>
  26. #endif
  27. #include "fb.h"
  28. #include "picturestr.h"
  29. #include "mipict.h"
  30. #include "renderedge.h"
  31. #include "fbpict.h"
  32. /*
  33. * 4 bit alpha
  34. */
  35. #define N_BITS 4
  36. #define rasterizeEdges fbRasterizeEdges4
  37. #if BITMAP_BIT_ORDER == LSBFirst
  38. #define Shift4(o) ((o) << 2)
  39. #else
  40. #define Shift4(o) ((1-(o)) << 2)
  41. #endif
  42. #define Get4(x,o) (((x) >> Shift4(o)) & 0xf)
  43. #define Put4(x,o,v) (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
  44. #define DefineAlpha(line,x) \
  45. CARD8 *__ap = (CARD8 *) line + ((x) >> 1); \
  46. int __ao = (x) & 1
  47. #define StepAlpha ((__ap += __ao), (__ao ^= 1))
  48. #define AddAlpha(a) { \
  49. CARD8 __o = *__ap; \
  50. CARD8 __a = (a) + Get4(__o, __ao); \
  51. *__ap = Put4 (__o, __ao, __a | (0 - ((__a) >> 4))); \
  52. }
  53. #include "fbedgeimp.h"
  54. #undef AddAlpha
  55. #undef StepAlpha
  56. #undef DefineAlpha
  57. #undef rasterizeEdges
  58. #undef N_BITS
  59. /*
  60. * 1 bit alpha
  61. */
  62. #define N_BITS 1
  63. #define rasterizeEdges fbRasterizeEdges1
  64. #include "fbedgeimp.h"
  65. #undef rasterizeEdges
  66. #undef N_BITS
  67. /*
  68. * 8 bit alpha
  69. */
  70. static INLINE CARD8
  71. clip255(int x)
  72. {
  73. if (x > 255)
  74. return 255;
  75. return x;
  76. }
  77. static INLINE void
  78. add_saturate_8(CARD8 *buf, int value, int length)
  79. {
  80. while (length--) {
  81. *buf = clip255(*buf + value);
  82. buf++;
  83. }
  84. }
  85. /*
  86. * We want to detect the case where we add the same value to a long
  87. * span of pixels. The triangles on the end are filled in while we
  88. * count how many sub-pixel scanlines contribute to the middle section.
  89. *
  90. * +--------------------------+
  91. * fill_height =| \ /
  92. * +------------------+
  93. * |================|
  94. * fill_start fill_end
  95. */
  96. static void
  97. fbRasterizeEdges8(FbBits * buf,
  98. int width,
  99. int stride,
  100. RenderEdge * l, RenderEdge * r, xFixed t, xFixed b)
  101. {
  102. xFixed y = t;
  103. FbBits *line;
  104. int fill_start = -1, fill_end = -1;
  105. int fill_size = 0;
  106. line = buf + xFixedToInt(y) * stride;
  107. for (;;) {
  108. CARD8 *ap = (CARD8 *) line;
  109. xFixed lx, rx;
  110. int lxi, rxi;
  111. /* clip X */
  112. lx = l->x;
  113. if (lx < 0)
  114. lx = 0;
  115. rx = r->x;
  116. if (xFixedToInt(rx) >= width)
  117. rx = IntToxFixed(width);
  118. /* Skip empty (or backwards) sections */
  119. if (rx > lx) {
  120. int lxs, rxs;
  121. /* Find pixel bounds for span. */
  122. lxi = xFixedToInt(lx);
  123. rxi = xFixedToInt(rx);
  124. /* Sample coverage for edge pixels */
  125. lxs = RenderSamplesX(lx, 8);
  126. rxs = RenderSamplesX(rx, 8);
  127. /* Add coverage across row */
  128. if (lxi == rxi) {
  129. ap[lxi] = clip255(ap[lxi] + rxs - lxs);
  130. }
  131. else {
  132. ap[lxi] = clip255(ap[lxi] + N_X_FRAC(8) - lxs);
  133. /* Move forward so that lxi/rxi is the pixel span */
  134. lxi++;
  135. /* Don't bother trying to optimize the fill unless
  136. * the span is longer than 4 pixels. */
  137. if (rxi - lxi > 4) {
  138. if (fill_start < 0) {
  139. fill_start = lxi;
  140. fill_end = rxi;
  141. fill_size++;
  142. }
  143. else {
  144. if (lxi >= fill_end || rxi < fill_start) {
  145. /* We're beyond what we saved, just fill it */
  146. add_saturate_8(ap + fill_start,
  147. fill_size * N_X_FRAC(8),
  148. fill_end - fill_start);
  149. fill_start = lxi;
  150. fill_end = rxi;
  151. fill_size = 1;
  152. }
  153. else {
  154. /* Update fill_start */
  155. if (lxi > fill_start) {
  156. add_saturate_8(ap + fill_start,
  157. fill_size * N_X_FRAC(8),
  158. lxi - fill_start);
  159. fill_start = lxi;
  160. }
  161. else if (lxi < fill_start) {
  162. add_saturate_8(ap + lxi, N_X_FRAC(8),
  163. fill_start - lxi);
  164. }
  165. /* Update fill_end */
  166. if (rxi < fill_end) {
  167. add_saturate_8(ap + rxi,
  168. fill_size * N_X_FRAC(8),
  169. fill_end - rxi);
  170. fill_end = rxi;
  171. }
  172. else if (fill_end < rxi) {
  173. add_saturate_8(ap + fill_end,
  174. N_X_FRAC(8), rxi - fill_end);
  175. }
  176. fill_size++;
  177. }
  178. }
  179. }
  180. else {
  181. add_saturate_8(ap + lxi, N_X_FRAC(8), rxi - lxi);
  182. }
  183. /* Do not add in a 0 alpha here. This check is
  184. * necessary to avoid a buffer overrun, (when rx
  185. * is exactly on a pixel boundary). */
  186. if (rxs)
  187. ap[rxi] = clip255(ap[rxi] + rxs);
  188. }
  189. }
  190. if (y == b) {
  191. /* We're done, make sure we clean up any remaining fill. */
  192. if (fill_start != fill_end) {
  193. if (fill_size == N_Y_FRAC(8)) {
  194. memset(ap + fill_start, 0xff, fill_end - fill_start);
  195. }
  196. else {
  197. add_saturate_8(ap + fill_start, fill_size * N_X_FRAC(8),
  198. fill_end - fill_start);
  199. }
  200. }
  201. break;
  202. }
  203. if (xFixedFrac(y) != Y_FRAC_LAST(8)) {
  204. RenderEdgeStepSmall(l);
  205. RenderEdgeStepSmall(r);
  206. y += STEP_Y_SMALL(8);
  207. }
  208. else {
  209. RenderEdgeStepBig(l);
  210. RenderEdgeStepBig(r);
  211. y += STEP_Y_BIG(8);
  212. if (fill_start != fill_end) {
  213. if (fill_size == N_Y_FRAC(8)) {
  214. memset(ap + fill_start, 0xff, fill_end - fill_start);
  215. }
  216. else {
  217. add_saturate_8(ap + fill_start, fill_size * N_X_FRAC(8),
  218. fill_end - fill_start);
  219. }
  220. fill_start = fill_end = -1;
  221. fill_size = 0;
  222. }
  223. line += stride;
  224. }
  225. }
  226. }
  227. void
  228. fbRasterizeEdges(FbBits * buf,
  229. int bpp,
  230. int width,
  231. int stride, RenderEdge * l, RenderEdge * r, xFixed t, xFixed b)
  232. {
  233. switch (bpp) {
  234. case 1:
  235. fbRasterizeEdges1(buf, width, stride, l, r, t, b);
  236. break;
  237. case 4:
  238. fbRasterizeEdges4(buf, width, stride, l, r, t, b);
  239. break;
  240. case 8:
  241. fbRasterizeEdges8(buf, width, stride, l, r, t, b);
  242. break;
  243. }
  244. }