r128_exa.c revision bb3c570c
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"
3942a55b46Smrg
4042a55b46Smrg#include "xf86.h"
4142a55b46Smrg
4242a55b46Smrgstatic struct {
4342a55b46Smrg    int rop;
4442a55b46Smrg    int pattern;
4542a55b46Smrg} R128_ROP[] = {
4642a55b46Smrg    { R128_ROP3_ZERO, R128_ROP3_ZERO }, /* GXclear        */
4742a55b46Smrg    { R128_ROP3_DSa,  R128_ROP3_DPa  }, /* Gxand          */
4842a55b46Smrg    { R128_ROP3_SDna, R128_ROP3_PDna }, /* GXandReverse   */
4942a55b46Smrg    { R128_ROP3_S,    R128_ROP3_P    }, /* GXcopy         */
5042a55b46Smrg    { R128_ROP3_DSna, R128_ROP3_DPna }, /* GXandInverted  */
5142a55b46Smrg    { R128_ROP3_D,    R128_ROP3_D    }, /* GXnoop         */
5242a55b46Smrg    { R128_ROP3_DSx,  R128_ROP3_DPx  }, /* GXxor          */
5342a55b46Smrg    { R128_ROP3_DSo,  R128_ROP3_DPo  }, /* GXor           */
5442a55b46Smrg    { R128_ROP3_DSon, R128_ROP3_DPon }, /* GXnor          */
5542a55b46Smrg    { R128_ROP3_DSxn, R128_ROP3_PDxn }, /* GXequiv        */
5642a55b46Smrg    { R128_ROP3_Dn,   R128_ROP3_Dn   }, /* GXinvert       */
5742a55b46Smrg    { R128_ROP3_SDno, R128_ROP3_PDno }, /* GXorReverse    */
5842a55b46Smrg    { R128_ROP3_Sn,   R128_ROP3_Pn   }, /* GXcopyInverted */
5942a55b46Smrg    { R128_ROP3_DSno, R128_ROP3_DPno }, /* GXorInverted   */
6042a55b46Smrg    { R128_ROP3_DSan, R128_ROP3_DPan }, /* GXnand         */
6142a55b46Smrg    { R128_ROP3_ONE,  R128_ROP3_ONE  }  /* GXset          */
6242a55b46Smrg};
6342a55b46Smrg
6442a55b46Smrg/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
6542a55b46Smrg * require src and dest datatypes to be equal.
6642a55b46Smrg */
6742a55b46SmrgBool R128GetDatatypeBpp(int bpp, uint32_t *type)
6842a55b46Smrg{
6942a55b46Smrg    switch (bpp) {
7042a55b46Smrg    case 8:
7142a55b46Smrg        *type = R128_DATATYPE_CI8;
7242a55b46Smrg        return TRUE;
7342a55b46Smrg    case 16:
7442a55b46Smrg        *type = R128_DATATYPE_RGB565;
7542a55b46Smrg        return TRUE;
7642a55b46Smrg    case 24:
7742a55b46Smrg        *type = R128_DATATYPE_RGB888;
7842a55b46Smrg        return TRUE;
7942a55b46Smrg    case 32:
8042a55b46Smrg        *type = R128_DATATYPE_ARGB8888;
8142a55b46Smrg        return TRUE;
8242a55b46Smrg    default:
8342a55b46Smrg        return FALSE;
8442a55b46Smrg    }
8542a55b46Smrg}
8642a55b46Smrg
8742a55b46Smrgstatic Bool R128GetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset,
8842a55b46Smrg				 unsigned int offset, unsigned int pitch)
8942a55b46Smrg{
9042a55b46Smrg    ScreenPtr     pScreen   = pPix->drawable.pScreen;
9142a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
9242a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
9342a55b46Smrg
9442a55b46Smrg    if (pitch > 16320 || pitch % info->ExaDriver->pixmapPitchAlign != 0) {
9542a55b46Smrg        R128TRACE(("Bad pitch 0x%08x\n", pitch));
9642a55b46Smrg	return FALSE;
9742a55b46Smrg    }
9842a55b46Smrg
9942a55b46Smrg    if (offset % info->ExaDriver->pixmapOffsetAlign != 0) {
10042a55b46Smrg        R128TRACE(("Bad offset 0x%08x\n", offset));
10142a55b46Smrg	return FALSE;
10242a55b46Smrg    }
10342a55b46Smrg
10442a55b46Smrg    *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
10542a55b46Smrg
10642a55b46Smrg    return TRUE;
10742a55b46Smrg}
10842a55b46Smrg
10942a55b46SmrgBool R128GetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
11042a55b46Smrg{
11142a55b46Smrg    uint32_t pitch, offset;
11242a55b46Smrg    int bpp;
11342a55b46Smrg
11442a55b46Smrg    bpp = pPix->drawable.bitsPerPixel;
11542a55b46Smrg    if (bpp == 24)
11642a55b46Smrg        bpp = 8;
11742a55b46Smrg
11842a55b46Smrg    offset = exaGetPixmapOffset(pPix);
11942a55b46Smrg    pitch = exaGetPixmapPitch(pPix);
12042a55b46Smrg
12142a55b46Smrg    return R128GetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
12242a55b46Smrg}
12342a55b46Smrg
12442a55b46Smrgstatic void Emit2DState(ScrnInfoPtr pScrn)
12542a55b46Smrg{
12642a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
12742a55b46Smrg    int has_src		    = info->state_2d.src_pitch_offset;
12842a55b46Smrg    unsigned char *R128MMIO = info->MMIO;
12942a55b46Smrg
13042a55b46Smrg    R128WaitForFifo(pScrn, (has_src ? 10 : 9));
13142a55b46Smrg
13242a55b46Smrg    OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
13342a55b46Smrg    OUTREG(R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
13442a55b46Smrg    OUTREG(R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
13542a55b46Smrg    OUTREG(R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
13642a55b46Smrg    OUTREG(R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
13742a55b46Smrg    OUTREG(R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
13842a55b46Smrg    OUTREG(R128_DP_WRITE_MASK, info->state_2d.dp_write_mask);
13942a55b46Smrg    OUTREG(R128_DP_CNTL, info->state_2d.dp_cntl);
14042a55b46Smrg
14142a55b46Smrg    OUTREG(R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
14242a55b46Smrg    if (has_src) OUTREG(R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
14342a55b46Smrg}
14442a55b46Smrg
14542a55b46Smrg#ifdef R128DRI
14642a55b46Smrgstatic void EmitCCE2DState(ScrnInfoPtr pScrn)
14742a55b46Smrg{
14842a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
14942a55b46Smrg    int has_src		    = info->state_2d.src_pitch_offset;
15042a55b46Smrg    RING_LOCALS;
15142a55b46Smrg
15242a55b46Smrg    R128CCE_REFRESH( pScrn, info );
15342a55b46Smrg
15442a55b46Smrg    BEGIN_RING( (has_src ? 20 : 18) );
15542a55b46Smrg
15642a55b46Smrg    OUT_RING_REG( R128_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right );
15742a55b46Smrg    OUT_RING_REG( R128_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl );
15842a55b46Smrg    OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr );
15942a55b46Smrg    OUT_RING_REG( R128_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr );
16042a55b46Smrg    OUT_RING_REG( R128_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr );
16142a55b46Smrg    OUT_RING_REG( R128_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr );
16242a55b46Smrg    OUT_RING_REG( R128_DP_WRITE_MASK, info->state_2d.dp_write_mask );
16342a55b46Smrg    OUT_RING_REG( R128_DP_CNTL, info->state_2d.dp_cntl );
16442a55b46Smrg
16542a55b46Smrg    OUT_RING_REG( R128_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset );
16642a55b46Smrg    if (has_src) OUT_RING_REG( R128_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset );
16742a55b46Smrg
16842a55b46Smrg    ADVANCE_RING();
16942a55b46Smrg}
17042a55b46Smrg#endif
17142a55b46Smrg
17242a55b46Smrg/* EXA Callbacks */
17342a55b46Smrg
17442a55b46Smrgstatic Bool
17542a55b46SmrgR128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
17642a55b46Smrg{
17742a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
17842a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
17942a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
18042a55b46Smrg
18142a55b46Smrg    int bpp = pPixmap->drawable.bitsPerPixel;
18242a55b46Smrg    uint32_t datatype, dst_pitch_offset;
18342a55b46Smrg
18442a55b46Smrg    if (!R128GetDatatypeBpp(bpp, &datatype)) {
18542a55b46Smrg        R128TRACE(("R128GetDatatypeBpp failed\n"));
18642a55b46Smrg	return FALSE;
18742a55b46Smrg    }
18842a55b46Smrg    if (!R128GetPixmapOffsetPitch(pPixmap, &dst_pitch_offset)) {
18942a55b46Smrg        R128TRACE(("R128GetPixmapOffsetPitch failed\n"));
19042a55b46Smrg	return FALSE;
19142a55b46Smrg    }
19242a55b46Smrg    if (info->state_2d.in_use) return FALSE;
19342a55b46Smrg
19442a55b46Smrg    info->state_2d.in_use = TRUE;
19542a55b46Smrg    info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
19642a55b46Smrg    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
19742a55b46Smrg    info->state_2d.dp_src_frgd_clr = 0xffffffff;
19842a55b46Smrg    info->state_2d.dp_src_bkgd_clr = 0x00000000;
19942a55b46Smrg    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
20042a55b46Smrg					  R128_GMC_BRUSH_SOLID_COLOR |
20142a55b46Smrg					  (datatype >> 8) |
20242a55b46Smrg					  R128_GMC_SRC_DATATYPE_COLOR |
20342a55b46Smrg					  R128_ROP[alu].pattern |
20442a55b46Smrg					  R128_GMC_CLR_CMP_CNTL_DIS);
20542a55b46Smrg    info->state_2d.dp_brush_frgd_clr = fg;
20642a55b46Smrg    info->state_2d.dp_cntl = (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
20742a55b46Smrg    info->state_2d.dp_write_mask = planemask;
20842a55b46Smrg    info->state_2d.dst_pitch_offset = dst_pitch_offset;
20942a55b46Smrg    info->state_2d.src_pitch_offset = 0;
21042a55b46Smrg
21142a55b46Smrg#ifdef R128DRI
21242a55b46Smrg    if (info->directRenderingEnabled) {
21342a55b46Smrg        EmitCCE2DState(pScrn);
21442a55b46Smrg    } else
21542a55b46Smrg#endif
21642a55b46Smrg    {
21742a55b46Smrg        Emit2DState(pScrn);
21842a55b46Smrg    }
21942a55b46Smrg    return TRUE;
22042a55b46Smrg}
22142a55b46Smrg
22242a55b46Smrgstatic void
22342a55b46SmrgR128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
22442a55b46Smrg{
22542a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
22642a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
22742a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
22842a55b46Smrg    unsigned char *R128MMIO = info->MMIO;
22942a55b46Smrg
23042a55b46Smrg    R128WaitForFifo(pScrn, 2);
23142a55b46Smrg    OUTREG(R128_DST_Y_X,          (y1 << 16) | x1);
23242a55b46Smrg    OUTREG(R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1));
233bb3c570cSmacallan    exaMarkSync(pScreen);
23442a55b46Smrg}
23542a55b46Smrg
23642a55b46Smrg#define R128DoneSolid R128Done
23742a55b46Smrg
23842a55b46Smrgvoid
23942a55b46SmrgR128DoPrepareCopy(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
24042a55b46Smrg			uint32_t dst_pitch_offset, uint32_t datatype, int alu, Pixel planemask)
24142a55b46Smrg{
24242a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
24342a55b46Smrg
24442a55b46Smrg    info->state_2d.in_use = TRUE;
24542a55b46Smrg    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
24642a55b46Smrg					  R128_GMC_SRC_PITCH_OFFSET_CNTL |
24742a55b46Smrg					  R128_GMC_BRUSH_NONE |
24842a55b46Smrg					  (datatype >> 8) |
24942a55b46Smrg					  R128_GMC_SRC_DATATYPE_COLOR |
25042a55b46Smrg					  R128_ROP[alu].rop |
25142a55b46Smrg					  R128_DP_SRC_SOURCE_MEMORY |
25242a55b46Smrg					  R128_GMC_CLR_CMP_CNTL_DIS);
25342a55b46Smrg    info->state_2d.dp_cntl = ((info->xdir >= 0 ? R128_DST_X_LEFT_TO_RIGHT : 0) |
25442a55b46Smrg			       (info->ydir >= 0 ? R128_DST_Y_TOP_TO_BOTTOM : 0));
25542a55b46Smrg    info->state_2d.dp_brush_frgd_clr = 0xffffffff;
25642a55b46Smrg    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
25742a55b46Smrg    info->state_2d.dp_src_frgd_clr = 0xffffffff;
25842a55b46Smrg    info->state_2d.dp_src_bkgd_clr = 0x00000000;
25942a55b46Smrg    info->state_2d.dp_write_mask = planemask;
26042a55b46Smrg    info->state_2d.dst_pitch_offset = dst_pitch_offset;
26142a55b46Smrg    info->state_2d.src_pitch_offset = src_pitch_offset;
26242a55b46Smrg    info->state_2d.default_sc_bottom_right = (R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
26342a55b46Smrg
26442a55b46Smrg#ifdef R128DRI
26542a55b46Smrg    if (info->directRenderingEnabled) {
26642a55b46Smrg        EmitCCE2DState(pScrn);
26742a55b46Smrg    } else
26842a55b46Smrg#endif
26942a55b46Smrg    {
27042a55b46Smrg        Emit2DState(pScrn);
27142a55b46Smrg    }
27242a55b46Smrg}
27342a55b46Smrg
27442a55b46Smrgstatic Bool
27542a55b46SmrgR128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask)
27642a55b46Smrg{
27742a55b46Smrg    ScreenPtr     pScreen   = pSrcPixmap->drawable.pScreen;
27842a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
27942a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
28042a55b46Smrg
28142a55b46Smrg    int bpp = pDstPixmap->drawable.bitsPerPixel;
28242a55b46Smrg    uint32_t datatype, src_pitch_offset, dst_pitch_offset;
28342a55b46Smrg
28442a55b46Smrg    if (!R128GetDatatypeBpp(bpp, &datatype)) {
28542a55b46Smrg        R128TRACE(("R128GetDatatypeBpp failed\n"));
28642a55b46Smrg	return FALSE;
28742a55b46Smrg    }
28842a55b46Smrg    if (!R128GetPixmapOffsetPitch(pSrcPixmap, &src_pitch_offset)) {
28942a55b46Smrg        R128TRACE(("R128GetPixmapOffsetPitch source failed\n"));
29042a55b46Smrg	return FALSE;
29142a55b46Smrg    }
29242a55b46Smrg    if (!R128GetPixmapOffsetPitch(pDstPixmap, &dst_pitch_offset)) {
29342a55b46Smrg        R128TRACE(("R128GetPixmapOffsetPitch dest failed\n"));
29442a55b46Smrg	return FALSE;
29542a55b46Smrg    }
29642a55b46Smrg    if (info->state_2d.in_use) return FALSE;
29742a55b46Smrg
29842a55b46Smrg    info->xdir = xdir;
29942a55b46Smrg    info->ydir = ydir;
30042a55b46Smrg
30142a55b46Smrg    R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, alu, planemask);
30242a55b46Smrg
30342a55b46Smrg    return TRUE;
30442a55b46Smrg}
30542a55b46Smrg
30642a55b46Smrgstatic void
30742a55b46SmrgR128Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
30842a55b46Smrg{
30942a55b46Smrg    ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
31042a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
31142a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
31242a55b46Smrg    unsigned char *R128MMIO = info->MMIO;
31342a55b46Smrg
31442a55b46Smrg    if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
31542a55b46Smrg    if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
31642a55b46Smrg
31742a55b46Smrg    R128WaitForFifo(pScrn, 3);
31842a55b46Smrg    OUTREG(R128_SRC_Y_X,          (srcY << 16) | srcX);
31942a55b46Smrg    OUTREG(R128_DST_Y_X,          (dstY << 16) | dstX);
32042a55b46Smrg    OUTREG(R128_DST_HEIGHT_WIDTH, (height << 16) | width);
321bb3c570cSmacallan    exaMarkSync(pScreen);
32242a55b46Smrg}
32342a55b46Smrg
32442a55b46Smrg#define R128DoneCopy R128Done
32542a55b46Smrg
32642a55b46Smrgstatic void
32742a55b46SmrgR128Sync(ScreenPtr pScreen, int marker)
32842a55b46Smrg{
32942a55b46Smrg    R128WaitForIdle(xf86ScreenToScrn(pScreen));
33042a55b46Smrg}
33142a55b46Smrg
33242a55b46Smrgstatic void
33342a55b46SmrgR128Done(PixmapPtr pPixmap)
33442a55b46Smrg{
33542a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
33642a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
33742a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
33842a55b46Smrg
33942a55b46Smrg    info->state_2d.in_use = FALSE;
34042a55b46Smrg#if defined(R128DRI) && defined(RENDER)
34142a55b46Smrg    if (info->state_2d.src_pix) {
34242a55b46Smrg        pScreen->DestroyPixmap(info->state_2d.src_pix);
34342a55b46Smrg	info->state_2d.src_pix = NULL;
34442a55b46Smrg    }
34542a55b46Smrg    if (info->state_2d.msk_pix) {
34642a55b46Smrg        pScreen->DestroyPixmap(info->state_2d.msk_pix);
34742a55b46Smrg	info->state_2d.msk_pix = NULL;
34842a55b46Smrg    }
34942a55b46Smrg#endif
35042a55b46Smrg}
35142a55b46Smrg
35242a55b46Smrg#ifdef R128DRI
35342a55b46Smrg
35442a55b46Smrg#define R128CCEPrepareSolid R128PrepareSolid
35542a55b46Smrg
35642a55b46Smrgstatic void
35742a55b46SmrgR128CCESolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
35842a55b46Smrg{
35942a55b46Smrg    ScreenPtr     pScreen   = pPixmap->drawable.pScreen;
36042a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
36142a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
36242a55b46Smrg    RING_LOCALS;
36342a55b46Smrg
36442a55b46Smrg    R128CCE_REFRESH( pScrn, info );
36542a55b46Smrg
36642a55b46Smrg    BEGIN_RING( 4 );
36742a55b46Smrg
36842a55b46Smrg    OUT_RING_REG( R128_DST_Y_X,          (y1 << 16) | x1 );
36942a55b46Smrg    OUT_RING_REG( R128_DST_WIDTH_HEIGHT, ((x2-x1) << 16) | (y2-y1) );
37042a55b46Smrg
37142a55b46Smrg    ADVANCE_RING();
37242a55b46Smrg}
37342a55b46Smrg
37442a55b46Smrg#define R128CCEDoneSolid R128Done
37542a55b46Smrg
37642a55b46Smrg#define R128CCEPrepareCopy R128PrepareCopy
37742a55b46Smrg
37842a55b46Smrgstatic void
37942a55b46SmrgR128CCECopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
38042a55b46Smrg	 int width, int height)
38142a55b46Smrg{
38242a55b46Smrg    ScreenPtr     pScreen   = pDstPixmap->drawable.pScreen;
38342a55b46Smrg    ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
38442a55b46Smrg    R128InfoPtr   info      = R128PTR(pScrn);
38542a55b46Smrg    RING_LOCALS;
38642a55b46Smrg
38742a55b46Smrg    R128CCE_REFRESH( pScrn, info );
38842a55b46Smrg
38942a55b46Smrg    if (info->xdir < 0) srcX += width - 1, dstX += width - 1;
39042a55b46Smrg    if (info->ydir < 0) srcY += height - 1, dstY += height - 1;
39142a55b46Smrg
39242a55b46Smrg    BEGIN_RING( 6 );
39342a55b46Smrg
39442a55b46Smrg    OUT_RING_REG( R128_SRC_Y_X,          (srcY << 16) | srcX );
39542a55b46Smrg    OUT_RING_REG( R128_DST_Y_X,          (dstY << 16) | dstX );
39642a55b46Smrg    OUT_RING_REG( R128_DST_HEIGHT_WIDTH, (height << 16) | width );
39742a55b46Smrg
39842a55b46Smrg    ADVANCE_RING();
39942a55b46Smrg}
40042a55b46Smrg
40142a55b46Smrg#define R128CCEDoneCopy R128Done
40242a55b46Smrg
40342a55b46Smrgstatic void
40442a55b46SmrgR128CCESync(ScreenPtr pScreen, int marker)
40542a55b46Smrg{
40642a55b46Smrg    R128CCEWaitForIdle(xf86ScreenToScrn(pScreen));
40742a55b46Smrg}
40842a55b46Smrg
40942a55b46Smrg#ifdef RENDER
41042a55b46Smrg#include "r128_exa_render.c"
41142a55b46Smrg#endif
41242a55b46Smrg
41342a55b46Smrg#endif
41442a55b46Smrg
415bb3c570cSmacallan/*
416bb3c570cSmacallan * Memcpy-based UTS.
417bb3c570cSmacallan */
418bb3c570cSmacallanstatic Bool
419bb3c570cSmacallanR128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
420bb3c570cSmacallan    char *src, int src_pitch)
421bb3c570cSmacallan{
422bb3c570cSmacallan    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
423bb3c570cSmacallan    R128InfoPtr	info      = R128PTR(pScrn);
424bb3c570cSmacallan    char	*dst        = info->FB + exaGetPixmapOffset(pDst);
425bb3c570cSmacallan    int		dst_pitch  = exaGetPixmapPitch(pDst);
426bb3c570cSmacallan    int		bpp    = pDst->drawable.bitsPerPixel;
427bb3c570cSmacallan    int		cpp    = (bpp + 7) >> 3;
428bb3c570cSmacallan    int		wBytes = w * cpp;
429bb3c570cSmacallan
430bb3c570cSmacallan    dst += (x * cpp) + (y * dst_pitch);
431bb3c570cSmacallan
432bb3c570cSmacallan    R128WaitForIdle(pScrn);
433bb3c570cSmacallan
434bb3c570cSmacallan    while (h--) {
435bb3c570cSmacallan	memcpy(dst, src, wBytes);
436bb3c570cSmacallan	src += src_pitch;
437bb3c570cSmacallan	dst += dst_pitch;
438bb3c570cSmacallan    }
439bb3c570cSmacallan
440bb3c570cSmacallan    return TRUE;
441bb3c570cSmacallan}
442bb3c570cSmacallan
443bb3c570cSmacallan/*
444bb3c570cSmacallan * Hostblit-based UTS.
445bb3c570cSmacallan * this assumes 32bit pixels
446bb3c570cSmacallan */
447bb3c570cSmacallanstatic Bool
448bb3c570cSmacallanR128UploadToScreenHW(PixmapPtr pDst, int x, int y, int w, int h,
449bb3c570cSmacallan    char *src, int src_pitch)
450bb3c570cSmacallan{
451bb3c570cSmacallan    ScrnInfoPtr	pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
452bb3c570cSmacallan    R128InfoPtr	info      = R128PTR(pScrn);
453bb3c570cSmacallan    uint32_t	dst_pitch_offset, datatype;
454bb3c570cSmacallan    int		cnt, line, px;
455bb3c570cSmacallan    unsigned char *R128MMIO = info->MMIO;
456bb3c570cSmacallan    int		bpp = pDst->drawable.bitsPerPixel;
457bb3c570cSmacallan    uint32_t	*s;
458bb3c570cSmacallan
459bb3c570cSmacallan    if (!R128GetDatatypeBpp(bpp, &datatype)) {
460bb3c570cSmacallan        R128TRACE(("R128GetDatatypeBpp failed\n"));
461bb3c570cSmacallan	return FALSE;
462bb3c570cSmacallan    }
463bb3c570cSmacallan
464bb3c570cSmacallan    if (!R128GetPixmapOffsetPitch(pDst, &dst_pitch_offset)) {
465bb3c570cSmacallan        R128TRACE(("R128GetPixmapOffsetPitch dest failed\n"));
466bb3c570cSmacallan	return FALSE;
467bb3c570cSmacallan    }
468bb3c570cSmacallan
469bb3c570cSmacallan    info->state_2d.in_use = TRUE;
470bb3c570cSmacallan    info->state_2d.dp_gui_master_cntl = (R128_GMC_DST_PITCH_OFFSET_CNTL |
471bb3c570cSmacallan					  R128_GMC_BRUSH_NONE |
472bb3c570cSmacallan					  (datatype >> 8) |
473bb3c570cSmacallan					  R128_GMC_SRC_DATATYPE_COLOR |
474bb3c570cSmacallan					  R128_ROP3_S |
475bb3c570cSmacallan					  R128_DP_SRC_SOURCE_HOST_DATA |
476bb3c570cSmacallan					  R128_GMC_CLR_CMP_CNTL_DIS);
477bb3c570cSmacallan    info->state_2d.dp_cntl = R128_DST_X_LEFT_TO_RIGHT |
478bb3c570cSmacallan                             R128_DST_Y_TOP_TO_BOTTOM;
479bb3c570cSmacallan    info->state_2d.dp_write_mask = 0xffffffff;
480bb3c570cSmacallan    info->state_2d.dst_pitch_offset = dst_pitch_offset;
481bb3c570cSmacallan    info->state_2d.default_sc_bottom_right = R128_DEFAULT_SC_RIGHT_MAX |
482bb3c570cSmacallan                                             R128_DEFAULT_SC_BOTTOM_MAX;
483bb3c570cSmacallan    Emit2DState(pScrn);
484bb3c570cSmacallan
485bb3c570cSmacallan    R128WaitForFifo(pScrn, 3);
486bb3c570cSmacallan    OUTREG(R128_SRC_Y_X, 0);
487bb3c570cSmacallan    OUTREG(R128_DST_Y_X, (y << 16) | x);
488bb3c570cSmacallan    OUTREG(R128_DST_HEIGHT_WIDTH, (h << 16) | w);
489bb3c570cSmacallan
490bb3c570cSmacallan    R128WaitForFifo(pScrn, 32);
491bb3c570cSmacallan    cnt = 0;
492bb3c570cSmacallan
493bb3c570cSmacallan    for (line = 0; line < h; line++) {
494bb3c570cSmacallan    	s = (void *)src;
495bb3c570cSmacallan    	for (px = 0; px < w; px++) {
496bb3c570cSmacallan    	    OUTREG(R128_HOST_DATA0, cpu_to_le32(*s));
497bb3c570cSmacallan    	    s++;
498bb3c570cSmacallan    	    cnt++;
499bb3c570cSmacallan    	    if (cnt > 31) {
500bb3c570cSmacallan		R128WaitForFifo(pScrn, 32);
501bb3c570cSmacallan		cnt = 0;
502bb3c570cSmacallan	    }
503bb3c570cSmacallan	}
504bb3c570cSmacallan	src += src_pitch;
505bb3c570cSmacallan    }
506bb3c570cSmacallan    info->state_2d.in_use = FALSE;
507bb3c570cSmacallan    exaMarkSync(pDst->drawable.pScreen);
508bb3c570cSmacallan    return TRUE;
509bb3c570cSmacallan}
510bb3c570cSmacallan
511bb3c570cSmacallan/*
512bb3c570cSmacallan * Memcpy-based DFS.
513bb3c570cSmacallan */
514bb3c570cSmacallanstatic Bool
515bb3c570cSmacallanR128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
516bb3c570cSmacallan    char *dst, int dst_pitch)
517bb3c570cSmacallan{
518bb3c570cSmacallan    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
519bb3c570cSmacallan    R128InfoPtr   info      = R128PTR(pScrn);
520bb3c570cSmacallan    char  *src        = info->FB + exaGetPixmapOffset(pSrc);
521bb3c570cSmacallan    int    src_pitch  = exaGetPixmapPitch(pSrc);
522bb3c570cSmacallan
523bb3c570cSmacallan    int bpp    = pSrc->drawable.bitsPerPixel;
524bb3c570cSmacallan    int cpp    = (bpp + 7) >> 3;
525bb3c570cSmacallan    int wBytes = w * cpp;
526bb3c570cSmacallan
527bb3c570cSmacallan    src += (x * cpp) + (y * src_pitch);
528bb3c570cSmacallan
529bb3c570cSmacallan    R128WaitForIdle(pScrn);
530bb3c570cSmacallan
531bb3c570cSmacallan    while (h--) {
532bb3c570cSmacallan	memcpy(dst, src, wBytes);
533bb3c570cSmacallan	src += src_pitch;
534bb3c570cSmacallan	dst += dst_pitch;
535bb3c570cSmacallan    }
536bb3c570cSmacallan
537bb3c570cSmacallan    return TRUE;
538bb3c570cSmacallan}
539bb3c570cSmacallan
54042a55b46SmrgBool
54142a55b46SmrgR128EXAInit(ScreenPtr pScreen)
54242a55b46Smrg{
54342a55b46Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
54442a55b46Smrg    R128InfoPtr info  = R128PTR(pScrn);
54542a55b46Smrg
54642a55b46Smrg    info->ExaDriver->exa_major = EXA_VERSION_MAJOR;
54742a55b46Smrg    info->ExaDriver->exa_minor = EXA_VERSION_MINOR;
54842a55b46Smrg
54942a55b46Smrg    info->ExaDriver->memoryBase = info->FB + pScrn->fbOffset;
550bb3c570cSmacallan    info->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS;
55142a55b46Smrg
55242a55b46Smrg#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
55342a55b46Smrg    info->ExaDriver->maxPitchBytes = 16320;
55442a55b46Smrg#endif
55542a55b46Smrg    /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */
55642a55b46Smrg    info->ExaDriver->pixmapPitchAlign = 32;
55742a55b46Smrg    info->ExaDriver->pixmapOffsetAlign = 32;
55842a55b46Smrg    info->ExaDriver->maxX = 2048;
55942a55b46Smrg    info->ExaDriver->maxY = 2048;
56042a55b46Smrg
56142a55b46Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
56242a55b46Smrg	       "Setting up EXA callbacks\n");
56342a55b46Smrg
56442a55b46Smrg#ifdef R128DRI
56542a55b46Smrg    if (info->directRenderingEnabled) {
56642a55b46Smrg	info->ExaDriver->PrepareSolid = R128CCEPrepareSolid;
56742a55b46Smrg	info->ExaDriver->Solid = R128CCESolid;
56842a55b46Smrg	info->ExaDriver->DoneSolid = R128CCEDoneSolid;
56942a55b46Smrg
57042a55b46Smrg	info->ExaDriver->PrepareCopy = R128CCEPrepareCopy;
57142a55b46Smrg	info->ExaDriver->Copy = R128CCECopy;
57242a55b46Smrg	info->ExaDriver->DoneCopy = R128CCEDoneCopy;
57342a55b46Smrg
57442a55b46Smrg#ifdef RENDER
57542a55b46Smrg	if (info->RenderAccel) {
576bb3c570cSmacallan	    info->ExaDriver->flags |= EXA_OFFSCREEN_ALIGN_POT;
57742a55b46Smrg	    info->ExaDriver->CheckComposite = R128CCECheckComposite;
57842a55b46Smrg	    info->ExaDriver->PrepareComposite = R128CCEPrepareComposite;
57942a55b46Smrg	    info->ExaDriver->Composite = R128CCEComposite;
58042a55b46Smrg	    info->ExaDriver->DoneComposite = R128CCEDoneComposite;
58142a55b46Smrg	}
58242a55b46Smrg#endif
58342a55b46Smrg
58442a55b46Smrg	info->ExaDriver->WaitMarker = R128CCESync;
58542a55b46Smrg    } else
58642a55b46Smrg#endif
58742a55b46Smrg    {
58842a55b46Smrg	info->ExaDriver->PrepareSolid = R128PrepareSolid;
58942a55b46Smrg	info->ExaDriver->Solid = R128Solid;
59042a55b46Smrg	info->ExaDriver->DoneSolid = R128DoneSolid;
59142a55b46Smrg
59242a55b46Smrg	info->ExaDriver->PrepareCopy = R128PrepareCopy;
59342a55b46Smrg	info->ExaDriver->Copy = R128Copy;
59442a55b46Smrg	info->ExaDriver->DoneCopy = R128DoneCopy;
59542a55b46Smrg
596bb3c570cSmacallan	if (pScrn->bitsPerPixel < 24) {
597bb3c570cSmacallan	    info->ExaDriver->UploadToScreen = R128UploadToScreen;
598bb3c570cSmacallan	} else {
599bb3c570cSmacallan	    info->ExaDriver->UploadToScreen = R128UploadToScreenHW;
600bb3c570cSmacallan	}
601bb3c570cSmacallan	info->ExaDriver->DownloadFromScreen = R128DownloadFromScreen;
602bb3c570cSmacallan
60342a55b46Smrg	/* The registers used for r128 compositing are CCE specific, just like the
60442a55b46Smrg	 * registers used for radeon compositing are CP specific. The radeon driver
60542a55b46Smrg	 * falls back to different registers when there is no DRI. The equivalent
60642a55b46Smrg	 * registers on the r128 (if they even exist) are not listed in the register
60742a55b46Smrg	 * file so I can't implement compositing without DRI.
60842a55b46Smrg	 */
60942a55b46Smrg
61042a55b46Smrg	info->ExaDriver->WaitMarker = R128Sync;
61142a55b46Smrg    }
61242a55b46Smrg
61342a55b46Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
61442a55b46Smrg	       "Initalizing 2D acceleration engine...\n");
61542a55b46Smrg
61642a55b46Smrg    R128EngineInit(pScrn);
61742a55b46Smrg
61842a55b46Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
61942a55b46Smrg	       "Initializing EXA driver...\n");
62042a55b46Smrg
62142a55b46Smrg    if (!exaDriverInit(pScreen, info->ExaDriver)) {
62242a55b46Smrg        free(info->ExaDriver);
62342a55b46Smrg	return FALSE;
62442a55b46Smrg    }
62542a55b46Smrg
62642a55b46Smrg    info->state_2d.composite_setup = FALSE;
62742a55b46Smrg    return TRUE;
62842a55b46Smrg}
629