255 lines
6.9 KiB
C++
255 lines
6.9 KiB
C++
|
/*==========================================================================;
|
||
|
*
|
||
|
* Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: buffer.cpp
|
||
|
* Content: Implementation of the CBuffer class.
|
||
|
*
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "ddrawpr.h"
|
||
|
|
||
|
#include "buffer.hpp"
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CBuffer::CBuffer"
|
||
|
|
||
|
// Constructor returns an error code
|
||
|
// if the object could not be fully
|
||
|
// constructed
|
||
|
CBuffer::CBuffer(CBaseDevice *pDevice,
|
||
|
DWORD cbLength,
|
||
|
DWORD dwFVF,
|
||
|
D3DFORMAT Format,
|
||
|
D3DRESOURCETYPE Type,
|
||
|
DWORD dwUsage,
|
||
|
DWORD dwActualUsage,
|
||
|
D3DPOOL Pool,
|
||
|
D3DPOOL ActualPool,
|
||
|
REF_TYPE refType,
|
||
|
HRESULT *phr
|
||
|
) :
|
||
|
CResource(pDevice, Pool, refType),
|
||
|
m_pbBuffer(NULL),
|
||
|
#if DBG
|
||
|
m_isLockable((dwActualUsage & (D3DUSAGE_LOCK | D3DUSAGE_LOADONCE)) != 0),
|
||
|
m_SceneStamp(0xFFFFFFFF),
|
||
|
m_TimesLocked(0),
|
||
|
#endif // DBG
|
||
|
m_LockCount(0)
|
||
|
{
|
||
|
// Determine if we need to allocate
|
||
|
// any memory
|
||
|
if (ActualPool == D3DPOOL_SYSTEMMEM ||
|
||
|
IsTypeD3DManaged(pDevice, Type, ActualPool))
|
||
|
{
|
||
|
// cbLength must be a DWORD multiple
|
||
|
cbLength = (cbLength + 3) & (DWORD) ~3;
|
||
|
|
||
|
m_pbBuffer = new BYTE[cbLength];
|
||
|
|
||
|
if (m_pbBuffer == NULL)
|
||
|
{
|
||
|
DPF_ERR("Out Of Memory allocating vertex or index buffer");
|
||
|
*phr = E_OUTOFMEMORY;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DXGASSERT((cbLength & 3) == 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
// We need to call the driver
|
||
|
// to get a handle for all cases
|
||
|
|
||
|
// Create a DDSURFACEINFO and CreateSurfaceData object
|
||
|
DDSURFACEINFO SurfInfo;
|
||
|
ZeroMemory(&SurfInfo, sizeof(SurfInfo));
|
||
|
|
||
|
D3D8_CREATESURFACEDATA CreateSurfaceData;
|
||
|
ZeroMemory(&CreateSurfaceData, sizeof(CreateSurfaceData));
|
||
|
|
||
|
// Set up the basic information
|
||
|
CreateSurfaceData.hDD = pDevice->GetHandle();
|
||
|
CreateSurfaceData.pSList = &SurfInfo;
|
||
|
CreateSurfaceData.dwSCnt = 1;
|
||
|
CreateSurfaceData.Type = Type;
|
||
|
CreateSurfaceData.dwUsage = dwActualUsage;
|
||
|
CreateSurfaceData.Pool = DetermineCreationPool(Device(), Type, dwActualUsage, ActualPool);
|
||
|
CreateSurfaceData.Format = Format;
|
||
|
CreateSurfaceData.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||
|
CreateSurfaceData.dwFVF = dwFVF;
|
||
|
|
||
|
if (Pool == D3DPOOL_DEFAULT &&
|
||
|
CreateSurfaceData.Pool == D3DPOOL_SYSTEMMEM)
|
||
|
{
|
||
|
// If we are using sys-mem in cases where the
|
||
|
// user asked for POOL_DEFAULT, we need to let
|
||
|
// the thunk layer know so that Reset will
|
||
|
// fail if this buffer hasn't been released
|
||
|
CreateSurfaceData.bTreatAsVidMem = TRUE;
|
||
|
}
|
||
|
|
||
|
// Specify the surface data
|
||
|
SurfInfo.cpWidth = cbLength;
|
||
|
SurfInfo.cpHeight = 1;
|
||
|
SurfInfo.pbPixels = m_pbBuffer;
|
||
|
SurfInfo.iPitch = cbLength;
|
||
|
|
||
|
// Call thunk to get our handles
|
||
|
*phr = pDevice->GetHalCallbacks()->CreateSurface(&CreateSurfaceData);
|
||
|
if (FAILED(*phr))
|
||
|
return;
|
||
|
|
||
|
// Cache away our handle
|
||
|
SetKernelHandle(SurfInfo.hKernelHandle);
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // CBuffer::CBuffer
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CBuffer::~CBuffer"
|
||
|
|
||
|
// Destructor
|
||
|
CBuffer::~CBuffer()
|
||
|
{
|
||
|
// Tell the thunk layer that we need to
|
||
|
// be freed.
|
||
|
if (CBaseObject::BaseKernelHandle())
|
||
|
{
|
||
|
D3D8_DESTROYSURFACEDATA DestroySurfData;
|
||
|
DestroySurfData.hDD = Device()->GetHandle();
|
||
|
DestroySurfData.hSurface = CBaseObject::BaseKernelHandle();
|
||
|
Device()->GetHalCallbacks()->DestroySurface(&DestroySurfData);
|
||
|
}
|
||
|
|
||
|
delete [] m_pbBuffer;
|
||
|
|
||
|
} // CBuffer::~CBuffer
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CBuffer::OnBufferChangeImpl"
|
||
|
|
||
|
void CBuffer::OnBufferChangeImpl(UINT cbOffsetToLock, UINT cbSizeToLock)
|
||
|
{
|
||
|
// 0 for cbSizeToLock; means the rest of the buffer
|
||
|
// We use this as a special value.
|
||
|
DWORD cbOffsetMax;
|
||
|
if (cbSizeToLock == 0)
|
||
|
cbOffsetMax = 0;
|
||
|
else
|
||
|
cbOffsetMax = cbOffsetToLock + cbSizeToLock;
|
||
|
|
||
|
if (!IsDirty())
|
||
|
{
|
||
|
m_cbDirtyMin = cbOffsetToLock;
|
||
|
m_cbDirtyMax = cbOffsetMax;
|
||
|
OnResourceDirty();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (m_cbDirtyMin > cbOffsetToLock)
|
||
|
m_cbDirtyMin = cbOffsetToLock;
|
||
|
|
||
|
// An cbOffsetMax of zero means all the way to the
|
||
|
// end of the buffer
|
||
|
if (m_cbDirtyMax < cbOffsetMax || cbOffsetMax == 0)
|
||
|
m_cbDirtyMax = cbOffsetMax;
|
||
|
|
||
|
// We should already be marked as dirty
|
||
|
DXGASSERT(IsDirty());
|
||
|
}
|
||
|
return;
|
||
|
} // OnBufferChangeImpl
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CBuffer::MarkAllDirty"
|
||
|
|
||
|
void CBuffer::MarkAllDirty()
|
||
|
{
|
||
|
// Mark our dirty bounds as being the whole
|
||
|
// thing.
|
||
|
m_cbDirtyMin = 0;
|
||
|
|
||
|
// Zero for max is a special value meaning
|
||
|
// all they way to the end
|
||
|
m_cbDirtyMax = 0;
|
||
|
|
||
|
// Mark ourselves as dirty
|
||
|
OnResourceDirty();
|
||
|
} // CBuffer::MarkAllDirty
|
||
|
|
||
|
// Methods for CCommandBuffer
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CCommandBuffer::Create"
|
||
|
|
||
|
// Static class function for creating a command buffer object.
|
||
|
// (Because it is static; it doesn't have a this pointer.)
|
||
|
|
||
|
// Creation function for Command Buffers
|
||
|
HRESULT CCommandBuffer::Create(CBaseDevice *pDevice,
|
||
|
DWORD cbLength,
|
||
|
D3DPOOL Pool,
|
||
|
CCommandBuffer **ppCmdBuffer)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
// Zero-out return parameter
|
||
|
*ppCmdBuffer = NULL;
|
||
|
|
||
|
// Allocate new buffer
|
||
|
CCommandBuffer *pCmdBuffer;
|
||
|
DXGASSERT(Pool == D3DPOOL_SYSTEMMEM);
|
||
|
pCmdBuffer = new CCommandBuffer(pDevice,
|
||
|
cbLength,
|
||
|
Pool,
|
||
|
&hr);
|
||
|
|
||
|
if (pCmdBuffer == NULL)
|
||
|
{
|
||
|
DPF_ERR("Out of Memory creating command buffer");
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
// Command buffers are always internal and hence
|
||
|
// need to be released through DecrementUseCount
|
||
|
DPF_ERR("Error during initialization of command buffer");
|
||
|
pCmdBuffer->DecrementUseCount();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// We're done; just return the object
|
||
|
*ppCmdBuffer = pCmdBuffer;
|
||
|
|
||
|
return hr;
|
||
|
} // static CCommandBuffer::Create
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CCommandBuffer::Clone"
|
||
|
|
||
|
HRESULT CCommandBuffer::Clone(D3DPOOL Pool,
|
||
|
CResource **ppResource) const
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
*ppResource = new CCommandBuffer(Device(), m_cbLength, Pool, &hr);
|
||
|
if (*ppResource == NULL)
|
||
|
{
|
||
|
DPF_ERR("Failed to allocate command buffer");
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
DPF_ERR("Failure creating command buffer");
|
||
|
}
|
||
|
return hr;
|
||
|
} // CCommandBuffer::Clone
|
||
|
|
||
|
|
||
|
|
||
|
// End of file : buffer.cpp
|