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
)
40 paddedWidth
= ((width
* bpp
+ FB_MASK
) >> FB_SHIFT
) * sizeof (FbBits
);
41 if (paddedWidth
/ 4 > 32767 || height
> 32767)
43 datasize
= height
* paddedWidth
;
44 base
= pScreen
->totalPixmapSize
;
47 adjust
= 8 - (base
& 7);
50 datasize
+= 2 * paddedWidth
;
52 pPixmap
= AllocatePixmap(pScreen
, datasize
);
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
;
68 pPixmap
->devPrivate
.ptr
= (pointer
) ((char *)pPixmap
+ base
+ adjust
);
70 pPixmap
->devPrivate
.ptr
= (void *) ((char *) pPixmap
->devPrivate
.ptr
+ paddedWidth
);
71 fbInitializeDrawable (&pPixmap
->drawable
);
75 pPixmap
->screen_x
= 0;
76 pPixmap
->screen_y
= 0;
83 fbCreatePixmap (ScreenPtr pScreen
, int width
, int height
, int depth
)
86 bpp
= BitsPerPixel (depth
);
87 #ifdef FB_SCREEN_PRIVATE
88 if (bpp
== 32 && depth
<= 24)
89 bpp
= fbGetScreenPrivate(pScreen
)->pix32bpp
;
91 return fbCreatePixmapBpp (pScreen
, width
, height
, depth
, bpp
);
95 fbDestroyPixmap (PixmapPtr pPixmap
)
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; \
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; \
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.
136 fbPixmapToRegion(PixmapPtr pPix
)
138 register RegionPtr pReg
;
141 int width
, h
, base
, rx1
= 0, crects
;
143 int irectPrevStart
, irectLineStart
;
144 register BoxPtr prectO
, prectN
;
145 BoxPtr FirstRect
, rects
, prectLineStart
;
147 register FbBits mask0
= FB_ALLONES
& ~FbScrRight(FB_ALLONES
, 1);
151 pReg
= REGION_CREATE(pPix
->drawable
.pScreen
, NULL
, 1);
154 FirstRect
= REGION_BOXPTR(pReg
);
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;
166 for(h
= 0; h
< pPix
->drawable
.height
; h
++)
170 irectLineStart
= rects
- FirstRect
;
171 /* If the Screen left most bit of the word is set, we're starting in
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
)
195 for(ib
= 0; ib
< FB_UNIT
; ib
++)
197 /* If the Screen left most bit of the word is set, we're
213 ADDRECT(pReg
, rects
, FirstRect
,
214 rx1
, h
, base
+ ib
, h
+ 1);
218 /* Shift the word VISUALLY left one. */
224 /* Process final partial word on line */
226 for(ib
= 0; ib
< (width
& FB_MASK
); ib
++)
228 /* If the Screen left most bit of the word is set, we're
244 ADDRECT(pReg
, rects
, FirstRect
,
245 rx1
, h
, base
+ ib
, h
+ 1);
249 /* Shift the word VISUALLY left one. */
253 /* If scanline ended with last bit set, end the box */
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
264 if(irectPrevStart
!= -1)
266 crects
= irectLineStart
- irectPrevStart
;
267 if(crects
== ((rects
- FirstRect
) - irectLineStart
))
269 prectO
= FirstRect
+ irectPrevStart
;
270 prectN
= prectLineStart
= FirstRect
+ irectLineStart
;
272 while(prectO
< prectLineStart
)
274 if((prectO
->x1
!= prectN
->x1
) || (prectO
->x2
!= prectN
->x2
))
284 prectO
= FirstRect
+ irectPrevStart
;
285 while(prectO
< prectLineStart
)
291 pReg
->data
->numRects
-= crects
;
296 irectPrevStart
= irectLineStart
;
298 if (!pReg
->data
->numRects
)
299 pReg
->extents
.x1
= pReg
->extents
.x2
= 0;
302 pReg
->extents
.y1
= REGION_BOXPTR(pReg
)->y1
;
303 pReg
->extents
.y2
= REGION_END(pReg
)->y2
;
304 if (pReg
->data
->numRects
== 1)
307 pReg
->data
= (RegDataPtr
)NULL
;
311 fbFinishAccess(&pPix
->drawable
);
313 if (!miValidRegion(pReg
))
314 FatalError("Assertion failed file %s, line %d: expr\n", __FILE__
, __LINE__
);
328 fbValidateBits (FbStip
*bits
, int stride
, FbStip data
)
335 NCD_DEBUG ((DEBUG_FAILURE
, "fdValidateBits failed at 0x%x (is 0x%x want 0x%x)",
338 fprintf (stderr
, "fbValidateBits failed\n");
347 fbValidateDrawable (DrawablePtr pDrawable
)
349 FbStip
*bits
, *first
, *last
;
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
);
367 fbSetBits (FbStip
*bits
, int stride
, FbStip data
)
374 fbInitializeDrawable (DrawablePtr pDrawable
)
376 FbStip
*bits
, *first
, *last
;
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 */