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