1 /***********************************************************************
2     created:    Mon Feb 9 2009
3     author:     Paul D Turner
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
7  *
8  *   Permission is hereby granted, free of charge, to any person obtaining
9  *   a copy of this software and associated documentation files (the
10  *   "Software"), to deal in the Software without restriction, including
11  *   without limitation the rights to use, copy, modify, merge, publish,
12  *   distribute, sublicense, and/or sell copies of the Software, and to
13  *   permit persons to whom the Software is furnished to do so, subject to
14  *   the following conditions:
15  *
16  *   The above copyright notice and this permission notice shall be
17  *   included in all copies or substantial portions of the Software.
18  *
19  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  ***************************************************************************/
27 #include <d3dx9.h>
28 #include "CEGUI/RendererModules/Direct3D9/Texture.h"
29 #include "CEGUI/Exceptions.h"
30 #include "CEGUI/System.h"
31 #include "CEGUI/ImageCodec.h"
32 
33 // Start of CEGUI namespace section
34 namespace CEGUI
35 {
36 //----------------------------------------------------------------------------//
37 // helper to convert cegui pixel format enum to equivalent D3D format.
toD3DPixelFormat(const Texture::PixelFormat fmt)38 static D3DFORMAT toD3DPixelFormat(const Texture::PixelFormat fmt)
39 {
40     switch (fmt)
41     {
42         case Texture::PF_RGBA:      return D3DFMT_A8R8G8B8;
43         case Texture::PF_RGB:       return D3DFMT_X8R8G8B8;
44         case Texture::PF_RGB_565:   return D3DFMT_R5G6B5;
45         case Texture::PF_RGBA_4444: return D3DFMT_A4R4G4B4;
46         case Texture::PF_RGBA_DXT1: return D3DFMT_DXT1;
47         case Texture::PF_RGBA_DXT3: return D3DFMT_DXT3;
48         case Texture::PF_RGBA_DXT5: return D3DFMT_DXT5;
49         default:                    return D3DFMT_UNKNOWN;
50     }
51 }
52 
53 //----------------------------------------------------------------------------//
54 // helper function to return byte width of given pixel width in given format
calculateDataWidth(const size_t width,Texture::PixelFormat fmt)55 static size_t calculateDataWidth(const size_t width, Texture::PixelFormat fmt)
56 {
57     switch (fmt)
58     {
59     case Texture::PF_RGBA:
60         return width * 4;
61 
62     case Texture::PF_RGB:
63         return width * 3;
64 
65     case Texture::PF_RGB_565:
66     case Texture::PF_RGBA_4444:
67         return width * 2;
68 
69     case Texture::PF_RGBA_DXT1:
70         return ((width + 3) / 4) * 8;
71 
72     case Texture::PF_RGBA_DXT3:
73     case Texture::PF_RGBA_DXT5:
74         return ((width + 3) / 4) * 16;
75 
76     default:
77         return 0;
78     }
79 }
80 
81 //----------------------------------------------------------------------------//
82 // Helper utility function that copies an RGB buffer into a region of a second
83 // buffer as BGR data values (i.e swap red and blue)
blitRGBToBGRSurface(const uchar * src,uchar * dst,const Sizef & sz)84 static void blitRGBToBGRSurface(const uchar* src, uchar* dst, const Sizef& sz)
85 {
86     for (uint i = 0; i < sz.d_height; ++i)
87     {
88         for (uint j = 0; j < sz.d_width; ++j)
89         {
90             *dst++ = src[2];
91             *dst++ = src[1];
92             *dst++ = src[0];
93             src += 3;
94         }
95     }
96 }
97 
98 //----------------------------------------------------------------------------//
99 // Helper utility function that copies an RGBA buffer into a region of a second
100 // buffer as D3DCOLOR data values
blitRGBAToD3DCOLORSurface(const uint32 * src,uint32 * dst,const Sizef & sz,size_t dest_pitch)101 static void blitRGBAToD3DCOLORSurface(const uint32* src, uint32* dst,
102                                       const Sizef& sz, size_t dest_pitch)
103 {
104     for (uint i = 0; i < sz.d_height; ++i)
105     {
106         for (uint j = 0; j < sz.d_width; ++j)
107         {
108             const uint32 pixel = src[j];
109             const uint32 tmp = pixel & 0x00FF00FF;
110             dst[j] = (pixel & 0xFF00FF00) | (tmp << 16) | (tmp >> 16);
111         }
112 
113         dst += dest_pitch / sizeof(uint32);
114         src += static_cast<uint32>(sz.d_width);
115     }
116 }
117 
118 //----------------------------------------------------------------------------//
119 // Helper utility function that copies a region of a buffer containing D3DCOLOR
120 // values into a second buffer as RGBA values.
blitD3DCOLORSurfaceToRGBA(const uint32 * src,uint32 * dst,const Sizef & sz,size_t source_pitch)121 static void blitD3DCOLORSurfaceToRGBA(const uint32* src, uint32* dst,
122                                       const Sizef& sz, size_t source_pitch)
123 {
124     for (uint i = 0; i < sz.d_height; ++i)
125     {
126         for (uint j = 0; j < sz.d_width; ++j)
127         {
128             const uint32 pixel = src[j];
129             const uint32 tmp = pixel & 0x00FF00FF;
130             dst[j] = (pixel & 0xFF00FF00) | (tmp << 16) | (tmp >> 16);
131         }
132 
133         src += source_pitch / sizeof(uint32);
134         dst += static_cast<uint32>(sz.d_width);
135     }
136 }
137 
138 //----------------------------------------------------------------------------//
139 // Helper class to wrap an image pixel buffer.  The main purpose of this is
140 // to prevent the need to have lots of conditionals and raw pointers that need
141 // managing in places where exceptions are used (i.e this prevents leaks while
142 // keeping code clean).
143 class PixelBuffer
144 {
145     const uchar* d_sourceBuffer;
146     uchar* d_workBuffer;
147     size_t d_pitch;
148 
149 public:
150     //------------------------------------------------------------------------//
PixelBuffer(const void * data,const Sizef & size,Texture::PixelFormat format)151     PixelBuffer(const void* data, const Sizef& size, Texture::PixelFormat format) :
152         d_sourceBuffer(static_cast<const uchar*>(data)),
153         d_workBuffer(0),
154         d_pitch(calculateDataWidth(static_cast<size_t>(size.d_width), format))
155     {
156         if (format != Texture::PF_RGBA && format != Texture::PF_RGB)
157             return;
158 
159         d_workBuffer = new uchar[d_pitch * static_cast<size_t>(size.d_height)];
160 
161         if (format == Texture::PF_RGBA)
162             blitRGBAToD3DCOLORSurface(reinterpret_cast<const uint32*>(d_sourceBuffer),
163                                       reinterpret_cast<uint32*>(d_workBuffer),
164                                       size, d_pitch);
165         else
166             blitRGBToBGRSurface(d_sourceBuffer, d_workBuffer, size);
167     }
168 
169     //------------------------------------------------------------------------//
~PixelBuffer()170     ~PixelBuffer()
171     {
172         delete[] d_workBuffer;
173     }
174 
175     //------------------------------------------------------------------------//
getPitch() const176     size_t getPitch() const
177     {
178         return d_pitch;
179     }
180 
181     //------------------------------------------------------------------------//
getPixelDataPtr() const182     const uchar* getPixelDataPtr() const
183     {
184         return d_workBuffer ? d_workBuffer : d_sourceBuffer;
185     }
186 
187     //------------------------------------------------------------------------//
188 };
189 
190 //----------------------------------------------------------------------------//
191 // Internal helper class to wrap the internal handling needed to copy data to
192 // and from a D3D9 texture.
193 class D3DSurfaceBlitter
194 {
195 public:
196     //------------------------------------------------------------------------//
D3DSurfaceBlitter(LPDIRECT3DDEVICE9 d3d_device,LPDIRECT3DTEXTURE9 tex)197     D3DSurfaceBlitter(LPDIRECT3DDEVICE9 d3d_device, LPDIRECT3DTEXTURE9 tex) :
198         d_device(d3d_device),
199         d_texture(tex),
200         d_renderTarget(0),
201         d_offscreen(0)
202     {
203         populateTextureSurfaceDescription();
204     }
205 
206     //------------------------------------------------------------------------//
~D3DSurfaceBlitter()207     ~D3DSurfaceBlitter()
208     {
209         cleanupSurfaces();
210     }
211 
212     //------------------------------------------------------------------------//
blitFromMemory(const uint32 * source,const Rectf & area)213     void blitFromMemory(const uint32* source, const Rectf& area)
214     {
215         if (!d_texture)
216             return;
217 
218         RECT target_rect = {static_cast<LONG>(area.left()), static_cast<LONG>(area.top()),
219                             static_cast<LONG>(area.right()), static_cast<LONG>(area.bottom())};
220 
221         lockRect(&target_rect);
222 
223         blitRGBAToD3DCOLORSurface(
224             source, static_cast<uint32*>(d_lockedRect.pBits),
225             area.getSize(), d_lockedRect.Pitch);
226 
227         unlockRect(&target_rect, true);
228     }
229 
230     //------------------------------------------------------------------------//
blitToMemory(uint32 * dest)231     void blitToMemory(uint32* dest)
232     {
233         if (!d_texture)
234             return;
235 
236         lockRect(0, true);
237 
238         blitD3DCOLORSurfaceToRGBA(
239             static_cast<uint32*>(d_lockedRect.pBits), dest,
240             Sizef(static_cast<float>(d_surfDesc.Width), static_cast<float>(d_surfDesc.Height)),
241             d_lockedRect.Pitch);
242 
243         unlockRect();
244     }
245 
246     //------------------------------------------------------------------------//
isRenderTarget() const247     bool isRenderTarget() const
248     {
249         return d_surfDesc.Usage == D3DUSAGE_RENDERTARGET;
250     }
251 
252     //------------------------------------------------------------------------//
253 
254 private:
255     LPDIRECT3DDEVICE9 d_device;
256     LPDIRECT3DTEXTURE9 d_texture;
257     LPDIRECT3DSURFACE9 d_renderTarget;
258     LPDIRECT3DSURFACE9 d_offscreen;
259     D3DSURFACE_DESC d_surfDesc;
260     D3DLOCKED_RECT d_lockedRect;
261     RECT d_fullArea;
262 
263     //------------------------------------------------------------------------//
initialiseSurfaces()264     void initialiseSurfaces()
265     {
266         if (!d_offscreen)
267             createOffscreenSurface();
268 
269         if (!d_renderTarget)
270             getTextureSurface();
271     }
272 
273     //------------------------------------------------------------------------//
cleanupSurfaces()274     void cleanupSurfaces()
275     {
276         if (d_renderTarget)
277         {
278             d_renderTarget->Release();
279             d_renderTarget = 0;
280         }
281 
282         if (d_offscreen)
283         {
284             d_offscreen->Release();
285             d_offscreen = 0;
286         }
287     }
288 
289     //------------------------------------------------------------------------//
lockRect(RECT * area=0,bool for_reading=false)290     void lockRect(RECT* area = 0, bool for_reading = false)
291     {
292         if (isRenderTarget())
293         {
294             initialiseSurfaces();
295 
296             if (for_reading)
297                 getRenderTargetData();
298 
299             lockSurfaceRect(area);
300         }
301         else
302         {
303             lockTextureRect(area);
304         }
305     }
306 
307     //------------------------------------------------------------------------//
unlockRect(RECT * area=0,bool needs_update=false)308     void unlockRect(RECT* area = 0, bool needs_update = false)
309     {
310         if (isRenderTarget())
311         {
312             d_offscreen->UnlockRect();
313 
314             if (needs_update)
315                 updateRenderTarget(area);
316         }
317         else
318             d_texture->UnlockRect(0);
319     }
320 
321     //------------------------------------------------------------------------//
populateTextureSurfaceDescription()322     void populateTextureSurfaceDescription()
323     {
324         if (FAILED(d_texture->GetLevelDesc(0, &d_surfDesc)))
325             CEGUI_THROW(RendererException(
326                 "IDirect3DTexture9::GetLevelDesc failed."));
327 
328         d_fullArea.left = 0;
329         d_fullArea.top = 0;
330         d_fullArea.right = d_surfDesc.Width;
331         d_fullArea.bottom = d_surfDesc.Height;
332     }
333 
334     //------------------------------------------------------------------------//
createOffscreenSurface()335     void createOffscreenSurface()
336     {
337         if (FAILED(d_device->CreateOffscreenPlainSurface(
338             d_surfDesc.Width, d_surfDesc.Height, d_surfDesc.Format,
339             D3DPOOL_SYSTEMMEM, &d_offscreen, 0)))
340         {
341             CEGUI_THROW(RendererException(
342                 "IDirect3DDevice9::CreateOffscreenPlainSurface failed."));
343         }
344     }
345 
346     //------------------------------------------------------------------------//
getTextureSurface()347     void getTextureSurface()
348     {
349         if (FAILED(d_texture->GetSurfaceLevel(0, &d_renderTarget)))
350             CEGUI_THROW(RendererException(
351                 "IDirect3DTexture9::GetSurfaceLevel failed."));
352     }
353 
354     //------------------------------------------------------------------------//
lockSurfaceRect(RECT * area)355     void lockSurfaceRect(RECT* area)
356     {
357         if (FAILED(d_offscreen->LockRect(&d_lockedRect, area, 0)))
358             CEGUI_THROW(RendererException(
359                 "IDirect3DSurface9::LockRect failed."));
360     }
361 
362     //------------------------------------------------------------------------//
lockTextureRect(RECT * area)363     void lockTextureRect(RECT* area)
364     {
365         if (FAILED(d_texture->LockRect(0, &d_lockedRect, area, 0)))
366             CEGUI_THROW(RendererException(
367                 "IDirect3DTexture9::LockRect failed."));
368     }
369 
370     //------------------------------------------------------------------------//
updateRenderTarget(RECT * area)371     void updateRenderTarget(RECT* area)
372     {
373         POINT pt = {area ? area->left : 0, area ? area->top : 0};
374         if (FAILED(d_device->UpdateSurface(d_offscreen,
375                                            area ? area : &d_fullArea,
376                                            d_renderTarget, &pt)))
377         {
378             CEGUI_THROW(RendererException(
379                 "IDirect3DDevice9::UpdateSurface failed."));
380         }
381     }
382 
383     //------------------------------------------------------------------------//
getRenderTargetData()384     void getRenderTargetData()
385     {
386         if (FAILED(d_device->GetRenderTargetData(d_renderTarget, d_offscreen)))
387             CEGUI_THROW(RendererException(
388                 "IDirect3DDevice9::GetRenderTargetData failed."));
389     }
390 
391     //------------------------------------------------------------------------//
392 };
393 
394 //----------------------------------------------------------------------------//
Direct3D9Texture(Direct3D9Renderer & owner,const String & name)395 Direct3D9Texture::Direct3D9Texture(Direct3D9Renderer& owner,
396                                    const String& name) :
397     d_owner(owner),
398     d_texture(0),
399     d_size(0, 0),
400     d_dataSize(0, 0),
401     d_texelScaling(0, 0),
402     d_savedSurfaceDescValid(false),
403     d_name(name)
404 {
405 }
406 
407 //----------------------------------------------------------------------------//
Direct3D9Texture(Direct3D9Renderer & owner,const String & name,const String & filename,const String & resourceGroup)408 Direct3D9Texture::Direct3D9Texture(Direct3D9Renderer& owner,
409                                    const String& name,
410                                    const String& filename,
411                                    const String& resourceGroup) :
412     d_owner(owner),
413     d_texture(0),
414     d_size(0, 0),
415     d_dataSize(0, 0),
416     d_texelScaling(0, 0),
417     d_savedSurfaceDescValid(false),
418     d_name(name)
419 {
420     loadFromFile(filename, resourceGroup);
421 }
422 
423 //----------------------------------------------------------------------------//
Direct3D9Texture(Direct3D9Renderer & owner,const String & name,const Sizef & sz)424 Direct3D9Texture::Direct3D9Texture(Direct3D9Renderer& owner,
425                                    const String& name, const Sizef& sz) :
426     d_owner(owner),
427     d_texture(0),
428     d_size(0, 0),
429     d_dataSize(sz),
430     d_texelScaling(0, 0),
431     d_savedSurfaceDescValid(false),
432     d_name(name)
433 {
434     createDirect3D9Texture(sz, D3DFMT_A8R8G8B8);
435 }
436 
437 //----------------------------------------------------------------------------//
Direct3D9Texture(Direct3D9Renderer & owner,const String & name,LPDIRECT3DTEXTURE9 tex)438 Direct3D9Texture::Direct3D9Texture(Direct3D9Renderer& owner,
439                                    const String& name,
440                                    LPDIRECT3DTEXTURE9 tex) :
441     d_owner(owner),
442     d_texture(0),
443     d_size(0, 0),
444     d_dataSize(0, 0),
445     d_texelScaling(0, 0),
446     d_savedSurfaceDescValid(false),
447     d_name(name)
448 {
449     setDirect3D9Texture(tex);
450 }
451 
452 //----------------------------------------------------------------------------//
~Direct3D9Texture()453 Direct3D9Texture::~Direct3D9Texture()
454 {
455     cleanupDirect3D9Texture();
456 }
457 
458 //----------------------------------------------------------------------------//
setDirect3D9Texture(LPDIRECT3DTEXTURE9 tex)459 void Direct3D9Texture::setDirect3D9Texture(LPDIRECT3DTEXTURE9 tex)
460 {
461     if (d_texture != tex)
462     {
463         cleanupDirect3D9Texture();
464         d_dataSize.d_width = d_dataSize.d_height = 0;
465 
466         d_texture = tex;
467         if (d_texture)
468             d_texture->AddRef();
469     }
470 
471     updateTextureSize();
472     d_dataSize = d_size;
473     updateCachedScaleValues();
474 }
475 
476 //----------------------------------------------------------------------------//
getDirect3D9Texture() const477 LPDIRECT3DTEXTURE9 Direct3D9Texture::getDirect3D9Texture() const
478 {
479     return d_texture;
480 }
481 
482 //----------------------------------------------------------------------------//
getName() const483 const String& Direct3D9Texture::getName() const
484 {
485     return d_name;
486 }
487 
488 //----------------------------------------------------------------------------//
getSize() const489 const Sizef& Direct3D9Texture::getSize() const
490 {
491     return d_size;
492 }
493 
494 //----------------------------------------------------------------------------//
getOriginalDataSize() const495 const Sizef& Direct3D9Texture::getOriginalDataSize() const
496 {
497     return d_dataSize;
498 }
499 
500 //----------------------------------------------------------------------------//
getTexelScaling() const501 const Vector2f& Direct3D9Texture::getTexelScaling() const
502 {
503     return d_texelScaling;
504 }
505 
506 //----------------------------------------------------------------------------//
loadFromFile(const String & filename,const String & resourceGroup)507 void Direct3D9Texture::loadFromFile(const String& filename,
508                                     const String& resourceGroup)
509 {
510     // get and check existence of CEGUI::System object
511     System* sys = System::getSingletonPtr();
512     if (!sys)
513         CEGUI_THROW(RendererException(
514             "CEGUI::System object has not been created!"));
515 
516     // load file to memory via resource provider
517     RawDataContainer texFile;
518     sys->getResourceProvider()->loadRawDataContainer(filename, texFile,
519             resourceGroup);
520 
521     Texture* res = sys->getImageCodec().load(texFile, this);
522 
523     // unload file data buffer
524     sys->getResourceProvider()->unloadRawDataContainer(texFile);
525 
526     if (!res)
527         // It's an error
528         CEGUI_THROW(RendererException(
529             sys->getImageCodec().getIdentifierString() +
530             " failed to load image '" + filename + "'."));
531 }
532 
533 //----------------------------------------------------------------------------//
loadFromMemory(const void * buffer,const Sizef & buffer_size,PixelFormat pixel_format)534 void Direct3D9Texture::loadFromMemory(const void* buffer,
535                                       const Sizef& buffer_size,
536                                       PixelFormat pixel_format)
537 {
538     if (!isPixelFormatSupported(pixel_format))
539         CEGUI_THROW(InvalidRequestException(
540             "Data was supplied in an unsupported pixel format."));
541 
542     const D3DFORMAT pixfmt = toD3DPixelFormat(pixel_format);
543     createDirect3D9Texture(buffer_size, pixfmt);
544 
545     LPDIRECT3DSURFACE9 surface = getTextureSurface();
546     const PixelBuffer pixel_buffer(buffer, buffer_size, pixel_format);
547 
548     const RECT src_rect = { 0, 0,
549         static_cast<LONG>(buffer_size.d_width),
550         static_cast<LONG>(buffer_size.d_height) };
551 
552     HRESULT hr = D3DXLoadSurfaceFromMemory(
553             surface, 0, 0, pixel_buffer.getPixelDataPtr(),
554             pixfmt == D3DFMT_X8R8G8B8 ? D3DFMT_R8G8B8 : pixfmt,
555             pixel_buffer.getPitch(), 0, &src_rect, D3DX_FILTER_NONE, 0);
556 
557     surface->Release();
558 
559     if (FAILED(hr))
560         CEGUI_THROW(RendererException(
561             "D3DXLoadSurfaceFromMemory failed."));
562 }
563 
564 //----------------------------------------------------------------------------//
createDirect3D9Texture(const Sizef sz,D3DFORMAT format)565 void Direct3D9Texture::createDirect3D9Texture(const Sizef sz, D3DFORMAT format)
566 {
567     cleanupDirect3D9Texture();
568 
569     const Sizef tex_sz(d_owner.getAdjustedSize(sz));
570 
571     HRESULT hr = D3DXCreateTexture(d_owner.getDevice(),
572                                    static_cast<UINT>(tex_sz.d_width),
573                                    static_cast<UINT>(tex_sz.d_height),
574                                    1, 0, format, D3DPOOL_MANAGED, &d_texture);
575 
576     if (FAILED(hr))
577         CEGUI_THROW(RendererException("D3DXCreateTexture failed."));
578 
579     d_dataSize = sz;
580     updateTextureSize();
581     updateCachedScaleValues();
582 }
583 
584 //----------------------------------------------------------------------------//
getTextureSurface() const585 IDirect3DSurface9* Direct3D9Texture::getTextureSurface() const
586 {
587     LPDIRECT3DSURFACE9 surface;
588     HRESULT hr = d_texture->GetSurfaceLevel(0, &surface);
589 
590     if (FAILED(hr))
591         CEGUI_THROW(RendererException(
592             "IDirect3DTexture9::GetSurfaceLevel failed."));
593 
594     return surface;
595 }
596 
597 //----------------------------------------------------------------------------//
blitFromMemory(const void * sourceData,const Rectf & area)598 void Direct3D9Texture::blitFromMemory(const void* sourceData, const Rectf& area)
599 {
600     D3DSurfaceBlitter blitter(d_owner.getDevice(), d_texture);
601     blitter.blitFromMemory(static_cast<const uint32*>(sourceData), area);
602 }
603 
604 //----------------------------------------------------------------------------//
blitToMemory(void * targetData)605 void Direct3D9Texture::blitToMemory(void* targetData)
606 {
607     D3DSurfaceBlitter blitter(d_owner.getDevice(), d_texture);
608     blitter.blitToMemory(static_cast<uint32*>(targetData));
609 }
610 
611 //----------------------------------------------------------------------------//
cleanupDirect3D9Texture()612 void Direct3D9Texture::cleanupDirect3D9Texture()
613 {
614     if (d_texture)
615     {
616         d_texture->Release();
617         d_texture = 0;
618     }
619 }
620 
621 //----------------------------------------------------------------------------//
updateCachedScaleValues()622 void Direct3D9Texture::updateCachedScaleValues()
623 {
624     //
625     // calculate what to use for x scale
626     //
627     const float orgW = d_dataSize.d_width;
628     const float texW = d_size.d_width;
629 
630     // if texture and original data width are the same, scale is based
631     // on the original size.
632     // if texture is wider (and source data was not stretched), scale
633     // is based on the size of the resulting texture.
634     d_texelScaling.d_x = 1.0f / ((orgW == texW) ? orgW : texW);
635 
636     //
637     // calculate what to use for y scale
638     //
639     const float orgH = d_dataSize.d_height;
640     const float texH = d_size.d_height;
641 
642     // if texture and original data height are the same, scale is based
643     // on the original size.
644     // if texture is taller (and source data was not stretched), scale
645     // is based on the size of the resulting texture.
646     d_texelScaling.d_y = 1.0f / ((orgH == texH) ? orgH : texH);
647 }
648 
649 //----------------------------------------------------------------------------//
updateTextureSize()650 void Direct3D9Texture::updateTextureSize()
651 {
652     D3DSURFACE_DESC surfDesc;
653 
654     // obtain details of the size of the texture
655     if (d_texture && SUCCEEDED(d_texture->GetLevelDesc(0, &surfDesc)))
656     {
657         d_size.d_width  = static_cast<float>(surfDesc.Width);
658         d_size.d_height = static_cast<float>(surfDesc.Height);
659     }
660     // use the original size if query failed.
661     // NB: This should probably be an exception.
662     else
663         d_size = d_dataSize;
664 }
665 
666 //----------------------------------------------------------------------------//
setOriginalDataSize(const Sizef & sz)667 void Direct3D9Texture::setOriginalDataSize(const Sizef& sz)
668 {
669     d_dataSize = sz;
670     updateCachedScaleValues();
671 }
672 
673 //----------------------------------------------------------------------------//
preD3DReset()674 void Direct3D9Texture::preD3DReset()
675 {
676     // if already saved surface info, or we have no texture, do nothing
677     if (d_savedSurfaceDescValid || !d_texture)
678         return;
679 
680     // get info about our texture
681     d_texture->GetLevelDesc(0, &d_savedSurfaceDesc);
682 
683     // if texture is managed, we have nothing more to do
684     if (d_savedSurfaceDesc.Pool == D3DPOOL_MANAGED)
685         return;
686 
687     // otherwise release texture.
688     d_texture->Release();
689     d_texture = 0;
690     d_savedSurfaceDescValid = true;
691 }
692 
693 //----------------------------------------------------------------------------//
postD3DReset()694 void Direct3D9Texture::postD3DReset()
695 {
696     // if texture has no saved surface info, we do nothing.
697     if (!d_savedSurfaceDescValid)
698         return;
699 
700     // otherwise, create a new texture using saved details.
701     d_owner.getDevice()->
702         CreateTexture(d_savedSurfaceDesc.Width,
703                       d_savedSurfaceDesc.Height,
704                       1, d_savedSurfaceDesc.Usage, d_savedSurfaceDesc.Format,
705                       d_savedSurfaceDesc.Pool, &d_texture, 0);
706 
707     d_savedSurfaceDescValid = false;
708 }
709 
710 //----------------------------------------------------------------------------//
isPixelFormatSupported(const PixelFormat fmt) const711 bool Direct3D9Texture::isPixelFormatSupported(const PixelFormat fmt) const
712 {
713     D3DDEVICE_CREATION_PARAMETERS dev_params;
714     d_owner.getDevice()->GetCreationParameters(&dev_params);
715 
716     LPDIRECT3D9 d3d;
717     d_owner.getDevice()->GetDirect3D(&d3d);
718 
719     D3DDISPLAYMODE dmode;
720     d3d->GetAdapterDisplayMode(dev_params.AdapterOrdinal, &dmode);
721 
722     const D3DFORMAT d3d_format = toD3DPixelFormat(fmt);
723 
724     if (d3d_format == D3DFMT_UNKNOWN)
725         return false;
726 
727     return SUCCEEDED(d3d->CheckDeviceFormat(
728         dev_params.AdapterOrdinal, dev_params.DeviceType,
729         dmode.Format, 0, D3DRTYPE_TEXTURE, d3d_format));
730 }
731 
732 //----------------------------------------------------------------------------//
733 
734 } // End of  CEGUI namespace section
735