OpenCores
URL https://opencores.org/ocsvn/orsoc_graphics_accelerator/orsoc_graphics_accelerator/trunk

Subversion Repositories orsoc_graphics_accelerator

[/] [orsoc_graphics_accelerator/] [trunk/] [sw/] [drivers/] [gfx/] [bare/] [orgfx.c] - Rev 5

Compare with Previous | Blame | View Log

/*
Bare metal OpenCores GFX IP driver for Wishbone bus.
 
Anton Fosselius, Per Lenander 2012
  */
 
#include "orgfx.h"
#include "orgfx_regs.h"
 
#define GFX_STAT_COUNT_OFFSET 16
#define GFX_INSTRUCTION_FIFO_SIZE 1024
 
#define SUBPIXEL_WIDTH 16
 
/* VGA defines */
#define VGA_BASEADDR   0x97000000 /* Bus Adress to VGA */
 
#define VGA_CTRL       (VGA_BASEADDR + 0x000) /* Control Register */
#define VGA_STAT       (VGA_BASEADDR + 0x004) /* Status Register */
#define VGA_HTIM       (VGA_BASEADDR + 0x008) /* Horisontal Timing Register */
#define VGA_VTIM       (VGA_BASEADDR + 0x00c) /* Vertical Timing Register */
#define VGA_HVLEN      (VGA_BASEADDR + 0x010) /* Horisontal and Vertical Total Screen Size, (Screen size + Blank) */
#define VGA_VBARA      (VGA_BASEADDR + 0x014) /* Adress to Video Base Register A */
#define VGA_VBARB      (VGA_BASEADDR + 0x018) /* Adress to Video Base Register B */
#define VGA_PALETTE    (VGA_BASEADDR + 0x800) /* Color Palette */
 
#define VGA_STAT_AVMP 16
#define VGA_CTRL_VEN   0x00000001 /* Video Enable */
#define VGA_CTRL_HIE   0x00000002 /* HSync Interrupt Enable */
#define VGA_CTRL_PC    0x00000800 /* 8-bit Pseudo Color Enable*/
#define VGA_CTRL_CD8   0x00000000 /* Color Depth 8 */
#define VGA_CTRL_CD16  0x00000200 /* Color Depth 16 */
#define VGA_CTRL_CD24  0x00000400 /* Color Depth 24 */
#define VGA_CTRL_CD32  0x00000600 /* Color Depth 32 */
#define VGA_CTRL_VBL1  0x00000000 /* Burst Length 1 */
#define VGA_CTRL_VBL2  0x00000080 /* Burst Length 2 */
#define VGA_CTRL_VBL4  0x00000100 /* Burst Length 4 */
#define VGA_CTRL_VBL8  0x00000180 /* Burst Length 8 */
#define VGA_CTRL_VBSWE 0x00000020 /* Bank switch enable */
 
// Generate bits from orgfx_regs.h
 
/* ===================== */
/* Control register bits */
/* ===================== */
#define GFX_CTRL_CD8         0                               /* Color Depth 8              */
#define GFX_CTRL_CD16        (1 << GFX_CTRL_COLOR_DEPTH    ) /* Color Depth 16             */
#define GFX_CTRL_CD24        (2 << GFX_CTRL_COLOR_DEPTH    ) /* Color Depth 24             */ // Not supported!
#define GFX_CTRL_CD32        (3 << GFX_CTRL_COLOR_DEPTH    ) /* Color Depth 32             */
#define GFX_CTRL_CDMASK      (3 << GFX_CTRL_COLOR_DEPTH    ) /* All color depth bits       */
 
#define GFX_TEXTURE_ENABLE   (1 << GFX_CTRL_TEXTURE        ) /* Enable Texture Reads       */
#define GFX_BLEND_ENABLE     (1 << GFX_CTRL_BLENDING       ) /* Enable Alpha Blending      */
#define GFX_COLORKEY_ENABLE  (1 << GFX_CTRL_COLORKEY       ) /* Enable Colorkeying         */
#define GFX_CLIPPING_ENABLE  (1 << GFX_CTRL_CLIPPING       ) /* Enable Clipping/Scissoring */
#define GFX_ZBUFFER_ENABLE   (1 << GFX_CTRL_ZBUFFER        ) /* Enable depth buffer        */
 
#define GFX_RECT             (1 << GFX_CTRL_RECT           ) /* Put rect                   */
#define GFX_LINE             (1 << GFX_CTRL_LINE           ) /* Put line                   */
#define GFX_TRI              (1 << GFX_CTRL_TRI            ) /* Put triangle               */
 
#define GFX_CURVE            (1 << GFX_CTRL_CURVE          ) /* Put curve                  */
#define GFX_INTERP           (1 << GFX_CTRL_INTERP         ) /* Activate interpolation     */
#define GFX_INSIDE           (1 << GFX_CTRL_INSIDE         ) /* Bezier inside/outside      */
 
#define GFX_ACTIVE_POINT0    0                               /* Set the active point to p0 */
#define GFX_ACTIVE_POINT1    (1 << GFX_CTRL_ACTIVE_POINT   ) /* Set the active point to p1 */
#define GFX_ACTIVE_POINT2    (2 << GFX_CTRL_ACTIVE_POINT   ) /* Set the active point to p2 */
#define GFX_ACTIVE_POINTMASK (3 << GFX_CTRL_ACTIVE_POINT   )
#define GFX_FORWARD_POINT    (1 << GFX_CTRL_FORWARD_POINT  ) /* Forward the active point   */
#define GFX_TRANSFORM_POINT  (1 << GFX_CTRL_TRANSFORM_POINT) /* Transform the active point */
 
/* ==================== */
/* Status register bits */
/* ==================== */
#define GFX_BUSY        (1 << GFX_STAT_BUSY           ) /* Ready for op */
 
/* Register access macros */
#define REG8(add)  *((volatile unsigned char  *)(add))
#define REG16(add) *((volatile unsigned short *)(add))
#define REG32(add) *((volatile unsigned int   *)(add))
 
// Wait until req_spaces number of places in the instruction fifo are clear
inline void orgfx_wait(unsigned int reg_spaces)
{
  while( REG32(GFX_STATUS) & GFX_BUSY );
  //while( (REG32(GFX_STATUS) >> GFX_STAT_COUNT_OFFSET) + reg_spaces > GFX_INSTRUCTION_FIFO_SIZE);
}
 
unsigned int memory_base = GFX_VMEM;
struct orgfx_surface* target_surface = 0;
struct orgfx_surface* tex0_surface = 0;
struct orgfx_surface* zbuffer_surface = 0;
unsigned int gfx_control_reg_memory = 0;
 
// Forward or transform points?
unsigned int transformation_mode = GFX_FORWARD_POINT;
 
inline void orgfx_set_colordepth(unsigned char bpp);
 
void Set640x480_60(void)
{
    // Set horizontal timing register
    REG32(VGA_HTIM) = ((96 - 1) << 24) |
            ((48 - 1) << 16) |
            (640 - 1);
    // Set vertical timing register
    REG32(VGA_VTIM) = ((2 - 1) << 24) |
            ((31 - 1) << 16) |
            (480 - 1);
    // Set total vertical and horizontal lenghts
    REG32(VGA_HVLEN) = ((800 - 1) << 16) | (525 - 1);
 
    orgfx_wait(2);
    REG32(GFX_TARGET_SIZE_X) = 640;
    REG32(GFX_TARGET_SIZE_Y) = 480;
}
 
void Set800x600_60(void)
{
    // Set horizontal timing register
    REG32(VGA_HTIM) = ((128 - 1) << 24) |
            ((88 - 1) << 16) |
            (800 - 1);
    // Set vertical timing register
    REG32(VGA_VTIM) = ((4 - 1) << 24) |
            ((23 - 1) << 16) |
            (600 - 1);
    // Set total vertical and horizontal lenghts
    REG32(VGA_HVLEN) = ((1056 - 1) << 16) | (628 - 1);
 
    orgfx_wait(2);
    REG32(GFX_TARGET_SIZE_X) = 800;
    REG32(GFX_TARGET_SIZE_Y) = 600;
}
 
void Set1024x768_60(void)
{
    // Set horizontal timing register
    REG32(VGA_HTIM) = ((136 - 1) << 24) |
            ((160 - 1) << 16) |
            (1024 - 1);
    // Set vertical timing register
    REG32(VGA_VTIM) = ((6 - 1) << 24) |
            ((29 - 1) << 16) |
            (768 - 1);
    // Set total vertical and horizontal lenghts
    REG32(VGA_HVLEN) = ((1344 - 1) << 16) | (806 - 1);
 
    orgfx_wait(2);
    REG32(GFX_TARGET_SIZE_X) = 1024;
    REG32(GFX_TARGET_SIZE_Y) = 768;
}
 
