xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

fbpixmap.c (10998B)


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