105b261ecSmrg/* 205b261ecSmrg * 305b261ecSmrg * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. 405b261ecSmrg * 505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 705b261ecSmrg * the above copyright notice appear in all copies and that both that 805b261ecSmrg * copyright notice and this permission notice appear in supporting 905b261ecSmrg * documentation, and that the name of Keith Packard not be used in 1005b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1105b261ecSmrg * specific, written prior permission. Keith Packard makes no 1205b261ecSmrg * representations about the suitability of this software for any purpose. It 1305b261ecSmrg * is provided "as is" without express or implied warranty. 1405b261ecSmrg * 1505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2205b261ecSmrg */ 2305b261ecSmrg 2405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2505b261ecSmrg#include <dix-config.h> 2605b261ecSmrg#endif 2705b261ecSmrg 2805b261ecSmrg#include <X11/X.h> 2905b261ecSmrg#include "scrnintstr.h" 3005b261ecSmrg#include "windowstr.h" 3105b261ecSmrg#include <X11/fonts/font.h> 3205b261ecSmrg#include "dixfontstr.h" 3305b261ecSmrg#include <X11/fonts/fontstruct.h> 3405b261ecSmrg#include "mi.h" 3505b261ecSmrg#include "regionstr.h" 3605b261ecSmrg#include "globals.h" 3705b261ecSmrg#include "gcstruct.h" 3805b261ecSmrg#include "shadow.h" 3905b261ecSmrg#include "fb.h" 4005b261ecSmrg 4105b261ecSmrg/* 4205b261ecSmrg * These indicate which way the source (shadow) is scanned when 4305b261ecSmrg * walking the screen in a particular direction 4405b261ecSmrg */ 4505b261ecSmrg 4605b261ecSmrg#define LEFT_TO_RIGHT 1 4705b261ecSmrg#define RIGHT_TO_LEFT -1 4805b261ecSmrg#define TOP_TO_BOTTOM 2 4905b261ecSmrg#define BOTTOM_TO_TOP -2 5005b261ecSmrg 5105b261ecSmrgvoid 5235c4bbdfSmrgshadowUpdateRotatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 5305b261ecSmrg{ 541b5d61b8Smrg RegionPtr damage = DamageRegion(pBuf->pDamage); 5535c4bbdfSmrg PixmapPtr pShadow = pBuf->pPixmap; 5635c4bbdfSmrg int nbox = RegionNumRects(damage); 5735c4bbdfSmrg BoxPtr pbox = RegionRects(damage); 5835c4bbdfSmrg FbBits *shaBits; 5935c4bbdfSmrg FbStride shaStride; 6035c4bbdfSmrg int shaBpp; 6135c4bbdfSmrg _X_UNUSED int shaXoff, shaYoff; 6235c4bbdfSmrg int box_x1, box_x2, box_y1, box_y2; 6335c4bbdfSmrg int sha_x1 = 0, sha_y1 = 0; 6435c4bbdfSmrg int scr_x1 = 0, scr_x2 = 0, scr_y1 = 0, scr_y2 = 0, scr_w, scr_h; 6535c4bbdfSmrg int scr_x, scr_y; 6635c4bbdfSmrg int w; 6735c4bbdfSmrg int pixelsPerBits; 6835c4bbdfSmrg int pixelsMask; 6935c4bbdfSmrg FbStride shaStepOverY = 0, shaStepDownY = 0; 7035c4bbdfSmrg FbStride shaStepOverX = 0, shaStepDownX = 0; 7135c4bbdfSmrg FbBits *shaLine, *sha; 7235c4bbdfSmrg int shaHeight = pShadow->drawable.height; 7335c4bbdfSmrg int shaWidth = pShadow->drawable.width; 7435c4bbdfSmrg FbBits shaMask; 7535c4bbdfSmrg int shaFirstShift, shaShift; 7635c4bbdfSmrg int o_x_dir; 7735c4bbdfSmrg int o_y_dir; 7835c4bbdfSmrg int x_dir; 7935c4bbdfSmrg int y_dir; 8005b261ecSmrg 8135c4bbdfSmrg fbGetDrawable(&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff, 8235c4bbdfSmrg shaYoff); 8335c4bbdfSmrg pixelsPerBits = (sizeof(FbBits) * 8) / shaBpp; 8405b261ecSmrg pixelsMask = ~(pixelsPerBits - 1); 8535c4bbdfSmrg shaMask = FbBitsMask(FB_UNIT - shaBpp, shaBpp); 8605b261ecSmrg /* 8705b261ecSmrg * Compute rotation related constants to walk the shadow 8805b261ecSmrg */ 8905b261ecSmrg o_x_dir = LEFT_TO_RIGHT; 9005b261ecSmrg o_y_dir = TOP_TO_BOTTOM; 9105b261ecSmrg if (pBuf->randr & SHADOW_REFLECT_X) 9235c4bbdfSmrg o_x_dir = -o_x_dir; 9305b261ecSmrg if (pBuf->randr & SHADOW_REFLECT_Y) 9435c4bbdfSmrg o_y_dir = -o_y_dir; 9505b261ecSmrg switch (pBuf->randr & (SHADOW_ROTATE_ALL)) { 9635c4bbdfSmrg case SHADOW_ROTATE_0: /* upper left shadow -> upper left screen */ 9705b261ecSmrg default: 9835c4bbdfSmrg x_dir = o_x_dir; 9935c4bbdfSmrg y_dir = o_y_dir; 10035c4bbdfSmrg break; 10135c4bbdfSmrg case SHADOW_ROTATE_90: /* upper right shadow -> upper left screen */ 10235c4bbdfSmrg x_dir = o_y_dir; 10335c4bbdfSmrg y_dir = -o_x_dir; 10435c4bbdfSmrg break; 10535c4bbdfSmrg case SHADOW_ROTATE_180: /* lower right shadow -> upper left screen */ 10635c4bbdfSmrg x_dir = -o_x_dir; 10735c4bbdfSmrg y_dir = -o_y_dir; 10835c4bbdfSmrg break; 10935c4bbdfSmrg case SHADOW_ROTATE_270: /* lower left shadow -> upper left screen */ 11035c4bbdfSmrg x_dir = -o_y_dir; 11135c4bbdfSmrg y_dir = o_x_dir; 11235c4bbdfSmrg break; 11305b261ecSmrg } 11405b261ecSmrg switch (x_dir) { 11505b261ecSmrg case LEFT_TO_RIGHT: 11635c4bbdfSmrg shaStepOverX = shaBpp; 11735c4bbdfSmrg shaStepOverY = 0; 11835c4bbdfSmrg break; 11905b261ecSmrg case TOP_TO_BOTTOM: 12035c4bbdfSmrg shaStepOverX = 0; 12135c4bbdfSmrg shaStepOverY = shaStride; 12235c4bbdfSmrg break; 12305b261ecSmrg case RIGHT_TO_LEFT: 12435c4bbdfSmrg shaStepOverX = -shaBpp; 12535c4bbdfSmrg shaStepOverY = 0; 12635c4bbdfSmrg break; 12705b261ecSmrg case BOTTOM_TO_TOP: 12835c4bbdfSmrg shaStepOverX = 0; 12935c4bbdfSmrg shaStepOverY = -shaStride; 13035c4bbdfSmrg break; 13105b261ecSmrg } 13205b261ecSmrg switch (y_dir) { 13305b261ecSmrg case TOP_TO_BOTTOM: 13435c4bbdfSmrg shaStepDownX = 0; 13535c4bbdfSmrg shaStepDownY = shaStride; 13635c4bbdfSmrg break; 13705b261ecSmrg case RIGHT_TO_LEFT: 13835c4bbdfSmrg shaStepDownX = -shaBpp; 13935c4bbdfSmrg shaStepDownY = 0; 14035c4bbdfSmrg break; 14105b261ecSmrg case BOTTOM_TO_TOP: 14235c4bbdfSmrg shaStepDownX = 0; 14335c4bbdfSmrg shaStepDownY = -shaStride; 14435c4bbdfSmrg break; 14505b261ecSmrg case LEFT_TO_RIGHT: 14635c4bbdfSmrg shaStepDownX = shaBpp; 14735c4bbdfSmrg shaStepDownY = 0; 14835c4bbdfSmrg break; 14905b261ecSmrg } 15035c4bbdfSmrg 15135c4bbdfSmrg while (nbox--) { 15205b261ecSmrg box_x1 = pbox->x1; 15305b261ecSmrg box_y1 = pbox->y1; 15405b261ecSmrg box_x2 = pbox->x2; 15505b261ecSmrg box_y2 = pbox->y2; 15605b261ecSmrg pbox++; 15705b261ecSmrg 15835c4bbdfSmrg /* 15935c4bbdfSmrg * Compute screen and shadow locations for this box 16035c4bbdfSmrg */ 16135c4bbdfSmrg switch (x_dir) { 16235c4bbdfSmrg case LEFT_TO_RIGHT: 16335c4bbdfSmrg scr_x1 = box_x1 & pixelsMask; 16435c4bbdfSmrg scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask; 16535c4bbdfSmrg 16635c4bbdfSmrg sha_x1 = scr_x1; 16735c4bbdfSmrg break; 16835c4bbdfSmrg case TOP_TO_BOTTOM: 16935c4bbdfSmrg scr_x1 = box_y1 & pixelsMask; 17035c4bbdfSmrg scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask; 17135c4bbdfSmrg 17235c4bbdfSmrg sha_y1 = scr_x1; 17335c4bbdfSmrg break; 17435c4bbdfSmrg case RIGHT_TO_LEFT: 17535c4bbdfSmrg scr_x1 = (shaWidth - box_x2) & pixelsMask; 17635c4bbdfSmrg scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask; 17735c4bbdfSmrg 17835c4bbdfSmrg sha_x1 = (shaWidth - scr_x1 - 1); 17935c4bbdfSmrg break; 18035c4bbdfSmrg case BOTTOM_TO_TOP: 18135c4bbdfSmrg scr_x1 = (shaHeight - box_y2) & pixelsMask; 18235c4bbdfSmrg scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask; 18305b261ecSmrg 18435c4bbdfSmrg sha_y1 = (shaHeight - scr_x1 - 1); 18535c4bbdfSmrg break; 18635c4bbdfSmrg } 18735c4bbdfSmrg switch (y_dir) { 18835c4bbdfSmrg case TOP_TO_BOTTOM: 18935c4bbdfSmrg scr_y1 = box_y1; 19035c4bbdfSmrg scr_y2 = box_y2; 19105b261ecSmrg 19235c4bbdfSmrg sha_y1 = scr_y1; 19335c4bbdfSmrg break; 19435c4bbdfSmrg case RIGHT_TO_LEFT: 19535c4bbdfSmrg scr_y1 = (shaWidth - box_x2); 19635c4bbdfSmrg scr_y2 = (shaWidth - box_x1); 19705b261ecSmrg 19835c4bbdfSmrg sha_x1 = box_x2 - 1; 19935c4bbdfSmrg break; 20035c4bbdfSmrg case BOTTOM_TO_TOP: 20135c4bbdfSmrg scr_y1 = shaHeight - box_y2; 20235c4bbdfSmrg scr_y2 = shaHeight - box_y1; 20305b261ecSmrg 20435c4bbdfSmrg sha_y1 = box_y2 - 1; 20535c4bbdfSmrg break; 20635c4bbdfSmrg case LEFT_TO_RIGHT: 20735c4bbdfSmrg scr_y1 = box_x1; 20835c4bbdfSmrg scr_y2 = box_x2; 20905b261ecSmrg 21035c4bbdfSmrg sha_x1 = box_x1; 21135c4bbdfSmrg break; 21235c4bbdfSmrg } 21335c4bbdfSmrg scr_w = ((scr_x2 - scr_x1) * shaBpp) >> FB_SHIFT; 21435c4bbdfSmrg scr_h = scr_y2 - scr_y1; 21535c4bbdfSmrg scr_y = scr_y1; 21605b261ecSmrg 21735c4bbdfSmrg /* shift amount for first pixel on screen */ 21835c4bbdfSmrg shaFirstShift = FB_UNIT - ((sha_x1 * shaBpp) & FB_MASK) - shaBpp; 21905b261ecSmrg 22035c4bbdfSmrg /* pointer to shadow data first placed on screen */ 22135c4bbdfSmrg shaLine = (shaBits + 22235c4bbdfSmrg sha_y1 * shaStride + ((sha_x1 * shaBpp) >> FB_SHIFT)); 22305b261ecSmrg 22435c4bbdfSmrg /* 22535c4bbdfSmrg * Copy the bits, always write across the physical frame buffer 22635c4bbdfSmrg * to take advantage of write combining. 22735c4bbdfSmrg */ 22835c4bbdfSmrg while (scr_h--) { 22935c4bbdfSmrg int p; 23035c4bbdfSmrg FbBits bits; 23135c4bbdfSmrg FbBits *win; 23235c4bbdfSmrg int i; 23335c4bbdfSmrg CARD32 winSize; 23405b261ecSmrg 23535c4bbdfSmrg sha = shaLine; 23635c4bbdfSmrg shaShift = shaFirstShift; 23735c4bbdfSmrg w = scr_w; 23835c4bbdfSmrg scr_x = scr_x1 * shaBpp >> FB_SHIFT; 23935c4bbdfSmrg 24035c4bbdfSmrg while (w) { 24135c4bbdfSmrg /* 24235c4bbdfSmrg * Map some of this line 24335c4bbdfSmrg */ 24435c4bbdfSmrg win = (FbBits *) (*pBuf->window) (pScreen, 24535c4bbdfSmrg scr_y, 24635c4bbdfSmrg scr_x << 2, 24735c4bbdfSmrg SHADOW_WINDOW_WRITE, 24835c4bbdfSmrg &winSize, pBuf->closure); 24935c4bbdfSmrg i = (winSize >> 2); 25035c4bbdfSmrg if (i > w) 25135c4bbdfSmrg i = w; 25235c4bbdfSmrg w -= i; 25335c4bbdfSmrg scr_x += i; 25435c4bbdfSmrg /* 25535c4bbdfSmrg * Copy the portion of the line mapped 25635c4bbdfSmrg */ 25735c4bbdfSmrg while (i--) { 25835c4bbdfSmrg bits = 0; 25935c4bbdfSmrg p = pixelsPerBits; 26035c4bbdfSmrg /* 26135c4bbdfSmrg * Build one word of output from multiple inputs 26235c4bbdfSmrg * 26335c4bbdfSmrg * Note that for 90/270 rotations, this will walk 26435c4bbdfSmrg * down the shadow hitting each scanline once. 26535c4bbdfSmrg * This is probably not very efficient. 26635c4bbdfSmrg */ 26735c4bbdfSmrg while (p--) { 26835c4bbdfSmrg bits = FbScrLeft(bits, shaBpp); 26935c4bbdfSmrg bits |= FbScrRight(*sha, shaShift) & shaMask; 27035c4bbdfSmrg 27135c4bbdfSmrg shaShift -= shaStepOverX; 27235c4bbdfSmrg if (shaShift >= FB_UNIT) { 27335c4bbdfSmrg shaShift -= FB_UNIT; 27435c4bbdfSmrg sha--; 27535c4bbdfSmrg } 27635c4bbdfSmrg else if (shaShift < 0) { 27735c4bbdfSmrg shaShift += FB_UNIT; 27835c4bbdfSmrg sha++; 27935c4bbdfSmrg } 28035c4bbdfSmrg sha += shaStepOverY; 28135c4bbdfSmrg } 28235c4bbdfSmrg *win++ = bits; 28335c4bbdfSmrg } 28435c4bbdfSmrg } 28535c4bbdfSmrg scr_y++; 28635c4bbdfSmrg shaFirstShift -= shaStepDownX; 28735c4bbdfSmrg if (shaFirstShift >= FB_UNIT) { 28835c4bbdfSmrg shaFirstShift -= FB_UNIT; 28935c4bbdfSmrg shaLine--; 29035c4bbdfSmrg } 29135c4bbdfSmrg else if (shaFirstShift < 0) { 29235c4bbdfSmrg shaFirstShift += FB_UNIT; 29335c4bbdfSmrg shaLine++; 29435c4bbdfSmrg } 29535c4bbdfSmrg shaLine += shaStepDownY; 29635c4bbdfSmrg } 29705b261ecSmrg } 29805b261ecSmrg} 299