display.c 3.22 KB
/*
 *  display.c - display texture output
 *
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#include "display.h"
#include "test_image.h"
#include "rdp_opts.h"

#define DEFAULT_NAME 	"rdp.rgb"
#define MAXX		320
#define MAXY		240

#define POSEDGE         (save_clk && !save_clk_old)
#define NEGEDGE         (!save_clk && save_clk_old)

/*
 *   G l o b a l s
 */

static char *Fname = DEFAULT_NAME;
static int   MaxX = MAXX;
static int   MaxY = MAXY;
static Image FrameBuf;
static int   VisualOutput = 0;

/*
 *  Quick and dirty display routine to write a frame buffer
 *  with blender outputs
 */

void
  display(display_t **pp0, display_t **pp1)
{
  unsigned char *pixel;
  /* pointers to memory structure */
  display_t *p0, *p1;
  int i;
  int save_clk;
  int save_clk_old;

  /* get pointers */
  p0 = *pp0;
  p1 = *pp1;
  save_clk = p0->gclk;
  save_clk_old = p1->gclk_old;

  if(POSEDGE) 
  {
    /* transfer all next-clock register values to register outputs. */
    *pp0 = p1; /* swap */
    *pp1 = p0;
    p0 = *pp0; /* fix pointers */
    p1 = *pp1;
  }

  if(NEGEDGE)
  {
    /* driver asserts wr_fb when ready to exit */
    if(p1->wr_fb)
    {
	save_image(Fname, &FrameBuf);
	printf("Display exit, saving %s\n", Fname);
	if (VisualOutput) {
	    printf("hit ^c to exit\n");
	    fflush(stdout);
	    pause();
	}
        p0->exit = 1;
    } 
    else
      p0->exit = 0;
 
    /* delay start address */
    p0->adrs_d1 = p1->ms_addr;
 
    /* get address */
    if(p1->st_span)
    {
      p0->addr[0] = p1->adrs_d1;
    }
    else if (p1->left)
      p0->addr[0] = p1->addr[0] + 1;  /* left major, assume one-cycle mode */
    else
      p0->addr[0] = p1->addr[0] - 1;  /* right major, assume one-cycle mode */
    
    /*  delay address until pixel shows up */
    for(i = 1; i < DISP_ADDR_DELAY; i++)
      p0->addr[i] = p1->addr[i-1];

    if(p1->clr_we)
    {
	/* write to frame buffer */
        if(p1->addr[DISP_ADDR_DELAY-1] >= (MAXY * MAXX))
        {
          fprintf(stderr,"Error, address (%d) out of range (%d)\n", 
            p1->addr[DISP_ADDR_DELAY-1], MAXX* MAXY);
        }
        else
        {
	  pixel = FrameBuf.base + (p1->addr[DISP_ADDR_DELAY-1] * 4);
	  pixel[0] = (unsigned char) p1->bl_r;
	  pixel[1] = (unsigned char) p1->bl_g;
	  pixel[2] = (unsigned char) p1->bl_b;
	  pixel[3] = (unsigned char) p1->bl_a;
       }
    }
  } /* negedge */

  /* save last clock state */
  p0->gclk_old = p1->gclk_old = save_clk;    
}


/*
 *  Display init
 */

void
  display_init(display_t *p0, display_t *p1)
{
  int c, i;

  extern char *optarg;
  extern int optind, opterr, optopt;

  optind = 1;
  opterr = 0;

  p0->gclk = p1->gclk = 0;
  p0->gclk_old = p1->gclk_old = 0;
  p0->addr[0] = p1->addr[0] = 0;

  while((c = getopt(p1->argc, p1->argv, OPTARG)) != EOF)
  {
     switch(c)
     {
       case 'v':
          VisualOutput = 1;
          break;

       case 'h':
          fprintf(stderr," -h, this usage message\n");
          fprintf(stderr," -v, visual output\n");
          return;
     }
  }

  /*
   * Init Frame Buffer
   */

  FrameBuf.xsize = MaxX;
  FrameBuf.ysize = MaxY;
  FrameBuf.lsize = MaxX * 4; /* 32 bit pixels */
  FrameBuf.base = (unsigned char *) calloc(FrameBuf.ysize * FrameBuf.lsize, sizeof(unsigned char));
}