xserver

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

fbseg.c (12888B)


      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 #include "miline.h"
     31 
     32 #define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
     33 					((dir < 0) ? FbStipLeft(mask,bpp) : \
     34 					 FbStipRight(mask,bpp)))
     35 
     36 static void
     37 fbBresSolid(DrawablePtr pDrawable,
     38             GCPtr pGC,
     39             int dashOffset,
     40             int signdx,
     41             int signdy,
     42             int axis, int x1, int y1, int e, int e1, int e3, int len)
     43 {
     44     FbStip *dst;
     45     FbStride dstStride;
     46     int dstBpp;
     47     int dstXoff, dstYoff;
     48     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
     49     FbStip and = (FbStip) pPriv->and;
     50     FbStip xor = (FbStip) pPriv->xor;
     51     FbStip mask, mask0;
     52     FbStip bits;
     53 
     54     fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
     55     dst += ((y1 + dstYoff) * dstStride);
     56     x1 = (x1 + dstXoff) * dstBpp;
     57     dst += x1 >> FB_STIP_SHIFT;
     58     x1 &= FB_STIP_MASK;
     59     mask0 = FbStipMask(0, dstBpp);
     60     mask = FbStipRight(mask0, x1);
     61     if (signdx < 0)
     62         mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp);
     63     if (signdy < 0)
     64         dstStride = -dstStride;
     65     if (axis == X_AXIS) {
     66         bits = 0;
     67         while (len--) {
     68             bits |= mask;
     69             mask = fbBresShiftMask(mask, signdx, dstBpp);
     70             if (!mask) {
     71                 WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
     72                 bits = 0;
     73                 dst += signdx;
     74                 mask = mask0;
     75             }
     76             e += e1;
     77             if (e >= 0) {
     78                 if (bits) {
     79                     WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
     80                     bits = 0;
     81                 }
     82                 dst += dstStride;
     83                 e += e3;
     84             }
     85         }
     86         if (bits)
     87             WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
     88     }
     89     else {
     90         while (len--) {
     91             WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask));
     92             dst += dstStride;
     93             e += e1;
     94             if (e >= 0) {
     95                 e += e3;
     96                 mask = fbBresShiftMask(mask, signdx, dstBpp);
     97                 if (!mask) {
     98                     dst += signdx;
     99                     mask = mask0;
    100                 }
    101             }
    102         }
    103     }
    104 
    105     fbFinishAccess(pDrawable);
    106 }
    107 
    108 static void
    109 fbBresDash(DrawablePtr pDrawable,
    110            GCPtr pGC,
    111            int dashOffset,
    112            int signdx,
    113            int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len)
    114 {
    115     FbStip *dst;
    116     FbStride dstStride;
    117     int dstBpp;
    118     int dstXoff, dstYoff;
    119     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
    120     FbStip and = (FbStip) pPriv->and;
    121     FbStip xor = (FbStip) pPriv->xor;
    122     FbStip bgand = (FbStip) pPriv->bgand;
    123     FbStip bgxor = (FbStip) pPriv->bgxor;
    124     FbStip mask, mask0;
    125 
    126     FbDashDeclare;
    127     int dashlen;
    128     Bool even;
    129     Bool doOdd;
    130 
    131     fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
    132     doOdd = pGC->lineStyle == LineDoubleDash;
    133 
    134     FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
    135 
    136     dst += ((y1 + dstYoff) * dstStride);
    137     x1 = (x1 + dstXoff) * dstBpp;
    138     dst += x1 >> FB_STIP_SHIFT;
    139     x1 &= FB_STIP_MASK;
    140     mask0 = FbStipMask(0, dstBpp);
    141     mask = FbStipRight(mask0, x1);
    142     if (signdx < 0)
    143         mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp);
    144     if (signdy < 0)
    145         dstStride = -dstStride;
    146     while (len--) {
    147         if (even)
    148             WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask));
    149         else if (doOdd)
    150             WRITE(dst, FbDoMaskRRop(READ(dst), bgand, bgxor, mask));
    151         if (axis == X_AXIS) {
    152             mask = fbBresShiftMask(mask, signdx, dstBpp);
    153             if (!mask) {
    154                 dst += signdx;
    155                 mask = mask0;
    156             }
    157             e += e1;
    158             if (e >= 0) {
    159                 dst += dstStride;
    160                 e += e3;
    161             }
    162         }
    163         else {
    164             dst += dstStride;
    165             e += e1;
    166             if (e >= 0) {
    167                 e += e3;
    168                 mask = fbBresShiftMask(mask, signdx, dstBpp);
    169                 if (!mask) {
    170                     dst += signdx;
    171                     mask = mask0;
    172                 }
    173             }
    174         }
    175         FbDashStep(dashlen, even);
    176     }
    177 
    178     fbFinishAccess(pDrawable);
    179 }
    180 
    181 static void
    182 fbBresFill(DrawablePtr pDrawable,
    183            GCPtr pGC,
    184            int dashOffset,
    185            int signdx,
    186            int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len)
    187 {
    188     while (len--) {
    189         fbFill(pDrawable, pGC, x1, y1, 1, 1);
    190         if (axis == X_AXIS) {
    191             x1 += signdx;
    192             e += e1;
    193             if (e >= 0) {
    194                 e += e3;
    195                 y1 += signdy;
    196             }
    197         }
    198         else {
    199             y1 += signdy;
    200             e += e1;
    201             if (e >= 0) {
    202                 e += e3;
    203                 x1 += signdx;
    204             }
    205         }
    206     }
    207 }
    208 
    209 static void
    210 fbSetFg(DrawablePtr pDrawable, GCPtr pGC, Pixel fg)
    211 {
    212     if (fg != pGC->fgPixel) {
    213         ChangeGCVal val;
    214 
    215         val.val = fg;
    216         ChangeGC(NullClient, pGC, GCForeground, &val);
    217         ValidateGC(pDrawable, pGC);
    218     }
    219 }
    220 
    221 static void
    222 fbBresFillDash(DrawablePtr pDrawable,
    223                GCPtr pGC,
    224                int dashOffset,
    225                int signdx,
    226                int signdy,
    227                int axis, int x1, int y1, int e, int e1, int e3, int len)
    228 {
    229     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
    230 
    231     FbDashDeclare;
    232     int dashlen;
    233     Bool even;
    234     Bool doOdd;
    235     Bool doBg;
    236     Pixel fg, bg;
    237 
    238     fg = pGC->fgPixel;
    239     bg = pGC->bgPixel;
    240 
    241     /* whether to fill the odd dashes */
    242     doOdd = pGC->lineStyle == LineDoubleDash;
    243     /* whether to switch fg to bg when filling odd dashes */
    244     doBg = doOdd && (pGC->fillStyle == FillSolid ||
    245                      pGC->fillStyle == FillStippled);
    246 
    247     /* compute current dash position */
    248     FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
    249 
    250     while (len--) {
    251         if (even || doOdd) {
    252             if (doBg) {
    253                 if (even)
    254                     fbSetFg(pDrawable, pGC, fg);
    255                 else
    256                     fbSetFg(pDrawable, pGC, bg);
    257             }
    258             fbFill(pDrawable, pGC, x1, y1, 1, 1);
    259         }
    260         if (axis == X_AXIS) {
    261             x1 += signdx;
    262             e += e1;
    263             if (e >= 0) {
    264                 e += e3;
    265                 y1 += signdy;
    266             }
    267         }
    268         else {
    269             y1 += signdy;
    270             e += e1;
    271             if (e >= 0) {
    272                 e += e3;
    273                 x1 += signdx;
    274             }
    275         }
    276         FbDashStep(dashlen, even);
    277     }
    278     if (doBg)
    279         fbSetFg(pDrawable, pGC, fg);
    280 }
    281 
    282 /*
    283  * For drivers that want to bail drawing some lines, this
    284  * function takes care of selecting the appropriate rasterizer
    285  * based on the contents of the specified GC.
    286  */
    287 
    288 static FbBres *
    289 fbSelectBres(DrawablePtr pDrawable, GCPtr pGC)
    290 {
    291     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
    292     int dstBpp = pDrawable->bitsPerPixel;
    293     FbBres *bres;
    294 
    295     if (pGC->lineStyle == LineSolid) {
    296         bres = fbBresFill;
    297         if (pGC->fillStyle == FillSolid) {
    298             bres = fbBresSolid;
    299             if (pPriv->and == 0) {
    300                 switch (dstBpp) {
    301                 case 8:
    302                     bres = fbBresSolid8;
    303                     break;
    304                 case 16:
    305                     bres = fbBresSolid16;
    306                     break;
    307                 case 32:
    308                     bres = fbBresSolid32;
    309                     break;
    310                 }
    311             }
    312         }
    313     }
    314     else {
    315         bres = fbBresFillDash;
    316         if (pGC->fillStyle == FillSolid) {
    317             bres = fbBresDash;
    318             if (pPriv->and == 0 &&
    319                 (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) {
    320                 switch (dstBpp) {
    321                 case 8:
    322                     bres = fbBresDash8;
    323                     break;
    324                 case 16:
    325                     bres = fbBresDash16;
    326                     break;
    327                 case 32:
    328                     bres = fbBresDash32;
    329                     break;
    330                 }
    331             }
    332         }
    333     }
    334     return bres;
    335 }
    336 
    337 void
    338 fbSegment(DrawablePtr pDrawable,
    339           GCPtr pGC,
    340           int x1, int y1, int x2, int y2, Bool drawLast, int *dashOffset)
    341 {
    342     FbBres *bres;
    343     RegionPtr pClip = fbGetCompositeClip(pGC);
    344     BoxPtr pBox;
    345     int nBox;
    346     int adx;                    /* abs values of dx and dy */
    347     int ady;
    348     int signdx;                 /* sign of dx and dy */
    349     int signdy;
    350     int e, e1, e2, e3;          /* bresenham error and increments */
    351     int len;                    /* length of segment */
    352     int axis;                   /* major axis */
    353     int octant;
    354     int dashoff;
    355     int doff;
    356     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
    357     unsigned int oc1;           /* outcode of point 1 */
    358     unsigned int oc2;           /* outcode of point 2 */
    359 
    360     nBox = RegionNumRects(pClip);
    361     pBox = RegionRects(pClip);
    362 
    363     bres = fbSelectBres(pDrawable, pGC);
    364 
    365     CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
    366 
    367     if (adx > ady) {
    368         axis = X_AXIS;
    369         e1 = ady << 1;
    370         e2 = e1 - (adx << 1);
    371         e = e1 - adx;
    372         len = adx;
    373     }
    374     else {
    375         axis = Y_AXIS;
    376         e1 = adx << 1;
    377         e2 = e1 - (ady << 1);
    378         e = e1 - ady;
    379         SetYMajorOctant(octant);
    380         len = ady;
    381     }
    382 
    383     FIXUP_ERROR(e, octant, bias);
    384 
    385     /*
    386      * Adjust error terms to compare against zero
    387      */
    388     e3 = e2 - e1;
    389     e = e - e1;
    390 
    391     /* we have bresenham parameters and two points.
    392        all we have to do now is clip and draw.
    393      */
    394 
    395     if (drawLast)
    396         len++;
    397     dashoff = *dashOffset;
    398     *dashOffset = dashoff + len;
    399     while (nBox--) {
    400         oc1 = 0;
    401         oc2 = 0;
    402         OUTCODES(oc1, x1, y1, pBox);
    403         OUTCODES(oc2, x2, y2, pBox);
    404         if ((oc1 | oc2) == 0) {
    405             (*bres) (pDrawable, pGC, dashoff,
    406                      signdx, signdy, axis, x1, y1, e, e1, e3, len);
    407             break;
    408         }
    409         else if (oc1 & oc2) {
    410             pBox++;
    411         }
    412         else {
    413             int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
    414             int clip1 = 0, clip2 = 0;
    415             int clipdx, clipdy;
    416             int err;
    417 
    418             if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2 - 1,
    419                                pBox->y2 - 1,
    420                                &new_x1, &new_y1, &new_x2, &new_y2,
    421                                adx, ady, &clip1, &clip2,
    422                                octant, bias, oc1, oc2) == -1) {
    423                 pBox++;
    424                 continue;
    425             }
    426 
    427             if (axis == X_AXIS)
    428                 len = abs(new_x2 - new_x1);
    429             else
    430                 len = abs(new_y2 - new_y1);
    431             if (clip2 != 0 || drawLast)
    432                 len++;
    433             if (len) {
    434                 /* unwind bresenham error term to first point */
    435                 doff = dashoff;
    436                 err = e;
    437                 if (clip1) {
    438                     clipdx = abs(new_x1 - x1);
    439                     clipdy = abs(new_y1 - y1);
    440                     if (axis == X_AXIS) {
    441                         doff += clipdx;
    442                         err += e3 * clipdy + e1 * clipdx;
    443                     }
    444                     else {
    445                         doff += clipdy;
    446                         err += e3 * clipdx + e1 * clipdy;
    447                     }
    448                 }
    449                 (*bres) (pDrawable, pGC, doff,
    450                          signdx, signdy, axis, new_x1, new_y1,
    451                          err, e1, e3, len);
    452             }
    453             pBox++;
    454         }
    455     }                           /* while (nBox--) */
    456 }