You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
11 KiB
356 lines
11 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: mcdline.c
|
|
*
|
|
* Contains all of the line-rendering routines for the Cirrus Logic 546X MCD driver.
|
|
*
|
|
* (based on mcdline.c from NT4.0 DDK)
|
|
*
|
|
* Copyright (c) 1996 Microsoft Corporation
|
|
* Copyright (c) 1997 Cirrus Logic, Inc.
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#include "mcdhw.h"
|
|
#include "mcdutil.h"
|
|
#include "mcdmath.h"
|
|
|
|
//#undef CHECK_FIFO_FREE
|
|
//#define CHECK_FIFO_FREE
|
|
|
|
#define EXCHANGE(i,j) \
|
|
{ \
|
|
ptemp=i; \
|
|
i=j; j=ptemp; \
|
|
}
|
|
|
|
|
|
VOID FASTCALL __MCDRenderLine(DEVRC *pRc, MCDVERTEX *a, MCDVERTEX *b, BOOL resetLine)
|
|
{
|
|
ULONG clipNum;
|
|
RECTL *pClip;
|
|
|
|
LONG lCoord;
|
|
|
|
PDEV *ppdev = pRc->ppdev;
|
|
unsigned int *pdwNext = ppdev->LL_State.pDL->pdwNext;
|
|
void *ptemp; // for EXCHANGE and ROTATE_L macros
|
|
|
|
// output queue stuff...
|
|
DWORD *pSrc;
|
|
DWORD *pDest = ppdev->LL_State.pRegs + HOST_3D_DATA_PORT;
|
|
DWORD *pdwStart = ppdev->LL_State.pDL->pdwStartOutPtr;
|
|
|
|
DWORD dwFlags=0; // MCD_TEMP - dwflags initialized to 0
|
|
DWORD *dwOrig; /* Temp display list pointer */
|
|
DWORD dwOpcode; // Built opcode
|
|
float frecip_step;
|
|
float v1red,v1grn,v1blu;
|
|
LONG ax, bx, ay, by;
|
|
|
|
// FUTURE - do something with resetLine input to line render proc
|
|
|
|
if ((clipNum = pRc->pEnumClip->c) > 1) {
|
|
pClip = &pRc->pEnumClip->arcl[0];
|
|
SET_HW_CLIP_REGS(pRc,pdwNext);
|
|
pClip++;
|
|
}
|
|
|
|
// window coords are float values, and need to have
|
|
// viewportadjust (MCDVIEWPORT) values subtracted to get to real screen space
|
|
|
|
// color values are 0->1 floats and must be multiplied by scale values (MCDRCINFO)
|
|
// to get to nbits range (scale = 0xff for 8 bit, 0x7 for 3 bit, etc.)
|
|
|
|
// Z values are 0->1 floats and must be multiplied by zscale values (MCDRCINFO)
|
|
|
|
|
|
// Exchange the pointers to vertices if the second point
|
|
// of the line is above the first one
|
|
//
|
|
pRc->pvProvoking = a; // keep track of original first for possible flat shading
|
|
if( a->windowCoord.y > b->windowCoord.y )
|
|
{
|
|
EXCHANGE(a,b);
|
|
}
|
|
|
|
|
|
// Store the first address for the opcode
|
|
//
|
|
dwOrig = pdwNext;
|
|
|
|
pdwNext += 3;
|
|
|
|
// Start with a plain line instruction (no modifiers)
|
|
// and assume same color. Also add three words for DDA
|
|
// line parameters + count (they can not be avoided)
|
|
//
|
|
dwOpcode = LINE | SAME_COLOR | (2+3);
|
|
|
|
// Set flags as requested from the dwFlags field of a batch.
|
|
// These bits have 1-1 correspondence to their instruction
|
|
// counterparts.
|
|
//
|
|
// Flags : LL_DITHER - Use dither pattern
|
|
// LL_PATTERN - Draw pattern
|
|
// LL_STIPPLE - Use stipple mask
|
|
// LL_LIGHTING - Do lighting
|
|
// LL_Z_BUFFER - Use Z buffer
|
|
// FETCH_COLOR - Appended for alpha blending
|
|
// LL_GOURAUD - Use Gouraud shading
|
|
// LL_TEXTURE - Texture mapping
|
|
//
|
|
|
|
/*
|
|
dwOpcode |= dwFlags &
|
|
( LL_DITHER | LL_PATTERN | LL_STIPPLE
|
|
| LL_LIGHTING | LL_Z_BUFFER | FETCH_COLOR
|
|
| LL_GOURAUD | LL_TEXTURE );
|
|
*/
|
|
dwOpcode |= pRc->privateEnables & (__MCDENABLE_SMOOTH|__MCDENABLE_Z);
|
|
|
|
if (pRc->privateEnables & __MCDENABLE_LINE_STIPPLE)
|
|
{
|
|
dwOpcode |= LL_STIPPLE;
|
|
}
|
|
else
|
|
{
|
|
// can dither only if no stipple
|
|
dwOpcode |= (pRc->privateEnables & __MCDENABLE_DITHER) ;
|
|
}
|
|
|
|
if( !(dwFlags & LL_SAME_COLOR) )
|
|
{
|
|
register DWORD color;
|
|
|
|
|
|
// Clear same_color flag
|
|
//
|
|
dwOpcode ^= LL_SAME_COLOR;
|
|
|
|
// If the line is shaded, the starting color that should
|
|
// be set is the topmost point (pVert1)
|
|
if (pRc->privateEnables & __MCDENABLE_SMOOTH)
|
|
{
|
|
v1red = a->colors[0].r * pRc->rScale;
|
|
*pdwNext = FTOL(v1red);
|
|
|
|
v1grn = a->colors[0].g * pRc->gScale;
|
|
v1blu = a->colors[0].b * pRc->bScale;
|
|
*(pdwNext+1) = FTOL(v1grn);
|
|
*(pdwNext+2) = FTOL(v1blu);
|
|
|
|
dwOpcode += 3;
|
|
pdwNext += 3;
|
|
}
|
|
else
|
|
{
|
|
MCDCOLOR *pColor = &pRc->pvProvoking->colors[0];
|
|
|
|
*pdwNext = FTOL(pColor->r * pRc->rScale);
|
|
|
|
*(pdwNext+1) = FTOL(pColor->g * pRc->gScale);
|
|
*(pdwNext+2) = FTOL(pColor->b * pRc->bScale);
|
|
|
|
dwOpcode += 3;
|
|
pdwNext += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Set the parameters of a line slope and count
|
|
// Note: line can only go down, so dy is always positive
|
|
//
|
|
{
|
|
int dx, dy, abs_dx, xdir;
|
|
|
|
// Well ordered points - set starting point1 coords
|
|
// using a pointer to the origin of the instruction
|
|
//
|
|
|
|
ax = FTOL(a->windowCoord.x);
|
|
lCoord = ax + pRc->xOffset;
|
|
*(dwOrig+1) = (DWORD) (lCoord << 16 );
|
|
|
|
ay = FTOL(a->windowCoord.y);
|
|
lCoord = ay + pRc->yOffset;
|
|
*(dwOrig+2) = (DWORD) (lCoord << 16 );
|
|
|
|
bx = FTOL(b->windowCoord.x);
|
|
by = FTOL(b->windowCoord.y);
|
|
|
|
// dx = x2 - x1,
|
|
// dy = y2 - y1 (always positive)
|
|
//
|
|
dx = bx - ax;
|
|
dy = by - ay;
|
|
|
|
// NOTE that dx and dy are in 32.0 format (LL3D has them in 16.16)
|
|
// so math below differs from LL3D
|
|
|
|
// make sure dx is positive, and setup xdir needed for x major since we're
|
|
// already doing the compare here to prevent having to do again for x major case
|
|
if (dx < 0)
|
|
{
|
|
abs_dx = -dx;
|
|
xdir = 0xffff0000;
|
|
}
|
|
else
|
|
{
|
|
abs_dx = dx;
|
|
xdir = 0x00010000;
|
|
}
|
|
|
|
if( abs_dx > dy )
|
|
{
|
|
// X-major
|
|
//
|
|
|
|
// compute slope with positive dx
|
|
frecip_step = ppdev->frecips[abs_dx];
|
|
|
|
*(pdwNext + 0) = xdir;
|
|
*(pdwNext + 1) = abs_dx;
|
|
// *(pdwNext + 2) = (double)dy / (double)ABS(dx) * 65536.0;
|
|
*(pdwNext + 2) = FTOL(dy * frecip_step * (float)65536.0); // equivalent to above
|
|
}
|
|
else
|
|
{
|
|
// Y-major
|
|
//
|
|
frecip_step = ppdev->frecips[dy];
|
|
|
|
*(pdwNext + 1) = dy; // Positive count always, by virtue of earlier EXCHANGE
|
|
*(pdwNext + 2) = 0x10000; // dy = 1
|
|
// *(pdwNext + 0) = (double)dx / (double)dy * 65536.0;
|
|
*(pdwNext + 0) = FTOL(dx * frecip_step * (float)65536.0); // equivalent to above
|
|
}
|
|
|
|
pdwNext += 3;
|
|
}
|
|
|
|
if (pRc->privateEnables & __MCDENABLE_SMOOTH)
|
|
{
|
|
float tmp;
|
|
|
|
// Calculate and set the color gradients
|
|
//
|
|
tmp = ((b->colors[0].r * pRc->rScale) - v1red) * frecip_step;
|
|
*pdwNext++ = FTOL(tmp);
|
|
|
|
tmp = ((b->colors[0].g * pRc->gScale) - v1grn) * frecip_step;
|
|
*pdwNext++ = FTOL(tmp);
|
|
|
|
tmp = ((b->colors[0].b * pRc->bScale) - v1blu) * frecip_step;
|
|
*pdwNext++ = FTOL(tmp);
|
|
|
|
// Increase count field by 6 for DR_MAIN_3D, DG_MAIN_3D,
|
|
// DB_MAIN_3D and DR_ORTHO_3D, DG_ORTHO_3D, DB_ORTHO_3D
|
|
//
|
|
dwOpcode += 3;
|
|
}
|
|
|
|
|
|
if( pRc->privateEnables & __MCDENABLE_Z)
|
|
{
|
|
float fdz_main = (b->windowCoord.z - a->windowCoord.z) * pRc->zScale * frecip_step;
|
|
|
|
*pdwNext++ = FTOL(a->windowCoord.z * pRc->zScale);
|
|
*pdwNext++ = FTOL(fdz_main);
|
|
|
|
// Increase count field by 2 for Z_3D, DZ_MAIN_3D
|
|
//
|
|
dwOpcode += 2;
|
|
}
|
|
|
|
|
|
#if 0
|
|
if( dwFlags & LL_TEXTURE )
|
|
{
|
|
...
|
|
...
|
|
...
|
|
}
|
|
|
|
|
|
#endif
|
|
if (pRc->privateEnables & (__MCDENABLE_BLEND|__MCDENABLE_FOG))
|
|
{
|
|
float v1alp,tmp;
|
|
|
|
if (pRc->privateEnables & __MCDENABLE_BLEND)
|
|
{
|
|
// recall that if both blending and fog active, all prims punted back to software
|
|
v1alp = a->colors[0].a * pRc->aScale;
|
|
*(pdwNext+0) = FTOL(v1alp);
|
|
tmp = ((b->colors[0].a * pRc->aScale) - v1alp) * frecip_step;
|
|
*(pdwNext+1) = FTOL(tmp);
|
|
}
|
|
else
|
|
{
|
|
v1alp = a->fog * (float)16777215.0; // convert from 0->1.0 val to 0->ff.ffff val
|
|
*(pdwNext+0) = FTOL(v1alp);
|
|
tmp = ((b->fog * (float)16777215.0) - v1alp) * frecip_step;
|
|
*(pdwNext+1) = FTOL(tmp);
|
|
}
|
|
|
|
*(pdwNext+0) &= 0x00ffff00;// bits 31->24 and 7->0 reserved
|
|
*(pdwNext+1) &= 0xffffff00;// bits 7->0 reserved
|
|
|
|
dwOpcode += ( FETCH_COLOR | ALPHA + 2 );
|
|
pdwNext += 2;
|
|
|
|
}
|
|
|
|
// Store the final opcode
|
|
//
|
|
*dwOrig = dwOpcode;
|
|
|
|
while (--clipNum) {
|
|
int len = (dwOpcode & 0x3F) + 1; // num words for line primitive
|
|
SET_HW_CLIP_REGS(pRc,pdwNext)
|
|
pClip++;
|
|
|
|
// dump same line regs again to draw while clipping against occlusion rectangle
|
|
pSrc = dwOrig;
|
|
|
|
while( len-- ) *pdwNext++ = *pSrc++;
|
|
}
|
|
|
|
|
|
// output queued data here....
|
|
#if 0 // FUTURE - enable queueing algorithm - just outputting everything for now
|
|
OUTPUT_COPROCMODE_QUEUE
|
|
#else // 0
|
|
{
|
|
pSrc = pdwStart;
|
|
while (pSrc != pdwNext)
|
|
{
|
|
/* Get the amount of data for this opcode */
|
|
int len = (*pSrc & 0x3F) + 1;
|
|
|
|
USB_TIMEOUT_FIX(ppdev)
|
|
|
|
while( len-- ) *pDest = *pSrc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
ppdev->LL_State.pDL->pdwNext = ppdev->LL_State.pDL->pdwStartOutPtr = pdwStart;
|
|
|
|
}
|
|
|
|
|
|
VOID FASTCALL __MCDRenderGenLine(DEVRC *pRc, MCDVERTEX *pv1, MCDVERTEX *pv2, BOOL resetLine)
|
|
{
|
|
// MGA and S3 MCD's have no code in this proc
|
|
MCDBG_PRINT("__MCDRenderGenLine - EMPTY ROUTINE");
|
|
|
|
}
|
|
|
|
|
|
|