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