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