1f29dbc25Smrg/* Copyrightg (c) 2006 Advanced Micro Devices, Inc.
2f29dbc25Smrg *
3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to
5f29dbc25Smrg * deal in the Software without restriction, including without limitation the
6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is
8f29dbc25Smrg * furnished to do so, subject to the following conditions:
9f29dbc25Smrg *
10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
11f29dbc25Smrg * all copies or substantial portions of the Software.
12f29dbc25Smrg *
13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19f29dbc25Smrg * IN THE SOFTWARE.
20f29dbc25Smrg *
21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
23f29dbc25Smrg * software without specific prior written permission.
24f29dbc25Smrg */
25f29dbc25Smrg
26f29dbc25Smrg#ifdef HAVE_CONFIG_H
27f29dbc25Smrg#include "config.h"
28f29dbc25Smrg#endif
29f29dbc25Smrg
3000be8644Schristos#include "xorg-server.h"
3100be8644Schristos
32f29dbc25Smrg#include "xf86.h"
33f29dbc25Smrg#include "shadow.h"
34f29dbc25Smrg#include "geode.h"
35f29dbc25Smrg
36f29dbc25Smrgstatic void *
37f29dbc25SmrgGXWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
3804007ebaSmrg               CARD32 *size, void *closure)
39f29dbc25Smrg{
4004007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
41f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
42f29dbc25Smrg
43f29dbc25Smrg    *size = pGeode->displayPitch;
44f29dbc25Smrg
45f29dbc25Smrg    return (pGeode->FBBase + pGeode->displayOffset) +
4604007ebaSmrg        row * pGeode->displayPitch + offset;
47f29dbc25Smrg}
48f29dbc25Smrg
49f29dbc25Smrgstatic void
50f29dbc25SmrgGXUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
51f29dbc25Smrg{
5204007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
53f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
54f29dbc25Smrg    int rotate = pGeode->rotation;
55f29dbc25Smrg
56f29dbc25Smrg    switch (rotate) {
57f29dbc25Smrg    case RR_Rotate_90:
58f29dbc25Smrg
5904007ebaSmrg        if (pScrni->bitsPerPixel == 8)
6004007ebaSmrg            shadowUpdateRotate8_90(pScreen, pBuf);
6104007ebaSmrg        else if (pScrni->bitsPerPixel == 16)
6204007ebaSmrg            shadowUpdateRotate16_90(pScreen, pBuf);
6304007ebaSmrg        else
6404007ebaSmrg            shadowUpdateRotate32_90(pScreen, pBuf);
65f29dbc25Smrg
6604007ebaSmrg        break;
67f29dbc25Smrg
68f29dbc25Smrg    case RR_Rotate_180:
69f29dbc25Smrg
7004007ebaSmrg        if (pScrni->bitsPerPixel == 8)
7104007ebaSmrg            shadowUpdateRotate8_180(pScreen, pBuf);
7204007ebaSmrg        else if (pScrni->bitsPerPixel == 16)
7304007ebaSmrg            shadowUpdateRotate16_180(pScreen, pBuf);
7404007ebaSmrg        else
7504007ebaSmrg            shadowUpdateRotate32_180(pScreen, pBuf);
76f29dbc25Smrg
7704007ebaSmrg        break;
78f29dbc25Smrg
79f29dbc25Smrg    case RR_Rotate_270:
8004007ebaSmrg        if (pScrni->bitsPerPixel == 8)
8104007ebaSmrg            shadowUpdateRotate8_270(pScreen, pBuf);
8204007ebaSmrg        else if (pScrni->bitsPerPixel == 16)
8304007ebaSmrg            shadowUpdateRotate16_270(pScreen, pBuf);
8404007ebaSmrg        else
8504007ebaSmrg            shadowUpdateRotate32_270(pScreen, pBuf);
8604007ebaSmrg
8704007ebaSmrg        break;
88f29dbc25Smrg    }
89f29dbc25Smrg}
90f29dbc25Smrg
91f29dbc25SmrgBool
92f29dbc25SmrgGXRotate(ScrnInfoPtr pScrni, DisplayModePtr mode)
93f29dbc25Smrg{
94f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
95f29dbc25Smrg    Rotation curr = pGeode->rotation;
96f29dbc25Smrg    unsigned int curdw = pScrni->displayWidth;
97f29dbc25Smrg    PixmapPtr pPixmap;
98f29dbc25Smrg    BOOL ret;
99f29dbc25Smrg
100f29dbc25Smrg    pPixmap = pScrni->pScreen->GetScreenPixmap(pScrni->pScreen);
101f29dbc25Smrg    pGeode->rotation = GXGetRotation(pScrni->pScreen);
102f29dbc25Smrg
103f29dbc25Smrg    /* Leave if we have nothing to do */
104f29dbc25Smrg
105f29dbc25Smrg    if (pGeode->rotation == curr && pGeode->curMode == mode) {
10604007ebaSmrg        return TRUE;
107f29dbc25Smrg    }
108f29dbc25Smrg
109f29dbc25Smrg    shadowRemove(pScrni->pScreen, NULL);
110f29dbc25Smrg
111f29dbc25Smrg    switch (pGeode->rotation) {
112f29dbc25Smrg    case RR_Rotate_0:
11304007ebaSmrg        ErrorF("Rotate to 0 degrees\n");
11404007ebaSmrg        pScrni->displayWidth = pGeode->displayWidth;
11504007ebaSmrg        pGeode->Pitch = pGeode->displayPitch;
11604007ebaSmrg        break;
117f29dbc25Smrg
118f29dbc25Smrg    case RR_Rotate_90:
11904007ebaSmrg        ErrorF("Rotate to 90 degrees\n");
12004007ebaSmrg        pScrni->displayWidth = pScrni->pScreen->width;
12104007ebaSmrg        break;
122f29dbc25Smrg
123f29dbc25Smrg    case RR_Rotate_180:
12404007ebaSmrg        ErrorF("Rotate to 180 degrees\n");
12504007ebaSmrg        pScrni->displayWidth = pGeode->displayWidth;
12604007ebaSmrg        break;
127f29dbc25Smrg
128f29dbc25Smrg    case RR_Rotate_270:
12904007ebaSmrg        ErrorF("Rotate to 270 degrees\n");
13004007ebaSmrg        pScrni->displayWidth = pScrni->pScreen->width;
13104007ebaSmrg        break;
132f29dbc25Smrg    }
133f29dbc25Smrg
134f29dbc25Smrg    if (pGeode->rotation != RR_Rotate_0) {
135f29dbc25Smrg
13604007ebaSmrg        ret =
13704007ebaSmrg            shadowAdd(pScrni->pScreen, pPixmap, GXUpdate, GXWindowLinear,
13804007ebaSmrg                      pGeode->rotation, NULL);
139f29dbc25Smrg
14004007ebaSmrg        if (!ret) {
14104007ebaSmrg            ErrorF("shadowAdd failed\n");
14204007ebaSmrg            goto error;
14304007ebaSmrg        }
144f29dbc25Smrg    }
145f29dbc25Smrg
146f29dbc25Smrg    if (pGeode->rotation == RR_Rotate_0)
14704007ebaSmrg        pScrni->fbOffset = pGeode->displayOffset;
148f29dbc25Smrg    else
14904007ebaSmrg        pScrni->fbOffset = pGeode->shadowOffset;
150f29dbc25Smrg
151f29dbc25Smrg    pScrni->pScreen->ModifyPixmapHeader(pPixmap,
15204007ebaSmrg                                        pScrni->pScreen->width,
15304007ebaSmrg                                        pScrni->pScreen->height,
15404007ebaSmrg                                        pScrni->pScreen->rootDepth,
15504007ebaSmrg                                        pScrni->bitsPerPixel,
15604007ebaSmrg                                        PixmapBytePad(pScrni->displayWidth,
15704007ebaSmrg                                                      pScrni->
15804007ebaSmrg                                                      pScreen->rootDepth),
15904007ebaSmrg                                        (pointer) (pGeode->FBBase +
16004007ebaSmrg                                                   pScrni->fbOffset));
161f29dbc25Smrg
162f29dbc25Smrg    /* Don't use XAA pixmap cache or offscreen pixmaps when rotated */
16304007ebaSmrg#if XF86XAA
164f29dbc25Smrg    if (pGeode->AccelInfoRec) {
16504007ebaSmrg        if (pGeode->rotation == RR_Rotate_0) {
16604007ebaSmrg            pGeode->AccelInfoRec->Flags =
16704007ebaSmrg                LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
16804007ebaSmrg            pGeode->AccelInfoRec->UsingPixmapCache = TRUE;
16904007ebaSmrg            pGeode->AccelInfoRec->maxOffPixWidth = 0;
17004007ebaSmrg            pGeode->AccelInfoRec->maxOffPixHeight = 0;
17104007ebaSmrg        }
17204007ebaSmrg        else {
17304007ebaSmrg            pGeode->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
17404007ebaSmrg            pGeode->AccelInfoRec->UsingPixmapCache = FALSE;
17504007ebaSmrg            pGeode->AccelInfoRec->maxOffPixWidth = 1;
17604007ebaSmrg            pGeode->AccelInfoRec->maxOffPixHeight = 1;
17704007ebaSmrg        }
178f29dbc25Smrg    }
17904007ebaSmrg#endif
180f29dbc25Smrg
181f29dbc25Smrg    return TRUE;
182f29dbc25Smrg
18304007ebaSmrg error:
184f29dbc25Smrg    /* Restore the old rotation */
185f29dbc25Smrg    pScrni->displayWidth = curdw;
186f29dbc25Smrg
187f29dbc25Smrg    if (curr & (RR_Rotate_0 | RR_Rotate_180)) {
18804007ebaSmrg        pScrni->pScreen->width = pScrni->virtualX;
18904007ebaSmrg        pScrni->pScreen->height = pScrni->virtualY;
19004007ebaSmrg    }
19104007ebaSmrg    else {
19204007ebaSmrg        pScrni->pScreen->width = pScrni->virtualY;
19304007ebaSmrg        pScrni->pScreen->height = pScrni->virtualX;
194f29dbc25Smrg    }
195f29dbc25Smrg
196f29dbc25Smrg    pGeode->rotation = curr;
197f29dbc25Smrg    return FALSE;
198f29dbc25Smrg}
199