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>
32 fbCreatePixmapBpp(ScreenPtr pScreen
, int width
, int height
, int depth
, int bpp
,
41 paddedWidth
= ((width
* bpp
+ FB_MASK
) >> FB_SHIFT
) * sizeof(FbBits
);
42 if (paddedWidth
/ 4 > 32767 || height
> 32767)
44 datasize
= height
* paddedWidth
;
45 base
= pScreen
->totalPixmapSize
;
48 adjust
= 8 - (base
& 7);
51 datasize
+= 2 * paddedWidth
;
53 pPixmap
= AllocatePixmap(pScreen
, datasize
);
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
;
69 pPixmap
->devPrivate
.ptr
= (pointer
) ((char *) pPixmap
+ base
+ adjust
);
70 pPixmap
->master_pixmap
= NULL
;
73 pPixmap
->devPrivate
.ptr
=
74 (void *) ((char *) pPixmap
->devPrivate
.ptr
+ paddedWidth
);
75 fbInitializeDrawable(&pPixmap
->drawable
);
79 pPixmap
->screen_x
= 0;
80 pPixmap
->screen_y
= 0;
83 pPixmap
->usage_hint
= usage_hint
;
89 fbCreatePixmap(ScreenPtr pScreen
, int width
, int height
, int depth
,
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
);
101 fbDestroyPixmap(PixmapPtr pPixmap
)
103 if (--pPixmap
->refcnt
)
109 #define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \
110 if (((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))))) \
117 if ((reg)->data->numRects == (reg)->data->size) \
119 RegionRectAlloc(reg, 1); \
120 fr = RegionBoxptr(reg); \
121 r = fr + (reg)->data->numRects; \
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; \
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.
142 fbPixmapToRegion(PixmapPtr pPix
)
144 register RegionPtr pReg
;
147 int width
, h
, base
, rx1
= 0, crects
;
149 int irectPrevStart
, irectLineStart
;
150 register BoxPtr prectO
, prectN
;
151 BoxPtr FirstRect
, rects
, prectLineStart
;
153 register FbBits mask0
= FB_ALLONES
& ~FbScrRight(FB_ALLONES
, 1);
157 pReg
= RegionCreate(NULL
, 1);
160 FirstRect
= RegionBoxptr(pReg
);
163 fbPrepareAccess(&pPix
->drawable
);
165 pwLine
= (FbBits
*) pPix
->devPrivate
.ptr
;
166 nWidth
= pPix
->devKind
>> (FB_SHIFT
- 3);
168 width
= pPix
->drawable
.width
;
169 pReg
->extents
.x1
= width
- 1;
170 pReg
->extents
.x2
= 0;
172 for (h
= 0; h
< pPix
->drawable
.height
; h
++) {
175 irectLineStart
= rects
- FirstRect
;
176 /* If the Screen left most bit of the word is set, we're starting in
178 if (READ(pw
) & mask0
) {
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
) {
196 for (ib
= 0; ib
< FB_UNIT
; ib
++) {
197 /* If the Screen left most bit of the word is set, we're
209 ADDRECT(pReg
, rects
, FirstRect
,
210 rx1
, h
, base
+ ib
, h
+ 1);
214 /* Shift the word VISUALLY left one. */
218 if (width
& FB_MASK
) {
219 /* Process final partial word on line */
221 for (ib
= 0; ib
< (width
& FB_MASK
); ib
++) {
222 /* If the Screen left most bit of the word is set, we're
234 ADDRECT(pReg
, rects
, FirstRect
,
235 rx1
, h
, base
+ ib
, h
+ 1);
239 /* Shift the word VISUALLY left one. */
243 /* If scanline ended with last bit set, end the box */
245 ADDRECT(pReg
, rects
, FirstRect
,
246 rx1
, h
, base
+ (width
& FB_MASK
), h
+ 1);
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
253 if (irectPrevStart
!= -1) {
254 crects
= irectLineStart
- irectPrevStart
;
255 if (crects
== ((rects
- FirstRect
) - irectLineStart
)) {
256 prectO
= FirstRect
+ irectPrevStart
;
257 prectN
= prectLineStart
= FirstRect
+ irectLineStart
;
259 while (prectO
< prectLineStart
) {
260 if ((prectO
->x1
!= prectN
->x1
) ||
261 (prectO
->x2
!= prectN
->x2
)) {
269 prectO
= FirstRect
+ irectPrevStart
;
270 while (prectO
< prectLineStart
) {
275 pReg
->data
->numRects
-= crects
;
280 irectPrevStart
= irectLineStart
;
282 if (!pReg
->data
->numRects
)
283 pReg
->extents
.x1
= pReg
->extents
.x2
= 0;
285 pReg
->extents
.y1
= RegionBoxptr(pReg
)->y1
;
286 pReg
->extents
.y2
= RegionEnd(pReg
)->y2
;
287 if (pReg
->data
->numRects
== 1) {
289 pReg
->data
= (RegDataPtr
) NULL
;
293 fbFinishAccess(&pPix
->drawable
);
295 if (!RegionIsValid(pReg
))
296 FatalError("Assertion failed file %s, line %d: expr\n", __FILE__
,
311 fbValidateBits(FbStip
* bits
, int stride
, FbStip data
)
316 NCD_DEBUG((DEBUG_FAILURE
,
317 "fdValidateBits failed at 0x%x (is 0x%x want 0x%x)",
320 fprintf(stderr
, "fbValidateBits failed\n");
329 fbValidateDrawable(DrawablePtr pDrawable
)
331 FbStip
*bits
, *first
, *last
;
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
);
349 fbSetBits(FbStip
* bits
, int stride
, FbStip data
)
356 fbInitializeDrawable(DrawablePtr pDrawable
)
358 FbStip
*bits
, *first
, *last
;
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
);
369 #endif /* FB_DEBUG */