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
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 */
|