Leaked source code of windows server 2003
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.
 
 
 
 
 
 

988 lines
42 KiB

/******************************Module*Header*******************************\
* Module Name: mcdutil.h
*
* Include file which indirects all of the hardware-dependent functionality
* in the MCD driver code.
*
* Copyright (c) 1996 Microsoft Corporation
* Copyright (c) 1997 Cirrus Logic, Inc.
\**************************************************************************/
#ifndef _MCDUTIL_H
#define _MCDUTIL_H
#include <gl\gl.h>
VOID MCDrvDebugPrint(char *, ...);
#if DBG // this is defined in \ddk\inc\makefile.def
UCHAR *MCDDbgAlloc(UINT);
VOID MCDDbgFree(UCHAR *);
#define MCDAlloc MCDDbgAlloc
#define MCDFree MCDDbgFree
#define MCDBG_PRINT MCDrvDebugPrint
//#define MCDBG_PRINT
#define MCDFREE_PRINT MCDrvDebugPrint
//#define MCDFREE_PRINT
#else
UCHAR *MCDAlloc(UINT);
VOID MCDFree(UCHAR *);
#define MCDBG_PRINT
//#define MCDFREE_PRINT MCDrvDebugPrint
#define MCDFREE_PRINT
#endif
//#define MCDFORCE_PRINT MCDrvDebugPrint
#define MCDFORCE_PRINT
#define MCD_CHECK_RC(pRc)\
if (pRc == NULL) {\
MCDBG_PRINT("NULL device RC");\
return FALSE;\
}
#define MCD_CHECK_BUFFERS_VALID(pMCDSurface, pRc, resChangedRet)\
{\
DEVWND *pDevWnd = (DEVWND *)pMCDSurface->pWnd->pvUser;\
\
if (!pDevWnd) {\
MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: NULL buffers");\
return FALSE;\
}\
\
if ((pRc->backBufEnabled) &&\
(!pDevWnd->bValidBackBuffer)) {\
MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: back buffer invalid");\
return FALSE;\
}\
\
if ((pRc->zBufEnabled) &&\
(!pDevWnd->bValidZBuffer)) {\
MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: z buffer invalid");\
return FALSE;\
}\
\
if (pDevWnd->dispUnique != GetDisplayUniqueness((PDEV *)pMCDSurface->pso->dhpdev)) {\
MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: resolution changed but not updated");\
return resChangedRet;\
}\
}
#define CHK_TEX_KEY(pTex); \
if(pTex == NULL) { \
MCDBG_PRINT("CHK_TEX_KEY:Attempted to update a null texture"); \
return FALSE; \
} \
\
if(pTex->textureKey == 0) { \
MCDBG_PRINT("CHK_TEX_KEY:Attempted to update a null device texture");\
return FALSE; \
}
BOOL HWAllocResources(MCDWINDOW *pMCDWnd, SURFOBJ *pso, BOOL zEnabled,
BOOL backBufferEnabled);
VOID HWFreeResources(MCDWINDOW *pMCDWnd, SURFOBJ *pso);
VOID HWUpdateBufferPos(MCDWINDOW *pMCDWnd, SURFOBJ *pso, BOOL bForce);
ULONG __MCDLoadTexture(PDEV *ppdev, DEVRC *pRc);
POFMHDL __MCDForceTexture (PDEV *ppdev, SIZEL *mapsize, int alignflag, float priority);
VOID ContextSwitch(DEVRC *pRc);
// simple wait added for 546x
__inline void WAIT_HW_IDLE(PDEV *ppdev)
{
int status;
volatile int wait_count=0;
do
{
status = (*((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)) & 0x3FF) ^ 0x3E0;
// do something to give bus a breather
wait_count++;
} while((status & 0x3e0) != 0x3e0);
}
// From Tim McDonald concerning bits in status register, and checking that 2D is idle
// execution engine - 3d only, says poly is being assembled
// cmd fifo - could have 2d command about to be sent to 2d engine, so must be empty
// 2d engine - must be idle
// see include\laguna.h for MACRO display driver uses to make sure 3D idle before starting 2D
//#define WAIT_2D_STATUS_MASK 0x3e0 // wait for everything to stop
#define WAIT_2D_STATUS_MASK 0x300 // wait for 2D(BLT) engine to idle and CMD fifo to drain
// wait for 2D operations to end
__inline void WAIT_2D_IDLE(PDEV *ppdev)
{
int status;
volatile int wait_count=0;
do
{
status = (*((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)) & 0x3FF) ^ WAIT_2D_STATUS_MASK;
// do something to give bus a breather
wait_count++;
} while((status & WAIT_2D_STATUS_MASK) != WAIT_2D_STATUS_MASK);
}
__inline void HW_WAIT_DRAWING_DONE(DEVRC *pRc)
{
// MCD_NOTE just waits for all engines to stop...need to change for displists
WAIT_HW_IDLE (pRc->ppdev);
}
__inline void HW_INIT_DRAWING_STATE(MCDSURFACE *pMCDSurface, MCDWINDOW *pMCDWnd,
DEVRC *pRc)
{
DEVWND *pDevWnd = (DEVWND *)pMCDWnd->pvUser;
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
DWORD *pdwNext= ppdev->LL_State.pDL->pdwNext;
union {
TBase0Reg Base0;
DWORD dwBase0;
}b0;
union {
TBase1Reg Base1;
DWORD dwBase1;
}b1;
b0.dwBase0 = pDevWnd->dwBase0;
b1.dwBase1 = pDevWnd->dwBase1;
// if window changed, or if double buffered, but drawing to front,
// set base addresses for current window
/* since can have case of GL_FRONT, followed by GL_BACK, may need to reset for either case
* instead of testing, just set regs since tests as expensive as blind set (?) */
/*
if (pRc->pLastDevWnd != pDevWnd ||
((pRc->MCDState.drawBuffer == GL_FRONT) && pDevWnd->pohBackBuffer) )
*/
{
if ((pRc->MCDState.drawBuffer == GL_FRONT) && pDevWnd->pohBackBuffer)
{
// if double buffered window, pDevWnd->base0 and base1 always set for
// draw to back - override that here
b1.Base1.Color_Buffer_Y_Offset = 0;
b0.Base0.Color_Buffer_X_Offset = 0;
}
*pdwNext++ = write_register( BASE0_ADDR_3D, 2 );
*pdwNext++ = b0.dwBase0;
*pdwNext++ = b1.dwBase1;
ppdev->LL_State.pDL->pdwNext = pdwNext;
pRc->pLastDevWnd = pDevWnd;
}
// adjust pattern offset if stipple active and window has moved
if (pRc->privateEnables & __MCDENABLE_PG_STIPPLE)
{
if ((b0.Base0.Pattern_Y_Offset != (DWORD)(16-(pMCDSurface->pWnd->clientRect.top & 0xf) & 0xf)) ||
(b0.Base0.Pattern_X_Offset != (DWORD)(16-(pMCDSurface->pWnd->clientRect.left & 0xf) & 0xf)) )
{
b0.Base0.Pattern_Y_Offset = 16-(pMCDSurface->pWnd->clientRect.top & 0xf) & 0xf;
b0.Base0.Pattern_X_Offset = 16-(pMCDSurface->pWnd->clientRect.left & 0xf) & 0xf;
*pdwNext++ = write_register( BASE0_ADDR_3D, 1 );
*pdwNext++ = b0.dwBase0;
ppdev->LL_State.pDL->pdwNext = pdwNext;
}
}
if (!(pRc->privateEnables & (__MCDENABLE_PG_STIPPLE|__MCDENABLE_LINE_STIPPLE)) &&
(pRc->privateEnables & __MCDENABLE_DITHER))
{
// dither active - check if dither pattern needs to be adjusted
// Must keep pattern relative to x mod 4 = 0, y mod 4 = 0 for consistency
// Windowed draw buffers start at x=y=0. FullScreen buffers start at arbitrary
// window offset - so must adjust dither pattern for these cases
// (which means we may need to "un-adjust" for windowed buffer)
int windowed_buffer =
((pRc->MCDState.drawBuffer==GL_BACK) && (ppdev->pohBackBuffer!=pDevWnd->pohBackBuffer)) ? TRUE : FALSE;
if ( (!windowed_buffer && // need to adjust???
((pMCDSurface->pWnd->clientRect.left & 0x3) != ppdev->LL_State.dither_x_offset) ||
((pMCDSurface->pWnd->clientRect.top & 0x3) != ppdev->LL_State.dither_y_offset) )
||
(windowed_buffer && // need to un-adjust???
(ppdev->LL_State.dither_x_offset || ppdev->LL_State.dither_y_offset))
)
{
if (windowed_buffer)
{
// load default dither pattern
ppdev->LL_State.dither_array.pat[0] = ppdev->LL_State.dither_array.pat[4] = 0x04150415;
ppdev->LL_State.dither_array.pat[1] = ppdev->LL_State.dither_array.pat[5] = 0x62736273;
ppdev->LL_State.dither_array.pat[2] = ppdev->LL_State.dither_array.pat[6] = 0x15041504;
ppdev->LL_State.dither_array.pat[3] = ppdev->LL_State.dither_array.pat[7] = 0x73627362;
ppdev->LL_State.dither_x_offset = ppdev->LL_State.dither_y_offset = 0;
}
else
{
// adjustment required
int offset;
// adjust columns for X first...
offset = pMCDSurface->pWnd->clientRect.left & 0x3; // number of x positions
offset *= 4; // 4 bits per x position
ppdev->LL_State.dither_array.pat[0] = (0x04150415)>>offset;
ppdev->LL_State.dither_array.pat[0] |= ((0x0415) & (0xFFFF>>(16-offset))) << (32 - offset);
ppdev->LL_State.dither_array.pat[1] = (0x62736273)>>offset;
ppdev->LL_State.dither_array.pat[1] |= ((0x6273) & (0xFFFF>>(16-offset))) << (32 - offset);
ppdev->LL_State.dither_array.pat[2] = (0x15041504)>>offset;
ppdev->LL_State.dither_array.pat[2] |= ((0x1504) & (0xFFFF>>(16-offset))) << (32 - offset);
ppdev->LL_State.dither_array.pat[3] = (0x73627362)>>offset;
ppdev->LL_State.dither_array.pat[3] |= ((0x7362) & (0xFFFF>>(16-offset))) << (32 - offset);
// now adjust rows for y
// copy adjusted row to second half of pattern (which HW sees as repeat of first half)
switch (pMCDSurface->pWnd->clientRect.top & 0x3)
{
case 0:
ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[0];
ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[1];
ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[2];
ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[3];
break;
case 1:
ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[3];
ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[0];
ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[1];
ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[2];
break;
case 2:
ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[2];
ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[3];
ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[0];
ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[1];
break;
case 3:
ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[1];
ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[2];
ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[3];
ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[0];
break;
}
// copied adjusted pattern back to first 4 row
ppdev->LL_State.dither_array.pat[0] = ppdev->LL_State.dither_array.pat[4];
ppdev->LL_State.dither_array.pat[1] = ppdev->LL_State.dither_array.pat[5];
ppdev->LL_State.dither_array.pat[2] = ppdev->LL_State.dither_array.pat[6];
ppdev->LL_State.dither_array.pat[3] = ppdev->LL_State.dither_array.pat[7];
ppdev->LL_State.dither_x_offset = pMCDSurface->pWnd->clientRect.left & 0x3;
ppdev->LL_State.dither_y_offset = pMCDSurface->pWnd->clientRect.top & 0x3;
}
// force adjusted pattern to be loaded before use
ppdev->LL_State.pattern_ram_state = PATTERN_RAM_INVALID;
}
}
// Make sure 2D engine idle before continuing w/ 3D operations
WAIT_2D_IDLE(ppdev);
}
__inline void HW_FILL_RECT(MCDSURFACE *pMCDSurface, DEVRC *pRc, RECTL *pRecl, ULONG buffers)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
WORD FillValue;
DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
DWORD *pdwNext = ppdev->LL_State.pDL->pdwNext;
DWORD bltdef = 0x1070;
DWORD drawdef = 0x00cc;
DWORD blt_x;
DWORD blt_y;
DWORD ext_x;
DWORD ext_y;
WORD color_l;
WORD color_h;
MCDBG_PRINT("fill rect = %d, %d, %d, %d", pRecl->left,
pRecl->top,
pRecl->right,
pRecl->bottom);
// Since not much setup per blit, all work done here, rather than some in HW_START_FILL_RECT
if ((buffers & GL_DEPTH_BUFFER_BIT) && pRc->MCDState.depthWritemask)
{
MCDBG_PRINT("Z fill rect");
// calculate blt info in the y-dimension, which is constant regardless of pixel-depth
// see mcd.c near line 525 for more hints on z buffer location
blt_y = pRecl->top + pDevWnd->pohZBuffer->aligned_y;
ext_y = pRecl->bottom - pRecl->top + 1;
// QST: always 16bits (2 bytes) per pixel for z?? - z fill macro assumes so
// Z buffer always starts at 0 x offset
blt_x = pRecl->left * 2;
ext_x = (pRecl->right - pRecl->left + 1) * 2;
if (ppdev->pohZBuffer != pDevWnd->pohZBuffer)
{
// Z buffer is window size only, so remove client rectangle origin
blt_y -= pMCDSurface->pWnd->clientRect.top;
blt_x -= pMCDSurface->pWnd->clientRect.left*2;
}
FillValue = (WORD)(pRc->MCDState.depthClearValue);
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
// check for blackness fill: don't need to set bg color
if (FillValue == 0)
{
bltdef = 0x1101;
drawdef = 0x0000;
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 4, 0);
}
else
{
// break bg color into low and high for stuffing command register
color_h = FillValue;
color_l = FillValue;
// set up to write the 2d command register
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 6, 0);
*pdwNext++ = C_BG_L << 16 | color_l; // bgcolor l
*pdwNext++ = C_BG_H << 16 | color_h; // bgcolor h
ppdev->shadowBGCOLOR = 0xDEADBEEF;
}
// burst the blt data to the 2d command register
*pdwNext++ = C_BLTDEF << 16 | bltdef; // set bltdef register
*pdwNext++ = C_DRWDEF << 16 | drawdef; // set drawdef register
ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
*pdwNext++ = C_MRX_0 << 16 | blt_x; // x location: use byte pointer
*pdwNext++ = C_MRY_0 << 16 | blt_y; // y location: use byte pointer
// launch the blt by writing the extents
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, L2D_MBLTEXT_EX, 1, 0); // note pixel ptr
*pdwNext++ = ext_y << 16 | ext_x;
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
} // end Z clear
if (buffers & GL_COLOR_BUFFER_BIT)
{
RGBACOLOR scaledcolor;
DWORD color;
MCDBG_PRINT("colorbuf fill rect");
// calculate blt info in the y-dimension, which is constant regardless of pixel-depth
blt_y = pRecl->top;
if ((pRc->MCDState.drawBuffer != GL_FRONT) && pRc->backBufEnabled)
blt_y += pDevWnd->pohBackBuffer->aligned_y;
ext_y = pRecl->bottom - pRecl->top + 1;
// these are x y coordinates - hw converts to proper byte-equivalent locations
blt_x = pRecl->left;
ext_x = (pRecl->right - pRecl->left + 1);
if ((pRc->MCDState.drawBuffer != GL_FRONT) && pRc->backBufEnabled)
{
// back buffer not necessarily at 0 x offset
blt_x += pDevWnd->pohBackBuffer->aligned_x / ppdev->iBytesPerPixel;
if (ppdev->pohBackBuffer != pDevWnd->pohBackBuffer)
{
// Back buffer is window size only, so remove client rectangle origin
blt_y -= pMCDSurface->pWnd->clientRect.top;
blt_x -= pMCDSurface->pWnd->clientRect.left;
}
}
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
// macro converts components to 8.16 format
MCDFIXEDRGB(scaledcolor, pRc->MCDState.colorClearValue);
switch( ppdev->iBitmapFormat )
{
case BMF_8BPP:
color =((scaledcolor.r & 0xe00000) >> 16) | // 3 significant bits, shifted to bits 7 6 5
((scaledcolor.g & 0xe00000) >> 16+3) | // 3 significant bits, shifted to bits 4 3 2
((scaledcolor.b & 0xc00000) >> 16+3+3); // 2 significant bits, shifted to bits 1 0
// duplicate the 8-bit color value as a full 32-bit dword
color = color | (color << 8) | (color << 16) | (color << 24);
break;
case BMF_16BPP:
color =((scaledcolor.r & 0xf80000) >> 8) | // 5 significant bits, shifted to bits 15 - 11
((scaledcolor.g & 0xfc0000) >> 8+5) | // 6 significant bits, shifted to bits 10 - 5
((scaledcolor.b & 0xf80000) >> 8+5+6); // 5 significant bits, shifted to bits 4 - 0
// duplicate the 16-bit color value as a full 32-bit dword
color = color | (color << 16);
break;
case BMF_24BPP:
case BMF_32BPP:
color = (scaledcolor.r & 0xff0000) | // 8 significant bits
((scaledcolor.g & 0xff0000) >> 8) | // 8 significant bits, shifted to bits 15 - 8
((scaledcolor.b & 0xff0000) >> 16); // 8 significant bits, shifted to bits 7 - 0
break;
}
// break bg color into low and high for stuffing command register
color_h = (0xffff0000 & color) >> 16;
color_l = (WORD)(0x0000ffff & color);
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 2, 0);
*pdwNext++ = C_BG_L << 16 | color_l; // bgcolor l
*pdwNext++ = C_BG_H << 16 | color_h; // bgcolor h
ppdev->shadowBGCOLOR = 0xDEADBEEF;
// burst blt data to 2d command register
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 4, 0);
*pdwNext++ = C_BLTDEF << 16 | bltdef;
*pdwNext++ = C_DRWDEF << 16 | drawdef;
ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
*pdwNext++ = C_RX_0 << 16 | blt_x; // x location
*pdwNext++ = C_RY_0 << 16 | blt_y; // y location
// launch the blt by writing the extents
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, L2D_BLTEXT_EX, 1, 0);
*pdwNext++ = ext_y << 16 | ext_x;
// wait for everything to quit
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
}
// send data to hardware
if (pdwNext != ppdev->LL_State.pDL->pdwNext) _RunLaguna(ppdev,pdwNext);
}
__inline void HW_COPY_RECT(MCDSURFACE *pMCDSurface, RECTL *pRecl)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
ULONG FillValue;
DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
DWORD *pdwNext = ppdev->LL_State.pDL->pdwNext;
DWORD src_x=0, src_y=0;
DWORD dst_x=0, dst_y=0;
DWORD ext_x=0, ext_y=0;
DWORD bltdef=0;
MCDBG_PRINT("copy rect = %d, %d, %d, %d", pRecl->left,
pRecl->top,
pRecl->right,
pRecl->bottom);
{
RGBACOLOR scaledcolor;
DWORD color;
// calculate blt info in the y-dimension, which is constant regardless of pixel-depth
dst_y = pRecl->top;
src_y = dst_y + pDevWnd->pohBackBuffer->aligned_y;
ext_y = pRecl->bottom - pRecl->top;
// these are x y coordinates - hw converts to proper byte-equivalent locations
dst_x = pRecl->left;
// back buffer may be at same y loc's as front, but offset to right
src_x = dst_x + (pDevWnd->pohBackBuffer->aligned_x / ppdev->iBytesPerPixel);
ext_x = pRecl->right - pRecl->left;
if (ppdev->pohBackBuffer != pDevWnd->pohBackBuffer)
{
// back buffer is window size only, so remove client rectangle origin
// front buffer is always relative to screen origin, so leave dest alone
src_y -= pMCDSurface->pWnd->clientRect.top;
src_x -= pMCDSurface->pWnd->clientRect.left;
}
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
// program frame->frame blt
bltdef |= 0x1010;
// set up blitter: check for display list
#if DRIVER_5465 // C_BLTX moved between 64 and 65, so converted to write extents more like fill proc
// leaving old code for 5464 - even though never enable on real product
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 6, 0);
*pdwNext++ = C_BLTDEF << 16 | bltdef; // set bltdef register
*pdwNext++ = C_DRWDEF << 16 | 0x00cc; // set drawdef register
ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
*pdwNext++ = C_RX_1 << 16 | src_x; // use PIXEL pointer for source x
*pdwNext++ = C_RY_1 << 16 | src_y; // use PIXEL pointer for source y
*pdwNext++ = C_RX_0 << 16 | dst_x; // set dest x always as pixel ptr
*pdwNext++ = C_RY_0 << 16 | dst_y; // set dest y always as pixel ptr
// launch the blt by writing the extents
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, L2D_BLTEXT_EX, 1, 0);
*pdwNext++ = ext_y << 16 | ext_x;
#else
*pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 9, 0);
*pdwNext++ = C_BLTDEF << 16 | bltdef; // set bltdef register
*pdwNext++ = C_DRWDEF << 16 | 0x00cc; // set drawdef register
ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
*pdwNext++ = C_RX_1 << 16 | src_x; // use PIXEL pointer for source x
*pdwNext++ = C_RY_1 << 16 | src_y; // use PIXEL pointer for source y
*pdwNext++ = C_RX_0 << 16 | dst_x; // set dest x always as pixel ptr
*pdwNext++ = C_RY_0 << 16 | dst_y; // set dest y always as pixel ptr
*pdwNext++ = C_BLTX << 16 | ext_x; // set x extent
*pdwNext++ = C_BLTY << 16 | ext_y; // set y extent
*pdwNext++ = C_EX_BLT << 16 | 0; // execute the blt
#endif
// wait for everything to quit
*pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
}
// send data to hardware
_RunLaguna(ppdev,pdwNext);
}
__inline int __MCDSetTextureRegisters(DEVRC *pRc)
{
PDEV *ppdev = pRc->ppdev;
unsigned int *pdwNext = ppdev->LL_State.pDL->pdwNext;
LL_Texture *pTex;
int control0_set=FALSE;
union {
TTxCtl0Reg TxControl0; // Tx_Ctl0_3D temp register
DWORD dwTxControl0;
} Tx;
// Set the texture control register with the texture information - start
// with the cleared register and build up info as needed
//
Tx.dwTxControl0 = pRc->dwTxControl0 & ~0x00640FFF;
pTex = pRc->pLastTexture;
// punt if clamp and linear filtering - in this case, BorderColor should be
// used for blend with portion where clamp is in effect, but 5465/5466/5468 has no
// support for border colors
if ( ((pTex->dwTxCtlBits & (CLMCD_TEX_U_SATURATE|CLMCD_TEX_FILTER)) == (CLMCD_TEX_U_SATURATE|CLMCD_TEX_FILTER)) ||
((pTex->dwTxCtlBits & (CLMCD_TEX_V_SATURATE|CLMCD_TEX_FILTER)) == (CLMCD_TEX_V_SATURATE|CLMCD_TEX_FILTER)) )
{
return (FALSE);
}
//MCD_NOTE2: for true Compliance, don't define TREAT_DECAL_LIKE_REPLACE and DONT_PUNT_MODULATE_W_BLEND
//MCD_NOTE2: below. However, without DONT_PUNT_MODULATE_W_BLEND defined, GLQuake
//MCD_NOTE2: punts the "sparkly chaff" textures.
// When DECAL with RGBA texture and BLEND active, theoretically, we should punt,
// but recall Microsoft's behavior on tlogo:
// - it looked like they treat DECAL like REPLACE in case of RGBA textures,
// so let's do same
//#define TREAT_DECAL_LIKE_REPLACE
// GLQuake using GL_MODULATE, with RGBA textures, with lots of blending
#define DONT_PUNT_MODULATE_W_BLEND
// determine if texture format requires blend capability hw doesn't have
if ( (pRc->privateEnables & (__MCDENABLE_BLEND|__MCDENABLE_FOG)) &&
pTex->bAlphaInTexture &&
#ifndef TREAT_DECAL_LIKE_REPLACE
#ifndef DONT_PUNT_MODULATE_W_BLEND
(pRc->MCDTexEnvState.texEnvMode != GL_REPLACE) )
#else // ndef DONT_PUNT_MODULATE_W_BLEND
(pRc->MCDTexEnvState.texEnvMode != GL_REPLACE) &&
(pRc->MCDTexEnvState.texEnvMode != GL_MODULATE) )
#endif // DONT_PUNT_MODULATE_W_BLEND
#else
(pRc->MCDTexEnvState.texEnvMode != GL_REPLACE) &&
#ifdef DONT_PUNT_MODULATE_W_BLEND
(pRc->MCDTexEnvState.texEnvMode != GL_MODULATE) &&
#endif // ndef DONT_PUNT_MODULATE_W_BLEND
(pRc->MCDTexEnvState.texEnvMode != GL_DECAL) )
#endif
{
return (FALSE);
}
#ifndef TREAT_DECAL_LIKE_REPLACE
if ((pRc->MCDTexEnvState.texEnvMode == GL_DECAL) && pTex->bAlphaInTexture )
{
// decal mode and texture has RGBA or BGRA
// will use alpha circuit for blending texel with polyeng, using alpha in texture
if( pRc->Control0.Alpha_Mode != LL_ALPHA_TEXTURE )
{
pRc->Control0.Alpha_Mode = LL_ALPHA_TEXTURE;
control0_set=TRUE;
}
if( pRc->Control0.Alpha_Dest_Color_Sel != LL_ALPHA_DEST_INTERP )
{
pRc->Control0.Alpha_Dest_Color_Sel = LL_ALPHA_DEST_INTERP;
control0_set=TRUE;
}
if (!pRc->Control0.Alpha_Blending_Enable)
{
pRc->Control0.Alpha_Blending_Enable = TRUE;
control0_set=TRUE;
}
}
#endif
// decal mode without alpha in texture, or replace mode - set alpha regs back for "normal" use
// (previous primitive may have used alpha regs for decal w/ alpha)
#ifndef TREAT_DECAL_LIKE_REPLACE
if ( ((pRc->MCDTexEnvState.texEnvMode == GL_DECAL) && !pTex->bAlphaInTexture) ||
#else
if ( ((pRc->MCDTexEnvState.texEnvMode == GL_DECAL)) ||
#endif
#ifdef DONT_PUNT_MODULATE_W_BLEND
(pRc->MCDTexEnvState.texEnvMode == GL_MODULATE) ||
#endif // DONT_PUNT_MODULATE_W_BLEND
(pRc->MCDTexEnvState.texEnvMode == GL_REPLACE))
{
// alpha circuit will be set as required for normal (blend|fog)
// note that __MCDPickRenderingFuncs will have set up for punt if current
// blend/fog mode not supported in hw
if (pRc->privateEnables & (__MCDENABLE_BLEND|__MCDENABLE_FOG))
{
if ((pRc->privateEnables & __MCDENABLE_BLEND) &&
pTex->bAlphaInTexture)
{
// case of GL_REPLACE and texture has alpha - use texture's alpha
if( pRc->Control0.Alpha_Mode != LL_ALPHA_TEXTURE )
{
pRc->Control0.Alpha_Mode = LL_ALPHA_TEXTURE;
control0_set=TRUE;
}
}
else
{
if( pRc->Control0.Alpha_Mode != LL_ALPHA_INTERP )
{
pRc->Control0.Alpha_Mode = LL_ALPHA_INTERP;
control0_set=TRUE;
}
}
if (pRc->privateEnables & __MCDENABLE_BLEND)
{
if( pRc->Control0.Alpha_Dest_Color_Sel != LL_ALPHA_DEST_FRAME )
{
pRc->Control0.Alpha_Dest_Color_Sel = LL_ALPHA_DEST_FRAME;
control0_set=TRUE;
}
}
else
{
// for fog dest_color is const and alpha values are coord's "fog" value
if( pRc->Control0.Alpha_Dest_Color_Sel != LL_ALPHA_DEST_CONST )
{
pRc->Control0.Alpha_Dest_Color_Sel = LL_ALPHA_DEST_CONST;
control0_set=TRUE;
}
// fog color already loaded into color0 register by __MCDPickRenderingFuncs
}
if (!pRc->Control0.Alpha_Blending_Enable)
{
pRc->Control0.Alpha_Blending_Enable = TRUE;
control0_set=TRUE;
}
}
else
{
// alpha blend not used, so turn off if currently on
if (pRc->Control0.Alpha_Blending_Enable)
{
pRc->Control0.Alpha_Blending_Enable = FALSE;
control0_set=TRUE;
}
}
}
pRc->texture_width = pTex->fWidth;
if (pRc->privateEnables & __MCDENABLE_1D_TEXTURE)
{
// set factors to make v always 0 in parameterization code
pRc->texture_height = (float)0.0;
}
else
{
pRc->texture_height = pTex->fHeight;
}
if (pTex->dwTxCtlBits & CLMCD_TEX_FILTER)
{
pRc->texture_bias = (float)-0.5;
}
else
{
pRc->texture_bias = (float)0.0;
}
// MCD_NOTE: allowing filtering with Decal - broke on 5464, fixed on 5465(?)
Tx.dwTxControl0 |= pTex->dwTxCtlBits &
( CLMCD_TEX_FILTER
| CLMCD_TEX_U_SATURATE|CLMCD_TEX_V_SATURATE
| CLMCD_TEX_DECAL|CLMCD_TEX_DECAL_POL
//QST: MCD doesn't use CLMCD_TEX_DECAL_INTERP? (currently disabled)
/*| CLMCD_TEX_DECAL_INTERP*/ );
Tx.TxControl0.Texel_Mode = pTex->bType;
Tx.TxControl0.Tex_U_Address_Mask = pTex->bSizeMask & 0xF;
Tx.TxControl0.Tex_V_Address_Mask = pTex->bSizeMask >> 4;
#if 0 // QST: support texture palette???
Tx.TxControl0.Texel_Lookup_En = pTex->fIndexed;
Tx.TxControl0.CLUT_Offset = pTex->bLookupOffset;
#endif //
// masking only meaningful if texture has alpha
if ((pRc->privateEnables & __MCDENABLE_TEXTUREMASKING) && pTex->bAlphaInTexture)
{
Tx.TxControl0.Tex_Mask_Enable=1;
// polarity set to 1 in MCDrvCreateContext and stays that way
}
// Two kinds of textures: those residing in the video memory and
// those rendered from the system memory. They need different setup.
//
#ifdef MCD_SUPPORTS_HOST_TEXTURES
if( pTex->dwFlags & TEX_IN_SYSTEM )
{
DWORD dwOffset;
printf(" Polys.c - tex in system id=%d\n",pBatch->wBuf);
// Texture is in the system memory, so set the location
//
if( LL_State.Base0.Texture_Location != 1 )
{
LL_State.Base0.Texture_Location = 1;
*pdwNext++ = write_register( BASE0_ADDR_3D, 1 );
*pdwNext++ = LL_State.dwBase0;
}
// Set the host access base address and texture map offset
//
dwOffset = (DWORD)pTex->dwAddress - (DWORD)LL_State.Tex.Mem[pTex->bMem].dwAddress;
if( LL_State.dwHXY_Base1_Address_Ptr != LL_State.Tex.Mem[pTex->bMem].dwPhyPtr ||
LL_State.dwHXY_Base1_Offset0 != dwOffset )
{
// Check if only the offset must be reloaded (this is most likely)
//
if( LL_State.dwHXY_Base1_Address_Ptr == LL_State.Tex.Mem[pTex->bMem].dwPhyPtr )
{
*pdwNext++ = write_dev_register( HOST_XY, HXY_BASE1_OFFSET0_3D, 1 );
*pdwNext++ = LL_State.dwHXY_Base1_Offset0 = dwOffset;
}
else
{
*pdwNext++ = write_dev_register( HOST_XY, HXY_BASE1_ADDRESS_PTR_3D, 2 );
*pdwNext++ = LL_State.dwHXY_Base1_Address_Ptr = LL_State.Tex.Mem[pTex->bMem].dwPhyPtr;
*pdwNext++ = LL_State.dwHXY_Base1_Offset0 = dwOffset;
}
}
// Set host control enable bit if necessary
//
if( LL_State.HXYHostControl.HostXYEnable != 1 )
{
LL_State.HXYHostControl.HostXYEnable = 1;
*pdwNext++ = write_dev_register( HOST_XY, HXY_HOST_CTRL_3D, 1 );
*pdwNext++ = LL_State.dwHXYHostControl;
}
*pdwNext++ = write_register( TX_CTL0_3D, 1 );
*pdwNext++ = LL_State.dwTxControl0 = Tx.dwTxControl0 & TX_CTL0_MASK;
}
else
#endif // def MCD_SUPPORTS_HOST_TEXTURES
{
// Texture is in the video memory, so set the location
//
// texture base init'd to RDRAM in LL_InitLib
#ifdef MCD_SUPPORTS_HOST_TEXTURES
if( ppdev->LL_State.Base0.Texture_Location != 0 )
{
ppdev->LL_State.Base0.Texture_Location = 0;
*pdwNext++ = write_register( BASE0_ADDR_3D, 1 );
*pdwNext++ = ppdev->LL_State.dwBase0;
}
#endif
// Set the coordinates of the texture
if( pRc->TxXYBase.Tex_Y_Base_Addr != pTex->wYloc ||
pRc->TxXYBase.Tex_X_Base_Addr != pTex->wXloc )
{
// New location, need to reload tx_xybase_3d register and perhaps control register
//
*pdwNext++ = write_register( TX_CTL0_3D, 2 );
*pdwNext++ = pRc->dwTxControl0 = Tx.dwTxControl0 & TX_CTL0_MASK;
*pdwNext++ = (pTex->wYloc << 16) | pTex->wXloc;
pRc->TxXYBase.Tex_Y_Base_Addr = pTex->wYloc;
pRc->TxXYBase.Tex_X_Base_Addr = pTex->wXloc;
}
else
{
*pdwNext++ = write_register( TX_CTL0_3D, 1 );
*pdwNext++ = pRc->dwTxControl0 = Tx.dwTxControl0 & TX_CTL0_MASK;
}
}
if (control0_set)
{
*pdwNext++ = write_register( CONTROL0_3D, 1 );
*pdwNext++ = pRc->dwControl0;
}
ppdev->LL_State.pDL->pdwNext = pdwNext;
return(TRUE);
}
__inline ULONG GetDisplayUniqueness(PDEV *ppdev)
{
return (ppdev->iUniqueness);
}
#define SET_HW_CLIP_REGS(pRc,pdwNext) { \
*pdwNext++ = write_register( X_CLIP_3D, 2 ); \
*pdwNext++ = ((pClip->right +pRc->AdjClip.right) <<16) | (pClip->left+pRc->AdjClip.left)| 0x80008000; \
*pdwNext++ = ((pClip->bottom+pRc->AdjClip.bottom)<<16) | (pClip->top +pRc->AdjClip.top) | 0x80008000; \
}
// verify MCDTextureData in client space is accessible
#define VERIFY_TEXTUREDATA_ACCESSIBLE(pTex){ \
try { \
EngProbeForRead(pTex->pMCDTextureData, sizeof(MCDTEXTUREDATA), 4); \
} except (EXCEPTION_EXECUTE_HANDLER) { \
MCDBG_PRINT("!!Exception accessing MCDTextureData in client address space!!"); \
return FALSE; \
} \
}
// verify struct addressed by MCDTextureData->level in client space is accessible
#define VERIFY_TEXTURELEVEL_ACCESSIBLE(pTex){ \
try { \
EngProbeForRead(pTex->pMCDTextureData->level, sizeof(MCDMIPMAPLEVEL), 4); \
} except (EXCEPTION_EXECUTE_HANDLER) { \
MCDBG_PRINT("!!Exception accessing MCDTextureData->level in client address space!!"); \
return FALSE; \
} \
}
// verify struct addressed by MCDTextureData->paletteData in client space is accessible
#define VERIFY_TEXTUREPALETTE8_ACCESSIBLE(pTex){ \
try { \
EngProbeForRead(pTex->pMCDTextureData->paletteData, 256*4, 4);/* 256 bytes for 8 bit indices */ \
} except (EXCEPTION_EXECUTE_HANDLER) { \
MCDBG_PRINT("!!Exception accessing MCDTextureData->paletteData in client address space!!"); \
return FALSE; \
} \
}
// verify struct addressed by MCDTextureData->paletteData in client space is accessible
#define VERIFY_TEXTUREPALETTE16_ACCESSIBLE(pTex){ \
try { \
EngProbeForRead(pTex->pMCDTextureData->paletteData, 65536*4, 4);/* 16K bytes for 16 bit indices */ \
} except (EXCEPTION_EXECUTE_HANDLER) { \
MCDBG_PRINT("!!Exception accessing MCDTextureData->paletteData in client address space!!"); \
return FALSE; \
} \
}
#define ENGPROBE_ALIGN_BYTE 1
#define ENGPROBE_ALIGN_WORD 2
#define ENGPROBE_ALIGN_DWORD 4
// verify struct addressed by MCDTextureData->paletteData in client space is accessible
#define VERIFY_TEXELS_ACCESSIBLE(pTexels,nBytes,Align){ \
try { \
EngProbeForRead(pTexels, nBytes, Align); \
} except (EXCEPTION_EXECUTE_HANDLER) { \
MCDBG_PRINT("!!Exception accessing MCDTextureData->level->pTexels in client address space!!"); \
return FALSE; \
} \
}
#define _3D_ENGINE_NOT_READY_FOR_MORE 0x040 // wait for execution engine idle
#define USB_TIMEOUT_FIX(ppdev) \
{ \
if (ppdev->dwDataStreaming) \
{ \
int status; \
volatile int wait_count=0; \
do \
{ \
status = *((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)); \
wait_count++; /* do something to give bus a breather */ \
wait_count++; /* do something to give bus a breather */ \
wait_count++; /* do something to give bus a breather */ \
} while(status & _3D_ENGINE_NOT_READY_FOR_MORE); \
} \
}
#endif /* _MCDUTIL_H */