2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "D3DResource.h"
23 #include "windowing/WindowingFactory.h"
24 #include "utils/log.h"
30 CD3DTexture::CD3DTexture()
36 m_format = D3DFMT_A8R8G8B8;
37 m_pool = D3DPOOL_DEFAULT;
43 CD3DTexture::~CD3DTexture()
49 bool CD3DTexture::Create(UINT width, UINT height, UINT mipLevels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
53 m_mipLevels = mipLevels;
59 HRESULT hr = D3DXCreateTexture(g_Windowing.Get3DDevice(), m_width, m_height, m_mipLevels, m_usage, m_format, m_pool, &m_texture);
62 CLog::Log(LOGERROR, __FUNCTION__" - failed 0x%08X", hr);
67 if( D3D_OK == m_texture->GetLevelDesc(0, &desc))
69 if(desc.Format != m_format)
70 CLog::Log(LOGWARNING, "CD3DTexture::Create - format changed from %d to %d", m_format, desc.Format);
71 if(desc.Height != m_height || desc.Width != m_width)
72 CLog::Log(LOGWARNING, "CD3DTexture::Create - size changed from %ux%u to %ux%u", m_width, m_height, desc.Width, desc.Height);
75 g_Windowing.Register(this);
81 void CD3DTexture::Release()
83 g_Windowing.Unregister(this);
84 SAFE_RELEASE(m_texture);
87 bool CD3DTexture::LockRect(UINT level, D3DLOCKED_RECT *lr, const RECT *rect, DWORD flags)
91 if ((flags & D3DLOCK_DISCARD) && !(m_usage & D3DUSAGE_DYNAMIC))
92 flags &= ~D3DLOCK_DISCARD;
93 return (D3D_OK == m_texture->LockRect(level, lr, rect, flags));
98 bool CD3DTexture::UnlockRect(UINT level)
101 return (D3D_OK == m_texture->UnlockRect(level));
105 bool CD3DTexture::GetLevelDesc(UINT level, D3DSURFACE_DESC *desc)
108 return (D3D_OK == m_texture->GetLevelDesc(level, desc));
112 bool CD3DTexture::GetSurfaceLevel(UINT level, LPDIRECT3DSURFACE9 *surface)
115 return (D3D_OK == m_texture->GetSurfaceLevel(level, surface));
119 void CD3DTexture::SaveTexture()
125 if(!(m_usage & D3DUSAGE_RENDERTARGET)
126 && !(m_usage & D3DUSAGE_DEPTHSTENCIL)
127 && !(m_pool == D3DPOOL_DEFAULT && (m_usage & D3DUSAGE_DYNAMIC) == 0))
130 if (LockRect( 0, &lr, NULL, D3DLOCK_READONLY ))
133 unsigned int memUsage = GetMemoryUsage(lr.Pitch);
134 m_data = new unsigned char[memUsage];
135 memcpy(m_data, lr.pBits, memUsage);
140 SAFE_RELEASE(m_texture);
143 void CD3DTexture::OnDestroyDevice()
148 void CD3DTexture::OnLostDevice()
150 if (m_pool == D3DPOOL_DEFAULT)
154 void CD3DTexture::RestoreTexture()
156 // yay, we're back - make a new copy of the texture
159 HRESULT hr = D3DXCreateTexture(g_Windowing.Get3DDevice(), m_width, m_height, m_mipLevels, m_usage, m_format, m_pool, &m_texture);
162 CLog::Log(LOGERROR, __FUNCTION__": D3DXCreateTexture failed 0x%08X", hr);
166 // copy the data to the texture
168 if (m_texture && m_data && LockRect(0, &lr, NULL, D3DLOCK_DISCARD ))
170 if (lr.Pitch == m_pitch)
171 memcpy(lr.pBits, m_data, GetMemoryUsage(lr.Pitch));
174 UINT minpitch = ((UINT)lr.Pitch < m_pitch) ? lr.Pitch : m_pitch;
176 for(UINT i = 0; i < m_height; ++i)
178 // Get pointers to the "rows" of pixels in texture
179 BYTE* pBits = (BYTE*)lr.pBits + i*lr.Pitch;
180 BYTE* pData = m_data + i*m_pitch;
181 memcpy(pBits, pData, minpitch);
194 void CD3DTexture::OnCreateDevice()
199 void CD3DTexture::OnResetDevice()
201 if (m_pool == D3DPOOL_DEFAULT)
206 unsigned int CD3DTexture::GetMemoryUsage(unsigned int pitch) const
213 return pitch * m_height / 4;
215 return pitch * m_height;
219 CD3DEffect::CD3DEffect()
224 CD3DEffect::~CD3DEffect()
229 bool CD3DEffect::Create(const CStdString &effectString, DefinesMap* defines)
232 m_effectString = effectString;
235 m_defines = *defines; //FIXME: is this a copy of all members?
238 g_Windowing.Register(this);
244 void CD3DEffect::Release()
246 g_Windowing.Unregister(this);
247 SAFE_RELEASE(m_effect);
250 void CD3DEffect::OnDestroyDevice()
252 SAFE_RELEASE(m_effect);
255 void CD3DEffect::OnCreateDevice()
260 bool CD3DEffect::SetFloatArray(D3DXHANDLE handle, const float* val, unsigned int count)
263 return (D3D_OK == m_effect->SetFloatArray(handle, val, count));
267 bool CD3DEffect::SetMatrix(D3DXHANDLE handle, const D3DXMATRIX* mat)
270 return (D3D_OK == m_effect->SetMatrix(handle, mat));
274 bool CD3DEffect::SetTechnique(D3DXHANDLE handle)
277 return (D3D_OK == m_effect->SetTechnique(handle));
281 bool CD3DEffect::SetTexture(D3DXHANDLE handle, CD3DTexture &texture)
284 return (D3D_OK == m_effect->SetTexture(handle, texture.Get()));
288 bool CD3DEffect::Begin(UINT *passes, DWORD flags)
291 return (D3D_OK == m_effect->Begin(passes, flags));
295 bool CD3DEffect::BeginPass(UINT pass)
298 return (D3D_OK == m_effect->BeginPass(pass));
302 bool CD3DEffect::EndPass()
305 return (D3D_OK == m_effect->EndPass());
309 bool CD3DEffect::End()
312 return (D3D_OK == m_effect->End());
316 bool CD3DEffect::CreateEffect()
319 LPD3DXBUFFER pError = NULL;
321 std::vector<D3DXMACRO> definemacros;
323 for( DefinesMap::const_iterator it = m_defines.begin(); it != m_defines.end(); ++it )
326 m.Name = it->first.c_str();
327 if (it->second.empty())
330 m.Definition = it->second.c_str();
331 definemacros.push_back( m );
334 definemacros.push_back(D3DXMACRO());
335 definemacros.back().Name = 0;
336 definemacros.back().Definition = 0;
338 hr = D3DXCreateEffect(g_Windowing.Get3DDevice(), m_effectString, m_effectString.length(), &definemacros[0], NULL, 0, NULL, &m_effect, &pError );
344 error.assign((const char*)pError->GetBufferPointer(), pError->GetBufferSize());
345 CLog::Log(LOGERROR, "CD3DEffect::CreateEffect(): %s", error.c_str());
348 CLog::Log(LOGERROR, "CD3DEffect::CreateEffect(): call to D3DXCreateEffect() failed with %" PRId32, hr);
352 void CD3DEffect::OnLostDevice()
355 m_effect->OnLostDevice();
358 void CD3DEffect::OnResetDevice()
361 m_effect->OnResetDevice();
364 CD3DVertexBuffer::CD3DVertexBuffer()
369 m_pool = D3DPOOL_DEFAULT;
374 CD3DVertexBuffer::~CD3DVertexBuffer()
380 bool CD3DVertexBuffer::Create(UINT length, DWORD usage, DWORD fvf, D3DPOOL pool)
387 // create the vertex buffer
389 if (CreateVertexBuffer())
391 g_Windowing.Register(this);
397 void CD3DVertexBuffer::Release()
399 g_Windowing.Unregister(this);
400 SAFE_RELEASE(m_vertex);
403 bool CD3DVertexBuffer::Lock(UINT level, UINT size, void **data, DWORD flags)
406 return (D3D_OK == m_vertex->Lock(level, size, data, flags));
410 bool CD3DVertexBuffer::Unlock()
413 return (D3D_OK == m_vertex->Unlock());
417 void CD3DVertexBuffer::OnDestroyDevice()
424 if (Lock(0, 0, &data, 0))
426 m_data = new BYTE[m_length];
427 memcpy(m_data, data, m_length);
431 SAFE_RELEASE(m_vertex);
434 void CD3DVertexBuffer::OnCreateDevice()
436 // yay, we're back - make a new copy of the vertices
437 if (!m_vertex && m_data && CreateVertexBuffer())
440 if (Lock(0, 0, &data, 0))
442 memcpy(data, m_data, m_length);
450 bool CD3DVertexBuffer::CreateVertexBuffer()
452 if (D3D_OK == g_Windowing.Get3DDevice()->CreateVertexBuffer(m_length, m_usage, m_fvf, m_pool, &m_vertex, NULL))