Imported Upstream version 1.15.1
[deb_xorg-server.git] / miext / shadow / shrotate.c
CommitLineData
a09e091a
JB
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
51void
52shadowUpdateRotatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
53{
54 RegionPtr damage = shadowDamage(pBuf);
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
300shadowUpdateProc
301shadowUpdateRotatePackedWeak(void)
302{
303 return shadowUpdateRotatePacked;
304}