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