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