1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ResTextureMapper.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: 18139 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "../precompiled.h"
17 
18 #include <nw/gfx/res/gfx_ResUtil.h>
19 #include <nw/gfx/res/gfx_ResTextureMapper.h>
20 #include <nw/gfx/res/gfx_ResGraphicsFile.h>
21 #include <nw/gfx/gfx_CommandUtil.h>
22 
23 namespace nw {
24 namespace gfx {
25 namespace res {
26 
27 typedef Result (*SetupFunc)(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile);
28 typedef void (*CleanupFunc)(ResTextureMapper resTextureMapper);
29 typedef ResTextureMapper (*CloneDynamicFunc)(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
30 typedef void (*DestroyDynamicFunc)(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
31 
32 static Result ResPixelBasedTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile);
33 static Result ResProceduralTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile);
34 static void ResPixelBasedTextureMapper_Cleanup(ResTextureMapper resTextureMapper);
35 static void ResProceduralTextureMapper_Cleanup(ResTextureMapper resTextureMapper);
36 static ResTextureMapper ResPixelBasedTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
37 static ResTextureMapper ResProceduralTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
38 static void ResPixelBasedTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
39 static void ResProceduralTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
40 
41 static ResTexture ReferResTexture(os::IAllocator* allocator, ResTexture resTexture);
42 
43 static Result SetupTexture(
44     os::IAllocator* allocator,
45     ResTexture resTexture,
46     ResGraphicsFile graphicsFile
47 );
48 
49 static void SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResImageTexture texture);
50 static void SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResCubeTexture texture);
51 static void SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResShadowTexture texture);
52 
53 static SetupFunc s_TextureMapperSetupTable[] =
54 {
55     ResPixelBasedTextureMapper_Setup,
56     ResProceduralTextureMapper_Setup
57 };
58 
59 static CleanupFunc s_TextureMapperCleanupTable[] =
60 {
61     ResPixelBasedTextureMapper_Cleanup,
62     ResProceduralTextureMapper_Cleanup
63 };
64 
65 static CloneDynamicFunc s_TextureMapperCloneDynamicTable[] =
66 {
67     ResPixelBasedTextureMapper_CloneDynamic,
68     ResProceduralTextureMapper_CloneDynamic
69 };
70 
71 static DestroyDynamicFunc s_TextureMapperDestroyDynamicTable[] =
72 {
73     ResPixelBasedTextureMapper_DestroyDynamic,
74     ResProceduralTextureMapper_DestroyDynamic
75 };
76 
77 //----------------------------------------
78 ::std::pair<u32, u32*>
GetOwnerCommand() const79 ResTextureSampler::GetOwnerCommand() const
80 {
81     ResPixelBasedTextureMapper textureMapper =
82         ResStaticCast<ResPixelBasedTextureMapper>(ResTextureMapper(this->GetOwnerData()));
83 
84     return ::std::make_pair(textureMapper.GetCommandSizeToSend(), textureMapper.GetCommandCache());
85 }
86 
87 /*!--------------------------------------------------------------------------*
88   @brief        ピクセルベーステクスチャマッパーをセットアップします。
89 
90   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
91   @param[in]    allocator        アロケータです。
92   @param[in]    graphicsFile     グラフィックスファイルです。
93  *---------------------------------------------------------------------------*/
94 static Result
ResPixelBasedTextureMapper_Setup(ResTextureMapper resTextureMapper,os::IAllocator * allocator,ResGraphicsFile graphicsFile)95 ResPixelBasedTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile)
96 {
97     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
98         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
99     ResTexture resTexture = resTextureMapper.GetTexture();
100 
101     Result result = SetupTexture(allocator, resTexture, graphicsFile);
102 
103     if (result.IsFailure())
104     {
105         return result;
106     }
107 
108     ResTexture resImageTexture = resTexture.Dereference();
109 
110     switch ( resImageTexture.ref().typeInfo )
111     {
112     case ResImageTexture::TYPE_INFO:
113         SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResImageTexture>(resImageTexture));
114         break;
115     case ResCubeTexture::TYPE_INFO:
116         SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResCubeTexture>(resImageTexture));
117         break;
118     case ResShadowTexture::TYPE_INFO:
119         SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResShadowTexture>(resImageTexture));
120         break;
121     default:
122         NW_FATAL_ERROR("Unsupported texture type.\n");
123     }
124 
125     return result;
126 }
127 
128 /*!--------------------------------------------------------------------------*
129   @brief        プロシージャルテクスチャマッパーをセットアップします。
130 
131   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
132   @param[in]    allocator        アロケータです。
133   @param[in]    graphicsFile     グラフィックスファイルです。
134  *---------------------------------------------------------------------------*/
135 static Result
ResProceduralTextureMapper_Setup(ResTextureMapper resTextureMapper,os::IAllocator * allocator,ResGraphicsFile graphicsFile)136 ResProceduralTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile)
137 {
138     return SetupTexture(allocator, resTextureMapper.GetTexture(), graphicsFile);
139 }
140 
141 /*!--------------------------------------------------------------------------*
142   @brief        ピクセルベーステクスチャマッパーの後始末をします。
143 
144   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
145  *---------------------------------------------------------------------------*/
146 static void
ResPixelBasedTextureMapper_Cleanup(ResTextureMapper resTextureMapper)147 ResPixelBasedTextureMapper_Cleanup(ResTextureMapper resTextureMapper)
148 {
149     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
150         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
151 
152     resPixelBasedTextureMapper.ResetCommand();
153 
154     ResTexture resTexture = resTextureMapper.GetTexture();
155     ut::SafeCleanup(resTexture);
156 }
157 
158 /*!--------------------------------------------------------------------------*
159   @brief        プロシージャルテクスチャマッパーの後始末をします。
160 
161   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
162  *---------------------------------------------------------------------------*/
163 static void
ResProceduralTextureMapper_Cleanup(ResTextureMapper resTextureMapper)164 ResProceduralTextureMapper_Cleanup(ResTextureMapper resTextureMapper)
165 {
166     ResTexture resTexture = resTextureMapper.GetTexture();
167     ut::SafeCleanup(resTexture);
168 }
169 
170 /*!--------------------------------------------------------------------------*
171   @brief        ピクセルベーステクスチャマッパーをクローンします。
172 
173   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
174   @param[in]    allocator  アロケータです。
175  *---------------------------------------------------------------------------*/
176 static ResTextureMapper
ResPixelBasedTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)177 ResPixelBasedTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
178 {
179     // この関数で確保されるメモリのサイズに変化があった場合は
180     // ResTextureMapper::GetRequiredMemorySizeForClone を修正してください。
181     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
182         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
183 
184     void* mapperMemory = allocator->Alloc(sizeof(ResPixelBasedTextureMapperData));
185     if (mapperMemory == NULL)
186     {
187         return ResTextureMapper(NULL);
188     }
189 
190     ResPixelBasedTextureMapperData* textureMapper =
191         new(mapperMemory) ResPixelBasedTextureMapperData(resPixelBasedTextureMapper.ref());
192 
193     ResPixelBasedTextureMapper cloneTextureMapper = ResPixelBasedTextureMapper(textureMapper);
194 
195     ResTexture resTexture = resPixelBasedTextureMapper.GetTexture();
196     if (resTexture.IsValid())
197     {
198         // リファレンステクスチャを生成してテクスチャを参照します。
199         ResTexture referenceTexture = ReferResTexture(allocator, resTexture);
200         if (referenceTexture.IsValid())
201         {
202             textureMapper->toTexture.set_ptr(referenceTexture.ptr());
203         }
204         else
205         {
206             ResPixelBasedTextureMapper_DestroyDynamic(cloneTextureMapper, allocator);
207             return ResTextureMapper(NULL);
208         }
209     }
210 
211     ResStandardTextureSampler resStandardTextureSampler =
212         ResDynamicCast<ResStandardTextureSampler>(resPixelBasedTextureMapper.GetSampler());
213 
214     if (resStandardTextureSampler.IsValid())
215     {
216         void* samplerMemory = allocator->Alloc(sizeof(ResStandardTextureSamplerData));
217         if (samplerMemory == NULL)
218         {
219             ResPixelBasedTextureMapper_DestroyDynamic(cloneTextureMapper, allocator);
220             return ResTextureMapper(NULL);
221         }
222 
223         ResStandardTextureSamplerData* textureSampler =
224             new(samplerMemory) ResStandardTextureSamplerData(resStandardTextureSampler.ref());
225 
226         textureMapper->toSampler.set_ptr(textureSampler);
227         textureSampler->toOwner.set_ptr(textureMapper);
228     }
229 
230     return cloneTextureMapper;
231 }
232 
233 /*!--------------------------------------------------------------------------*
234   @brief        プロシージャルテクスチャマッパーをクローンします。
235 
236   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
237   @param[in]    allocator  アロケータです。
238  *---------------------------------------------------------------------------*/
239 static ResTextureMapper
ResProceduralTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)240 ResProceduralTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
241 {
242     // この関数で確保されるメモリのサイズに変化があった場合は
243     // ResTextureMapper::GetRequiredMemorySizeForClone を修正してください。
244     ResProceduralTextureMapper resProceduralTextureMapper =
245         ResStaticCast<ResProceduralTextureMapper>(resTextureMapper);
246 
247     void* mapperMemory = allocator->Alloc(sizeof(ResProceduralTextureMapperData));
248     if (mapperMemory == NULL)
249     {
250         return ResTextureMapper(NULL);
251     }
252 
253     ResProceduralTextureMapperData* textureMapper =
254         new(mapperMemory) ResProceduralTextureMapperData(resProceduralTextureMapper.ref());
255 
256     ResProceduralTextureMapper cloneTextureMapper = ResProceduralTextureMapper(textureMapper);
257 
258     ResTexture resTexture = resProceduralTextureMapper.GetTexture();
259     if (resTexture.IsValid())
260     {
261         // リファレンステクスチャを生成してテクスチャを参照します。
262         ResTexture referenceTexture = ReferResTexture(allocator, resTexture);
263         if (referenceTexture.IsValid())
264         {
265             textureMapper->toTexture.set_ptr(referenceTexture.ptr());
266         }
267         else
268         {
269             ResProceduralTextureMapper_DestroyDynamic(cloneTextureMapper, allocator);
270             return ResTextureMapper(NULL);
271         }
272     }
273 
274     return cloneTextureMapper;
275 }
276 
277 /*!--------------------------------------------------------------------------*
278   @brief        ピクセルベーステクスチャマッパーを削除します。
279 
280   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
281   @param[in]    allocator        アロケータです。
282  *---------------------------------------------------------------------------*/
283 static void
ResPixelBasedTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)284 ResPixelBasedTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
285 {
286     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
287         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
288 
289     if (resPixelBasedTextureMapper.GetSampler().IsValid())
290     {
291         allocator->Free(resPixelBasedTextureMapper.ref().toSampler.to_ptr());
292     }
293 
294     if (resPixelBasedTextureMapper.GetTexture().IsValid())
295     {
296         allocator->Free(resPixelBasedTextureMapper.ref().toTexture.to_ptr());
297     }
298 
299     allocator->Free(resPixelBasedTextureMapper.ptr());
300 }
301 
302 /*!--------------------------------------------------------------------------*
303   @brief        プロシージャルテクスチャマッパーを削除します。
304 
305   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
306   @param[in]    allocator        アロケータです。
307  *---------------------------------------------------------------------------*/
308 static void
ResProceduralTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)309 ResProceduralTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
310 {
311     ResProceduralTextureMapper resProceduralTextureMapper =
312         ResStaticCast<ResProceduralTextureMapper>(resTextureMapper);
313 
314     if (resProceduralTextureMapper.GetTexture().IsValid())
315     {
316         allocator->Free(resProceduralTextureMapper.ref().toTexture.to_ptr());
317     }
318 
319     allocator->Free(resProceduralTextureMapper.ptr());
320 }
321 
322 //-----------------------------------------
323 ResTextureMapper
CloneDynamic(os::IAllocator * allocator)324 ResTextureMapper::CloneDynamic(os::IAllocator* allocator)
325 {
326     NW_NULL_ASSERT(allocator);
327     ResTextureMapper resTextureMapper;
328     switch ( this->ref().typeInfo )
329     {
330     case ResPixelBasedTextureMapper::TYPE_INFO:
331         {
332             resTextureMapper = s_TextureMapperCloneDynamicTable[0]( *this, allocator );
333         }
334         break;
335     case ResProceduralTextureMapper::TYPE_INFO:
336         {
337             resTextureMapper = s_TextureMapperCloneDynamicTable[1]( *this, allocator );
338         }
339         break;
340     default:
341         {
342             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
343         }
344     }
345 
346     if (resTextureMapper.IsValid())
347     {
348         resTextureMapper.ref().m_DynamicAllocator = allocator;
349     }
350 
351     return resTextureMapper;
352 }
353 
354 //-----------------------------------------
355 void
GetMemorySizeForCloneInternal(os::MemorySizeCalculator * pSize) const356 ResTextureMapper::GetMemorySizeForCloneInternal(os::MemorySizeCalculator* pSize) const
357 {
358     os::MemorySizeCalculator& size = *pSize;
359 
360     switch ( this->ref().typeInfo )
361     {
362     case res::ResPixelBasedTextureMapper::TYPE_INFO:
363         {
364             // ResPixelBasedTextureMapper_CloneDynamic
365             NW_ASSERT(ResStaticCast<ResPixelBasedTextureMapper>(*this).GetTexture().IsValid());
366             NW_ASSERT(ResDynamicCast<ResStandardTextureSampler>(ResStaticCast<ResPixelBasedTextureMapper>(*this).GetSampler()).IsValid());
367 
368             size += sizeof(ResPixelBasedTextureMapperData);
369             size += sizeof(ResReferenceTextureData);
370             size += sizeof(ResStandardTextureSamplerData);
371 
372             return;
373         }
374     case res::ResProceduralTextureMapper::TYPE_INFO:
375     default:
376         NW_FATAL_ERROR("Unsupported texture mapper type.\n");
377     }
378 }
379 
380 //-----------------------------------------
381 void
DestroyDynamic()382 ResTextureMapper::DestroyDynamic()
383 {
384     if ( this->ref().m_DynamicAllocator == NULL ) { return; }
385 
386     switch ( this->ref().typeInfo )
387     {
388     case ResPixelBasedTextureMapper::TYPE_INFO:
389         {
390             s_TextureMapperDestroyDynamicTable[0]( *this, this->ref().m_DynamicAllocator );
391         }
392         break;
393     case ResProceduralTextureMapper::TYPE_INFO:
394         {
395             s_TextureMapperDestroyDynamicTable[1]( *this, this->ref().m_DynamicAllocator );
396         }
397         break;
398     default:
399         {
400             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
401         }
402     }
403 
404     this->ref().m_DynamicAllocator = NULL;
405 }
406 
407 
408 
409 //----------------------------------------
410 Result
Setup(os::IAllocator * allocator,ResGraphicsFile graphicsFile)411 ResTextureMapper::Setup(
412     os::IAllocator* allocator,
413     ResGraphicsFile graphicsFile
414 )
415 {
416     NW_NULL_ASSERT(allocator);
417     Result result = RESOURCE_RESULT_OK;
418 
419     switch ( this->ref().typeInfo )
420     {
421     case ResPixelBasedTextureMapper::TYPE_INFO:
422         {
423             result |= s_TextureMapperSetupTable[0]( *this, allocator, graphicsFile );
424         }
425         break;
426     case ResProceduralTextureMapper::TYPE_INFO:
427         {
428             result |= s_TextureMapperSetupTable[1]( *this, allocator, graphicsFile );
429         }
430         break;
431     default:
432         {
433             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
434         }
435     }
436 
437     return result;
438 }
439 
440 //----------------------------------------
441 void
Cleanup()442 ResTextureMapper::Cleanup()
443 {
444     switch ( this->ref().typeInfo )
445     {
446     case ResPixelBasedTextureMapper::TYPE_INFO:
447         {
448             s_TextureMapperCleanupTable[0]( *this );
449         }
450         break;
451     case ResProceduralTextureMapper::TYPE_INFO:
452         {
453             s_TextureMapperCleanupTable[1]( *this );
454         }
455         break;
456     default:
457         {
458             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
459         }
460     }
461 }
462 
463 //----------------------------------------
464 void
SetTexture(ResTexture resTexture)465 ResTextureMapper::SetTexture(ResTexture resTexture)
466 {
467     NW_ASSERT(resTexture.IsValid());
468 
469     ResReferenceTexture referenceTexture = ResStaticCast<ResReferenceTexture>(this->GetTexture());
470     referenceTexture.ref().toTargetTexture.set_ptr(resTexture.Dereference().ptr());
471 
472     switch ( this->ref().typeInfo )
473     {
474     case ResPixelBasedTextureMapper::TYPE_INFO:
475         {
476             ResPixelBasedTextureMapper resPixelBasedTextureMapper =
477                 ResStaticCast<ResPixelBasedTextureMapper>(*this);
478             ResTexture resImageTexture = resTexture.Dereference();
479 
480             switch ( resImageTexture.ref().typeInfo )
481             {
482             case ResImageTexture::TYPE_INFO:
483                 SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResImageTexture>(resImageTexture));
484                 break;
485             case ResCubeTexture::TYPE_INFO:
486                 SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResCubeTexture>(resImageTexture));
487                 break;
488             case ResShadowTexture::TYPE_INFO:
489                 SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResShadowTexture>(resImageTexture));
490                 break;
491             default:
492                 NW_FATAL_ERROR("Unsupported texture type.\n");
493             }
494         }
495         break;
496     case ResProceduralTextureMapper::TYPE_INFO:
497         {
498             // TODO: ProceduralTextureに対応したコマンドを生成する。
499             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
500         }
501         break;
502     default:
503         {
504             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
505         }
506     }
507 }
508 
509 //----------------------------------------
510 void
SetSampler(ResTextureSampler resTextureSampler)511 ResPixelBasedTextureMapper::SetSampler(ResTextureSampler resTextureSampler)
512 {
513     NW_ASSERT(resTextureSampler.IsValid());
514 
515     this->ref().toSampler.set_ptr(resTextureSampler.ptr());
516 
517     u32* command = this->GetCommandCache();
518 
519     // BorderColorを更新する
520     NW_NULL_ASSERT(command);
521 
522     switch ( resTextureSampler.ref().typeInfo )
523     {
524     case ResStandardTextureSampler::TYPE_INFO:
525         {
526             ResStandardTextureSampler resStandardTextureSampler =
527                 ResStaticCast<ResStandardTextureSampler>(resTextureSampler);
528             command[2] = resStandardTextureSampler.GetBorderColor().ToPicaU32();
529         }
530         break;
531     case ResShadowTextureSampler ::TYPE_INFO:
532         {
533             // TODO: ShadowTextureSampler が実装されたら対応する。
534         }
535         break;
536     default:
537         {
538             NW_FATAL_ERROR("Unsupported sampler type.");
539         }
540         break;
541     }
542 }
543 
544 /*!--------------------------------------------------------------------------*
545   @brief        リソースのテクスチャを参照します。
546 
547   @param[in]    allocator アロケータです。
548   @param[in]    resTexture オリジナルのデータです。
549  *---------------------------------------------------------------------------*/
ReferResTexture(os::IAllocator * allocator,ResTexture resTexture)550 static ResTexture ReferResTexture(
551     os::IAllocator* allocator,
552     ResTexture resTexture)
553 {
554     // この関数で確保されるメモリのサイズに変化があった場合は
555     // ResTextureMapper::GetRequiredMemorySizeForClone を修正してください。
556 
557     void* textureMemory = allocator->Alloc(sizeof(ResReferenceTextureData));
558     if (textureMemory == NULL)
559     {
560         return ResTexture(NULL);
561     }
562 
563     ResReferenceTextureData* texture = new(textureMemory) ResReferenceTextureData();
564     texture->typeInfo = ResReferenceTexture::TYPE_INFO;
565     texture->toName.set_ptr(NULL);
566     texture->toPath.set_ptr(NULL);
567     texture->toTargetTexture.set_ptr(NULL);
568 
569     switch ( resTexture.ref().typeInfo )
570     {
571     case ResImageTexture::TYPE_INFO:
572         {
573             texture->toTargetTexture.set_ptr(resTexture.ptr());
574         }
575         break;
576     case ResCubeTexture::TYPE_INFO:
577         {
578             texture->toTargetTexture.set_ptr(resTexture.ptr());
579         }
580         break;
581     case ResReferenceTexture::TYPE_INFO:
582         {
583             ResReferenceTexture referenceTexture = ResDynamicCast<ResReferenceTexture>(resTexture);
584             texture->toTargetTexture.set_ptr(referenceTexture.GetTargetTexture().ptr());
585         }
586         break;
587     case ResProceduralTexture::TYPE_INFO:
588         {
589             texture->toTargetTexture.set_ptr(resTexture.ptr());
590         }
591         break;
592     default:
593         {
594             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
595         }
596     }
597 
598     return ResTexture(texture);
599 }
600 
601 /*!--------------------------------------------------------------------------*
602   @brief        テクスチャをセットアップします。
603 
604   @param[in]    allocator アロケータです。
605   @param[in]    resTexture セットアップを行うテクスチャです。
606   @param[in]    graphicsFile グラフィックスファイルです。
607  *---------------------------------------------------------------------------*/
SetupTexture(os::IAllocator * allocator,ResTexture resTexture,ResGraphicsFile graphicsFile)608 static Result SetupTexture(
609     os::IAllocator* allocator,
610     ResTexture resTexture,
611     ResGraphicsFile graphicsFile
612 )
613 {
614     Result result = RESOURCE_RESULT_OK;
615     ResTexture setupTexture;
616 
617     bool existTexture = false;
618     if (resTexture.IsValid())
619     {
620         ResReferenceTexture refer = ResDynamicCast<ResReferenceTexture>(resTexture);
621         if (refer.IsValid())
622         {
623             if (refer.GetTargetTexture().IsValid())
624             {
625                 setupTexture = refer.GetTargetTexture();
626                 existTexture = true;
627             }
628             else
629             {
630                 ::std::pair<ResTexture, bool> referenceResult;
631                 referenceResult = GetReferenceTextureTarget(refer, graphicsFile);
632                 if (referenceResult.second)
633                 {
634                     setupTexture = referenceResult.first;
635                     existTexture = true;
636                 }
637                 else
638                 {
639                     result |= Result::MASK_FAIL_BIT;
640                     result |= RESOURCE_RESULT_NOT_FOUND_TEXTURE;
641                 }
642             }
643         }
644         else
645         {
646             setupTexture = resTexture;
647             existTexture = true;
648         }
649     }
650 
651     if (existTexture)
652     {
653         result |= setupTexture.Setup(allocator, graphicsFile);
654     }
655 
656     return result;
657 }
658 
659 enum
660 {
661     HEIGHT_SHIFT = 0,
662     WIDTH_SHIFT = 16,
663     HEIGHT_MASK = 0x7FF << HEIGHT_SHIFT,
664     WIDTH_MASK = 0x7FF << WIDTH_SHIFT,
665     ADDRESS_MASK = 0x0FFFFFFF,
666     CUBE_ADDRESS_MASK = 0x003FFFFF,
667     FORMAT_SHIFT = 0,
668     FORMAT_MASK = 0xF,
669     FORMAT_ETC_SHIFT = 4,
670     FORMAT_ETC_MASK = 0x3 << FORMAT_ETC_SHIFT,
671     MIPMAP_SIZE_SHIFT = 16,
672     MIPMAP_SIZE_MASK = 0xF << MIPMAP_SIZE_SHIFT,
673     SAMPLER_TYPE_SHADOW_2D = 2,
674     SAMPLER_TYPE_SHIFT = 28,
675     SAMPLER_TYPE_MASK = 0x7 << SAMPLER_TYPE_SHIFT
676 };
677 
678 /* --------------------------------------------------------------------------
679     コマンドのフォーマット
680     0 : 0x8e [3:0]format
681     1 : コマンドヘッダ
682     2 : 0x81 border_color
683     3 : コマンドヘッダ
684     4 : 0x82 [26:16]width [10:0]height
685     5 : 0x83 [5:4]etc_format|[14:12]wrap_s|[10:8]wraw_t|[1]mag_filter|[24][2]min_filter|[30:28]sampler_type
686     6 : 0x84 [27:24]min lod|[19:16]mipmap size|[12:0]lod bias
687     7 : 0x85 [27:0] addr
688     8 : 0x86 [21:0] addr(neg_x)
689     9 : 0x87 [21:0] addr(pos_y)
690    10 : 0x88 [21:0] addr(neg_y)
691    11 : 0x89 [21:0] addr(pos_z)
692    12 : 0x8a [21:0] addr(neg_z)
693    13 : 0x8b [0:0]perspectiveShadow [23:1]shadowZBias [31:24]shadowZScale
694  -------------------------------------------------------------------------- */
695 static void
SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper,ResImageTexture texture)696 SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResImageTexture texture)
697 {
698     u32* command = mapper.GetCommandCache();
699     mapper.SetCommandSizeToSend(8 * sizeof(u32));
700 
701     // これから設定する箇所をリセットする
702     command[0] &= ~FORMAT_MASK; // format
703     command[3] &= ~0x0FF00000;  // コマンドヘッダ
704     command[4] &= ~(HEIGHT_MASK | WIDTH_MASK); // width, height
705     command[5] &= ~(FORMAT_ETC_MASK); // etc_format
706     command[6] &= ~(MIPMAP_SIZE_MASK); // mipmap
707     command[7] &= ~ADDRESS_MASK; // address
708 
709     uint texId = texture.GetTextureObject();
710     ResPixelBasedImage resImage = texture.GetImage();
711     u32 addr = resImage.GetImageAddress();
712 
713     uint format = texture.GetFormatHW();
714 
715     command[0] |= format & FORMAT_MASK;
716 
717     // コマンドの長さを設定
718     // 0x82-0x85で 5 - 1 = 4
719     command[3] |= 4 << 20;
720     command[1] |= 0x000F0000; // glの吐くコードと同じにしてみる。
721 
722     command[4] |= (texture.GetHeight() & 0x7FF) << 0;
723     command[4] |= (texture.GetWidth() & 0x7FF) << WIDTH_SHIFT;
724 
725     if (format == ResImageTexture::FORMAT_HW_ETC1)
726     {
727         command[5] |= 2 << FORMAT_ETC_SHIFT;
728     }
729 
730     command[6] |= ((texture.GetMipmapSize() - 1) & 0xF) << MIPMAP_SIZE_SHIFT;
731 
732     command[7] |= (nngxGetPhysicalAddr( addr ) >> 3) & ADDRESS_MASK;
733 }
734 
735 //---------------------------------------------------------------------------
736 //! @brief        テクスチャのアドレスが GPU の制約を満たしているかどうかをチェックします。
737 //!
738 //! @param[in]    texture キューブテクスチャです。
739 //!
740 //! @return       制約を満たしているならば true, 満たしていない場合は false を返します。
741 //---------------------------------------------------------------------------
742 static bool
VerifyCubeTextureAddress_(ResCubeTexture texture)743 VerifyCubeTextureAddress_( ResCubeTexture texture )
744 {
745     u32 base_addr = 0;
746     uint texId = texture.GetTextureObject();
747 
748     for ( int face = 0; face < ResCubeTexture::MAX_CUBE_FACE; ++face )
749     {
750         ResPixelBasedImage resImage = texture.GetImage( static_cast<ResCubeTexture::CubeFace>( face ) );
751         u32 addr = nngxGetPhysicalAddr( resImage.GetImageAddress() );
752 
753         // POSITIVE_X が必ず先頭アドレスである必要がある。全ての面のテクスチャが 32MB 境界を跨がない。
754         if (face == ResCubeTexture::CUBE_FACE_POSITIVE_X)
755         {
756             base_addr = addr;
757         }
758         else
759         {
760             if ( addr < base_addr )
761             {
762                 return false;
763             }
764 
765             if ( (base_addr & 0xFE000000) != (addr & 0xFE000000) )
766             {
767                 return false;
768             }
769         }
770     }
771 
772     return true;
773 }
774 
775 //--------------------------------------------------------------------------
776 //! @brief        キューブテクスチャの情報を収集してテクスチャマッパにコマンドを構築します。
777 //!
778 //! @param[in]    mapper  テクスチャマッパです。
779 //! @param[in]    texture キューブテクスチャの情報です。
780 //---------------------------------------------------------------------------
781 static void
SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper,ResCubeTexture texture)782 SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResCubeTexture texture)
783 {
784     u32* command = mapper.GetCommandCache();
785     mapper.SetCommandSizeToSend(14 * sizeof(u32));
786 
787     uint texId = texture.GetTextureObject();
788 
789     uint format = texture.GetFormatHW();
790 
791     // これから設定する箇所をリセットする
792     command[0] &= ~FORMAT_MASK;
793     command[3] &= ~0x0FF00000;
794     command[4] &= ~(HEIGHT_MASK | WIDTH_MASK); // width, height
795     command[5] &= ~(FORMAT_ETC_MASK); // etc_format
796     command[6] &= ~(MIPMAP_SIZE_MASK); // mipmap
797     command[7] &= ~ADDRESS_MASK; // address
798     command[8] &= ~CUBE_ADDRESS_MASK;
799     command[9] &= ~CUBE_ADDRESS_MASK;
800     command[10] &= ~CUBE_ADDRESS_MASK;
801     command[11] &= ~CUBE_ADDRESS_MASK;
802     command[12] &= ~CUBE_ADDRESS_MASK;
803 
804     command[0] |= format & 0xF;
805     // コマンドの長さを調整
806     command[3] |= 9 << 20;
807 
808     command[4] |= (texture.GetHeight() & 0x7FF) << 0;
809     command[4] |= (texture.GetWidth() & 0x7FF) << WIDTH_SHIFT;
810 
811     if (format == ResImageTexture::FORMAT_HW_ETC1)
812     {
813         command[5] |= 2 << FORMAT_ETC_SHIFT;
814     }
815 
816     NW_ASSERT( VerifyCubeTextureAddress_( texture ) );
817 
818     command[6] |= ((texture.GetMipmapSize() - 1) & 0xF) << MIPMAP_SIZE_SHIFT;
819 
820     for ( int face = 0; face < ResCubeTexture::MAX_CUBE_FACE; ++face )
821     {
822         ResPixelBasedImage resImage = texture.GetImage( static_cast<ResCubeTexture::CubeFace>( face ) );
823         u32 addr = resImage.GetImageAddress();
824 
825         if (face == 0)
826         {
827             command[7] |= (nngxGetPhysicalAddr( addr ) >> 3) & ADDRESS_MASK;
828         }
829         else
830         {
831             command[7 + face] |= (nngxGetPhysicalAddr( addr ) >> 3) & CUBE_ADDRESS_MASK;
832         }
833     }
834 }
835 
836 //--------------------------------------------------------------------------
837 //! @brief        シャドウテクスチャの情報を収集してテクスチャマッパにコマンドを構築します。
838 //!
839 //! @param[in]    mapper  テクスチャマッパです。
840 //! @param[in]    texture シャドウテクスチャの情報です。
841 //---------------------------------------------------------------------------
842 static void
SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper,ResShadowTexture texture)843 SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResShadowTexture texture)
844 {
845     u32* command = mapper.GetCommandCache();
846     mapper.SetCommandSizeToSend(14 * sizeof(u32));
847 
848     // これから設定する箇所をリセットする
849     command[0] &= ~FORMAT_MASK; // format
850     command[3] &= ~0x0FF00000;  // コマンドヘッダ
851     command[4] &= ~(HEIGHT_MASK | WIDTH_MASK); // width, height
852     command[5] &= ~(FORMAT_ETC_MASK | SAMPLER_TYPE_MASK); // etc_format
853     command[6] &= ~(MIPMAP_SIZE_MASK); // mipmap
854     command[7] &= ~ADDRESS_MASK; // address
855     command[13] = 0x0; // shadow
856 
857     uint texId = texture.GetTextureObject();
858     ResPixelBasedImage resImage = texture.GetImage();
859     u32 addr = resImage.GetImageAddress();
860 
861     uint format = texture.GetFormatHW();
862 
863     command[0] |= format & FORMAT_MASK;
864 
865     // コマンドの長さを設定
866     command[3] |= 10 << 20;
867     command[1] |= 0x000F0000; // glの吐くコードと同じにしてみる。
868 
869     command[4] |= (texture.GetHeight() & 0x7FF) << 0;
870     command[4] |= (texture.GetWidth() & 0x7FF) << WIDTH_SHIFT;
871     // texture_shadow_2d
872     command[5] |= SAMPLER_TYPE_SHADOW_2D << SAMPLER_TYPE_SHIFT;
873 
874     command[6] |= ((texture.GetMipmapSize() - 1) & 0xF) << MIPMAP_SIZE_SHIFT;
875 
876     command[7] |= (nngxGetPhysicalAddr( addr ) >> 3) & ADDRESS_MASK;
877 
878     command[13] |= ((texture.IsPerspectiveShadow() ? 0 : 1) & 0x1) << 0;
879     command[13] |= ((ut::FixedU24::Float32ToFixedU24(texture.GetShadowZBias()) >> 1) & 0x7FFFFF) << 1;
880 
881     u32 scaleU32 = ((ut::Float32::Float32ToBits32(texture.GetShadowZScale()) >> 23) & 0xFF);
882     command[13] |= ((scaleU32 - 127) & 0xFF) << 24;
883 }
884 
885 } /* namespace res */
886 } /* namespace gfx */
887 } /* namespace nw */
888 
889