|
|
/******************************Module*Header***********************************\
* * ******************* * * GDI SAMPLE CODE * * ******************* * * Module Name: hwinit.c * * This module contains the functions that enable and disable the hardware * * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. \******************************************************************************/
#include "precomp.h"
#include "gdi.h"
#include "p2ctxt.h"
#include "tvp4020.h"
#include "p2rd.h"
#define ALLOC_TAG ALLOC_TAG_WH2P
//-----------------------------------------------------------------------------
//
// vInitCoreRegisters
//
// set all core Permedia registers to a known state
//
//-----------------------------------------------------------------------------
VOID vInitCoreRegisters(PPDev ppdev) { PERMEDIA_DECL; PERMEDIA_DEFS(ppdev);
// tracks FBWindowBase for off-screen bitmaps
permediaInfo->PixelOffset = 0; permediaInfo->TextureAddressMode = __PERMEDIA_ENABLE; permediaInfo->TextureReadMode = __PERMEDIA_DISABLE; /*__FX_TEXREADMODE_2048HIGH |
__FX_TEXREADMODE_2048WIDE | __FX_TEXREADMODE_TWRAP_REPEAT | __FX_TEXREADMODE_SWRAP_REPEAT | __PERMEDIA_ENABLE;*/ RESERVEDMAPTR( 41); SEND_PERMEDIA_DATA(DeltaMode, 0); SEND_PERMEDIA_DATA(ColorDDAMode, 0); SEND_PERMEDIA_DATA(ScissorMode, 0); SEND_PERMEDIA_DATA(TextureColorMode, 0); SEND_PERMEDIA_DATA(FogMode, 0); SEND_PERMEDIA_DATA(Window, 0); SEND_PERMEDIA_DATA(StencilMode, 0); SEND_PERMEDIA_DATA(DepthMode, 0); SEND_PERMEDIA_DATA(AlphaBlendMode, 0); SEND_PERMEDIA_DATA(DitherMode, 0); SEND_PERMEDIA_DATA(LBReadMode, 0); SEND_PERMEDIA_DATA(LBWriteMode, 0); SEND_PERMEDIA_DATA(RasterizerMode, 0); SEND_PERMEDIA_DATA(WindowOrigin, 0); SEND_PERMEDIA_DATA(StatisticMode, 0); SEND_PERMEDIA_DATA(FBSoftwareWriteMask, -1); SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1); SEND_PERMEDIA_DATA(FilterMode, 0); SEND_PERMEDIA_DATA(FBWindowBase, 0); SEND_PERMEDIA_DATA(FBPixelOffset, 0); SEND_PERMEDIA_DATA(LogicalOpMode, 0); SEND_PERMEDIA_DATA(FBReadMode, 0); SEND_PERMEDIA_DATA(dXDom, 0); SEND_PERMEDIA_DATA(dXSub, 0); SEND_PERMEDIA_DATA(dY, INTtoFIXED(1)); SEND_PERMEDIA_DATA(TextureAddressMode, 0); SEND_PERMEDIA_DATA(TextureReadMode, 0); SEND_PERMEDIA_DATA(TexelLUTMode, 0); SEND_PERMEDIA_DATA(Texel0, 0); SEND_PERMEDIA_DATA(YUVMode, 0); SEND_PERMEDIA_DATA(FBReadPixel, __PERMEDIA_32BITPIXEL); // 32 bit pixels
SEND_PERMEDIA_DATA(SStart, 0); SEND_PERMEDIA_DATA(dSdx, 1 << 20); SEND_PERMEDIA_DATA(dSdyDom, 0); SEND_PERMEDIA_DATA(TStart, 0); SEND_PERMEDIA_DATA(dTdx, 0); SEND_PERMEDIA_DATA(dTdyDom, 0); SEND_PERMEDIA_DATA(TextureDataFormat, __FX_TEXTUREDATAFORMAT_32BIT_RGBA | __P2_TEXTURE_DATAFORMAT_FLIP); SEND_PERMEDIA_DATA(TextureColorMode, (_P2_TEXTURE_COPY << PM_TEXCOLORMODE_APPLICATION) | __PERMEDIA_ENABLE); // ignored by texture glyph rendering
SEND_PERMEDIA_DATA(TextureAddressMode, permediaInfo->TextureAddressMode); SEND_PERMEDIA_DATA(TextureReadMode, permediaInfo->TextureReadMode); COMMITDMAPTR(); FLUSHDMA(); }
//-----------------------------------------------------------------------------
//
// bInitializeHW
//
// Called to load the initial values into the chip. We assume the hardware
// has been mapped. All the relevant stuff should be hanging off ppdev. We
// also sort out all the hardware capabilities etc.
//
//-----------------------------------------------------------------------------
BOOL bInitializeHW(PPDev ppdev) { HwDataPtr permediaInfo; Surf* psurf; LONG i, j; ULONG width; ULONG ulValue; BOOL bExists; ULONG ulLength; ULONG dmaBufferSize; PERMEDIA_DEFS(ppdev);
DBG_GDI((7, "bInitializeHW: fbsize: 0x%x", ppdev->FrameBufferLength));
// allocate and initialize ppdev->permediaInfo. We store hardware specific
// stuff in this structure.
//
permediaInfo = (HwDataPtr) ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(HwDataRec), ALLOC_TAG); if ( permediaInfo == NULL ) { DBG_GDI((0, "cannot allocate memory for permediaInfo struct")); return (FALSE); } ppdev->permediaInfo = permediaInfo; permediaInfo->pGDICtxt = NULL; permediaInfo->pCurrentCtxt = NULL;
// retrieve the PCI configuration information and local buffer size
ulLength = sizeof(Hw_Device_Info); if ( EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_QUERY_DEVICE_INFO, NULL, 0, (PVOID)&(permediaInfo->deviceInfo), ulLength, &ulLength) ) { DBG_GDI((1, "QUERY_DEVICE_INFO failed.")); return (FALSE); }
ulLength = sizeof(PINTERRUPT_CONTROL_BLOCK); if ( EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF, NULL, 0, (PVOID)&pP2dma, ulLength, &ulLength) ) { DBG_GDI((1, "MAP_INTERRUPT_CMD_BUF failed.")); return FALSE; }
//
// On NT4.0 the above IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF will fail and
// pP2dma will be NULL. Hence we allocate it via ENGALLOCMEM.
//
if(g_bOnNT40) { ASSERTDD(pP2dma == 0, "bInitializeHW: pP2dma != 0"); pP2dma = (P2DMA*) ENGALLOCMEM(FL_ZERO_MEMORY, sizeof(_P2DMA), ALLOC_TAG); }
// Even if IOCtrl call succeeded,
// the allocation can still fail.
if (pP2dma==NULL) { DBG_GDI((0,"allocation of memory for P2DMA from miniport failed")); return FALSE; }
// store away shared memory area for later use in ppdev
ppdev->pP2dma=pP2dma; //@@BEGIN_DDKSPLIT
#if MULTITHREADED && DBG
pP2dma->ppdev = ppdev; #endif
//@@END_DDKSPLIT
DBG_GDI((7, "deviceInfo: VendorId: 0x%x, DevId %d, DeltaId 0x%x," "RevId %d, SubId %d, SubVId %d, lbuf len 0x%x, lbuf width %d", permediaInfo->deviceInfo.VendorId, permediaInfo->deviceInfo.DeviceId, permediaInfo->deviceInfo.DeltaRevId, permediaInfo->deviceInfo.RevisionId, permediaInfo->deviceInfo.SubsystemId, permediaInfo->deviceInfo.SubsystemVendorId, permediaInfo->deviceInfo.LocalbufferLength, permediaInfo->deviceInfo.LocalbufferWidth));
// collect flags as we initialize so zero it here
permediaInfo->flags = 0;
// set up default pointers to our low level rendering functions
//
ppdev->pgfnAlphaBlend = vAlphaBlend; ppdev->pgfnConstantAlphaBlend = vConstantAlphaBlend; ppdev->pgfnCopyBlt = vCopyBlt; ppdev->pgfnGradientFillRect = vGradientFillRect; ppdev->pgfnPatFill = vPatFill; ppdev->pgfnMonoPatFill = vMonoPatFill; ppdev->pgfnMonoOffset = vMonoOffset; ppdev->pgfnPatRealize = vPatRealize; ppdev->pgfnSolidFill = vSolidFill; ppdev->pgfnSolidFillWithRop = vSolidFillWithRop; ppdev->pgfnTransparentBlt = vTransparentBlt; ppdev->pgfnInvert = vInvert;
ppdev->pulRamdacBase = (ULONG*) ppdev->pulCtrlBase[0] + P2_EXTERNALVIDEO / sizeof(ULONG);
// safe pointers to Permedia 2 registers for later use
//
ppdev->pCtrlBase = ((ULONG *)ppdev->pulCtrlBase[0])+CTRLBASE/sizeof(ULONG); ppdev->pGPFifo = ((ULONG *)ppdev->pulCtrlBase[0])+GPFIFO/sizeof(ULONG); ppdev->pCoreBase = ((ULONG *)ppdev->pulCtrlBase[0])+COREBASE/sizeof(ULONG);
DBG_GDI((5, "Initialize: pCtrlBase=0x%p", ppdev->pCtrlBase)); DBG_GDI((5, "Initialize: pGPFifo=0x%p", ppdev->pGPFifo)); DBG_GDI((5, "Initialize: pCoreBase=0x%p", ppdev->pCoreBase));
if (!bInitializeP2DMA( pP2dma, ppdev->hDriver, (ULONG *)ppdev->pulCtrlBase[0], ppdev->dwAccelLevel, TRUE )) { DBG_GDI((0, "P2DMA initialization failed.")); return FALSE; }
// keep a copy of Permedia 2 ChipConfig, so we know
// if we are running on a AGP card or not
ppdev->dwChipConfig = P2_READ_CTRL_REG(PREG_CHIPCONFIG);
//
// If we have a gamma ramp saved in the registry then use that. Otherwise,
// initialize the LUT with a gamma of 1.0
//
if ( !bRegistryRetrieveGammaLUT(ppdev, &permediaInfo->gammaLUT) || !bInstallGammaLUT(ppdev, &permediaInfo->gammaLUT) ) { vSetNewGammaValue(ppdev, 0x10000); }
//
// fill in the permediaInfo capability flags and block fill size.
//
permediaInfo->flags |= GLICAP_NT_CONFORMANT_LINES;
//
// reset all core registers
//
vInitCoreRegisters(ppdev);
//
// now initialize the non-zero core registers
//
RESERVEDMAPTR(20); // reserve a reasonable amount until the all is setup
// Rasterizer Mode
// Fraction and Bias are used by the line drawing code. MirrorBitMask
// is set as all the bits we download are interpreted from bit 31 to bit 0
permediaInfo->RasterizerMode = __PERMEDIA_START_BIAS_ZERO << 4 | __PERMEDIA_FRACTION_ADJUST_ALMOST_HALF << 2 | __PERMEDIA_ENABLE << 0 | // mirror bit mask
__PERMEDIA_ENABLE << 18; // limits enabled
SEND_PERMEDIA_DATA(RasterizerMode, permediaInfo->RasterizerMode);
//@@BEGIN_DDKSPLIT
// TODO: we should not enable limit checking
//@@END_DDKSPLIT
SEND_PERMEDIA_DATA(YLimits, 2047 << 16); SEND_PERMEDIA_DATA(XLimits, 2047 << 16); // Disable screen scissor
SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(ScreenSize, ppdev->cyScreen << 16 | ppdev->cxScreen);
ULONG ulPackedPP;
DBG_GDI((7, "assuming screen stride is %d pixels\n", ppdev->cxMemory)); vCalcPackedPP( ppdev->cxMemory, NULL, &ulPackedPP);
// initialize FBReadMode for our default stride
SEND_PERMEDIA_DATA(FBReadMode, ulPackedPP);
// FB Write Mode
permediaInfo->FBWriteMode = 1 | ((32/*permediaInfo->fastFillBlockSz*/ >> 4) << 1);
SEND_PERMEDIA_DATA(FBWriteMode, permediaInfo->FBWriteMode); DBG_GDI((7, "setting FBWriteMode to 0x%x", (DWORD)permediaInfo->FBWriteMode));
SEND_PERMEDIA_DATA(FBReadPixel, ppdev->cPelSize);
//
// do a probe to see if we support hardware writemasks. use the bottom
// 8 bits only so the same code works for all depths. We also query a
// registry variable which, if set, forces the use of software masking.
//
bExists = bRegistryQueryUlong( ppdev, REG_USE_SOFTWARE_WRITEMASK, &ulValue);
if ( !bExists || (ulValue == 0) ) { // this code works as everything is little endian. i.e. the byte we
// test is always at the lowest address regardless of the pixel depth.
//
WRITE_SCREEN_ULONG(ppdev->pjScreen, 0); // quickest way to clear a pixel!!
SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE); SEND_PERMEDIA_DATA(FBWriteData, 0xff); SEND_PERMEDIA_DATA(StartXDom, 0); SEND_PERMEDIA_DATA(StartY, 0); SEND_PERMEDIA_DATA(FBHardwareWriteMask, 0xa5); SEND_PERMEDIA_DATA(Render, __RENDER_POINT_PRIMITIVE); COMMITDMAPTR();
SYNC_WITH_PERMEDIA;
ulValue = READ_SCREEN_ULONG(ppdev->pjScreen); if ( (ulValue & 0xff) == 0xa5 ) permediaInfo->flags |= GLICAP_HW_WRITE_MASK;
RESERVEDMAPTR(3); }
DBG_GDI((7, "mode registers initialized"));
SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1); SEND_PERMEDIA_DATA(TextureAddressMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureColorMode, __PERMEDIA_DISABLE); COMMITDMAPTR(); FLUSHDMA(); // Initialize out InFifo cached information
dmaBufferSize = INPUT_BUFFER_SIZE;
#if defined(_X86_) || defined(_IA64_)
if(!g_bOnNT40 && !pP2dma->bDMAEmulation) { AllocateDMABuffer(ppdev->hDriver, (LONG *) &dmaBufferSize, &ppdev->dmaBufferVirtualAddress, &ppdev->dmaBufferPhysicalAddress);
if(ppdev->dmaBufferVirtualAddress != NULL && dmaBufferSize < INPUT_BUFFER_SIZE) { FreeDMABuffer(ppdev->hDriver, ppdev->dmaBufferVirtualAddress); ppdev->dmaBufferVirtualAddress = NULL; } } else { ppdev->dmaBufferVirtualAddress = NULL; } #else
ppdev->dmaBufferVirtualAddress = NULL; #endif
if(ppdev->dmaBufferVirtualAddress != NULL) { ppdev->pulInFifoStart = ppdev->dmaBufferVirtualAddress; ppdev->pulInFifoEnd = ppdev->dmaBufferVirtualAddress + (INPUT_BUFFER_SIZE>>3); ppdev->dmaCurrentBufferOffset = 0; } else { ppdev->pulInFifoStart = (ULONG*) ENGALLOCMEM(0, INPUT_BUFFER_SIZE>>1, ALLOC_TAG);
if(ppdev->pulInFifoStart == NULL) { DBG_GDI((0, "bInitializeHW: unable to allocate scratch buffer")); pP2dma->bEnabled = FALSE; goto errExit; } ppdev->pulInFifoEnd = ppdev->pulInFifoStart + (INPUT_BUFFER_SIZE>>3); }
ppdev->pulInFifoPtr = ppdev->pulInFifoStart;
#if DBG
ppdev->ulReserved = 0; #endif
//
// We are done setting up the GDI context state.
//
//
// Allocate a hardware context for this PDEV saving the current context.
//
DBG_GDI((7, "allocating new context")); permediaInfo->pGDICtxt = P2AllocateNewContext(ppdev, NULL, 0, P2CtxtWriteOnly );
if ( permediaInfo->pGDICtxt == NULL ) { DBG_GDI((1, "failed to allocate Permedia context for display driver/GDI")); pP2dma->bEnabled = FALSE; return (FALSE); }
DBG_GDI((7, "got context id 0x%x for GDI context", permediaInfo->pGDICtxt)); P2SwitchContext(ppdev, permediaInfo->pGDICtxt);
return (TRUE);
errExit: return FALSE;
}// bInitializeHW()
//-----------------------------------------------------------------------------
//
// vDisableHW
//
// do whatever needs to be done to disable the hardware and free resources
// allocated in bInitializeHW
//
//-----------------------------------------------------------------------------
VOID vDisableHW(PPDev ppdev) { Surf* psurf; PERMEDIA_DECL;
if ( !permediaInfo ) { return; }
if(ppdev->dmaBufferVirtualAddress != NULL) FreeDMABuffer( ppdev->hDriver, ppdev->dmaBufferVirtualAddress); else if(ppdev->pulInFifoStart) // No DMA case..we allocated via ENGALLOCMEM
ENGFREEMEM(ppdev->pulInFifoStart);
//
// Free up any contexts we allocated
//
if ( permediaInfo->pGDICtxt != NULL ) { P2FreeContext(ppdev, permediaInfo->pGDICtxt); permediaInfo->pGDICtxt = NULL; }
if ( permediaInfo->ContextTable ) { ENGFREEMEM(permediaInfo->ContextTable); } permediaInfo->ContextTable=NULL;
vFree(ppdev->pP2dma); ppdev->pP2dma = NULL;
ENGFREEMEM(permediaInfo);
}// vDisableHW()
//-----------------------------------------------------------------------------
//
// VOID vAssertModeHW
//
// We're about to switch to/from full screen mode so do whatever we need to
// to save context etc.
//
//-----------------------------------------------------------------------------
VOID vAssertModeHW(PPDev ppdev, BOOL bEnable) { PERMEDIA_DECL;
if (!permediaInfo) return;
if (!bEnable) { if(ppdev->permediaInfo->pCurrentCtxt != NULL) P2SwitchContext(ppdev, NULL); //
// Disable DMA
//
ASSERTDD(ppdev->pP2dma->bEnabled, "vAssertModeHW: expected dma to be enabled");
vSyncWithPermedia(ppdev->pP2dma); ppdev->pP2dma->bEnabled = FALSE; } else { //
// Enable DMA
//
if (!bInitializeP2DMA( ppdev->pP2dma, ppdev->hDriver, (ULONG *)ppdev->pulCtrlBase[0], ppdev->dwAccelLevel, FALSE )) { RIP("vAssertModeHW: Cannot restore DMA"); }
ASSERTDD(ppdev->permediaInfo->pCurrentCtxt == NULL, "vAssertModeHW: expected no active context");
//
// Restore the current gamma LUT.
//
bInstallGammaLUT(ppdev, &permediaInfo->gammaLUT); } }
|