diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CD3D9Texture.cpp | 699 |
1 files changed, 699 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CD3D9Texture.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CD3D9Texture.cpp new file mode 100644 index 0000000..122ee2a --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CD3D9Texture.cpp | |||
@@ -0,0 +1,699 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "IrrCompileConfig.h" | ||
6 | #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ | ||
7 | |||
8 | #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE | ||
9 | #include "CD3D9Texture.h" | ||
10 | #include "CD3D9Driver.h" | ||
11 | #include "os.h" | ||
12 | |||
13 | #include <d3dx9tex.h> | ||
14 | |||
15 | #ifndef _IRR_COMPILE_WITH_DIRECT3D_8_ | ||
16 | // The D3DXFilterTexture function seems to get linked wrong when | ||
17 | // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. | ||
18 | // So mipmapgeneration is replaced with my own bad generation in d3d 8 when | ||
19 | // compiling with both D3D 8 and 9. | ||
20 | // #define _IRR_USE_D3DXFilterTexture_ | ||
21 | #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ | ||
22 | |||
23 | #ifdef _IRR_USE_D3DXFilterTexture_ | ||
24 | #pragma comment(lib, "d3dx9.lib") | ||
25 | #endif | ||
26 | |||
27 | namespace irr | ||
28 | { | ||
29 | namespace video | ||
30 | { | ||
31 | |||
32 | //! rendertarget constructor | ||
33 | CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, | ||
34 | const io::path& name, const ECOLOR_FORMAT format) | ||
35 | : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), | ||
36 | TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN), | ||
37 | HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true) | ||
38 | { | ||
39 | #ifdef _DEBUG | ||
40 | setDebugName("CD3D9Texture"); | ||
41 | #endif | ||
42 | |||
43 | Device=driver->getExposedVideoData().D3D9.D3DDev9; | ||
44 | if (Device) | ||
45 | Device->AddRef(); | ||
46 | |||
47 | createRenderTarget(format); | ||
48 | } | ||
49 | |||
50 | |||
51 | //! constructor | ||
52 | CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, | ||
53 | u32 flags, const io::path& name, void* mipmapData) | ||
54 | : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), | ||
55 | TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN), | ||
56 | HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) | ||
57 | { | ||
58 | #ifdef _DEBUG | ||
59 | setDebugName("CD3D9Texture"); | ||
60 | #endif | ||
61 | |||
62 | HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); | ||
63 | |||
64 | Device=driver->getExposedVideoData().D3D9.D3DDev9; | ||
65 | if (Device) | ||
66 | Device->AddRef(); | ||
67 | |||
68 | if (image) | ||
69 | { | ||
70 | if (createTexture(flags, image)) | ||
71 | { | ||
72 | if (copyTexture(image)) | ||
73 | { | ||
74 | regenerateMipMapLevels(mipmapData); | ||
75 | } | ||
76 | } | ||
77 | else | ||
78 | os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | //! destructor | ||
84 | CD3D9Texture::~CD3D9Texture() | ||
85 | { | ||
86 | if (Texture) | ||
87 | Texture->Release(); | ||
88 | |||
89 | if (RTTSurface) | ||
90 | RTTSurface->Release(); | ||
91 | |||
92 | // if this texture was the last one using the depth buffer | ||
93 | // we can release the surface. We only use the value of the pointer | ||
94 | // hence it is safe to use the dropped pointer... | ||
95 | if (DepthSurface) | ||
96 | { | ||
97 | if (DepthSurface->drop()) | ||
98 | Driver->removeDepthSurface(DepthSurface); | ||
99 | } | ||
100 | |||
101 | if (Device) | ||
102 | Device->Release(); | ||
103 | } | ||
104 | |||
105 | |||
106 | void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format) | ||
107 | { | ||
108 | // are texture size restrictions there ? | ||
109 | if(!Driver->queryFeature(EVDF_TEXTURE_NPOT)) | ||
110 | { | ||
111 | if (TextureSize != ImageSize) | ||
112 | os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION); | ||
113 | } | ||
114 | TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); | ||
115 | |||
116 | D3DFORMAT d3dformat = Driver->getD3DColorFormat(); | ||
117 | |||
118 | if(ColorFormat == ECF_UNKNOWN) | ||
119 | { | ||
120 | // get irrlicht format from backbuffer | ||
121 | // (This will get overwritten by the custom format if it is provided, else kept.) | ||
122 | ColorFormat = Driver->getColorFormat(); | ||
123 | setPitch(d3dformat); | ||
124 | |||
125 | // Use color format if provided. | ||
126 | if(format != ECF_UNKNOWN) | ||
127 | { | ||
128 | ColorFormat = format; | ||
129 | d3dformat = Driver->getD3DFormatFromColorFormat(format); | ||
130 | setPitch(d3dformat); // This will likely set pitch to 0 for now. | ||
131 | } | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat); | ||
136 | } | ||
137 | |||
138 | // create texture | ||
139 | HRESULT hr; | ||
140 | |||
141 | hr = Device->CreateTexture( | ||
142 | TextureSize.Width, | ||
143 | TextureSize.Height, | ||
144 | 1, // mip map level count, we don't want mipmaps here | ||
145 | D3DUSAGE_RENDERTARGET, | ||
146 | d3dformat, | ||
147 | D3DPOOL_DEFAULT, | ||
148 | &Texture, | ||
149 | NULL); | ||
150 | |||
151 | if (FAILED(hr)) | ||
152 | { | ||
153 | if (D3DERR_INVALIDCALL == hr) | ||
154 | os::Printer::log("Could not create render target texture", "Invalid Call"); | ||
155 | else | ||
156 | if (D3DERR_OUTOFVIDEOMEMORY == hr) | ||
157 | os::Printer::log("Could not create render target texture", "Out of Video Memory"); | ||
158 | else | ||
159 | if (E_OUTOFMEMORY == hr) | ||
160 | os::Printer::log("Could not create render target texture", "Out of Memory"); | ||
161 | else | ||
162 | os::Printer::log("Could not create render target texture"); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | |||
167 | bool CD3D9Texture::createMipMaps(u32 level) | ||
168 | { | ||
169 | if (level==0) | ||
170 | return true; | ||
171 | |||
172 | if (HardwareMipMaps && Texture) | ||
173 | { | ||
174 | // generate mipmaps in hardware | ||
175 | Texture->GenerateMipSubLevels(); | ||
176 | return true; | ||
177 | } | ||
178 | |||
179 | // manual mipmap generation | ||
180 | IDirect3DSurface9* upperSurface = 0; | ||
181 | IDirect3DSurface9* lowerSurface = 0; | ||
182 | |||
183 | // get upper level | ||
184 | HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface); | ||
185 | if (FAILED(hr) || !upperSurface) | ||
186 | { | ||
187 | os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING); | ||
188 | return false; | ||
189 | } | ||
190 | |||
191 | // get lower level | ||
192 | hr = Texture->GetSurfaceLevel(level, &lowerSurface); | ||
193 | if (FAILED(hr) || !lowerSurface) | ||
194 | { | ||
195 | os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING); | ||
196 | upperSurface->Release(); | ||
197 | return false; | ||
198 | } | ||
199 | |||
200 | D3DSURFACE_DESC upperDesc, lowerDesc; | ||
201 | upperSurface->GetDesc(&upperDesc); | ||
202 | lowerSurface->GetDesc(&lowerDesc); | ||
203 | |||
204 | D3DLOCKED_RECT upperlr; | ||
205 | D3DLOCKED_RECT lowerlr; | ||
206 | |||
207 | // lock upper surface | ||
208 | if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0))) | ||
209 | { | ||
210 | upperSurface->Release(); | ||
211 | lowerSurface->Release(); | ||
212 | os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING); | ||
213 | return false; | ||
214 | } | ||
215 | |||
216 | // lock lower surface | ||
217 | if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0))) | ||
218 | { | ||
219 | upperSurface->UnlockRect(); | ||
220 | upperSurface->Release(); | ||
221 | lowerSurface->Release(); | ||
222 | os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING); | ||
223 | return false; | ||
224 | } | ||
225 | |||
226 | if (upperDesc.Format != lowerDesc.Format) | ||
227 | { | ||
228 | os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING); | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5)) | ||
233 | copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, | ||
234 | lowerDesc.Width, lowerDesc.Height, | ||
235 | upperlr.Pitch, lowerlr.Pitch); | ||
236 | else | ||
237 | if (upperDesc.Format == D3DFMT_A8R8G8B8) | ||
238 | copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, | ||
239 | lowerDesc.Width, lowerDesc.Height, | ||
240 | upperlr.Pitch, lowerlr.Pitch); | ||
241 | else | ||
242 | os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING); | ||
243 | } | ||
244 | |||
245 | bool result=true; | ||
246 | // unlock | ||
247 | if (FAILED(upperSurface->UnlockRect())) | ||
248 | result=false; | ||
249 | if (FAILED(lowerSurface->UnlockRect())) | ||
250 | result=false; | ||
251 | |||
252 | // release | ||
253 | upperSurface->Release(); | ||
254 | lowerSurface->Release(); | ||
255 | |||
256 | if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3)) | ||
257 | return result; // stop generating levels | ||
258 | |||
259 | // generate next level | ||
260 | return createMipMaps(level+1); | ||
261 | } | ||
262 | |||
263 | |||
264 | //! creates the hardware texture | ||
265 | bool CD3D9Texture::createTexture(u32 flags, IImage * image) | ||
266 | { | ||
267 | ImageSize = image->getDimension(); | ||
268 | |||
269 | core::dimension2d<u32> optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); | ||
270 | |||
271 | D3DFORMAT format = D3DFMT_A1R5G5B5; | ||
272 | |||
273 | switch(getTextureFormatFromFlags(flags)) | ||
274 | { | ||
275 | case ETCF_ALWAYS_16_BIT: | ||
276 | format = D3DFMT_A1R5G5B5; break; | ||
277 | case ETCF_ALWAYS_32_BIT: | ||
278 | format = D3DFMT_A8R8G8B8; break; | ||
279 | case ETCF_OPTIMIZED_FOR_QUALITY: | ||
280 | { | ||
281 | switch(image->getColorFormat()) | ||
282 | { | ||
283 | case ECF_R8G8B8: | ||
284 | case ECF_A8R8G8B8: | ||
285 | format = D3DFMT_A8R8G8B8; break; | ||
286 | case ECF_A1R5G5B5: | ||
287 | case ECF_R5G6B5: | ||
288 | format = D3DFMT_A1R5G5B5; break; | ||
289 | } | ||
290 | } | ||
291 | break; | ||
292 | case ETCF_OPTIMIZED_FOR_SPEED: | ||
293 | format = D3DFMT_A1R5G5B5; | ||
294 | break; | ||
295 | default: | ||
296 | break; | ||
297 | } | ||
298 | if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL)) | ||
299 | { | ||
300 | if (format == D3DFMT_A8R8G8B8) | ||
301 | format = D3DFMT_R8G8B8; | ||
302 | else if (format == D3DFMT_A1R5G5B5) | ||
303 | format = D3DFMT_R5G6B5; | ||
304 | } | ||
305 | |||
306 | const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); | ||
307 | |||
308 | DWORD usage = 0; | ||
309 | |||
310 | // This enables hardware mip map generation. | ||
311 | if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) | ||
312 | { | ||
313 | LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9; | ||
314 | D3DDISPLAYMODE d3ddm; | ||
315 | intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm); | ||
316 | |||
317 | if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format)) | ||
318 | { | ||
319 | usage = D3DUSAGE_AUTOGENMIPMAP; | ||
320 | HardwareMipMaps = true; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height, | ||
325 | mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) | ||
326 | usage, // usage | ||
327 | format, D3DPOOL_MANAGED , &Texture, NULL); | ||
328 | |||
329 | if (FAILED(hr)) | ||
330 | { | ||
331 | // try brute force 16 bit | ||
332 | HardwareMipMaps = false; | ||
333 | if (format == D3DFMT_A8R8G8B8) | ||
334 | format = D3DFMT_A1R5G5B5; | ||
335 | else if (format == D3DFMT_R8G8B8) | ||
336 | format = D3DFMT_R5G6B5; | ||
337 | else | ||
338 | return false; | ||
339 | |||
340 | hr = Device->CreateTexture(optSize.Width, optSize.Height, | ||
341 | mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) | ||
342 | 0, format, D3DPOOL_MANAGED, &Texture, NULL); | ||
343 | } | ||
344 | |||
345 | ColorFormat = Driver->getColorFormatFromD3DFormat(format); | ||
346 | setPitch(format); | ||
347 | return (SUCCEEDED(hr)); | ||
348 | } | ||
349 | |||
350 | |||
351 | //! copies the image to the texture | ||
352 | bool CD3D9Texture::copyTexture(IImage * image) | ||
353 | { | ||
354 | if (Texture && image) | ||
355 | { | ||
356 | D3DSURFACE_DESC desc; | ||
357 | Texture->GetLevelDesc(0, &desc); | ||
358 | |||
359 | TextureSize.Width = desc.Width; | ||
360 | TextureSize.Height = desc.Height; | ||
361 | |||
362 | D3DLOCKED_RECT rect; | ||
363 | HRESULT hr = Texture->LockRect(0, &rect, 0, 0); | ||
364 | if (FAILED(hr)) | ||
365 | { | ||
366 | os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR); | ||
367 | return false; | ||
368 | } | ||
369 | |||
370 | Pitch = rect.Pitch; | ||
371 | image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch); | ||
372 | |||
373 | hr = Texture->UnlockRect(0); | ||
374 | if (FAILED(hr)) | ||
375 | { | ||
376 | os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR); | ||
377 | return false; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return true; | ||
382 | } | ||
383 | |||
384 | |||
385 | //! lock function | ||
386 | void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) | ||
387 | { | ||
388 | if (!Texture) | ||
389 | return 0; | ||
390 | |||
391 | MipLevelLocked=mipmapLevel; | ||
392 | HRESULT hr; | ||
393 | D3DLOCKED_RECT rect; | ||
394 | if(!IsRenderTarget) | ||
395 | { | ||
396 | hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0); | ||
397 | if (FAILED(hr)) | ||
398 | { | ||
399 | os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); | ||
400 | return 0; | ||
401 | } | ||
402 | } | ||
403 | else | ||
404 | { | ||
405 | if (!RTTSurface) | ||
406 | { | ||
407 | // Make RTT surface large enough for all miplevels (including 0) | ||
408 | D3DSURFACE_DESC desc; | ||
409 | Texture->GetLevelDesc(0, &desc); | ||
410 | hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0); | ||
411 | if (FAILED(hr)) | ||
412 | { | ||
413 | os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR); | ||
414 | return 0; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | IDirect3DSurface9 *surface = 0; | ||
419 | hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); | ||
420 | if (FAILED(hr)) | ||
421 | { | ||
422 | os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR); | ||
423 | return 0; | ||
424 | } | ||
425 | hr = Device->GetRenderTargetData(surface, RTTSurface); | ||
426 | surface->Release(); | ||
427 | if(FAILED(hr)) | ||
428 | { | ||
429 | os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR); | ||
430 | return 0; | ||
431 | } | ||
432 | hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0); | ||
433 | if(FAILED(hr)) | ||
434 | { | ||
435 | os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR); | ||
436 | return 0; | ||
437 | } | ||
438 | } | ||
439 | return rect.pBits; | ||
440 | } | ||
441 | |||
442 | |||
443 | //! unlock function | ||
444 | void CD3D9Texture::unlock() | ||
445 | { | ||
446 | if (!Texture) | ||
447 | return; | ||
448 | |||
449 | if (!IsRenderTarget) | ||
450 | Texture->UnlockRect(MipLevelLocked); | ||
451 | else if (RTTSurface) | ||
452 | RTTSurface->UnlockRect(); | ||
453 | } | ||
454 | |||
455 | |||
456 | //! Returns original size of the texture. | ||
457 | const core::dimension2d<u32>& CD3D9Texture::getOriginalSize() const | ||
458 | { | ||
459 | return ImageSize; | ||
460 | } | ||
461 | |||
462 | |||
463 | //! Returns (=size) of the texture. | ||
464 | const core::dimension2d<u32>& CD3D9Texture::getSize() const | ||
465 | { | ||
466 | return TextureSize; | ||
467 | } | ||
468 | |||
469 | |||
470 | //! returns driver type of texture (=the driver, who created the texture) | ||
471 | E_DRIVER_TYPE CD3D9Texture::getDriverType() const | ||
472 | { | ||
473 | return EDT_DIRECT3D9; | ||
474 | } | ||
475 | |||
476 | |||
477 | //! returns color format of texture | ||
478 | ECOLOR_FORMAT CD3D9Texture::getColorFormat() const | ||
479 | { | ||
480 | return ColorFormat; | ||
481 | } | ||
482 | |||
483 | |||
484 | //! returns pitch of texture (in bytes) | ||
485 | u32 CD3D9Texture::getPitch() const | ||
486 | { | ||
487 | return Pitch; | ||
488 | } | ||
489 | |||
490 | |||
491 | //! returns the DIRECT3D9 Texture | ||
492 | IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const | ||
493 | { | ||
494 | return Texture; | ||
495 | } | ||
496 | |||
497 | |||
498 | //! returns if texture has mipmap levels | ||
499 | bool CD3D9Texture::hasMipMaps() const | ||
500 | { | ||
501 | return HasMipMaps; | ||
502 | } | ||
503 | |||
504 | |||
505 | void CD3D9Texture::copy16BitMipMap(char* src, char* tgt, | ||
506 | s32 width, s32 height, | ||
507 | s32 pitchsrc, s32 pitchtgt) const | ||
508 | { | ||
509 | for (s32 y=0; y<height; ++y) | ||
510 | { | ||
511 | for (s32 x=0; x<width; ++x) | ||
512 | { | ||
513 | u32 a=0, r=0, g=0, b=0; | ||
514 | |||
515 | for (s32 dy=0; dy<2; ++dy) | ||
516 | { | ||
517 | const s32 tgy = (y*2)+dy; | ||
518 | for (s32 dx=0; dx<2; ++dx) | ||
519 | { | ||
520 | const s32 tgx = (x*2)+dx; | ||
521 | |||
522 | SColor c; | ||
523 | if (ColorFormat == ECF_A1R5G5B5) | ||
524 | c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)])); | ||
525 | else | ||
526 | c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)])); | ||
527 | |||
528 | a += c.getAlpha(); | ||
529 | r += c.getRed(); | ||
530 | g += c.getGreen(); | ||
531 | b += c.getBlue(); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | a /= 4; | ||
536 | r /= 4; | ||
537 | g /= 4; | ||
538 | b /= 4; | ||
539 | |||
540 | u16 c; | ||
541 | if (ColorFormat == ECF_A1R5G5B5) | ||
542 | c = RGBA16(r,g,b,a); | ||
543 | else | ||
544 | c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color); | ||
545 | *(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c; | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | |||
550 | |||
551 | void CD3D9Texture::copy32BitMipMap(char* src, char* tgt, | ||
552 | s32 width, s32 height, | ||
553 | s32 pitchsrc, s32 pitchtgt) const | ||
554 | { | ||
555 | for (s32 y=0; y<height; ++y) | ||
556 | { | ||
557 | for (s32 x=0; x<width; ++x) | ||
558 | { | ||
559 | u32 a=0, r=0, g=0, b=0; | ||
560 | SColor c; | ||
561 | |||
562 | for (s32 dy=0; dy<2; ++dy) | ||
563 | { | ||
564 | const s32 tgy = (y*2)+dy; | ||
565 | for (s32 dx=0; dx<2; ++dx) | ||
566 | { | ||
567 | const s32 tgx = (x*2)+dx; | ||
568 | |||
569 | c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]); | ||
570 | |||
571 | a += c.getAlpha(); | ||
572 | r += c.getRed(); | ||
573 | g += c.getGreen(); | ||
574 | b += c.getBlue(); | ||
575 | } | ||
576 | } | ||
577 | |||
578 | a /= 4; | ||
579 | r /= 4; | ||
580 | g /= 4; | ||
581 | b /= 4; | ||
582 | |||
583 | c.set(a, r, g, b); | ||
584 | *(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color; | ||
585 | } | ||
586 | } | ||
587 | } | ||
588 | |||
589 | |||
590 | //! Regenerates the mip map levels of the texture. Useful after locking and | ||
591 | //! modifying the texture | ||
592 | void CD3D9Texture::regenerateMipMapLevels(void* mipmapData) | ||
593 | { | ||
594 | if (mipmapData) | ||
595 | { | ||
596 | core::dimension2du size = TextureSize; | ||
597 | u32 level=0; | ||
598 | do | ||
599 | { | ||
600 | if (size.Width>1) | ||
601 | size.Width /=2; | ||
602 | if (size.Height>1) | ||
603 | size.Height /=2; | ||
604 | ++level; | ||
605 | IDirect3DSurface9* mipSurface = 0; | ||
606 | HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); | ||
607 | if (FAILED(hr) || !mipSurface) | ||
608 | { | ||
609 | os::Printer::log("Could not get mipmap level", ELL_WARNING); | ||
610 | return; | ||
611 | } | ||
612 | D3DSURFACE_DESC mipDesc; | ||
613 | mipSurface->GetDesc(&mipDesc); | ||
614 | D3DLOCKED_RECT miplr; | ||
615 | |||
616 | // lock mipmap surface | ||
617 | if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) | ||
618 | { | ||
619 | mipSurface->Release(); | ||
620 | os::Printer::log("Could not lock texture", ELL_WARNING); | ||
621 | return; | ||
622 | } | ||
623 | |||
624 | memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); | ||
625 | mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; | ||
626 | // unlock | ||
627 | mipSurface->UnlockRect(); | ||
628 | // release | ||
629 | mipSurface->Release(); | ||
630 | } while (size.Width != 1 || size.Height != 1); | ||
631 | } | ||
632 | else if (HasMipMaps) | ||
633 | { | ||
634 | // create mip maps. | ||
635 | #ifdef _IRR_USE_D3DXFilterTexture_ | ||
636 | // The D3DXFilterTexture function seems to get linked wrong when | ||
637 | // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. | ||
638 | // So mipmapgeneration is replaced with my own bad generation | ||
639 | HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); | ||
640 | if (FAILED(hr)) | ||
641 | #endif | ||
642 | createMipMaps(); | ||
643 | } | ||
644 | } | ||
645 | |||
646 | |||
647 | //! returns if it is a render target | ||
648 | bool CD3D9Texture::isRenderTarget() const | ||
649 | { | ||
650 | return IsRenderTarget; | ||
651 | } | ||
652 | |||
653 | |||
654 | //! Returns pointer to the render target surface | ||
655 | IDirect3DSurface9* CD3D9Texture::getRenderTargetSurface() | ||
656 | { | ||
657 | if (!IsRenderTarget) | ||
658 | return 0; | ||
659 | |||
660 | IDirect3DSurface9 *pRTTSurface = 0; | ||
661 | if (Texture) | ||
662 | Texture->GetSurfaceLevel(0, &pRTTSurface); | ||
663 | |||
664 | if (pRTTSurface) | ||
665 | pRTTSurface->Release(); | ||
666 | |||
667 | return pRTTSurface; | ||
668 | } | ||
669 | |||
670 | |||
671 | void CD3D9Texture::setPitch(D3DFORMAT d3dformat) | ||
672 | { | ||
673 | switch(d3dformat) | ||
674 | { | ||
675 | case D3DFMT_X1R5G5B5: | ||
676 | case D3DFMT_A1R5G5B5: | ||
677 | Pitch = TextureSize.Width * 2; | ||
678 | break; | ||
679 | case D3DFMT_A8B8G8R8: | ||
680 | case D3DFMT_A8R8G8B8: | ||
681 | case D3DFMT_X8R8G8B8: | ||
682 | Pitch = TextureSize.Width * 4; | ||
683 | break; | ||
684 | case D3DFMT_R5G6B5: | ||
685 | Pitch = TextureSize.Width * 2; | ||
686 | break; | ||
687 | case D3DFMT_R8G8B8: | ||
688 | Pitch = TextureSize.Width * 3; | ||
689 | break; | ||
690 | default: | ||
691 | Pitch = 0; | ||
692 | }; | ||
693 | } | ||
694 | |||
695 | |||
696 | } // end namespace video | ||
697 | } // end namespace irr | ||
698 | |||
699 | #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ | ||