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_sw.c] - Rev 5

Compare with Previous | Blame | View Log

/*
Bare metal OpenCores GFX IP driver for Wishbone bus.
 
THIS IS A SOFTWARE IMPLEMENTATION USING SDL, FOR TESTING PROGRAMS AGAINST THE API
 
Anton Fosselius, Per Lenander 2012
  */
 
#include "orgfx.h"
#include "orgfx_plus.h"
#include "orgfx_3d.h"
 
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
 
#include <math.h>
 
typedef struct Point
{
    float x, y, z;
} Point;
 
 
SDL_Surface* screen = NULL;
 
#define NUM_SURFACES 10
SDL_Surface* surfaces[NUM_SURFACES];
int sCounter = 0;
 
SDL_Surface* target_surface = NULL;
SDL_Surface* tex0_surface = NULL;
SDL_Surface* zbuffer_surface = NULL;
 
SDL_Rect cliprect;
SDL_Rect srcrect;
 
unsigned int color_depth_reg = 16;
 
unsigned int texture_enable = 0;
unsigned int blend_enable = 0;
unsigned int colorkey_enable = 0;
unsigned int clipping_enable = 0;
unsigned int transform_enable = 0;
unsigned int zbuffer_enable = 0;
 
int z_reg = 0;
 
unsigned int colorkey_reg = 0;
float alpha_global_reg = 1;
float alpha0_reg = 1;
float alpha1_reg = 1;
float alpha2_reg = 1;
float pixel_alpha = 1;
 
unsigned int u0_reg = 0, v0_reg = 0;
unsigned int u1_reg = 0, v1_reg = 0;
unsigned int u2_reg = 0, v2_reg = 0;
 
float aa_reg = 1;
float ab_reg = 0;
float ac_reg = 0;
float tx_reg = 0;
float ba_reg = 0;
float bb_reg = 1;
float bc_reg = 0;
float ty_reg = 0;
float ca_reg = 0;
float cb_reg = 0;
float cc_reg = 1;
float tz_reg = 0;
 
// Pixel manipulation
void put_pixel16( SDL_Surface *surface, int x, int y, Uint16 pixel )
{
    if(x<0 || x > surface->w)
        return;
    if(y<0 || y > surface->h)
        return;
    //Convert the pixels to 16 bit
    Uint16 *pixels = (Uint16 *)surface->pixels;
 
    //Set the pixel
    pixels[ ( y * surface->w ) + x ] = pixel;
}
 
Uint16 get_pixel16( SDL_Surface *surface, int x, int y )
{
    if(x<0 || x > surface->w)
        return;
    if(y<0 || y > surface->h)
        return;
    //Convert the pixels to 16 bit
    Uint16 *pixels = (Uint16 *)surface->pixels;
 
    //Get the requested pixel
    return pixels[ ( y * surface->w ) + x ];
}
 
 
unsigned int color0_reg = 0, color1_reg = 0, color2_reg = 0;
 
unsigned int gfx_control_reg_memory = 0;
 
Point toPoint(int x, int y, int z)
{
    Point p;
    p.x = (float)x / FIXEDW;
    p.y = (float)y / FIXEDW;
    p.z = (float)z / FIXEDW;
 
    //printf("x: %d y: %d z: %d  --->  ", x, y, z);
    //printf("p: %f,%f,%f\n", p.x, p.y, p.z);
 
    if(!transform_enable)
        return p;
 
    Point ret;
 
    ret.x = aa_reg*p.x + ab_reg*p.y + ac_reg*p.z + tx_reg;
    ret.y = ba_reg*p.x + bb_reg*p.y + bc_reg*p.z + ty_reg;
    ret.z = ca_reg*p.x + cb_reg*p.y + cc_reg*p.z + tz_reg;
 
    return ret;
}
 
void orgfx_init(unsigned int memoryArea)
{
    SDL_Init(SDL_INIT_VIDEO);
}
 
void orgfx_vga_set_vbara(unsigned int addr)
{
 
}
 
void orgfx_vga_set_vbarb(unsigned int addr)
{
 
}
 
inline void orgfx_vga_bank_switch()
{
 
}
 
void orgfx_vga_set_videomode(unsigned int width, unsigned int height, unsigned char bpp)
{
    color_depth_reg = bpp;
    screen = SDL_SetVideoMode(width, height, bpp, SDL_DOUBLEBUF);
    target_surface = screen;
}
 
struct orgfx_surface orgfx_init_surface(unsigned int width, unsigned int height)
{
    static int screenInitialized = 0;
    struct orgfx_surface surface;
 
    surface.addr = sCounter;
 
