gx_rotate.c revision 04007eba
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 "xf86.h"
31#include "shadow.h"
32#include "geode.h"
33
34static void *
35GXWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
36               CARD32 *size, void *closure)
37{
38    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
39    GeodeRec *pGeode = GEODEPTR(pScrni);
40
41    *size = pGeode->displayPitch;
42
43    return (pGeode->FBBase + pGeode->displayOffset) +
44        row * pGeode->displayPitch + offset;
45}
46
47static void
48GXUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
49{
50    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
51    GeodeRec *pGeode = GEODEPTR(pScrni);
52    int rotate = pGeode->rotation;
53
54    switch (rotate) {
55    case RR_Rotate_90:
56
57        if (pScrni->bitsPerPixel == 8)
58            shadowUpdateRotate8_90(pScreen, pBuf);
59        else if (pScrni->bitsPerPixel == 16)
60            shadowUpdateRotate16_90(pScreen, pBuf);
61        else
62            shadowUpdateRotate32_90(pScreen, pBuf);
63
64        break;
65
66    case RR_Rotate_180:
67
68        if (pScrni->bitsPerPixel == 8)
69            shadowUpdateRotate8_180(pScreen, pBuf);
70        else if (pScrni->bitsPerPixel == 16)
71            shadowUpdateRotate16_180(pScreen, pBuf);
72        else
73            shadowUpdateRotate32_180(pScreen, pBuf);
74
75        break;
76
77    case RR_Rotate_270:
78        if (pScrni->bitsPerPixel == 8)
79            shadowUpdateRotate8_270(pScreen, pBuf);
80        else if (pScrni->bitsPerPixel == 16)
81            shadowUpdateRotate16_270(pScreen, pBuf);
82        else
83            shadowUpdateRotate32_270(pScreen, pBuf);
84
85        break;
86    }
87}
88
89Bool
90GXRotate(ScrnInfoPtr pScrni, DisplayModePtr mode)
91{
92    GeodeRec *pGeode = GEODEPTR(pScrni);
93    Rotation curr = pGeode->rotation;
94    unsigned int curdw = pScrni->displayWidth;
95    PixmapPtr pPixmap;
96    BOOL ret;
97
98    pPixmap = pScrni->pScreen->GetScreenPixmap(pScrni->pScreen);
99    pGeode->rotation = GXGetRotation(pScrni->pScreen);
100
101    /* Leave if we have nothing to do */
102
103    if (pGeode->rotation == curr && pGeode->curMode == mode) {
104        return TRUE;
105    }
106
107    shadowRemove(pScrni->pScreen, NULL);
108
109    switch (pGeode->rotation) {
110    case RR_Rotate_0:
111        ErrorF("Rotate to 0 degrees\n");
112        pScrni->displayWidth = pGeode->displayWidth;
113        pGeode->Pitch = pGeode->displayPitch;
114        break;
115
116    case RR_Rotate_90:
117        ErrorF("Rotate to 90 degrees\n");
118        pScrni->displayWidth = pScrni->pScreen->width;
119        break;
120
121    case RR_Rotate_180:
122        ErrorF("Rotate to 180 degrees\n");
123        pScrni->displayWidth = pGeode->displayWidth;
124        break;
125
126    case RR_Rotate_270:
127        ErrorF("Rotate to 270 degrees\n");
128        pScrni->displayWidth = pScrni->pScreen->width;
129        break;
130    }
131
132    if (pGeode->rotation != RR_Rotate_0) {
133
134        ret =
135            shadowAdd(pScrni->pScreen, pPixmap, GXUpdate, GXWindowLinear,
136                      pGeode->rotation, NULL);
137
138        if (!ret) {
139            ErrorF("shadowAdd failed\n");
140            goto error;
141        }
142    }
143
144    if (pGeode->rotation == RR_Rotate_0)
145        pScrni->fbOffset = pGeode->displayOffset;
146    else
147        pScrni->fbOffset = pGeode->shadowOffset;
148
149    pScrni->pScreen->ModifyPixmapHeader(pPixmap,
150                                        pScrni->pScreen->width,
151                                        pScrni->pScreen->height,
152                                        pScrni->pScreen->rootDepth,
153                                        pScrni->bitsPerPixel,
154                                        PixmapBytePad(pScrni->displayWidth,
155                                                      pScrni->
156                                                      pScreen->rootDepth),
157                                        (pointer) (pGeode->FBBase +
158                                                   pScrni->fbOffset));
159
160    /* Don't use XAA pixmap cache or offscreen pixmaps when rotated */
161#if XF86XAA
162    if (pGeode->AccelInfoRec) {
163        if (pGeode->rotation == RR_Rotate_0) {
164            pGeode->AccelInfoRec->Flags =
165                LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
166            pGeode->AccelInfoRec->UsingPixmapCache = TRUE;
167            pGeode->AccelInfoRec->maxOffPixWidth = 0;
168            pGeode->AccelInfoRec->maxOffPixHeight = 0;
169        }
170        else {
171            pGeode->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
172            pGeode->AccelInfoRec->UsingPixmapCache = FALSE;
173            pGeode->AccelInfoRec->maxOffPixWidth = 1;
174            pGeode->AccelInfoRec->maxOffPixHeight = 1;
175        }
176    }
177#endif
178
179    return TRUE;
180
181 error:
182    /* Restore the old rotation */
183    pScrni->displayWidth = curdw;
184
185    if (curr & (RR_Rotate_0 | RR_Rotate_180)) {
186        pScrni->pScreen->width = pScrni->virtualX;
187        pScrni->pScreen->height = pScrni->virtualY;
188    }
189    else {
190        pScrni->pScreen->width = pScrni->virtualY;
191        pScrni->pScreen->height = pScrni->virtualX;
192    }
193
194    pGeode->rotation = curr;
195    return FALSE;
196}
197