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