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