//-------------------------------------------------------------------------------------- // File: d3dxGlobal.cpp // // Direct3D 11 Effects implementation for helper data structures // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. // // http://go.microsoft.com/fwlink/p/?LinkId=271568 //-------------------------------------------------------------------------------------- #include "pchfx.h" // VS 2010's stdint.h conflicts with intsafe.h #pragma warning(push) #pragma warning(disable : 4005) #include #pragma warning(pop) #include #include namespace D3DX11Core { ////////////////////////////////////////////////////////////////////////// // CMemoryStream - A class to simplify reading binary data ////////////////////////////////////////////////////////////////////////// CMemoryStream::CMemoryStream() : m_pData(nullptr), m_cbData(0), m_readPtr(0) { } CMemoryStream::~CMemoryStream() { } _Use_decl_annotations_ HRESULT CMemoryStream::SetData(const void *pData, size_t size) { m_pData = (uint8_t*) pData; m_cbData = size; m_readPtr = 0; return S_OK; } _Use_decl_annotations_ HRESULT CMemoryStream::ReadAtOffset(size_t offset, size_t size, void **ppData) { if (offset >= m_cbData) return E_FAIL; m_readPtr = offset; return Read(ppData, size); } _Use_decl_annotations_ HRESULT CMemoryStream::ReadAtOffset(size_t offset, LPCSTR *ppString) { if (offset >= m_cbData) return E_FAIL; m_readPtr = offset; return Read(ppString); } _Use_decl_annotations_ HRESULT CMemoryStream::Read(void **ppData, size_t size) { size_t temp = m_readPtr + size; if (temp < m_readPtr || temp > m_cbData) return E_FAIL; *ppData = m_pData + m_readPtr; m_readPtr = temp; return S_OK; } _Use_decl_annotations_ HRESULT CMemoryStream::Read(uint32_t *pDword) { uint32_t *pTempDword; HRESULT hr; hr = Read((void**) &pTempDword, sizeof(uint32_t)); if (FAILED(hr)) return E_FAIL; *pDword = *pTempDword; return S_OK; } _Use_decl_annotations_ HRESULT CMemoryStream::Read(LPCSTR *ppString) { size_t iChar=m_readPtr; for(; m_pData[iChar]; iChar++) { if (iChar > m_cbData) return E_FAIL; } *ppString = (LPCSTR) (m_pData + m_readPtr); m_readPtr = iChar; return S_OK; } size_t CMemoryStream::GetPosition() { return m_readPtr; } HRESULT CMemoryStream::Seek(_In_ size_t offset) { if (offset > m_cbData) return E_FAIL; m_readPtr = offset; return S_OK; } } ////////////////////////////////////////////////////////////////////////// // CDataBlock - used to dynamically build up the effect file in memory ////////////////////////////////////////////////////////////////////////// CDataBlock::CDataBlock() : m_size(0), m_maxSize(0), m_pData(nullptr), m_pNext(nullptr), m_IsAligned(false) { } CDataBlock::~CDataBlock() { SAFE_DELETE_ARRAY(m_pData); SAFE_DELETE(m_pNext); } void CDataBlock::EnableAlignment() { m_IsAligned = true; } _Use_decl_annotations_ HRESULT CDataBlock::AddData(const void *pvNewData, uint32_t bufferSize, CDataBlock **ppBlock) { HRESULT hr = S_OK; uint32_t bytesToCopy; const uint8_t *pNewData = (const uint8_t*) pvNewData; if (m_maxSize == 0) { // This is a brand new DataBlock, fill it up m_maxSize = std::max(8192, bufferSize); VN( m_pData = new uint8_t[m_maxSize] ); } assert(m_pData == AlignToPowerOf2(m_pData, c_DataAlignment)); bytesToCopy = std::min(m_maxSize - m_size, bufferSize); memcpy(m_pData + m_size, pNewData, bytesToCopy); pNewData += bytesToCopy; if (m_IsAligned) { assert(m_size == AlignToPowerOf2(m_size, c_DataAlignment)); m_size += AlignToPowerOf2(bytesToCopy, c_DataAlignment); } else { m_size += bytesToCopy; } bufferSize -= bytesToCopy; *ppBlock = this; if (bufferSize != 0) { assert(nullptr == m_pNext); // make sure we're not overwriting anything // Couldn't fit all data into this block, spill over into next VN( m_pNext = new CDataBlock() ); if (m_IsAligned) { m_pNext->EnableAlignment(); } VH( m_pNext->AddData(pNewData, bufferSize, ppBlock) ); } lExit: return hr; } _Use_decl_annotations_ void* CDataBlock::Allocate(uint32_t bufferSize, CDataBlock **ppBlock) { void *pRetValue; uint32_t temp = m_size + bufferSize; if (temp < m_size) return nullptr; *ppBlock = this; if (m_maxSize == 0) { // This is a brand new DataBlock, fill it up m_maxSize = std::max(8192, bufferSize); m_pData = new uint8_t[m_maxSize]; if (!m_pData) return nullptr; memset(m_pData, 0xDD, m_maxSize); } else if (temp > m_maxSize) { assert(nullptr == m_pNext); // make sure we're not overwriting anything // Couldn't fit data into this block, spill over into next m_pNext = new CDataBlock(); if (!m_pNext) return nullptr; if (m_IsAligned) { m_pNext->EnableAlignment(); } return m_pNext->Allocate(bufferSize, ppBlock); } assert(m_pData == AlignToPowerOf2(m_pData, c_DataAlignment)); pRetValue = m_pData + m_size; if (m_IsAligned) { assert(m_size == AlignToPowerOf2(m_size, c_DataAlignment)); m_size = AlignToPowerOf2(temp, c_DataAlignment); } else { m_size = temp; } return pRetValue; } ////////////////////////////////////////////////////////////////////////// CDataBlockStore::CDataBlockStore() : m_pFirst(nullptr), m_pLast(nullptr), m_Size(0), m_Offset(0), m_IsAligned(false) { #if _DEBUG m_cAllocations = 0; #endif } CDataBlockStore::~CDataBlockStore() { // Can't just do SAFE_DELETE(m_pFirst) since it blows the stack when deleting long chains of data CDataBlock* pData = m_pFirst; while(pData) { CDataBlock* pCurrent = pData; pData = pData->m_pNext; pCurrent->m_pNext = nullptr; delete pCurrent; } // m_pLast will be deleted automatically } void CDataBlockStore::EnableAlignment() { m_IsAligned = true; } _Use_decl_annotations_ HRESULT CDataBlockStore::AddString(LPCSTR pString, uint32_t *pOffset) { size_t strSize = strlen(pString) + 1; assert( strSize <= 0xffffffff ); return AddData(pString, (uint32_t)strSize, pOffset); } _Use_decl_annotations_ HRESULT CDataBlockStore::AddData(const void *pNewData, uint32_t bufferSize, uint32_t *pCurOffset) { HRESULT hr = S_OK; if (bufferSize == 0) { if (pCurOffset) { *pCurOffset = 0; } goto lExit; } if (!m_pFirst) { VN( m_pFirst = new CDataBlock() ); if (m_IsAligned) { m_pFirst->EnableAlignment(); } m_pLast = m_pFirst; } if (pCurOffset) *pCurOffset = m_Size + m_Offset; VH( m_pLast->AddData(pNewData, bufferSize, &m_pLast) ); m_Size += bufferSize; lExit: return hr; } void* CDataBlockStore::Allocate(_In_ uint32_t bufferSize) { void *pRetValue = nullptr; #if _DEBUG m_cAllocations++; #endif if (!m_pFirst) { m_pFirst = new CDataBlock(); if (!m_pFirst) return nullptr; if (m_IsAligned) { m_pFirst->EnableAlignment(); } m_pLast = m_pFirst; } if (FAILED(UIntAdd(m_Size, bufferSize, &m_Size))) return nullptr; pRetValue = m_pLast->Allocate(bufferSize, &m_pLast); if (!pRetValue) return nullptr; return pRetValue; } uint32_t CDataBlockStore::GetSize() { return m_Size; } ////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG _Use_decl_annotations_ void __cdecl D3DXDebugPrintf(UINT lvl, LPCSTR szFormat, ...) { UNREFERENCED_PARAMETER(lvl); char strA[4096]; char strB[4096]; va_list ap; va_start(ap, szFormat); vsprintf_s(strA, sizeof(strA), szFormat, ap); strA[4095] = '\0'; va_end(ap); sprintf_s(strB, sizeof(strB), "Effects11: %s\r\n", strA); strB[4095] = '\0'; OutputDebugStringA(strB); } #endif // _DEBUG