142a55b46Smrg/*
242a55b46Smrg * Copyright 2006 Joseph Garvin
342a55b46Smrg * Copyright 2012 Connor Behan
442a55b46Smrg * All Rights Reserved.
542a55b46Smrg *
642a55b46Smrg * Permission is hereby granted, free of charge, to any person obtaining a
742a55b46Smrg * copy of this software and associated documentation files (the "Software"),
842a55b46Smrg * to deal in the Software without restriction, including without limitation
942a55b46Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1042a55b46Smrg * and/or sell copies of the Software, and to permit persons to whom the
1142a55b46Smrg * Software is furnished to do so, subject to the following conditions:
1242a55b46Smrg *
1342a55b46Smrg * The above copyright notice and this permission notice (including the next
1442a55b46Smrg * paragraph) shall be included in all copies or substantial portions of the
1542a55b46Smrg * Software.
1642a55b46Smrg *
1742a55b46Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1842a55b46Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1942a55b46Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2042a55b46Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2142a55b46Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2242a55b46Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2342a55b46Smrg * SOFTWARE.
2442a55b46Smrg *
2542a55b46Smrg * Authors:
2642a55b46Smrg *    Joseph Garvin <joseph.h.garvin@gmail.com>
2742a55b46Smrg *    Connor Behan <connor.behan@gmail.com>
2842a55b46Smrg *
2942a55b46Smrg */
3042a55b46Smrg
3142a55b46Smrg#ifdef HAVE_CONFIG_H
3242a55b46Smrg#include "config.h"
3342a55b46Smrg#endif
3442a55b46Smrg
3542a55b46Smrg#include "r128.h"
3642a55b46Smrg#include "exa.h"
3742a55b46Smrg
3842a55b46Smrg#include "r128_reg.h"
3981f79626Smrg#include "r128_rop.h"
4042a55b46Smrg
4142a55b46Smrg#include "xf86.h"
4242a55b46Smrg
4342a55b46Smrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
4442a55b46Smrg * require src and dest datatypes to be equal.
4542a55b46Smrg */
4642a55b46SmrgBool R128GetDatatypeBpp(int bpp, uint32_t *type)
4742a55b46Smrg{
4842a55b46Smrg    switch (bpp) {
4942a55b46Smrg    case 8:
5042a55b46Smrg        *type = R128_DATATYPE_CI8;
5142a55b46Smrg        return TRUE;
5242a55b46Smrg    case 16:
5342a55b46Smrg        *type = R128_DATATYPE_RGB565;
5442a55b46Smrg        return TRUE;
5542a55b46Smrg    case 24:
5642a55b46Smrg        *type = R128_DATATYPE_RGB888;
5742a55b46Smrg        return TRUE;
5842a55b46Smrg    case 32:
5942a55b46Smrg        *type = R128_DATATYPE_ARGB8888;
6042a55b46Smrg        return TRUE;
6142a55b46Smrg    default:
6242a55b46Smrg        return FALSE;
6342a55b46Smrg    }
6442a55b46Smrg}
6542a55b46Smrg
6642a55b46Smrgstatic Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
6742a55b46Smrg				 unsigned int offset, unsigned int pitch)
6842a55b46Smrg{
6942a55b46Smrg    ScreenPtr     pScreen   = pPix->drawable.pScreen;
7042a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
7142a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
7242a55b46Smrg
7342a55b46Smrg    if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) {
7481f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7581f79626Smrg                            "Bad pitch 0x%08x\n", pitch));
7642a55b46Smrg	return FALSE;
7742a55b46Smrg    }
7842a55b46Smrg
7942a55b46Smrg    if (offset % info->ExaDriver->pixmapOffsetAlign != 0) {
8081f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
8181f79626Smrg                            "Bad offset 0x%08x\n", offset));
8242a55b46Smrg	return FALSE;
8342a55b46Smrg    }
8442a55b46Smrg
8542a55b46Smrg    *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
8642a55b46Smrg
8742a55b46Smrg    return TRUE;
8842a55b46Smrg}
8942a55b46Smrg
9042a55b46SmrgBool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
9142a55b46Smrg{
9242a55b46Smrg    uint32_t pitch, offset;
9342a55b46Smrg    int bpp;
9442a55b46Smrg
9542a55b46Smrg    bpp = pPix->drawable.bitsPerPixel;
9642a55b46Smrg    if (bpp == 24)
9742a55b46Smrg        bpp = 8;
9842a55b46Smrg
9942a55b46Smrg    offset = exaGetPixmapOffset(pPix);
10042a55b46Smrg    pitch = exaGetPixmapPitch(pPix);
10142a55b46Smrg
10242a55b46Smrg    return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
10342a55b46Smrg}
10442a55b46Smrg
10542a55b46Smrgstatic void Emit2DState(ScrnInfoPtr pScrn)
10642a55b46Smrg{
10742a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
10842a55b46Smrg    int has_src		    = info->state_2d.src_pitch_offset;
10942a55b46Smrg    unsigned char *R128MMIO = info->MMIO;
11042a55b46Smrg
11142a55b46Smrg    R128WaitForFifo(pScrn, (has_src ? 10 : 9));
11242a55b46Smrg
11342a55b46Smrg    OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
11442a55b46Smrg    OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
11542a55b46Smrg    OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
11642a55b46Smrg    OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
11742a55b46Smrg    OUTREG(R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
11842a55b46Smrg    OUTREG(R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
11942a55b46Smrg    OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask);
12042a55b46Smrg    OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl);
12142a55b46Smrg
12242a55b46Smrg    OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
12342a55b46Smrg    if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
12442a55b46Smrg}
12542a55b46Smrg
12642a55b46Smrg#ifdef R128DRI
12781f79626Smrgvoid EmitCCE2DState(ScrnInfoPtr pScrn)
12842a55b46Smrg{
12942a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
13042a55b46Smrg    int has_src		    = info->state_2d.src_pitch_offset;
13142a55b46Smrg    RING_LOCALS;
13242a55b46Smrg
13342a55b46Smrg    R128CCE_REFRESH( pScrn, info );
13442a55b46Smrg
13542a55b46Smrg    BEGIN_RING( (has_src ? 20 : 18) );
13642a55b46Smrg
13742a55b46Smrg    OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right );
13842a55b46Smrg    OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl );
13942a55b46Smrg    OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr );
14042a55b46Smrg    OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr );
14142a55b46Smrg    OUT_RING_REG( R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr );
14242a55b46Smrg    OUT_RING_REG( R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr );
14342a55b46Smrg    OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask );
14442a55b46Smrg    OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl );
14542a55b46Smrg
14642a55b46Smrg    OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset );
14742a55b46Smrg    if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset );
14842a55b46Smrg
14942a55b46Smrg    ADVANCE_RING();
15042a55b46Smrg}
15142a55b46Smrg#endif
15242a55b46Smrg
15342a55b46Smrg/* EXA Callbacks */
15442a55b46Smrg
15542a55b46Smrgstatic Bool
15642a55b46SmrgR128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
15742a55b46Smrg{
15842a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
15942a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
16042a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
16142a55b46Smrg
16242a55b46Smrg    int bpp = pPixmap->drawable.bitsPerPixel;
16342a55b46Smrg    uint32_t datatype, dst_pitch_offset;
16442a55b46Smrg
16542a55b46Smrg    if (!R128GetDatatypeBpp(bpp, &datatype)) {
16681f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
16781f79626Smrg                            "R128GetDatatypeBpp failed\n"));
16842a55b46Smrg	return FALSE;
16942a55b46Smrg    }
17042a55b46Smrg    if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) {
17181f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
17281f79626Smrg                            "R128GetPixmapOffsetPitch failed\n"));
17342a55b46Smrg	return FALSE;
17442a55b46Smrg    }
17542a55b46Smrg    if (info->state_2d.in_use) return FALSE;
17642a55b46Smrg
17742a55b46Smrg    info->state_2d.in_use = TRUE;
17842a55b46Smrg    info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
17942a55b46Smrg    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
18042a55b46Smrg    info->state_2d.dp_src_frgd_clr = 0xffffffff;
18142a55b46Smrg    info->state_2d.dp_src_bkgd_clr = 0x00000000;
18242a55b46Smrg    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
18342a55b46Smrg					  R128_GMC_BRUSH_SOLID_COLOR |
18442a55b46Smrg					  (datatype >> 8) |
18542a55b46Smrg					  R128_GMC_SRC_DATATYPE_COLOR |
18642a55b46Smrg					  R128_ROP[alu].pattern |
18742a55b46Smrg					  R128_GMC_CLR_CMP_CNTL_DIS);
18842a55b46Smrg    info->state_2d.dp_brush_frgd_clr = fg;
18942a55b46Smrg    info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
19042a55b46Smrg    info->state_2d.dp_write_mask = planemask;
19142a55b46Smrg    info->state_2d.dst_pitch_offset = dst_pitch_offset;
19242a55b46Smrg    info->state_2d.src_pitch_offset = 0;
19342a55b46Smrg
19442a55b46Smrg#ifdef R128DRI
19542a55b46Smrg    if (info->directRenderingEnabled) {
19642a55b46Smrg        EmitCCE2DState(pScrn);
19742a55b46Smrg    } else
19842a55b46Smrg#endif
19942a55b46Smrg    {
20042a55b46Smrg        Emit2DState(pScrn);
20142a55b46Smrg    }
20242a55b46Smrg    return TRUE;
20342a55b46Smrg}
20442a55b46Smrg
20542a55b46Smrgstatic void
20642a55b46SmrgR128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
20742a55b46Smrg{
20842a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
20942a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
21042a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
21142a55b46Smrg    unsigned char *R128MMIO = info->MMIO;
21242a55b46Smrg
21342a55b46Smrg    R128WaitForFifo(pScrn, 2);
21442a55b46Smrg    OUTREG(R128_DST_Y_X,          (y1 << 16) | x1);
21542a55b46Smrg    OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1));
216bb3c570cSmacallan    exaMarkSync(pScreen);
21742a55b46Smrg}
21842a55b46Smrg
21942a55b46Smrg#define R128DoneSolid R128Done
22042a55b46Smrg
22142a55b46Smrgvoid
22242a55b46SmrgR128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
22342a55b46Smrg			uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask)
22442a55b46Smrg{
22542a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
22642a55b46Smrg
22742a55b46Smrg    info->state_2d.in_use = TRUE;
22842a55b46Smrg    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
22942a55b46Smrg					  R128_GMC_SRC_PITCH_OFFSET_CNTL |
23042a55b46Smrg					  R128_GMC_BRUSH_NONE |
23142a55b46Smrg					  (datatype >> 8) |
23242a55b46Smrg					  R128_GMC_SRC_DATATYPE_COLOR |
23342a55b46Smrg					  R128_ROP[alu].rop |
23442a55b46Smrg					  R128_DP_SRC_SOURCE_MEMORY |
23542a55b46Smrg					  R128_GMC_CLR_CMP_CNTL_DIS);
23642a55b46Smrg    info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
23742a55b46Smrg			       (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0));
23842a55b46Smrg    info->state_2d.dp_brush_frgd_clr = 0xffffffff;
23942a55b46Smrg    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
24042a55b46Smrg    info->state_2d.dp_src_frgd_clr = 0xffffffff;
24142a55b46Smrg    info->state_2d.dp_src_bkgd_clr = 0x00000000;
24242a55b46Smrg    info->state_2d.dp_write_mask = planemask;
24342a55b46Smrg    info->state_2d.dst_pitch_offset = dst_pitch_offset;
24442a55b46Smrg    info->state_2d.src_pitch_offset = src_pitch_offset;
24542a55b46Smrg    info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
24642a55b46Smrg
24742a55b46Smrg#ifdef R128DRI
24842a55b46Smrg    if (info->directRenderingEnabled) {
24942a55b46Smrg        EmitCCE2DState(pScrn);
25042a55b46Smrg    } else
25142a55b46Smrg#endif
25242a55b46Smrg    {
25342a55b46Smrg        Emit2DState(pScrn);
25442a55b46Smrg    }
25542a55b46Smrg}
25642a55b46Smrg
25742a55b46Smrgstatic Bool
25842a55b46SmrgR128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask)
25942a55b46Smrg{
26042a55b46Smrg    ScreenPtr     pScreen   = pSrcPixmap->drawable.pScreen;
26142a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
26242a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
26342a55b46Smrg
26442a55b46Smrg    int bpp = pDstPixmap->drawable.bitsPerPixel;
26542a55b46Smrg    uint32_t datatype, src_pitch_offset, dst_pitch_offset;
26642a55b46Smrg
26742a55b46Smrg    if (!R128GetDatatypeBpp(bpp, &datatype)) {
26881f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
26981f79626Smrg                            "R128GetDatatypeBpp failed\n"));
27042a55b46Smrg	return FALSE;
27142a55b46Smrg    }
27242a55b46Smrg    if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) {
27381f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
27481f79626Smrg                            "R128GetPixmapOffsetPitch source "
27581f79626Smrg                            "failed\n"));
27642a55b46Smrg	return FALSE;
27742a55b46Smrg    }
27842a55b46Smrg    if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) {
27981f79626Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
28081f79626Smrg                            "R128GetPixmapOffsetPitch dest failed\n"));
28142a55b46Smrg	return FALSE;
28242a55b46Smrg    }
28342a55b46Smrg    if (info->state_2d.in_use) return FALSE;
28442a55b46Smrg
28542a55b46Smrg    info->xdir = xdir;
28642a55b46Smrg    info->ydir = ydir;
28742a55b46Smrg
28842a55b46Smrg    R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask);
28942a55b46Smrg
29042a55b46Smrg    return TRUE;
29142a55b46Smrg}
29242a55b46Smrg
29342a55b46Smrgstatic void
29442a55b46SmrgR128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
29542a55b46Smrg{
29642a55b46Smrg    ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
29742a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
29842a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
29942a55b46Smrg    unsigned char *R128MMIO = info->MMIO;
30042a55b46Smrg
30142a55b46Smrg    if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
30242a55b46Smrg    if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
30342a55b46Smrg
30442a55b46Smrg    R128WaitForFifo(pScrn, 3);
30542a55b46Smrg    OUTREG(R128_SRC_Y_X,          (srcY << 16) | srcX);
30642a55b46Smrg    OUTREG(R128_DST_Y_X,          (dstY << 16) | dstX);
30742a55b46Smrg    OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width);
308bb3c570cSmacallan    exaMarkSync(pScreen);
30942a55b46Smrg}
31042a55b46Smrg
31142a55b46Smrg#define R128DoneCopy R128Done
31242a55b46Smrg
31342a55b46Smrgstatic void
31442a55b46SmrgR128Sync(ScreenPtr pScreen, int marker)
31542a55b46Smrg{
31642a55b46Smrg    R128WaitForIdle(xf86ScreenToScrn(pScreen));
31742a55b46Smrg}
31842a55b46Smrg
31981f79626Smrgvoid
32042a55b46SmrgR128Done(PixmapPtr pPixmap)
32142a55b46Smrg{
32242a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
32342a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
32442a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
32542a55b46Smrg
32642a55b46Smrg    info->state_2d.in_use = FALSE;
32742a55b46Smrg#if defined(R128DRI) && defined(RENDER)
32842a55b46Smrg    if (info->state_2d.src_pix) {
32942a55b46Smrg        pScreen->DestroyPixmap(info->state_2d.src_pix);
33042a55b46Smrg	info->state_2d.src_pix = NULL;
33142a55b46Smrg    }
33242a55b46Smrg    if (info->state_2d.msk_pix) {
33342a55b46Smrg        pScreen->DestroyPixmap(info->state_2d.msk_pix);
33442a55b46Smrg	info->state_2d.msk_pix = NULL;
33542a55b46Smrg    }
33642a55b46Smrg#endif
33742a55b46Smrg}
33842a55b46Smrg
33942a55b46Smrg#ifdef R128DRI
34042a55b46Smrg
34142a55b46Smrg#define R128CCEPrepareSolid R128PrepareSolid
34242a55b46Smrg
34342a55b46Smrgstatic void
34442a55b46SmrgR128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
34542a55b46Smrg{
34642a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
34742a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
34842a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
34942a55b46Smrg    RING_LOCALS;
35042a55b46Smrg
35142a55b46Smrg    R128CCE_REFRESH( pScrn, info );
35242a55b46Smrg
35342a55b46Smrg    BEGIN_RING( 4 );
35442a55b46Smrg
35542a55b46Smrg    OUT_RING_REG( R128_DST_Y_X,          (y1 << 16) | x1 );
35642a55b46Smrg    OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) );
35742a55b46Smrg
35842a55b46Smrg    ADVANCE_RING();
35942a55b46Smrg}
36042a55b46Smrg
36142a55b46Smrg#define R128CCEDoneSolid R128Done
36242a55b46Smrg
36342a55b46Smrg#define R128CCEPrepareCopy R128PrepareCopy
36442a55b46Smrg
36542a55b46Smrgstatic void
36642a55b46SmrgR128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
36742a55b46Smrg	 int width, int height)
36842a55b46Smrg{
36942a55b46Smrg    ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
37042a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
37142a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
37242a55b46Smrg    RING_LOCALS;
37342a55b46Smrg
37442a55b46Smrg    R128CCE_REFRESH( pScrn, info );
37542a55b46Smrg
37642a55b46Smrg    if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
37742a55b46Smrg    if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
37842a55b46Smrg
37942a55b46Smrg    BEGIN_RING( 6 );
38042a55b46Smrg
38142a55b46Smrg    OUT_RING_REG( R128_SRC_Y_X,          (srcY << 16) | srcX );
38242a55b46Smrg    OUT_RING_REG( R128_DST_Y_X,          (dstY << 16) | dstX );
38342a55b46Smrg    OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width );
38442a55b46Smrg
38542a55b46Smrg    ADVANCE_RING();
38642a55b46Smrg}
38742a55b46Smrg
38842a55b46Smrg#define R128CCEDoneCopy R128Done
38942a55b46Smrg
39042a55b46Smrgstatic void
39142a55b46SmrgR128CCESync(ScreenPtr pScreen, int marker)
39242a55b46Smrg{
39342a55b46Smrg    R128CCEWaitForIdle(xf86ScreenToScrn(pScreen));
39442a55b46Smrg}
39542a55b46Smrg
39642a55b46Smrg#endif
39742a55b46Smrg
398bb3c570cSmacallan/*
399bb3c570cSmacallan * Memcpy-based UTS.
400bb3c570cSmacallan */
401bb3c570cSmacallanstatic Bool
402bb3c570cSmacallanR128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
403bb3c570cSmacallan    char *src, int src_pitch)
404bb3c570cSmacallan{
405bb3c570cSmacallan    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
406bb3c570cSmacallan    R128InfoPtr	info      = R128PTR(pScrn);
407bb3c570cSmacallan    char	*dst        = info->FB + exaGetPixmapOffset(pDst);
408bb3c570cSmacallan    int		dst_pitch  = exaGetPixmapPitch(pDst);
409bb3c570cSmacallan    int		bpp    = pDst->drawable.bitsPerPixel;
410bb3c570cSmacallan    int		cpp    = (bpp + 7) >> 3;
411bb3c570cSmacallan    int		wBytes = w * cpp;
412bb3c570cSmacallan
413bb3c570cSmacallan    dst += (x * cpp) + (y * dst_pitch);
414bb3c570cSmacallan
415bb3c570cSmacallan    R128WaitForIdle(pScrn);
416bb3c570cSmacallan
417bb3c570cSmacallan    while (h--) {
418bb3c570cSmacallan	memcpy(dst, src, wBytes);
419bb3c570cSmacallan	src += src_pitch;
420bb3c570cSmacallan	dst += dst_pitch;
421bb3c570cSmacallan    }
422bb3c570cSmacallan
423bb3c570cSmacallan    return TRUE;
424bb3c570cSmacallan}
425bb3c570cSmacallan
426bb3c570cSmacallan/*
427bb3c570cSmacallan * Hostblit-based UTS.
428bb3c570cSmacallan * this assumes 32bit pixels
429bb3c570cSmacallan */
430bb3c570cSmacallanstatic Bool
431bb3c570cSmacallanR128UploadToScreenHW(PixmapPtr pDst, int x, int y, int w, int h,
432bb3c570cSmacallan    char *src, int src_pitch)
433bb3c570cSmacallan{
434bb3c570cSmacallan    ScrnInfoPtr	pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
435bb3c570cSmacallan    R128InfoPtr	info      = R128PTR(pScrn);
436bb3c570cSmacallan    uint32_t	dst_pitch_offset, datatype;
437bb3c570cSmacallan    int		cnt, line, px;
438bb3c570cSmacallan    unsigned char *R128MMIO = info->MMIO;
439bb3c570cSmacallan    int		bpp = pDst->drawable.bitsPerPixel;
440bb3c570cSmacallan    uint32_t	*s;
441bb3c570cSmacallan
442bb3c570cSmacallan    if (!R128GetDatatypeBpp(bpp, &datatype)) {
443bb3c570cSmacallan	return FALSE;
444bb3c570cSmacallan    }
445bb3c570cSmacallan
446bb3c570cSmacallan    if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) {
447bb3c570cSmacallan	return FALSE;
448bb3c570cSmacallan    }
449bb3c570cSmacallan
450bb3c570cSmacallan    info->state_2d.in_use = TRUE;
451bb3c570cSmacallan    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
452bb3c570cSmacallan					  R128_GMC_BRUSH_NONE |
453bb3c570cSmacallan					  (datatype >> 8) |
454bb3c570cSmacallan					  R128_GMC_SRC_DATATYPE_COLOR |
455bb3c570cSmacallan					  R128_ROP3_S |
456bb3c570cSmacallan					  R128_DP_SRC_SOURCE_HOST_DATA |
457bb3c570cSmacallan					  R128_GMC_CLR_CMP_CNTL_DIS);
458bb3c570cSmacallan    info->state_2d.dp_cntl = R128_DST_X_LEFT_TO_RIGHT |
459bb3c570cSmacallan                             R128_DST_Y_TOP_TO_BOTTOM;
460bb3c570cSmacallan    info->state_2d.dp_write_mask = 0xffffffff;
461bb3c570cSmacallan    info->state_2d.dst_pitch_offset = dst_pitch_offset;
462bb3c570cSmacallan    info->state_2d.default_sc_bottom_right = R128_DEFAULT_SC_RIGHT_MAX |
463bb3c570cSmacallan                                             R128_DEFAULT_SC_BOTTOM_MAX;
464bb3c570cSmacallan    Emit2DState(pScrn);
465bb3c570cSmacallan
466bb3c570cSmacallan    R128WaitForFifo(pScrn, 3);
467bb3c570cSmacallan    OUTREG(R128_SRC_Y_X, 0);
468bb3c570cSmacallan    OUTREG(R128_DST_Y_X, (y << 16) | x);
469bb3c570cSmacallan    OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
470bb3c570cSmacallan
471bb3c570cSmacallan    R128WaitForFifo(pScrn, 32);
472bb3c570cSmacallan    cnt = 0;
473bb3c570cSmacallan
474bb3c570cSmacallan    for (line = 0; line < h; line++) {
475bb3c570cSmacallan    	s = (void *)src;
476bb3c570cSmacallan    	for (px = 0; px < w; px++) {
477bb3c570cSmacallan    	    OUTREG(R128_HOST_DATA0, cpu_to_le32(*s));
478bb3c570cSmacallan    	    s++;
479bb3c570cSmacallan    	    cnt++;
480bb3c570cSmacallan    	    if (cnt > 31) {
481bb3c570cSmacallan		R128WaitForFifo(pScrn, 32);
482bb3c570cSmacallan		cnt = 0;
483bb3c570cSmacallan	    }
484bb3c570cSmacallan	}
485bb3c570cSmacallan	src += src_pitch;
486bb3c570cSmacallan    }
487bb3c570cSmacallan    info->state_2d.in_use = FALSE;
488bb3c570cSmacallan    exaMarkSync(pDst->drawable.pScreen);
489bb3c570cSmacallan    return TRUE;
490bb3c570cSmacallan}
491bb3c570cSmacallan
492bb3c570cSmacallan/*
493bb3c570cSmacallan * Memcpy-based DFS.
494bb3c570cSmacallan */
495bb3c570cSmacallanstatic Bool
496bb3c570cSmacallanR128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
497bb3c570cSmacallan    char *dst, int dst_pitch)
498bb3c570cSmacallan{
499bb3c570cSmacallan    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
500bb3c570cSmacallan    R128InfoPtr   info      = R128PTR(pScrn);
501bb3c570cSmacallan    char  *src        = info->FB + exaGetPixmapOffset(pSrc);
502bb3c570cSmacallan    int    src_pitch  = exaGetPixmapPitch(pSrc);
503bb3c570cSmacallan
504bb3c570cSmacallan    int bpp    = pSrc->drawable.bitsPerPixel;
505bb3c570cSmacallan    int cpp    = (bpp + 7) >> 3;
506bb3c570cSmacallan    int wBytes = w * cpp;
507bb3c570cSmacallan
508bb3c570cSmacallan    src += (x * cpp) + (y * src_pitch);
509bb3c570cSmacallan
510bb3c570cSmacallan    R128WaitForIdle(pScrn);
511bb3c570cSmacallan
512bb3c570cSmacallan    while (h--) {
513bb3c570cSmacallan	memcpy(dst, src, wBytes);
514bb3c570cSmacallan	src += src_pitch;
515bb3c570cSmacallan	dst += dst_pitch;
516bb3c570cSmacallan    }
517bb3c570cSmacallan
518bb3c570cSmacallan    return TRUE;
519bb3c570cSmacallan}
520bb3c570cSmacallan
52142a55b46SmrgBool
52281f79626SmrgR128EXAInit(ScreenPtr pScreen, int total)
52342a55b46Smrg{
52442a55b46Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
52542a55b46Smrg    R128InfoPtr info  = R128PTR(pScrn);
52642a55b46Smrg
52781f79626Smrg    info->ExaDriver = exaDriverAlloc();
52881f79626Smrg    if (!info->ExaDriver) {
52981f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
53081f79626Smrg                    "Could not allocate EXA driver...\n");
53181f79626Smrg        return FALSE;
53281f79626Smrg    }
53381f79626Smrg
53442a55b46Smrg    info->ExaDriver->exa_major = EXA_VERSION_MAJOR;
53542a55b46Smrg    info->ExaDriver->exa_minor = EXA_VERSION_MINOR;
53642a55b46Smrg
53742a55b46Smrg    info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset;
53881f79626Smrg    info->ExaDriver->offScreenBase = pScrn->virtualY *
53981f79626Smrg                                        (pScrn->displayWidth *
54081f79626Smrg                                        info->CurrentLayout.pixel_bytes);
54181f79626Smrg    info->ExaDriver->memorySize = total;
542bb3c570cSmacallan    info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS;
54342a55b46Smrg
54442a55b46Smrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
54542a55b46Smrg    info->ExaDriver->maxPitchBytes = 16320;
54642a55b46Smrg#endif
54742a55b46Smrg    /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */
54842a55b46Smrg    info->ExaDriver->pixmapPitchAlign = 32;
54942a55b46Smrg    info->ExaDriver->pixmapOffsetAlign = 32;
55042a55b46Smrg    info->ExaDriver->maxX = 2048;
55142a55b46Smrg    info->ExaDriver->maxY = 2048;
55242a55b46Smrg
55342a55b46Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
55442a55b46Smrg	       "Setting up EXA callbacks\n");
55542a55b46Smrg
55642a55b46Smrg#ifdef R128DRI
55742a55b46Smrg    if (info->directRenderingEnabled) {
55842a55b46Smrg	info->ExaDriver->PrepareSolid = R128CCEPrepareSolid;
55942a55b46Smrg	info->ExaDriver->Solid = R128CCESolid;
56042a55b46Smrg	info->ExaDriver->DoneSolid = R128CCEDoneSolid;
56142a55b46Smrg
56242a55b46Smrg	info->ExaDriver->PrepareCopy = R128CCEPrepareCopy;
56342a55b46Smrg	info->ExaDriver->Copy = R128CCECopy;
56442a55b46Smrg	info->ExaDriver->DoneCopy = R128CCEDoneCopy;
56542a55b46Smrg
56642a55b46Smrg#ifdef RENDER
56742a55b46Smrg	if (info->RenderAccel) {
568bb3c570cSmacallan	    info->ExaDriver->flags |= EXA_OFFSCREEN_ALIGN_POT;
56942a55b46Smrg	    info->ExaDriver->CheckComposite = R128CCECheckComposite;
57042a55b46Smrg	    info->ExaDriver->PrepareComposite = R128CCEPrepareComposite;
57142a55b46Smrg	    info->ExaDriver->Composite = R128CCEComposite;
57242a55b46Smrg	    info->ExaDriver->DoneComposite = R128CCEDoneComposite;
57342a55b46Smrg	}
57442a55b46Smrg#endif
57542a55b46Smrg
57642a55b46Smrg	info->ExaDriver->WaitMarker = R128CCESync;
57742a55b46Smrg    } else
57842a55b46Smrg#endif
57942a55b46Smrg    {
58042a55b46Smrg	info->ExaDriver->PrepareSolid = R128PrepareSolid;
58142a55b46Smrg	info->ExaDriver->Solid = R128Solid;
58242a55b46Smrg	info->ExaDriver->DoneSolid = R128DoneSolid;
58342a55b46Smrg
58442a55b46Smrg	info->ExaDriver->PrepareCopy = R128PrepareCopy;
58542a55b46Smrg	info->ExaDriver->Copy = R128Copy;
58642a55b46Smrg	info->ExaDriver->DoneCopy = R128DoneCopy;
58742a55b46Smrg
588bb3c570cSmacallan	if (pScrn->bitsPerPixel < 24) {
589bb3c570cSmacallan	    info->ExaDriver->UploadToScreen = R128UploadToScreen;
590bb3c570cSmacallan	} else {
591bb3c570cSmacallan	    info->ExaDriver->UploadToScreen = R128UploadToScreenHW;
592bb3c570cSmacallan	}
593bb3c570cSmacallan	info->ExaDriver->DownloadFromScreen = R128DownloadFromScreen;
594bb3c570cSmacallan
59542a55b46Smrg	/* The registers used for r128 compositing are CCE specific, just like the
59642a55b46Smrg	 * registers used for radeon compositing are CP specific. The radeon driver
59742a55b46Smrg	 * falls back to different registers when there is no DRI. The equivalent
59842a55b46Smrg	 * registers on the r128 (if they even exist) are not listed in the register
59942a55b46Smrg	 * file so I can't implement compositing without DRI.
60042a55b46Smrg	 */
60142a55b46Smrg
60242a55b46Smrg	info->ExaDriver->WaitMarker = R128Sync;
60342a55b46Smrg    }
60442a55b46Smrg
60542a55b46Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
60681f79626Smrg	       "Initializing 2D acceleration engine...\n");
60742a55b46Smrg
60842a55b46Smrg    R128EngineInit(pScrn);
60942a55b46Smrg
61042a55b46Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
61142a55b46Smrg	       "Initializing EXA driver...\n");
61242a55b46Smrg
61342a55b46Smrg    if (!exaDriverInit(pScreen, info->ExaDriver)) {
61442a55b46Smrg        free(info->ExaDriver);
61542a55b46Smrg	return FALSE;
61642a55b46Smrg    }
61742a55b46Smrg
61842a55b46Smrg    info->state_2d.composite_setup = FALSE;
61942a55b46Smrg    return TRUE;
62042a55b46Smrg}
621