First import
[xorg_rtime.git] / xorg-server-1.4 / fb / fbpixmap.c
blob88f693e7367d4cbc0f7731fa362ba5d3869299e8
1 /*
2 * Copyright © 1998 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include <stdlib.h>
29 #include "fb.h"
31 PixmapPtr
32 fbCreatePixmapBpp (ScreenPtr pScreen, int width, int height, int depth, int bpp)
34 PixmapPtr pPixmap;
35 size_t datasize;
36 size_t paddedWidth;
37 int adjust;
38 int base;
40 paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits);
41 if (paddedWidth / 4 > 32767 || height > 32767)
42 return NullPixmap;
43 datasize = height * paddedWidth;
44 base = pScreen->totalPixmapSize;
45 adjust = 0;
46 if (base & 7)
47 adjust = 8 - (base & 7);
48 datasize += adjust;
49 #ifdef FB_DEBUG
50 datasize += 2 * paddedWidth;
51 #endif
52 pPixmap = AllocatePixmap(pScreen, datasize);
53 if (!pPixmap)
54 return NullPixmap;
55 pPixmap->drawable.type = DRAWABLE_PIXMAP;
56 pPixmap->drawable.class = 0;
57 pPixmap->drawable.pScreen = pScreen;
58 pPixmap->drawable.depth = depth;
59 pPixmap->drawable.bitsPerPixel = bpp;
60 pPixmap->drawable.id = 0;
61 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
62 pPixmap->drawable.x = 0;
63 pPixmap->drawable.y = 0;
64 pPixmap->drawable.width = width;
65 pPixmap->drawable.height = height;
66 pPixmap->devKind = paddedWidth;
67 pPixmap->refcnt = 1;
68 pPixmap->devPrivate.ptr = (pointer) ((char *)pPixmap + base + adjust);
69 #ifdef FB_DEBUG
70 pPixmap->devPrivate.ptr = (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth);
71 fbInitializeDrawable (&pPixmap->drawable);
72 #endif
74 #ifdef COMPOSITE
75 pPixmap->screen_x = 0;
76 pPixmap->screen_y = 0;
77 #endif
79 return pPixmap;
82 PixmapPtr
83 fbCreatePixmap (ScreenPtr pScreen, int width, int height, int depth)
85 int bpp;
86 bpp = BitsPerPixel (depth);
87 #ifdef FB_SCREEN_PRIVATE
88 if (bpp == 32 && depth <= 24)
89 bpp = fbGetScreenPrivate(pScreen)->pix32bpp;
90 #endif
91 return fbCreatePixmapBpp (pScreen, width, height, depth, bpp);
94 Bool
95 fbDestroyPixmap (PixmapPtr pPixmap)
97 if(--pPixmap->refcnt)
98 return TRUE;
99 xfree(pPixmap);
100 return TRUE;
103 #define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \
104 if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \
105 (!((reg)->data->numRects && \
106 ((r-1)->y1 == (ry1)) && \
107 ((r-1)->y2 == (ry2)) && \
108 ((r-1)->x1 <= (rx1)) && \
109 ((r-1)->x2 >= (rx2))))) \
111 if ((reg)->data->numRects == (reg)->data->size) \
113 miRectAlloc(reg, 1); \
114 fr = REGION_BOXPTR(reg); \
115 r = fr + (reg)->data->numRects; \
117 r->x1 = (rx1); \
118 r->y1 = (ry1); \
119 r->x2 = (rx2); \
120 r->y2 = (ry2); \
121 (reg)->data->numRects++; \
122 if(r->x1 < (reg)->extents.x1) \
123 (reg)->extents.x1 = r->x1; \
124 if(r->x2 > (reg)->extents.x2) \
125 (reg)->extents.x2 = r->x2; \
126 r++; \
129 /* Convert bitmap clip mask into clipping region.
130 * First, goes through each line and makes boxes by noting the transitions
131 * from 0 to 1 and 1 to 0.
132 * Then it coalesces the current line with the previous if they have boxes
133 * at the same X coordinates.
135 RegionPtr
136 fbPixmapToRegion(PixmapPtr pPix)
138 register RegionPtr pReg;
139 FbBits *pw, w;
140 register int ib;
141 int width, h, base, rx1 = 0, crects;
142 FbBits *pwLineEnd;
143 int irectPrevStart, irectLineStart;
144 register BoxPtr prectO, prectN;
145 BoxPtr FirstRect, rects, prectLineStart;
146 Bool fInBox, fSame;
147 register FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1);
148 FbBits *pwLine;
149 int nWidth;
151 pReg = REGION_CREATE(pPix->drawable.pScreen, NULL, 1);
152 if(!pReg)
153 return NullRegion;
154 FirstRect = REGION_BOXPTR(pReg);
155 rects = FirstRect;
157 fbPrepareAccess(&pPix->drawable);
159 pwLine = (FbBits *) pPix->devPrivate.ptr;
160 nWidth = pPix->devKind >> (FB_SHIFT-3);
162 width = pPix->drawable.width;
163 pReg->extents.x1 = width - 1;
164 pReg->extents.x2 = 0;
165 irectPrevStart = -1;
166 for(h = 0; h < pPix->drawable.height; h++)
168 pw = pwLine;
169 pwLine += nWidth;
170 irectLineStart = rects - FirstRect;
171 /* If the Screen left most bit of the word is set, we're starting in
172 * a box */
173 if(READ(pw) & mask0)
175 fInBox = TRUE;
176 rx1 = 0;
178 else
179 fInBox = FALSE;
180 /* Process all words which are fully in the pixmap */
181 pwLineEnd = pw + (width >> FB_SHIFT);
182 for (base = 0; pw < pwLineEnd; base += FB_UNIT)
184 w = READ(pw++);
185 if (fInBox)
187 if (!~w)
188 continue;
190 else
192 if (!w)
193 continue;
195 for(ib = 0; ib < FB_UNIT; ib++)
197 /* If the Screen left most bit of the word is set, we're
198 * starting a box */
199 if(w & mask0)
201 if(!fInBox)
203 rx1 = base + ib;
204 /* start new box */
205 fInBox = TRUE;
208 else
210 if(fInBox)
212 /* end box */
213 ADDRECT(pReg, rects, FirstRect,
214 rx1, h, base + ib, h + 1);
215 fInBox = FALSE;
218 /* Shift the word VISUALLY left one. */
219 w = FbScrLeft(w, 1);
222 if(width & FB_MASK)
224 /* Process final partial word on line */
225 w = READ(pw++);
226 for(ib = 0; ib < (width & FB_MASK); ib++)
228 /* If the Screen left most bit of the word is set, we're
229 * starting a box */
230 if(w & mask0)
232 if(!fInBox)
234 rx1 = base + ib;
235 /* start new box */
236 fInBox = TRUE;
239 else
241 if(fInBox)
243 /* end box */
244 ADDRECT(pReg, rects, FirstRect,
245 rx1, h, base + ib, h + 1);
246 fInBox = FALSE;
249 /* Shift the word VISUALLY left one. */
250 w = FbScrLeft(w, 1);
253 /* If scanline ended with last bit set, end the box */
254 if(fInBox)
256 ADDRECT(pReg, rects, FirstRect,
257 rx1, h, base + (width & FB_MASK), h + 1);
259 /* if all rectangles on this line have the same x-coords as
260 * those on the previous line, then add 1 to all the previous y2s and
261 * throw away all the rectangles from this line
263 fSame = FALSE;
264 if(irectPrevStart != -1)
266 crects = irectLineStart - irectPrevStart;
267 if(crects == ((rects - FirstRect) - irectLineStart))
269 prectO = FirstRect + irectPrevStart;
270 prectN = prectLineStart = FirstRect + irectLineStart;
271 fSame = TRUE;
272 while(prectO < prectLineStart)
274 if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2))
276 fSame = FALSE;
277 break;
279 prectO++;
280 prectN++;
282 if (fSame)
284 prectO = FirstRect + irectPrevStart;
285 while(prectO < prectLineStart)
287 prectO->y2 += 1;
288 prectO++;
290 rects -= crects;
291 pReg->data->numRects -= crects;
295 if(!fSame)
296 irectPrevStart = irectLineStart;
298 if (!pReg->data->numRects)
299 pReg->extents.x1 = pReg->extents.x2 = 0;
300 else
302 pReg->extents.y1 = REGION_BOXPTR(pReg)->y1;
303 pReg->extents.y2 = REGION_END(pReg)->y2;
304 if (pReg->data->numRects == 1)
306 xfree(pReg->data);
307 pReg->data = (RegDataPtr)NULL;
311 fbFinishAccess(&pPix->drawable);
312 #ifdef DEBUG
313 if (!miValidRegion(pReg))
314 FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__);
315 #endif
316 return(pReg);
319 #ifdef FB_DEBUG
321 #ifndef WIN32
322 #include <stdio.h>
323 #else
324 #include <dbg.h>
325 #endif
327 static Bool
328 fbValidateBits (FbStip *bits, int stride, FbStip data)
330 while (stride--)
332 if (*bits != data)
334 #ifdef WIN32
335 NCD_DEBUG ((DEBUG_FAILURE, "fdValidateBits failed at 0x%x (is 0x%x want 0x%x)",
336 bits, *bits, data));
337 #else
338 fprintf (stderr, "fbValidateBits failed\n");
339 #endif
340 return FALSE;
342 bits++;
346 void
347 fbValidateDrawable (DrawablePtr pDrawable)
349 FbStip *bits, *first, *last;
350 int stride, bpp;
351 int xoff, yoff;
352 int height;
353 Bool failed;
355 if (pDrawable->type != DRAWABLE_PIXMAP)
356 pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable);
357 fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
358 first = bits - stride;
359 last = bits + stride * pDrawable->height;
360 if (!fbValidateBits (first, stride, FB_HEAD_BITS) ||
361 !fbValidateBits (last, stride, FB_TAIL_BITS))
362 fbInitializeDrawable(pDrawable);
363 fbFinishAccess (pDrawable);
366 void
367 fbSetBits (FbStip *bits, int stride, FbStip data)
369 while (stride--)
370 *bits++ = data;
373 void
374 fbInitializeDrawable (DrawablePtr pDrawable)
376 FbStip *bits, *first, *last;
377 int stride, bpp;
378 int xoff, yoff;
380 fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
381 first = bits - stride;
382 last = bits + stride * pDrawable->height;
383 fbSetBits (first, stride, FB_HEAD_BITS);
384 fbSetBits (last, stride, FB_TAIL_BITS);
385 fbFinishAccess (pDrawable);
387 #endif /* FB_DEBUG */