1 /*!
2 	@file
3 	@author		Losev Vasiliy aka bool
4 	@date		06/2009
5 */
6 
7 #include <d3dx9.h>
8 #include "MyGUI_DirectXTexture.h"
9 #include "MyGUI_DirectXDataManager.h"
10 #include "MyGUI_DirectXRTTexture.h"
11 #include "MyGUI_DirectXDiagnostic.h"
12 
13 namespace MyGUI
14 {
15 
DirectXTexture(const std::string & _name,IDirect3DDevice9 * _device)16 	DirectXTexture::DirectXTexture(const std::string& _name, IDirect3DDevice9* _device) :
17 		mName(_name),
18 		mpD3DDevice(_device),
19 		mpTexture(nullptr),
20 		mNumElemBytes(0),
21 		mLock(false),
22 		mRenderTarget(nullptr),
23 		mInternalPool(D3DPOOL_MANAGED),
24 		mInternalFormat(D3DFMT_UNKNOWN),
25 		mInternalUsage(0)
26 	{
27 	}
28 
~DirectXTexture()29 	DirectXTexture::~DirectXTexture()
30 	{
31 		destroy();
32 	}
33 
getName() const34 	const std::string& DirectXTexture::getName() const
35 	{
36 		return mName;
37 	}
38 
createManual(int _width,int _height,TextureUsage _usage,PixelFormat _format)39 	void DirectXTexture::createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format)
40 	{
41 		destroy();
42 
43 		mInternalUsage = 0;
44 		mInternalFormat = D3DFMT_UNKNOWN;
45 
46 		mSize.set(_width, _height);
47 		mTextureUsage = _usage;
48 		mPixelFormat = _format;
49 		mInternalPool = D3DPOOL_MANAGED;
50 
51 		if (mTextureUsage == TextureUsage::RenderTarget)
52 		{
53 			mInternalUsage |= D3DUSAGE_RENDERTARGET;
54 			mInternalPool = D3DPOOL_DEFAULT;
55 		}
56 		else if (mTextureUsage == TextureUsage::Dynamic)
57 			mInternalUsage |= D3DUSAGE_DYNAMIC;
58 		else if (mTextureUsage == TextureUsage::Stream)
59 			mInternalUsage |= D3DUSAGE_DYNAMIC;
60 
61 		if (mPixelFormat == PixelFormat::R8G8B8A8)
62 		{
63 			mInternalFormat = D3DFMT_A8R8G8B8;
64 			mNumElemBytes = 4;
65 		}
66 		else if (mPixelFormat == PixelFormat::R8G8B8)
67 		{
68 			mInternalFormat = D3DFMT_R8G8B8;
69 			mNumElemBytes = 3;
70 		}
71 		else if (mPixelFormat == PixelFormat::L8A8)
72 		{
73 			mInternalFormat = D3DFMT_A8L8;
74 			mNumElemBytes = 2;
75 		}
76 		else if (mPixelFormat == PixelFormat::L8)
77 		{
78 			mInternalFormat = D3DFMT_L8;
79 			mNumElemBytes = 1;
80 		}
81 		else
82 		{
83 			MYGUI_PLATFORM_EXCEPT("Creating texture with unknown pixel formal.");
84 		}
85 
86 		HRESULT result = mpD3DDevice->CreateTexture(mSize.width, mSize.height, 1, mInternalUsage, mInternalFormat, mInternalPool, &mpTexture, nullptr);
87 		if (FAILED(result))
88 		{
89 			MYGUI_PLATFORM_EXCEPT("Failed to create texture (error code " << result <<"): size '" << mSize <<
90 				"' internal usage '" << mInternalUsage <<
91 				"' internal format '" << mInternalFormat << "'."
92 				);
93 		}
94 
95 	}
96 
loadFromFile(const std::string & _filename)97 	void DirectXTexture::loadFromFile(const std::string& _filename)
98 	{
99 		destroy();
100 		mTextureUsage = TextureUsage::Default;
101 		mPixelFormat = PixelFormat::R8G8B8A8;
102 		mNumElemBytes = 4;
103 
104 		std::string fullname = DirectXDataManager::getInstance().getDataPath(_filename);
105 
106 		D3DXIMAGE_INFO info;
107 		D3DXGetImageInfoFromFile(fullname.c_str(), &info);
108 
109 		if (info.Format == D3DFMT_A8R8G8B8)
110 		{
111 			mPixelFormat = PixelFormat::R8G8B8A8;
112 			mNumElemBytes = 4;
113 		}
114 		else if (info.Format == D3DFMT_R8G8B8)
115 		{
116 			mPixelFormat = PixelFormat::R8G8B8;
117 			mNumElemBytes = 3;
118 		}
119 		else if (info.Format == D3DFMT_A8L8)
120 		{
121 			mPixelFormat = PixelFormat::L8A8;
122 			mNumElemBytes = 2;
123 		}
124 		else if (info.Format == D3DFMT_L8)
125 		{
126 			mPixelFormat = PixelFormat::L8;
127 			mNumElemBytes = 1;
128 		}
129 
130 		mSize.set(info.Width, info.Height);
131 		HRESULT result = D3DXCreateTextureFromFile(mpD3DDevice, fullname.c_str(), &mpTexture);
132 		if (FAILED(result))
133 		{
134 			MYGUI_PLATFORM_EXCEPT("Failed to load texture '" << _filename <<
135 				"' (error code " << result <<
136 				"): size '" << mSize <<
137 				"' format '" << info.Format << "'."
138 				);
139 		}
140 	}
141 
destroy()142 	void DirectXTexture::destroy()
143 	{
144 		if (mRenderTarget != nullptr)
145 		{
146 			delete mRenderTarget;
147 			mRenderTarget = nullptr;
148 		}
149 
150 		if (mpTexture != nullptr)
151 		{
152 			int nNewRefCount = mpTexture->Release();
153 
154 			if (nNewRefCount > 0)
155 			{
156 				MYGUI_PLATFORM_EXCEPT("The texture object failed to cleanup properly.\n"
157 					"Release() returned a reference count of '" << nNewRefCount << "'."
158 					);
159 			}
160 
161 			mpTexture = nullptr;
162 		}
163 	}
164 
getWidth()165 	int DirectXTexture::getWidth()
166 	{
167 		return mSize.width;
168 	}
169 
getHeight()170 	int DirectXTexture::getHeight()
171 	{
172 		return mSize.height;
173 	}
174 
lock(TextureUsage _access)175 	void* DirectXTexture::lock(TextureUsage _access)
176 	{
177 		D3DLOCKED_RECT d3dlr;
178 		int lockFlag = (_access == TextureUsage::Write) ? D3DLOCK_DISCARD : D3DLOCK_READONLY;
179 
180 		HRESULT result = mpTexture->LockRect(0, &d3dlr, nullptr, lockFlag);
181 		if (FAILED(result))
182 		{
183 			MYGUI_PLATFORM_EXCEPT("Failed to lock texture (error code " << result << ").");
184 		}
185 
186 		mLock = true;
187 		return d3dlr.pBits;
188 	}
189 
unlock()190 	void DirectXTexture::unlock()
191 	{
192 		HRESULT result = mpTexture->UnlockRect(0);
193 		if (FAILED(result))
194 		{
195 			MYGUI_PLATFORM_EXCEPT("Failed to unlock texture (error code " << result << ").");
196 		}
197 
198 		mLock = false;
199 	}
200 
isLocked()201 	bool DirectXTexture::isLocked()
202 	{
203 		return mLock;
204 	}
205 
getFormat()206 	PixelFormat DirectXTexture::getFormat()
207 	{
208 		return mPixelFormat;
209 	}
210 
getNumElemBytes()211 	size_t DirectXTexture::getNumElemBytes()
212 	{
213 		return mNumElemBytes;
214 	}
215 
getUsage()216 	TextureUsage DirectXTexture::getUsage()
217 	{
218 		return mTextureUsage;
219 	}
220 
getRenderTarget()221 	IRenderTarget* DirectXTexture::getRenderTarget()
222 	{
223 		if (mpTexture == nullptr)
224 			return nullptr;
225 
226 		if (mRenderTarget == nullptr)
227 			mRenderTarget = new DirectXRTTexture(mpD3DDevice, mpTexture);
228 
229 		return mRenderTarget;
230 	}
231 
deviceLost()232 	void DirectXTexture::deviceLost()
233 	{
234 		if (mInternalPool == D3DPOOL_DEFAULT)
235 		{
236 			destroy();
237 		}
238 	}
239 
deviceRestore()240 	void DirectXTexture::deviceRestore()
241 	{
242 		if (mInternalPool == D3DPOOL_DEFAULT)
243 		{
244 			HRESULT result = mpD3DDevice->CreateTexture(mSize.width, mSize.height, 1, mInternalUsage, mInternalFormat, D3DPOOL_DEFAULT, &mpTexture, nullptr);
245 			if (FAILED(result))
246 			{
247 				MYGUI_PLATFORM_EXCEPT("Failed to recreate texture on device restore (error code " << result << ").");
248 			}
249 		}
250 	}
251 
252 } // namespace MyGUI
253