/******************************Module*Header**********************************\ * * ******************* * * D3D SAMPLE CODE * * ******************* * * Module Name: d3dhw.c * * Content: Hardware dependent texture setup for D3D * * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. \*****************************************************************************/ #include "precomp.h" #include "d3dhw.h" #include "d3dcntxt.h" #include "d3ddelta.h" #include "dd.h" #include "heap.h" #include "d3dtxman.h" //----------------------------------------------------------------------------- // // PERMEDIA_D3DTEXTURE *TextureHandleToPtr // // Find the texture associated to a given texture handle vale (which is to // say , to a surface handle ) // //----------------------------------------------------------------------------- PERMEDIA_D3DTEXTURE * TextureHandleToPtr(UINT_PTR thandle, PERMEDIA_D3DCONTEXT* pContext) { // only a DX7 context can get here ASSERTDD(NULL != pContext->pHandleList, "pHandleList==NULL in TextureHandleToPtr"); if (pContext->pHandleList->dwSurfaceList == NULL) { // avoid AV if our surface list is missing return NULL; } if ((PtrToUlong(pContext->pHandleList->dwSurfaceList[0]) > thandle) && (0 != thandle)) { return pContext->pHandleList->dwSurfaceList[(DWORD)thandle]; } // Request for pointer for an invalid handle returns NULL return NULL; } // TextureHandleToPtr //----------------------------------------------------------------------------- // // PERMEDIA_D3DTEXTURE *PaletteHandleToPtr // //----------------------------------------------------------------------------- PERMEDIA_D3DPALETTE * PaletteHandleToPtr(UINT_PTR phandle, PERMEDIA_D3DCONTEXT* pContext) { ASSERTDD(NULL != pContext->pHandleList, "pHandleList==NULL in PaletteHandleToPtr"); if ( (NULL != pContext->pHandleList->dwPaletteList) && (PtrToUlong(pContext->pHandleList->dwPaletteList[0]) > phandle) && (0 != phandle) ) { return pContext->pHandleList->dwPaletteList[(DWORD)phandle]; } return NULL; } // PaletteHandleToPtr //----------------------------------------------------------------------------- // //void StorePermediaLODLevel // // Store private data specific to a level of detail // //----------------------------------------------------------------------------- void StorePermediaLODLevel(PPDev ppdev, PERMEDIA_D3DTEXTURE* pTexture, LPDDRAWI_DDRAWSURFACE_LCL pSurf, int LOD) { DWORD dwPartialWidth; int iPixelSize; DBG_D3D((10,"Entering StorePermediaLODLevel")); // if it's any surface type that's not created by driver // certainly there's no need to texture it if (NULL == pTexture->pTextureSurface) return; // Get the BYTE Offset to the texture map if (DDSCAPS_NONLOCALVIDMEM & pTexture->dwCaps) { pTexture->MipLevels[LOD].PixelOffset = (DWORD)(DD_AGPSURFACEPHYSICAL(pSurf->lpGbl) - ppdev->dwGARTDev); } else { pTexture->MipLevels[LOD].PixelOffset = (DWORD)pSurf->lpGbl->fpVidMem; } // .. Convert it to Pixels switch(pTexture->pTextureSurface->SurfaceFormat.PixelSize) { case __PERMEDIA_4BITPIXEL: pTexture->MipLevels[LOD].PixelOffset <<= 1; break; case __PERMEDIA_8BITPIXEL: /* No Change*/ break; case __PERMEDIA_16BITPIXEL: pTexture->MipLevels[LOD].PixelOffset >>= 1; break; case __PERMEDIA_24BITPIXEL: pTexture->MipLevels[LOD].PixelOffset /= 3; break; case __PERMEDIA_32BITPIXEL: pTexture->MipLevels[LOD].PixelOffset >>= 2; break; default: ASSERTDD(0,"Invalid Texture Pixel Size!"); pTexture->MipLevels[LOD].PixelOffset >>= 1; break; } // P2 recognises that the texture is AGP if you set bit 30 to be 1. if (DDSCAPS_NONLOCALVIDMEM & pTexture->dwCaps) { pTexture->MipLevels[LOD].PixelOffset |= (1 << 30); } DBG_D3D((4,"Storing LOD: %d, Pitch: %d, Width: %d PixelOffset=%08lx", LOD, pSurf->lpGbl->lPitch, pSurf->lpGbl->wWidth,pTexture->MipLevels[LOD].PixelOffset)); // Get the Partial Products for this LOD iPixelSize = pTexture->pTextureSurface->SurfaceFormat.PixelSize; if (iPixelSize == __PERMEDIA_4BITPIXEL) { dwPartialWidth = (pSurf->lpGbl->lPitch << 1); } else { if (iPixelSize != __PERMEDIA_24BITPIXEL) { dwPartialWidth = (pSurf->lpGbl->lPitch >> iPixelSize); } else { dwPartialWidth = pSurf->lpGbl->lPitch / 3; } } if (dwPartialWidth < 32) dwPartialWidth = 32; vCalcPackedPP( dwPartialWidth, NULL, &pTexture->MipLevels[LOD].ulPackedPP); pTexture->MipLevels[LOD].logWidth = log2((int)pSurf->lpGbl->wWidth); pTexture->MipLevels[LOD].logHeight = log2((int)pSurf->lpGbl->wHeight); DBG_D3D((10,"Exiting StorePermediaLODLevel")); } // StorePermediaLODLevel //@@BEGIN_DDKSPLIT // Note: we are currently not using more than 8MB of AGP memory #if 0 //----------------------------------------------------------------------------- // // BOOL CheckAGPTexturePage // // Check that the AGP texture we are about to use hasn't been placed // in a different 8MB page. // dwGARTDev represents our current base address for the AGP texture memory // dwGARTDevBase is the value we were passed at start of day //----------------------------------------------------------------------------- BOOL CheckAGPTexturePage(PPDev ppdev, PERMEDIA_D3DCONTEXT* pContext, PERMEDIA_D3DTEXTURE* pTexture, LPDDRAWI_DDRAWSURFACE_LCL pSurf) { BOOL bChanged = FALSE; DBG_D3D((10,"Entering CheckAGPTexturePage")); ASSERTDD(pSurf, "ERROR: NULL Surface passed to CheckAGPTexturePage!"); // Calculate the offset to the texture from the current // base pointer in AGP memory UINT_PTR lSurfaceOffset = pTexture->lSurfaceOffset; UINT_PTR lTextureSize = pTexture->wHeight * pTexture->lPitch; // Account for a potential LUT added to the end of the surface lTextureSize += (256 * sizeof(DWORD)); // If the texture falls outside the current 8Mb window // then adjust the AGP base address if (lSurfaceOffset < ppdev->dwGARTLin || ((lSurfaceOffset + lTextureSize - ppdev->dwGARTLin) >= 0x800000)) { UINT_PTR dwNewGARTOffset = lSurfaceOffset; bChanged = TRUE; ppdev->dwGARTDev = ppdev->dwGARTDevBase + dwNewGARTOffset; ppdev->dwGARTLin = ppdev->dwGARTLinBase + dwNewGARTOffset; DBG_D3D((4,"Relocated AGP TextureBase Address " "to : 0x%x (Base: 0x%x)", ppdev->dwGARTDev, ppdev->dwGARTDevBase)); } //If the texture is in a different place relative to the base of // AGP memory that we are using then update it if (pTexture->dwGARTDevLast != ppdev->dwGARTDev) { pTexture->dwGARTDevLast = ppdev->dwGARTDev; StorePermediaLODLevel(ppdev, pTexture, pSurf, 0); } DBG_D3D((10,"Exiting CheckAGPTexturePage")); return bChanged; } #endif //@@END_DDKSPLIT //----------------------------------------------------------------------------- // // void DisableTexturePermedia // // Disable texturing in P2 // //----------------------------------------------------------------------------- void DisableTexturePermedia(PERMEDIA_D3DCONTEXT* pContext) { DWORD* pFlags = &pContext->Hdr.Flags; PERMEDIA_D3DTEXTURE* pTexture = NULL; __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs; PERMEDIA_DEFS(pContext->ppdev); DBG_D3D((10,"Entering DisableTexturePermedia")); pContext->FakeBlendNum &= ~FAKE_ALPHABLEND_MODULATE; // The textures have been turned off, so... ASSERTDD(pContext->CurrentTextureHandle == 0, "DisableTexturePermedia expected zero texture handle"); DBG_D3D((4, "Disabling Texturing")); RESERVEDMAPTR(8); // Turn off texture address generation pSoftPermedia->TextureAddressMode.Enable = 0; COPY_PERMEDIA_DATA(TextureAddressMode, pSoftPermedia->TextureAddressMode); // Turn off texture reads pSoftPermedia->TextureReadMode.Enable = 0; COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode); // Turn off textures pSoftPermedia->TextureColorMode.TextureEnable = 0; COPY_PERMEDIA_DATA(TextureColorMode, pSoftPermedia->TextureColorMode); // Set the texture base address to 0 // (turning off the 'AGP' bit in the process) // Also stop TexelLUTTransfer messages SEND_PERMEDIA_DATA(TextureBaseAddress, 0); SEND_PERMEDIA_DATA(TexelLUTTransfer, __PERMEDIA_DISABLE); // Set current texture to 0 pContext->CurrentTextureHandle = 0; *pFlags &= ~CTXT_HAS_TEXTURE_ENABLED; RENDER_TEXTURE_DISABLE(pContext->RenderCommand); // If textures were in copy mode, we may have fiddled with the DDA, // to improve performance. if ((unsigned int)pSoftPermedia->TextureColorMode.ApplicationMode == _P2_TEXTURE_COPY) { if (*pFlags & CTXT_HAS_GOURAUD_ENABLED) { pSoftPermedia->DeltaMode.SmoothShadingEnable = 1; COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); pSoftPermedia->ColorDDAMode.UnitEnable = 1; // Smooth shade, DDA Enable COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode); } else { pSoftPermedia->DeltaMode.SmoothShadingEnable = 0; COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); pSoftPermedia->ColorDDAMode.UnitEnable = 1; // Flat shade, DDA Enable COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode); } } if (pContext->bCanChromaKey == TRUE) { // Turn off Chroma Keying pSoftPermedia->YUVMode.TestMode = PM_YUVMODE_CHROMATEST_DISABLE; pSoftPermedia->YUVMode.Enable = __PERMEDIA_DISABLE; COPY_PERMEDIA_DATA(YUVMode, pSoftPermedia->YUVMode); pContext->bCanChromaKey = FALSE; } COMMITDMAPTR(); DBG_D3D((10,"Exiting DisableTexturePermedia")); return; } // DisableTexturePermedia //----------------------------------------------------------------------------- // // void Convert_Chroma_2_8888ARGB // // Conversion of a chroma value into 32bpp ARGB // //----------------------------------------------------------------------------- void Convert_Chroma_2_8888ARGB(DWORD *pdwLowerBound, DWORD *pdwUpperBound, DWORD dwRedMask, DWORD dwAlphaMask, DWORD dwPixelSize) { DBG_D3D((10,"Entering Convert_Chroma_2_8888ARGB")); switch (dwPixelSize) { case __PERMEDIA_8BITPIXEL: if (dwRedMask == 0xE0) { // Never any alpha *pdwLowerBound = CHROMA_LOWER_ALPHA(FORMAT_332_32BIT_BGR(*pdwLowerBound)); *pdwUpperBound = CHROMA_UPPER_ALPHA(FORMAT_332_32BIT_BGR(*pdwUpperBound)); } else { *pdwLowerBound = FORMAT_2321_32BIT_BGR(*pdwLowerBound); *pdwUpperBound = FORMAT_2321_32BIT_BGR(*pdwUpperBound); if (!dwAlphaMask) { *pdwLowerBound = CHROMA_LOWER_ALPHA(*pdwLowerBound); *pdwUpperBound = CHROMA_UPPER_ALPHA(*pdwUpperBound); } } break; case __PERMEDIA_16BITPIXEL: switch (dwRedMask) { case 0xf00: *pdwLowerBound = (FORMAT_4444_32BIT_BGR(*pdwLowerBound)); *pdwUpperBound = (FORMAT_4444_32BIT_BGR(*pdwUpperBound)); if (!dwAlphaMask) { *pdwLowerBound = CHROMA_LOWER_ALPHA(*pdwLowerBound); *pdwUpperBound = CHROMA_UPPER_ALPHA(*pdwUpperBound); } // Acount for the internal 8888 -> 4444 translation // which causes bilinear chroma keying to fail in // some cases *pdwLowerBound = *pdwLowerBound & 0xF0F0F0F0; *pdwUpperBound = *pdwUpperBound | 0x0F0F0F0F; break; case 0x7c00: *pdwLowerBound = FORMAT_5551_32BIT_BGR(*pdwLowerBound); *pdwUpperBound = FORMAT_5551_32BIT_BGR(*pdwUpperBound); if (!dwAlphaMask) { *pdwLowerBound = CHROMA_LOWER_ALPHA(*pdwLowerBound); *pdwUpperBound = CHROMA_UPPER_ALPHA(*pdwUpperBound); } // Acount for the internal 8888 -> 5551 translation // which causes bilinear chroma keying to fail in // some cases *pdwLowerBound = *pdwLowerBound & 0x80F8F8F8; *pdwUpperBound = *pdwUpperBound | 0x7F070707; break; default: // Always supply full range of alpha values to ensure test // is done *pdwLowerBound = CHROMA_LOWER_ALPHA(FORMAT_565_32BIT_BGR(*pdwLowerBound)); *pdwUpperBound = CHROMA_UPPER_ALPHA(FORMAT_565_32BIT_BGR(*pdwUpperBound)); if (!dwAlphaMask) { *pdwLowerBound = CHROMA_LOWER_ALPHA(*pdwLowerBound); *pdwUpperBound = CHROMA_UPPER_ALPHA(*pdwUpperBound); } // Acount for the internal 888 -> 565 translation // which causes bilinear chroma keying to fail in // some cases *pdwLowerBound = *pdwLowerBound & 0xF8F8FCF8; *pdwUpperBound = *pdwUpperBound | 0x07070307; break; } break; case __PERMEDIA_24BITPIXEL: case __PERMEDIA_32BITPIXEL: *pdwLowerBound = FORMAT_8888_32BIT_BGR(*pdwLowerBound); *pdwUpperBound = FORMAT_8888_32BIT_BGR(*pdwUpperBound); // If the surface isn't alpha'd then set a valid // range of alpha to catch all cases. if (!dwAlphaMask) { *pdwLowerBound = CHROMA_LOWER_ALPHA(*pdwLowerBound); *pdwUpperBound = CHROMA_UPPER_ALPHA(*pdwUpperBound); } break; } DBG_D3D((10,"Exiting Convert_Chroma_2_8888ARGB")); } // Convert_Chroma_2_8888ARGB //----------------------------------------------------------------------------- // // void EnableTexturePermedia // // Enable and setup texturing for pContext->CurrentTextureHandle // //----------------------------------------------------------------------------- void EnableTexturePermedia(PERMEDIA_D3DCONTEXT* pContext) { DWORD* pFlags = &pContext->Hdr.Flags; PERMEDIA_D3DTEXTURE* pTexture = NULL; __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs; PERMEDIA_DEFS(pContext->ppdev); PERMEDIA_D3DPALETTE* pPalette=NULL; LPPALETTEENTRY lpColorTable=NULL; // array of palette entries PPDev ppdev = pContext->ppdev; DBG_D3D((10,"Entering EnableTexturePermedia %d", pContext->CurrentTextureHandle)); pContext->FakeBlendNum &= ~FAKE_ALPHABLEND_MODULATE; // A texture has been turned on so ... ASSERTDD(pContext->CurrentTextureHandle != 0, "EnableTexturePermedia expected non zero texture handle"); // We must be texturing so... pTexture = TextureHandleToPtr(pContext->CurrentTextureHandle, pContext); if (CHECK_D3DSURFACE_VALIDITY(pTexture)) { PermediaSurfaceData* pPrivateData; DWORD cop = pContext->TssStates[D3DTSS_COLOROP]; DWORD ca1 = pContext->TssStates[D3DTSS_COLORARG1]; DWORD ca2 = pContext->TssStates[D3DTSS_COLORARG2]; DWORD aop = pContext->TssStates[D3DTSS_ALPHAOP]; DWORD aa1 = pContext->TssStates[D3DTSS_ALPHAARG1]; // Current is the same as diffuse in stage 0 if (ca2 == D3DTA_CURRENT) ca2 = D3DTA_DIFFUSE; pPrivateData = pTexture->pTextureSurface; if (!CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData)) { DBG_D3D((0,"EnableTexturePermedia get invalid pPrivateData=0x%x" " from SurfaceHandle=%d", pPrivateData, pContext->CurrentTextureHandle)); pContext->CurrentTextureHandle = 0; // If the texture is bad, let's ensure it's marked as such. pTexture->MagicNo = TC_MAGIC_DISABLE; goto Exit_EnableTexturePermedia; } if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE) { if (NULL==pPrivateData->fpVidMem) { TextureCacheManagerAllocNode(pContext,pTexture); if (NULL==pPrivateData->fpVidMem) { DBG_D3D((0,"EnableTexturePermedia unable to allocate memory from heap")); pContext->CurrentTextureHandle = 0; goto Exit_EnableTexturePermedia; } pPrivateData->dwFlags |= P2_SURFACE_NEEDUPDATE; } TextureCacheManagerTimeStamp(pContext->pTextureManager,pTexture); if (pPrivateData->dwFlags & P2_SURFACE_NEEDUPDATE) { RECTL rect; rect.left=rect.top=0; rect.right=pTexture->wWidth; rect.bottom=pTexture->wHeight; // texture download // Switch to DirectDraw context pPrivateData->dwFlags &= ~P2_SURFACE_NEEDUPDATE; // .. Convert it to Pixels pTexture->MipLevels[0].PixelOffset = (DWORD)(pPrivateData->fpVidMem); switch(pTexture->pTextureSurface->SurfaceFormat.PixelSize) { case __PERMEDIA_4BITPIXEL: pTexture->MipLevels[0].PixelOffset <<= 1; break; case __PERMEDIA_8BITPIXEL: /* No Change*/ break; case __PERMEDIA_16BITPIXEL: pTexture->MipLevels[0].PixelOffset >>= 1; break; case __PERMEDIA_24BITPIXEL: pTexture->MipLevels[0].PixelOffset /= 3; break; case __PERMEDIA_32BITPIXEL: pTexture->MipLevels[0].PixelOffset >>= 2; break; default: ASSERTDD(0,"Invalid Texture Pixel Size!"); pTexture->MipLevels[0].PixelOffset >>= 1; break; } PermediaPatchedTextureDownload(pContext->ppdev, pPrivateData, pTexture->fpVidMem, pTexture->lPitch, &rect, pPrivateData->fpVidMem, pTexture->lPitch, &rect); //need to restore following registers RESERVEDMAPTR(7); SEND_PERMEDIA_DATA(FBReadPixel, pSoftPermedia->FBReadPixel); COPY_PERMEDIA_DATA(FBReadMode, pSoftPermedia->FBReadMode); SEND_PERMEDIA_DATA(FBPixelOffset, pContext->PixelOffset); SEND_PERMEDIA_DATA(FBWindowBase,0); COPY_PERMEDIA_DATA(Window, pSoftPermedia->Window); COPY_PERMEDIA_DATA(AlphaBlendMode, pSoftPermedia->AlphaBlendMode); COPY_PERMEDIA_DATA(DitherMode, pSoftPermedia->DitherMode); COMMITDMAPTR(); DBG_D3D((10, "Copy from %08lx to %08lx w=%08lx h=%08lx p=%08lx b=%08lx", pTexture->fpVidMem,pPrivateData->fpVidMem,pTexture->wWidth, pTexture->wHeight,pTexture->lPitch,pTexture->dwRGBBitCount)); } } // If it is a palette indexed texture, we simply follow the chain // down from the surface to it's palette and pull out the LUT values // from the PALETTEENTRY's in the palette. if (pPrivateData->SurfaceFormat.Format == PERMEDIA_8BIT_PALETTEINDEX || pPrivateData->SurfaceFormat.Format == PERMEDIA_4BIT_PALETTEINDEX) { pPalette = PaletteHandleToPtr(pTexture->dwPaletteHandle,pContext); if (NULL != pPalette) { //some apps are not setting their alpha correctly with palette //then it's up to palette to tell us pPrivateData->SurfaceFormat.bAlpha = pPalette->dwFlags & DDRAWIPAL_ALPHA; } } if ((ca2 == D3DTA_DIFFUSE && ca1 == D3DTA_TEXTURE) && cop == D3DTOP_MODULATE && (aa1 == D3DTA_TEXTURE && aop == D3DTOP_LEGACY_ALPHAOVR)) { // if this is legacy modulation then we take the texture alpha // only if the texure format has it if (pPrivateData->SurfaceFormat.bAlpha) pContext->FakeBlendNum |= FAKE_ALPHABLEND_MODULATE; } else if ((ca2 == D3DTA_DIFFUSE && ca1 == D3DTA_TEXTURE) && cop == D3DTOP_MODULATE && (aa1 == D3DTA_TEXTURE && aop == D3DTOP_SELECTARG1)) { // if this is DX6 modulation then we take the texture alpha // no matter what ( it will be xFF if it doesn't exist) pContext->FakeBlendNum |= FAKE_ALPHABLEND_MODULATE; } // Enable Texture Address calculation pSoftPermedia->TextureAddressMode.Enable = 1; // Enable Textures pSoftPermedia->TextureColorMode.TextureEnable = 1; if (*pFlags & CTXT_HAS_SPECULAR_ENABLED) { pSoftPermedia->DeltaMode.SpecularTextureEnable = 1; pSoftPermedia->TextureColorMode.KsDDA = 1; pSoftPermedia->TextureColorMode.ApplicationMode |= _P2_TEXTURE_SPECULAR; } else { pSoftPermedia->DeltaMode.SpecularTextureEnable = 0; pSoftPermedia->TextureColorMode.KsDDA = 0; pSoftPermedia->TextureColorMode.ApplicationMode &= ~_P2_TEXTURE_SPECULAR; } // reserve here for all cases in this function!! RESERVEDMAPTR(272); COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); // Set Partial products for texture (assume no mipmapping). pSoftPermedia->TextureMapFormat.PackedPP = pTexture->MipLevels[0].ulPackedPP; pSoftPermedia->TextureMapFormat.TexelSize = pPrivateData->SurfaceFormat.PixelSize; if (pPrivateData->dwFlags & P2_ISPATCHED) { DBG_D3D((4," Enabling Patching for this texture")); pSoftPermedia->TextureMapFormat.SubPatchMode = 1; } else { pSoftPermedia->TextureMapFormat.SubPatchMode = 0; } DBG_D3D((4, " Texel Size: 0x%x", pPrivateData->SurfaceFormat.PixelSize)); // Set texture size DBG_D3D((4," Texture Width: 0x%x", pTexture->MipLevels[0].logWidth)); DBG_D3D((4," Texture Height: 0x%x", pTexture->MipLevels[0].logHeight)); pSoftPermedia->TextureReadMode.Width = pTexture->MipLevels[0].logWidth; pSoftPermedia->TextureReadMode.Height = pTexture->MipLevels[0].logHeight; pSoftPermedia->TextureReadMode.Enable = 1; pContext->DeltaWidthScale = (float)pTexture->wWidth * (1 / 2048.0f); pContext->DeltaHeightScale = (float)pTexture->wHeight * (1 / 2048.0f); pContext->MaxTextureXf = (float)(2048 / pTexture->wWidth); pContext->MaxTextureYf = (float)(2048 / pTexture->wHeight); myFtoui(&pContext->MaxTextureXi, pContext->MaxTextureXf); pContext->MaxTextureXi -= 1; myFtoui(&pContext->MaxTextureYi, pContext->MaxTextureYf); pContext->MaxTextureYi -= 1; *pFlags |= CTXT_HAS_TEXTURE_ENABLED; RENDER_TEXTURE_ENABLE(pContext->RenderCommand); DBG_D3D((4," Texture Format: 0x%x", pPrivateData->SurfaceFormat.Format)); DBG_D3D((4," Texture Format Extension: 0x%x", pPrivateData->SurfaceFormat.FormatExtension)); pSoftPermedia->TextureDataFormat.TextureFormat = pPrivateData->SurfaceFormat.Format; pSoftPermedia->TextureDataFormat.TextureFormatExtension = pPrivateData->SurfaceFormat.FormatExtension; if (pPrivateData->SurfaceFormat.bAlpha) { pSoftPermedia->TextureDataFormat.NoAlphaBuffer = 0; } else { pSoftPermedia->TextureDataFormat.NoAlphaBuffer = 1; } // If we are copying textures, there is no need for colour data // to be generated, so we turn off the DDA if (((unsigned int)pSoftPermedia->TextureColorMode.ApplicationMode) == _P2_TEXTURE_COPY) { pSoftPermedia->ColorDDAMode.UnitEnable = 0; DBG_D3D((4, " Disabling DDA")); } else { pSoftPermedia->ColorDDAMode.UnitEnable = 1; DBG_D3D((4, " Enabling DDA")); } // Load the texture base address BEFORE the TexelLUTTransfer message // to ensure we load the LUT from the right sort of memory (AGP or not) // Always set the base address at the root texture (not the miplevels // if there are any) DBG_D3D((4, "Setting texture base address to 0x%08X", pTexture->MipLevels[0].PixelOffset)); SEND_PERMEDIA_DATA(TextureBaseAddress, pTexture->MipLevels[0].PixelOffset); // If it is a palette indexed texture, we simply follow the chain // down from the surface to it's palette and pull out the LUT values // from the PALETTEENTRY's in the palette. if (pPrivateData->SurfaceFormat.Format == PERMEDIA_8BIT_PALETTEINDEX) { if (NULL != pPalette) { int i; lpColorTable = pPalette->ColorTable; if (pPalette->dwFlags & DDRAWIPAL_ALPHA) { for (i = 0; i < 256; i++) { SEND_PERMEDIA_DATA(TexelLUTData, *(DWORD*)lpColorTable); lpColorTable++; } } else { for (i = 0; i < 256; i++) { SEND_PERMEDIA_DATA(TexelLUTData, CHROMA_UPPER_ALPHA(*(DWORD*)lpColorTable)); lpColorTable++; } } SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_ENABLE); DBG_D3D((4,"Texel LUT pPalette->dwFlags=%08lx bAlpha=%d", pPalette->dwFlags,pPrivateData->SurfaceFormat.bAlpha)); // Must reset the LUT index on Permedia P2 SEND_PERMEDIA_DATA(TexelLUTIndex, 0); } else { DBG_D3D((0, "NULL == pPalette in EnableTexturePermedia" "dwPaletteHandle=%08lx dwSurfaceHandle=%08lx", pTexture->dwPaletteHandle, pContext->CurrentTextureHandle)); } } else if (pPrivateData->SurfaceFormat.Format == PERMEDIA_4BIT_PALETTEINDEX) { if (NULL != pPalette) { int i; lpColorTable = pPalette->ColorTable; SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_ENABLE); if (pPalette->dwFlags & DDRAWIPAL_ALPHA) { for (i = 0; i < 16; i++) { SEND_PERMEDIA_DATA_OFFSET(TexelLUT0, *(DWORD*)lpColorTable,i); lpColorTable++; } } else { for (i = 0; i < 16; i++) { SEND_PERMEDIA_DATA_OFFSET(TexelLUT0, CHROMA_UPPER_ALPHA(*(DWORD*)lpColorTable),i); lpColorTable++; } } // Must reset the LUT index on Permedia P2 SEND_PERMEDIA_DATA(TexelLUTIndex, 0); SEND_PERMEDIA_DATA(TexelLUTTransfer, __PERMEDIA_DISABLE); } else { DBG_D3D((0, "NULL == pPalette in EnableTexturePermedia" "dwPaletteHandle=%08lx dwSurfaceHandle=%08lx", pTexture->dwPaletteHandle, pContext->CurrentTextureHandle)); } } else { // Not palette indexed SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_DISABLE); } if ((pTexture->dwFlags & DDRAWISURF_HASCKEYSRCBLT) && (pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE])) { DWORD LowerBound = pTexture->dwKeyLow; DWORD UpperBound = pTexture->dwKeyHigh; DWORD dwLowIndexColor; pContext->bCanChromaKey = TRUE; DBG_D3D((4," Can Chroma Key the texture")); // Enable Chroma keying for the texture // ..and set the correct colour // Evaluate the new chroma key value. Shouldn't be too expensive, // as it is only bit shifts and a couple of tests. // We also change only when the texture map has changed. DBG_D3D((4, "dwColorSpaceLow = 0x%08X", LowerBound)); DBG_D3D((4, "dwColorSpaceHigh = 0x%08X", UpperBound)); if (NULL != pPalette) { if (pPrivateData->SurfaceFormat.Format == PERMEDIA_4BIT_PALETTEINDEX) { LowerBound &= 0x0F; } else { LowerBound &= 0xFF; } lpColorTable = pPalette->ColorTable; // ChromaKeying for 4/8 Bit textures is done on the looked up // color, not the index. This means using a range is // meaningless and we have to lookup the color from the // palette. Make sure the user doesn't force us to access // invalid memory. dwLowIndexColor = *(DWORD*)(&lpColorTable[LowerBound]); if (pPalette->dwFlags & DDRAWIPAL_ALPHA) { LowerBound = UpperBound = dwLowIndexColor; } else { LowerBound = CHROMA_LOWER_ALPHA(dwLowIndexColor); UpperBound = CHROMA_UPPER_ALPHA(dwLowIndexColor); } DBG_D3D((4,"PaletteHandle=%08lx Lower=%08lx ChromaColor=%08lx" "lpColorTable=%08lx dwFlags=%08lx", pTexture->dwPaletteHandle, LowerBound, dwLowIndexColor, lpColorTable, pPalette->dwFlags)); } else Convert_Chroma_2_8888ARGB(&LowerBound, &UpperBound, pPrivateData->SurfaceFormat.RedMask, pPrivateData->SurfaceFormat.AlphaMask, pPrivateData->SurfaceFormat.PixelSize); DBG_D3D((4,"LowerBound Selected: 0x%x", LowerBound)); DBG_D3D((4,"UpperBound Selected: 0x%x", UpperBound)); // If it's a P2 we can use alpha mapping to // improve bilinear chroma keying. if (0/*(unsigned int)pSoftPermedia->TextureReadMode.FilterMode == 1*/) { pSoftPermedia->TextureDataFormat.AlphaMap = PM_TEXDATAFORMAT_ALPHAMAP_EXCLUDE; pSoftPermedia->TextureDataFormat.NoAlphaBuffer = 1; SEND_PERMEDIA_DATA(AlphaMapUpperBound, UpperBound); SEND_PERMEDIA_DATA(AlphaMapLowerBound, LowerBound); SEND_PERMEDIA_DATA(ChromaUpperBound, 0xFFFFFFFF); SEND_PERMEDIA_DATA(ChromaLowerBound, 0xFF000000); pSoftPermedia->YUVMode.TestMode = PM_YUVMODE_CHROMATEST_PASSWITHIN; } else { pSoftPermedia->TextureDataFormat.AlphaMap = PM_TEXDATAFORMAT_ALPHAMAP_DISABLE; SEND_PERMEDIA_DATA(ChromaUpperBound, UpperBound); SEND_PERMEDIA_DATA(ChromaLowerBound, LowerBound); pSoftPermedia->YUVMode.TestMode = PM_YUVMODE_CHROMATEST_FAILWITHIN; } } else { DBG_D3D((2," Can't Chroma Key the texture")); pContext->bCanChromaKey = FALSE; pSoftPermedia->TextureDataFormat.AlphaMap = __PERMEDIA_DISABLE; pSoftPermedia->YUVMode.TestMode = PM_YUVMODE_CHROMATEST_DISABLE; } // Restore the filter mode from the mag filter. if (pContext->bMagFilter) { pSoftPermedia->TextureReadMode.FilterMode = 1; } else { pSoftPermedia->TextureReadMode.FilterMode = 0; } // If the texture is a YUV texture we need to change the color order // of the surface and turn on the YUV->RGB conversoin if (pPrivateData->SurfaceFormat.Format == PERMEDIA_YUV422) { pSoftPermedia->YUVMode.Enable = __PERMEDIA_ENABLE; pSoftPermedia->TextureDataFormat.ColorOrder = INV_COLOR_MODE; } else { pSoftPermedia->YUVMode.Enable = __PERMEDIA_DISABLE; pSoftPermedia->TextureDataFormat.ColorOrder = COLOR_MODE; } // Send the Commands at the end (except the texture base address!!) COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode); COPY_PERMEDIA_DATA(TextureDataFormat, pSoftPermedia->TextureDataFormat); COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode); COPY_PERMEDIA_DATA(TextureMapFormat, pSoftPermedia->TextureMapFormat); COPY_PERMEDIA_DATA(TextureColorMode, pSoftPermedia->TextureColorMode); COPY_PERMEDIA_DATA(YUVMode, pSoftPermedia->YUVMode); COPY_PERMEDIA_DATA(TextureAddressMode, pSoftPermedia->TextureAddressMode); COMMITDMAPTR(); FLUSHDMA(); } else { DBG_D3D((0,"Invalid Texture handle (%d)!, doing nothing", pContext->CurrentTextureHandle)); pContext->CurrentTextureHandle = 0; // If the texture is bad, let's ensure it's marked as such. // But only if the texture is actually there!! if (pTexture) pTexture->MagicNo = TC_MAGIC_DISABLE; } Exit_EnableTexturePermedia: DBG_D3D((10,"Exiting EnableTexturePermedia")); } // EnableTexturePermedia //----------------------------------------------------------------------------- // // void: __PermediaDisableUnits // // Disables all the mode registers to give us a clean start. // //----------------------------------------------------------------------------- void __PermediaDisableUnits(PERMEDIA_D3DCONTEXT* pContext) { PERMEDIA_DEFS(pContext->ppdev); DBG_D3D((10,"Entering __PermediaDisableUnits")); RESERVEDMAPTR(28); SEND_PERMEDIA_DATA(RasterizerMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AreaStippleMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(ColorDDAMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FogMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LBReadMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(Window, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(StencilMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(DepthMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LBWriteMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FBReadMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(DitherMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AlphaBlendMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FBWriteMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(StatisticMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FilterMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(FBSourceData, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(LBWriteFormat, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureReadMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureMapFormat, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureDataFormat, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(TextureColorMode, __PERMEDIA_DISABLE); SEND_PERMEDIA_DATA(AStart, PM_BYTE_COLOR(0xFF)); // Ensure AGP bit not set. SEND_PERMEDIA_DATA(TextureBaseAddress, 0); SEND_PERMEDIA_DATA(TexelLUTIndex, 0); SEND_PERMEDIA_DATA(TexelLUTTransfer, __PERMEDIA_DISABLE); COMMITDMAPTR(); FLUSHDMA(); DBG_D3D((10,"Exiting __PermediaDisableUnits")); } // __PermediaDisableUnits #ifdef DBG //----------------------------------------------------------------------------- // // void DumpTexture // // Debug dump of texture information // //----------------------------------------------------------------------------- void DumpTexture(PPDev ppdev, PERMEDIA_D3DTEXTURE* pTexture, DDPIXELFORMAT* pPixelFormat) { DBG_D3D((4, "\n** Texture Dump:")); DBG_D3D((4," Texture Width: %d", pTexture->wWidth)); DBG_D3D((4," Texture Height: %d", pTexture->wHeight)); if (NULL != pTexture->pTextureSurface) { DBG_D3D((4," LogWidth: %d", pTexture->MipLevels[0].logWidth)); DBG_D3D((4," LogHeight: %d", pTexture->MipLevels[0].logHeight)); DBG_D3D((4," PackedPP0: 0x%x", pTexture->pTextureSurface->ulPackedPP)); } DBG_D3D((4," Pixel Offset of Texture (PERMEDIA Chip): 0x%x", pTexture->MipLevels[0].PixelOffset)); // Show texture format if (pPixelFormat->dwRGBAlphaBitMask == 0xf000) { DBG_D3D((4," Texture is 4:4:4:4")); } else if (pPixelFormat->dwRBitMask == 0xff0000) { if (pPixelFormat->dwRGBAlphaBitMask != 0) { DBG_D3D((4," Texture is 8:8:8:8")); } else { DBG_D3D((4," Texture is 8:8:8")); } } else if (pPixelFormat->dwRBitMask == 0x7c00) { if (pPixelFormat->dwRGBAlphaBitMask != 0) { DBG_D3D((4," Texture is 1:5:5:5")); } else { DBG_D3D((4," Texture is 5:5:5")); } } else if (pPixelFormat->dwRBitMask == 0xf800) { DBG_D3D((4," Texture is 5:6:5")); } else if (pPixelFormat->dwRBitMask == 0xe0) { DBG_D3D((4," Texture is 3:3:2")); } } // DumpTexture #endif