From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/gfxdrivers/cle266/uc_accel.c | 504 +++++++++++++++++++++++++++ 1 file changed, 504 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/cle266/uc_accel.c (limited to 'Source/DirectFB/gfxdrivers/cle266/uc_accel.c') diff --git a/Source/DirectFB/gfxdrivers/cle266/uc_accel.c b/Source/DirectFB/gfxdrivers/cle266/uc_accel.c new file mode 100755 index 0000000..caad848 --- /dev/null +++ b/Source/DirectFB/gfxdrivers/cle266/uc_accel.c @@ -0,0 +1,504 @@ +/* + Copyright (c) 2003 Andreas Robinson, All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. +*/ + +#include + +#include + +#include + +#include "unichrome.h" +#include "uc_accel.h" +#include "uc_fifo.h" +#include "mmio.h" + +#define UC_ACCEL_BEGIN() \ + UcDriverData *ucdrv = (UcDriverData*) drv; \ + UcDeviceData *ucdev = (UcDeviceData*) dev; \ + struct uc_fifo *fifo = ucdrv->fifo; \ + /*printf("entering %s\n", __PRETTY_FUNCTION__)*/ + +#define UC_ACCEL_END() \ + UC_FIFO_CHECK(fifo); \ + /*printf("leaving %s\n", __PRETTY_FUNCTION__)*/ + +// Private functions --------------------------------------------------------- + +/** Wait until a new command can be set up. */ + +static inline void uc_waitcmd(UcDriverData* ucdrv, UcDeviceData* ucdev) +{ + int loop = 0; + + if (!ucdev->must_wait) + return; + + //printf("waitcmd "); + + while (VIA_IN(ucdrv->hwregs, VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) { + if (++loop > MAXLOOP) { + D_ERROR("DirectFB/VIA: Timeout waiting for idle command regulator!\n"); + break; + } + } + + //printf("waited for %d (0x%x) cycles.\n", loop, loop); + + ucdev->cmd_waitcycles += loop; + ucdev->must_wait = 0; +} + +/** Send commands to 2D/3D engine. */ + +void uc_emit_commands(void* drv, void* dev) +{ + UC_ACCEL_BEGIN() + + uc_waitcmd(ucdrv, ucdev); + + UC_FIFO_FLUSH(fifo); + + ucdev->must_wait = 1; +} + +void uc_flush_texture_cache(void* drv, void* dev) +{ + UC_ACCEL_BEGIN() + + (void) ucdev; + + UC_FIFO_PREPARE(fifo, 4); + + UC_FIFO_ADD_HDR(fifo, (HC_ParaType_Tex << 16) | (HC_SubType_TexGeneral << 24)); + UC_FIFO_ADD_3D(fifo, HC_SubA_HTXSMD, HC_HTXCHCLR_MASK); + UC_FIFO_ADD_3D(fifo, HC_SubA_HTXSMD, 0); + + UC_FIFO_CHECK(fifo); +} + +/** + * Draw a horizontal or vertical line. + * + * @param fifo command FIFO + * + * @param x start x position + * @param y start y position + * @param len length + * @param hv if zero: draw from left to right + * if nonzero: draw from top to bottom. + * + * @note This is actually a 1-pixel high or wide rectangular color fill. + */ + +static inline void uc_draw_hv_line(struct uc_fifo* fifo, + int x, int y, int len, int hv, int rop) +{ + UC_FIFO_ADD_2D(fifo, VIA_REG_DSTPOS, ((RS16(y) << 16) | RS16(x))); + UC_FIFO_ADD_2D(fifo, VIA_REG_DIMENSION, len << (hv ? 16 : 0)); + UC_FIFO_ADD_2D(fifo, VIA_REG_GECMD, VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT + | rop | VIA_GEC_CLIP_ENABLE); +} + +// DirectFB interfacing functions -------------------------------------------- + +// Functions using the 2D engine --- + +bool uc_fill_rectangle(void* drv, void* dev, DFBRectangle* r) +{ + UC_ACCEL_BEGIN() + + //printf("%s: r = {%d, %d, %d, %d}, c = 0x%08x\n", __PRETTY_FUNCTION__, + // r->x, r->y, r->w, r->h, ucdev->color); + + if (r->w == 0 || r->h == 0) return true; + + UC_FIFO_PREPARE(fifo, 8); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_NotTex << 16); + + UC_FIFO_ADD_2D(fifo, VIA_REG_DSTPOS, ((RS16(r->y) << 16) | RS16(r->x))); + UC_FIFO_ADD_2D(fifo, VIA_REG_DIMENSION, + (((RS16(r->h - 1)) << 16) | RS16((r->w - 1)))); + UC_FIFO_ADD_2D(fifo, VIA_REG_GECMD, VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT + | ucdev->draw_rop2d | VIA_GEC_CLIP_ENABLE); + + UC_ACCEL_END(); + return true; +} + +bool uc_draw_rectangle(void* drv, void* dev, DFBRectangle* r) +{ + UC_ACCEL_BEGIN() + + //printf("%s: r = {%d, %d, %d, %d}, c = 0x%08x\n", __PRETTY_FUNCTION__, + // r->x, r->y, r->w, r->h, ucdev->color); + + int rop = ucdev->draw_rop2d; + + // Draw lines, in this order: top, bottom, left, right + + UC_FIFO_PREPARE(fifo, 26); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_NotTex << 16); + + uc_draw_hv_line(fifo, r->x, r->y, r->w - 1, 0, rop); + uc_draw_hv_line(fifo, r->x, r->y + r->h - 1, r->w - 1, 0, rop); + uc_draw_hv_line(fifo, r->x, r->y, r->h - 1, 1, rop); + uc_draw_hv_line(fifo, r->x + r->w - 1, r->y, r->h - 1, 1, rop); + + UC_ACCEL_END(); + return true; +} + +bool uc_draw_line(void* drv, void* dev, DFBRegion* line) +{ + UC_ACCEL_BEGIN() + + //printf("%s: l = (%d, %d) - (%d, %d), c = 0x%08x\n", __PRETTY_FUNCTION__, + // line->x1, line->y1, line->x2, line->y2, ucdev->color); + + int cmd; + int dx, dy, tmp, error; + + error = 1; + + cmd = VIA_GEC_LINE | VIA_GEC_FIXCOLOR_PAT | ucdev->draw_rop2d + | VIA_GEC_CLIP_ENABLE; + + dx = line->x2 - line->x1; + if (dx < 0) + { + dx = -dx; + cmd |= VIA_GEC_DECX; // line will be drawn from right + error = 0; + } + + dy = line->y2 - line->y1; + if (dy < 0) + { + dy = -dy; + cmd |= VIA_GEC_DECY; // line will be drawn from bottom + } + + if (dy > dx) + { + tmp = dy; + dy = dx; + dx = tmp; // Swap 'dx' and 'dy' + cmd |= VIA_GEC_Y_MAJOR; // Y major line + } + + UC_FIFO_PREPARE(fifo, 12); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_NotTex << 16); + + UC_FIFO_ADD_2D(fifo, VIA_REG_LINE_K1K2, + ((((dy << 1) & 0x3fff) << 16)| (((dy - dx) << 1) & 0x3fff))); + UC_FIFO_ADD_2D(fifo, VIA_REG_LINE_XY, + ((RS16(line->y1) << 16) | RS16(line->x1))); + UC_FIFO_ADD_2D(fifo, VIA_REG_DIMENSION, dx); + UC_FIFO_ADD_2D(fifo, VIA_REG_LINE_ERROR, + (((dy << 1) - dx - error) & 0x3fff)); + UC_FIFO_ADD_2D(fifo, VIA_REG_GECMD, cmd); + + UC_ACCEL_END(); + return true; +} + +bool uc_blit(void* drv, void* dev, DFBRectangle* rect, int dx, int dy) +{ + UC_ACCEL_BEGIN() + + //printf("%s: r = (%d, %d, %d, %d) -> (%d, %d)\n", __PRETTY_FUNCTION__, + // rect->x, rect->y, rect->h, rect->w, dx, dy); + + int cmd = VIA_GEC_BLT | VIA_ROP_S | VIA_GEC_CLIP_ENABLE; + + int sx = rect->x; + int sy = rect->y; + int w = rect->w; + int h = rect->h; + + if (!w || !h) return true; + + (void) ucdev; // Kill 'unused variable' compiler warning. + + if (sx < dx) { + cmd |= VIA_GEC_DECX; + sx += w - 1; + dx += w - 1; + } + + if (sy < dy) { + cmd |= VIA_GEC_DECY; + sy += h - 1; + dy += h - 1; + } + + UC_FIFO_PREPARE(fifo, 10); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_NotTex << 16); + + UC_FIFO_ADD_2D(fifo, VIA_REG_SRCPOS, (RS16(sy) << 16) | RS16(sx)); + UC_FIFO_ADD_2D(fifo, VIA_REG_DSTPOS, (RS16(dy) << 16) | RS16(dx)); + UC_FIFO_ADD_2D(fifo, VIA_REG_DIMENSION, (RS16(h - 1) << 16) | RS16(w - 1)); + UC_FIFO_ADD_2D(fifo, VIA_REG_GECMD, cmd); + + UC_ACCEL_END(); + return true; +} + +// Functions using the 3D engine --- + +bool uc_fill_rectangle_3d(void* drv, void* dev, DFBRectangle* r) +{ + UC_ACCEL_BEGIN() + + //printf("%s: r = {%d, %d, %d, %d}, c = 0x%08x\n", __PRETTY_FUNCTION__, + // r->x, r->y, r->w, r->h, ucdev->color3d); + + int cmdB = HC_ACMD_HCmdB | HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Cd; + int cmdA = HC_ACMD_HCmdA | HC_HPMType_Tri | HC_HVCycle_AFP | + HC_HVCycle_AA | HC_HVCycle_BB | HC_HVCycle_NewC | HC_HShading_FlatC; + int cmdA_End = cmdA | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; + + if (r->w == 0 || r->h == 0) return true; + + UC_FIFO_PREPARE(fifo, 18); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_CmdVdata << 16); + UC_FIFO_ADD(fifo, cmdB); + UC_FIFO_ADD(fifo, cmdA); + + UC_FIFO_ADD_XYC(fifo, r->x, r->y, 0); + UC_FIFO_ADD_XYC(fifo, r->x + r->w, r->y + r->h, 0); + UC_FIFO_ADD_XYC(fifo, r->x + r->w, r->y, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, r->x, r->y + r->h, ucdev->color3d); + + UC_FIFO_ADD(fifo, cmdA_End); + + UC_FIFO_PAD_EVEN(fifo); + + UC_ACCEL_END(); + return true; +} + +bool uc_draw_rectangle_3d(void* drv, void* dev, DFBRectangle* r) +{ + UC_ACCEL_BEGIN() + + int cmdB = HC_ACMD_HCmdB | HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Cd; + int cmdA = HC_ACMD_HCmdA | HC_HPMType_Line | HC_HVCycle_AFP | HC_HShading_FlatA; + int cmdA_End = cmdA | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; + + UC_FIFO_PREPARE(fifo, 20); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_CmdVdata << 16); + UC_FIFO_ADD(fifo, cmdB); + UC_FIFO_ADD(fifo, cmdA); + + UC_FIFO_ADD_XYC(fifo, r->x, r->y, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, r->x + r->w - 1, r->y, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, r->x + r->w - 1, r->y + r->h - 1, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, r->x, r->y + r->h - 1, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, r->x, r->y, ucdev->color3d); + + UC_FIFO_ADD(fifo, cmdA_End); + + UC_ACCEL_END(); + return true; +} + +bool uc_draw_line_3d(void* drv, void* dev, DFBRegion* line) +{ + UC_ACCEL_BEGIN() + + int cmdB = HC_ACMD_HCmdB | HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Cd; + int cmdA = HC_ACMD_HCmdA | HC_HPMType_Line | HC_HVCycle_Full | HC_HShading_FlatA; + int cmdA_End = cmdA | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; + + UC_FIFO_PREPARE(fifo, 12); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_CmdVdata << 16); + UC_FIFO_ADD(fifo, cmdB); + UC_FIFO_ADD(fifo, cmdA); + + UC_FIFO_ADD_XYC(fifo, line->x1, line->y1, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, line->x2, line->y2, 0); + + UC_FIFO_ADD(fifo, cmdA_End); + + UC_FIFO_PAD_EVEN(fifo); + + UC_ACCEL_END(); + return true; +} + +bool uc_fill_triangle(void* drv, void* dev, DFBTriangle* tri) +{ + UC_ACCEL_BEGIN() + + int cmdB = HC_ACMD_HCmdB | HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Cd; + int cmdA = HC_ACMD_HCmdA | HC_HPMType_Tri | HC_HVCycle_Full | HC_HShading_FlatA; + int cmdA_End = cmdA | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; + + UC_FIFO_PREPARE(fifo, 14); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_CmdVdata << 16); + UC_FIFO_ADD(fifo, cmdB); + UC_FIFO_ADD(fifo, cmdA); + + UC_FIFO_ADD_XYC(fifo, tri->x1, tri->y1, ucdev->color3d); + UC_FIFO_ADD_XYC(fifo, tri->x2, tri->y2, 0); + UC_FIFO_ADD_XYC(fifo, tri->x3, tri->y3, 0); + + UC_FIFO_ADD(fifo, cmdA_End); + + UC_ACCEL_END(); + return true; +} + +bool uc_blit_3d(void* drv, void* dev, + DFBRectangle* rect, int dx, int dy) +{ + // TODO: Write separate blit function to save some overhead. + + // Hmm, I don't think we can save anything beyond a few CPU cycles. -- dok + + DFBRectangle dest = {dx, dy, rect->w, rect->h}; + return uc_stretch_blit(drv, dev, rect, &dest); +} + +bool uc_stretch_blit(void* drv, void* dev, + DFBRectangle* sr, DFBRectangle* dr) +{ + UC_ACCEL_BEGIN() + + float w = ucdev->hwtex.l2w; + float h = ucdev->hwtex.l2h; + + float dy = dr->y; + + float s1 = (sr->x ) / w; + float t1 = (sr->y ) / h; + float s2 = (sr->x + sr->w) / w; + float t2 = (sr->y + sr->h) / h; + + int cmdB = HC_ACMD_HCmdB | HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_W | + HC_HVPMSK_Cd | HC_HVPMSK_S | HC_HVPMSK_T; + + int cmdA = HC_ACMD_HCmdA | HC_HPMType_Tri | HC_HShading_FlatC | + HC_HVCycle_AFP | HC_HVCycle_AA | HC_HVCycle_BB | HC_HVCycle_NewC; + + int cmdA_End = cmdA | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; + + if (ucdev->bflags & DSBLIT_DEINTERLACE) { + t1 *= 0.5f; + t2 *= 0.5f; + + if (ucdev->field) + dy += 0.5f; + else + dy -= 0.5f; + } + + UC_FIFO_PREPARE(fifo, 30); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_CmdVdata << 16); + UC_FIFO_ADD(fifo, cmdB); + UC_FIFO_ADD(fifo, cmdA); + + UC_FIFO_ADD_XYWCST(fifo, dr->x+dr->w, dy, 1, 0, s2, t1); + UC_FIFO_ADD_XYWCST(fifo, dr->x, dy+dr->h, 1, 0, s1, t2); + UC_FIFO_ADD_XYWCST(fifo, dr->x, dy, 1, ucdev->color3d, s1, t1); + UC_FIFO_ADD_XYWCST(fifo, dr->x+dr->w, dy+dr->h, 1, ucdev->color3d, s2, t2); + + UC_FIFO_ADD(fifo, cmdA_End); + + UC_FIFO_PAD_EVEN(fifo); + + UC_ACCEL_END(); + + return true; +} + +#define DFBCOLOR_TO_ARGB(c) PIXEL_ARGB( (c).a, (c).r, (c).g, (c).b ) + +bool uc_texture_triangles( void *drv, void *dev, + DFBVertex *vertices, int num, + DFBTriangleFormation formation ) +{ + UC_ACCEL_BEGIN() + + int i; + + int cmdB = HC_ACMD_HCmdB | + HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z | HC_HVPMSK_W | + HC_HVPMSK_Cd | HC_HVPMSK_S | HC_HVPMSK_T; + + int cmdA = HC_ACMD_HCmdA | HC_HPMType_Tri | HC_HShading_Gouraud | + HC_HVCycle_Full; + + int cmdA_End = cmdA | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK; + + + switch (formation) { + case DTTF_LIST: + cmdA |= HC_HVCycle_NewA | HC_HVCycle_NewB | HC_HVCycle_NewC; + break; + case DTTF_STRIP: + cmdA |= HC_HVCycle_AB | HC_HVCycle_BC | HC_HVCycle_NewC; + break; + case DTTF_FAN: + cmdA |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC; + break; + default: + D_ONCE( "unknown triangle formation" ); + return false; + } + + UC_FIFO_PREPARE(fifo, 6 + num * 7); + + UC_FIFO_ADD_HDR(fifo, HC_ParaType_CmdVdata << 16); + UC_FIFO_ADD(fifo, cmdB); + UC_FIFO_ADD(fifo, cmdA); + + for (i=0; icolor3d, + vertices[i].s, vertices[i].t); + } + + UC_FIFO_ADD(fifo, cmdA_End); + + UC_FIFO_PAD_EVEN(fifo); + + UC_ACCEL_END(); + + return true; +} + + // Blit profiling + + //struct timeval tv_start, tv_stop; + //gettimeofday(&tv_start, NULL); + + // Run test here + + //gettimeofday(&tv_stop, NULL); + + //tv_stop.tv_sec -= tv_start.tv_sec; + //tv_stop.tv_usec -= tv_start.tv_usec; + //if (tv_stop.tv_usec < 0) { + // tv_stop.tv_sec--; + // tv_stop.tv_usec += 1000000; + //} + + //printf("elapsed time: %d us\n", tv_stop.tv_usec); -- cgit