    if(screenInitialized)
    {
        SDL_Surface* s = SDL_CreateRGBSurface(0,width, height, color_depth_reg, 0, 0, 0, 0);
        surfaces[sCounter] = s;
        surface.w = s->w;
        surface.h = s->h;
    }
    else
    {
        surfaces[sCounter] = screen;
        surface.w = screen->w;
        surface.h = screen->h;
        screenInitialized = 1;
    }
 
    sCounter++;
 
    return surface;
}
 
void orgfx_bind_rendertarget(struct orgfx_surface *surface)
{
    unsigned int sIndex = surface->addr;
    target_surface = surfaces[sIndex];
    // Clear clip rect
    orgfx_cliprect(0,0,surface->w,surface->h);
}
 
void orgfx_enable_cliprect(unsigned int enable)
{
    clipping_enable = enable;
}
 
void orgfx_cliprect(unsigned int x0, unsigned int y0,
                     unsigned int x1, unsigned int y1)
{
    cliprect.x = x0;
    cliprect.y = y0;
    cliprect.w = x1-x0;
    cliprect.h = y1-y0;
}
 
void orgfx_srcrect(unsigned int x0, unsigned int y0,
                    unsigned int x1, unsigned int y1)
{
    srcrect.x = x0;
    srcrect.y = y0;
    srcrect.w = x1-x0;
    srcrect.h = y1-y0;
}
 
