/*
** Copyright (c) 1997, 3Dfx Interactive, Inc.
** All Rights Reserved.
**
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.;
** the contents of this file may not be disclosed to third parties, copied or
** duplicated in any form, in whole or in part, without the prior written
** permission of 3Dfx Interactive, Inc.
**
** RESTRICTED RIGHTS LEGEND:
** Use, duplication or disclosure by the Government is subject to restrictions
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
** rights reserved under the Copyright Laws of the United States.
**
*/

#include <stdlib.h>
#include <stdio.h>
#ifndef __linux__
#include <conio.h>
#endif
#include <assert.h>
#include <string.h>

#include <glide.h>
#include "tlib.h"


GrHwConfiguration hwconfig;
static char version[80];

static const char name[]    = "test31";
static const char purpose[] = "draws gouraud shaded triangle using grDrawVertexArray";
static const char usage[]   = "-n <frames> -r <res> -d <filename>";

void
main( int argc, char **argv)
{
  char
    match, 
    **remArgs,
    *args =
#ifdef GLIDE3
      "nrdlsfap",
#else
      "nrd",
#endif
    filename[256];
  int
    frames = -1,
    rv;
  float
    scrWidth   = 640.f,
    scrHeight  = 480.f;
  FxBool
    scrgrab = FXFALSE;

  GrScreenResolution_t
    resolution = GR_RESOLUTION_640x480;

#ifdef GLIDE3
  FxU32
    listType = GR_TRIANGLE_STRIP;
  FxBool
    useList = FXFALSE;
  FxBool
    aaenable = FXFALSE;
  FxBool
    packedrgb = FXFALSE;
#endif
  
  /* Process Command Line Arguments */
  while( rv = tlGetOpt( argc, argv, args, &match, &remArgs ) ) {
    if ( rv == -1 ) {
      printf( "Unrecognized command line argument\n" );
      printf( "%s %s\n", name, usage );
      printf( "Available resolutions:\n%s\n",
             tlGetResolutionList() );
      return;
    }
    switch( match ) {
    case 'n':
      frames = atoi( remArgs[0] );
      break;
    case 'r':
      resolution = tlGetResolutionConstant( remArgs[0], 
                                           &scrWidth, 
                                           &scrHeight );
      break;
    case 'd':
      scrgrab = FXTRUE;
      frames = 1;
      strcpy(filename, remArgs[0]);
      break;

#ifdef GLIDE3
    case 'l':
      useList = FXTRUE;
      listType = atoi( remArgs[0] );
      break;

    case 'f':
      listType = GR_TRIANGLE_FAN;
      break;

    case 's':
      listType = GR_TRIANGLE_STRIP;
      break;

    case 'a':
      aaenable = FXTRUE;
      break;

    case 'p':
      packedrgb = FXTRUE;
      break;

#endif
    }
  }
  
  tlSetScreen( scrWidth, scrHeight );
  
  grGlideGetVersion( version );
  
  printf( "%s:\n%s\n", name, purpose );
  printf( "%s\n", version );
  printf( "Resolution: %s\n", tlGetResolutionString( resolution ) );
  if ( frames == -1 ) {
    printf( "Press A Key To Begin Test.\n" );
    tlGetCH();
  }
  
  /* Initialize Glide */
  grGlideInit();
  assert( grSstQueryHardware( &hwconfig ) );
  grSstSelect( 0 );
  assert( grSstWinOpen( 0,
                       resolution,
                       GR_REFRESH_60Hz,
                       GR_COLORFORMAT_ABGR,
                       GR_ORIGIN_UPPER_LEFT,
                       2, 1 ) );
  
  tlConSet( 0.f, 0.f, 1.f, 1.f, 
           60, 30, 0xffffff );
  
  /* Set up Render State - gouraud shading */
  grColorCombine( GR_COMBINE_FUNCTION_LOCAL,
                 GR_COMBINE_FACTOR_NONE,
                 GR_COMBINE_LOCAL_ITERATED,
                 GR_COMBINE_OTHER_NONE,
                 FXFALSE );

#ifdef GLIDE3
  if (aaenable) {
    grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL,
                    GR_COMBINE_FACTOR_NONE,
                    GR_COMBINE_LOCAL_ITERATED,
                    GR_COMBINE_OTHER_NONE,
                    FXFALSE );
    grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA,
                          GR_BLEND_ZERO, GR_BLEND_ZERO );
  }

  grVertexLayout(GR_PARAM_XY,  GR_VERTEX_X_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_RGB, GR_VERTEX_R_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_A,   GR_VERTEX_A_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_Z,   GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_W,   GR_VERTEX_OOW_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_ST0, GR_VERTEX_SOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_Q0,  GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE);
  grVertexLayout(GR_PARAM_Q1,  GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE);

