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, 53 shadowBufPtr pBuf) 54{ 55 RegionPtr damage = shadowDamage (pBuf); 56 PixmapPtr pShadow = pBuf->pPixmap; 57 int nbox = RegionNumRects (damage); 58 BoxPtr pbox = RegionRects (damage); 59 FbBits *shaBits; 60 FbStride shaStride; 61 int shaBpp; 62 int shaXoff, shaYoff; 63 int box_x1, box_x2, box_y1, box_y2; 64 int sha_x1 = 0, sha_y1 = 0; 65 int scr_x1 = 0, scr_x2 = 0, scr_y1 = 0, scr_y2 = 0, scr_w, scr_h; 66 int scr_x, scr_y; 67 int w; 68 int pixelsPerBits; 69 int pixelsMask; 70 FbStride shaStepOverY = 0, shaStepDownY = 0; 71 FbStride shaStepOverX = 0, shaStepDownX = 0; 72 FbBits *shaLine, *sha; 73 int shaHeight = pShadow->drawable.height; 74 int shaWidth = pShadow->drawable.width; 75 FbBits shaMask; 76 int shaFirstShift, shaShift; 77 int o_x_dir; 78 int o_y_dir; 79 int x_dir; 80 int y_dir; 81 82 fbGetDrawable (&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff, 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 { 153 box_x1 = pbox->x1; 154 box_y1 = pbox->y1; 155 box_x2 = pbox->x2; 156 box_y2 = pbox->y2; 157 pbox++; 158 159 /* 160 * Compute screen and shadow locations for this box 161 */ 162 switch (x_dir) { 163 case LEFT_TO_RIGHT: 164 scr_x1 = box_x1 & pixelsMask; 165 scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask; 166 167 sha_x1 = scr_x1; 168 break; 169 case TOP_TO_BOTTOM: 170 scr_x1 = box_y1 & pixelsMask; 171 scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask; 172 173 sha_y1 = scr_x1; 174 break; 175 case RIGHT_TO_LEFT: 176 scr_x1 = (shaWidth - box_x2) & pixelsMask; 177 scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask; 178 179 sha_x1 = (shaWidth - scr_x1 - 1); 180 break; 181 case BOTTOM_TO_TOP: 182 scr_x1 = (shaHeight - box_y2) & pixelsMask; 183 scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask; 184 185 sha_y1 = (shaHeight - scr_x1 - 1); 186 break; 187 } 188 switch (y_dir) { 189 case TOP_TO_BOTTOM: 190 scr_y1 = box_y1; 191 scr_y2 = box_y2; 192 193 sha_y1 = scr_y1; 194 break; 195 case RIGHT_TO_LEFT: 196 scr_y1 = (shaWidth - box_x2); 197 scr_y2 = (shaWidth - box_x1); 198 199 sha_x1 = box_x2 - 1; 200 break; 201 case BOTTOM_TO_TOP: 202 scr_y1 = shaHeight - box_y2; 203 scr_y2 = shaHeight - box_y1; 204 205 sha_y1 = box_y2 - 1; 206 break; 207 case LEFT_TO_RIGHT: 208 scr_y1 = box_x1; 209 scr_y2 = box_x2; 210 211 sha_x1 = box_x1; 212 break; 213 } 214 scr_w = ((scr_x2 - scr_x1) * shaBpp) >> FB_SHIFT; 215 scr_h = scr_y2 - scr_y1; 216 scr_y = scr_y1; 217 218 /* shift amount for first pixel on screen */ 219 shaFirstShift = FB_UNIT - ((sha_x1 * shaBpp) & FB_MASK) - shaBpp; 220 221 /* pointer to shadow data first placed on screen */ 222 shaLine = (shaBits + 223 sha_y1 * shaStride + 224 ((sha_x1 * shaBpp) >> FB_SHIFT)); 225 226 /* 227 * Copy the bits, always write across the physical frame buffer 228 * to take advantage of write combining. 229 */ 230 while (scr_h--) 231 { 232 int p; 233 FbBits bits; 234 FbBits *win; 235 int i; 236 CARD32 winSize; 237 238 sha = shaLine; 239 shaShift = shaFirstShift; 240 w = scr_w; 241 scr_x = scr_x1 * shaBpp >> FB_SHIFT; 242 243 while (w) 244 { 245 /* 246 * Map some of this line 247 */ 248 win = (FbBits *) (*pBuf->window) (pScreen, 249 scr_y, 250 scr_x << 2, 251 SHADOW_WINDOW_WRITE, 252 &winSize, 253 pBuf->closure); 254 i = (winSize >> 2); 255 if (i > w) 256 i = w; 257 w -= i; 258 scr_x += i; 259 /* 260 * Copy the portion of the line mapped 261 */ 262 while (i--) 263 { 264 bits = 0; 265 p = pixelsPerBits; 266 /* 267 * Build one word of output from multiple inputs 268 * 269 * Note that for 90/270 rotations, this will walk 270 * down the shadow hitting each scanline once. 271 * This is probably not very efficient. 272 */ 273 while (p--) 274 { 275 bits = FbScrLeft(bits, shaBpp); 276 bits |= FbScrRight (*sha, shaShift) & shaMask; 277 278 shaShift -= shaStepOverX; 279 if (shaShift >= FB_UNIT) 280 { 281 shaShift -= FB_UNIT; 282 sha--; 283 } 284 else if (shaShift < 0) 285 { 286 shaShift += FB_UNIT; 287 sha++; 288 } 289 sha += shaStepOverY; 290 } 291 *win++ = bits; 292 } 293 } 294 scr_y++; 295 shaFirstShift -= shaStepDownX; 296 if (shaFirstShift >= FB_UNIT) 297 { 298 shaFirstShift -= FB_UNIT; 299 shaLine--; 300 } 301 else if (shaFirstShift < 0) 302 { 303 shaFirstShift += FB_UNIT; 304 shaLine++; 305 } 306 shaLine += shaStepDownY; 307 } 308 } 309} 310 311shadowUpdateProc shadowUpdateRotatePackedWeak(void) { 312 return shadowUpdateRotatePacked; 313} 314