gx_rotate.c revision 00be8644
1/* Copyrightg (c) 2006 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29 30#include "xorg-server.h" 31 32#include "xf86.h" 33#include "shadow.h" 34#include "geode.h" 35 36static void * 37GXWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 38 CARD32 *size, void *closure) 39{ 40 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 41 GeodeRec *pGeode = GEODEPTR(pScrni); 42 43 *size = pGeode->displayPitch; 44 45 return (pGeode->FBBase + pGeode->displayOffset) + 46 row * pGeode->displayPitch + offset; 47} 48 49static void 50GXUpdate(ScreenPtr pScreen, shadowBufPtr pBuf) 51{ 52 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 53 GeodeRec *pGeode = GEODEPTR(pScrni); 54 int rotate = pGeode->rotation; 55 56 switch (rotate) { 57 case RR_Rotate_90: 58 59 if (pScrni->bitsPerPixel == 8) 60 shadowUpdateRotate8_90(pScreen, pBuf); 61 else if (pScrni->bitsPerPixel == 16) 62 shadowUpdateRotate16_90(pScreen, pBuf); 63 else 64 shadowUpdateRotate32_90(pScreen, pBuf); 65 66 break; 67 68 case RR_Rotate_180: 69 70 if (pScrni->bitsPerPixel == 8) 71 shadowUpdateRotate8_180(pScreen, pBuf); 72 else if (pScrni->bitsPerPixel == 16) 73 shadowUpdateRotate16_180(pScreen, pBuf); 74 else 75 shadowUpdateRotate32_180(pScreen, pBuf); 76 77 break; 78 79 case RR_Rotate_270: 80 if (pScrni->bitsPerPixel == 8) 81 shadowUpdateRotate8_270(pScreen, pBuf); 82 else if (pScrni->bitsPerPixel == 16) 83 shadowUpdateRotate16_270(pScreen, pBuf); 84 else 85 shadowUpdateRotate32_270(pScreen, pBuf); 86 87 break; 88 } 89} 90 91Bool 92GXRotate(ScrnInfoPtr pScrni, DisplayModePtr mode) 93{ 94 GeodeRec *pGeode = GEODEPTR(pScrni); 95 Rotation curr = pGeode->rotation; 96 unsigned int curdw = pScrni->displayWidth; 97 PixmapPtr pPixmap; 98 BOOL ret; 99 100 pPixmap = pScrni->pScreen->GetScreenPixmap(pScrni->pScreen); 101 pGeode->rotation = GXGetRotation(pScrni->pScreen); 102 103 /* Leave if we have nothing to do */ 104 105 if (pGeode->rotation == curr && pGeode->curMode == mode) { 106 return TRUE; 107 } 108 109 shadowRemove(pScrni->pScreen, NULL); 110 111 switch (pGeode->rotation) { 112 case RR_Rotate_0: 113 ErrorF("Rotate to 0 degrees\n"); 114 pScrni->displayWidth = pGeode->displayWidth; 115 pGeode->Pitch = pGeode->displayPitch; 116 break; 117 118 case RR_Rotate_90: 119 ErrorF("Rotate to 90 degrees\n"); 120 pScrni->displayWidth = pScrni->pScreen->width; 121 break; 122 123 case RR_Rotate_180: 124 ErrorF("Rotate to 180 degrees\n"); 125 pScrni->displayWidth = pGeode->displayWidth; 126 break; 127 128 case RR_Rotate_270: 129 ErrorF("Rotate to 270 degrees\n"); 130 pScrni->displayWidth = pScrni->pScreen->width; 131 break; 132 } 133 134 if (pGeode->rotation != RR_Rotate_0) { 135 136 ret = 137 shadowAdd(pScrni->pScreen, pPixmap, GXUpdate, GXWindowLinear, 138 pGeode->rotation, NULL); 139 140 if (!ret) { 141 ErrorF("shadowAdd failed\n"); 142 goto error; 143 } 144 } 145 146 if (pGeode->rotation == RR_Rotate_0) 147 pScrni->fbOffset = pGeode->displayOffset; 148 else 149 pScrni->fbOffset = pGeode->shadowOffset; 150 151 pScrni->pScreen->ModifyPixmapHeader(pPixmap, 152 pScrni->pScreen->width, 153 pScrni->pScreen->height, 154 pScrni->pScreen->rootDepth, 155 pScrni->bitsPerPixel, 156 PixmapBytePad(pScrni->displayWidth, 157 pScrni-> 158 pScreen->rootDepth), 159 (pointer) (pGeode->FBBase + 160 pScrni->fbOffset)); 161 162 /* Don't use XAA pixmap cache or offscreen pixmaps when rotated */ 163#if XF86XAA 164 if (pGeode->AccelInfoRec) { 165 if (pGeode->rotation == RR_Rotate_0) { 166 pGeode->AccelInfoRec->Flags = 167 LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; 168 pGeode->AccelInfoRec->UsingPixmapCache = TRUE; 169 pGeode->AccelInfoRec->maxOffPixWidth = 0; 170 pGeode->AccelInfoRec->maxOffPixHeight = 0; 171 } 172 else { 173 pGeode->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER; 174 pGeode->AccelInfoRec->UsingPixmapCache = FALSE; 175 pGeode->AccelInfoRec->maxOffPixWidth = 1; 176 pGeode->AccelInfoRec->maxOffPixHeight = 1; 177 } 178 } 179#endif 180 181 return TRUE; 182 183 error: 184 /* Restore the old rotation */ 185 pScrni->displayWidth = curdw; 186 187 if (curr & (RR_Rotate_0 | RR_Rotate_180)) { 188 pScrni->pScreen->width = pScrni->virtualX; 189 pScrni->pScreen->height = pScrni->virtualY; 190 } 191 else { 192 pScrni->pScreen->width = pScrni->virtualY; 193 pScrni->pScreen->height = pScrni->virtualX; 194 } 195 196 pGeode->rotation = curr; 197 return FALSE; 198} 199