#endif
  
  grCullMode(GR_CULL_DISABLE);

  tlConOutput( "Press a key to quit\n" );
  while( frames-- && tlOkToRender()) {
    GrVertex vtxA, vtxB, vtxC;

    if (hwconfig.SSTs[0].type == GR_SSTTYPE_SST96) {
      tlGetDimsByConst(resolution,
                       &scrWidth, 
                       &scrHeight );
        
      grClipWindow(0, 0, (FxU32) scrWidth, (FxU32) scrHeight);
    }
    grRenderBuffer( GR_BUFFER_BACKBUFFER );

#ifdef GLIDE3
    if (useList == FXFALSE) {
#endif
      grBufferClear( 0x00, 0, GR_WDEPTHVALUE_FARTHEST );
      
      vtxA.x = tlScaleX( 0.3f ), vtxA.y = tlScaleY( 0.3f );
      vtxA.r = 255.f, vtxA.g = 0.f, vtxA.b = 0.f;
      
      vtxB.x = tlScaleX( 0.8f ), vtxB.y = tlScaleY( 0.4f );
      vtxB.r = 0.f, vtxB.g = 255.f, vtxB.b = 0.f;
      
      vtxC.x = tlScaleX( 0.5f ), vtxC.y = tlScaleY( 0.8f );
      vtxC.r = 0.f, vtxC.g = 0.f, vtxC.b = 255.f;
      
      grDrawTriangle( &vtxA, &vtxB, &vtxC );
#ifdef GLIDE3
    } else {

#define NVERTS  4
#if 0
#define NVELEM  6               /* XYZRGBA */
#define VTX_X   4
#define VTX_Y   5
#define VTX_R   0
#define VTX_G   1
#define VTX_B   2
#define VTX_A   3
#endif

      int v;
      float vArray[2*NVERTS * sizeof(GrVertex)];
      float *vPtrArray[NVERTS*2];
      
      grBufferClear( 0x00, 0, GR_WDEPTHVALUE_FARTHEST );

      /* Setup the pointer array */
      for (v = 0; v < 2*NVERTS; v++)
        vPtrArray[v] = &vArray[sizeof(GrVertex) * v];


      /* Set up the vertices */
      if ((listType == GR_TRIANGLE_FAN) || (listType == GR_POLYGON)) {
        vPtrArray[1][GR_VERTEX_X_OFFSET] = tlScaleX(0.3f);
        vPtrArray[1][GR_VERTEX_Y_OFFSET] = tlScaleY( 0.3f );
        vPtrArray[1][GR_VERTEX_A_OFFSET] = 255.f;
        vPtrArray[1][GR_VERTEX_R_OFFSET] = 255.f;
        vPtrArray[1][GR_VERTEX_G_OFFSET] = 0.f;
        vPtrArray[1][GR_VERTEX_B_OFFSET] = 0.f;

        vPtrArray[0][GR_VERTEX_X_OFFSET] = tlScaleX( 0.8f );
        vPtrArray[0][GR_VERTEX_Y_OFFSET] = tlScaleY( 0.4f );
        vPtrArray[0][GR_VERTEX_A_OFFSET] = 255.f;
        vPtrArray[0][GR_VERTEX_R_OFFSET] = 0.f;
        vPtrArray[0][GR_VERTEX_G_OFFSET] = 255.f;
        vPtrArray[0][GR_VERTEX_B_OFFSET] = 0.f;
        if (packedrgb) {
          *((FxU32 *)&vPtrArray[1][GR_VERTEX_R_OFFSET]) = 0xffff0000;
          *((FxU32 *)&vPtrArray[0][GR_VERTEX_R_OFFSET]) = 0xff00ff00;
        }
      }
      else {
        vPtrArray[0][GR_VERTEX_X_OFFSET] = tlScaleX(0.3f);
        vPtrArray[0][GR_VERTEX_Y_OFFSET] = tlScaleY( 0.3f );
        vPtrArray[0][GR_VERTEX_A_OFFSET] = 255.f;
        vPtrArray[0][GR_VERTEX_R_OFFSET] = 255.f;
        vPtrArray[0][GR_VERTEX_G_OFFSET] = 0.f;
        vPtrArray[0][GR_VERTEX_B_OFFSET] = 0.f;

        vPtrArray[1][GR_VERTEX_X_OFFSET] = tlScaleX( 0.8f );
        vPtrArray[1][GR_VERTEX_Y_OFFSET] = tlScaleY( 0.4f );
        vPtrArray[1][GR_VERTEX_A_OFFSET] = 255.f;
        vPtrArray[1][GR_VERTEX_R_OFFSET] = 0.f;
        vPtrArray[1][GR_VERTEX_G_OFFSET] = 255.f;
        vPtrArray[1][GR_VERTEX_B_OFFSET] = 0.f;      
        if (packedrgb) {
          *((FxU32 *)&vPtrArray[0][GR_VERTEX_R_OFFSET]) = 0xffff0000;
          *((FxU32 *)&vPtrArray[1][GR_VERTEX_R_OFFSET]) = 0xff00ff00;
        }
      }
      
      vPtrArray[2][GR_VERTEX_X_OFFSET] = tlScaleX( 0.5f );
      vPtrArray[2][GR_VERTEX_Y_OFFSET] = tlScaleY( 0.8f );
      vPtrArray[2][GR_VERTEX_A_OFFSET] = 255.f;
      vPtrArray[2][GR_VERTEX_R_OFFSET] = 0.f;
      vPtrArray[2][GR_VERTEX_G_OFFSET] = 0.f;
      vPtrArray[2][GR_VERTEX_B_OFFSET] = 255.f;

      vPtrArray[3][GR_VERTEX_X_OFFSET] = tlScaleX( 0.9f );
      vPtrArray[3][GR_VERTEX_Y_OFFSET] = tlScaleY( 0.8f );
      vPtrArray[3][GR_VERTEX_A_OFFSET] = 255.f;
      vPtrArray[3][GR_VERTEX_R_OFFSET] = 255.f;
      vPtrArray[3][GR_VERTEX_G_OFFSET] = 255.f;
      vPtrArray[3][GR_VERTEX_B_OFFSET] = 255.f;
      if (packedrgb) {
        *((FxU32 *)&vPtrArray[2][GR_VERTEX_R_OFFSET]) = 0xff0000ff;
        *((FxU32 *)&vPtrArray[3][GR_VERTEX_R_OFFSET]) = 0xffffffff;
      }

      /* Describe the vertices to Glide */
#if 0
      grVertexLayout(GR_PARAM_XY, GR_VERTEX_X_OFFSET << 2);
      if (packedrgb)
        grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_R_OFFSET << 2);
      else
        grVertexLayout(GR_PARAM_RGB, GR_VERTEX_R_OFFSET << 2);

      if (aaenable) {
        if (!packedrgb)
          grVertexLayout(GR_PARAM_A, GR_VERTEX_A_OFFSET << 2);
        grEnable(GR_AA_ORDERED);
      }
#endif
      if (aaenable) {
        grEnable(GR_AA_ORDERED);
      }

      if (listType == GR_TRIANGLES) {
        float *vertArray[6];
        vertArray[0] = &vPtrArray[0][0];
        vertArray[1] = &vPtrArray[1][0];
        vertArray[2] = &vPtrArray[2][0];
        vertArray[3] = &vPtrArray[2][0];
        vertArray[4] = &vPtrArray[1][0];
        vertArray[5] = &vPtrArray[3][0];
        grDrawVertexArray(listType, NVERTS+2, vertArray);
      }
      else {
        grDrawVertexArray(listType, NVERTS, vPtrArray);
      }

    }
#endif    
    tlConRender();
    grBufferSwap( 1 );
    
    
    
    /* grab the frame buffer */
    if (scrgrab) {
      if (!tlScreenDump(filename, (FxU16)scrWidth, (FxU16)scrHeight))
        printf( "Cannot open %s\n", filename);
      scrgrab = FXFALSE;
    }

    if ( tlKbHit() ) frames = 0;
  }
  
  grGlideShutdown();
  return;
} /* main */







