610 lines
19 KiB
C
610 lines
19 KiB
C
/*
|
|
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
|
|
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
|
|
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
|
|
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
|
|
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
|
|
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
|
|
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
|
|
**
|
|
** 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.
|
|
**
|
|
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
|
|
**
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <glide.h>
|
|
#include "tlib.h"
|
|
|
|
/* Video timing data structure
|
|
*
|
|
* NB: This structure definition should be used w/ care since most
|
|
* monitors will not correctly be able to handle arbitrary settings of
|
|
* the fields in this structure.
|
|
*/
|
|
typedef struct {
|
|
FxU32 hSyncOn;
|
|
FxU32 hSyncOff;
|
|
FxU32 vSyncOn;
|
|
FxU32 vSyncOff;
|
|
FxU32 hBackPorch;
|
|
FxU32 vBackPorch;
|
|
FxU32 xDimension;
|
|
FxU32 yDimension;
|
|
FxU32 refreshRate;
|
|
FxU32 miscCtrl;
|
|
FxU32 memOffset;
|
|
FxU32 tilesInX;
|
|
FxU32 vFifoThreshold;
|
|
FxBool video16BPPIsOK;
|
|
FxBool video24BPPIsOK;
|
|
float clkFreq16bpp;
|
|
float clkFreq24bpp;
|
|
} FxVideoTimingInfo;
|
|
|
|
/* this is semi-undocumented external for arcade developers */
|
|
FX_ENTRY void FX_CALL
|
|
grSstVidMode(FxU32 whichSst, FxVideoTimingInfo* vidTimings);
|
|
|
|
/* VESA Standard - 640x480 60Hz */
|
|
static FxVideoTimingInfo
|
|
gDefaultTimingVal = {
|
|
96, /* hSyncOn */
|
|
704, /* hSyncOff */
|
|
2, /* vSyncOn */
|
|
523, /* vSyncOff */
|
|
38, /* hBackPorch */
|
|
25, /* vBackPorch */
|
|
640, /* xDimension */
|
|
480, /* yDimension */
|
|
60, /* refreshRate */
|
|
0, /* miscCtrl */
|
|
150, /* memOffset */
|
|
20, /* tilesInX */
|
|
25, /* vFifoThreshold */
|
|
FXTRUE, /* video16BPPIsOK */
|
|
FXTRUE, /* video24BPPIsOK */
|
|
25.175F, /* clkFreq16bpp */
|
|
50.350F /* clkFreq24bpp */
|
|
};
|
|
|
|
int hwconfig;
|
|
static const char *version;
|
|
|
|
static const char name[] = "test30";
|
|
static const char purpose[] = "Glide resolution/refresh rate/buffer test";
|
|
static const char usage[] = "-n <frames> -d <filename> -v (use vid timing)";
|
|
|
|
static void
|
|
XLateTri(GrVertex* a, GrVertex* b, GrVertex* c,
|
|
const float theta, const float scale,
|
|
const float x, const float y, const float z);
|
|
|
|
static void
|
|
OutputPromptMessage(GrScreenResolution_t conRes,
|
|
GrScreenResolution_t res, GrScreenRefresh_t refresh,
|
|
int colorBuf, int auxBuf,
|
|
const FxVideoTimingInfo* vidTiming,
|
|
FxBool errorP);
|
|
|
|
static FxBool
|
|
ProcessPromptKey(int* frames,
|
|
GrScreenResolution_t* res,
|
|
GrScreenRefresh_t* refresh,
|
|
int* colorBuf,
|
|
int* auxBuf,
|
|
FxVideoTimingInfo* vidTiming);
|
|
|
|
int
|
|
main(int argc, char **argv) {
|
|
float scrWidth = 640.0f;
|
|
float scrHeight = 480.0f;
|
|
int frames = -1;
|
|
FxBool scrgrab = FXFALSE;
|
|
char filename[256];
|
|
FxVideoTimingInfo* vidTiming = NULL;
|
|
FxVideoTimingInfo curVidTiming = gDefaultTimingVal;
|
|
|
|
/* Initialize Glide */
|
|
grGlideInit();
|
|
assert( hwconfig = tlVoodooType() );
|
|
|
|
/* Process Command Line Arguments */
|
|
{
|
|
char match;
|
|
char **remArgs;
|
|
int rv;
|
|
|
|
while(rv = tlGetOpt(argc, argv, "ndv", &match, &remArgs)) {
|
|
if(rv == -1) {
|
|
printf("Unrecognized command line argument\n");
|
|
printf("%s %s\n", name, usage);
|
|
|
|
return -1;
|
|
}
|
|
|
|
switch(match) {
|
|
case 'n':
|
|
frames = atoi(remArgs[0]);
|
|
break;
|
|
|
|
case 'd':
|
|
scrgrab = FXTRUE;
|
|
frames = 1;
|
|
strcpy(filename, remArgs[0]);
|
|
break;
|
|
|
|
case 'v':
|
|
if (hwconfig == TL_VOODOORUSH) {
|
|
printf("%s: cannot use grSstVidMode on Voodoo Rush systems.\n", name);
|
|
} else {
|
|
vidTiming = &curVidTiming;
|
|
grSstVidMode(0, vidTiming);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
tlSetScreen(scrWidth, scrHeight);
|
|
version = grGetString( GR_VERSION );
|
|
|
|
printf("%s:\n%s\n", name, purpose);
|
|
printf("%s\n", version);
|
|
|
|
grSstSelect(0);
|
|
assert(grSstWinOpen(tlGethWnd(),
|
|
GR_RESOLUTION_640x480,
|
|
GR_REFRESH_60Hz,
|
|
GR_COLORFORMAT_ABGR,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
2, 1));
|
|
|
|
tlConSet(0.0f, 0.0f, 1.0f, 1.0f,
|
|
60, 30, 0xffffff);
|
|
grSstWinClose(0);
|
|
|
|
{
|
|
GrScreenRefresh_t curRefresh = GR_REFRESH_60Hz;
|
|
GrScreenResolution_t curRes = GR_RESOLUTION_640x480;
|
|
int numColorBuf = 2, numAuxBuf = 1;
|
|
|
|
while((frames != 0) && tlOkToRender()) {
|
|
/* Try to open at the current user selection */
|
|
if (!grSstWinOpen(tlGethWnd(),
|
|
curRes, curRefresh,
|
|
GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT,
|
|
numColorBuf, numAuxBuf)) {
|
|
|
|
/* If we cannot use the user selection the set to one that
|
|
* should work so that we have reasonable error output.
|
|
*
|
|
* NB: We clear the user's video data here so that we don't
|
|
* any failures due to bad data.
|
|
*/
|
|
grSstVidMode(0, NULL);
|
|
if (!grSstWinOpen(tlGethWnd(), GR_RESOLUTION_640x480, GR_REFRESH_60Hz,
|
|
GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT,
|
|
2, 0)) {
|
|
fprintf(stderr, "Could not set error resolution.\n");
|
|
exit(-1);
|
|
}
|
|
grSstVidMode(0, vidTiming);
|
|
|
|
/* Let the user know something went wrong, and poll for some new input */
|
|
OutputPromptMessage(GR_RESOLUTION_640x480,
|
|
curRes, curRefresh, numColorBuf, numAuxBuf,
|
|
vidTiming,
|
|
FXTRUE);
|
|
tlConRender();
|
|
grBufferSwap(1);
|
|
|
|
while(!tlKbHit() && !ProcessPromptKey(&frames, &curRes, &curRefresh,
|
|
&numColorBuf, &numAuxBuf,
|
|
vidTiming))
|
|
/* Do Nothing */;
|
|
|
|
/* Cleanup the error reporting and try again. */
|
|
grSstWinClose(0);
|
|
continue;
|
|
}
|
|
|
|
tlGetDimsByConst(curRes, &scrWidth, &scrHeight);
|
|
tlConSet(0.0f, 0.0f, 1.0f, 1.0f,
|
|
60, 30, 0xffffff);
|
|
|
|
grClipWindow(0, 0,(FxU32)scrWidth,(FxU32)scrHeight);
|
|
|
|
grReset(GR_VERTEX_PARAMETER);
|
|
grVertexLayout(GR_PARAM_XY, 0, GR_PARAM_ENABLE);
|
|
|
|
/* Turn on z-buffering if we have an aux buffer */
|
|
if (numAuxBuf != 0) {
|
|
grVertexLayout(GR_PARAM_Z, GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE);
|
|
grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
|
|
grDepthBufferFunction(GR_CMP_LESS);
|
|
grDepthMask(FXTRUE);
|
|
}
|
|
|
|
/* Mmmmm.... Gouraud triangles */
|
|
grVertexLayout(GR_PARAM_RGB, GR_VERTEX_R_OFFSET << 2, GR_PARAM_ENABLE);
|
|
grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
|
|
GR_COMBINE_FACTOR_NONE,
|
|
GR_COMBINE_LOCAL_ITERATED,
|
|
GR_COMBINE_OTHER_NONE,
|
|
FXFALSE);
|
|
|
|
{
|
|
GrVertex vtxA, vtxB, vtxC;
|
|
const float triEdge = MIN(scrWidth, scrHeight) / 2.0f;
|
|
const float sin60 = 0.8660254f;
|
|
const float baseXCoor = (triEdge / 2.0f);
|
|
const float baseYCoor = ((sin60 * triEdge) / 2.0f);
|
|
GrVertex templateA = {
|
|
0.f, /* x: - (triEdge / 2.0f) */
|
|
0.f, /* y: - ((sin60 * triEdge) / 2.0f) */
|
|
0.0f, /* z */
|
|
255.0f, /* r */
|
|
0.0f, /* g */
|
|
0.0f /* b */
|
|
};
|
|
GrVertex templateB = {
|
|
0.0f, /* x: (triEdge / 2.0f) */
|
|
0.0f, /* y: - ((sin60 * triEdge) / 2.0f) */
|
|
0.0f, /* z */
|
|
0.0f, /* r */
|
|
255.0f, /* g */
|
|
0.0f /* b */
|
|
};
|
|
GrVertex templateC = {
|
|
0.0f, /* x: 0.0f */
|
|
0.0f, /* y: ((sin60 * triEdge) / 2.0f) */
|
|
0.0f, /* z */
|
|
0.0f, /* r */
|
|
0.0f, /* g */
|
|
255.0f /* b */
|
|
};
|
|
|
|
templateA.x = -baseXCoor;
|
|
templateA.y = -baseYCoor;
|
|
|
|
templateB.x = baseXCoor;
|
|
templateB.y = -baseYCoor;
|
|
|
|
templateC.x = 0.0f;
|
|
templateC.y = baseYCoor;
|
|
|
|
while (frames != 0) {
|
|
#define kPi 3.14159f
|
|
static float t = 0.0f;
|
|
|
|
grBufferClear(0x00, 0x00, 0xFFFF);
|
|
|
|
{
|
|
static float zVal = 0.0f;
|
|
static float zDir = 1.0f;
|
|
|
|
vtxA = templateA;
|
|
vtxB = templateB;
|
|
vtxC = templateC;
|
|
|
|
if (zVal > 100.0f) {
|
|
zDir = -1.0f;
|
|
} else if (zVal < 1.0f) {
|
|
zDir = 1.0f;
|
|
}
|
|
zVal += zDir;
|
|
|
|
vtxA.z =
|
|
vtxB.z =
|
|
vtxC.z = zVal;
|
|
|
|
XLateTri(&vtxA, &vtxB, &vtxC,
|
|
-1.0f * t, 2.0f,
|
|
(scrWidth / 2.0f), (scrHeight / 2.0f), 0.0f);
|
|
grDrawTriangle(&vtxA, &vtxB, &vtxC);
|
|
}
|
|
|
|
{
|
|
vtxA = templateA;
|
|
vtxB = templateB;
|
|
vtxC = templateC;
|
|
|
|
vtxA.z = 1.0f;
|
|
vtxB.z = 100.0f;
|
|
vtxC.z = 100.0f;
|
|
|
|
XLateTri(&vtxA, &vtxB, &vtxC,
|
|
2.0f * t, 1.0f,
|
|
(scrWidth / 4.0f), 3.0f * (scrHeight / 4.0f), 0.0f);
|
|
grDrawTriangle(&vtxA, &vtxB, &vtxC);
|
|
}
|
|
|
|
{
|
|
vtxA = templateA;
|
|
vtxB = templateB;
|
|
vtxC = templateC;
|
|
|
|
vtxA.z = 100.0f;
|
|
vtxB.z = 1.0f;
|
|
vtxC.z = 100.0f;
|
|
|
|
XLateTri(&vtxA, &vtxB, &vtxC,
|
|
3.0f * t, 1.0f,
|
|
2.0f * (scrWidth / 4.0f), (scrHeight / 4.0f), 0.0f);
|
|
grDrawTriangle(&vtxA, &vtxB, &vtxC);
|
|
}
|
|
|
|
{
|
|
vtxA = templateA;
|
|
vtxB = templateB;
|
|
vtxC = templateC;
|
|
|
|
vtxA.z = 100.0f;
|
|
vtxB.z = 100.0f;
|
|
vtxC.z = 1.0f;
|
|
|
|
XLateTri(&vtxA, &vtxB, &vtxC,
|
|
4.0f * t, 1.0f,
|
|
3.0f * (scrWidth / 4.0f), 3.0f * (scrHeight / 4.0f), 0.0f);
|
|
grDrawTriangle(&vtxA, &vtxB, &vtxC);
|
|
}
|
|
|
|
/* Advance triangle rotation */
|
|
t += (kPi / 180.0f);
|
|
if (t >= (2.0f * kPi)) t = 0.0f;
|
|
|
|
OutputPromptMessage(curRes, curRes, curRefresh,
|
|
numColorBuf, numAuxBuf,
|
|
vidTiming,
|
|
FXFALSE);
|
|
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() && ProcessPromptKey(&frames, &curRes, &curRefresh,
|
|
&numColorBuf, &numAuxBuf,
|
|
vidTiming)) break;
|
|
if (frames > 0) frames--;
|
|
}
|
|
}
|
|
|
|
/* Start new refresh settings */
|
|
grSstWinClose(0);
|
|
}
|
|
}
|
|
|
|
grGlideShutdown();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
OutputPromptMessage(GrScreenResolution_t conRes,
|
|
GrScreenResolution_t res, GrScreenRefresh_t refresh,
|
|
int colorBuf, int auxBuf,
|
|
const FxVideoTimingInfo* vidTiming,
|
|
FxBool errorP)
|
|
{
|
|
/* Reset the console attributes so the text
|
|
* is always at the top of the screen.
|
|
*/
|
|
{
|
|
float scrWidth, scrHeight;
|
|
|
|
tlGetDimsByConst(conRes, &scrWidth, &scrHeight);
|
|
tlSetScreen(scrWidth, scrHeight);
|
|
tlConClear();
|
|
}
|
|
|
|
if (errorP) tlConOutput("Could not use Resolution/Refresh/Buffer combination.\n");
|
|
tlConOutput("ColorBuf:%d AuxBuf:%d\n",
|
|
colorBuf, auxBuf);
|
|
if (vidTiming == NULL) {
|
|
static const char* refreshStrings[] = {
|
|
"60", "70", "72", "75", "80", "90", "100", "85", "120"
|
|
};
|
|
tlConOutput("Res:(%s : 0x%X) Refresh:%s\n",
|
|
tlGetResolutionString(res), res, refreshStrings[refresh]);
|
|
tlConOutput("z - Resolution\n");
|
|
} else {
|
|
tlConOutput("Res:(%d x %d) Refresh:%d\n",
|
|
vidTiming->xDimension, vidTiming->yDimension,
|
|
vidTiming->refreshRate);
|
|
tlConOutput("x y - Resolution\n");
|
|
}
|
|
tlConOutput("f - Refresh rate\n");
|
|
tlConOutput("c - Color buffer\n");
|
|
tlConOutput("a - Aux Buffer\n");
|
|
tlConOutput("q - Quit\n");
|
|
}
|
|
|
|
static FxBool
|
|
ProcessPromptKey(int* frames,
|
|
GrScreenResolution_t* res,
|
|
GrScreenRefresh_t* refresh,
|
|
int* colorBuf,
|
|
int* auxBuf,
|
|
FxVideoTimingInfo* vidTiming)
|
|
{
|
|
int origKey = tlGetCH();
|
|
int keyHit = tolower(origKey);
|
|
FxI32 dir = ((origKey == keyHit) ? 1 : -1);
|
|
FxBool retVal = FXTRUE;
|
|
FxBool doVidTiming = FXFALSE;
|
|
|
|
switch(keyHit) {
|
|
case 'a':
|
|
*auxBuf += dir;
|
|
if (*auxBuf > 1) *auxBuf = 0;
|
|
if (*auxBuf < 0) *auxBuf = 1;
|
|
break;
|
|
|
|
case 'c':
|
|
*colorBuf += dir;
|
|
if (*colorBuf > 3) *colorBuf = 2;
|
|
if (*colorBuf < 2) *colorBuf = 3;
|
|
break;
|
|
|
|
case 'f':
|
|
if (vidTiming == NULL) {
|
|
*refresh += dir;
|
|
if (*refresh > GR_REFRESH_120Hz) *refresh = GR_REFRESH_60Hz;
|
|
if (*refresh < GR_REFRESH_60Hz) *refresh = GR_REFRESH_120Hz;
|
|
} else {
|
|
vidTiming->refreshRate += dir;
|
|
doVidTiming = FXTRUE;
|
|
}
|
|
break;
|
|
|
|
case 'q':
|
|
*frames = 0;
|
|
break;
|
|
|
|
case 'x':
|
|
case 'y':
|
|
case 'z':
|
|
if (vidTiming == NULL) {
|
|
*res += dir;
|
|
if (*res > GR_RESOLUTION_400x300) *res = GR_RESOLUTION_320x200;
|
|
if (*res < GR_RESOLUTION_320x200) *res = GR_RESOLUTION_400x300;
|
|
} else if (keyHit != 'z') {
|
|
FxU32* valChange = NULL;
|
|
|
|
switch(keyHit) {
|
|
case 'x':
|
|
valChange = &vidTiming->xDimension;
|
|
doVidTiming = FXTRUE;
|
|
break;
|
|
|
|
case 'y':
|
|
{
|
|
FxI32 num_boards;
|
|
valChange = &vidTiming->yDimension;
|
|
grGet(GR_NUM_FB, 4, &num_boards);
|
|
if (num_boards == 2) dir *= 2;
|
|
doVidTiming = FXTRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valChange != NULL) *valChange += dir;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
retVal = FXFALSE;
|
|
}
|
|
|
|
/* Re-compute the rest of the video timing structure. Don't blame
|
|
* me, this is a direct translation of the vesa timing spreadsheet
|
|
* that Scott gave me w/o all of the unused fields.
|
|
*/
|
|
if ((vidTiming != NULL) && doVidTiming) {
|
|
const FxU32 hGradient = 600;
|
|
const FxU32 hOffset = 40;
|
|
const FxU32 hTimeScale = 128;
|
|
const FxU32 hScale = 20;
|
|
const float floatTimeScale = ((hTimeScale == 0) ? 0.001f : (float)hTimeScale);
|
|
const float floatOffset = (((hOffset - hScale) * floatTimeScale / 256.0f) + hScale);
|
|
const float floatGradient = (floatTimeScale / 256.0f * hGradient);
|
|
const float estHPeriod = (((1.0f / vidTiming->refreshRate) - 550.0f / 1000000.0f) /
|
|
(vidTiming->yDimension + (2.0f * 0.0f) + 1.0f + 0.0f) *
|
|
1000000.0f);
|
|
const float linesSyncPorch = (float)floor(0.5f + (550.0f / estHPeriod));
|
|
const float linesBackPorch = linesSyncPorch - 3.0f;
|
|
const float linesField = (vidTiming->yDimension + linesSyncPorch + 1.0f);
|
|
const float estVFieldRate = (1.0f / estHPeriod / linesField * 1000000.0f);
|
|
const float actHPeriod = (estHPeriod / (vidTiming->refreshRate / estVFieldRate));
|
|
const float idealDutyCycle = floatOffset - (floatGradient * actHPeriod / 1000.0f);
|
|
const float blankingTimePixels = ((2.0f * 8.0f) *
|
|
(float)floor(0.5f + (vidTiming->xDimension *
|
|
idealDutyCycle /
|
|
(100.0f - idealDutyCycle) /
|
|
(2.0f * 8.0f))));
|
|
const float totalPixels = (vidTiming->xDimension + blankingTimePixels);
|
|
const float pixelFreq = (totalPixels / actHPeriod);
|
|
const float totalHTime = (float)floor(totalPixels / 8.0f);
|
|
const float syncWidthPixel = (float)floor(0.5f + (8.0f / 100.0f * totalPixels / 8.0f) * 8.0f);
|
|
const float frontPorch = (blankingTimePixels / 2.0f) - syncWidthPixel;
|
|
const float backPorch = frontPorch + syncWidthPixel;
|
|
const float syncWidthChar = syncWidthPixel / 8.0f;
|
|
const float backPorchChar = backPorch / 8.0f;
|
|
|
|
vidTiming->clkFreq16bpp = pixelFreq;
|
|
vidTiming->clkFreq24bpp = pixelFreq * 2.0f;
|
|
vidTiming->memOffset = (FxU32)(floor(0.5f + ((vidTiming->xDimension / 64.0f) + 0.99)) *
|
|
floor(0.5f + ((vidTiming->yDimension / 32.0f) + 0.99)));
|
|
vidTiming->tilesInX = (FxU32)(floor(0.5f + ((vidTiming->xDimension / 64.0f) + 0.99) * 2.0f));
|
|
|
|
vidTiming->hSyncOff = (FxU32)(((totalHTime - syncWidthChar) * 8.0f) - 1.0f);
|
|
vidTiming->hSyncOn = (FxU32)((syncWidthChar * 8.0f) - 1.0f);
|
|
vidTiming->hBackPorch = (FxU32)((backPorchChar * 8.0f) - 2.0f);
|
|
|
|
vidTiming->vSyncOff = (FxU32)(linesField - 3.0f);
|
|
vidTiming->vSyncOn = (FxU32)3.0f;
|
|
vidTiming->vBackPorch = (FxU32)linesBackPorch;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
static void
|
|
XLateTri(GrVertex* a, GrVertex* b, GrVertex* c,
|
|
const float theta, const float scale,
|
|
const float x, const float y, const float z)
|
|
{
|
|
GrVertex* vertList[3];
|
|
const float cosTheta = (const float)cos(theta);
|
|
const float sinTheta = (const float)sin(theta);
|
|
int i;
|
|
|
|
vertList[0] = a;
|
|
vertList[1] = b;
|
|
vertList[2] = c;
|
|
|
|
for(i = 0; i < sizeof(vertList) / sizeof(vertList[0]); i++) {
|
|
const GrVertex* curVertex = vertList[i];
|
|
GrVertex tempVert = *curVertex;
|
|
|
|
tempVert.x = ((scale * cosTheta * curVertex->x) +
|
|
(-sinTheta * curVertex->y) +
|
|
(0.0f * curVertex->z) +
|
|
(x * 1.0f));
|
|
|
|
tempVert.y = ((sinTheta * curVertex->x) +
|
|
(scale * cosTheta * curVertex->y) +
|
|
(0.0f * curVertex->z) +
|
|
(y * 1.0f));
|
|
|
|
tempVert.z = ((0.0f * curVertex->x) +
|
|
(0.0f * curVertex->y) +
|
|
(scale * 1.0f * curVertex->z) +
|
|
(0.0f * 1.0f));
|
|
tempVert.ooz = (1.0f * tempVert.z);
|
|
|
|
*vertList[i] = tempVert;
|
|
}
|
|
}
|