1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ResTextureMapper.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: $
16  *---------------------------------------------------------------------------*/
17 
18 #include "../precompiled.h"
19 
20 #include <nw/gfx/res/gfx_ResUtil.h>
21 #include <nw/gfx/res/gfx_ResTextureMapper.h>
22 #include <nw/gfx/res/gfx_ResGraphicsFile.h>
23 #include <nw/gfx/gfx_CommandUtil.h>
24 
25 namespace nw {
26 namespace gfx {
27 namespace res {
28 
29 typedef Result (*SetupFunc)(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile);
30 typedef void (*CleanupFunc)(ResTextureMapper resTextureMapper);
31 typedef ResTextureMapper (*CloneDynamicFunc)(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
32 typedef void (*DestroyDynamicFunc)(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
33 
34 static Result ResPixelBasedTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile);
35 static Result ResProceduralTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile);
36 static void ResPixelBasedTextureMapper_Cleanup(ResTextureMapper resTextureMapper);
37 static void ResProceduralTextureMapper_Cleanup(ResTextureMapper resTextureMapper);
38 static ResTextureMapper ResPixelBasedTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
39 static ResTextureMapper ResProceduralTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
40 static void ResPixelBasedTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
41 static void ResProceduralTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator);
42 
43 static ResTexture ReferResTexture(os::IAllocator* allocator, ResTexture resTexture);
44 
45 static Result SetupTexture(
46     os::IAllocator* allocator,
47     ResTexture resTexture,
48     ResGraphicsFile graphicsFile
49 );
50 
51 static void SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResImageTexture texture);
52 static void SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResCubeTexture texture);
53 static void SetupTextureMapperCommand(ResPixelBasedTextureMapper mapper, ResShadowTexture texture);
54 
55 static SetupFunc s_TextureMapperSetupTable[] =
56 {
57     ResPixelBasedTextureMapper_Setup,
58     ResProceduralTextureMapper_Setup
59 };
60 
61 static CleanupFunc s_TextureMapperCleanupTable[] =
62 {
63     ResPixelBasedTextureMapper_Cleanup,
64     ResProceduralTextureMapper_Cleanup
65 };
66 
67 static CloneDynamicFunc s_TextureMapperCloneDynamicTable[] =
68 {
69     ResPixelBasedTextureMapper_CloneDynamic,
70     ResProceduralTextureMapper_CloneDynamic
71 };
72 
73 static DestroyDynamicFunc s_TextureMapperDestroyDynamicTable[] =
74 {
75     ResPixelBasedTextureMapper_DestroyDynamic,
76     ResProceduralTextureMapper_DestroyDynamic
77 };
78 
79 //----------------------------------------
80 ::std::pair<u32, u32*>
GetOwnerCommand() const81 ResTextureSampler::GetOwnerCommand() const
82 {
83     ResPixelBasedTextureMapper textureMapper =
84         ResStaticCast<ResPixelBasedTextureMapper>(ResTextureMapper(this->GetOwnerData()));
85 
86     return ::std::make_pair(textureMapper.GetCommandSizeToSend(), textureMapper.GetCommandCache());
87 }
88 
89 //----------------------------------------
90 void
SetTextureMipmapCommand()91 ResTextureSampler::SetTextureMipmapCommand()
92 {
93     ResPixelBasedTextureMapper textureMapper =
94         ResStaticCast<ResPixelBasedTextureMapper>(ResTextureMapper(this->GetOwnerData()));
95 
96     ResTexture texture = textureMapper.GetTexture();
97 
98     MinFilter filter = this->GetMinFilter();
99 
100     int mipmapSize = 0;
101     if (texture.IsValid() &&
102         filter != MINFILTER_LINEAR &&
103         filter != MINFILTER_NEAREST)
104     {
105         ResPixelBasedTexture pixelBasedTexture =
106             ResStaticCast<ResPixelBasedTexture>(texture.Dereference());
107         mipmapSize = pixelBasedTexture.GetMipmapSize() - 1;
108     }
109 
110     u32* command = textureMapper.GetCommandCache();
111 
112     enum {
113         CMD_SHIFT = 16,
114         CMD_MASK = 0xF,
115         CMD_INDEX = 6
116     };
117 
118     internal::SetCmdValue( &command[CMD_INDEX], mipmapSize, CMD_MASK, CMD_SHIFT );
119 }
120 
121 /*!--------------------------------------------------------------------------*
122   @brief        ピクセルベーステクスチャマッパーをセットアップします。
123 
124   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
125   @param[in]    allocator        アロケータです。
126   @param[in]    graphicsFile     グラフィックスファイルです。
127  *---------------------------------------------------------------------------*/
128 static Result
ResPixelBasedTextureMapper_Setup(ResTextureMapper resTextureMapper,os::IAllocator * allocator,ResGraphicsFile graphicsFile)129 ResPixelBasedTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile)
130 {
131     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
132         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
133     ResTexture resTexture = resTextureMapper.GetTexture();
134 
135     Result result = SetupTexture(allocator, resTexture, graphicsFile);
136 
137     if (result.IsFailure())
138     {
139         return result;
140     }
141 
142     ResTexture resImageTexture = resTexture.Dereference();
143 
144     switch ( resImageTexture.ref().typeInfo )
145     {
146     case ResImageTexture::TYPE_INFO:
147         SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResImageTexture>(resImageTexture));
148         break;
149     case ResCubeTexture::TYPE_INFO:
150         SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResCubeTexture>(resImageTexture));
151         break;
152     case ResShadowTexture::TYPE_INFO:
153         SetupTextureMapperCommand(resPixelBasedTextureMapper, ResStaticCast<ResShadowTexture>(resImageTexture));
154         break;
155     default:
156         NW_FATAL_ERROR("Unsupported texture type.\n");
157     }
158 
159     return result;
160 }
161 
162 /*!--------------------------------------------------------------------------*
163   @brief        プロシージャルテクスチャマッパーをセットアップします。
164 
165   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
166   @param[in]    allocator        アロケータです。
167   @param[in]    graphicsFile     グラフィックスファイルです。
168  *---------------------------------------------------------------------------*/
169 static Result
ResProceduralTextureMapper_Setup(ResTextureMapper resTextureMapper,os::IAllocator * allocator,ResGraphicsFile graphicsFile)170 ResProceduralTextureMapper_Setup(ResTextureMapper resTextureMapper, os::IAllocator* allocator, ResGraphicsFile graphicsFile)
171 {
172     return SetupTexture(allocator, resTextureMapper.GetTexture(), graphicsFile);
173 }
174 
175 /*!--------------------------------------------------------------------------*
176   @brief        ピクセルベーステクスチャマッパーの後始末をします。
177 
178   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
179  *---------------------------------------------------------------------------*/
180 static void
ResPixelBasedTextureMapper_Cleanup(ResTextureMapper resTextureMapper)181 ResPixelBasedTextureMapper_Cleanup(ResTextureMapper resTextureMapper)
182 {
183     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
184         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
185 
186     resPixelBasedTextureMapper.ResetCommand();
187 
188     ResTexture resTexture = resTextureMapper.GetTexture();
189     ut::SafeCleanup(resTexture);
190 }
191 
192 /*!--------------------------------------------------------------------------*
193   @brief        プロシージャルテクスチャマッパーの後始末をします。
194 
195   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
196  *---------------------------------------------------------------------------*/
197 static void
ResProceduralTextureMapper_Cleanup(ResTextureMapper resTextureMapper)198 ResProceduralTextureMapper_Cleanup(ResTextureMapper resTextureMapper)
199 {
200     ResTexture resTexture = resTextureMapper.GetTexture();
201     ut::SafeCleanup(resTexture);
202 }
203 
204 /*!--------------------------------------------------------------------------*
205   @brief        ピクセルベーステクスチャマッパーをクローンします。
206 
207   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
208   @param[in]    allocator  アロケータです。
209  *---------------------------------------------------------------------------*/
210 static ResTextureMapper
ResPixelBasedTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)211 ResPixelBasedTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
212 {
213     // この関数で確保されるメモリのサイズに変化があった場合は
214     // ResTextureMapper::GetRequiredMemorySizeForClone を修正してください。
215     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
216         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
217 
218     void* mapperMemory = allocator->Alloc(sizeof(ResPixelBasedTextureMapperData));
219     if (mapperMemory == NULL)
220     {
221         return ResTextureMapper(NULL);
222     }
223 
224     ResPixelBasedTextureMapperData* textureMapper =
225         new(mapperMemory) ResPixelBasedTextureMapperData(resPixelBasedTextureMapper.ref());
226 
227     ResPixelBasedTextureMapper cloneTextureMapper = ResPixelBasedTextureMapper(textureMapper);
228 
229     ResTexture resTexture = resPixelBasedTextureMapper.GetTexture();
230     if (resTexture.IsValid())
231     {
232         // リファレンステクスチャを生成してテクスチャを参照します。
233         ResTexture referenceTexture = ReferResTexture(allocator, resTexture);
234         if (referenceTexture.IsValid())
235         {
236             textureMapper->toTexture.set_ptr(referenceTexture.ptr());
237         }
238         else
239         {
240             ResPixelBasedTextureMapper_DestroyDynamic(cloneTextureMapper, allocator);
241             return ResTextureMapper(NULL);
242         }
243     }
244 
245     ResStandardTextureSampler resStandardTextureSampler =
246         ResDynamicCast<ResStandardTextureSampler>(resPixelBasedTextureMapper.GetSampler());
247 
248     if (resStandardTextureSampler.IsValid())
249     {
250         void* samplerMemory = allocator->Alloc(sizeof(ResStandardTextureSamplerData));
251         if (samplerMemory == NULL)
252         {
253             ResPixelBasedTextureMapper_DestroyDynamic(cloneTextureMapper, allocator);
254             return ResTextureMapper(NULL);
255         }
256 
257         ResStandardTextureSamplerData* textureSampler =
258             new(samplerMemory) ResStandardTextureSamplerData(resStandardTextureSampler.ref());
259 
260         textureMapper->toSampler.set_ptr(textureSampler);
261         textureSampler->toOwner.set_ptr(textureMapper);
262     }
263 
264     return cloneTextureMapper;
265 }
266 
267 /*!--------------------------------------------------------------------------*
268   @brief        プロシージャルテクスチャマッパーをクローンします。
269 
270   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
271   @param[in]    allocator  アロケータです。
272  *---------------------------------------------------------------------------*/
273 static ResTextureMapper
ResProceduralTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)274 ResProceduralTextureMapper_CloneDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
275 {
276     // この関数で確保されるメモリのサイズに変化があった場合は
277     // ResTextureMapper::GetRequiredMemorySizeForClone を修正してください。
278     ResProceduralTextureMapper resProceduralTextureMapper =
279         ResStaticCast<ResProceduralTextureMapper>(resTextureMapper);
280 
281     void* mapperMemory = allocator->Alloc(sizeof(ResProceduralTextureMapperData));
282     if (mapperMemory == NULL)
283     {
284         return ResTextureMapper(NULL);
285     }
286 
287     ResProceduralTextureMapperData* textureMapper =
288         new(mapperMemory) ResProceduralTextureMapperData(resProceduralTextureMapper.ref());
289 
290     ResProceduralTextureMapper cloneTextureMapper = ResProceduralTextureMapper(textureMapper);
291 
292     ResTexture resTexture = resProceduralTextureMapper.GetTexture();
293     if (resTexture.IsValid())
294     {
295         // リファレンステクスチャを生成してテクスチャを参照します。
296         ResTexture referenceTexture = ReferResTexture(allocator, resTexture);
297         if (referenceTexture.IsValid())
298         {
299             textureMapper->toTexture.set_ptr(referenceTexture.ptr());
300         }
301         else
302         {
303             ResProceduralTextureMapper_DestroyDynamic(cloneTextureMapper, allocator);
304             return ResTextureMapper(NULL);
305         }
306     }
307 
308     return cloneTextureMapper;
309 }
310 
311 /*!--------------------------------------------------------------------------*
312   @brief        ピクセルベーステクスチャマッパーを削除します。
313 
314   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
315   @param[in]    allocator        アロケータです。
316  *---------------------------------------------------------------------------*/
317 static void
ResPixelBasedTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)318 ResPixelBasedTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
319 {
320     ResPixelBasedTextureMapper resPixelBasedTextureMapper =
321         ResStaticCast<ResPixelBasedTextureMapper>(resTextureMapper);
322 
323     if (resPixelBasedTextureMapper.GetSampler().IsValid())
324     {
325         allocator->Free(resPixelBasedTextureMapper.ref().toSampler.to_ptr());
326     }
327 
328     if (resPixelBasedTextureMapper.GetTexture().IsValid())
329     {
330         allocator->Free(resPixelBasedTextureMapper.ref().toTexture.to_ptr());
331     }
332 
333     allocator->Free(resPixelBasedTextureMapper.ptr());
334 }
335 
336 /*!--------------------------------------------------------------------------*
337   @brief        プロシージャルテクスチャマッパーを削除します。
338 
339   @param[in]    resTextureMapper 対象となるテクスチャマッパーリソースのインスタンスです。
340   @param[in]    allocator        アロケータです。
341  *---------------------------------------------------------------------------*/
342 static void
ResProceduralTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper,os::IAllocator * allocator)343 ResProceduralTextureMapper_DestroyDynamic(ResTextureMapper resTextureMapper, os::IAllocator* allocator)
344 {
345     ResProceduralTextureMapper resProceduralTextureMapper =
346         ResStaticCast<ResProceduralTextureMapper>(resTextureMapper);
347 
348     if (resProceduralTextureMapper.GetTexture().IsValid())
349     {
350         allocator->Free(resProceduralTextureMapper.ref().toTexture.to_ptr());
351     }
352 
353     allocator->Free(resProceduralTextureMapper.ptr());
354 }
355 
356 //-----------------------------------------
357 ResTextureMapper
CloneDynamic(os::IAllocator * allocator)358 ResTextureMapper::CloneDynamic(os::IAllocator* allocator)
359 {
360     NW_NULL_ASSERT(allocator);
361     ResTextureMapper resTextureMapper;
362     switch ( this->ref().typeInfo )
363     {
364     case ResPixelBasedTextureMapper::TYPE_INFO:
365         {
366             resTextureMapper = s_TextureMapperCloneDynamicTable[0]( *this, allocator );
367         }
368         break;
369     case ResProceduralTextureMapper::TYPE_INFO:
370         {
371             resTextureMapper = s_TextureMapperCloneDynamicTable[1]( *this, allocator );
372         }
373         break;
374     default:
375         {
376             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
377         }
378     }
379 
380     if (resTextureMapper.IsValid())
381     {
382         resTextureMapper.ref().m_DynamicAllocator = allocator;
383     }
384 
385     return resTextureMapper;
386 }
387 
388 //-----------------------------------------
389 void
GetMemorySizeForCloneInternal(os::MemorySizeCalculator * pSize) const390 ResTextureMapper::GetMemorySizeForCloneInternal(os::MemorySizeCalculator* pSize) const
391 {
392     os::MemorySizeCalculator& size = *pSize;
393 
394     switch ( this->ref().typeInfo )
395     {
396     case res::ResPixelBasedTextureMapper::TYPE_INFO:
397         {
398             // ResPixelBasedTextureMapper_CloneDynamic
399             NW_ASSERT(ResStaticCast<ResPixelBasedTextureMapper>(*this).GetTexture().IsValid());
400             NW_ASSERT(ResDynamicCast<ResStandardTextureSampler>(ResStaticCast<ResPixelBasedTextureMapper>(*this).GetSampler()).IsValid());
401 
402             size += sizeof(ResPixelBasedTextureMapperData);
403             size += sizeof(ResReferenceTextureData);
404             size += sizeof(ResStandardTextureSamplerData);
405 
406             return;
407         }
408     case res::ResProceduralTextureMapper::TYPE_INFO:
409     default:
410         NW_FATAL_ERROR("Unsupported texture mapper type.\n");
411     }
412 }
413 
414 //-----------------------------------------
415 void
DestroyDynamic()416 ResTextureMapper::DestroyDynamic()
417 {
418     if ( this->ref().m_DynamicAllocator == NULL ) { return; }
419 
420     switch ( this->ref().typeInfo )
421     {
422     case ResPixelBasedTextureMapper::TYPE_INFO:
423         {
424             s_TextureMapperDestroyDynamicTable[0]( *this, this->ref().m_DynamicAllocator );
425         }
426         break;
427     case ResProceduralTextureMapper::TYPE_INFO:
428         {
429             s_TextureMapperDestroyDynamicTable[1]( *this, this->ref().m_DynamicAllocator );
430         }
431         break;
432     default:
433         {
434             NW_FATAL_ERROR("Unsupported texture mapper type.\n");
435         }
436     }
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 //----------------------------------------
ForceSetupTexture(ResTexture texture)901 void ResPixelBasedTextureMapper::ForceSetupTexture(ResTexture texture)
902 {
903     NW_ASSERT(texture.IsValid());
904     ResReferenceTexture refer = ResStaticCast<ResReferenceTexture>(this->GetTexture());
905     refer.ref().toTargetTexture.set_ptr(texture.ptr());
906 
907     ResTexture resImageTexture = refer.Dereference();
908 
909     switch ( resImageTexture.ref().typeInfo )
910     {
911     case ResImageTexture::TYPE_INFO:
912         SetupTextureMapperCommand(*this, ResStaticCast<ResImageTexture>(resImageTexture));
913         break;
914     case ResCubeTexture::TYPE_INFO:
915         SetupTextureMapperCommand(*this, ResStaticCast<ResCubeTexture>(resImageTexture));
916         break;
917     case ResShadowTexture::TYPE_INFO:
918         SetupTextureMapperCommand(*this, ResStaticCast<ResShadowTexture>(resImageTexture));
919         break;
920     default:
921         NW_FATAL_ERROR("Unsupported texture type.\n");
922     }
923 }
924 
925 } /* namespace res */
926 } /* namespace gfx */
927 } /* namespace nw */
928 
929