#ifndef __TEXTURE_HPP__ #define __TEXTURE_HPP__ /*==========================================================================; * * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved. * * File: texture.h * Content: Base class for all texture objects. Texture management is * done at this level. * * ***************************************************************************/ // The mip texture class has all of the functionality of the // the Base Object class along with some additional state for // managing LODs. #include #include "resource.hpp" #include "pixel.hpp" #define __INVALIDPALETTE USHRT_MAX class CBaseTexture : public IDirect3DBaseTexture8, public CResource { public: // Constructor CBaseTexture( CBaseDevice *pDevice, DWORD cLevels, D3DPOOL UserPool, D3DFORMAT UserFormat, REF_TYPE refType); // Function to convert a IDirect3DBaseTexture8 * to // a CBaseTexture *. static CBaseTexture *SafeCast(IDirect3DBaseTexture8 *pInterface); // Returns the format that the user passed in D3DFORMAT GetUserFormat() const { return m_formatUser; } // GetUserFormat BOOL IsPaletted() const { DXGASSERT(GetBufferDesc()->Format == GetUserFormat()); return CPixel::IsPaletted(GetUserFormat()); } // Returns the current palette DWORD GetPalette() const { DXGASSERT(GetBufferDesc()->Format == GetUserFormat()); DXGASSERT(CPixel::IsPaletted(GetUserFormat())); return m_Palette; } // GetPalette // Set the current palette void SetPalette(DWORD Palette) { DXGASSERT(GetBufferDesc()->Format == GetUserFormat()); #if DBG if(Palette != __INVALIDPALETTE) { DXGASSERT(CPixel::IsPaletted(GetUserFormat())); } #endif DXGASSERT(Palette <= USHRT_MAX); m_Palette = (WORD)Palette; } // SetPalette // Return current LOD DWORD GetLODI() const { return m_LOD; } // Sets current LOD (but doesn't actually do any work) DWORD SetLODI(DWORD LOD) { DXGASSERT(LOD <= UCHAR_MAX); DWORD oldLOD = m_LOD; m_LOD = (BYTE)LOD; return oldLOD; } // Method for UpdateTexture to call; does type-specific // parameter checking before calling UpdateDirtyPortion virtual HRESULT UpdateTexture(CBaseTexture *pTextureTarget) PURE; // Parameter validation method to make sure that no part of // the texture is locked. #ifdef DEBUG virtual BOOL IsTextureLocked() PURE; #endif // DEBUG #ifdef DEBUG // DPF helper for explaining why lock failed void ReportWhyLockFailed(void) const; #else // !DEBUG void ReportWhyLockFailed(void) const { // Do Nothing In Retail } // ReportWhyLockFailed #endif // !DEBUG protected: // Remember the format that the user passed in D3DFORMAT m_formatUser; // Currently all textures have a number of levels; // If that changes, then we should create a derived // class CMipTexture and move this data member there. BYTE m_cLevels; // Contains the current LOD for D3D managed textures BYTE m_LOD; // Currently set palette (valid only if format is paletted) WORD m_Palette; // Level Count accessor DWORD GetLevelCountImpl() const { return m_cLevels; }; // GetLevelCountImpl // Function to verify external parameters // to various texture create APIs static HRESULT Validate(CBaseDevice *pDevice, D3DRESOURCETYPE Type, D3DPOOL Pool, DWORD Usage, D3DFORMAT Format); // Infer usage flags based on external parameters // (All inferences MUST be device-independent.) static DWORD InferUsageFlags(D3DPOOL Pool, DWORD Usage, D3DFORMAT Format); // Helper to check if TexBlt is support on this // device for this texture BOOL CanTexBlt(CBaseTexture *pDestTexture) const; // Helper function to scale a Rect down by some // number of powers of two; useful for figuring out // what part of mip-sub-levels to copy static void ScaleRectDown(RECT *pRect, UINT PowersOfTwo = 1); // Box version for volumes static void ScaleBoxDown(D3DBOX *pBox, UINT PowersOfTwo = 1); // Compute Levels for the user static UINT ComputeLevels(UINT width, UINT height = 0, UINT depth = 0); // Common implementation for Set/Get LOD. DWORD SetLODImpl(DWORD LOD); DWORD GetLODImpl(); private: // Textures overload this to call OnTextureDestroy on the // Device before calling Sync. virtual void OnDestroy(void); }; // class CBaseTexture #undef DPF_MODNAME #define DPF_MODNAME "CBaseTexture::CBaseTexture" // Inlines inline CBaseTexture::CBaseTexture( CBaseDevice *pDevice, DWORD cLevels, D3DPOOL UserPool, D3DFORMAT UserFormat, REF_TYPE refType) : CResource(pDevice, UserPool, refType), m_cLevels((BYTE)cLevels), m_Palette(__INVALIDPALETTE), m_formatUser(UserFormat) { DXGASSERT(cLevels > 0 && cLevels < 256); }; // CBaseTexture::CBaseTexture #undef DPF_MODNAME #define DPF_MODNAME "CBaseTexture::SafeCast" // Function to convert a IDirect3DBaseTexture8 * to // a CBaseTexture *. Classes that expose IDirect3DBaseTexture8 // must list CBaseTexture FIRST and IDirect3DFoo8* // SECOND in their list of inheritances. (The Foo8 interface // must itself inherit from IDirect3DBaseTexture8*. inline CBaseTexture * CBaseTexture::SafeCast(IDirect3DBaseTexture8 *pInterface) { if (pInterface == NULL) return NULL; // Textures must by law obey certain layout rules. In // particular the CBaseTexture object must reside precisely // before the IDirect3DBaseTexture8 interface BYTE *pbInt = reinterpret_cast(pInterface); CBaseTexture *pTex = reinterpret_cast(pbInt - sizeof(CBaseTexture)); return pTex; } // CBaseTexture::SafeCast #undef DPF_MODNAME #define DPF_MODNAME "CBaseTexture::ScaleRectDown" // We round down on for left and top; and we round up for // right and bottom inline void CBaseTexture::ScaleRectDown(RECT *pRect, UINT PowersOfTwo) { DXGASSERT(PowersOfTwo > 0); DXGASSERT(PowersOfTwo < 32); DXGASSERT(pRect->right > 0); DXGASSERT(pRect->bottom > 0); DXGASSERT(pRect->left < pRect->right); DXGASSERT(pRect->top < pRect->bottom); DXGASSERT(pRect->left >= 0); DXGASSERT(pRect->top >= 0); // Rounding down is automatic with the shift operator pRect->left >>= PowersOfTwo; pRect->top >>= PowersOfTwo; if (pRect->right & ((1 << PowersOfTwo) - 1)) { pRect->right >>= PowersOfTwo; pRect->right++; } else { pRect->right >>= PowersOfTwo; } if (pRect->bottom & ((1 << PowersOfTwo) - 1)) { pRect->bottom >>= PowersOfTwo; pRect->bottom++; } else { pRect->bottom >>= PowersOfTwo; } return; } // CBaseTexture::ScaleRectDown #undef DPF_MODNAME #define DPF_MODNAME "CBaseTexture::ScaleBoxDown" inline void CBaseTexture::ScaleBoxDown(D3DBOX *pBox, UINT PowersOfTwo) { DXGASSERT(pBox); DXGASSERT(pBox->Front < pBox->Back); DXGASSERT(pBox->Back > 0); ScaleRectDown((RECT*)pBox, PowersOfTwo); // Rounding down is automatic with the shift operator pBox->Front >>= PowersOfTwo; if (pBox->Back & ((1 << PowersOfTwo) - 1)) { pBox->Back >>= PowersOfTwo; pBox->Back++; } else { pBox->Back >>= PowersOfTwo; } } // CBaseTexture::ScaleBoxDown #undef DPF_MODNAME #define DPF_MODNAME "CBaseTexture::ComputeLevels" inline UINT CBaseTexture::ComputeLevels(UINT width, UINT height, // = 0, UINT depth // = 0 ) { UINT maxEdge = max(width, height); maxEdge = max(maxEdge, depth); UINT cLevels = 0; while (maxEdge) { cLevels++; // D3D rule is that sizes round down always maxEdge >>= 1; } return cLevels; } // CBaseTexture::ComputeLevels #endif // __TEXTURE_HPP__