fbpixmap.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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. PixmapPtr
  29. fbCreatePixmapBpp(ScreenPtr pScreen, int width, int height, int depth, int bpp)
  30. {
  31. PixmapPtr pPixmap;
  32. size_t datasize;
  33. size_t paddedWidth;
  34. int adjust;
  35. int base;
  36. paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
  37. if (paddedWidth / 4 > 32767 || height > 32767)
  38. return NullPixmap;
  39. datasize = height * paddedWidth;
  40. base = pScreen->totalPixmapSize;
  41. adjust = 0;
  42. if (base & 7)
  43. adjust = 8 - (base & 7);
  44. datasize += adjust;
  45. #ifdef FB_DEBUG
  46. datasize += 2 * paddedWidth;
  47. #endif
  48. pPixmap = AllocatePixmap(pScreen, datasize);
  49. if (!pPixmap)
  50. return NullPixmap;
  51. pPixmap->drawable.type = DRAWABLE_PIXMAP;
  52. pPixmap->drawable.class = 0;
  53. pPixmap->drawable.pScreen = pScreen;
  54. pPixmap->drawable.depth = depth;
  55. pPixmap->drawable.bitsPerPixel = bpp;
  56. pPixmap->drawable.id = 0;
  57. pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  58. pPixmap->drawable.x = 0;
  59. pPixmap->drawable.y = 0;
  60. pPixmap->drawable.width = width;
  61. pPixmap->drawable.height = height;
  62. pPixmap->devKind = paddedWidth;
  63. pPixmap->refcnt = 1;
  64. pPixmap->devPrivate.ptr = (pointer) ((char *) pPixmap + base + adjust);
  65. #ifdef FB_DEBUG
  66. pPixmap->devPrivate.ptr =
  67. (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth);
  68. fbInitializeDrawable(&pPixmap->drawable);
  69. #endif
  70. return pPixmap;
  71. }
  72. PixmapPtr
  73. fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth)
  74. {
  75. int bpp;
  76. bpp = BitsPerPixel(depth);
  77. if (bpp == 32 && depth <= 24)
  78. bpp = fbGetScreenPrivate(pScreen)->pix32bpp;
  79. return fbCreatePixmapBpp(pScreen, width, height, depth, bpp);
  80. }
  81. Bool
  82. fbDestroyPixmap(PixmapPtr pPixmap)
  83. {
  84. if (--pPixmap->refcnt)
  85. return TRUE;
  86. free(pPixmap);
  87. return TRUE;
  88. }
  89. #define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \
  90. if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \
  91. (!((reg)->data->numRects && \
  92. ((r-1)->y1 == (ry1)) && \
  93. ((r-1)->y2 == (ry2)) && \
  94. ((r-1)->x1 <= (rx1)) && \
  95. ((r-1)->x2 >= (rx2))))) \
  96. { \
  97. if ((reg)->data->numRects == (reg)->data->size) \
  98. { \
  99. miRectAlloc(reg, 1); \
  100. fr = REGION_BOXPTR(reg); \
  101. r = fr + (reg)->data->numRects; \
  102. } \
  103. r->x1 = (rx1); \
  104. r->y1 = (ry1); \
  105. r->x2 = (rx2); \
  106. r->y2 = (ry2); \
  107. (reg)->data->numRects++; \
  108. if(r->x1 < (reg)->extents.x1) \
  109. (reg)->extents.x1 = r->x1; \
  110. if(r->x2 > (reg)->extents.x2) \
  111. (reg)->extents.x2 = r->x2; \
  112. r++; \
  113. }
  114. /* Convert bitmap clip mask into clipping region.
  115. * First, goes through each line and makes boxes by noting the transitions
  116. * from 0 to 1 and 1 to 0.
  117. * Then it coalesces the current line with the previous if they have boxes
  118. * at the same X coordinates.
  119. */
  120. RegionPtr
  121. fbPixmapToRegion(PixmapPtr pPix)
  122. {
  123. RegionPtr pReg;
  124. FbBits *pw, w;
  125. int ib;
  126. int width, h, base, rx1 = 0, crects;
  127. FbBits *pwLineEnd;
  128. int irectPrevStart, irectLineStart;
  129. BoxPtr prectO, prectN;
  130. BoxPtr FirstRect, rects, prectLineStart;
  131. Bool fInBox, fSame;
  132. FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1);
  133. FbBits *pwLine;
  134. int nWidth;
  135. pReg = REGION_CREATE(NULL, 1);
  136. if (!pReg)
  137. return NullRegion;
  138. FirstRect = REGION_BOXPTR(pReg);
  139. rects = FirstRect;
  140. pwLine = (FbBits *) pPix->devPrivate.ptr;
  141. nWidth = pPix->devKind >> (FB_SHIFT - 3);
  142. width = pPix->drawable.width;
  143. pReg->extents.x1 = width - 1;
  144. pReg->extents.x2 = 0;
  145. irectPrevStart = -1;
  146. for (h = 0; h < pPix->drawable.height; h++) {
  147. pw = pwLine;
  148. pwLine += nWidth;
  149. irectLineStart = rects - FirstRect;
  150. /* If the Screen left most bit of the word is set, we're starting in
  151. * a box */
  152. if (*pw & mask0) {
  153. fInBox = TRUE;
  154. rx1 = 0;
  155. }
  156. else
  157. fInBox = FALSE;
  158. /* Process all words which are fully in the pixmap */
  159. pwLineEnd = pw + (width >> FB_SHIFT);
  160. for (base = 0; pw < pwLineEnd; base += FB_UNIT) {
  161. w = *pw++;
  162. if (fInBox) {
  163. if (!~w)
  164. continue;
  165. }
  166. else {
  167. if (!w)
  168. continue;
  169. }
  170. for (ib = 0; ib < FB_UNIT; ib++) {
  171. /* If the Screen left most bit of the word is set, we're
  172. * starting a box */
  173. if (w & mask0) {
  174. if (!fInBox) {
  175. rx1 = base + ib;
  176. /* start new box */
  177. fInBox = TRUE;
  178. }
  179. }
  180. else {
  181. if (fInBox) {
  182. /* end box */
  183. ADDRECT(pReg, rects, FirstRect,
  184. rx1, h, base + ib, h + 1);
  185. fInBox = FALSE;
  186. }
  187. }
  188. /* Shift the word VISUALLY left one. */
  189. w = FbScrLeft(w, 1);
  190. }
  191. }
  192. if (width & FB_MASK) {
  193. /* Process final partial word on line */
  194. w = *pw++;
  195. for (ib = 0; ib < (width & FB_MASK); ib++) {
  196. /* If the Screen left most bit of the word is set, we're
  197. * starting a box */
  198. if (w & mask0) {
  199. if (!fInBox) {
  200. rx1 = base + ib;
  201. /* start new box */
  202. fInBox = TRUE;
  203. }
  204. }
  205. else {
  206. if (fInBox) {
  207. /* end box */
  208. ADDRECT(pReg, rects, FirstRect,
  209. rx1, h, base + ib, h + 1);
  210. fInBox = FALSE;
  211. }
  212. }
  213. /* Shift the word VISUALLY left one. */
  214. w = FbScrLeft(w, 1);
  215. }
  216. }
  217. /* If scanline ended with last bit set, end the box */
  218. if (fInBox) {
  219. ADDRECT(pReg, rects, FirstRect,
  220. rx1, h, base + (width & FB_MASK), h + 1);
  221. }
  222. /* if all rectangles on this line have the same x-coords as
  223. * those on the previous line, then add 1 to all the previous y2s and
  224. * throw away all the rectangles from this line
  225. */
  226. fSame = FALSE;
  227. if (irectPrevStart != -1) {
  228. crects = irectLineStart - irectPrevStart;
  229. if (crects == ((rects - FirstRect) - irectLineStart)) {
  230. prectO = FirstRect + irectPrevStart;
  231. prectN = prectLineStart = FirstRect + irectLineStart;
  232. fSame = TRUE;
  233. while (prectO < prectLineStart) {
  234. if ((prectO->x1 != prectN->x1) ||
  235. (prectO->x2 != prectN->x2)) {
  236. fSame = FALSE;
  237. break;
  238. }
  239. prectO++;
  240. prectN++;
  241. }
  242. if (fSame) {
  243. prectO = FirstRect + irectPrevStart;
  244. while (prectO < prectLineStart) {
  245. prectO->y2 += 1;
  246. prectO++;
  247. }
  248. rects -= crects;
  249. pReg->data->numRects -= crects;
  250. }
  251. }
  252. }
  253. if (!fSame)
  254. irectPrevStart = irectLineStart;
  255. }
  256. if (!pReg->data->numRects)
  257. pReg->extents.x1 = pReg->extents.x2 = 0;
  258. else {
  259. pReg->extents.y1 = REGION_BOXPTR(pReg)->y1;
  260. pReg->extents.y2 = REGION_END(pReg)->y2;
  261. if (pReg->data->numRects == 1) {
  262. free(pReg->data);
  263. pReg->data = (RegDataPtr) NULL;
  264. }
  265. }
  266. #ifdef DEBUG
  267. if (!miValidRegion(pReg))
  268. FatalError("Assertion failed file %s, line %d: expr\n", __FILE__,
  269. __LINE__);
  270. #endif
  271. return (pReg);
  272. }
  273. #ifdef FB_DEBUG
  274. #include <stdio.h>
  275. static Bool
  276. fbValidateBits(FbStip * bits, int stride, FbStip data)
  277. {
  278. while (stride--) {
  279. if (*bits != data) {
  280. fprintf(stderr, "fbValidateBits failed\n");
  281. return FALSE;
  282. }
  283. bits++;
  284. }
  285. }
  286. void
  287. fbValidateDrawable(DrawablePtr pDrawable)
  288. {
  289. FbStip *bits, *first, *last;
  290. int stride, bpp;
  291. int xoff, yoff;
  292. int height;
  293. Bool failed;
  294. if (pDrawable->type != DRAWABLE_PIXMAP)
  295. pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable);
  296. fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
  297. first = bits - stride;
  298. last = bits + stride * pDrawable->height;
  299. if (!fbValidateBits(first, stride, FB_HEAD_BITS) ||
  300. !fbValidateBits(last, stride, FB_TAIL_BITS))
  301. fbInitializeDrawable(pDrawable);
  302. }
  303. void
  304. fbSetBits(FbStip * bits, int stride, FbStip data)
  305. {
  306. while (stride--)
  307. *bits++ = data;
  308. }
  309. void
  310. fbInitializeDrawable(DrawablePtr pDrawable)
  311. {
  312. FbStip *bits, *first, *last;
  313. int stride, bpp;
  314. int xoff, yoff;
  315. fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
  316. first = bits - stride;
  317. last = bits + stride * pDrawable->height;
  318. fbSetBits(first, stride, FB_HEAD_BITS);
  319. fbSetBits(last, stride, FB_TAIL_BITS);
  320. }
  321. #endif /* FB_DEBUG */