windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/d3d8/fw/texture.hpp
2020-09-26 16:20:57 +08:00

307 lines
8.3 KiB
C++

#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 <limits.h>
#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<BYTE *>(pInterface);
CBaseTexture *pTex = reinterpret_cast<CBaseTexture *>(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__