xref: /OK3568_Linux_fs/external/xserver/miext/shadow/shrotate.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of Keith Packard not be used in
10  * advertising or publicity pertaining to distribution of the software without
11  * specific, written prior permission.  Keith Packard makes no
12  * representations about the suitability of this software for any purpose.  It
13  * is provided "as is" without express or implied warranty.
14  *
15  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21  * PERFORMANCE OF THIS SOFTWARE.
22  */
23 
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
26 #endif
27 
28 #include    <X11/X.h>
29 #include    "scrnintstr.h"
30 #include    "windowstr.h"
31 #include    <X11/fonts/font.h>
32 #include    "dixfontstr.h"
33 #include    <X11/fonts/fontstruct.h>
34 #include    "mi.h"
35 #include    "regionstr.h"
36 #include    "globals.h"
37 #include    "gcstruct.h"
38 #include    "shadow.h"
39 #include    "fb.h"
40 
41 /*
42  * These indicate which way the source (shadow) is scanned when
43  * walking the screen in a particular direction
44  */
45 
46 #define LEFT_TO_RIGHT	1
47 #define RIGHT_TO_LEFT	-1
48 #define TOP_TO_BOTTOM	2
49 #define BOTTOM_TO_TOP	-2
50 
51 void
shadowUpdateRotatePacked(ScreenPtr pScreen,shadowBufPtr pBuf)52 shadowUpdateRotatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
53 {
54     RegionPtr damage = DamageRegion(pBuf->pDamage);
55     PixmapPtr pShadow = pBuf->pPixmap;
56     int nbox = RegionNumRects(damage);
57     BoxPtr pbox = RegionRects(damage);
58     FbBits *shaBits;
59     FbStride shaStride;
60     int shaBpp;
61     _X_UNUSED int shaXoff, shaYoff;
62     int box_x1, box_x2, box_y1, box_y2;
63     int sha_x1 = 0, sha_y1 = 0;
64     int scr_x1 = 0, scr_x2 = 0, scr_y1 = 0, scr_y2 = 0, scr_w, scr_h;
65     int scr_x, scr_y;
66     int w;
67     int pixelsPerBits;
68     int pixelsMask;
69     FbStride shaStepOverY = 0, shaStepDownY = 0;
70     FbStride shaStepOverX = 0, shaStepDownX = 0;
71     FbBits *shaLine, *sha;
72     int shaHeight = pShadow->drawable.height;
73     int shaWidth = pShadow->drawable.width;
74     FbBits shaMask;
75     int shaFirstShift, shaShift;
76     int o_x_dir;
77     int o_y_dir;
78     int x_dir;
79     int y_dir;
80 
81     fbGetDrawable(&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff,
82                   shaYoff);
83     pixelsPerBits = (sizeof(FbBits) * 8) / shaBpp;
84     pixelsMask = ~(pixelsPerBits - 1);
85     shaMask = FbBitsMask(FB_UNIT - shaBpp, shaBpp);
86     /*
87      * Compute rotation related constants to walk the shadow
88      */
89     o_x_dir = LEFT_TO_RIGHT;
90     o_y_dir = TOP_TO_BOTTOM;
91     if (pBuf->randr & SHADOW_REFLECT_X)
92         o_x_dir = -o_x_dir;
93     if (pBuf->randr & SHADOW_REFLECT_Y)
94         o_y_dir = -o_y_dir;
95     switch (pBuf->randr & (SHADOW_ROTATE_ALL)) {
96     case SHADOW_ROTATE_0:      /* upper left shadow -> upper left screen */
97     default:
98         x_dir = o_x_dir;
99         y_dir = o_y_dir;
100         break;
101     case SHADOW_ROTATE_90:     /* upper right shadow -> upper left screen */
102         x_dir = o_y_dir;
103         y_dir = -o_x_dir;
104         break;
105     case SHADOW_ROTATE_180:    /* lower right shadow -> upper left screen */
106         x_dir = -o_x_dir;
107         y_dir = -o_y_dir;
108         break;
109     case SHADOW_ROTATE_270:    /* lower left shadow -> upper left screen */
110         x_dir = -o_y_dir;
111         y_dir = o_x_dir;
112         break;
113     }
114     switch (x_dir) {
115     case LEFT_TO_RIGHT:
116         shaStepOverX = shaBpp;
117         shaStepOverY = 0;
118         break;
119     case TOP_TO_BOTTOM:
120         shaStepOverX = 0;
121         shaStepOverY = shaStride;
122         break;
123     case RIGHT_TO_LEFT:
124         shaStepOverX = -shaBpp;
125         shaStepOverY = 0;
126         break;
127     case BOTTOM_TO_TOP:
128         shaStepOverX = 0;
129         shaStepOverY = -shaStride;
130         break;
131     }
132     switch (y_dir) {
133     case TOP_TO_BOTTOM:
134         shaStepDownX = 0;
135         shaStepDownY = shaStride;
136         break;
137     case RIGHT_TO_LEFT:
138         shaStepDownX = -shaBpp;
139         shaStepDownY = 0;
140         break;
141     case BOTTOM_TO_TOP:
142         shaStepDownX = 0;
143         shaStepDownY = -shaStride;
144         break;
145     case LEFT_TO_RIGHT:
146         shaStepDownX = shaBpp;
147         shaStepDownY = 0;
148         break;
149     }
150 
151     while (nbox--) {
152         box_x1 = pbox->x1;
153         box_y1 = pbox->y1;
154         box_x2 = pbox->x2;
155         box_y2 = pbox->y2;
156         pbox++;
157 
158         /*
159          * Compute screen and shadow locations for this box
160          */
161         switch (x_dir) {
162         case LEFT_TO_RIGHT:
163             scr_x1 = box_x1 & pixelsMask;
164             scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask;
165 
166             sha_x1 = scr_x1;
167             break;
168         case TOP_TO_BOTTOM:
169             scr_x1 = box_y1 & pixelsMask;
170             scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask;
171 
172             sha_y1 = scr_x1;
173             break;
174         case RIGHT_TO_LEFT:
175             scr_x1 = (shaWidth - box_x2) & pixelsMask;
176             scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask;
177 
178             sha_x1 = (shaWidth - scr_x1 - 1);
179             break;
180         case BOTTOM_TO_TOP:
181             scr_x1 = (shaHeight - box_y2) & pixelsMask;
182             scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask;
183 
184             sha_y1 = (shaHeight - scr_x1 - 1);
185             break;
186         }
187         switch (y_dir) {
188         case TOP_TO_BOTTOM:
189             scr_y1 = box_y1;
190             scr_y2 = box_y2;
191 
192             sha_y1 = scr_y1;
193             break;
194         case RIGHT_TO_LEFT:
195             scr_y1 = (shaWidth - box_x2);
196             scr_y2 = (shaWidth - box_x1);
197 
198             sha_x1 = box_x2 - 1;
199             break;
200         case BOTTOM_TO_TOP:
201             scr_y1 = shaHeight - box_y2;
202             scr_y2 = shaHeight - box_y1;
203 
204             sha_y1 = box_y2 - 1;
205             break;
206         case LEFT_TO_RIGHT:
207             scr_y1 = box_x1;
208             scr_y2 = box_x2;
209 
210             sha_x1 = box_x1;
211             break;
212         }
213         scr_w = ((scr_x2 - scr_x1) * shaBpp) >> FB_SHIFT;
214         scr_h = scr_y2 - scr_y1;
215         scr_y = scr_y1;
216 
217         /* shift amount for first pixel on screen */
218         shaFirstShift = FB_UNIT - ((sha_x1 * shaBpp) & FB_MASK) - shaBpp;
219 
220         /* pointer to shadow data first placed on screen */
221         shaLine = (shaBits +
222                    sha_y1 * shaStride + ((sha_x1 * shaBpp) >> FB_SHIFT));
223 
224         /*
225          * Copy the bits, always write across the physical frame buffer
226          * to take advantage of write combining.
227          */
228         while (scr_h--) {
229             int p;
230             FbBits bits;
231             FbBits *win;
232             int i;
233             CARD32 winSize;
234 
235             sha = shaLine;
236             shaShift = shaFirstShift;
237             w = scr_w;
238             scr_x = scr_x1 * shaBpp >> FB_SHIFT;
239 
240             while (w) {
241                 /*
242                  * Map some of this line
243                  */
244                 win = (FbBits *) (*pBuf->window) (pScreen,
245                                                   scr_y,
246                                                   scr_x << 2,
247                                                   SHADOW_WINDOW_WRITE,
248                                                   &winSize, pBuf->closure);
249                 i = (winSize >> 2);
250                 if (i > w)
251                     i = w;
252                 w -= i;
253                 scr_x += i;
254                 /*
255                  * Copy the portion of the line mapped
256                  */
257                 while (i--) {
258                     bits = 0;
259                     p = pixelsPerBits;
260                     /*
261                      * Build one word of output from multiple inputs
262                      *
263                      * Note that for 90/270 rotations, this will walk
264                      * down the shadow hitting each scanline once.
265                      * This is probably not very efficient.
266                      */
267                     while (p--) {
268                         bits = FbScrLeft(bits, shaBpp);
269                         bits |= FbScrRight(*sha, shaShift) & shaMask;
270 
271                         shaShift -= shaStepOverX;
272                         if (shaShift >= FB_UNIT) {
273                             shaShift -= FB_UNIT;
274                             sha--;
275                         }
276                         else if (shaShift < 0) {
277                             shaShift += FB_UNIT;
278                             sha++;
279                         }
280                         sha += shaStepOverY;
281                     }
282                     *win++ = bits;
283                 }
284             }
285             scr_y++;
286             shaFirstShift -= shaStepDownX;
287             if (shaFirstShift >= FB_UNIT) {
288                 shaFirstShift -= FB_UNIT;
289                 shaLine--;
290             }
291             else if (shaFirstShift < 0) {
292                 shaFirstShift += FB_UNIT;
293                 shaLine++;
294             }
295             shaLine += shaStepDownY;
296         }
297     }
298 }
299