123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /*
- *
- * Copyright © 1998 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <stdlib.h>
- #include "fb.h"
- PixmapPtr
- fbCreatePixmapBpp(ScreenPtr pScreen, int width, int height, int depth, int bpp)
- {
- PixmapPtr pPixmap;
- size_t datasize;
- size_t paddedWidth;
- int adjust;
- int base;
- paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
- if (paddedWidth / 4 > 32767 || height > 32767)
- return NullPixmap;
- datasize = height * paddedWidth;
- base = pScreen->totalPixmapSize;
- adjust = 0;
- if (base & 7)
- adjust = 8 - (base & 7);
- datasize += adjust;
- #ifdef FB_DEBUG
- datasize += 2 * paddedWidth;
- #endif
- pPixmap = AllocatePixmap(pScreen, datasize);
- if (!pPixmap)
- return NullPixmap;
- pPixmap->drawable.type = DRAWABLE_PIXMAP;
- pPixmap->drawable.class = 0;
- pPixmap->drawable.pScreen = pScreen;
- pPixmap->drawable.depth = depth;
- pPixmap->drawable.bitsPerPixel = bpp;
- pPixmap->drawable.id = 0;
- pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- pPixmap->drawable.x = 0;
- pPixmap->drawable.y = 0;
- pPixmap->drawable.width = width;
- pPixmap->drawable.height = height;
- pPixmap->devKind = paddedWidth;
- pPixmap->refcnt = 1;
- pPixmap->devPrivate.ptr = (pointer) ((char *) pPixmap + base + adjust);
- #ifdef FB_DEBUG
- pPixmap->devPrivate.ptr =
- (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth);
- fbInitializeDrawable(&pPixmap->drawable);
- #endif
- return pPixmap;
- }
- PixmapPtr
- fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth)
- {
- int bpp;
- bpp = BitsPerPixel(depth);
- if (bpp == 32 && depth <= 24)
- bpp = fbGetScreenPrivate(pScreen)->pix32bpp;
- return fbCreatePixmapBpp(pScreen, width, height, depth, bpp);
- }
- Bool
- fbDestroyPixmap(PixmapPtr pPixmap)
- {
- if (--pPixmap->refcnt)
- return TRUE;
- free(pPixmap);
- return TRUE;
- }
- #define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \
- if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \
- (!((reg)->data->numRects && \
- ((r-1)->y1 == (ry1)) && \
- ((r-1)->y2 == (ry2)) && \
- ((r-1)->x1 <= (rx1)) && \
- ((r-1)->x2 >= (rx2))))) \
- { \
- if ((reg)->data->numRects == (reg)->data->size) \
- { \
- miRectAlloc(reg, 1); \
- fr = REGION_BOXPTR(reg); \
- r = fr + (reg)->data->numRects; \
- } \
- r->x1 = (rx1); \
- r->y1 = (ry1); \
- r->x2 = (rx2); \
- r->y2 = (ry2); \
- (reg)->data->numRects++; \
- if(r->x1 < (reg)->extents.x1) \
- (reg)->extents.x1 = r->x1; \
- if(r->x2 > (reg)->extents.x2) \
- (reg)->extents.x2 = r->x2; \
- r++; \
- }
- /* Convert bitmap clip mask into clipping region.
- * First, goes through each line and makes boxes by noting the transitions
- * from 0 to 1 and 1 to 0.
- * Then it coalesces the current line with the previous if they have boxes
- * at the same X coordinates.
- */
- RegionPtr
- fbPixmapToRegion(PixmapPtr pPix)
- {
- RegionPtr pReg;
- FbBits *pw, w;
- int ib;
- int width, h, base, rx1 = 0, crects;
- FbBits *pwLineEnd;
- int irectPrevStart, irectLineStart;
- BoxPtr prectO, prectN;
- BoxPtr FirstRect, rects, prectLineStart;
- Bool fInBox, fSame;
- FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1);
- FbBits *pwLine;
- int nWidth;
- pReg = REGION_CREATE(NULL, 1);
- if (!pReg)
- return NullRegion;
- FirstRect = REGION_BOXPTR(pReg);
- rects = FirstRect;
- pwLine = (FbBits *) pPix->devPrivate.ptr;
- nWidth = pPix->devKind >> (FB_SHIFT - 3);
- width = pPix->drawable.width;
- pReg->extents.x1 = width - 1;
- pReg->extents.x2 = 0;
- irectPrevStart = -1;
- for (h = 0; h < pPix->drawable.height; h++) {
- pw = pwLine;
- pwLine += nWidth;
- irectLineStart = rects - FirstRect;
- /* If the Screen left most bit of the word is set, we're starting in
- * a box */
- if (*pw & mask0) {
- fInBox = TRUE;
- rx1 = 0;
- }
- else
- fInBox = FALSE;
- /* Process all words which are fully in the pixmap */
- pwLineEnd = pw + (width >> FB_SHIFT);
- for (base = 0; pw < pwLineEnd; base += FB_UNIT) {
- w = *pw++;
- if (fInBox) {
- if (!~w)
- continue;
- }
- else {
- if (!w)
- continue;
- }
- for (ib = 0; ib < FB_UNIT; ib++) {
- /* If the Screen left most bit of the word is set, we're
- * starting a box */
- if (w & mask0) {
- if (!fInBox) {
- rx1 = base + ib;
- /* start new box */
- fInBox = TRUE;
- }
- }
- else {
- if (fInBox) {
- /* end box */
- ADDRECT(pReg, rects, FirstRect,
- rx1, h, base + ib, h + 1);
- fInBox = FALSE;
- }
- }
- /* Shift the word VISUALLY left one. */
- w = FbScrLeft(w, 1);
- }
- }
- if (width & FB_MASK) {
- /* Process final partial word on line */
- w = *pw++;
- for (ib = 0; ib < (width & FB_MASK); ib++) {
- /* If the Screen left most bit of the word is set, we're
- * starting a box */
- if (w & mask0) {
- if (!fInBox) {
- rx1 = base + ib;
- /* start new box */
- fInBox = TRUE;
- }
- }
- else {
- if (fInBox) {
- /* end box */
- ADDRECT(pReg, rects, FirstRect,
- rx1, h, base + ib, h + 1);
- fInBox = FALSE;
- }
- }
- /* Shift the word VISUALLY left one. */
- w = FbScrLeft(w, 1);
- }
- }
- /* If scanline ended with last bit set, end the box */
- if (fInBox) {
- ADDRECT(pReg, rects, FirstRect,
- rx1, h, base + (width & FB_MASK), h + 1);
- }
- /* if all rectangles on this line have the same x-coords as
- * those on the previous line, then add 1 to all the previous y2s and
- * throw away all the rectangles from this line
- */
- fSame = FALSE;
- if (irectPrevStart != -1) {
- crects = irectLineStart - irectPrevStart;
- if (crects == ((rects - FirstRect) - irectLineStart)) {
- prectO = FirstRect + irectPrevStart;
- prectN = prectLineStart = FirstRect + irectLineStart;
- fSame = TRUE;
- while (prectO < prectLineStart) {
- if ((prectO->x1 != prectN->x1) ||
- (prectO->x2 != prectN->x2)) {
- fSame = FALSE;
- break;
- }
- prectO++;
- prectN++;
- }
- if (fSame) {
- prectO = FirstRect + irectPrevStart;
- while (prectO < prectLineStart) {
- prectO->y2 += 1;
- prectO++;
- }
- rects -= crects;
- pReg->data->numRects -= crects;
- }
- }
- }
- if (!fSame)
- irectPrevStart = irectLineStart;
- }
- if (!pReg->data->numRects)
- pReg->extents.x1 = pReg->extents.x2 = 0;
- else {
- pReg->extents.y1 = REGION_BOXPTR(pReg)->y1;
- pReg->extents.y2 = REGION_END(pReg)->y2;
- if (pReg->data->numRects == 1) {
- free(pReg->data);
- pReg->data = (RegDataPtr) NULL;
- }
- }
- #ifdef DEBUG
- if (!miValidRegion(pReg))
- FatalError("Assertion failed file %s, line %d: expr\n", __FILE__,
- __LINE__);
- #endif
- return (pReg);
- }
- #ifdef FB_DEBUG
- #include <stdio.h>
- static Bool
- fbValidateBits(FbStip * bits, int stride, FbStip data)
- {
- while (stride--) {
- if (*bits != data) {
- fprintf(stderr, "fbValidateBits failed\n");
- return FALSE;
- }
- bits++;
- }
- }
- void
- fbValidateDrawable(DrawablePtr pDrawable)
- {
- FbStip *bits, *first, *last;
- int stride, bpp;
- int xoff, yoff;
- int height;
- Bool failed;
- if (pDrawable->type != DRAWABLE_PIXMAP)
- pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable);
- fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
- first = bits - stride;
- last = bits + stride * pDrawable->height;
- if (!fbValidateBits(first, stride, FB_HEAD_BITS) ||
- !fbValidateBits(last, stride, FB_TAIL_BITS))
- fbInitializeDrawable(pDrawable);
- }
- void
- fbSetBits(FbStip * bits, int stride, FbStip data)
- {
- while (stride--)
- *bits++ = data;
- }
- void
- fbInitializeDrawable(DrawablePtr pDrawable)
- {
- FbStip *bits, *first, *last;
- int stride, bpp;
- int xoff, yoff;
- fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff);
- first = bits - stride;
- last = bits + stride * pDrawable->height;
- fbSetBits(first, stride, FB_HEAD_BITS);
- fbSetBits(last, stride, FB_TAIL_BITS);
- }
- #endif /* FB_DEBUG */
|