shrotate.c (9346B)
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 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 }