1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_ResTexture.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: $
16 *---------------------------------------------------------------------------*/
17
18 #include "../precompiled.h"
19
20 #include <nw/ut/ut_ResUtil.h>
21 #include <nw/ut/ut_ResDictionary.h>
22 #include <nw/gfx/gfx_Common.h>
23 #include <nw/gfx/gfx_SceneObject.h>
24 #include <nw/gfx/res/gfx_ResTexture.h>
25 #include <nw/gfx/gfx_ShaderProgram.h>
26 #include <nw/gfx/res/gfx_ResGraphicsFile.h>
27
28 #include <nn/gx.h>
29
30 namespace nw {
31 namespace gfx {
32 namespace res {
33
34 typedef void (*SetupFunc)(ResTexture resTex);
35
36 static void ResImageTexture_Setup(ResTexture resTex);
37 static void ResCubeTexture_Setup(ResTexture resTex);
38 static void ResReferenceTexture_Setup(ResTexture resTex);
39 static void ResProceduralTexture_Setup(ResTexture resTex);
40 static void ResShadowTexture_Setup(ResTexture resTex);
41
42 static void ResImageTexture_Cleanup(ResTexture resTex);
43 static void ResCubeTexture_Cleanup(ResTexture resTex);
44 static void ResReferenceTexture_Cleanup(ResTexture resTex);
45 static void ResProceduralTexture_Cleanup(ResTexture resTex);
46 static void ResShadowTexture_Cleanup(ResTexture resTex);
47
48 static SetupFunc s_TextureSetupTable[] =
49 {
50 ResImageTexture_Setup,
51 ResCubeTexture_Setup,
52 ResReferenceTexture_Setup,
53 ResProceduralTexture_Setup,
54 ResShadowTexture_Setup
55 };
56
57 static SetupFunc s_TextureCleanupTable[] =
58 {
59 ResImageTexture_Cleanup,
60 ResCubeTexture_Cleanup,
61 ResReferenceTexture_Cleanup,
62 ResProceduralTexture_Cleanup,
63 ResShadowTexture_Cleanup
64 };
65
66 namespace {
67 // ピクセルフォーマットを取得するためのテーブルです。
68 static const uint GL_FORMAT_TABLE[] =
69 {
70 GL_RGBA_NATIVE_DMP, // 1ピクセルが4バイト、RGBAが各8ビットのフォーマットです。
71 GL_RGB_NATIVE_DMP, // 1ピクセルが4バイト、RGBが各8ビットのフォーマットです。
72 GL_RGBA_NATIVE_DMP, // 1ピクセルが2バイト、RGBが各5ビット、Aが1ビットのフォーマットです。
73 GL_RGB_NATIVE_DMP, // 1ピクセルが2バイト、RGBが各5,6,5ビットのフォーマットです。
74 GL_RGBA_NATIVE_DMP, // 1ピクセルが2バイト、RGBAが各4ビットのフォーマットです。
75 GL_LUMINANCE_ALPHA_NATIVE_DMP, // 1ピクセルが2バイト、AlpahとLuminanceが各8ビットのフォーマットです。
76 GL_HILO8_DMP_NATIVE_DMP, // 1ピクセルが2バイト、X,Yが各8ビットのフォーマットです。
77 GL_LUMINANCE_NATIVE_DMP, // 1ピクセルが1バイト、Luminanceが8ビットのフォーマットです。
78 GL_ALPHA_NATIVE_DMP, // 1ピクセルが1バイト、Alphaが8ビットのフォーマットです。
79 GL_LUMINANCE_ALPHA_NATIVE_DMP, // 1ピクセルが1バイト、AlpahとLuminanceが各4ビットのフォーマットです。
80 GL_LUMINANCE_NATIVE_DMP, // 1ピクセルが1バイト、Luminanceが4ビットのフォーマットです。
81 GL_ALPHA_NATIVE_DMP, // 1ピクセルが1バイト、Alphaが4ビットのフォーマットです。
82 GL_ETC1_RGB8_NATIVE_DMP, // 1ピクセルが4ビット相当の圧縮フォーマットです。
83 GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP // 1ピクセルが8ビット相当の圧縮フォーマットです。
84 };
85
86 static const uint GL_FORMAT_TYPE_TABLE[] =
87 {
88 GL_UNSIGNED_BYTE, // 1ピクセルが4バイト、RGBAが各8ビットのフォーマットです。
89 GL_UNSIGNED_BYTE, // 1ピクセルが4バイト、RGBが各8ビットのフォーマットです。
90 GL_UNSIGNED_SHORT_5_5_5_1, // 1ピクセルが2バイト、RGBが各5ビット、Aが1ビットのフォーマットです。
91 GL_UNSIGNED_SHORT_5_6_5, // 1ピクセルが2バイト、RGBが各5,6,5ビットのフォーマットです。
92 GL_UNSIGNED_SHORT_4_4_4_4, // 1ピクセルが2バイト、RGBAが各4ビットのフォーマットです。
93 GL_UNSIGNED_BYTE, // 1ピクセルが2バイト、AlpahとLuminanceが各8ビットのフォーマットです。
94 GL_UNSIGNED_BYTE, // 1ピクセルが2バイト、X,Yが各8ビットのフォーマットです。
95 GL_UNSIGNED_BYTE, // 1ピクセルが1バイト、Luminanceが8ビットのフォーマットです。
96 GL_UNSIGNED_BYTE, // 1ピクセルが1バイト、Alphaが8ビットのフォーマットです。
97 GL_UNSIGNED_BYTE_4_4_DMP, // 1ピクセルが1バイト、AlpahとLuminanceが各4ビットのフォーマットです
98 GL_UNSIGNED_4BITS_DMP, // 1ピクセルが1バイト、Luminanceが4ビットのフォーマットです。
99 GL_UNSIGNED_4BITS_DMP, // 1ピクセルが1バイト、Alphaが4ビットのフォーマットです。
100 0, // 1ピクセルが4ビット相当の圧縮フォーマットです。
101 0 // 1ピクセルが8ビット相当の圧縮フォーマットです。
102 };
103
104 const f32 BYTESIZE_4 = 4.0f;
105 const f32 BYTESIZE_2 = 2.0f;
106 const f32 BYTESIZE_1 = 1.0f;
107 const f32 BYTESIZE_HALF = 0.5f;
108 static const f32 BYTESIZE_PER_PIXEL_TABLE[] =
109 {
110 BYTESIZE_4,
111 BYTESIZE_4,
112 BYTESIZE_2,
113 BYTESIZE_2,
114 BYTESIZE_2,
115 BYTESIZE_2,
116 BYTESIZE_2,
117 BYTESIZE_1,
118 BYTESIZE_1,
119 BYTESIZE_1,
120 BYTESIZE_1,
121 BYTESIZE_1,
122 BYTESIZE_HALF,
123 BYTESIZE_1
124 };
125 }
126
127 //---------------------------------------------------------------------------
128 //! @brief 必要であればテクスチャのコピー用のメモリを確保し、転送をおこないます。
129 //!
130 //! @param[in] texID メモリ確保用のテクスチャIDです。
131 //! @param[in] resImage イメージリソースです。
132 //! @param[in] loadFlag テクスチャの配置メモリフラグです。
133 //---------------------------------------------------------------------------
134 static void
TexImage2D(u32 texID,ResPixelBasedImage resImage,u32 loadFlag)135 TexImage2D( u32 texID, ResPixelBasedImage resImage, u32 loadFlag )
136 {
137 u32 size = resImage.GetImageDataCount();
138 GLenum transtype = loadFlag & 0xFFFF0000;
139 const u32 NN_GX_MEM_MASK = 0x00030000;
140 void* address = NULL;
141
142 if (size == 0)
143 {
144 size = resImage.GetWidth() * resImage.GetHeight() * resImage.GetBitsPerPixel() / 8;
145 }
146
147 switch (transtype)
148 {
149 case (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP):
150 nngxUpdateBuffer( resImage.GetImageData(), size );
151 break;
152
153 case (NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP):
154 case (NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP):
155 {
156 GLuint area = (transtype & NN_GX_MEM_MASK);
157 address = __dmpgl_allocator(area, NN_GX_MEM_TEXTURE, texID, size);
158 if ( resImage.GetImageData() )
159 {
160 nngxAddVramDmaCommand( resImage.GetImageData(), address, size );
161 }
162
163 resImage.SetLocationAddress( address );
164 resImage.ref().m_MemoryArea = area;
165 }
166 break;
167
168 case (NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP):
169 {
170 address = __dmpgl_allocator(NN_GX_MEM_FCRAM, NN_GX_MEM_TEXTURE, texID, size);
171 if ( resImage.GetImageData() )
172 {
173 nw::os::MemCpy( address, resImage.GetImageData(), size );
174 nngxUpdateBuffer( address, size );
175 }
176
177 resImage.SetLocationAddress( address );
178 resImage.ref().m_MemoryArea = NN_GX_MEM_FCRAM;
179 }
180 break;
181
182 case (NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP):
183 case (NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP):
184 NW_FATAL_ERROR("(GL_COPY_FCRAM_DMP | NN_GX_MEM_VRAM) is not supported!");
185 break;
186 default:
187 break;
188 }
189 }
190
191
192 //---------------------------------------------------------------------------
193 //! @brief テクスチャ用のコピーメモリを解放します。
194 //!
195 //! @param[in] texID メモリ確保用のテクスチャIDです。
196 //! @param[in] resImage リソースのイメージです。
197 //---------------------------------------------------------------------------
198 static void
DeleteImage2D(u32 texID,ResPixelBasedImage resImage)199 DeleteImage2D( u32 texID, ResPixelBasedImage resImage )
200 {
201 GLuint area = resImage.ref().m_MemoryArea;
202
203 if (area != ResPixelBasedImageData::AREA_NO_MALLOC)
204 {
205 void* address = reinterpret_cast<void*>( resImage.GetLocationAddress() );
206 __dmpgl_deallocator( area, NN_GX_MEM_TEXTURE, texID, address );
207 resImage.SetLocationAddress( static_cast<u32>(NULL) );
208 }
209 }
210
211 //---------------------------------------------------------------------------
212 //! @brief テクスチャイメージの設定を行ないます。
213 //!
214 //! @param[in] resImage 設定するイメージリソースです。
215 //! @param[in] loadFlag テクスチャのメモリ配置指定フラグです。
216 //---------------------------------------------------------------------------
217 static inline void
SetTexImage2D(u32 texID,ResPixelBasedImage resImage,u32 loadFlag)218 SetTexImage2D( u32 texID, ResPixelBasedImage resImage, u32 loadFlag )
219 {
220 NW_ASSERT( resImage.IsValid() );
221
222 // 既にアドレスが設定されている場合はデータのコピーをおこなわない。
223 if (resImage.GetLocationAddress() != NULL)
224 {
225 resImage.ref().m_MemoryArea = ResPixelBasedImageData::AREA_NO_MALLOC;
226 return;
227 }
228
229 // テクスチャのメモリへの読み込み指定
230 // デフォルトは、FCRAM から NO_COPY。
231 if (loadFlag == 0)
232 {
233 loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
234 }
235
236 // FCRAM, NO_COPY の場合は、アライメントチェック。デバイスメモリ 且つ 128バイトアライメント。
237 NW_ASSERT( (loadFlag != (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP)) || resImage.CheckMemoryLocation() );
238
239 TexImage2D( texID, resImage, loadFlag );
240 }
241
242
243 /*!--------------------------------------------------------------------------*
244 @brief イメージテクスチャをセットアップします。
245
246 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
247 *---------------------------------------------------------------------------*/
248 static void
ResImageTexture_Setup(ResTexture resTex)249 ResImageTexture_Setup(ResTexture resTex)
250 {
251 ResImageTexture resImgTex = ResDynamicCast<ResImageTexture>( resTex );
252
253 NW_ASSERT( resImgTex.IsValid() );
254
255 if ( resImgTex.GetTextureObject() != 0 )
256 {
257 return;
258 }
259
260 u32 texID = reinterpret_cast<u32>(resTex.ptr());
261 resImgTex.SetTextureObject( texID );
262
263 ResPixelBasedImage resImage = resImgTex.GetImage();
264
265 u32 loadFlag = resImgTex.GetLocationFlag();
266
267 SetTexImage2D( texID, resImage, loadFlag );
268 }
269
270 /*!--------------------------------------------------------------------------*
271 @brief シャドウテクスチャをセットアップします。
272
273 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
274 *---------------------------------------------------------------------------*/
275 static void
ResShadowTexture_Setup(ResTexture resTex)276 ResShadowTexture_Setup(ResTexture resTex)
277 {
278 ResShadowTexture resSdwTex = ResDynamicCast<ResShadowTexture>( resTex );
279
280 NW_ASSERT( resSdwTex.IsValid() );
281
282 if ( resSdwTex.GetTextureObject() != 0 )
283 {
284 return;
285 }
286
287 u32 texID = reinterpret_cast<u32>(resTex.ptr());
288 resSdwTex.SetTextureObject( texID );
289
290 ResPixelBasedImage resImage = resSdwTex.GetImage();
291
292 u32 loadFlag = resSdwTex.GetLocationFlag();
293
294 SetTexImage2D( texID, resImage, loadFlag );
295 }
296
297 /*!--------------------------------------------------------------------------*
298 @brief キューブテクスチャをセットアップします。
299
300 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
301 *---------------------------------------------------------------------------*/
302 static void
ResCubeTexture_Setup(ResTexture resTex)303 ResCubeTexture_Setup(ResTexture resTex)
304 {
305 ResCubeTexture resCubeTex = ResDynamicCast<ResCubeTexture>( resTex );
306
307 NW_ASSERT( resCubeTex.IsValid() );
308
309 if ( resCubeTex.GetTextureObject() != 0 )
310 {
311 return;
312 }
313
314 u32 texID = reinterpret_cast<u32>(resTex.ptr());
315 resCubeTex.SetTextureObject( texID );
316
317 u32 loadFlag = resCubeTex.GetLocationFlag();
318
319 // 各フェイスのテクスチャをセットアップする。
320 // 同じテクスチャが別のフェイスに張られている場合もあるので注意。
321 for ( int face = 0; face < ResCubeTexture::MAX_CUBE_FACE; ++face )
322 {
323 ResPixelBasedImage resImage = resCubeTex.GetImage( static_cast<ResCubeTexture::CubeFace>( face ) );
324
325 SetTexImage2D( texID, resImage, loadFlag );
326 }
327 }
328
329 /*!--------------------------------------------------------------------------*
330 @brief 参照テクスチャを有効にします。
331
332 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
333 *---------------------------------------------------------------------------*/
334 static void
ResReferenceTexture_Setup(ResTexture resTex)335 ResReferenceTexture_Setup(ResTexture resTex)
336 {
337 ResReferenceTexture resRefTex = ResStaticCast<ResReferenceTexture>( resTex );
338
339 NW_ASSERT( resRefTex.GetTargetTexture().IsValid() );
340
341 switch(resRefTex.GetTargetTexture().ref().typeInfo)
342 {
343 case ResImageTexture::TYPE_INFO:
344 {
345 ResImageTexture_Setup(resRefTex.GetTargetTexture());
346 break;
347 }
348 case ResCubeTexture::TYPE_INFO:
349 {
350 ResCubeTexture_Setup(resRefTex.GetTargetTexture());
351 break;
352 }
353 case ResReferenceTexture::TYPE_INFO:
354 {
355 ResReferenceTexture_Setup(resRefTex.GetTargetTexture());
356 break;
357 }
358 case ResProceduralTexture::TYPE_INFO:
359 {
360 ResProceduralTexture_Setup(resRefTex.GetTargetTexture());
361 break;
362 }
363 case ResShadowTexture::TYPE_INFO:
364 {
365 ResShadowTexture_Setup(resRefTex.GetTargetTexture());
366 break;
367 }
368 default:
369 {
370 NW_FATAL_ERROR("Unsupported texture type.\n");
371 }
372 }
373 }
374
375 /*!--------------------------------------------------------------------------*
376 @brief プロシージャルテクスチャをセットアップします。
377
378 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
379 *---------------------------------------------------------------------------*/
380 static void
ResProceduralTexture_Setup(ResTexture resTex)381 ResProceduralTexture_Setup(ResTexture resTex)
382 {
383 NW_UNUSED_VARIABLE( resTex )
384 }
385
386 /*!--------------------------------------------------------------------------*
387 @brief イメージテクスチャの終了処理をおこないます。
388
389 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
390 *---------------------------------------------------------------------------*/
391 static void
ResImageTexture_Cleanup(ResTexture resTex)392 ResImageTexture_Cleanup(ResTexture resTex)
393 {
394 ResImageTexture resImgTex = ResDynamicCast<ResImageTexture>( resTex );
395 NW_ASSERT( resImgTex.IsValid() );
396
397 GLuint texID = resImgTex.GetTextureObject();
398 if ( texID == 0 )
399 {
400 return;
401 }
402
403 ResPixelBasedImage resImage = resImgTex.GetImage();
404 DeleteImage2D( texID, resImage );
405 resImgTex.SetTextureObject( 0 );
406 }
407
408 /*!--------------------------------------------------------------------------*
409 @brief シャドウテクスチャの終了処理をおこないます。
410
411 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
412 *---------------------------------------------------------------------------*/
413 static void
ResShadowTexture_Cleanup(ResTexture resTex)414 ResShadowTexture_Cleanup(ResTexture resTex)
415 {
416 ResShadowTexture resSdwTex = ResDynamicCast<ResShadowTexture>( resTex );
417 NW_ASSERT( resSdwTex.IsValid() );
418
419 GLuint texID = resSdwTex.GetTextureObject();
420 if ( texID == 0 )
421 {
422 return;
423 }
424
425 ResPixelBasedImage resImage = resSdwTex.GetImage();
426 DeleteImage2D( texID, resImage );
427 resSdwTex.SetTextureObject( 0 );
428 }
429
430 /*!--------------------------------------------------------------------------*
431 @brief イメージテクスチャの終了処理をおこないます。
432
433 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
434 *---------------------------------------------------------------------------*/
435 static void
ResCubeTexture_Cleanup(ResTexture resTex)436 ResCubeTexture_Cleanup(ResTexture resTex)
437 {
438 ResCubeTexture resCubeTex = ResDynamicCast<ResCubeTexture>( resTex );
439 NW_ASSERT( resCubeTex.IsValid() );
440
441 GLuint texID = resCubeTex.GetTextureObject();
442 if ( texID == 0 )
443 {
444 return;
445 }
446
447 for ( int face = 0; face < ResCubeTexture::MAX_CUBE_FACE; ++face )
448 {
449 ResPixelBasedImage resImage = resCubeTex.GetImage( static_cast<ResCubeTexture::CubeFace>( face ) );
450 DeleteImage2D( texID, resImage );
451 }
452
453 resCubeTex.SetTextureObject( 0 );
454 }
455
456 /*!--------------------------------------------------------------------------*
457 @brief 参照テクスチャの終了処理をおこないます。
458
459 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
460 *---------------------------------------------------------------------------*/
461 static void
ResReferenceTexture_Cleanup(ResTexture resTex)462 ResReferenceTexture_Cleanup(ResTexture resTex)
463 {
464 ResReferenceTexture resRefTex = ResStaticCast<ResReferenceTexture>( resTex );
465
466 resRefTex.ref().toTargetTexture.set_ptr(NULL);
467 }
468
469 /*!--------------------------------------------------------------------------*
470 @brief プロシージャルテクスチャの終了処理をおこないます。
471
472 @param[in] resTex 対象となるテクスチャリソースのインスタンスです。
473 *---------------------------------------------------------------------------*/
474 static void
ResProceduralTexture_Cleanup(ResTexture resTex)475 ResProceduralTexture_Cleanup(ResTexture resTex)
476 {
477 ResProceduralTexture resProcTex = ResDynamicCast<ResProceduralTexture>( resTex );
478 NW_ASSERT( resProcTex.IsValid() );
479
480 ResProceduralNoise noise = resProcTex.GetNoise();
481 ut::SafeCleanup(noise.GetNoiseTable());
482
483 ResProceduralClampShift clamp = resProcTex.GetClampShift();
484 ResProceduralMapping mapping = resProcTex.GetMapping();
485 ut::SafeCleanup(mapping.GetMappingTable());
486 ut::SafeCleanup(mapping.GetAlphaMappingTable());
487
488 ResProceduralColor color = resProcTex.GetColor();
489 ut::SafeCleanup(color.GetColorTables(0));
490 ut::SafeCleanup(color.GetColorTables(1));
491 ut::SafeCleanup(color.GetColorTables(2));
492 ut::SafeCleanup(color.GetColorTables(3));
493 }
494
495 //-------------------------------------------------------------------------
496 Result
Setup(os::IAllocator * allocator,ResGraphicsFile graphicsFile)497 ResTexture::Setup(os::IAllocator* allocator, ResGraphicsFile graphicsFile)
498 {
499 NW_UNUSED_VARIABLE(allocator);
500 NW_UNUSED_VARIABLE(graphicsFile);
501
502 NW_ASSERT( internal::ResCheckRevision( *this ) );
503
504 Result result = RESOURCE_RESULT_OK;
505 switch ( this->ref().typeInfo )
506 {
507 case ResImageTexture::TYPE_INFO:
508 {
509 s_TextureSetupTable[0]( *this );
510 }
511 break;
512 case ResCubeTexture::TYPE_INFO:
513 {
514 s_TextureSetupTable[1]( *this );
515 }
516 break;
517 case ResReferenceTexture::TYPE_INFO:
518 {
519 s_TextureSetupTable[2]( *this );
520 }
521 break;
522 case ResProceduralTexture::TYPE_INFO:
523 {
524 s_TextureSetupTable[3]( *this );
525 }
526 break;
527 case ResShadowTexture::TYPE_INFO:
528 {
529 s_TextureSetupTable[4]( *this );
530 }
531 break;
532 default:
533 {
534 NW_FATAL_ERROR("Unsupported texture type.\n");
535 }
536 }
537
538 return result;
539 }
540
541 //---------------------------------------------------------------------------
542 Result
Setup(os::IAllocator * allocator)543 ResTexture::Setup(os::IAllocator* allocator)
544 {
545 return this->Setup(allocator, ResGraphicsFile(NULL));
546 }
547
548 /*---------------------------------------------------------------------------*
549 @brief テクスチャリソースの後始末をします。
550 *---------------------------------------------------------------------------*/
551 void
Cleanup()552 ResTexture::Cleanup()
553 {
554 switch ( this->ref().typeInfo )
555 {
556 case ResImageTexture::TYPE_INFO:
557 {
558 s_TextureCleanupTable[0]( *this );
559 }
560 break;
561 case ResCubeTexture::TYPE_INFO:
562 {
563 s_TextureCleanupTable[1]( *this );
564 }
565 break;
566 case ResReferenceTexture::TYPE_INFO:
567 {
568 s_TextureCleanupTable[2]( *this );
569 }
570 break;
571 case ResProceduralTexture::TYPE_INFO:
572 {
573 s_TextureCleanupTable[3]( *this );
574 }
575 break;
576 case ResShadowTexture::TYPE_INFO:
577 {
578 s_TextureCleanupTable[4]( *this );
579 }
580 break;
581 default:
582 {
583 NW_FATAL_ERROR("Unsupported texture type.\n");
584 }
585 }
586 }
587
588 //----------------------------------------
589 ResImageTexture
Create(os::IAllocator * allocator)590 ResImageTexture::DynamicBuilder::Create(
591 os::IAllocator* allocator
592 )
593 {
594 NW_NULL_ASSERT(allocator);
595
596 // 2のべき乗のチェック
597 NW_ASSERT( (m_Description.height & (m_Description.height - 1)) == 0 );
598 NW_ASSERT( (m_Description.width & (m_Description.width - 1)) == 0 );
599
600 // テクスチャサイズのチェック
601 const s32 TEXTURE_SIZE_MAX = 1024;
602 const s32 TEXTURE_SIZE_MIN =
603 ( m_Description.formatHW == ResPixelBasedTexture::FORMAT_HW_ETC1 ? 16 : 8 );
604
605 NW_MINMAX_ASSERT( m_Description.height, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX );
606 NW_MINMAX_ASSERT( m_Description.width, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX );
607
608 // ミップマップサイズは 1 以上を指定する必要があります。
609 NW_ASSERT(m_Description.mipmapSize > 0);
610
611 // ResImageTextureData のメモリ確保
612 void* textureDataMemory = allocator->Alloc(sizeof(ResImageTextureData));
613 NW_NULL_ASSERT(textureDataMemory);
614 ResImageTextureData* textureData = new(textureDataMemory) ResImageTextureData();
615
616 //--------------------------------
617 // ResSceneObjectData のメンバ初期化
618 textureData->typeInfo = ResImageTexture::TYPE_INFO;
619 textureData->m_Header.revision = ResImageTexture::BINARY_REVISION;
620 textureData->m_Header.signature = ResImageTexture::SIGNATURE;
621 textureData->toName.set_ptr(NULL);
622 textureData->m_UserDataDicCount = 0;
623 textureData->toUserDataDic.set_ptr(NULL);
624
625 //--------------------------------
626 // ResPixelBasedTextureData のメンバ初期化
627 textureData->m_Height = m_Description.height;
628 textureData->m_Width = m_Description.width;
629 textureData->m_Format = GL_FORMAT_TABLE[m_Description.formatHW];
630 textureData->m_FormatType = GL_FORMAT_TYPE_TABLE[m_Description.formatHW];
631 textureData->m_MipmapSize = m_Description.mipmapSize;
632 textureData->m_TextureObject = 0;
633 textureData->m_LocationFlag = m_Description.locationFlag;
634 textureData->m_FormatHW = m_Description.formatHW;
635
636 // ResPixelBasedImageData のメモリ確保
637 void* imageDataMemory = allocator->Alloc(sizeof(ResPixelBasedImageData));
638 NW_NULL_ASSERT(imageDataMemory);
639 ResPixelBasedImageData* imageData = new(imageDataMemory) ResPixelBasedImageData();
640
641 imageData->m_DynamicAllocator = allocator;
642 imageData->m_Height = m_Description.height;
643 imageData->m_Width = m_Description.width;
644 imageData->m_LocationAddress = m_Description.locationAddress;
645
646 f32 bytesizePerPixel = BYTESIZE_PER_PIXEL_TABLE[m_Description.formatHW];
647 imageData->m_BitsPerPixel = static_cast<u32>(bytesizePerPixel * 8);
648
649 u32 byteCount = 0;
650 s32 h = m_Description.height;
651 s32 w = m_Description.width;
652
653 // テクスチャのために確保するメモリサイズを計算します。
654 // ミップマップを使用する場合、ミップマップ数に応じたメモリ確保量を計算します。
655 for (s32 mipmapSize = m_Description.mipmapSize; mipmapSize > 0; --mipmapSize)
656 {
657 byteCount += static_cast<u32>(bytesizePerPixel * h * w);
658
659 if (h == TEXTURE_SIZE_MIN && w == TEXTURE_SIZE_MIN)
660 {
661 textureData->m_MipmapSize = m_Description.mipmapSize - mipmapSize + 1;
662 break;
663 }
664
665 if (h > TEXTURE_SIZE_MIN)
666 {
667 h /= 2;
668 }
669 if (w > TEXTURE_SIZE_MIN)
670 {
671 w /= 2;
672 }
673 }
674
675 // ピクセルデータ のメモリ確保
676 // isDynamicAllocation が指定されていた場合はメモリ確保を行う
677 if (m_Description.isDynamicAllocation)
678 {
679 const u8 ALIGNMENT = 128;
680 NW_ASSERT(byteCount != 0);
681 void* bufferMemory = allocator->Alloc(byteCount, ALIGNMENT);
682 NW_NULL_ASSERT(bufferMemory);
683 u8* buffer = static_cast<u8*>(bufferMemory);
684 if (m_Description.executingMemoryFill)
685 {
686 std::fill_n(NW_CHECKED_ARRAY_ITERATOR(buffer, byteCount), byteCount, 0);
687 }
688
689 imageData->m_ImageDataTableCount = byteCount;
690 imageData->toImageDataTable.set_ptr(buffer);
691 }
692 else
693 {
694 imageData->m_ImageDataTableCount = 0;
695 imageData->toImageDataTable.set_ptr(NULL);
696 }
697
698 //--------------------------------
699 // ResImageTextureData のメンバ初期化
700 textureData->toImage.set_ptr(imageData);
701
702 return ResImageTexture(textureData);
703 }
704
705 //----------------------------------------
706 ResCubeTexture
Create(os::IAllocator * allocator)707 ResCubeTexture::DynamicBuilder::Create(
708 os::IAllocator* allocator
709 )
710 {
711 NW_NULL_ASSERT(allocator);
712
713 // 2のべき乗のチェック
714 NW_ASSERT( (m_Description.width & (m_Description.width - 1)) == 0 );
715
716 // テクスチャサイズのチェック
717 const s32 TEXTURE_SIZE_MAX = 1024;
718 const s32 TEXTURE_SIZE_MIN =
719 ( m_Description.formatHW == ResPixelBasedTexture::FORMAT_HW_ETC1 ? 16 : 8 );
720
721 // キューブテクスチャーでは FORMAT_HW_RGB8 は使用できない
722 NW_ASSERT(m_Description.formatHW != ResPixelBasedTexture::FORMAT_HW_RGB8);
723
724 NW_MINMAX_ASSERT( m_Description.width, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX );
725
726 // ミップマップサイズは 1 以上を指定する必要があります。
727 NW_ASSERT(m_Description.mipmapSize > 0);
728
729 // ResImageTextureData のメモリ確保
730 void* textureDataMemory = allocator->Alloc(sizeof(ResCubeTextureData));
731 NW_NULL_ASSERT(textureDataMemory);
732 ResCubeTextureData* textureData = new(textureDataMemory) ResCubeTextureData();
733
734 //--------------------------------
735 // ResSceneObjectData のメンバ初期化
736 textureData->typeInfo = ResCubeTexture::TYPE_INFO;
737 textureData->m_Header.revision = ResCubeTexture::BINARY_REVISION;
738 textureData->m_Header.signature = ResCubeTexture::SIGNATURE;
739 textureData->toName.set_ptr(NULL);
740 textureData->m_UserDataDicCount = 0;
741 textureData->toUserDataDic.set_ptr(NULL);
742
743 //--------------------------------
744 // ResPixelBasedTextureData のメンバ初期化
745 textureData->m_Height = m_Description.width;
746 textureData->m_Width = m_Description.width;
747 textureData->m_Format = GL_FORMAT_TABLE[m_Description.formatHW];
748 textureData->m_FormatType = GL_FORMAT_TYPE_TABLE[m_Description.formatHW];
749 textureData->m_MipmapSize = m_Description.mipmapSize;
750 textureData->m_TextureObject = 0;
751 textureData->m_LocationFlag = m_Description.locationFlag;
752 textureData->m_FormatHW = m_Description.formatHW;
753
754 // ResPixelBasedImageData のメモリ確保
755 void* imageDataMemory = allocator->Alloc(sizeof(ResPixelBasedImageData) * MAX_CUBE_FACE);
756 NW_NULL_ASSERT(imageDataMemory);
757 ResPixelBasedImageData* imageData = new(imageDataMemory) ResPixelBasedImageData[MAX_CUBE_FACE];
758
759 f32 bytesizePerPixel = BYTESIZE_PER_PIXEL_TABLE[m_Description.formatHW];
760
761 u32 byteCount = 0;
762 s32 h = m_Description.width;
763 s32 w = m_Description.width;
764
765 // テクスチャのために確保するメモリサイズを計算します。
766 // ミップマップを使用する場合、ミップマップ数に応じたメモリ確保量を計算します。
767 for (s32 mipmapSize = m_Description.mipmapSize; mipmapSize > 0; --mipmapSize)
768 {
769 byteCount += static_cast<u32>(bytesizePerPixel * h * w);
770
771 if (h == TEXTURE_SIZE_MIN && w == TEXTURE_SIZE_MIN)
772 {
773 textureData->m_MipmapSize = m_Description.mipmapSize - mipmapSize + 1;
774 break;
775 }
776
777 if (h > TEXTURE_SIZE_MIN)
778 {
779 h /= 2;
780 }
781 if (w > TEXTURE_SIZE_MIN)
782 {
783 w /= 2;
784 }
785 }
786
787 uptr bufferMemory = 0;
788
789 // ピクセルデータ のメモリ確保
790 // isDynamicAllocation が指定されていた場合はメモリ確保を行う
791 if (m_Description.isDynamicAllocation)
792 {
793 u32 totalByteCount = byteCount * MAX_CUBE_FACE;
794 const u8 ALIGNMENT = 128;
795 NW_ASSERT(totalByteCount != 0);
796 bufferMemory = reinterpret_cast<uptr>(allocator->Alloc(totalByteCount, ALIGNMENT));
797 NW_NULL_ASSERT(bufferMemory);
798 u8* buffer = reinterpret_cast<u8*>(bufferMemory);
799 if (m_Description.executingMemoryFill)
800 {
801 std::fill_n(NW_CHECKED_ARRAY_ITERATOR(buffer, totalByteCount), totalByteCount, 0);
802 }
803 }
804
805 for (int i = 0 ; i < MAX_CUBE_FACE ; ++i)
806 {
807 // 安全のため ImageDataTable を解放できる 1 枚目のみ DynamicAllocator を設定する。
808 imageData[i].m_DynamicAllocator = (i == 0) ? allocator : NULL;
809 imageData[i].m_Height = m_Description.width;
810 imageData[i].m_Width = m_Description.width;
811 imageData[i].m_LocationAddress = m_Description.locationAddress[i];
812
813 imageData[i].m_BitsPerPixel = static_cast<u32>(bytesizePerPixel * 8);
814
815 if (m_Description.isDynamicAllocation)
816 {
817 imageData[i].m_ImageDataTableCount = byteCount;
818 imageData[i].toImageDataTable.set_ptr(reinterpret_cast<void*>(bufferMemory + byteCount * i));
819 }
820 else
821 {
822 imageData[i].m_ImageDataTableCount = 0;
823 imageData[i].toImageDataTable.set_ptr(NULL);
824 }
825
826 //--------------------------------
827 // ResImageTextureData のメンバ初期化
828 textureData->toImagesTables[i].set_ptr(&imageData[i]);
829 }
830
831 return ResCubeTexture(textureData);
832 }
833
834 //----------------------------------------
835 ResShadowTexture
Create(os::IAllocator * allocator)836 ResShadowTexture::DynamicBuilder::Create(
837 os::IAllocator* allocator
838 )
839 {
840 NW_NULL_ASSERT(allocator);
841
842 // 2のべき乗のチェック
843 NW_ASSERT( (m_Description.height & (m_Description.height - 1)) == 0 );
844 NW_ASSERT( (m_Description.width & (m_Description.width - 1)) == 0 );
845
846 // テクスチャサイズのチェック
847 const s32 TEXTURE_SIZE_MAX = 1024;
848 const s32 TEXTURE_SIZE_MIN = 8;
849 NW_MINMAX_ASSERT( m_Description.height, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX );
850 NW_MINMAX_ASSERT( m_Description.width, TEXTURE_SIZE_MIN, TEXTURE_SIZE_MAX );
851
852 // ResShadowTextureData のメモリ確保
853 void* textureDataMemory = allocator->Alloc(sizeof(ResShadowTextureData));
854 NW_NULL_ASSERT(textureDataMemory);
855 ResShadowTextureData* textureData = new(textureDataMemory) ResShadowTextureData();
856
857 //--------------------------------
858 // ResSceneObjectData のメンバ初期化
859 textureData->typeInfo = ResShadowTexture::TYPE_INFO;
860 textureData->m_Header.revision = ResShadowTexture::BINARY_REVISION;
861 textureData->m_Header.signature = ResShadowTexture::SIGNATURE;
862 textureData->toName.set_ptr(NULL);
863 textureData->m_UserDataDicCount = 0;
864 textureData->toUserDataDic.set_ptr(NULL);
865
866 //--------------------------------
867 // ResPixelBasedTextureData のメンバ初期化
868 textureData->m_Height = m_Description.height;
869 textureData->m_Width = m_Description.width;
870 textureData->m_Format = GL_SHADOW_DMP;
871 textureData->m_FormatType = GL_UNSIGNED_INT;
872 textureData->m_MipmapSize = 0;
873 textureData->m_TextureObject = 0;
874 textureData->m_LocationFlag = m_Description.locationFlag;
875 textureData->m_FormatHW = ResPixelBasedTexture::FORMAT_HW_RGBA8;
876
877 // ResPixelBasedImageData のメモリ確保
878 void* imageDataMemory = allocator->Alloc(sizeof(ResPixelBasedImageData));
879 NW_NULL_ASSERT(imageDataMemory);
880 ResPixelBasedImageData* imageData = new(imageDataMemory) ResPixelBasedImageData();
881
882 imageData->m_DynamicAllocator = allocator;
883 imageData->m_Height = m_Description.height;
884 imageData->m_Width = m_Description.width;
885 imageData->m_LocationAddress = m_Description.locationAddress;
886
887 const f32 BYTESIZE_4 = 4.0f;
888 f32 bytesizePerPixel = BYTESIZE_4;
889
890 imageData->m_BitsPerPixel = static_cast<u32>(bytesizePerPixel * 8);
891
892 u32 byteCount = 0;
893 s32 h = m_Description.height;
894 s32 w = m_Description.width;
895
896 // テクスチャのために確保するメモリサイズを計算します。
897 // ミップマップを使用する場合、ミップマップ数に応じたメモリ確保量を計算します。
898 byteCount += static_cast<u32>(bytesizePerPixel * h * w);
899
900 // ピクセルデータ のメモリ確保
901 // isDynamicAllocation が指定されていた場合はメモリ確保を行う
902 if (m_Description.isDynamicAllocation)
903 {
904 const u8 ALIGNMENT = 128;
905 NW_ASSERT(byteCount);
906 void* bufferMemory = allocator->Alloc(byteCount, ALIGNMENT);
907 NW_NULL_ASSERT(bufferMemory);
908 u8* buffer = static_cast<u8*>(bufferMemory);
909 if (m_Description.executingMemoryFill)
910 {
911 std::fill_n(NW_CHECKED_ARRAY_ITERATOR(buffer, byteCount), byteCount, 0);
912 }
913
914 imageData->m_ImageDataTableCount = byteCount;
915 imageData->toImageDataTable.set_ptr(buffer);
916 }
917 else
918 {
919 imageData->m_ImageDataTableCount = 0;
920 imageData->toImageDataTable.set_ptr(NULL);
921 }
922
923 //--------------------------------
924 // ResImageTextureData のメンバ初期化
925 textureData->toImage.set_ptr(imageData);
926
927 //--------------------------------
928 // ResShadowTextureData のメンバ初期化
929 textureData->m_IsPerspectiveShadow = m_Description.isPerspectiveShadow;
930 textureData->m_ShadowZBias = m_Description.shadowZBias;
931 textureData->m_ShadowZScale = m_Description.shadowZScale;
932
933 return ResShadowTexture(textureData);
934 }
935
936 //-----------------------------------------
937 void
DynamicDestroy()938 ResImageTexture::DynamicDestroy()
939 {
940 os::IAllocator* allocator = this->GetImage().ref().m_DynamicAllocator;
941
942 NW_NULL_ASSERT( allocator );
943
944 if (this->IsValid())
945 {
946 ResPixelBasedImage resPixelBasedImage = this->GetImage();
947
948 if (resPixelBasedImage.IsValid())
949 {
950 // ピクセルデータ のメモリ開放
951 if (resPixelBasedImage.ptr()->toImageDataTable.to_ptr() != NULL)
952 {
953 allocator->Free(resPixelBasedImage.ptr()->toImageDataTable.to_ptr());
954 }
955
956 // ResPixelBasedImageData のメモリ開放
957 allocator->Free(resPixelBasedImage.ptr());
958 }
959
960 // ResImageTextureData のメモリ開放
961 allocator->Free(this->ptr());
962 this->invalidate();
963 }
964 }
965
966 //-----------------------------------------
967 void
DynamicDestroy()968 ResCubeTexture::DynamicDestroy()
969 {
970 ResPixelBasedImage firstFace = this->GetImage(static_cast<CubeFace>(0));
971
972 os::IAllocator* allocator = firstFace.ref().m_DynamicAllocator;
973
974 NW_NULL_ASSERT( allocator );
975
976 if (this->IsValid())
977 {
978 // メモリは 6 面分まとめて確保しているので、
979 // 1 面目のアドレスで解放すれば 6 面分すべて解放される。
980 if (firstFace.IsValid())
981 {
982 // ピクセルデータ のメモリ開放
983 if (firstFace.ptr()->toImageDataTable.to_ptr() != NULL)
984 {
985 allocator->Free(firstFace.ptr()->toImageDataTable.to_ptr());
986 }
987
988 // ResPixelBasedImageData のメモリ開放
989 allocator->Free(firstFace.ptr());
990 }
991
992 // ResImageTextureData のメモリ開放
993 allocator->Free(this->ptr());
994 this->invalidate();
995 }
996 }
997
998 //-----------------------------------------
999 void
DynamicDestroy()1000 ResShadowTexture::DynamicDestroy()
1001 {
1002 os::IAllocator* allocator = this->GetImage().ref().m_DynamicAllocator;
1003
1004 NW_NULL_ASSERT( allocator );
1005
1006 ResPixelBasedImage resPixelBasedImage = this->GetImage();
1007
1008 if(resPixelBasedImage.IsValid())
1009 {
1010 // ピクセルデータ のメモリ開放
1011 if (resPixelBasedImage.ptr()->toImageDataTable.to_ptr() != NULL)
1012 {
1013 allocator->Free(resPixelBasedImage.ptr()->toImageDataTable.to_ptr());
1014 }
1015
1016 // ResPixelBasedImageData のメモリ開放
1017 allocator->Free(resPixelBasedImage.ptr());
1018 }
1019
1020 // ResImageTextureData のメモリ開放
1021 allocator->Free(this->ptr());
1022 this->invalidate();
1023 }
1024
1025 //---------------------------------------------------------------------------
1026 bool
CheckMemoryLocation() const1027 ResPixelBasedImage::CheckMemoryLocation() const
1028 {
1029 if (! nw::os::IsDeviceMemory(this->GetImageData()))
1030 {
1031 return false;
1032 }
1033
1034 u32 startAddress = reinterpret_cast<u32>( this->GetImageData() );
1035 u32 endAddress = reinterpret_cast<u32>( this->GetImageData() ) + static_cast<u32>(this->GetImageDataCount()) - 1;
1036
1037 // 128 バイトアライメントチェック。
1038 if ((startAddress & 0x7F) != 0)
1039 {
1040 return false;
1041 }
1042
1043 // 32MB 境界チェックは ハードウェア的に問題が無いことが分かったので削除。
1044
1045 return true;
1046 }
1047
1048
1049
1050 } /* namespace res */
1051 } /* namespace gfx */
1052 } /* namespace nw */
1053
1054