]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CD3D9Texture.cpp
Fix Windows, Android build
[irrlicht.git] / source / Irrlicht / CD3D9Texture.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "IrrCompileConfig.h"\r
6 \r
7 #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_\r
8 \r
9 #include "CD3D9Texture.h"\r
10 #include "CD3D9Driver.h"\r
11 #include "os.h"\r
12 \r
13 namespace irr\r
14 {\r
15 namespace video\r
16 {\r
17 \r
18 CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& image, E_TEXTURE_TYPE type, CD3D9Driver* driver)\r
19         : ITexture(name, type), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockReadOnly(false), LockData(0), LockLayer(0),\r
20         MipLevelLocked(0), HardwareMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)\r
21 {\r
22 #ifdef _DEBUG\r
23         setDebugName("CD3D9Texture");\r
24 #endif\r
25 \r
26         _IRR_DEBUG_BREAK_IF(image.size() == 0)\r
27 \r
28         Device=driver->getExposedVideoData().D3D9.D3DDev9;\r
29 \r
30         if (Device)\r
31                 Device->AddRef();\r
32 \r
33         DriverType = Driver->getDriverType();\r
34         HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);\r
35         HardwareMipMaps = Driver->getTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS) && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);\r
36 \r
37         getImageValues(image[0]);\r
38 \r
39         DWORD flags = 0;\r
40 \r
41         if (HasMipMaps && HardwareMipMaps)\r
42         {\r
43                 LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;\r
44                 D3DDISPLAYMODE d3ddm;\r
45                 intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);\r
46 \r
47                 if (D3D_OK == intf->CheckDeviceFormat(Driver->Params.DisplayAdapter, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, InternalFormat))\r
48                         flags = D3DUSAGE_AUTOGENMIPMAP;\r
49                 else\r
50                         HardwareMipMaps = false;\r
51         }\r
52 \r
53         HRESULT hr = 0;\r
54         \r
55         switch (Type)\r
56         {\r
57         case ETT_2D:\r
58                 hr = Device->CreateTexture(Size.Width, Size.Height, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &Texture, NULL);\r
59                 break;\r
60         case ETT_CUBEMAP:\r
61                 hr = Device->CreateCubeTexture(Size.Width, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &CubeTexture, NULL);\r
62                 break;\r
63         default:\r
64                 _IRR_DEBUG_BREAK_IF(true)\r
65                 break;\r
66         }\r
67 \r
68         if (FAILED(hr))\r
69         {\r
70                 // Try again with 16-bit format \r
71                 if (InternalFormat == D3DFMT_A8R8G8B8)\r
72                 {\r
73                         InternalFormat = D3DFMT_A1R5G5B5;\r
74                         ColorFormat = ECF_A1R5G5B5;\r
75                 }\r
76                 else if (InternalFormat == D3DFMT_R8G8B8)       // (24 bit is usually failing in d3d9, not sure if it's ever supported)\r
77                 {\r
78                         InternalFormat = D3DFMT_R5G6B5;\r
79                         ColorFormat = ECF_R5G6B5;\r
80                 }\r
81                 switch (Type)\r
82                 {\r
83                         case ETT_2D:\r
84                                 hr = Device->CreateTexture(Size.Width, Size.Height, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &Texture, NULL);\r
85                                 break;\r
86                         case ETT_CUBEMAP:\r
87                                 hr = Device->CreateCubeTexture(Size.Width, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &CubeTexture, NULL);\r
88                                 break;\r
89                 }\r
90         }\r
91 \r
92         core::array<IImage*> tmpImage = image;\r
93         bool releaseImageData = false;\r
94 \r
95         if (SUCCEEDED(hr))\r
96         {\r
97                 if (OriginalSize != Size || OriginalColorFormat != ColorFormat)\r
98                 {\r
99                         releaseImageData = true;\r
100 \r
101                         for (u32 i = 0; i < image.size(); ++i)\r
102                         {\r
103                                 tmpImage[i] = Driver->createImage(ColorFormat, Size);\r
104 \r
105                                 if (image[i]->getDimension() == Size)\r
106                                         image[i]->copyTo(tmpImage[i]);\r
107                                 else\r
108                                         image[i]->copyToScaling(tmpImage[i]);\r
109                         }\r
110                 }\r
111 \r
112                 for (u32 i = 0; i < tmpImage.size(); ++i)\r
113                         uploadTexture(tmpImage[i]->getData(), 0, i);\r
114 \r
115                 bool autoGenerateRequired = true;\r
116 \r
117                 for (u32 i = 0; i < tmpImage.size(); ++i)\r
118                 {\r
119                         void* mipmapsData = tmpImage[i]->getMipMapsData();\r
120 \r
121                         if (autoGenerateRequired || mipmapsData)\r
122                                 regenerateMipMapLevels(mipmapsData, i);\r
123 \r
124                         if (!mipmapsData)\r
125                                 autoGenerateRequired = false;\r
126                 }\r
127         }\r
128         else\r
129         {\r
130                 switch  (hr )\r
131                 {\r
132                         case D3DERR_INVALIDCALL:\r
133                                 os::Printer::log("Could not create DIRECT3D9 Texture. D3DERR_INVALIDCALL", ELL_WARNING);\r
134                                 break;\r
135                         case D3DERR_OUTOFVIDEOMEMORY:\r
136                                 os::Printer::log("Could not create DIRECT3D9 Texture. D3DERR_OUTOFVIDEOMEMORY", ELL_WARNING);\r
137                                 break;\r
138                         case E_OUTOFMEMORY:\r
139                                 os::Printer::log("Could not create DIRECT3D9 Texture. E_OUTOFMEMORY", ELL_WARNING);\r
140                                 break;\r
141                         default:\r
142                                 os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);\r
143                 }\r
144         }\r
145         \r
146         if (releaseImageData)\r
147     {\r
148                 for (u32 i = 0; i < tmpImage.size(); ++i)\r
149                         tmpImage[i]->drop();\r
150     }\r
151 }\r
152 \r
153 CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, E_TEXTURE_TYPE type, const ECOLOR_FORMAT format)\r
154         : ITexture(name, type), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockReadOnly(false), LockData(0), LockLayer(0),\r
155         MipLevelLocked(0), HardwareMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)\r
156 {\r
157 #ifdef _DEBUG\r
158         setDebugName("CD3D9Texture");\r
159 #endif\r
160 \r
161         Device = driver->getExposedVideoData().D3D9.D3DDev9;\r
162 \r
163         if (Device)\r
164                 Device->AddRef();\r
165 \r
166         DriverType = Driver->getDriverType();\r
167         HasMipMaps = false;\r
168         IsRenderTarget = true;\r
169 \r
170         OriginalColorFormat = format;\r
171 \r
172         if (ECF_UNKNOWN == OriginalColorFormat)\r
173                 ColorFormat = getBestColorFormat(Driver->getColorFormat());\r
174         else\r
175                 ColorFormat = OriginalColorFormat;\r
176 \r
177         OriginalSize = size;\r
178         Size = OriginalSize;\r
179 \r
180         if (!Driver->queryFeature(EVDF_TEXTURE_NPOT))\r
181         {\r
182                 Size = Size.getOptimalSize(true, !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);\r
183 \r
184                 if (Size != OriginalSize)\r
185                         os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);\r
186         }\r
187 \r
188         Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;\r
189 \r
190         InternalFormat = Driver->getD3DFormatFromColorFormat(ColorFormat);\r
191 \r
192         generateRenderTarget();\r
193 }\r
194 \r
195 CD3D9Texture::~CD3D9Texture()\r
196 {\r
197         releaseTexture();\r
198 \r
199         if (Device)\r
200                 Device->Release();\r
201 }\r
202 \r
203 void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E_TEXTURE_LOCK_FLAGS lockFlags)\r
204 {\r
205         if (LockData)\r
206                 return LockData;\r
207 \r
208         if (IImage::isCompressedFormat(ColorFormat))\r
209                 return 0;\r
210 \r
211         MipLevelLocked = mipmapLevel;\r
212         LockReadOnly = (mode == ETLM_READ_ONLY);\r
213         LockLayer = layer;\r
214 \r
215         HRESULT hr;\r
216         D3DLOCKED_RECT rect;\r
217 \r
218         if (!IsRenderTarget)\r
219         {\r
220                 if (Texture)\r
221                 {\r
222                         hr = Texture->LockRect(MipLevelLocked, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);\r
223                 }\r
224                 else if (CubeTexture)\r
225                 {\r
226                         _IRR_DEBUG_BREAK_IF(layer > 5)\r
227 \r
228                         hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), MipLevelLocked, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);\r
229                 }\r
230                 else\r
231                 {\r
232                         os::Printer::log("Could not lock DIRECT3D9 Texture. Missing internal D3D texture.", ELL_ERROR);\r
233                         return 0;\r
234                 }\r
235                 \r
236                 if (FAILED(hr))\r
237                 {\r
238                         os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);\r
239                         return 0;\r
240                 }\r
241         }\r
242         else\r
243         {\r
244                 if (!RTTSurface)\r
245                 {\r
246                         // Make RTT surface large enough for all miplevels (including 0)\r
247                         D3DSURFACE_DESC desc;\r
248                         if (Texture)\r
249                                 Texture->GetLevelDesc(0, &desc);\r
250                         else if (CubeTexture)\r
251                                 CubeTexture->GetLevelDesc(0, &desc);\r
252                         hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0);\r
253                         if (FAILED(hr))\r
254                         {\r
255                                 os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR);\r
256                                 return 0;\r
257                         }\r
258                 }\r
259 \r
260                 IDirect3DSurface9 *surface = 0;\r
261                 if (Texture)\r
262                         hr = Texture->GetSurfaceLevel(MipLevelLocked, &surface);\r
263                 else if (CubeTexture)\r
264                         hr = CubeTexture->GetCubeMapSurface(static_cast<_D3DCUBEMAP_FACES>(layer), MipLevelLocked, &surface);\r
265                 if (FAILED(hr))\r
266                 {\r
267                         os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);\r
268                         return 0;\r
269                 }\r
270                 hr = Device->GetRenderTargetData(surface, RTTSurface);\r
271                 surface->Release();\r
272                 if(FAILED(hr))\r
273                 {\r
274                         os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);\r
275                         return 0;\r
276                 }\r
277                 hr = RTTSurface->LockRect(&rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);\r
278                 if(FAILED(hr))\r
279                 {\r
280                         os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);\r
281                         return 0;\r
282                 }\r
283         }\r
284 \r
285         LockData = rect.pBits;\r
286 \r
287         return LockData;\r
288 }\r
289 \r
290 void CD3D9Texture::unlock()\r
291 {\r
292         if (!LockData)\r
293                 return;\r
294 \r
295         if (!IsRenderTarget)\r
296         {\r
297                 if (Texture)\r
298                 {\r
299                         Texture->UnlockRect(MipLevelLocked);\r
300                 }\r
301                 else if (CubeTexture)\r
302                 {\r
303                         CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(LockLayer), MipLevelLocked);\r
304                 }\r
305         }\r
306         else if (RTTSurface)\r
307         {\r
308                 RTTSurface->UnlockRect();\r
309         }\r
310 \r
311         LockReadOnly = false;\r
312         LockData = 0;\r
313         LockLayer = 0;\r
314 }\r
315 \r
316 void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)\r
317 {\r
318         if (!HasMipMaps || (Size.Width <= 1 && Size.Height <= 1))\r
319                 return;\r
320 \r
321         if ( HardwareMipMaps )  \r
322         {\r
323                 // Can't update with custom data with those unfortunately \r
324                 // Also MSDN docs don't mention it, but GenerateMipSubLevels only works when AUTOGENMIPMAP is set.\r
325                 // So we can't call this to get hardware mipmaps when not setting AUTOGENMIPMAP.\r
326                 if (Texture)\r
327                         Texture->GenerateMipSubLevels();\r
328                 else if (CubeTexture)\r
329                         CubeTexture->GenerateMipSubLevels();\r
330         }\r
331         else if (data)\r
332         {\r
333                 u32 width = Size.Width;\r
334                 u32 height = Size.Height;\r
335                 u8* tmpData = static_cast<u8*>(data);\r
336                 u32 dataSize = 0;\r
337                 u32 level = 0;\r
338 \r
339                 do\r
340                 {\r
341                         if (width > 1)\r
342                                 width >>= 1;\r
343 \r
344                         if (height > 1)\r
345                                 height >>= 1;\r
346 \r
347                         dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);\r
348                         ++level;\r
349 \r
350                         uploadTexture(tmpData, level, layer);\r
351 \r
352                         tmpData += dataSize;\r
353                 } while (width != 1 || height != 1);\r
354         }\r
355         else\r
356         {\r
357                 createManualMipMaps(1);\r
358         }\r
359 }\r
360 \r
361 void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,\r
362                                    s32 width, s32 height,\r
363                                    s32 pitchsrc, s32 pitchtgt) const\r
364 {\r
365         for (s32 y=0; y<height; ++y)\r
366         {\r
367                 for (s32 x=0; x<width; ++x)\r
368                 {\r
369                         u32 a=0, r=0, g=0, b=0;\r
370 \r
371                         for (s32 dy=0; dy<2; ++dy)\r
372                         {\r
373                                 const s32 tgy = (y*2)+dy;\r
374                                 for (s32 dx=0; dx<2; ++dx)\r
375                                 {\r
376                                         const s32 tgx = (x*2)+dx;\r
377 \r
378                                         SColor c;\r
379                                         if (ColorFormat == ECF_A1R5G5B5)\r
380                                                 c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));\r
381                                         else\r
382                                                 c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));\r
383 \r
384                                         a += c.getAlpha();\r
385                                         r += c.getRed();\r
386                                         g += c.getGreen();\r
387                                         b += c.getBlue();\r
388                                 }\r
389                         }\r
390 \r
391                         a /= 4;\r
392                         r /= 4;\r
393                         g /= 4;\r
394                         b /= 4;\r
395 \r
396                         u16 c;\r
397                         if (ColorFormat == ECF_A1R5G5B5)\r
398                                 c = RGBA16(r,g,b,a);\r
399                         else\r
400                                 c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);\r
401                         *(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;\r
402                 }\r
403         }\r
404 }\r
405 \r
406 void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,\r
407                                    s32 width, s32 height,\r
408                                    s32 pitchsrc, s32 pitchtgt) const\r
409 {\r
410         for (s32 y=0; y<height; ++y)\r
411         {\r
412                 for (s32 x=0; x<width; ++x)\r
413                 {\r
414                         u32 a=0, r=0, g=0, b=0;\r
415                         SColor c;\r
416 \r
417                         for (s32 dy=0; dy<2; ++dy)\r
418                         {\r
419                                 const s32 tgy = (y*2)+dy;\r
420                                 for (s32 dx=0; dx<2; ++dx)\r
421                                 {\r
422                                         const s32 tgx = (x*2)+dx;\r
423 \r
424                                         c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);\r
425 \r
426                                         a += c.getAlpha();\r
427                                         r += c.getRed();\r
428                                         g += c.getGreen();\r
429                                         b += c.getBlue();\r
430                                 }\r
431                         }\r
432 \r
433                         a /= 4;\r
434                         r /= 4;\r
435                         g /= 4;\r
436                         b /= 4;\r
437 \r
438                         c.set(a, r, g, b);\r
439                         *(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;\r
440                 }\r
441         }\r
442 }\r
443 \r
444 bool CD3D9Texture::createManualMipMaps(u32 level)\r
445 {\r
446         if (level==0)\r
447                 return true;\r
448 \r
449         if (!Texture)   //Manual mips for CubeTexture not supported yet\r
450         {\r
451                 return true;\r
452         }\r
453 \r
454         // manual mipmap generation\r
455         IDirect3DSurface9* upperSurface = 0;\r
456         IDirect3DSurface9* lowerSurface = 0;\r
457 \r
458         // get upper level\r
459         HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);\r
460         if (FAILED(hr) || !upperSurface)\r
461         {\r
462                 os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);\r
463                 return false;\r
464         }\r
465 \r
466         // get lower level\r
467         hr = Texture->GetSurfaceLevel(level, &lowerSurface);\r
468         if (FAILED(hr) || !lowerSurface)\r
469         {\r
470                 os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);\r
471                 upperSurface->Release();\r
472                 return false;\r
473         }\r
474 \r
475         D3DSURFACE_DESC upperDesc, lowerDesc;\r
476         upperSurface->GetDesc(&upperDesc);\r
477         lowerSurface->GetDesc(&lowerDesc);\r
478 \r
479         D3DLOCKED_RECT upperlr;\r
480         D3DLOCKED_RECT lowerlr;\r
481 \r
482         // lock upper surface\r
483         if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))\r
484         {\r
485                 upperSurface->Release();\r
486                 lowerSurface->Release();\r
487                 os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);\r
488                 return false;\r
489         }\r
490 \r
491         // lock lower surface\r
492         if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))\r
493         {\r
494                 upperSurface->UnlockRect();\r
495                 upperSurface->Release();\r
496                 lowerSurface->Release();\r
497                 os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);\r
498                 return false;\r
499         }\r
500 \r
501         if (upperDesc.Format != lowerDesc.Format)\r
502         {\r
503                 os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);\r
504         }\r
505         else\r
506         {\r
507                 if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))\r
508                         copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,\r
509                                         lowerDesc.Width, lowerDesc.Height,\r
510                                         upperlr.Pitch, lowerlr.Pitch);\r
511                 else\r
512                 if (upperDesc.Format == D3DFMT_A8R8G8B8)\r
513                         copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,\r
514                                         lowerDesc.Width, lowerDesc.Height,\r
515                                         upperlr.Pitch, lowerlr.Pitch);\r
516                 else\r
517                         os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);\r
518         }\r
519 \r
520         bool result=true;\r
521         // unlock\r
522         if (FAILED(upperSurface->UnlockRect()))\r
523                 result=false;\r
524         if (FAILED(lowerSurface->UnlockRect()))\r
525                 result=false;\r
526 \r
527         // release\r
528         upperSurface->Release();\r
529         lowerSurface->Release();\r
530 \r
531         if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))\r
532                 return result; // stop generating levels\r
533 \r
534         // generate next level\r
535         return createManualMipMaps(level+1);\r
536 }\r
537 \r
538 \r
539 IDirect3DBaseTexture9* CD3D9Texture::getDX9BaseTexture() const\r
540 {\r
541         return (Texture) ? static_cast<IDirect3DBaseTexture9*>(Texture) : static_cast<IDirect3DBaseTexture9*>(CubeTexture);\r
542 }\r
543 \r
544 IDirect3DTexture9* CD3D9Texture::getDX9Texture() const\r
545 {\r
546         return Texture;\r
547 }\r
548 \r
549 IDirect3DCubeTexture9* CD3D9Texture::getDX9CubeTexture() const\r
550 {\r
551         return CubeTexture;\r
552 }\r
553 \r
554 void CD3D9Texture::releaseTexture()\r
555 {\r
556         if (RTTSurface)\r
557         {\r
558                 if (RTTSurface->Release() == 0)\r
559                         RTTSurface = 0;\r
560         }\r
561 \r
562         if (Texture)\r
563         {\r
564                 if (Texture->Release() == 0)\r
565                         Texture = 0;\r
566         }\r
567 \r
568         if (CubeTexture)\r
569         {\r
570                 if (CubeTexture->Release() == 0)\r
571                         CubeTexture = 0;\r
572         }\r
573 }\r
574 \r
575 void CD3D9Texture::generateRenderTarget()\r
576 {\r
577         DWORD flags = (IImage::isDepthFormat(ColorFormat)) ? D3DUSAGE_DEPTHSTENCIL : D3DUSAGE_RENDERTARGET;\r
578 \r
579         HRESULT hr = 0;\r
580 \r
581         switch (Type)\r
582         {\r
583                 case ETT_2D:\r
584                         if (!Texture )\r
585                                 hr = Device->CreateTexture(Size.Width, Size.Height, 1, flags, InternalFormat, D3DPOOL_DEFAULT, &Texture, NULL);\r
586                         break;\r
587                 case ETT_CUBEMAP:\r
588                         if (!CubeTexture)\r
589                                 hr = Device->CreateCubeTexture(Size.Width, 1, flags, InternalFormat, D3DPOOL_DEFAULT, &CubeTexture, NULL);\r
590                         break;\r
591                 default:\r
592                         _IRR_DEBUG_BREAK_IF(true)\r
593                         break;\r
594         }\r
595 \r
596         if (FAILED(hr))\r
597         {\r
598                 if (D3DERR_INVALIDCALL == hr)\r
599                         os::Printer::log("Could not create render target texture", "Invalid Call", irr::ELL_ERROR);\r
600                 else if (D3DERR_OUTOFVIDEOMEMORY == hr)\r
601                         os::Printer::log("Could not create render target texture", "Out of Video Memory", irr::ELL_ERROR);\r
602                 else if (E_OUTOFMEMORY == hr)\r
603                         os::Printer::log("Could not create render target texture", "Out of Memory", irr::ELL_ERROR);\r
604                 else\r
605                         os::Printer::log("Could not create render target texture", irr::ELL_ERROR);\r
606                 core::stringc params("Width:");\r
607                 params += (unsigned int)Size.Width;\r
608                 params += " Height: ";\r
609                 params += (unsigned int)Size.Height;\r
610                 params += " flag: ";\r
611                 params += (unsigned int)flags;\r
612                 params += " format";\r
613                 params += (unsigned int)InternalFormat;\r
614                 params += " Type: ";\r
615                 params += (unsigned int)Type;\r
616                 os::Printer::log(params.c_str(), irr::ELL_ERROR);\r
617         }\r
618 }\r
619 \r
620 ECOLOR_FORMAT CD3D9Texture::getBestColorFormat(ECOLOR_FORMAT format)\r
621 {\r
622         // We only try for to adapt "simple" formats\r
623         ECOLOR_FORMAT destFormat = (format <= ECF_A8R8G8B8) ? ECF_A8R8G8B8 : format;\r
624 \r
625         switch (format)\r
626         {\r
627         case ECF_A1R5G5B5:\r
628                 if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))\r
629                         destFormat = ECF_A1R5G5B5;\r
630                 break;\r
631         case ECF_R5G6B5:\r
632                 if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))\r
633                         destFormat = ECF_R5G6B5;\r
634                 break;\r
635         case ECF_A8R8G8B8:\r
636                 if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||\r
637                         Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))\r
638                         destFormat = ECF_A1R5G5B5;\r
639                 break;\r
640         case ECF_R8G8B8:\r
641                 // Note: Using ECF_A8R8G8B8 even when ETCF_ALWAYS_32_BIT is not set as 24 bit textures fail with too many cards\r
642                 if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))\r
643                         destFormat = ECF_A1R5G5B5;\r
644         default:\r
645                 break;\r
646         }\r
647 \r
648         if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))\r
649         {\r
650                 switch (destFormat)\r
651                 {\r
652                 case ECF_A1R5G5B5:\r
653                         destFormat = ECF_R5G6B5;\r
654                         break;\r
655                 case ECF_A8R8G8B8:\r
656                         destFormat = ECF_R8G8B8;\r
657                         break;\r
658                 default:\r
659                         break;\r
660                 }\r
661         }\r
662 \r
663         return destFormat;\r
664 }\r
665 \r
666 void CD3D9Texture::getImageValues(const IImage* image)\r
667 {\r
668         OriginalColorFormat = image->getColorFormat();\r
669         ColorFormat = getBestColorFormat(OriginalColorFormat);\r
670 \r
671         InternalFormat = Driver->getD3DFormatFromColorFormat(ColorFormat);\r
672 \r
673         if (IImage::isCompressedFormat(image->getColorFormat()))\r
674         {\r
675                 HardwareMipMaps = false;\r
676         }\r
677 \r
678         OriginalSize = image->getDimension();\r
679         Size = OriginalSize;\r
680 \r
681         if (Size.Width == 0 || Size.Height == 0)\r
682         {\r
683                 os::Printer::log("Invalid size of image for texture.", ELL_ERROR);\r
684                 return;\r
685         }\r
686 \r
687         const f32 ratio = (f32)Size.Width / (f32)Size.Height;\r
688 \r
689         if ((Size.Width > Driver->Caps.MaxTextureWidth) && (ratio >= 1.f))\r
690         {\r
691                 Size.Width = Driver->Caps.MaxTextureWidth;\r
692                 Size.Height = (u32)(Driver->Caps.MaxTextureWidth / ratio);\r
693         }\r
694         else if (Size.Height > Driver->Caps.MaxTextureHeight)\r
695         {\r
696                 Size.Height = Driver->Caps.MaxTextureHeight;\r
697                 Size.Width = (u32)(Driver->Caps.MaxTextureHeight * ratio);\r
698         }\r
699 \r
700         bool needSquare = (!Driver->queryFeature(EVDF_TEXTURE_NSQUARE) || Type == ETT_CUBEMAP);\r
701 \r
702         Size = Size.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), needSquare, true, Driver->Caps.MaxTextureWidth);\r
703 \r
704         Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;\r
705 }\r
706 \r
707 void CD3D9Texture::uploadTexture(void* data, u32 mipmapLevel, u32 layer)\r
708 {\r
709         if (!data)\r
710                 return;\r
711 \r
712         u32 width = Size.Width >> mipmapLevel;\r
713         u32 height = Size.Height >> mipmapLevel;\r
714 \r
715         u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);\r
716 \r
717         HRESULT hr = 0;\r
718 \r
719         D3DLOCKED_RECT lockRectangle;\r
720 \r
721         if (Texture)\r
722         {\r
723                 hr = Texture->LockRect(mipmapLevel, &lockRectangle, 0, 0);\r
724         }\r
725         else if (CubeTexture)\r
726         {\r
727                 _IRR_DEBUG_BREAK_IF(layer > 5)\r
728 \r
729                 hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), mipmapLevel, &lockRectangle, 0, 0);\r
730         }\r
731 \r
732         if (FAILED(hr))\r
733         {\r
734                 os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);\r
735                 return;\r
736         }\r
737 \r
738         memcpy(lockRectangle.pBits, data, dataSize);\r
739 \r
740         if (Texture)\r
741         {\r
742                 hr = Texture->UnlockRect(mipmapLevel);\r
743         }\r
744         else if (CubeTexture)\r
745         {\r
746                 hr = CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(layer), mipmapLevel);\r
747         }\r
748 \r
749         if (FAILED(hr))\r
750         {\r
751                 os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);\r
752         }\r
753 }\r
754 \r
755 }\r
756 }\r
757 \r
758 #endif\r