void orgfx_init(unsigned int memoryArea)
{
    memory_base = memoryArea;
 
    // Reset VGA+GFX first
    REG32(VGA_CTRL) = 0;
 
    gfx_control_reg_memory = 0;
    orgfx_wait(2);
    REG32(GFX_CONTROL) = gfx_control_reg_memory;
 
    orgfx_vga_set_vbara(memory_base);
    orgfx_vga_set_vbarb(memory_base);
 
    REG32(GFX_TARGET_BASE) = memory_base;
}
 
void orgfx_vga_set_vbara(unsigned int addr)
{
    // Set base address for Video Base Register A
    REG32(VGA_VBARA) = addr;
}
 
void orgfx_vga_set_vbarb(unsigned int addr)
{
    // Set base address for Video Base Register B
    REG32(VGA_VBARB) = addr;
}
 
inline void orgfx_vga_bank_switch()
{
    orgfx_wait(GFX_INSTRUCTION_FIFO_SIZE);
    REG32(VGA_CTRL) |= VGA_CTRL_VBSWE;
}
 
inline unsigned int orgfx_vga_AVMP()
{
    // Get the active memory page bit
    unsigned int status_reg = REG32(VGA_STAT);
    status_reg = status_reg >> VGA_STAT_AVMP;
    return status_reg & 1;
}
 
void orgfx_set_colordepth(unsigned char bpp)
{
    unsigned int vga_bpp = 0, gfx_bpp = 0;
    switch(bpp)
    {
    case 8:  vga_bpp = VGA_CTRL_CD8;  gfx_bpp = GFX_CTRL_CD8;  break;
    case 16: vga_bpp = VGA_CTRL_CD16; gfx_bpp = GFX_CTRL_CD16; break;
        //	case 24: vga_bpp = VGA_CTRL_CD24; gfx_bpp = GFX_CTRL_CD24; break; // Unsupported by gfx
    case 32: vga_bpp = VGA_CTRL_CD32; gfx_bpp = GFX_CTRL_CD32; break;
    default: break;
    }
 
    // Activate VGA
    REG32(VGA_CTRL) |= VGA_CTRL_VEN | VGA_CTRL_VBL8 | vga_bpp;
    gfx_control_reg_memory &= ~GFX_CTRL_CDMASK;
    gfx_control_reg_memory |= gfx_bpp;
    orgfx_wait(1);
    REG32(GFX_CONTROL) = gfx_control_reg_memory;
}
 
void orgfx_vga_set_videomode(unsigned int width, unsigned int height, unsigned char bpp)
{
    if(width == 640 && height == 480)
        Set640x480_60();
    else if(width == 800 && height == 600)
        Set800x600_60();
    else if(width == 1024 && height == 768)
        Set1024x768_60();
    else // Default mode
        Set640x480_60();
 
    orgfx_set_colordepth(bpp);
}
 
struct orgfx_surface orgfx_init_surface(unsigned int width, unsigned int height)
{
    struct orgfx_surface surface;
    surface.addr = memory_base;
    surface.w = width;
    surface.h = height;
    memory_base += (width << 1) * height; // TODO: Only true for 16 bit surfaces!
    return surface;
}
 
void orgfx_bind_rendertarget(struct orgfx_surface *surface)
{
    target_surface = surface;
    orgfx_wait(3);
    REG32(GFX_TARGET_BASE) = surface->addr;
    REG32(GFX_TARGET_SIZE_X) = surface->w;
    REG32(GFX_TARGET_SIZE_Y) = surface->h;
    // Clear clip rect
    orgfx_cliprect(0,0,surface->w,surface->h);
}
 
void orgfx_enable_zbuffer(unsigned int enable)
{
    if(enable)
        gfx_control_reg_memory |= GFX_ZBUFFER_ENABLE;
    else
        gfx_control_reg_memory &= ~GFX_ZBUFFER_ENABLE;
 
    orgfx_wait(1);
    REG32(GFX_CONTROL) = gfx_control_reg_memory;
}
 
void orgfx_bind_zbuffer(struct orgfx_surface *surface)
{
    zbuffer_surface = surface;
    orgfx_wait(1);
    REG32(GFX_ZBUFFER_BASE) = surface->addr;
}
 
void orgfx_clear_zbuffer()
{
    int y, x;
    for(y = 0; y < zbuffer_surface->h; ++y)
    {
        for(x = 0; x < zbuffer_surface->w; x+=2)
        {
            int addr = (y*zbuffer_surface->w + x)*2; // TODO: only works for 16bits
            REG32(zbuffer_surface->addr+addr) = 0x80008000;
        }
    }
}
 
