]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/cfb/cfbsetsp.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / cfb / cfbsetsp.c
1 /* $XConsortium: cfbsetsp.c,v 5.10 94/04/17 20:29:01 dpw Exp $ */
2 /* $XFree86: xc/programs/Xserver/cfb/cfbsetsp.c,v 3.0 1996/06/29 09:05:49 dawes Exp $ */
3 /***********************************************************
4
5 Copyright (c) 1987  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
27
28
29 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30
31                         All Rights Reserved
32
33 Permission to use, copy, modify, and distribute this software and its 
34 documentation for any purpose and without fee is hereby granted, 
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in 
37 supporting documentation, and that the name of Digital not be
38 used in advertising or publicity pertaining to distribution of the
39 software without specific, written prior permission.  
40
41 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
42 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
43 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
44 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
45 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
46 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 SOFTWARE.
48
49 ******************************************************************/
50
51 #include "X.h"
52 #include "Xmd.h"
53 #include "servermd.h"
54
55 #include "misc.h"
56 #include "regionstr.h"
57 #include "gcstruct.h"
58 #include "windowstr.h"
59 #include "pixmapstr.h"
60 #include "scrnintstr.h"
61
62 #include "cfb.h"
63 #include "cfbmskbits.h"
64 #include <mergerop.h>
65
66 /* cfbSetScanline -- copies the bits from psrc to the drawable starting at
67  * (xStart, y) and continuing to (xEnd, y).  xOrigin tells us where psrc 
68  * starts on the scanline. (I.e., if this scanline passes through multiple
69  * boxes, we may not want to start grabbing bits at psrc but at some offset
70  * further on.) 
71  */
72 cfbSetScanline(y, xOrigin, xStart, xEnd, psrc, alu, pdstBase, widthDst, planemask)
73     int                 y;
74     int                 xOrigin;        /* where this scanline starts */
75     int                 xStart;         /* first bit to use from scanline */
76     int                 xEnd;           /* last bit to use from scanline + 1 */
77     register unsigned int *psrc;
78     register int        alu;            /* raster op */
79     int                 *pdstBase;      /* start of the drawable */
80     int                 widthDst;       /* width of drawable in words */
81     unsigned long       planemask;
82 {
83     int                 w;              /* width of scanline in bits */
84     register int        *pdst;          /* where to put the bits */
85     register int        tmpSrc;         /* scratch buffer to collect bits in */
86     int                 dstBit;         /* offset in bits from beginning of 
87                                          * word */
88     register int        nstart;         /* number of bits from first partial */
89     register int        nend;           /* " " last partial word */
90     int                 offSrc;
91     int         startmask, endmask, nlMiddle, nl;
92 #if PSZ == 24
93     register char *psrcb, *pdstb;
94     register int        xIndex;
95 #endif
96     DeclareMergeRop()
97
98     InitializeMergeRop(alu,planemask);
99 #if PSZ == 24
100     pdst = pdstBase + (y * widthDst);
101     xIndex = xStart;
102     pdstb = (char *)pdst + (xStart * 3);
103     offSrc = xStart - xOrigin;
104     psrcb = (char *)psrc + (offSrc * 3);
105 #else
106     pdst = pdstBase + (y * widthDst) + (xStart >> PWSH); 
107     psrc += (xStart - xOrigin) >> PWSH;
108     offSrc = (xStart - xOrigin) & PIM;
109 #endif
110     w = xEnd - xStart;
111     dstBit = xStart & PIM;
112
113 #if PSZ == 24
114     nl = w;
115     while (nl--){
116       psrc = (unsigned int *)((unsigned long)psrcb & ~0x03);
117       getbits24(psrc, tmpSrc, offSrc);
118       pdst = (int *)((unsigned long)pdstb & ~0x03);
119       DoMergeRop24(tmpSrc, pdst, xIndex);
120       offSrc++;
121       psrcb += 3;
122       xIndex++;
123       pdstb += 3;
124     } 
125 #else /* PSZ == 24 */
126     if (dstBit + w <= PPW) 
127     { 
128         maskpartialbits(dstBit, w, startmask);
129         endmask = 0;
130         nlMiddle = 0;
131     } 
132     else 
133     { 
134         maskbits(xStart, w, startmask, endmask, nlMiddle);
135     }
136     if (startmask) 
137         nstart = PPW - dstBit; 
138     else 
139         nstart = 0; 
140     if (endmask) 
141         nend = xEnd & PIM; 
142     else 
143         nend = 0; 
144     if (startmask) 
145     { 
146         getbits(psrc, offSrc, nstart, tmpSrc);
147         putbitsmropshort(tmpSrc, dstBit, nstart, pdst);
148         pdst++; 
149         offSrc += nstart;
150         if (offSrc > PLST)
151         {
152             psrc++;
153             offSrc -= PPW;
154         }
155     } 
156     nl = nlMiddle; 
157     while (nl--) 
158     { 
159         getbits(psrc, offSrc, PPW, tmpSrc);
160         *pdst = DoMergeRop(tmpSrc, *pdst);
161         pdst++; 
162         psrc++; 
163     } 
164     if (endmask) 
165     { 
166         getbits(psrc, offSrc, nend, tmpSrc);
167         putbitsmropshort(tmpSrc, 0, nend, pdst);
168     } 
169 #endif /* PSZ == 24 */
170 }
171
172 \f
173
174 /* SetSpans -- for each span copy pwidth[i] bits from psrc to pDrawable at
175  * ppt[i] using the raster op from the GC.  If fSorted is TRUE, the scanlines
176  * are in increasing Y order.
177  * Source bit lines are server scanline padded so that they always begin
178  * on a word boundary.
179  */ 
180 void
181 cfbSetSpans(pDrawable, pGC, pcharsrc, ppt, pwidth, nspans, fSorted)
182     DrawablePtr         pDrawable;
183     GCPtr               pGC;
184     char                *pcharsrc;
185     register DDXPointPtr ppt;
186     int                 *pwidth;
187     int                 nspans;
188     int                 fSorted;
189 {
190     unsigned int        *psrc = (unsigned int *)pcharsrc;
191     unsigned long       *pdstBase;      /* start of dst bitmap */
192     int                 widthDst;       /* width of bitmap in words */
193     register BoxPtr     pbox, pboxLast, pboxTest;
194     register DDXPointPtr pptLast;
195     int                 alu;
196     RegionPtr           prgnDst;
197     int                 xStart, xEnd;
198     int                 yMax;
199
200     alu = pGC->alu;
201     prgnDst = cfbGetCompositeClip(pGC);
202     pptLast = ppt + nspans;
203
204     cfbGetLongWidthAndPointer (pDrawable, widthDst, pdstBase)
205
206     yMax = (int) pDrawable->y + (int) pDrawable->height;
207
208     pbox = REGION_RECTS(prgnDst);
209     pboxLast = pbox + REGION_NUM_RECTS(prgnDst);
210
211     if(fSorted)
212     {
213     /* scan lines sorted in ascending order. Because they are sorted, we
214      * don't have to check each scanline against each clip box.  We can be
215      * sure that this scanline only has to be clipped to boxes at or after the
216      * beginning of this y-band 
217      */
218         pboxTest = pbox;
219         while(ppt < pptLast)
220         {
221             pbox = pboxTest;
222             if(ppt->y >= yMax)
223                 break;
224             while(pbox < pboxLast)
225             {
226                 if(pbox->y1 > ppt->y)
227                 {
228                     /* scanline is before clip box */
229                     break;
230                 }
231                 else if(pbox->y2 <= ppt->y)
232                 {
233                     /* clip box is before scanline */
234                     pboxTest = ++pbox;
235                     continue;
236                 }
237                 else if(pbox->x1 > ppt->x + *pwidth) 
238                 {
239                     /* clip box is to right of scanline */
240                     break;
241                 }
242                 else if(pbox->x2 <= ppt->x)
243                 {
244                     /* scanline is to right of clip box */
245                     pbox++;
246                     continue;
247                 }
248
249                 /* at least some of the scanline is in the current clip box */
250                 xStart = max(pbox->x1, ppt->x);
251                 xEnd = min(ppt->x + *pwidth, pbox->x2);
252                 cfbSetScanline(ppt->y, ppt->x, xStart, xEnd, psrc, alu,
253                     (int *)pdstBase, widthDst, pGC->planemask);
254                 if(ppt->x + *pwidth <= pbox->x2)
255                 {
256                     /* End of the line, as it were */
257                     break;
258                 }
259                 else
260                     pbox++;
261             }
262             /* We've tried this line against every box; it must be outside them
263              * all.  move on to the next point */
264             ppt++;
265             psrc += PixmapWidthInPadUnits(*pwidth, pDrawable->depth);
266             pwidth++;
267         }
268     }
269     else
270     {
271     /* scan lines not sorted. We must clip each line against all the boxes */
272         while(ppt < pptLast)
273         {
274             if(ppt->y >= 0 && ppt->y < yMax)
275             {
276                 
277                 for(pbox = REGION_RECTS(prgnDst); pbox< pboxLast; pbox++)
278                 {
279                     if(pbox->y1 > ppt->y)
280                     {
281                         /* rest of clip region is above this scanline,
282                          * skip it */
283                         break;
284                     }
285                     if(pbox->y2 <= ppt->y)
286                     {
287                         /* clip box is below scanline */
288                         pbox++;
289                         break;
290                     }
291                     if(pbox->x1 <= ppt->x + *pwidth &&
292                        pbox->x2 > ppt->x)
293                     {
294                         xStart = max(pbox->x1, ppt->x);
295                         xEnd = min(pbox->x2, ppt->x + *pwidth);
296                         cfbSetScanline(ppt->y, ppt->x, xStart, xEnd, psrc, alu,
297                             (int *)pdstBase, widthDst, pGC->planemask);
298                     }
299
300                 }
301             }
302         psrc += PixmapWidthInPadUnits(*pwidth, pDrawable->depth);
303         ppt++;
304         pwidth++;
305         }
306     }
307 }
308