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