void orgfx_enable_cliprect(unsigned int enable)
{
    if(enable)
        gfx_control_reg_memory |= GFX_CLIPPING_ENABLE;
    else
        gfx_control_reg_memory &= ~GFX_CLIPPING_ENABLE;
 
    orgfx_wait(1);
    REG32(GFX_CONTROL) = gfx_control_reg_memory;
}
 
void orgfx_cliprect(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
{
    orgfx_wait(4);
    REG32(GFX_CLIP_PIXEL0_X) = x0;
    REG32(GFX_CLIP_PIXEL0_Y) = y0;
    REG32(GFX_CLIP_PIXEL1_X) = x1;
    REG32(GFX_CLIP_PIXEL1_Y) = y1;
}
 
void orgfx_srcrect(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
{
    orgfx_wait(4);
    REG32(GFX_SRC_PIXEL0_X) = x0;
    REG32(GFX_SRC_PIXEL0_Y) = y0;
    REG32(GFX_SRC_PIXEL1_X) = x1;
    REG32(GFX_SRC_PIXEL1_Y) = y1;
}
 
void orgfx_init_src()
{
    if((gfx_control_reg_memory & GFX_TEXTURE_ENABLE) && tex0_surface)
        orgfx_srcrect(0, 0, tex0_surface->w, tex0_surface->h);
    else if(target_surface)
        orgfx_srcrect(0, 0, target_surface->w, target_surface->h);
}
 
void orgfx_set_pixel(int x, int y, unsigned int color)
{
    if(x >= 0 && y >= 0)
    {
        int addr = (y*target_surface->w + x)*2; // TODO: only works for 16bits
        REG32(target_surface->addr+addr) = color;
    }
}
 
// Copies a buffer into the current render target
void orgfx_memcpy(unsigned int mem[], unsigned int size)
{
    unsigned int i;
    for(i=0; i < size; ++i)
        REG32(target_surface->addr+i*4) = mem[i];
}
 
void orgfx_set_color(unsigned int color)
{
    orgfx_wait(1);
    REG32(GFX_COLOR0) = color;
}
 
 
void orgfx_set_colors(unsigned int color0, unsigned int color1, unsigned int color2)
{
    orgfx_wait(3);
    REG32(GFX_COLOR0) = color0;
    REG32(GFX_COLOR1) = color1;
    REG32(GFX_COLOR2) = color2;
}
 
void orgfx_rect(int x0, int y0, int x1, int y1)
{
    orgfx_wait(7);
    REG32(GFX_DEST_PIXEL_X) = x0;
    REG32(GFX_DEST_PIXEL_Y) = y0;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT0 | transformation_mode;
    REG32(GFX_DEST_PIXEL_X) = x1;
    REG32(GFX_DEST_PIXEL_Y) = y1;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT1 | transformation_mode;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_RECT;
}
 
void orgfx_line(int x0, int y0, int x1, int y1)
{
    orgfx_line3d(x0, y0, 0, x1, y1, 0);
}
 
void orgfx_triangle(int x0, int y0,
                     int x1, int y1,
                     int x2, int y2,
                     unsigned int interpolate)
{
    orgfx_triangle3d(x0, y0, 0, x1, y1, 0, x2, y2, 0, interpolate);
}
 
void orgfx_curve(int x0, int y0,
                  int x1, int y1,
                  int x2, int y2,
                  unsigned int inside)
{
    orgfx_wait(14);
    REG32(GFX_DEST_PIXEL_Z) = 0; // Set all points depth value to zero
 
    REG32(GFX_DEST_PIXEL_X) = x0;
    REG32(GFX_DEST_PIXEL_Y) = y0;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT0 | transformation_mode;
    REG32(GFX_DEST_PIXEL_X) = x1;
    REG32(GFX_DEST_PIXEL_Y) = y1;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT1 | transformation_mode;
    REG32(GFX_DEST_PIXEL_X) = x2;
    REG32(GFX_DEST_PIXEL_Y) = y2;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT2 | transformation_mode;
 
    if(inside)
        gfx_control_reg_memory |= GFX_INSIDE;
    else
        gfx_control_reg_memory &= ~GFX_INSIDE;
 
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_CURVE | GFX_TRI | GFX_INTERP;
}
 
void orgfx_triangle3d(int x0, int y0, int z0,
                       int x1, int y1, int z1,
                       int x2, int y2, int z2,
                       unsigned int interpolate)
{
    orgfx_wait(13);
    REG32(GFX_DEST_PIXEL_X) = x0;
    REG32(GFX_DEST_PIXEL_Y) = y0;
    REG32(GFX_DEST_PIXEL_Z) = z0;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT0 | transformation_mode;
    REG32(GFX_DEST_PIXEL_X) = x1;
    REG32(GFX_DEST_PIXEL_Y) = y1;
    REG32(GFX_DEST_PIXEL_Z) = z1;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT1 | transformation_mode;
    REG32(GFX_DEST_PIXEL_X) = x2;
    REG32(GFX_DEST_PIXEL_Y) = y2;
    REG32(GFX_DEST_PIXEL_Z) = z2;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT2 | transformation_mode;
 
    if(interpolate)
        REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_TRI | GFX_INTERP;
    else
        REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_TRI;
}
 
void orgfx_line3d(int x0, int y0, int z0, int x1, int y1, int z1)
{
    orgfx_wait(9);
    REG32(GFX_DEST_PIXEL_X) = x0;
    REG32(GFX_DEST_PIXEL_Y) = y0;
    REG32(GFX_DEST_PIXEL_Z) = z0;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT0 | transformation_mode;
    REG32(GFX_DEST_PIXEL_X) = x1;
    REG32(GFX_DEST_PIXEL_Y) = y1;
    REG32(GFX_DEST_PIXEL_Z) = z1;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_ACTIVE_POINT1 | transformation_mode;
    REG32(GFX_CONTROL) = gfx_control_reg_memory | GFX_LINE;
}
 
void orgfx_uv(unsigned int u0, unsigned int v0,
               unsigned int u1, unsigned int v1,
               unsigned int u2, unsigned int v2)
{
    orgfx_wait(6);
    REG32(GFX_U0) = u0;
    REG32(GFX_V0) = v0;
    REG32(GFX_U1) = u1;
    REG32(GFX_V1) = v1;
    REG32(GFX_U2) = u2;
    REG32(GFX_V2) = v2;
}
 
void orgfx_enable_tex0(unsigned int enable)
{
    orgfx_wait(1);
    if(enable)
    {
        gfx_control_reg_memory   |= GFX_TEXTURE_ENABLE;
        REG32(GFX_CONTROL) = gfx_control_reg_memory;
    }
    else
    {
        gfx_control_reg_memory &= ~GFX_TEXTURE_ENABLE;
        REG32(GFX_CONTROL) = gfx_control_reg_memory;
    }
    orgfx_init_src();
}
 
void orgfx_bind_tex0(struct orgfx_surface* surface)
{
    orgfx_wait(3);
    tex0_surface = surface;
    REG32(GFX_TEX0_BASE) = surface->addr;
    REG32(GFX_TEX0_SIZE_X) = surface->w;
    REG32(GFX_TEX0_SIZE_Y) = surface->h;
    orgfx_init_src();
}
 
void orgfx_enable_alpha(unsigned int enable)
{
    orgfx_wait(1);
    if(enable)
        gfx_control_reg_memory |= GFX_BLEND_ENABLE;
    else
        gfx_control_reg_memory &= ~GFX_BLEND_ENABLE;
 
    REG32(GFX_CONTROL) = gfx_control_reg_memory;
}
 
void orgfx_set_alpha(unsigned int alpha)
{
    orgfx_wait(1);
    REG32(GFX_ALPHA) = alpha;
}
 
void orgfx_enable_colorkey(unsigned int enable)
{
    orgfx_wait(1);
    if(enable)
        gfx_control_reg_memory |= GFX_COLORKEY_ENABLE;
    else
        gfx_control_reg_memory &= ~GFX_COLORKEY_ENABLE;
 
    REG32(GFX_CONTROL) = gfx_control_reg_memory;
}
 
void orgfx_set_colorkey(unsigned int colorkey)
{
    orgfx_wait(1);
    REG32(GFX_COLORKEY) = colorkey;
}
 
void orgfx_enable_transform(unsigned int enable)
{
    if(enable)
        transformation_mode = GFX_TRANSFORM_POINT;
    else
        transformation_mode = GFX_FORWARD_POINT;
}
 
void orgfx_set_transformation_matrix(int aa, int ab, int ac, int tx,
                                      int ba, int bb, int bc, int ty,
                                      int ca, int cb, int cc, int tz)
{
    orgfx_wait(12);
    REG32(GFX_AA) = aa;
    REG32(GFX_AB) = ab;
    REG32(GFX_AC) = ac;
    REG32(GFX_TX) = tx;
    REG32(GFX_BA) = ba;
    REG32(GFX_BB) = bb;
    REG32(GFX_BC) = bc;
    REG32(GFX_TY) = ty;
    REG32(GFX_CA) = ca;
    REG32(GFX_CB) = cb;
    REG32(GFX_CC) = cc;
    REG32(GFX_TZ) = tz;
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.