196 lines
5.5 KiB
C++
196 lines
5.5 KiB
C++
|
#ifndef __VOLUME_HPP__
|
||
|
#define __VOLUME_HPP__
|
||
|
|
||
|
/*==========================================================================;
|
||
|
*
|
||
|
* Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: volume.hpp
|
||
|
* Content: Class header the volume class. This class acts
|
||
|
* as a level for the MipVolume class. The base class
|
||
|
* assumes a system-memory allocation; while the
|
||
|
* Driver sub-class will call the driver for every
|
||
|
* lock and unlock operation.
|
||
|
*
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
// Includes
|
||
|
#include "mipvol.hpp"
|
||
|
|
||
|
//
|
||
|
// Each Volume implements the IDirect3DVolume8 interface.
|
||
|
// To reduce overhead per level, we have
|
||
|
// put most of the "real" guts of each volume into the MipVolume container
|
||
|
// class; i.e. most of the methods of the Volume really just end
|
||
|
// up calling something in the MipVolume object.
|
||
|
//
|
||
|
// The base class implementation assumes a sys-mem allocation.
|
||
|
//
|
||
|
|
||
|
|
||
|
//
|
||
|
// The CVolume class is a special class that
|
||
|
// works solely with the CMipVolume class. Each Volume
|
||
|
// corresponds to a single level of the mip-volume. They are
|
||
|
// not stand-alone COM objects because they share the
|
||
|
// same life-time as their CMipVolume parent.
|
||
|
//
|
||
|
// The CDriverVolume class is declared later in this file
|
||
|
//
|
||
|
|
||
|
class CVolume : public IDirect3DVolume8
|
||
|
{
|
||
|
public:
|
||
|
// Constructor
|
||
|
CVolume(CMipVolume *pParent,
|
||
|
BYTE iLevel,
|
||
|
HANDLE hKernelHandle
|
||
|
) :
|
||
|
m_pParent(pParent),
|
||
|
m_isLocked(FALSE),
|
||
|
m_iLevel(iLevel),
|
||
|
m_hKernelHandle(hKernelHandle)
|
||
|
{
|
||
|
DXGASSERT(pParent);
|
||
|
DXGASSERT(hKernelHandle || (pParent->GetUserPool() == D3DPOOL_SCRATCH) );
|
||
|
#ifdef DEBUG
|
||
|
m_cRefDebug = 0;
|
||
|
#endif // DEBUG
|
||
|
|
||
|
if (m_pParent->Desc()->Usage &
|
||
|
(D3DUSAGE_LOCK | D3DUSAGE_LOADONCE))
|
||
|
{
|
||
|
m_isLockable = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_isLockable = FALSE;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
} // CVolume
|
||
|
|
||
|
~CVolume()
|
||
|
{
|
||
|
DXGASSERT(m_cRefDebug == 0);
|
||
|
if (m_pParent->GetUserPool() != D3DPOOL_SCRATCH)
|
||
|
{
|
||
|
// Tell the thunk layer that we need to
|
||
|
// be freed.
|
||
|
DXGASSERT(m_hKernelHandle);
|
||
|
|
||
|
D3D8_DESTROYSURFACEDATA DestroySurfData;
|
||
|
DestroySurfData.hDD = m_pParent->Device()->GetHandle();
|
||
|
DestroySurfData.hSurface = m_hKernelHandle;
|
||
|
m_pParent->Device()->GetHalCallbacks()->DestroySurface(&DestroySurfData);
|
||
|
}
|
||
|
#ifdef DEBUG
|
||
|
else
|
||
|
{
|
||
|
DXGASSERT(m_pParent->GetUserPool() == D3DPOOL_SCRATCH);
|
||
|
}
|
||
|
#endif //DEBUG
|
||
|
}; // ~CVolume
|
||
|
|
||
|
public:
|
||
|
// IUnknown methods
|
||
|
STDMETHOD(QueryInterface) (REFIID riid,
|
||
|
VOID **ppvObj);
|
||
|
STDMETHOD_(ULONG,AddRef) ();
|
||
|
STDMETHOD_(ULONG,Release) ();
|
||
|
|
||
|
// IBuffer methods
|
||
|
STDMETHOD(SetPrivateData)(REFGUID riid,
|
||
|
CONST VOID *pvData,
|
||
|
DWORD cbData,
|
||
|
DWORD dwFlags);
|
||
|
|
||
|
STDMETHOD(GetPrivateData)(REFGUID riid,
|
||
|
VOID *pvData,
|
||
|
DWORD *pcbData);
|
||
|
|
||
|
STDMETHOD(FreePrivateData)(REFGUID riid);
|
||
|
|
||
|
STDMETHOD(GetContainer)(REFIID riid,
|
||
|
void **ppContainer);
|
||
|
|
||
|
STDMETHOD(GetDevice)(IDirect3DDevice8 **ppDevice);
|
||
|
|
||
|
// IDirect3DVolume8 methods
|
||
|
STDMETHOD(GetDesc)(D3DVOLUME_DESC *pDesc);
|
||
|
|
||
|
STDMETHOD(LockBox)(D3DLOCKED_BOX *pLockedBox,
|
||
|
CONST D3DBOX *pBox,
|
||
|
DWORD dwFlags);
|
||
|
STDMETHOD(UnlockBox)(void);
|
||
|
|
||
|
virtual HRESULT InternalLockBox(D3DLOCKED_BOX *pLockedBox,
|
||
|
CONST D3DBOX *pBox,
|
||
|
DWORD dwFlags);
|
||
|
virtual HRESULT InternalUnlockBox();
|
||
|
|
||
|
BOOL IsLocked() const
|
||
|
{
|
||
|
return m_isLocked;
|
||
|
} // IsLocked
|
||
|
|
||
|
protected:
|
||
|
CMipVolume *m_pParent;
|
||
|
BOOL m_isLocked;
|
||
|
BOOL m_isLockable;
|
||
|
BYTE m_iLevel;
|
||
|
|
||
|
// We'll need internal handles so that
|
||
|
// we can communicate call Destroy
|
||
|
// and so that CDriverVolume can call
|
||
|
// Lock/Unlock etc.
|
||
|
HANDLE m_hKernelHandle;
|
||
|
|
||
|
CBaseDevice * Device() const
|
||
|
{
|
||
|
return m_pParent->Device();
|
||
|
} // Device
|
||
|
|
||
|
// Debugging trick to help spew better
|
||
|
// information if someone over-releases a volume
|
||
|
// (Since our ref's carry over to the parent object; it
|
||
|
// means that over-releases can be hard to find.)
|
||
|
#ifdef DEBUG
|
||
|
DWORD m_cRefDebug;
|
||
|
#endif // DEBUG
|
||
|
|
||
|
}; // CVolume
|
||
|
|
||
|
// The CDriverVolume is a modification of the base volume
|
||
|
// class. It overrides lock and unlock and routes the call to the
|
||
|
// driver
|
||
|
class CDriverVolume : public CVolume
|
||
|
{
|
||
|
public:
|
||
|
// Constructor
|
||
|
CDriverVolume(CMipVolume *pParent,
|
||
|
BYTE iLevel,
|
||
|
HANDLE hKernelHandle
|
||
|
) :
|
||
|
CVolume(pParent, iLevel, hKernelHandle)
|
||
|
{
|
||
|
} // CDriverVolume
|
||
|
|
||
|
public:
|
||
|
|
||
|
STDMETHOD(LockBox)(D3DLOCKED_BOX *pLockedBox,
|
||
|
CONST D3DBOX *pBox,
|
||
|
DWORD dwFlags);
|
||
|
STDMETHOD(UnlockBox)();
|
||
|
|
||
|
virtual HRESULT InternalLockBox(D3DLOCKED_BOX *pLockedBox,
|
||
|
CONST D3DBOX *pBox,
|
||
|
DWORD dwFlags);
|
||
|
virtual HRESULT InternalUnlockBox();
|
||
|
|
||
|
}; // CDriverVolume
|
||
|
|
||
|
|
||
|
#endif // __VOLUME_HPP__
|