3 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
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.
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.
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.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>
35 #include "regionstr.h"
42 * These indicate which way the source (shadow) is scanned when
43 * walking the screen in a particular direction
46 #define LEFT_TO_RIGHT 1
47 #define RIGHT_TO_LEFT -1
48 #define TOP_TO_BOTTOM 2
49 #define BOTTOM_TO_TOP -2
52 shadowUpdateRotatePacked(ScreenPtr pScreen
, shadowBufPtr pBuf
)
54 RegionPtr damage
= shadowDamage(pBuf
);
55 PixmapPtr pShadow
= pBuf
->pPixmap
;
56 int nbox
= RegionNumRects(damage
);
57 BoxPtr pbox
= RegionRects(damage
);
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
;
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
;
75 int shaFirstShift
, shaShift
;
81 fbGetDrawable(&pShadow
->drawable
, shaBits
, shaStride
, shaBpp
, shaXoff
,
83 pixelsPerBits
= (sizeof(FbBits
) * 8) / shaBpp
;
84 pixelsMask
= ~(pixelsPerBits
- 1);
85 shaMask
= FbBitsMask(FB_UNIT
- shaBpp
, shaBpp
);
87 * Compute rotation related constants to walk the shadow
89 o_x_dir
= LEFT_TO_RIGHT
;
90 o_y_dir
= TOP_TO_BOTTOM
;
91 if (pBuf
->randr
& SHADOW_REFLECT_X
)
93 if (pBuf
->randr
& SHADOW_REFLECT_Y
)
95 switch (pBuf
->randr
& (SHADOW_ROTATE_ALL
)) {
96 case SHADOW_ROTATE_0
: /* upper left shadow -> upper left screen */
101 case SHADOW_ROTATE_90
: /* upper right shadow -> upper left screen */
105 case SHADOW_ROTATE_180
: /* lower right shadow -> upper left screen */
109 case SHADOW_ROTATE_270
: /* lower left shadow -> upper left screen */
116 shaStepOverX
= shaBpp
;
121 shaStepOverY
= shaStride
;
124 shaStepOverX
= -shaBpp
;
129 shaStepOverY
= -shaStride
;
135 shaStepDownY
= shaStride
;
138 shaStepDownX
= -shaBpp
;
143 shaStepDownY
= -shaStride
;
146 shaStepDownX
= shaBpp
;
159 * Compute screen and shadow locations for this box
163 scr_x1
= box_x1
& pixelsMask
;
164 scr_x2
= (box_x2
+ pixelsPerBits
- 1) & pixelsMask
;
169 scr_x1
= box_y1
& pixelsMask
;
170 scr_x2
= (box_y2
+ pixelsPerBits
- 1) & pixelsMask
;
175 scr_x1
= (shaWidth
- box_x2
) & pixelsMask
;
176 scr_x2
= (shaWidth
- box_x1
+ pixelsPerBits
- 1) & pixelsMask
;
178 sha_x1
= (shaWidth
- scr_x1
- 1);
181 scr_x1
= (shaHeight
- box_y2
) & pixelsMask
;
182 scr_x2
= (shaHeight
- box_y1
+ pixelsPerBits
- 1) & pixelsMask
;
184 sha_y1
= (shaHeight
- scr_x1
- 1);
195 scr_y1
= (shaWidth
- box_x2
);
196 scr_y2
= (shaWidth
- box_x1
);
201 scr_y1
= shaHeight
- box_y2
;
202 scr_y2
= shaHeight
- box_y1
;
213 scr_w
= ((scr_x2
- scr_x1
) * shaBpp
) >> FB_SHIFT
;
214 scr_h
= scr_y2
- scr_y1
;
217 /* shift amount for first pixel on screen */
218 shaFirstShift
= FB_UNIT
- ((sha_x1
* shaBpp
) & FB_MASK
) - shaBpp
;
220 /* pointer to shadow data first placed on screen */
222 sha_y1
* shaStride
+ ((sha_x1
* shaBpp
) >> FB_SHIFT
));
225 * Copy the bits, always write across the physical frame buffer
226 * to take advantage of write combining.
236 shaShift
= shaFirstShift
;
238 scr_x
= scr_x1
* shaBpp
>> FB_SHIFT
;
242 * Map some of this line
244 win
= (FbBits
*) (*pBuf
->window
) (pScreen
,
248 &winSize
, pBuf
->closure
);
255 * Copy the portion of the line mapped
261 * Build one word of output from multiple inputs
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.
268 bits
= FbScrLeft(bits
, shaBpp
);
269 bits
|= FbScrRight(*sha
, shaShift
) & shaMask
;
271 shaShift
-= shaStepOverX
;
272 if (shaShift
>= FB_UNIT
) {
276 else if (shaShift
< 0) {
286 shaFirstShift
-= shaStepDownX
;
287 if (shaFirstShift
>= FB_UNIT
) {
288 shaFirstShift
-= FB_UNIT
;
291 else if (shaFirstShift
< 0) {
292 shaFirstShift
+= FB_UNIT
;
295 shaLine
+= shaStepDownY
;
301 shadowUpdateRotatePackedWeak(void)
303 return shadowUpdateRotatePacked
;