Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: atv2
Fetching contributors…

Cannot retrieve contributors at this time

457 lines (402 sloc) 9.885 kB
/*
* Copyright (C) 2005-2008 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "system.h"
#include "D3DResource.h"
#include "WindowingFactory.h"
#include "utils/log.h"
#ifdef HAS_DX
using namespace std;
CD3DTexture::CD3DTexture()
{
m_width = 0;
m_height = 0;
m_mipLevels = 0;
m_usage = 0;
m_format = D3DFMT_A8R8G8B8;
m_pool = D3DPOOL_DEFAULT;
m_texture = NULL;
m_data = NULL;
m_pitch = 0;
}
CD3DTexture::~CD3DTexture()
{
Release();
delete[] m_data;
}
bool CD3DTexture::Create(UINT width, UINT height, UINT mipLevels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
{
m_width = width;
m_height = height;
m_mipLevels = mipLevels;
m_usage = usage;
m_format = format;
m_pool = pool;
// create the texture
Release();
HRESULT hr = D3DXCreateTexture(g_Windowing.Get3DDevice(), m_width, m_height, m_mipLevels, m_usage, m_format, m_pool, &m_texture);
if (FAILED(hr))
{
CLog::Log(LOGERROR, __FUNCTION__" - failed 0x%08X", hr);
}
else
{
D3DSURFACE_DESC desc;
if( D3D_OK == m_texture->GetLevelDesc(0, &desc))
{
if(desc.Format != m_format)
CLog::Log(LOGWARNING, "CD3DTexture::Create - format changed from %d to %d", m_format, desc.Format);
if(desc.Height != m_height || desc.Width != m_width)
CLog::Log(LOGWARNING, "CD3DTexture::Create - size changed from %ux%u to %ux%u", m_width, m_height, desc.Width, desc.Height);
}
g_Windowing.Register(this);
return true;
}
return false;
}
void CD3DTexture::Release()
{
g_Windowing.Unregister(this);
SAFE_RELEASE(m_texture);
}
bool CD3DTexture::LockRect(UINT level, D3DLOCKED_RECT *lr, const RECT *rect, DWORD flags)
{
if (m_texture)
{
if ((flags & D3DLOCK_DISCARD) && !(m_usage & D3DUSAGE_DYNAMIC))
flags &= ~D3DLOCK_DISCARD;
return (D3D_OK == m_texture->LockRect(level, lr, rect, flags));
}
return false;
}
bool CD3DTexture::UnlockRect(UINT level)
{
if (m_texture)
return (D3D_OK == m_texture->UnlockRect(level));
return false;
}
bool CD3DTexture::GetLevelDesc(UINT level, D3DSURFACE_DESC *desc)
{
if (m_texture)
return (D3D_OK == m_texture->GetLevelDesc(level, desc));
return false;
}
bool CD3DTexture::GetSurfaceLevel(UINT level, LPDIRECT3DSURFACE9 *surface)
{
if (m_texture)
return (D3D_OK == m_texture->GetSurfaceLevel(level, surface));
return false;
}
void CD3DTexture::SaveTexture()
{
if (m_texture)
{
delete[] m_data;
m_data = NULL;
if(!(m_usage & D3DUSAGE_RENDERTARGET)
&& !(m_usage & D3DUSAGE_DEPTHSTENCIL)
&& !(m_pool == D3DPOOL_DEFAULT && (m_usage & D3DUSAGE_DYNAMIC) == 0))
{
D3DLOCKED_RECT lr;
if (LockRect( 0, &lr, NULL, D3DLOCK_READONLY ))
{
m_pitch = lr.Pitch;
unsigned int memUsage = GetMemoryUsage(lr.Pitch);
m_data = new unsigned char[memUsage];
memcpy(m_data, lr.pBits, memUsage);
UnlockRect(0);
}
}
}
SAFE_RELEASE(m_texture);
}
void CD3DTexture::OnDestroyDevice()
{
SaveTexture();
}
void CD3DTexture::OnLostDevice()
{
if (m_pool == D3DPOOL_DEFAULT)
SaveTexture();
}
void CD3DTexture::RestoreTexture()
{
// yay, we're back - make a new copy of the texture
if (!m_texture)
{
HRESULT hr = D3DXCreateTexture(g_Windowing.Get3DDevice(), m_width, m_height, m_mipLevels, m_usage, m_format, m_pool, &m_texture);
if (FAILED(hr))
{
CLog::Log(LOGERROR, __FUNCTION__": D3DXCreateTexture failed 0x%08X", hr);
}
else
{
// copy the data to the texture
D3DLOCKED_RECT lr;
if (m_texture && m_data && LockRect(0, &lr, NULL, D3DLOCK_DISCARD ))
{
if (lr.Pitch == m_pitch)
memcpy(lr.pBits, m_data, GetMemoryUsage(lr.Pitch));
else
{
UINT minpitch = ((UINT)lr.Pitch < m_pitch) ? lr.Pitch : m_pitch;
for(UINT i = 0; i < m_height; ++i)
{
// Get pointers to the "rows" of pixels in texture
BYTE* pBits = (BYTE*)lr.pBits + i*lr.Pitch;
BYTE* pData = m_data + i*m_pitch;
memcpy(pBits, pData, minpitch);
}
}
UnlockRect(0);
}
}
delete[] m_data;
m_data = NULL;
m_pitch = 0;
}
}
void CD3DTexture::OnCreateDevice()
{
RestoreTexture();
}
void CD3DTexture::OnResetDevice()
{
if (m_pool == D3DPOOL_DEFAULT)
RestoreTexture();
}
unsigned int CD3DTexture::GetMemoryUsage(unsigned int pitch) const
{
switch (m_format)
{
case D3DFMT_DXT1:
case D3DFMT_DXT3:
case D3DFMT_DXT5:
return pitch * m_height / 4;
default:
return pitch * m_height;
}
}
CD3DEffect::CD3DEffect()
{
m_effect = NULL;
}
CD3DEffect::~CD3DEffect()
{
Release();
}
bool CD3DEffect::Create(const CStdString &effectString, DefinesMap* defines)
{
Release();
m_effectString = effectString;
m_defines.clear();
if (defines != NULL)
m_defines = *defines; //FIXME: is this a copy of all members?
if (CreateEffect())
{
g_Windowing.Register(this);
return true;
}
return false;
}
void CD3DEffect::Release()
{
g_Windowing.Unregister(this);
SAFE_RELEASE(m_effect);
}
void CD3DEffect::OnDestroyDevice()
{
SAFE_RELEASE(m_effect);
}
void CD3DEffect::OnCreateDevice()
{
CreateEffect();
}
bool CD3DEffect::SetFloatArray(D3DXHANDLE handle, const float* val, unsigned int count)
{
if(m_effect)
return (D3D_OK == m_effect->SetFloatArray(handle, val, count));
return false;
}
bool CD3DEffect::SetMatrix(D3DXHANDLE handle, const D3DXMATRIX* mat)
{
if (m_effect)
return (D3D_OK == m_effect->SetMatrix(handle, mat));
return false;
}
bool CD3DEffect::SetTechnique(D3DXHANDLE handle)
{
if (m_effect)
return (D3D_OK == m_effect->SetTechnique(handle));
return false;
}
bool CD3DEffect::SetTexture(D3DXHANDLE handle, CD3DTexture &texture)
{
if (m_effect)
return (D3D_OK == m_effect->SetTexture(handle, texture.Get()));
return false;
}
bool CD3DEffect::Begin(UINT *passes, DWORD flags)
{
if (m_effect)
return (D3D_OK == m_effect->Begin(passes, flags));
return false;
}
bool CD3DEffect::BeginPass(UINT pass)
{
if (m_effect)
return (D3D_OK == m_effect->BeginPass(pass));
return false;
}
bool CD3DEffect::EndPass()
{
if (m_effect)
return (D3D_OK == m_effect->EndPass());
return false;
}
bool CD3DEffect::End()
{
if (m_effect)
return (D3D_OK == m_effect->End());
return false;
}
bool CD3DEffect::CreateEffect()
{
HRESULT hr;
LPD3DXBUFFER pError = NULL;
std::vector<D3DXMACRO> definemacros;
for( DefinesMap::const_iterator it = m_defines.begin(); it != m_defines.end(); ++it )
{
D3DXMACRO m;
m.Name = it->first.c_str();
if (it->second.IsEmpty())
m.Definition = NULL;
else
m.Definition = it->second.c_str();
definemacros.push_back( m );
}
definemacros.push_back(D3DXMACRO());
definemacros.back().Name = 0;
definemacros.back().Definition = 0;
hr = D3DXCreateEffect(g_Windowing.Get3DDevice(), m_effectString, m_effectString.length(), &definemacros[0], NULL, 0, NULL, &m_effect, &pError );
if(hr == S_OK)
return true;
else if(pError)
{
CStdString error;
error.assign((const char*)pError->GetBufferPointer(), pError->GetBufferSize());
CLog::Log(LOGERROR, "%s", error.c_str());
}
return false;
}
void CD3DEffect::OnLostDevice()
{
if (m_effect)
m_effect->OnLostDevice();
}
void CD3DEffect::OnResetDevice()
{
if (m_effect)
m_effect->OnResetDevice();
}
CD3DVertexBuffer::CD3DVertexBuffer()
{
m_length = 0;
m_usage = 0;
m_fvf = 0;
m_pool = D3DPOOL_DEFAULT;
m_vertex = NULL;
m_data = NULL;
}
CD3DVertexBuffer::~CD3DVertexBuffer()
{
Release();
delete[] m_data;
}
bool CD3DVertexBuffer::Create(UINT length, DWORD usage, DWORD fvf, D3DPOOL pool)
{
m_length = length;
m_usage = usage;
m_fvf = fvf;
m_pool = pool;
// create the vertex buffer
Release();
if (CreateVertexBuffer())
{
g_Windowing.Register(this);
return true;
}
return false;
}
void CD3DVertexBuffer::Release()
{
g_Windowing.Unregister(this);
SAFE_RELEASE(m_vertex);
}
bool CD3DVertexBuffer::Lock(UINT level, UINT size, void **data, DWORD flags)
{
if (m_vertex)
return (D3D_OK == m_vertex->Lock(level, size, data, flags));
return false;
}
bool CD3DVertexBuffer::Unlock()
{
if (m_vertex)
return (D3D_OK == m_vertex->Unlock());
return false;
}
void CD3DVertexBuffer::OnDestroyDevice()
{
if (m_vertex)
{
delete[] m_data;
m_data = NULL;
void* data;
if (Lock(0, 0, &data, 0))
{
m_data = new BYTE[m_length];
memcpy(m_data, data, m_length);
Unlock();
}
}
SAFE_RELEASE(m_vertex);
}
void CD3DVertexBuffer::OnCreateDevice()
{
// yay, we're back - make a new copy of the vertices
if (!m_vertex && m_data && CreateVertexBuffer())
{
void *data = NULL;
if (Lock(0, 0, &data, 0))
{
memcpy(data, m_data, m_length);
Unlock();
}
delete[] m_data;
m_data = NULL;
}
}
bool CD3DVertexBuffer::CreateVertexBuffer()
{
if (D3D_OK == g_Windowing.Get3DDevice()->CreateVertexBuffer(m_length, m_usage, m_fvf, m_pool, &m_vertex, NULL))
return true;
return false;
}
#endif
Jump to Line
Something went wrong with that request. Please try again.