void orgfx_init_src()
{
    if(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(!colorkey_enable || colorkey_reg != color)
    {
        // Check for depth
        if(zbuffer_enable)
        {
            short depthAtTarget = get_pixel16(zbuffer_surface, x, y);
 
            if(depthAtTarget > z_reg)
            {
                //printf("Z: %d ZBUF: %d\n", z_reg, depthAtTarget);
                return;
            }
            else
                put_pixel16(zbuffer_surface, x, y, z_reg);
        }
 
        if(blend_enable)
        {
            unsigned int targetCol = get_pixel16(target_surface, x, y);
 
            float alpha = alpha_global_reg * pixel_alpha;
 
            Uint8 rt = targetCol >> 11, rc = color >> 11;
            Uint8 gt = (targetCol >> 5) & 0x3f, gc = (color >> 5) & 0x3f;
            Uint8 bt = targetCol & 0x1f, bc = color & 0x1f;
 
            Uint8 r = alpha*rc+(1.0 - alpha)*rt;
            Uint8 g = alpha*gc+(1.0 - alpha)*gt;
            Uint8 b = alpha*bc+(1.0 - alpha)*bt;
 
            color = (r << 11) + (g << 5) + b;
        }
        put_pixel16(target_surface, x, y, 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)
    {
        put_pixel16(target_surface,
                    (2*i)%target_surface->w,    // x
                    (2*i)/target_surface->w,    // y
                    mem[i]>>SUBPIXEL_WIDTH);    // high word
        put_pixel16(target_surface,
                    (2*i)%target_surface->w+1,  // x+1
                    (2*i)/target_surface->w,    // y
                    mem[i]&0xffff);             // low word
    }
}
 
void orgfx_clear_zbuffer()
{
    if(zbuffer_surface)
        SDL_FillRect(zbuffer_surface, NULL, -32768); // -maxdepth
}
 
void orgfx_set_color(unsigned int color)
{
    color0_reg = color;
}
 
 
void orgfx_set_colors(unsigned int color0, unsigned int color1, unsigned int color2)
{
    color0_reg = color0;
    color1_reg = color1;
    color2_reg = color2;
}
 
void orgfx_rect(int x0, int y0,
                 int x1, int y1)
{
    Point p0 = toPoint(x0, y0, 0);
    Point p1 = toPoint(x1, y1, 0);
    pixel_alpha = 1;
 
    SDL_Rect dest;
    dest.x = p0.x;
    dest.y = p0.y;
    dest.w = p1.x-p0.x;
    dest.h = p1.y-p0.y;
 
    if(texture_enable)
    {
        int y, x, u, v;
        for(y = p0.y, v = srcrect.y; y < p1.y; ++y, ++v)
            for(x = p0.x, u = srcrect.x; x < p1.x; ++x, ++u)
                orgfx_set_pixel(x, y, get_pixel16(tex0_surface, u, v));
    }
    //   SDL_BlitSurface(tex0_surface, &srcrect, target_surface, &dest);
    else
    {
        int y, x;
        for(y = p0.y; y < p1.y; ++y)
            for(x = p0.x; x < p1.x; ++x)
                orgfx_set_pixel(x, y, color0_reg);
    }
    //   SDL_FillRect(target_surface, &dest, color0_reg);
}
 
void orgfx_line(int x0, int y0,
                 int x1, int y1)
{
    orgfx_line3d(x0, y0, 0, x1, y1, 0);
}
 
 
void orgfx_line3d(int x0, int y0, int z0,
                   int x1, int y1, int z1)
{
    Point p0 = toPoint(x0, y0, z0);
    Point p1 = toPoint(x1, y1, z1);
    pixel_alpha = 1;
 
    orgfx_set_pixel(p0.x,p0.y,color0_reg);
    orgfx_set_pixel(p1.x,p1.y,color0_reg);
 
    int X0 = p0.x, Y0 = p0.y;
    int X1 = p1.x, Y1 = p1.y;
    int dx = abs(X1-X0), sx = X0<X1 ? 1 : -1;
    int dy = abs(Y1-Y0), sy = Y0<Y1 ? 1 : -1;
    int err = (dx>dy ? dx : -dy)/2, e2;
 
    for(;;){
        orgfx_set_pixel(X0, Y0, color0_reg);
        if (X0==X1 && Y0==Y1) break;
        e2 = err;
        if (e2 >-dx) { err -= dy; X0 += sx; }
        if (e2 < dy) { err += dx; Y0 += sy; }
    }
}
 
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)
{
    Point p0 = toPoint(x0, y0, 0);
    Point p1 = toPoint(x1, y1, 0);
    Point p2 = toPoint(x2, y2, 0);
 
    float xmin = p0.x; float xmax = p0.x;
    if(p1.x < xmin) xmin = p1.x; if(p1.x > xmax) xmax = p1.x;
    if(p2.x < xmin) xmin = p2.x; if(p2.x > xmax) xmax = p2.x;
    float ymin = p0.y; float ymax = p0.y;
    if(p1.y < ymin) ymin = p1.y; if(p1.y > ymax) ymax = p1.y;
    if(p2.y < ymin) ymin = p2.y; if(p2.y > ymax) ymax = p2.y;
 
    float area = (p1.x - p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
 
    float x, y;
 
    for(y = ymin; y < ymax; y++)
    {
        for(x = xmin; x < xmax; x++)
        {
            float e0 = -(p2.y-p1.y)*(x-p1.x)+(p2.x-p1.x)*(y-p1.y);
            float e1 = -(p0.y-p2.y)*(x-p2.x)+(p0.x-p2.x)*(y-p2.y);
            float e2 = -(p1.y-p0.y)*(x-p0.x)+(p1.x-p0.x)*(y-p0.y);
 
            if(e0 >= 0 && e1 >= 0 && e2 >= 0)
            {
                float factor1 = e1/area;
                float factor2 = e2/area;
                float factor0 = 1 - factor1 - factor2;
 
                if(blend_enable)
                    pixel_alpha = factor0*alpha0_reg + factor1*alpha1_reg + factor2*alpha2_reg;
                else
                    pixel_alpha = 1;
 
                float bezierFactor0 = factor1/2.0 + factor2;
                float bezierFactor1 = factor2;
 
                if(inside)
                {
                    if(bezierFactor0*bezierFactor0 < bezierFactor1)
                        orgfx_set_pixel( x, y, color0_reg);
                }
                else if(bezierFactor0*bezierFactor0 > bezierFactor1)
                    orgfx_set_pixel( x, y, color0_reg);
            }
        }
    }
}
 
#include <stdio.h>
 
void orgfx_triangle3d(int x0, int y0, int z0,
                       int x1, int y1, int z1,
                       int x2, int y2, int z2,
                       unsigned int interpolate)
{
    Point p0 = toPoint(x0, y0, z0);
    Point p1 = toPoint(x1, y1, z1);
    Point p2 = toPoint(x2, y2, z2);
 
    float xmin = p0.x; float xmax = p0.x;
    if(p1.x < xmin) xmin = p1.x; if(p1.x > xmax) xmax = p1.x;
    if(p2.x < xmin) xmin = p2.x; if(p2.x > xmax) xmax = p2.x;
    float ymin = p0.y; float ymax = p0.y;
    if(p1.y < ymin) ymin = p1.y; if(p1.y > ymax) ymax = p1.y;
    if(p2.y < ymin) ymin = p2.y; if(p2.y > ymax) ymax = p2.y;
 
    float area = (p1.x - p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
 
    if(area < 0)
        return;
 
    pixel_alpha = 1;
 
    float x, y;
 
    for(y = ymin; y < ymax; y++)
    {
        for(x = xmin; x < xmax; x++)
        {
            float e0 = -(p2.y-p1.y)*(x-p1.x)+(p2.x-p1.x)*(y-p1.y);
            float e1 = -(p0.y-p2.y)*(x-p2.x)+(p0.x-p2.x)*(y-p2.y);
            float e2 = -(p1.y-p0.y)*(x-p0.x)+(p1.x-p0.x)*(y-p0.y);
 
            if(e0 >= 0 && e1 >= 0 && e2 >= 0)
            {
                if(interpolate)
                {
                    float factor1 = e1/area;
                    float factor2 = e2/area;
                    float factor0 = 1.0 - factor1 - factor2;
 
                    // Calculate depth
                    z_reg = factor0*p0.z + factor1*p1.z + factor2*p2.z;
 
                    if(blend_enable)
                        pixel_alpha = factor0*alpha0_reg + factor1*alpha1_reg + factor2*alpha2_reg;
                    else
                        pixel_alpha = 1;
 
                    if(texture_enable)
                    {
                        unsigned int u = factor0*u0_reg + factor1*u1_reg + factor2*u2_reg;
                        unsigned int v = factor0*v0_reg + factor1*v1_reg + factor2*v2_reg;
                        if(u >= tex0_surface->w) u = tex0_surface->w-1;
                        if(v >= tex0_surface->h) v = tex0_surface->h-1;
 
                        Uint32 col = get_pixel16(tex0_surface, u, v);
 
                        orgfx_set_pixel(x, y, col);
                    }
                    else
                    {
                        Uint8 r0 = color0_reg >> 11, r1 = color1_reg >> 11, r2 = color2_reg >> 11;
                        Uint8 g0 = (color0_reg >> 5) & 0x3f, g1 = (color1_reg >> 5) & 0x3f, g2 = (color2_reg >> 5) & 0x3f;
                        Uint8 b0 = color0_reg & 0x1f, b1 = color1_reg & 0x1f, b2 = color2_reg & 0x1f;
 
                        Uint8 r = factor0*r0+factor1*r1+factor2*r2;
                        Uint8 g = factor0*g0+factor1*g1+factor2*g2;
                        Uint8 b = factor0*b0+factor1*b1+factor2*b2;
 
                        Uint32 col = (r << 11) + (g << 5) + b;
 
                        orgfx_set_pixel(x, y, col);
                    }
                }
                else
                    orgfx_set_pixel(x, y, color0_reg);
            }
        }
    }
}
 
void orgfx_uv(unsigned int u0, unsigned int v0,
               unsigned int u1, unsigned int v1,
               unsigned int u2, unsigned int v2)
{
    u0_reg = u0;
    v0_reg = v0;
    u1_reg = u1;
    v1_reg = v1;
    u2_reg = u2;
    v2_reg = v2;
}
 
void orgfx_enable_tex0(unsigned int enable)
{
    texture_enable = enable;
 
    orgfx_init_src();
}
 
void orgfx_bind_tex0(struct orgfx_surface* surface)
{
    tex0_surface = surfaces[surface->addr];
 
    orgfx_init_src();
}
 
void orgfx_enable_zbuffer(unsigned int enable)
{
    zbuffer_enable = enable;
}
 
void orgfx_bind_zbuffer(struct orgfx_surface *surface)
{
    unsigned int sIndex = surface->addr;
    zbuffer_surface = surfaces[sIndex];
}
 
void orgfx_enable_alpha(unsigned int enable)
{
    blend_enable = enable;
}
 
void orgfx_set_alpha(unsigned int alpha)
{
    alpha_global_reg = (float)(alpha & 0xff) / 0xff;
    alpha0_reg = (float)((alpha >> 24) & 0xff) / 0xff;
    alpha1_reg = (float)((alpha >> 16) & 0xff) / 0xff;
    alpha2_reg = (float)((alpha >> 8) & 0xff) / 0xff;
}
 
void orgfx_enable_colorkey(unsigned int enable)
{
    colorkey_enable = enable;
}
 
void orgfx_set_colorkey(unsigned int colorkey)
{
    colorkey_reg = colorkey;
}
 
void orgfx_enable_transform(unsigned int enable)
{
    transform_enable = enable;
}
 
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)
{
    aa_reg = (float)aa / FIXEDW;
    ab_reg = (float)ab / FIXEDW;
    ac_reg = (float)ac / FIXEDW;
    tx_reg = (float)tx / FIXEDW;
    ba_reg = (float)ba / FIXEDW;
    bb_reg = (float)bb / FIXEDW;
    bc_reg = (float)bc / FIXEDW;
    ty_reg = (float)ty / FIXEDW;
    ca_reg = (float)ca / FIXEDW;
    cb_reg = (float)cb / FIXEDW;
    cc_reg = (float)cc / FIXEDW;
    tz_reg = (float)tz / FIXEDW;
}
 
// ******** //
// GFX PLUS //
// ******** //
 
struct orgfx_surface textures[NUM_SURFACES];
int surfaceCounter = 0;
 
int activeSurface = -1;
struct orgfx_surface screen0;
struct orgfx_surface depthBuffer;
 
int orgfxplus_init(unsigned int width, unsigned int height, unsigned char bpp, unsigned char doubleBuffering, unsigned char zbuffer)
{
    orgfx_init(GFX_VMEM);
    orgfx_vga_set_videomode(width, height, bpp);
 
    screen0 = orgfx_init_surface(width, height);
    orgfx_bind_rendertarget(&screen0);
 
    if(zbuffer)
    {
        depthBuffer = orgfx_init_surface(width, height);
        orgfx_bind_zbuffer(&depthBuffer);
    }
 
    return -1; // This index is used for binding the screen surface(s)
}
 
int orgfxplus_init_surface(unsigned int width, unsigned int height, unsigned int mem[])
{
    if(surfaceCounter >= NUM_SURFACES)
        return -1;
    textures[surfaceCounter] = orgfx_init_surface(width, height);
 
    int tmp = activeSurface;
 
    orgfxplus_bind_rendertarget(surfaceCounter);
    orgfx_memcpy(mem, width*height/2); // TODO: Only works for 16 bits!
 
    orgfxplus_bind_rendertarget(tmp);
 
    return surfaceCounter++;
}
 
void orgfxplus_bind_rendertarget(int surface)
{
    if(surface == -1)
        orgfx_bind_rendertarget(&screen0);
    else
        orgfx_bind_rendertarget(&textures[surface]);
}
 
void orgfxplus_bind_tex0(int surface)
{
    if(surface == -1)
    {
 
    }
    else
        orgfx_bind_tex0(&textures[surface]);
}
 
void orgfxplus_clip(unsigned int x0, unsigned int y0,
                     unsigned int x1, unsigned int y1,
                     unsigned int enable)
{
    orgfx_enable_cliprect(enable);
    orgfx_cliprect(x0, y0, x1, y1);
}
 
void orgfxplus_fill(int x0, int y0,
                     int x1, int y1,
                     unsigned int color)
{
    orgfx_enable_tex0(0);
    orgfx_set_color(color);
    orgfx_rect(x0, y0, x1, y1);
}
 
void orgfxplus_line(int x0, int y0,
                     int x1, int y1,
                     unsigned int color)
{
    orgfx_enable_tex0(0);
    orgfx_set_color(color);
    orgfx_line(x0, y0, x1, y1);
}
 
void orgfxplus_triangle(int x0, int y0,
                         int x1, int y1,
                         int x2, int y2,
                         unsigned int color)
{
    orgfx_enable_tex0(0);
    orgfx_set_color(color);
    orgfx_triangle(x0, y0, x1, y1, x2, y2, 0);
}
 
void orgfxplus_curve(int x0, int y0,
                      int x1, int y1,
                      int x2, int y2,
                      unsigned int inside, unsigned int color)
{
    orgfx_enable_tex0(0);
    orgfx_set_color(color);
    orgfx_curve(x0, y0, x1, y1, x2, y2, inside);
}
 
void orgfxplus_draw_surface(int x0, int y0,
                             unsigned int surface)
{
    orgfx_enable_tex0(1);
    orgfx_bind_tex0(&textures[surface]);
    orgfx_rect(x0, y0, x0+textures[surface].w*FIXEDW, y0+textures[surface].h*FIXEDW);
}
 
void orgfxplus_draw_surface_section(int x0, int y0,
                                     unsigned int srcx0, unsigned int srcy0,
                                     unsigned int srcx1, unsigned int srcy1,
                                     unsigned int surface)
{
    orgfx_enable_tex0(1);
    orgfx_bind_tex0(&textures[surface]);
    orgfx_srcrect(srcx0, srcy0, srcx1, srcy1);
    orgfx_rect(x0, y0, x0+(srcx1-srcx0)*FIXEDW, y0+(srcy1-srcy0)*FIXEDW);
}
 
// Swap active frame buffers
void orgfxplus_flip()
{
    SDL_Flip(screen);
}
 
void orgfxplus_colorkey(unsigned int colorkey, unsigned int enable)
{
    orgfx_enable_colorkey(enable);
    orgfx_set_colorkey(colorkey);
}
 
void orgfxplus_alpha(unsigned int alpha, unsigned int enable)
{
    orgfx_enable_alpha(enable);
    orgfx_set_alpha(alpha);
}
 
 

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.