|
|
/******************************Module*Header**********************************\
* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * !! !! * !! WARNING: NOT DDK SAMPLE CODE !! * !! !! * !! This source code is provided for completeness only and should not be !! * !! used as sample code for display driver development. Only those sources !! * !! marked as sample code for a given driver component should be used for !! * !! development purposes. !! * !! !! * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * Module Name: hwcontxt.c * * Content: Manages hardware context switching between GDI/DD/D3D * * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved. \*****************************************************************************/
#include "glint.h"
#include "dma.h"
#include "tag.h"
//-----------------------------------------------------------------------------
//
// Driver Version
//
// This helps us find out from the debugger what driver is loaded on a given
// remote system
//
//-----------------------------------------------------------------------------
char gc_DriverVersion[] = #if DX8_DDI
" DX8" #else
" DX7" #endif
#if DBG
" CHECKED DRIVER" #else
" FREE DRIVER" #endif
" In Path: " __FILE__ " Compiled on Date: " __DATE__ " Time: " __TIME__ " With #defines: " " DX8_MULTSTREAMS: " #if DX8_MULTSTREAMS
"1" #else
"0" #endif
" DX8_VERTEXSHADERS: " #if DX8_VERTEXSHADERS
"1" #else
"0" #endif
" DX8_POINTSPRITES: " #if DX8_POINTSPRITES
"1" #else
"0" #endif
" DX8_PIXELSHADERS: " #if DX8_PIXELSHADERS
"1" #else
"0" #endif
" DX8_3DTEXTURES: " #if DX8_3DTEXTURES
"1" #else
"0" #endif
" DX8_MULTISAMPLING: " #if DX8_MULTISAMPLING
"1" #else
"0" #endif
" DX7_ANTIALIAS: " #if DX7_ANTIALIAS
"1" #else
"0" #endif
" DX7_D3DSTATEBLOCKS: " #if DX7_D3DSTATEBLOCKS
"1" #else
"0" #endif
" DX7_PALETTETEXTURE: " #if DX7_PALETTETEXTURE
"1" #else
"0" #endif
" DX7_STEREO: " #if DX7_STEREO
"1" #else
"0" #endif
" DX7_TEXMANAGEMENT: " #if DX7_TEXMANAGEMENT
"1" #else
"0" #endif
;
//-----------------------------------------------------------------------------
//
// __HWC_SwitchToDX
//
// Writes any hardware registers that need updating on entry into the
// DirectX driver, which are appropriate to both DirectDraw and Direct3D.
//
//-----------------------------------------------------------------------------
void __HWC_SwitchToDX( P3_THUNKEDDATA* pThisDisplay, BOOL bDXEntry) { P3_DMA_DEFS();
P3_DMA_GET_BUFFER_ENTRIES(4);
SEND_P3_DATA(SizeOfFramebuffer, pThisDisplay->pGLInfo->ddFBSize >> 4);
// We have entered the DirectX driver from a
// foreign context (such as the display driver)
if (bDXEntry) { //@@BEGIN_DDKSPLIT
#if DX7_VERTEXBUFFERS
// First cause a flush of all buffers
// We know this is safe because the contex switch
// from the other driver to here will have caused a sync
// and the buffers must therefore have been consumed
// therefore we call with bWait == FALSE
_D3D_EB_FlushAllBuffers(pThisDisplay, FALSE); #endif //DX7_VERTEXBUFFERS
//@@END_DDKSPLIT
// Reset the hostin ID
SEND_P3_DATA(HostInID, 0); pThisDisplay->dwCurrentSequenceID = 0; }
P3_DMA_COMMIT_BUFFER();
if (bDXEntry) { P3_DMA_GET_BUFFER_ENTRIES( 4 );
// Reset the RenderID to the last-used one.
SEND_HOST_RENDER_ID ( GET_HOST_RENDER_ID() ); P3_DMA_FLUSH_BUFFER();
// Need to push the render ID to the end of the pipe...
SYNC_WITH_GLINT;
// ...and now it's valid.
pThisDisplay->bRenderIDValid = (DWORD)TRUE;
} } // __HWC_SwitchToDX
//-----------------------------------------------------------------------------
//
// HWC_SwitchToDDRAW
//
// Writes any hardware registers that need updating on entry into the
// DirectX driver, which are appropriate specifically to DirectDraw
//
//-----------------------------------------------------------------------------
void HWC_SwitchToDDRAW( P3_THUNKEDDATA* pThisDisplay, BOOL bDXEntry) { P3_DMA_DEFS();
__HWC_SwitchToDX(pThisDisplay, bDXEntry);
P3_DMA_GET_BUFFER();
P3_ENSURE_DX_SPACE(32); WAIT_FIFO(32);
// Disable various units
SEND_P3_DATA(AreaStippleMode, __PERMEDIA_DISABLE); SEND_P3_DATA(LineStippleMode, __PERMEDIA_DISABLE); SEND_P3_DATA(ScissorMode, __PERMEDIA_DISABLE); SEND_P3_DATA(ColorDDAMode, __PERMEDIA_DISABLE); SEND_P3_DATA(FogMode, __PERMEDIA_DISABLE); SEND_P3_DATA(AntialiasMode, __PERMEDIA_DISABLE); SEND_P3_DATA(AlphaTestMode, __PERMEDIA_DISABLE); SEND_P3_DATA(Window, __PERMEDIA_DISABLE); SEND_P3_DATA(StencilMode, __PERMEDIA_DISABLE); SEND_P3_DATA(DepthMode, __PERMEDIA_DISABLE); SEND_P3_DATA(DitherMode, __PERMEDIA_DISABLE); SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE); SEND_P3_DATA(StatisticMode, __PERMEDIA_DISABLE); SEND_P3_DATA(FilterMode, __PERMEDIA_DISABLE);
P3_ENSURE_DX_SPACE(30); WAIT_FIFO(30);
// Frame buffer
SEND_P3_DATA(FBSourceData, __PERMEDIA_DISABLE); SEND_P3_DATA(FBHardwareWriteMask, __GLINT_ALL_WRITEMASKS_SET); SEND_P3_DATA(FBSoftwareWriteMask, __GLINT_ALL_WRITEMASKS_SET); SEND_P3_DATA(FBWriteMode, __PERMEDIA_ENABLE);
// We sometimes use the scissor in DDRAW to scissor out unnecessary pixels.
SEND_P3_DATA(ScissorMinXY, 0); SEND_P3_DATA(ScissorMaxXY, (pThisDisplay->cyMemory << 16) | (pThisDisplay->cxMemory) ); SEND_P3_DATA(ScreenSize, (pThisDisplay->cyMemory << 16) | (pThisDisplay->cxMemory) ); SEND_P3_DATA(WindowOrigin, 0x0);
// DirectDraw might not need to set these up
SEND_P3_DATA(dXDom, 0x0); SEND_P3_DATA(dXSub, 0x0); SEND_P3_DATA(dY, 1 << 16);
P3_ENSURE_DX_SPACE(32); WAIT_FIFO(32); SEND_P3_DATA(GIDMode, __PERMEDIA_DISABLE); SEND_P3_DATA(YUVMode, __PERMEDIA_DISABLE);
// Delta Unit
SEND_P3_DATA(DeltaControl, 0); SEND_P3_DATA(DeltaMode, __PERMEDIA_DISABLE);
SEND_P3_DATA(FBSourceReadMode, __PERMEDIA_DISABLE); SEND_P3_DATA(FBDestReadMode, __PERMEDIA_DISABLE); SEND_P3_DATA(FBDestReadEnables, __PERMEDIA_DISABLE);
// DDraw driver code doesn't want offsets
SEND_P3_DATA(LBSourceReadBufferOffset, 0); SEND_P3_DATA(LBDestReadBufferOffset, 0); SEND_P3_DATA(LBWriteBufferOffset, 0); SEND_P3_DATA(FBWriteBufferOffset0, 0); SEND_P3_DATA(FBDestReadBufferOffset0, 0); SEND_P3_DATA(FBSourceReadBufferOffset, 0);
P3_ENSURE_DX_SPACE(12); WAIT_FIFO(12); // Local buffer
SEND_P3_DATA(LBSourceReadMode, __PERMEDIA_DISABLE); SEND_P3_DATA(LBDestReadMode, __PERMEDIA_DISABLE); SEND_P3_DATA(LBWriteMode, __PERMEDIA_DISABLE); SEND_P3_DATA(LBWriteFormat, __PERMEDIA_DISABLE);
// Blending
SEND_P3_DATA(AlphaBlendAlphaMode, __PERMEDIA_DISABLE); SEND_P3_DATA(AlphaBlendColorMode, __PERMEDIA_DISABLE);
P3_ENSURE_DX_SPACE(32); WAIT_FIFO(32); // Texturing (disable)
SEND_P3_DATA(TextureReadMode0, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureReadMode1, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureIndexMode0, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureIndexMode1, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureCoordMode, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureApplicationMode, __PERMEDIA_DISABLE); SEND_P3_DATA(ChromaTestMode, __PERMEDIA_DISABLE); SEND_P3_DATA(TextureFilterMode, __PERMEDIA_DISABLE); SEND_P3_DATA(LUTTransfer, __PERMEDIA_DISABLE); SEND_P3_DATA(LUTIndex, __PERMEDIA_DISABLE); SEND_P3_DATA(LUTAddress, __PERMEDIA_DISABLE); SEND_P3_DATA(LUTMode, __PERMEDIA_DISABLE);
SEND_P3_DATA(RasterizerMode, __PERMEDIA_DISABLE);
// Router setup. DDRAW doesn't care about Z Writes
SEND_P3_DATA(RouterMode, __PERMEDIA_ENABLE);
P3_DMA_COMMIT_BUFFER();
} //HWC_SwitchToDDRAW
//-----------------------------------------------------------------------------
//
// HWC_SwitchToD3D
//
// Writes any hardware registers that need updating on entry into the
// DirectX driver, which are appropriate specifically to Direct3D
//
//-----------------------------------------------------------------------------
void HWC_SwitchToD3D( P3_D3DCONTEXT *pContext, P3_THUNKEDDATA* pThisDisplay, BOOL bDXEntry) { P3_SOFTWARECOPY* pSoftPermedia = &pContext->SoftCopyGlint; int i; P3_DMA_DEFS();
// Switch first to the common DX/DDraw/D3D setup
__HWC_SwitchToDX(pThisDisplay, bDXEntry);
P3_DMA_GET_BUFFER();
#if DBG
ASSERTDD(IS_DXCONTEXT_CURRENT(pThisDisplay), "ERROR: DX Context not current in HWC_SwitchToDDRAW!"); if ( ((ULONG_PTR)dmaPtr >= (ULONG_PTR)pThisDisplay->pGlint->GPFifo) && ((ULONG_PTR)dmaPtr <= (ULONG_PTR)pThisDisplay->pGlint->GPFifo + 4000) ) { ASSERTDD(pThisDisplay->pGLInfo->InterfaceType != GLINT_DMA, "Error: In FIFO space and setup for DMA"); } else { ASSERTDD(pThisDisplay->pGLInfo->InterfaceType == GLINT_DMA, "Error: In DMA space and setup for FIFO's"); } #endif
// Now we restore default values and restore D3D context dependent settings
// directly from what we stored in our context structure.
// Common registers
P3_ENSURE_DX_SPACE(32); WAIT_FIFO(16); SEND_P3_DATA(WindowOrigin, 0); SEND_P3_DATA(AreaStippleMode, 1); COPY_P3_DATA(DitherMode, pSoftPermedia->DitherMode);
WAIT_FIFO(16); COPY_P3_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode); COPY_P3_DATA(Window, pSoftPermedia->PermediaWindow); #if DX8_DDI
SEND_P3_DATA(FBHardwareWriteMask, pContext->dwColorWriteHWMask); SEND_P3_DATA(FBSoftwareWriteMask, pContext->dwColorWriteSWMask); #else
SEND_P3_DATA(FBHardwareWriteMask, pContext->RenderStates[D3DRENDERSTATE_PLANEMASK]); SEND_P3_DATA(FBSoftwareWriteMask, __GLINT_ALL_WRITEMASKS_SET); #endif
SEND_P3_DATA(FilterMode, __PERMEDIA_DISABLE);
// Force the flat stippled alpha renderers to reload
// the stipple pattern if needed.
P3_ENSURE_DX_SPACE(32); // First 16 Stipple registers
WAIT_FIFO(32); for( i = 0; i < 16; i++ ) { SEND_P3_DATA_OFFSET( AreaStipplePattern0, (DWORD)pContext->CurrentStipple[i], i ); } P3_ENSURE_DX_SPACE(32); // Second set of 16 Stipple registers
WAIT_FIFO(32); // (loaded separately to have GVX1 compatibilty)
for( i = 16; i < 32; i++ ) { SEND_P3_DATA_OFFSET( AreaStipplePattern0, (DWORD)pContext->CurrentStipple[i], i ); }
P3_ENSURE_DX_SPACE(32); WAIT_FIFO(32);
SEND_P3_DATA(GIDMode, 0);
// Don't want offsets
SEND_P3_DATA(LBSourceReadBufferOffset, 0); SEND_P3_DATA(LBDestReadBufferOffset, 0); SEND_P3_DATA(LBWriteBufferOffset, 0); SEND_P3_DATA(FBWriteBufferOffset0, 0); SEND_P3_DATA(FBDestReadBufferOffset0, 0); SEND_P3_DATA(FBSourceReadBufferOffset, 0);
// Frame buffer
SEND_P3_DATA(FBSourceReadMode, __PERMEDIA_DISABLE); SEND_P3_DATA(FBDestReadMode, __PERMEDIA_DISABLE); SEND_P3_DATA(FBDestReadEnables, __PERMEDIA_DISABLE);
SEND_P3_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
SEND_P3_DATA(GIDMode, __PERMEDIA_DISABLE); SEND_P3_DATA(YUVMode, __PERMEDIA_DISABLE);
// Frame buffer
COPY_P3_DATA(FBWriteMode, pSoftPermedia->P3RXFBWriteMode);
// Delta
COPY_P3_DATA(DeltaMode, pSoftPermedia->P3RX_P3DeltaMode); COPY_P3_DATA(DeltaControl, pSoftPermedia->P3RX_P3DeltaControl);
P3_ENSURE_DX_SPACE(32); WAIT_FIFO(32);
SEND_P3_DATA(XBias, *(DWORD*)&pContext->XBias); SEND_P3_DATA(YBias, *(DWORD*)&pContext->YBias);
// Disable chroma tests
SEND_P3_DATA(ChromaTestMode, __PERMEDIA_DISABLE);
// Router setup
SEND_P3_DATA(RouterMode, __PERMEDIA_ENABLE);
SEND_P3_DATA( VertexTagList0, V0FloatX_Tag ); SEND_P3_DATA( VertexTagList1, V0FloatY_Tag ); SEND_P3_DATA( VertexTagList2, V0FloatZ_Tag ); SEND_P3_DATA( VertexTagList3, V0FloatQ_Tag ); SEND_P3_DATA( VertexTagList4, V0FloatPackedColour_Tag ); SEND_P3_DATA( VertexTagList5, V0FloatPackedSpecularFog_Tag ); SEND_P3_DATA( VertexTagList6, V0FloatS_Tag ); SEND_P3_DATA( VertexTagList7, V0FloatT_Tag ); SEND_P3_DATA( VertexTagList8, V0FloatS1_Tag ); SEND_P3_DATA( VertexTagList9, V0FloatT1_Tag );
// Restore the texturecachereplacement mode.
COPY_P3_DATA(TextureCacheReplacementMode, pSoftPermedia->P3RXTextureCacheReplacementMode);
SEND_P3_DATA( ProvokingVertexMask, 0xfff );
P3_ENSURE_DX_SPACE(8); WAIT_FIFO(8);
COPY_P3_DATA( LineStippleMode, pSoftPermedia->PXRXLineStippleMode);
P3_DMA_COMMIT_BUFFER();
//@@BEGIN_DDKSPLIT
// azn - is this really necessary???
//@@END_DDKSPLIT
// This will cause the FVF state to be recalculated
ZeroMemory(&pContext->FVFData, sizeof(FVFOFFSETS));
// Force everything to be set up again before rendering
DIRTY_EVERYTHING(pContext);
} // HWC_SwitchToD3D
//-----------------------------------------------------------------------------
//
// HWC_SwitchToFIFO
//
// Allows us to switch from DMA mode to FIFO transfers
//
//-----------------------------------------------------------------------------
void HWC_SwitchToFIFO( P3_THUNKEDDATA* pThisDisplay, LPGLINTINFO pGLInfo ) { P3_DMA_DEFS();
if (pGLInfo->InterfaceType != GLINT_NON_DMA) { DISPDBG((WRNLVL,"Switching to 4K Funny FIFO Memory")); P3_DMA_GET_BUFFER(); P3_DMA_FLUSH_BUFFER(); SYNC_WITH_GLINT; pGLInfo->InterfaceType = GLINT_NON_DMA; pGLInfo->CurrentBuffer = (ULONG *)pThisDisplay->pGlint->GPFifo; } else { // This means we already are in FIFO mode
DISPDBG((DBGLVL,"NOT Switching to 4K Funny FIFO Memory")); } } // HWC_SwitchToFIFO
//-----------------------------------------------------------------------------
//
// HWC_SwitchToDMA
//
// Allows us to switch from FIFO transfers to DMA mode
//
//-----------------------------------------------------------------------------
void HWC_SwitchToDMA( P3_THUNKEDDATA* pThisDisplay, LPGLINTINFO pGLInfo ) {
if (pGLInfo->InterfaceType != GLINT_DMA) { DISPDBG((WRNLVL,"Switching to DMA buffers")); SYNC_WITH_GLINT;
pGLInfo->InterfaceType = GLINT_DMA; pGLInfo->CurrentBuffer = pGLInfo->DMAPartition[pGLInfo->CurrentPartition].VirtAddr; } else { DISPDBG((WRNLVL,"NOT Switching to DMA buffers")); } } // HWC_SwitchToDMA
//-----------------------------------------------------------------------------
//
// __HWC_RecalculateDXDMABuffers
//
// Run through the OpanGL buffer mask to determine which remaining piece of
// buffer is the biggest and setup DirectX to use this buffer.
//
//-----------------------------------------------------------------------------
void __HWC_RecalculateDXDMABuffers( P3_THUNKEDDATA* pThisDisplay) { DWORD dwSize, i; LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo;
if (pGLInfo->InterfaceType != GLINT_DMA) { // exit if we are not using DMA
return; }
// Just use the entire DMA Buffer.
pThisDisplay->DMAInfo.dwBuffSize = pThisDisplay->pGLInfo->dw3DDMABufferSize; pThisDisplay->DMAInfo.dwBuffPhys = pThisDisplay->pGLInfo->dw3DDMABufferPhys; pThisDisplay->DMAInfo.dwBuffVirt = pThisDisplay->pGLInfo->dw3DDMABufferVirt; DISPDBG((DBGLVL,"__HWC_RecalculateDXDMABuffers V:0x%p P:0x%x S:0x%x", pThisDisplay->DMAInfo.dwBuffVirt, pThisDisplay->DMAInfo.dwBuffPhys, pThisDisplay->DMAInfo.dwBuffSize));
dwSize = ((DWORD)(pThisDisplay->DMAInfo.dwBuffSize) / (DWORD)pGLInfo->NumberOfSubBuffers); dwSize = ((dwSize + 3) & ~3);
pThisDisplay->PartitionSize = dwSize / sizeof(DWORD);
DISPDBG((DBGLVL,"Got Buffer with 0x%x Sub Buffers", pGLInfo->NumberOfSubBuffers));
for (i = 0; i < pGLInfo->NumberOfSubBuffers; i++) { pGLInfo->DMAPartition[i].VirtAddr = (ULONG *)((char*)(pThisDisplay->DMAInfo.dwBuffVirt) + (i * dwSize)); pGLInfo->DMAPartition[i].PhysAddr = (DWORD)((pThisDisplay->DMAInfo.dwBuffPhys) + (i * dwSize)); pGLInfo->DMAPartition[i].MaxAddress = (ULONG_PTR)pGLInfo->DMAPartition[i].VirtAddr + dwSize; pGLInfo->DMAPartition[i].Locked = FALSE;
DISPDBG((DBGLVL," Partition%d: VirtAddr = 0x%x, " " PhysAddr = 0x%x, MaxAddres = 0x%x", i, pGLInfo->DMAPartition[i].VirtAddr, pGLInfo->DMAPartition[i].PhysAddr, pGLInfo->DMAPartition[i].MaxAddress));
#if DBG
pGLInfo->DMAPartition[i].bStampedDMA = TRUE; //@@BEGIN_DDKSPLIT
#if 0
//azn hard to say in 64 bits!
memset((void*)pGLInfo->DMAPartition[i].VirtAddr, 0x4D, (pGLInfo->DMAPartition[i].MaxAddress - pGLInfo->DMAPartition[i].VirtAddr)); #endif
//@@END_DDKSPLIT
#endif
}
pGLInfo->CurrentBuffer = pGLInfo->DMAPartition[pGLInfo->CurrentPartition].VirtAddr; } // __HWC_RecalculateDXDMABuffers
//-----------------------------------------------------------------------------
//
// HWC_StartDMA
//
//-----------------------------------------------------------------------------
DWORD WINAPI HWC_StartDMA( P3_THUNKEDDATA* pThisDisplay, DWORD dwContext, DWORD dwSize, DWORD dwPhys, ULONG_PTR dwVirt, DWORD dwEvent) { LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo;
ASSERTDD( (int)dwSize > 0, "DMA buffer size non-positive" );
ASSERTDD((IS_DXCONTEXT_CURRENT(pThisDisplay) && (pGLInfo->InterfaceType == GLINT_DMA)), "Error, Trying DMA when not setup for it!" );
#if W95_DDRAW
ASSERTDD( pGLInfo->endIndex != 0, "Trying DMA with zero sub-buffers" ); #endif
#if DBG
pGLInfo->DMAPartition[pGLInfo->CurrentPartition].bStampedDMA = FALSE; #endif
#ifdef W95_DDRAW
ASSERTDD(pThisDisplay->pGLInfo->dwCurrentContext != CONTEXT_DISPLAY_HANDLE, "HWC_StartDMA: In display driver context" )
ASSERTDD( pThisDisplay->pGlint->FilterMode == 0, "FilterMode non-zero" ); #endif
#if WNT_DDRAW
DDSendDMAData(pThisDisplay->ppdev, dwPhys, dwVirt, dwSize); #else
StartDMAProper(pThisDisplay, pGLInfo, dwPhys, dwVirt, dwSize); #endif
DISPDBG((DBGLVL, "HWC_StartDMA sent %d dwords", dwSize));
return GLDD_SUCCESS; } // HWC_StartDMA
//-----------------------------------------------------------------------------
//
// HWC_AllocDMABuffer
//
//-----------------------------------------------------------------------------
void HWC_AllocDMABuffer( P3_THUNKEDDATA* pThisDisplay) { LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo; int i; DWORD bDMA = TRUE; BOOL bRet; DWORD Result;
// Empty the DMA partition slots
for (i = 0; i < MAX_SUBBUFFERS; i++) { pGLInfo->DMAPartition[i].PhysAddr = 0; pGLInfo->DMAPartition[i].VirtAddr = 0; pGLInfo->DMAPartition[i].MaxAddress = 0; }
#if WNT_DDRAW
// DMA turned off
bDMA = FALSE; #else
// Are we allowed to DMA?
bRet = GET_REGISTRY_ULONG_FROM_STRING("Direct3DHAL.NoDMA", &Result); if ((bRet && (Result != 0)) || (pThisDisplay->pGLInfo->dw3DDMABufferSize == 0)) { bDMA = FALSE; } #endif
// Find out how many sub buffers the user wants.
bRet = GET_REGISTRY_ULONG_FROM_STRING("Direct3DHAL.SubBuffers", &Result); if ((Result == 0) || (bRet == FALSE)) { // Default
pGLInfo->NumberOfSubBuffers = DEFAULT_SUBBUFFERS; } else { if (Result > MAX_SUBBUFFERS) { pGLInfo->NumberOfSubBuffers = MAX_SUBBUFFERS; } else { pGLInfo->NumberOfSubBuffers = Result; } if (pGLInfo->NumberOfSubBuffers < 2) { pGLInfo->NumberOfSubBuffers = 2; } }
// if no interrupt driven DMA or asked for less than 3 buffers then
// configure no Q for this context
if ((pGLInfo->dwFlags & GMVF_NOIRQ) || (pGLInfo->NumberOfSubBuffers < 2)) { pGLInfo->NumberOfSubBuffers = 2; }
DISPDBG((DBGLVL,"Setting 0x%x Sub Buffers", pGLInfo->NumberOfSubBuffers));
// Initialise for no DMA if DMA has been turned off for whatever reason
if (!bDMA) { DISPDBG((WRNLVL,"Using 4K Funny FIFO Memory")); pGLInfo->InterfaceType = GLINT_NON_DMA; pThisDisplay->StartDMA = 0; pGLInfo->NumberOfSubBuffers = 0;
pGLInfo->CurrentBuffer = (ULONG *)pThisDisplay->pGlint->GPFifo;
pThisDisplay->b2D_FIFOS = TRUE; } else { // DMA Setup
pGLInfo->InterfaceType = GLINT_DMA; pThisDisplay->StartDMA = HWC_StartDMA;
// This call will actually setup the partitions
__HWC_RecalculateDXDMABuffers(pThisDisplay);
// Is DirectDraw DMA disabled?
bRet = GET_REGISTRY_ULONG_FROM_STRING("Direct3DHAL.No2DDMA", &Result); if (bRet && (Result == 1)) { pThisDisplay->b2D_FIFOS = TRUE; } else { pThisDisplay->b2D_FIFOS = FALSE; } } #if W95_DDRAW
// Store the end index in the context.
SetEndIndex(pGLInfo, CONTEXT_DIRECTX_HANDLE, (unsigned short)pGLInfo->NumberOfSubBuffers); #endif // W95_DDRAW
if (pGLInfo->InterfaceType == GLINT_NON_DMA) { DISPDBG((WRNLVL,"DDRAW: Using FIFO's")); } else { DISPDBG((WRNLVL,"DDRAW: Using DMA")); } } // HWC_AllocDMABuffer
//-----------------------------------------------------------------------------
//
// HWC_FlushDXBuffer
//
//-----------------------------------------------------------------------------
void HWC_FlushDXBuffer( P3_THUNKEDDATA* pThisDisplay ) { LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo;
if( pGLInfo->InterfaceType == GLINT_DMA ) { DWORD Send; P3_DMAPartition *pCurrDMAPartition;
pCurrDMAPartition = &(pGLInfo->DMAPartition[pGLInfo->CurrentPartition]);
//@@BEGIN_DDKSPLIT
// azn - we might lose 64 bit precision here!
//@@END_DDKSPLIT
Send = (DWORD)(pGLInfo->CurrentBuffer - pCurrDMAPartition->VirtAddr) / sizeof(DWORD);
if( Send ) { ASSERTDD( Send < 0x10000, "Wacky DMA size" );
((__StartDMA)pThisDisplay->StartDMA) (pThisDisplay, CONTEXT_DIRECTX_HANDLE, Send, (DWORD)(pCurrDMAPartition->PhysAddr), (ULONG_PTR)(pCurrDMAPartition->VirtAddr), 0); pGLInfo->CurrentPartition++;
if (pGLInfo->CurrentPartition == pGLInfo->NumberOfSubBuffers) { pGLInfo->CurrentPartition = 0; }
ASSERTDD(!pGLInfo->DMAPartition[pGLInfo->CurrentPartition].Locked, "Partition already locked" ); }
pGLInfo->CurrentBuffer = pGLInfo->DMAPartition[pGLInfo->CurrentPartition].VirtAddr; } else { pGLInfo->CurrentBuffer = (ULONG *)pThisDisplay->pGlint->GPFifo; } } // HWC_FlushDXBuffer
#if DBG
//-----------------------------------------------------------------------------
//
// HWC_GetDXBuffer
//
//-----------------------------------------------------------------------------
void HWC_GetDXBuffer( P3_THUNKEDDATA* pThisDisplay, char *file, int line ) { LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo; ASSERTDD( pGLInfo->dwFlags & GMVF_GCOP, "VDD not locked out" );
ASSERTDD( !pThisDisplay->BufferLocked, "Buffer already locked" );
pThisDisplay->BufferLocked = TRUE;
#ifdef WANT_DMA
if(( pGLInfo->endIndex > 2 ) && !IS_DXCONTEXT_CURRENT(pThisDisplay)) { ASSERTDD( pGLInfo->CurrentBuffer == pGLInfo->DMAPartition[pGLInfo->CurrentPartition].VirtAddr, "Trying to DMA in display driver context" ); } #endif
DISPDBG(( DBGLVL, "HWC_GetDXBuffer: %s %d: Curr part %d, dmaPtr 0x%08x", file, line, pGLInfo->CurrentPartition, pGLInfo->CurrentBuffer ));
if (pGLInfo->InterfaceType == GLINT_DMA) { DISPDBG(( DBGLVL, "HWC_GetDXBuffer: %d dwords to flush", ( pGLInfo->CurrentBuffer - pGLInfo->DMAPartition[pGLInfo->CurrentPartition].VirtAddr ) / 4 )); } else { DISPDBG(( DBGLVL, "HWC_GetDXBuffer: Using FIFOs")); }
#ifdef WANT_DMA
// Ensure nobody has scribbled on the DMA Buffer
if(( pGLInfo->InterfaceType == GLINT_DMA ) && (pGLInfo->DMAPartition[pGLInfo->CurrentPartition].bStampedDMA) ) { ASSERTDD( *(DWORD*)pThisDisplay->pGLInfo->CurrentBuffer == 0x4D4D4D4D, "ERROR: DMA Buffer signature invalid!" ); }
// Ensure we aren't writing to the wrong region
if(IS_DXCONTEXT_CURRENT(pThisDisplay) && ( pThisDisplay->pGLInfo->InterfaceType != GLINT_UNKNOWN_INTERFACE )) { if ((((ULONG_PTR)pThisDisplay->pGLInfo->CurrentBuffer >= (ULONG_PTR)pThisDisplay->pGlint->GPFifo)) && ((ULONG_PTR)pThisDisplay->pGLInfo->CurrentBuffer <= ((ULONG_PTR)pThisDisplay->pGlint->GPFifo + 4000)) ) { ASSERTDD(pThisDisplay->pGLInfo->InterfaceType == GLINT_NON_DMA, "Error: In FIFO space and setup for DMA"); } else { ASSERTDD(pThisDisplay->pGLInfo->InterfaceType == GLINT_DMA, "Error: In DMA space and setup for FIFO's"); } } #endif
} // HWC_GetDXBuffer
//-----------------------------------------------------------------------------
//
// HWC_SetDXBuffer
//
//-----------------------------------------------------------------------------
void HWC_SetDXBuffer( P3_THUNKEDDATA* pThisDisplay, char *file, int line ) { LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo;
ASSERTDD( pGLInfo->dwFlags & GMVF_GCOP, "VDD not locked out" );
pThisDisplay->BufferLocked = FALSE;
DISPDBG(( DBGLVL, "HWC_SetDXBuffer: %s %d: Curr part %d, dmaPtr 0x%08x", file, line, pGLInfo->CurrentPartition, pGLInfo->CurrentBuffer )); if (pGLInfo->InterfaceType == GLINT_DMA) { DISPDBG(( DBGLVL, "HWC_SetDXBuffer: %d dwords to flush", ( pGLInfo->CurrentBuffer - pGLInfo->DMAPartition[pGLInfo->CurrentPartition].VirtAddr ) / 4 )); } else { DISPDBG(( DBGLVL, "HWC_SetDXBuffer: Using FIFOs")); }
#ifdef WANT_DMA
// Ensure nobody has scribbled on the DMA Buffer
if(( pGLInfo->InterfaceType == GLINT_DMA ) && (pGLInfo->DMAPartition[pGLInfo->CurrentPartition].bStampedDMA) ) { ASSERTDD( *(DWORD*)pThisDisplay->pGLInfo->CurrentBuffer == 0x4D4D4D4D, "ERROR: DMA Buffer signature invalid!" ); }
// Ensure we aren't writing to the wrong region
if(IS_DXCONTEXT_CURRENT(pThisDisplay) && ( pThisDisplay->pGLInfo->InterfaceType != GLINT_UNKNOWN_INTERFACE )) { if ((((ULONG_PTR)pThisDisplay->pGLInfo->CurrentBuffer >= (ULONG_PTR)pThisDisplay->pGlint->GPFifo)) && ((ULONG_PTR)pThisDisplay->pGLInfo->CurrentBuffer <= ((ULONG_PTR)pThisDisplay->pGlint->GPFifo + 4000)) ) { ASSERTDD(pThisDisplay->pGLInfo->InterfaceType == GLINT_NON_DMA, "Error: In FIFO space and setup for DMA"); } else { ASSERTDD(pThisDisplay->pGLInfo->InterfaceType == GLINT_DMA, "Error: In DMA space and setup for FIFO's"); } }
#endif // WANT_DMA
} // HWC_SetDXBuffer
//-----------------------------------------------------------------------------
//
// HWC_bRenderIDHasCompleted
//
// This is simply the paranoid version of the macro
// declared in directx.h. It is present only in checked (debug)
// builds, since the non-debug version is just a
// one-line #define.
//-----------------------------------------------------------------------------
BOOL HWC_bRenderIDHasCompleted ( DWORD dwID, P3_THUNKEDDATA* pThisDisplay ) { DWORD dwCurID, dwCurHostID; int iTemp;
ASSERTDD (CHIP_RENDER_ID_IS_VALID(), "** RENDER_ID_HAS_COMPLETED: Chip's RenderID is not valid." );
dwCurID = GET_CURRENT_CHIP_RENDER_ID(); // Make sure the invalid bits have been zapped.
ASSERTDD ( ( dwCurID | RENDER_ID_KNACKERED_BITS ) == dwCurID, "** RENDER_ID_HAS_COMPLETED: Current chip ID is invalid" ); ASSERTDD ( ( dwID | RENDER_ID_KNACKERED_BITS ) == dwID, "** RENDER_ID_HAS_COMPLETED: Checked ID is invalid" );
// We need to cope with the fact that the MinRegion register sign-extends
// some bits in the middle, irritatingly. It's not a problem for simple
// >=< tests, but this wants to know _how much_ we are out.
// Bits 0xf000f000 are rubbish, so we need to chop them out.
// This is not a problem on P3, and the RENDER_ID_VALID macros are set up
// so this code will basically be compiled out of existence.
dwCurID = ( dwCurID & RENDER_ID_VALID_BITS_LOWER ) | ( ( dwCurID & RENDER_ID_VALID_BITS_UPPER ) >> RENDER_ID_VALID_BITS_UPPER_SHIFT ); dwID = ( dwID & RENDER_ID_VALID_BITS_LOWER ) | ( ( dwID & RENDER_ID_VALID_BITS_UPPER ) >> RENDER_ID_VALID_BITS_UPPER_SHIFT );
iTemp = (signed)( dwCurID - dwID ); // Cope with the dodgy sign bits - sign extend the top n bits.
iTemp <<= RENDER_ID_VALID_BITS_SIGN_SHIFT; iTemp >>= RENDER_ID_VALID_BITS_SIGN_SHIFT; // Some fairly arbitrary boundaries. If they are too small
// for common use, just enlarge them a bit.
// Generally, dwCurId can be well ahead of my_id (if the surface
// hasn't been used for ages), but should not be too far behind,
// because the pipe isn't _that_ big.
if ( ( iTemp < RENDER_ID_LOWER_LIMIT ) || ( iTemp > RENDER_ID_UPPER_LIMIT ) ) { DISPDBG (( ERRLVL," ** Current chip ID 0x%x, surface ID, 0x%x", dwCurID, dwID )); DISPDBG ((ERRLVL,"** RENDER_ID_HAS_COMPLETED: Current render" " ID is a long way out from surface's." )); }
// We should never have a render ID newer
// than the current host render ID.
dwCurHostID = GET_HOST_RENDER_ID(); // Make sure the invalid bits have been zapped.
ASSERTDD ( ( dwCurHostID | RENDER_ID_KNACKERED_BITS ) == dwCurHostID, "** RENDER_ID_HAS_COMPLETED: Current host ID is invalid" ); // Get a real contiguous number.
dwCurHostID = ( dwCurHostID & RENDER_ID_VALID_BITS_LOWER ) | ( ( dwCurHostID & RENDER_ID_VALID_BITS_UPPER ) >> RENDER_ID_VALID_BITS_UPPER_SHIFT ); iTemp = (signed)( dwCurHostID - dwID ); // Cope with the dodgy sign bits - sign extend the top n bits.
iTemp <<= RENDER_ID_VALID_BITS_SIGN_SHIFT; iTemp >>= RENDER_ID_VALID_BITS_SIGN_SHIFT; if ( iTemp < 0 ) { DISPDBG ((ERRLVL," ** Current host ID 0x%x, surface ID, 0x%x", dwCurHostID, dwID )); // This may be caused by wrapping, of course.
DISPDBG ((ERRLVL, "** RENDER_ID_HAS_COMPLETED: Surface's ID is " "more recent than current host render ID." )); }
return ( !RENDER_ID_LESS_THAN ( dwCurID, dwID ) ); } // HWC_bRenderIDHasCompleted
#endif //DBG
|