1 | /*
|
---|
2 | -----------------------------------------------------------------------------
|
---|
3 | This source file is part of OGRE
|
---|
4 | (Object-oriented Graphics Rendering Engine)
|
---|
5 | For the latest info, see http://www.ogre3d.org/
|
---|
6 |
|
---|
7 | Copyright (c) 2000-2005 The OGRE Team
|
---|
8 | Also see acknowledgements in Readme.html
|
---|
9 |
|
---|
10 | This program is free software; you can redistribute it and/or modify it under
|
---|
11 | the terms of the GNU Lesser General Public License as published by the Free Software
|
---|
12 | Foundation; either version 2 of the License, or (at your option) any later
|
---|
13 | version.
|
---|
14 |
|
---|
15 | This program is distributed in the hope that it will be useful, but WITHOUT
|
---|
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
---|
17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
---|
18 |
|
---|
19 | You should have received a copy of the GNU Lesser General Public License along with
|
---|
20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
---|
21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to
|
---|
22 | http://www.gnu.org/copyleft/lesser.txt.
|
---|
23 | -----------------------------------------------------------------------------
|
---|
24 | */
|
---|
25 | #include "OgreD3D7Texture.h"
|
---|
26 | #include "OgreException.h"
|
---|
27 | #include "OgreImage.h"
|
---|
28 | #include "OgreLogManager.h"
|
---|
29 | #include "OgreHardwarePixelBuffer.h"
|
---|
30 | #include "OgreRoot.h"
|
---|
31 |
|
---|
32 | namespace Ogre {
|
---|
33 |
|
---|
34 | D3DX_SURFACEFORMAT D3DTexture::OgreFormat_to_D3DXFormat( PixelFormat format )
|
---|
35 | {
|
---|
36 | switch( format )
|
---|
37 | {
|
---|
38 | case PF_R8G8B8:
|
---|
39 | return D3DX_SF_R8G8B8;
|
---|
40 | case PF_A8R8G8B8:
|
---|
41 | return D3DX_SF_A8R8G8B8;
|
---|
42 | case PF_X8R8G8B8:
|
---|
43 | return D3DX_SF_X8R8G8B8;
|
---|
44 | case PF_R5G6B5:
|
---|
45 | return D3DX_SF_R5G6B5;
|
---|
46 | case PF_A4R4G4B4:
|
---|
47 | return D3DX_SF_A4R4G4B4;
|
---|
48 | case PF_L8:
|
---|
49 | return D3DX_SF_L8;
|
---|
50 | case PF_BYTE_LA: // Assume little endian
|
---|
51 | return D3DX_SF_A8L8;
|
---|
52 | case PF_DXT1:
|
---|
53 | return D3DX_SF_DXT1;
|
---|
54 | case PF_DXT3:
|
---|
55 | return D3DX_SF_DXT3;
|
---|
56 | case PF_DXT5:
|
---|
57 | return D3DX_SF_DXT5;
|
---|
58 | case PF_A8:
|
---|
59 | return D3DX_SF_A8;
|
---|
60 | default:
|
---|
61 | return D3DX_SF_UNKNOWN;
|
---|
62 | }
|
---|
63 | }
|
---|
64 |
|
---|
65 | PixelFormat D3DTexture::closestD3DXFormat( PixelFormat format )
|
---|
66 | {
|
---|
67 | if(OgreFormat_to_D3DXFormat(format) != D3DX_SF_UNKNOWN)
|
---|
68 | {
|
---|
69 | // Format is directly supported -- great!
|
---|
70 | return format;
|
---|
71 | }
|
---|
72 | switch(format)
|
---|
73 | {
|
---|
74 | case PF_B5G6R5:
|
---|
75 | return PF_R5G6B5;
|
---|
76 | case PF_B8G8R8:
|
---|
77 | return PF_R8G8B8;
|
---|
78 | case PF_B8G8R8A8:
|
---|
79 | return PF_A8R8G8B8;
|
---|
80 | default:
|
---|
81 | return PF_A8R8G8B8;
|
---|
82 | }
|
---|
83 | }
|
---|
84 |
|
---|
85 | bool D3DTexture::OgreFormat_to_DDPixelFormat( PixelFormat format, DDPIXELFORMAT & out )
|
---|
86 | {
|
---|
87 | D3DX_SURFACEFORMAT fmt = OgreFormat_to_D3DXFormat(format);
|
---|
88 | if(fmt != D3DX_SF_UNKNOWN)
|
---|
89 | {
|
---|
90 | D3DXMakeDDPixelFormat(fmt, &out);
|
---|
91 | return true;
|
---|
92 | }
|
---|
93 | return false;
|
---|
94 | #if 0
|
---|
95 | memset( &out, 0, sizeof( DDPIXELFORMAT ) );
|
---|
96 | out.dwSize = sizeof( DDPIXELFORMAT );
|
---|
97 | if(PixelUtil::isNativeEndian(format))
|
---|
98 | {
|
---|
99 | int depths[4];
|
---|
100 | uint32 masks[4];
|
---|
101 | size_t elemBits = PixelUtil::getNumElemBits(format);
|
---|
102 | PixelUtil::getBitDepths(format, depths);
|
---|
103 | PixelUtil::getBitMasks(format, masks);
|
---|
104 |
|
---|
105 | if(PixelUtil::isLuminance(format))
|
---|
106 | {
|
---|
107 | out.dwFlags = DDPF_LUMINANCE;
|
---|
108 | out.dwLuminanceBitCount = elemBits;
|
---|
109 | out.dwLuminanceBitMask = masks[0];
|
---|
110 | if(PixelUtil::hasAlpha(format))
|
---|
111 | {
|
---|
112 | out.dwFlags |= DDPF_ALPHAPIXELS;
|
---|
113 | out.dwLuminanceAlphaBitMask = masks[3];
|
---|
114 | }
|
---|
115 | }
|
---|
116 | else if(depths[0]==0 && depths[1]==0 && depths[2] == 0 && depths[3] != 0)
|
---|
117 | {
|
---|
118 | // Alpha only format
|
---|
119 | out.dwFlags = DDPF_ALPHA;
|
---|
120 | out.dwAlphaBitDepth = elemBits;
|
---|
121 | }
|
---|
122 | else
|
---|
123 | {
|
---|
124 | // RGB[A] format
|
---|
125 | out.dwFlags = DDPF_RGB;
|
---|
126 | out.dwRGBBitCount = elemBits;
|
---|
127 | out.dwRBitMask = masks[0];
|
---|
128 | out.dwGBitMask = masks[1];
|
---|
129 | out.dwBBitMask = masks[2];
|
---|
130 |
|
---|
131 | if(PixelUtil::hasAlpha(format))
|
---|
132 | {
|
---|
133 | out.dwFlags |= DDPF_ALPHAPIXELS;
|
---|
134 | out.dwRGBAlphaBitMask = masks[3];
|
---|
135 | }
|
---|
136 | }
|
---|
137 | }
|
---|
138 | else
|
---|
139 | {
|
---|
140 | switch( format )
|
---|
141 | {
|
---|
142 | case PF_BYTE_LA:
|
---|
143 | // Assume little endian
|
---|
144 | out.dwFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS;
|
---|
145 | out.dwLuminanceBitCount = 16;
|
---|
146 |
|
---|
147 | out.dwLuminanceAlphaBitMask = 0xff00;
|
---|
148 | out.dwLuminanceBitMask = 0x00ff;
|
---|
149 | break;
|
---|
150 | default:
|
---|
151 | // Error unknown format
|
---|
152 | return false;
|
---|
153 | }
|
---|
154 | }
|
---|
155 | return true;
|
---|
156 | #endif
|
---|
157 | }
|
---|
158 |
|
---|
159 | //---------------------------------------------------------------------------------------------
|
---|
160 | D3DTexture::D3DTexture(ResourceManager* creator, const String& name,
|
---|
161 | ResourceHandle handle, const String& group, bool isManual,
|
---|
162 | ManualResourceLoader* loader, IDirect3DDevice7 * lpDirect3dDevice)
|
---|
163 | :Texture(creator, name, handle, group, isManual, loader),
|
---|
164 | mD3DDevice(lpDirect3dDevice), mRestoring(false)
|
---|
165 | {
|
---|
166 | mD3DDevice->AddRef();
|
---|
167 | }
|
---|
168 | //---------------------------------------------------------------------------------------------
|
---|
169 | D3DTexture::~D3DTexture()
|
---|
170 | {
|
---|
171 | __safeRelease( &mD3DDevice );
|
---|
172 | // have to call this here reather than in Resource destructor
|
---|
173 | // since calling virtual methods in base destructors causes crash
|
---|
174 | if (mIsLoaded)
|
---|
175 | {
|
---|
176 | unload();
|
---|
177 | }
|
---|
178 | else
|
---|
179 | {
|
---|
180 | freeInternalResources();
|
---|
181 | }
|
---|
182 | }
|
---|
183 |
|
---|
184 | //---------------------------------------------------------------------------------------------
|
---|
185 | void D3DTexture::loadImage( const Image & img )
|
---|
186 | {
|
---|
187 | // Use OGRE its own codecs
|
---|
188 | std::vector<const Image*> imagePtrs;
|
---|
189 | imagePtrs.push_back(&img);
|
---|
190 | _loadImages( imagePtrs );
|
---|
191 | }
|
---|
192 | //---------------------------------------------------------------------------------------------
|
---|
193 | void D3DTexture::loadImage3D( const Image imgs[] )
|
---|
194 | {
|
---|
195 | // Use OGRE its own codecs
|
---|
196 | std::vector<const Image*> imagePtrs;
|
---|
197 | imagePtrs.push_back(&imgs[0]);
|
---|
198 | imagePtrs.push_back(&imgs[1]);
|
---|
199 | imagePtrs.push_back(&imgs[2]);
|
---|
200 | imagePtrs.push_back(&imgs[3]);
|
---|
201 | imagePtrs.push_back(&imgs[4]);
|
---|
202 | imagePtrs.push_back(&imgs[5]);
|
---|
203 | _loadImages( imagePtrs );
|
---|
204 | }
|
---|
205 | //---------------------------------------------------------------------------------------------
|
---|
206 | void D3DTexture::createInternalResourcesImpl(void)
|
---|
207 | {
|
---|
208 | // Skip this if we're restoring device
|
---|
209 | // We're using the generic load() but skipping init since DD can restore that
|
---|
210 | if (!mRestoring)
|
---|
211 | {
|
---|
212 | if (mTextureType == TEX_TYPE_CUBE_MAP)
|
---|
213 | {
|
---|
214 | createSurface3D();
|
---|
215 | }
|
---|
216 | else if(mTextureType == TEX_TYPE_2D)
|
---|
217 | {
|
---|
218 | createSurface2D();
|
---|
219 | }
|
---|
220 | else
|
---|
221 | {
|
---|
222 | OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3DTexture::createInternalResources" );
|
---|
223 | }
|
---|
224 | _createSurfaceList();
|
---|
225 | }
|
---|
226 | }
|
---|
227 | //---------------------------------------------------------------------------------------------
|
---|
228 | void D3DTexture::restoreFromLostDevice(void)
|
---|
229 | {
|
---|
230 | if (mIsLoaded && !(mUsage & TU_RENDERTARGET))
|
---|
231 | {
|
---|
232 | mRestoring = true;
|
---|
233 | // Mark as unloaded even though we're not so we can reload content
|
---|
234 | mIsLoaded = false;
|
---|
235 | load();
|
---|
236 | mRestoring = false;
|
---|
237 | }
|
---|
238 | }
|
---|
239 | //---------------------------------------------------------------------------------------------
|
---|
240 | void D3DTexture::loadImpl(void)
|
---|
241 | {
|
---|
242 | if (mTextureType == TEX_TYPE_CUBE_MAP)
|
---|
243 | {
|
---|
244 | _constructCubeFaceNames(mName);
|
---|
245 | Image imgs[6];
|
---|
246 | for (int face = 0; face < 6; ++face)
|
---|
247 | {
|
---|
248 | imgs[face].load(mCubeFaceNames[face], mGroup);
|
---|
249 | }
|
---|
250 | loadImage3D(imgs);
|
---|
251 |
|
---|
252 | }
|
---|
253 | else if(mTextureType == TEX_TYPE_2D)
|
---|
254 | {
|
---|
255 | Image img;
|
---|
256 | img.load(mName, mGroup);
|
---|
257 |
|
---|
258 | loadImage( img );
|
---|
259 | }
|
---|
260 | else
|
---|
261 | {
|
---|
262 | OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3DTexture::loadImpl" );
|
---|
263 | }
|
---|
264 |
|
---|
265 | }
|
---|
266 | //---------------------------------------------------------------------------------------------
|
---|
267 | void D3DTexture::copyToTexture(TexturePtr& target )
|
---|
268 | {
|
---|
269 | HRESULT hr;
|
---|
270 | if( FAILED( hr = ((D3DTexture*)(target.get()))->getDDSurface()->Blt( NULL, mSurface, NULL, DDBLT_WAIT, NULL ) ) )
|
---|
271 | {
|
---|
272 | if(hr != DDERR_SURFACELOST)
|
---|
273 | OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Couldn't blit!", "D3DTexture::copyToTexture" );
|
---|
274 | }
|
---|
275 | }
|
---|
276 |
|
---|
277 | //---------------------------------------------------------------------------------------------
|
---|
278 | void D3DTexture::freeInternalResourcesImpl()
|
---|
279 | {
|
---|
280 | __safeRelease( &mSurface );
|
---|
281 | }
|
---|
282 | //---------------------------------------------------------------------------------------------
|
---|
283 | void D3DTexture::_chooseD3DFormat(DDPIXELFORMAT &ddpf)
|
---|
284 | {
|
---|
285 | //mFormat = closestD3DXFormat(mFormat);
|
---|
286 | //OgreFormat_to_DDPixelFormat(mFormat, ddpf);
|
---|
287 | /* The pixel format is always RGB */
|
---|
288 | ddpf.dwFlags = DDPF_RGB;
|
---|
289 | ddpf.dwRGBBitCount = mFinalBpp;
|
---|
290 |
|
---|
291 | if( mHasAlpha )
|
---|
292 | {
|
---|
293 | ddpf.dwFlags |= DDPF_ALPHAPIXELS;
|
---|
294 | }
|
---|
295 |
|
---|
296 | /* Compute the bit masks */
|
---|
297 | if( mFinalBpp == 16 )
|
---|
298 | {
|
---|
299 | if( mHasAlpha )
|
---|
300 | {
|
---|
301 | /* 4-4-4-4 ARGB */
|
---|
302 | ddpf.dwRGBAlphaBitMask = 0xf000;
|
---|
303 | ddpf.dwRBitMask = 0x0f00;
|
---|
304 | ddpf.dwGBitMask = 0x00f0;
|
---|
305 | ddpf.dwBBitMask = 0x000f;
|
---|
306 | mFormat = PF_A4R4G4B4;
|
---|
307 | }
|
---|
308 | else
|
---|
309 | {
|
---|
310 | /* 5-6-5 RGB */
|
---|
311 | ddpf.dwRBitMask = 0xf800;
|
---|
312 | ddpf.dwGBitMask = 0x07e0;
|
---|
313 | ddpf.dwBBitMask = 0x001f;
|
---|
314 | mFormat = PF_R5G6B5;
|
---|
315 | }
|
---|
316 | }
|
---|
317 | else
|
---|
318 | {
|
---|
319 | if( mHasAlpha )
|
---|
320 | {
|
---|
321 | /* 8-8-8-8 ARGB */
|
---|
322 | ddpf.dwRGBAlphaBitMask = 0xff000000;
|
---|
323 | ddpf.dwRBitMask = 0x00ff0000;
|
---|
324 | ddpf.dwGBitMask = 0x0000ff00;
|
---|
325 | ddpf.dwBBitMask = 0x000000ff;
|
---|
326 | mFormat = PF_A8R8G8B8;
|
---|
327 | }
|
---|
328 | else
|
---|
329 | {
|
---|
330 | /* 8-8-8 RGB */
|
---|
331 | ddpf.dwRBitMask = 0xff0000;
|
---|
332 | ddpf.dwGBitMask = 0x00ff00;
|
---|
333 | ddpf.dwBBitMask = 0x0000ff;
|
---|
334 | mFormat = PF_X8R8G8B8;
|
---|
335 | }
|
---|
336 | }
|
---|
337 | }
|
---|
338 | //---------------------------------------------------------------------------------------------
|
---|
339 | void D3DTexture::createSurface2D(void)
|
---|
340 | {
|
---|
341 | D3DDEVICEDESC7 ddDesc;
|
---|
342 | ZeroMemory( &ddDesc, sizeof(D3DDEVICEDESC7) );
|
---|
343 |
|
---|
344 | if( FAILED( mD3DDevice->GetCaps( &ddDesc ) ) )
|
---|
345 | OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR,
|
---|
346 | "Could not retrieve Direct3D Device caps.",
|
---|
347 | "D3DTexture::createSurfaces" );
|
---|
348 |
|
---|
349 | // Create a surface descriptor.
|
---|
350 | DDSURFACEDESC2 ddsd;
|
---|
351 | D3DUtil_InitSurfaceDesc( ddsd );
|
---|
352 |
|
---|
353 | ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
---|
354 | ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
---|
355 | ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
---|
356 | ddsd.ddsCaps.dwCaps2 = 0;
|
---|
357 | ddsd.dwWidth = mSrcWidth;
|
---|
358 | ddsd.dwHeight = mSrcHeight;
|
---|
359 |
|
---|
360 | /* If the texture is a render target, set the corresponding flags */
|
---|
361 | if( mUsage & TU_RENDERTARGET )
|
---|
362 | {
|
---|
363 | ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
|
---|
364 | ddsd.ddsCaps.dwCaps2 = 0;
|
---|
365 | mNumRequestedMipmaps = 0;
|
---|
366 | }
|
---|
367 | else
|
---|
368 | {
|
---|
369 | ddsd.ddsCaps.dwCaps2 = DDSCAPS2_D3DTEXTUREMANAGE;
|
---|
370 | }
|
---|
371 |
|
---|
372 | /* If we want to have mip-maps, set the flags. Note that if the
|
---|
373 | texture is the render target type mip-maps are automatically
|
---|
374 | disabled. */
|
---|
375 | if( mNumRequestedMipmaps )
|
---|
376 | {
|
---|
377 | ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
|
---|
378 | ddsd.dwMipMapCount = mNumRequestedMipmaps;
|
---|
379 |
|
---|
380 | ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
---|
381 | }
|
---|
382 |
|
---|
383 | _chooseD3DFormat(ddsd.ddpfPixelFormat);
|
---|
384 |
|
---|
385 | /* Change texture size so that it is a power of 2, if needed. */
|
---|
386 | if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
|
---|
387 | {
|
---|
388 | for( ddsd.dwWidth = 1; mSrcWidth > ddsd.dwWidth; ddsd.dwWidth <<= 1 );
|
---|
389 | for( ddsd.dwHeight = 1; mSrcHeight > ddsd.dwHeight; ddsd.dwHeight <<= 1 );
|
---|
390 | }
|
---|
391 |
|
---|
392 | /* Change texture size so that it is square, if needed. Note that we made it a
|
---|
393 | power of 2 in the above test, so here we just have to find the bigger dimension
|
---|
394 | and make it the side length. */
|
---|
395 | if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
|
---|
396 | {
|
---|
397 | if( ddsd.dwWidth > ddsd.dwHeight )
|
---|
398 | ddsd.dwHeight = ddsd.dwWidth;
|
---|
399 | else
|
---|
400 | ddsd.dwWidth = ddsd.dwHeight;
|
---|
401 | }
|
---|
402 |
|
---|
403 | /* Register the possibly modified dimensions. */
|
---|
404 | mWidth = ddsd.dwWidth;
|
---|
405 | mHeight = ddsd.dwHeight;
|
---|
406 | mIsLoaded = true;
|
---|
407 |
|
---|
408 | LPDIRECTDRAWSURFACE7 pddsRender;
|
---|
409 | LPDIRECTDRAW7 pDD;
|
---|
410 |
|
---|
411 | /* Get a DirectDraw interface. */
|
---|
412 | mD3DDevice->GetRenderTarget( &pddsRender );
|
---|
413 | pddsRender->GetDDInterface( (VOID**)&pDD );
|
---|
414 | pddsRender->Release();
|
---|
415 |
|
---|
416 | if( mUsage & TU_RENDERTARGET )
|
---|
417 | {
|
---|
418 | /* Get the pixel format of the primary surface - we need it because
|
---|
419 | render target surfaces need to have the same pixel format. */
|
---|
420 | IDirectDrawSurface7 * pddsPrimarySurface;
|
---|
421 | pDD->GetGDISurface( &pddsPrimarySurface );
|
---|
422 | pddsPrimarySurface->GetPixelFormat( &( ddsd.ddpfPixelFormat ) );
|
---|
423 | pddsPrimarySurface->Release();
|
---|
424 | }
|
---|
425 |
|
---|
426 | HRESULT hr;
|
---|
427 |
|
---|
428 | /* Now create the surface. */
|
---|
429 | if( FAILED( hr = pDD->CreateSurface( &ddsd, &mSurface, NULL ) ) )
|
---|
430 | {
|
---|
431 | pDD->Release();
|
---|
432 | OGRE_EXCEPT( hr,
|
---|
433 | "Could not create DirectDraw surface.",
|
---|
434 | "D3DTexture::createSurfaces" );
|
---|
435 | }
|
---|
436 |
|
---|
437 | if( mUsage & TU_RENDERTARGET )
|
---|
438 | {
|
---|
439 | LPDIRECTDRAWSURFACE7 pddsZBuffer, pddsBackBuffer, pddsTexZBuffer;
|
---|
440 |
|
---|
441 | DDSCAPS2 ZBuffDDSCaps;
|
---|
442 | DDSURFACEDESC2 ZBuffDDSD;
|
---|
443 |
|
---|
444 | ZBuffDDSCaps.dwCaps = DDSCAPS_ZBUFFER;
|
---|
445 | ZBuffDDSCaps.dwCaps2 = ZBuffDDSCaps.dwCaps3 = ZBuffDDSCaps.dwCaps4 = 0;
|
---|
446 |
|
---|
447 | memset( &ZBuffDDSD, 0, sizeof( DDSURFACEDESC2 ) );
|
---|
448 | ZBuffDDSD.dwSize = sizeof( DDSURFACEDESC2 );
|
---|
449 |
|
---|
450 | /* If the primary surface has an attached z-buffer, we need one for our texture
|
---|
451 | too. Here, we get the primary surface's z-buffer format and we create a new
|
---|
452 | Z-buffer that we attach to the our texture. */
|
---|
453 | if( SUCCEEDED( mD3DDevice->GetRenderTarget( &pddsBackBuffer ) ) )
|
---|
454 | {
|
---|
455 | if( SUCCEEDED( pddsBackBuffer->GetAttachedSurface( &ZBuffDDSCaps, &pddsZBuffer ) ) )
|
---|
456 | {
|
---|
457 | pddsZBuffer->GetSurfaceDesc( &ZBuffDDSD );
|
---|
458 |
|
---|
459 | /* Our new Z-buffer should have the size of the new render target. */
|
---|
460 | ZBuffDDSD.dwWidth = ddsd.dwWidth;
|
---|
461 | ZBuffDDSD.dwHeight = ddsd.dwHeight;
|
---|
462 |
|
---|
463 | hr = pDD->CreateSurface( &ZBuffDDSD, &pddsTexZBuffer, NULL );
|
---|
464 | hr = mSurface->AddAttachedSurface( pddsTexZBuffer );
|
---|
465 |
|
---|
466 | pddsBackBuffer->Release();
|
---|
467 | pddsZBuffer->Release();
|
---|
468 | pddsTexZBuffer->Release();
|
---|
469 | }
|
---|
470 | }
|
---|
471 | }
|
---|
472 |
|
---|
473 | /* Release the DirectDraw interface used in the surface creation */
|
---|
474 | pDD->Release();
|
---|
475 | }
|
---|
476 | //---------------------------------------------------------------------------------------------
|
---|
477 | void D3DTexture::createSurface3D(void)
|
---|
478 | {
|
---|
479 | D3DDEVICEDESC7 ddDesc;
|
---|
480 | ZeroMemory( &ddDesc, sizeof(D3DDEVICEDESC7) );
|
---|
481 |
|
---|
482 | if( FAILED( mD3DDevice->GetCaps( &ddDesc ) ) )
|
---|
483 | OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR,
|
---|
484 | "Could not retrieve Direct3D Device caps.",
|
---|
485 | "D3DTexture::createSurfaces" );
|
---|
486 |
|
---|
487 | // Create a surface descriptor.
|
---|
488 | DDSURFACEDESC2 ddsd;
|
---|
489 | D3DUtil_InitSurfaceDesc( ddsd );
|
---|
490 |
|
---|
491 | ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
---|
492 | ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
---|
493 | ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_TEXTURE;
|
---|
494 | ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP|DDSCAPS2_CUBEMAP_ALLFACES;
|
---|
495 | ddsd.dwWidth = mSrcWidth;
|
---|
496 | ddsd.dwHeight = mSrcHeight;
|
---|
497 |
|
---|
498 | /* If the texture is a render target, set the corresponding flags */
|
---|
499 | if( mUsage & TU_RENDERTARGET )
|
---|
500 | {
|
---|
501 | ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
|
---|
502 | mNumRequestedMipmaps = 0;
|
---|
503 | }
|
---|
504 | else
|
---|
505 | {
|
---|
506 | ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_D3DTEXTUREMANAGE;
|
---|
507 | }
|
---|
508 |
|
---|
509 | /* If we want to have mip-maps, set the flags. Note that if the
|
---|
510 | texture is the render target type mip-maps are automatically
|
---|
511 | disabled. */
|
---|
512 | if( mNumRequestedMipmaps )
|
---|
513 | {
|
---|
514 | ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
|
---|
515 | ddsd.dwMipMapCount = mNumRequestedMipmaps;
|
---|
516 |
|
---|
517 | ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
|
---|
518 | }
|
---|
519 |
|
---|
520 | _chooseD3DFormat(ddsd.ddpfPixelFormat);
|
---|
521 |
|
---|
522 | /* Change texture size so that it is a power of 2, if needed. */
|
---|
523 | if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
|
---|
524 | {
|
---|
525 | for( ddsd.dwWidth = 1; mSrcWidth > ddsd.dwWidth; ddsd.dwWidth <<= 1 );
|
---|
526 | for( ddsd.dwHeight = 1; mSrcHeight > ddsd.dwHeight; ddsd.dwHeight <<= 1 );
|
---|
527 | }
|
---|
528 |
|
---|
529 | /* Change texture size so that it is square, if needed. Note that we made it a
|
---|
530 | power of 2 in the above test, so here we just have to find the bigger dimension
|
---|
531 | and make it the side length. */
|
---|
532 | if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
|
---|
533 | {
|
---|
534 | if( ddsd.dwWidth > ddsd.dwHeight )
|
---|
535 | ddsd.dwHeight = ddsd.dwWidth;
|
---|
536 | else
|
---|
537 | ddsd.dwWidth = ddsd.dwHeight;
|
---|
538 | }
|
---|
539 |
|
---|
540 | /* Register the possibly modified dimensions. */
|
---|
541 | mWidth = ddsd.dwWidth;
|
---|
542 | mHeight = ddsd.dwHeight;
|
---|
543 | mIsLoaded = true;
|
---|
544 |
|
---|
545 |
|
---|
546 | LPDIRECTDRAWSURFACE7 pddsRender;
|
---|
547 | LPDIRECTDRAW7 pDD;
|
---|
548 |
|
---|
549 | /* Get a DirectDraw interface. */
|
---|
550 | mD3DDevice->GetRenderTarget( &pddsRender );
|
---|
551 | pddsRender->GetDDInterface( (VOID**)&pDD );
|
---|
552 | pddsRender->Release();
|
---|
553 |
|
---|
554 | if( mUsage & TU_RENDERTARGET )
|
---|
555 | {
|
---|
556 | /* Get the pixel format of the primary surface - we need it because
|
---|
557 | render target surfaces need to have the same pixel format. */
|
---|
558 | IDirectDrawSurface7 * pddsPrimarySurface;
|
---|
559 | pDD->GetGDISurface( &pddsPrimarySurface );
|
---|
560 | pddsPrimarySurface->GetPixelFormat( &( ddsd.ddpfPixelFormat ) );
|
---|
561 | pddsPrimarySurface->Release();
|
---|
562 | }
|
---|
563 |
|
---|
564 | HRESULT hr;
|
---|
565 |
|
---|
566 | /* Now create the surface. */
|
---|
567 | if( FAILED( hr = pDD->CreateSurface( &ddsd, &mSurface, NULL ) ) )
|
---|
568 | {
|
---|
569 | pDD->Release();
|
---|
570 | OGRE_EXCEPT( hr,
|
---|
571 | "Could not create DirectDraw surface.",
|
---|
572 | "D3DTexture::createSurfaces" );
|
---|
573 | }
|
---|
574 |
|
---|
575 |
|
---|
576 | if( mUsage & TU_RENDERTARGET )
|
---|
577 | {
|
---|
578 | LPDIRECTDRAWSURFACE7 pddsZBuffer, pddsBackBuffer, pddsTexZBuffer;
|
---|
579 |
|
---|
580 | DDSCAPS2 ZBuffDDSCaps;
|
---|
581 | DDSURFACEDESC2 ZBuffDDSD;
|
---|
582 |
|
---|
583 | ZBuffDDSCaps.dwCaps = DDSCAPS_ZBUFFER;
|
---|
584 | ZBuffDDSCaps.dwCaps2 = ZBuffDDSCaps.dwCaps3 = ZBuffDDSCaps.dwCaps4 = 0;
|
---|
585 |
|
---|
586 | memset( &ZBuffDDSD, 0, sizeof( DDSURFACEDESC2 ) );
|
---|
587 | ZBuffDDSD.dwSize = sizeof( DDSURFACEDESC2 );
|
---|
588 |
|
---|
589 | /* If the primary surface has an attached z-buffer, we need one for our texture
|
---|
590 | too. Here, we get the primary surface's z-buffer format and we create a new
|
---|
591 | Z-buffer that we attach to the our texture. */
|
---|
592 | if( SUCCEEDED( mD3DDevice->GetRenderTarget( &pddsBackBuffer ) ) )
|
---|
593 | {
|
---|
594 | if( SUCCEEDED( pddsBackBuffer->GetAttachedSurface( &ZBuffDDSCaps, &pddsZBuffer ) ) )
|
---|
595 | {
|
---|
596 | pddsZBuffer->GetSurfaceDesc( &ZBuffDDSD );
|
---|
597 |
|
---|
598 | /* Our new Z-buffer should have the size of the new render target. */
|
---|
599 | ZBuffDDSD.dwWidth = ddsd.dwWidth;
|
---|
600 | ZBuffDDSD.dwHeight = ddsd.dwHeight;
|
---|
601 |
|
---|
602 | hr = pDD->CreateSurface( &ZBuffDDSD, &pddsTexZBuffer, NULL );
|
---|
603 | hr = mSurface->AddAttachedSurface( pddsTexZBuffer );
|
---|
604 |
|
---|
605 | pddsBackBuffer->Release();
|
---|
606 | pddsZBuffer->Release();
|
---|
607 | pddsTexZBuffer->Release();
|
---|
608 | }
|
---|
609 | }
|
---|
610 | }
|
---|
611 |
|
---|
612 | /* Release the DirectDraw interface used in the surface creation */
|
---|
613 | pDD->Release();
|
---|
614 | }
|
---|
615 | //---------------------------------------------------------------------------------------------
|
---|
616 | LPDIRECTDRAWSURFACE7 D3DTexture::getDDSurface(void)
|
---|
617 | {
|
---|
618 | return mSurface;
|
---|
619 | }
|
---|
620 | void D3DTexture::_constructCubeFaceNames(const String name)
|
---|
621 | {
|
---|
622 | // the suffixes
|
---|
623 | String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};
|
---|
624 | size_t pos = -1;
|
---|
625 |
|
---|
626 | String ext; // the extension
|
---|
627 | String baseName; // the base name
|
---|
628 | String fakeName = name; // the 'fake' name, temp. holder
|
---|
629 |
|
---|
630 | // first find the base name
|
---|
631 | pos = fakeName.find_last_of(".");
|
---|
632 | if (pos == -1)
|
---|
633 | {
|
---|
634 | OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Invalid cube texture base name", "D3D9Texture::_constructCubeFaceNames" );
|
---|
635 | }
|
---|
636 |
|
---|
637 | baseName = fakeName.substr(0, pos);
|
---|
638 | ext = fakeName.substr(pos);
|
---|
639 |
|
---|
640 | // construct the full 6 faces file names from the baseName, suffixes and extension
|
---|
641 | for (size_t i = 0; i < 6; ++i)
|
---|
642 | mCubeFaceNames[i] = baseName + suffixes[i] + ext;
|
---|
643 | }
|
---|
644 | //---------------------------------------------------------------------------------------------
|
---|
645 | HardwarePixelBufferSharedPtr D3DTexture::getBuffer(size_t face, size_t mipmap)
|
---|
646 | {
|
---|
647 | if(face >= getNumFaces())
|
---|
648 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "A three dimensional cube has six faces",
|
---|
649 | "D3D9Texture::getBuffer");
|
---|
650 | if(mipmap > getNumMipmaps())
|
---|
651 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Mipmap index out of range",
|
---|
652 | "D3D9Texture::getBuffer");
|
---|
653 | int idx = face*(mNumMipmaps+1) + mipmap;
|
---|
654 | assert(idx < mSurfaceList.size());
|
---|
655 | return mSurfaceList[idx];
|
---|
656 | }
|
---|
657 |
|
---|
658 | //---------------------------------------------------------------------------------------------
|
---|
659 | // Macro to hide ugly cast
|
---|
660 | #define GETLEVEL(face,mip) \
|
---|
661 | static_cast<D3D7HardwarePixelBuffer*>(mSurfaceList[face*(mNumMipmaps+1)+mip].get())
|
---|
662 | void D3DTexture::_createSurfaceList()
|
---|
663 | {
|
---|
664 | HRESULT hr;
|
---|
665 | size_t face;
|
---|
666 | mSurfaceList.clear();
|
---|
667 |
|
---|
668 | // Get real number of mipmaps
|
---|
669 | DDSURFACEDESC2 desc;
|
---|
670 | desc.dwSize = sizeof(DDSURFACEDESC2);
|
---|
671 | if(mSurface->GetSurfaceDesc(&desc) != D3D_OK)
|
---|
672 | OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Could not get surface information",
|
---|
673 | "D3DTexture::_createSurfaceList()");
|
---|
674 | if(desc.dwFlags & DDSD_MIPMAPCOUNT)
|
---|
675 | mNumMipmaps = desc.dwMipMapCount;
|
---|
676 | else
|
---|
677 | mNumMipmaps = 0;
|
---|
678 |
|
---|
679 | // Create the list
|
---|
680 | HardwareBuffer::Usage bufusage;
|
---|
681 | if ((mUsage & TU_DYNAMIC))
|
---|
682 | {
|
---|
683 | bufusage = HardwareBuffer::HBU_DYNAMIC;
|
---|
684 | }
|
---|
685 | else
|
---|
686 | {
|
---|
687 | bufusage = HardwareBuffer::HBU_STATIC;
|
---|
688 | }
|
---|
689 | for(face=0; face < getNumFaces(); ++face)
|
---|
690 | {
|
---|
691 | for(size_t mip=0; mip<=mNumMipmaps; ++mip)
|
---|
692 | {
|
---|
693 | mSurfaceList.push_back(
|
---|
694 | HardwarePixelBufferSharedPtr(
|
---|
695 | new D3D7HardwarePixelBuffer(bufusage, mD3DDevice)
|
---|
696 | )
|
---|
697 | );
|
---|
698 | }
|
---|
699 | }
|
---|
700 |
|
---|
701 | // Enumerate all surfaces
|
---|
702 | for (face = 0; face < getNumFaces(); ++face)
|
---|
703 | {
|
---|
704 | LPDIRECTDRAWSURFACE7 pCubeFace;
|
---|
705 | if(mTextureType == TEX_TYPE_CUBE_MAP)
|
---|
706 | {
|
---|
707 | // Get cube map face to blit to
|
---|
708 | DDSCAPS2 cubeCaps;
|
---|
709 | ZeroMemory(&cubeCaps, sizeof(DDSCAPS2));
|
---|
710 | switch (face)
|
---|
711 | {
|
---|
712 | case 0:
|
---|
713 | // left
|
---|
714 | cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
|
---|
715 | break;
|
---|
716 | case 1:
|
---|
717 | // right
|
---|
718 | cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX;
|
---|
719 | break;
|
---|
720 | case 2:
|
---|
721 | // up
|
---|
722 | cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY;
|
---|
723 | break;
|
---|
724 | case 3:
|
---|
725 | // down
|
---|
726 | cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY;
|
---|
727 | break;
|
---|
728 | case 4:
|
---|
729 | // front - NB DirectX is backwards
|
---|
730 | cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ;
|
---|
731 | break;
|
---|
732 | case 5:
|
---|
733 | // back - NB DirectX is backwards
|
---|
734 | cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ;
|
---|
735 | break;
|
---|
736 | }
|
---|
737 |
|
---|
738 | if (FAILED(hr = mSurface->GetAttachedSurface( &cubeCaps, &pCubeFace)))
|
---|
739 | {
|
---|
740 | OGRE_EXCEPT( hr, "Error getting cube face surface.", "D3DTexture::_createSurfaceList" );
|
---|
741 | }
|
---|
742 | }
|
---|
743 | else
|
---|
744 | {
|
---|
745 | pCubeFace = mSurface;
|
---|
746 | pCubeFace->AddRef();
|
---|
747 | }
|
---|
748 |
|
---|
749 | GETLEVEL(face, 0)->bind(pCubeFace, mFormat);
|
---|
750 |
|
---|
751 | LPDIRECTDRAWSURFACE7 ddsMipLevel, ddsNextLevel;
|
---|
752 | DDSCAPS2 ddsCaps;
|
---|
753 | HRESULT mipRes = DD_OK;
|
---|
754 | size_t mipLevel = 1;
|
---|
755 |
|
---|
756 | ZeroMemory(&ddsCaps, sizeof(DDSCAPS2));
|
---|
757 | ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
|
---|
758 |
|
---|
759 | // Get the base level and increae the reference count.
|
---|
760 | ddsMipLevel = pCubeFace;
|
---|
761 | ddsMipLevel->AddRef();
|
---|
762 |
|
---|
763 | /// While we can get a next level in the mip-map chain.
|
---|
764 | while( ddsMipLevel->GetAttachedSurface( &ddsCaps, &ddsNextLevel ) == DD_OK )
|
---|
765 | {
|
---|
766 | GETLEVEL(face, mipLevel)->bind(ddsNextLevel, mFormat);
|
---|
767 | // Release the current level and get the next one, incrementing the mip depth.
|
---|
768 | ddsMipLevel->Release();
|
---|
769 | ddsMipLevel = ddsNextLevel;
|
---|
770 | mipLevel++;
|
---|
771 | }
|
---|
772 |
|
---|
773 | // Release the last mip-map level surface.
|
---|
774 | ddsMipLevel->Release();
|
---|
775 | // Release face reference
|
---|
776 | pCubeFace->Release();
|
---|
777 | }
|
---|
778 |
|
---|
779 | // Set autogeneration of mipmaps for each face of the texture, if it is enabled
|
---|
780 | if(mNumMipmaps>0 && (mUsage & TU_AUTOMIPMAP))
|
---|
781 | {
|
---|
782 | for(size_t face=0; face<getNumFaces(); ++face)
|
---|
783 | {
|
---|
784 | GETLEVEL(face, 0)->_setMipmapping(true);
|
---|
785 | }
|
---|
786 | }
|
---|
787 | }
|
---|
788 | #undef GETLEVEL
|
---|
789 | }
|
---|