1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Material.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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 
20 #include <nw/gfx/gfx_Material.h>
21 #include <nw/gfx/gfx_Model.h>
22 #include <nw/gfx/res/gfx_ResMaterial.h>
23 #include <nw/gfx/res/gfx_ResShader.h>
24 #include <nw/gfx/gfx_AnimObject.h>
25 
26 namespace
27 {
GetAvailableResMaterial(nw::gfx::Material * material,nw::gfx::Model::BufferOption bufferOption)28 nw::gfx::ResMaterial GetAvailableResMaterial(
29     nw::gfx::Material* material, nw::gfx::Model::BufferOption bufferOption)
30 {
31     return nw::ut::CheckFlag(material->GetOwnerModel()->GetBufferOption(), bufferOption)
32         ? material->GetBuffer()
33         : material->GetOriginal();
34 }
35 }
36 
37 namespace nw
38 {
39 namespace gfx
40 {
41 
42 NW_UT_RUNTIME_TYPEINFO_DEFINITION(Material, SceneObject);
43 
44 //----------------------------------------
Material(os::IAllocator * allocator,ResMaterial resMaterial,s32 bufferCount,Model * owner)45 Material::Material(
46     os::IAllocator* allocator,
47     ResMaterial resMaterial,
48     s32 bufferCount,
49     Model* owner)
50 : SceneObject(
51     allocator,
52     resMaterial),
53     m_Owner(owner),
54     m_BufferCount(bufferCount)
55 {
56     ResBinaryShader resShader = resMaterial.GetShader().Dereference();
57 
58     NW_ASSERT(resShader.IsValid());
59     m_ProgramDescription =
60         resShader.GetDescriptions(resMaterial.GetShaderProgramDescriptionIndex());
61 }
62 
63 //----------------------------------------
64 Material*
Create(ResMaterial resource,s32 bufferCount,Model * parent,os::IAllocator * allocator)65 Material::Create(
66     ResMaterial resource,
67     s32 bufferCount,
68     Model* parent,
69     os::IAllocator* allocator
70 )
71 {
72     NW_NULL_ASSERT(allocator);
73     NW_ASSERT(resource.IsValid());
74 
75     // マテリアルバッファは1つのみ作成可能です。
76     NW_ASSERTMSG(bufferCount <= 1, "Material Buffer Count must be 0 or 1.");
77 
78     void* memory = allocator->Alloc(sizeof(Material));
79     if (memory == NULL)
80     {
81         return NULL;
82     }
83 
84     Material* material = new(memory) Material(
85         allocator,
86         resource,
87         bufferCount,
88         parent);
89 
90     Result result = material->Initialize(allocator);
91     if (result.IsSuccess())
92     {
93         material->m_ShaderParameterResMaterial =
94             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SHADER_PARAMETER);
95         material->m_ShadingParameterResMaterial =
96             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SHADING_PARAMETER);
97         material->m_MaterialColorResMaterial =
98             GetAvailableResMaterial(material, Model::FLAG_BUFFER_MATERIAL_COLOR);
99         material->m_RasterizationResMaterial =
100             GetAvailableResMaterial(material, Model::FLAG_BUFFER_RASTERIZATION);
101         material->m_TextureCoordinatorResMaterial =
102             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_COORDINATOR);
103         material->m_TextureMapperResMaterial =
104             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_MAPPER);
105         material->m_FragmentLightingResMaterial =
106             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_LIGHTING);
107         material->m_FragmentLightingTableResMaterial =
108             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE);
109         material->m_TextureCombinerResMaterial =
110             GetAvailableResMaterial(material, Model::FLAG_BUFFER_TEXTURE_COMBINER);
111         material->m_AlphaTestResMaterial =
112             GetAvailableResMaterial(material, Model::FLAG_BUFFER_ALPHA_TEST);
113         material->m_FragmentOperationResMaterial =
114             GetAvailableResMaterial(material, Model::FLAG_BUFFER_FRAGMENT_OPERATION);
115         material->m_SceneEnvironmentResMaterial =
116             GetAvailableResMaterial(material, Model::FLAG_BUFFER_SCENE_ENVIRONMENT);
117         return material;
118     }
119     else
120     {
121         SafeDestroy(material);
122         return NULL;
123     }
124 }
125 
126 //----------------------------------------
127 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResMaterial resMaterial,s32 bufferCount,bit32 bufferOption)128 Material::GetMemorySizeInternal(
129     os::MemorySizeCalculator* pSize,
130     ResMaterial resMaterial,
131     s32 bufferCount,
132     bit32 bufferOption)
133 {
134     os::MemorySizeCalculator& size = *pSize;
135 
136     // Material::Create
137     size += sizeof(Material);
138 
139     // Material::Initialize
140 
141     // Material::CreateBuffers
142     size += sizeof(ResMaterial) * bufferCount;
143     if (bufferCount > 0)
144     {
145         // TODO: 要検証
146         // Material::CopyResMaterial
147         os::MemorySizeCalculator bufferSize(size.GetAlignment());
148 
149         bufferSize += sizeof(ResMaterialData);
150 
151         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_SHADER_PARAMETER))
152         {
153             bufferSize += sizeof(ut::Offset) * resMaterial.GetShaderParametersCount();
154 
155             for (int i = 0; i < resMaterial.GetShaderParametersCount(); ++i)
156             {
157                 const int parameterLength = resMaterial.GetShaderParameters(i).GetParameterLength();
158 
159                 bufferSize += sizeof(ResShaderParameterData) + sizeof(f32) * (parameterLength - 1);
160             }
161         }
162 
163         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_TEXTURE_MAPPER))
164         {
165             for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
166             {
167                 ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(i);
168                 if (resTextureMapper.IsValid())
169                 {
170                     resTextureMapper.GetMemorySizeForCloneInternal(&bufferSize);
171                 }
172             }
173         }
174 
175         if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER))
176         {
177             ResProceduralTextureMapper resTextureMapper = resMaterial.GetProceduralTextureMapper();
178             if (resTextureMapper.IsValid())
179             {
180                 resTextureMapper.GetMemorySizeForCloneInternal(&bufferSize);
181             }
182         }
183 
184         if (ut::CheckFlagOr(bufferOption, Model::MULTI_FLAG_BUFFER_FRAGMENT_SHADER))
185         {
186             if (resMaterial.GetFragmentShader().IsValid())
187             {
188                 bufferSize += sizeof(ResFragmentShaderData);
189 
190                 if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE))
191                 {
192                     // Material::CopyResFragmentLightingTable
193                     ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
194 
195                     if (resFragmentShader.GetFragmentLightingTable().IsValid())
196                     {
197                         ResFragmentLightingTable resFragmentLightingTable =
198                             resFragmentShader.GetFragmentLightingTable();
199 
200                         bufferSize += sizeof(ResFragmentLightingTableData);
201                         if (resFragmentLightingTable.GetReflectanceRSampler().IsValid())
202                         {
203                             bufferSize += sizeof(ResLightingLookupTableData);
204                             bufferSize += sizeof(ResReferenceLookupTableData);
205                         }
206                         if (resFragmentLightingTable.GetReflectanceGSampler().IsValid())
207                         {
208                             bufferSize += sizeof(ResLightingLookupTableData);
209                             bufferSize += sizeof(ResReferenceLookupTableData);
210                         }
211                         if (resFragmentLightingTable.GetReflectanceBSampler().IsValid())
212                         {
213                             bufferSize += sizeof(ResLightingLookupTableData);
214                             bufferSize += sizeof(ResReferenceLookupTableData);
215                         }
216                         if (resFragmentLightingTable.GetDistribution0Sampler().IsValid())
217                         {
218                             bufferSize += sizeof(ResLightingLookupTableData);
219                             bufferSize += sizeof(ResReferenceLookupTableData);
220                         }
221                         if (resFragmentLightingTable.GetDistribution1Sampler().IsValid())
222                         {
223                             bufferSize += sizeof(ResLightingLookupTableData);
224                             bufferSize += sizeof(ResReferenceLookupTableData);
225                         }
226                         if (resFragmentLightingTable.GetFresnelSampler().IsValid())
227                         {
228                             bufferSize += sizeof(ResLightingLookupTableData);
229                             bufferSize += sizeof(ResReferenceLookupTableData);
230                         }
231                     }
232                 }
233             }
234         }
235 
236         bufferSize *= bufferCount;
237         size += bufferSize.GetSizeWithPadding(size.GetAlignment());
238     }
239 }
240 
241 //----------------------------------------
~Material()242 Material::~Material()
243 {
244     std::for_each(
245         m_Buffers.begin(), m_Buffers.end(), ResMaterialDestroyer(&this->GetAllocator()));
246 }
247 
248 //----------------------------------------
249 bool
CanUseBuffer(u32 objectType) const250 Material::CanUseBuffer(u32 objectType) const
251 {
252     if (0 < m_BufferCount)
253     {
254         bit32 option = this->GetOwnerModel()->GetBufferOption();
255         switch (objectType)
256         {
257         case anim::ResAnimGroupMember::OBJECT_TYPE_MATERIAL_COLOR:
258             return ut::CheckFlag(option, Model::FLAG_BUFFER_MATERIAL_COLOR);
259         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_SAMPLER:
260             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_MAPPER);
261         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_MAPPER:
262             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_MAPPER);
263         case anim::ResAnimGroupMember::OBJECT_TYPE_BLEND_OPERATION:
264             return ut::CheckFlag(option, Model::FLAG_BUFFER_FRAGMENT_OPERATION);
265         case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_COORDINATOR:
266             return ut::CheckFlag(option, Model::FLAG_BUFFER_TEXTURE_COORDINATOR);
267         default:
268             NW_ASSERT(false);
269         }
270     }
271     return false;
272 }
273 
274 //-----------------------------------------
275 Result
CreateBuffers(os::IAllocator * allocator)276 Material::CreateBuffers(os::IAllocator* allocator)
277 {
278     Result result = INITIALIZE_RESULT_OK;
279 
280     NW_NULL_ASSERT(this->m_Owner);
281     bit32 bufferOption = m_Owner->GetBufferOption();
282 
283     if (m_BufferCount != 0)
284     {
285         void* memory = allocator->Alloc(sizeof(ResMaterial) * m_BufferCount);
286         if (memory == NULL)
287         {
288             result |= Result::MASK_FAIL_BIT;
289         }
290 
291         NW_ENSURE_AND_RETURN(result);
292 
293         m_Buffers = ResMaterialArray(memory, m_BufferCount, allocator);
294 
295         for (int bufferIndex = 0; bufferIndex < m_BufferCount; bufferIndex++)
296         {
297             NW_ENSURE_AND_RETURN(result);
298             ::std::pair<ResMaterial, Result> copyResult = this->CopyResMaterial(allocator, bufferOption);
299 
300             if (copyResult.second.IsSuccess())
301             {
302                 m_Buffers.PushBackFast(copyResult.first);
303             }
304             else
305             {
306                 DestroyResMaterial(allocator, copyResult.first);
307                 result |= Result::MASK_FAIL_BIT;
308             }
309         }
310     }
311 
312     return result;
313 }
314 
315 //-----------------------------------------
316 ::std::pair<ResMaterial, Result>
CopyResMaterial(os::IAllocator * allocator,bit32 bufferOption)317 Material::CopyResMaterial(
318     os::IAllocator* allocator,
319     bit32 bufferOption)
320 {
321     Result result = INITIALIZE_RESULT_OK;
322 
323     ResMaterial resMaterial = this->GetOriginal();
324 
325     void* materialMemory = allocator->Alloc(sizeof(ResMaterialData));
326     if (materialMemory == NULL)
327     {
328         result |= Result::MASK_FAIL_BIT;
329         return ::std::make_pair(ResMaterial(NULL), result);
330     }
331 
332     ResMaterialData* buffer =
333         new(materialMemory) ResMaterialData(this->GetOriginal().ref());
334 
335     ResMaterial copyMaterial = ResMaterial(buffer);
336 
337     // 判定に用いるために NULL でクリアしておく
338     buffer->toName.set_ptr(NULL);
339     buffer->toShader.set_ptr(NULL);
340     buffer->m_ShaderParametersTableCount = 0;
341     buffer->toShaderParametersTable.set_ptr(NULL);
342     buffer->toTextureMappers[0].set_ptr(NULL);
343     buffer->toTextureMappers[1].set_ptr(NULL);
344     buffer->toTextureMappers[2].set_ptr(NULL);
345     buffer->toProceduralTextureMapper.set_ptr(NULL);
346     buffer->toFragmentShader.set_ptr(NULL);
347 
348     // ハッシュ無効化
349     buffer->m_AlphaTestHash = 0x0;
350     buffer->m_FragmentLightingHash = 0x0;
351     buffer->m_FragmentLightingTableHash = 0x0;
352     buffer->m_FragmentLightingTableParametersHash = 0x0;
353     buffer->m_FragmentOperationHash = 0x0;
354     buffer->m_MaterialColorHash = 0x0;
355     buffer->m_RasterizationHash = 0x0;
356     buffer->m_ShaderParametersHash = 0x0;
357     buffer->m_ShadingParameterHash = 0x0;
358     buffer->m_TextureCombinersHash = 0x0;
359     buffer->m_TextureCoordinatorsHash = 0x0;
360     buffer->m_TextureMappersHash = 0x0;
361     buffer->m_TextureSamplersHash = 0x0;
362 
363     // シェーダーパラメータのコピー
364     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_SHADER_PARAMETER))
365     {
366         buffer->m_ShaderParametersTableCount = resMaterial.GetShaderParametersCount();
367 
368         ut::Offset* offsets = NULL;
369         if (buffer->m_ShaderParametersTableCount != 0)
370         {
371             offsets = allocator->AllocAndConstruct<ut::Offset>(resMaterial.GetShaderParametersCount());
372 
373             if (offsets == NULL)
374             {
375                 result |= Result::MASK_FAIL_BIT;
376                 return ::std::make_pair(copyMaterial, result);
377             }
378 
379             buffer->toShaderParametersTable.set_ptr(offsets);
380         }
381 
382         // メモリ解放を容易にするために NULL で初期化しておく
383         for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
384         {
385             offsets[i].set_ptr(NULL);
386         }
387 
388         for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
389         {
390             ResShaderParameter resShaderParameter = resMaterial.GetShaderParameters(i);
391             ResShaderParameterValue resShaderParameterValue = resShaderParameter.GetParameter();
392 
393             const int parameterLength = resShaderParameter.GetParameterLength();
394 
395             // sizeof(ResShaderParameterData)で32ビット分の Value の領域が確保されるので-1をする。
396             void* parameterMemory = allocator->Alloc(sizeof(ResShaderParameterData) + sizeof(f32) * (parameterLength - 1));
397             if (parameterMemory == NULL)
398             {
399                 result |= Result::MASK_FAIL_BIT;
400                 return ::std::make_pair(copyMaterial, result);
401             }
402 
403             ResShaderParameterData* shaderParameter = static_cast<ResShaderParameterData*>(parameterMemory);
404             *shaderParameter = ResShaderParameterData(resShaderParameter.ref());
405 
406             for (int j = 0; j < parameterLength; ++j)
407             {
408                 shaderParameter->m_Parameter.m_Value[j] = resShaderParameterValue.ref().m_Value[j];
409             }
410 
411             offsets[i].set_ptr(shaderParameter);
412         }
413     }
414 
415     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_TEXTURE_MAPPER))
416     {
417         for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
418         {
419             ResPixelBasedTextureMapper resTextureMapper = resMaterial.GetTextureMappers(i);
420             if (resTextureMapper.IsValid())
421             {
422                 ResTextureMapper textureMapper = resTextureMapper.CloneDynamic(allocator);
423 
424                 if (!textureMapper.IsValid())
425                 {
426                     result |= Result::MASK_FAIL_BIT;
427                     return ::std::make_pair(copyMaterial, result);
428                 }
429 
430                 buffer->toTextureMappers[i].set_ptr(textureMapper.ptr());
431             }
432         }
433     }
434 
435     if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER))
436     {
437         ResProceduralTextureMapper resTextureMapper = resMaterial.GetProceduralTextureMapper();
438         if (resTextureMapper.IsValid())
439         {
440             ResTextureMapper textureMapper = resTextureMapper.CloneDynamic(allocator);
441 
442             if (!textureMapper.IsValid())
443             {
444                 result |= Result::MASK_FAIL_BIT;
445                 return ::std::make_pair(copyMaterial, result);
446             }
447 
448             buffer->toProceduralTextureMapper.set_ptr(textureMapper.ptr());
449         }
450     }
451 
452     if (ut::CheckFlagOr(bufferOption, Model::MULTI_FLAG_BUFFER_FRAGMENT_SHADER))
453     {
454         ResFragmentShader resFragmentShader = resMaterial.GetFragmentShader();
455         if (resFragmentShader.IsValid())
456         {
457             void* shaderMemory = allocator->Alloc(sizeof(ResFragmentShaderData));
458 
459             if (shaderMemory == NULL)
460             {
461                 result |= Result::MASK_FAIL_BIT;
462                 return ::std::make_pair(copyMaterial, result);
463             }
464 
465             ResFragmentShaderData* fragmentShader =
466                 new(shaderMemory) ResFragmentShaderData(resFragmentShader.ref());
467 
468             buffer->toFragmentShader.set_ptr(fragmentShader);
469 
470             // 判定に用いるために NULL でクリアしておく
471             fragmentShader->toFragmentLightingTable.set_ptr(NULL);
472 
473             if (ut::CheckFlag(bufferOption, Model::FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE))
474             {
475                 ResFragmentLightingTable resFragmentLightingTable =
476                     resFragmentShader.GetFragmentLightingTable();
477                 if (resFragmentLightingTable.IsValid())
478                 {
479                     ::std::pair<ResFragmentLightingTable, Result> copyResult =
480                         this->CopyResFragmentLightingTable(allocator, resFragmentLightingTable);
481 
482                     fragmentShader->toFragmentLightingTable.set_ptr(copyResult.first.ptr());
483 
484                     if (copyResult.second.IsFailure())
485                     {
486                         result |= Result::MASK_FAIL_BIT;
487                         return ::std::make_pair(copyMaterial, result);
488                     }
489                 }
490             }
491         }
492     }
493 
494     return ::std::make_pair(copyMaterial, result);
495 }
496 
497 //-----------------------------------------
498 void
DestroyResMaterial(os::IAllocator * allocator,ResMaterial resMaterial)499 Material::DestroyResMaterial(os::IAllocator* allocator, ResMaterial resMaterial)
500 {
501     NW_NULL_ASSERT( allocator );
502     if (resMaterial.IsValid())
503     {
504         resMaterial.Cleanup();
505 
506         DestroyResFragmentShader(allocator, resMaterial.GetFragmentShader());
507 
508         if (resMaterial.GetProceduralTextureMapper().IsValid())
509         {
510             resMaterial.GetProceduralTextureMapper().DestroyDynamic();
511         }
512 
513         for (int i = 0; i < resMaterial.GetTextureMappersCount(); i++)
514         {
515             if (resMaterial.GetTextureMappers(i).IsValid())
516             {
517                 resMaterial.GetTextureMappers(i).DestroyDynamic();
518             }
519         }
520 
521         // シェーダーパラメータのメモリ解放
522         if (resMaterial.ref().toShaderParametersTable.to_ptr() != NULL)
523         {
524             for (int i = 0; i < resMaterial.GetShaderParametersCount(); i++)
525             {
526                 DestroyResShaderParameter(allocator, resMaterial.GetShaderParameters(i));
527             }
528             allocator->Free(resMaterial.ref().toShaderParametersTable.to_ptr());
529         }
530 
531         allocator->Free(resMaterial.ptr());
532     }
533 }
534 
535 //-----------------------------------------
536 void
DestroyResFragmentShader(os::IAllocator * allocator,ResFragmentShader resFragmentShader)537 Material::DestroyResFragmentShader(
538     os::IAllocator* allocator,
539     ResFragmentShader resFragmentShader)
540 {
541     if (resFragmentShader.IsValid())
542     {
543         ResFragmentLightingTable resFragmentLightingTable = resFragmentShader.GetFragmentLightingTable();
544 
545         if (resFragmentLightingTable.IsValid())
546         {
547             if (resFragmentLightingTable.GetReflectanceRSampler().IsValid())
548             {
549                 allocator->Free(resFragmentLightingTable.GetReflectanceRSampler().GetSampler().ptr());
550                 allocator->Free(resFragmentLightingTable.GetReflectanceRSampler().ptr());
551             }
552 
553             if (resFragmentLightingTable.GetReflectanceGSampler().IsValid())
554             {
555                 allocator->Free(resFragmentLightingTable.GetReflectanceGSampler().GetSampler().ptr());
556                 allocator->Free(resFragmentLightingTable.GetReflectanceGSampler().ptr());
557             }
558 
559             if (resFragmentLightingTable.GetReflectanceBSampler().IsValid())
560             {
561                 allocator->Free(resFragmentLightingTable.GetReflectanceBSampler().GetSampler().ptr());
562                 allocator->Free(resFragmentLightingTable.GetReflectanceBSampler().ptr());
563             }
564 
565             if (resFragmentLightingTable.GetDistribution0Sampler().IsValid())
566             {
567                 allocator->Free(resFragmentLightingTable.GetDistribution0Sampler().GetSampler().ptr());
568                 allocator->Free(resFragmentLightingTable.GetDistribution0Sampler().ptr());
569             }
570 
571             if (resFragmentLightingTable.GetDistribution1Sampler().IsValid())
572             {
573                 allocator->Free(resFragmentLightingTable.GetDistribution1Sampler().GetSampler().ptr());
574                 allocator->Free(resFragmentLightingTable.GetDistribution1Sampler().ptr());
575             }
576 
577             if (resFragmentLightingTable.GetFresnelSampler().IsValid())
578             {
579                 allocator->Free(resFragmentLightingTable.GetFresnelSampler().GetSampler().ptr());
580                 allocator->Free(resFragmentLightingTable.GetFresnelSampler().ptr());
581             }
582 
583             allocator->Free(resFragmentLightingTable.ptr());
584         }
585 
586         allocator->Free(resFragmentShader.ptr());
587     }
588 }
589 
590 //-----------------------------------------
591 void
DestroyResShaderParameter(os::IAllocator * allocator,ResShaderParameter resShaderParameter)592 Material::DestroyResShaderParameter(
593     os::IAllocator* allocator,
594     ResShaderParameter resShaderParameter)
595 {
596     if (resShaderParameter.IsValid())
597     {
598         allocator->Free(resShaderParameter.ptr());
599     }
600 }
601 
602 //-----------------------------------------
603 ::std::pair<ResFragmentLightingTable, Result>
CopyResFragmentLightingTable(os::IAllocator * allocator,ResFragmentLightingTable resFragmentLightingTable)604 Material::CopyResFragmentLightingTable(
605     os::IAllocator* allocator,
606     ResFragmentLightingTable resFragmentLightingTable)
607 {
608     Result result = INITIALIZE_RESULT_OK;
609 
610     void* tableMemory = allocator->Alloc(sizeof(ResFragmentLightingTableData));
611     if (tableMemory == NULL)
612     {
613         result |= Result::MASK_FAIL_BIT;
614         return ::std::make_pair(ResFragmentLightingTable(NULL), result);
615     }
616 
617     ResFragmentLightingTableData* fragmentLightingTable =
618         new(tableMemory) ResFragmentLightingTableData(resFragmentLightingTable.ref());
619 
620     fragmentLightingTable->toReflectanceRSampler.set_ptr(NULL);
621     fragmentLightingTable->toReflectanceGSampler.set_ptr(NULL);
622     fragmentLightingTable->toReflectanceBSampler.set_ptr(NULL);
623     fragmentLightingTable->toDistribution0Sampler.set_ptr(NULL);
624     fragmentLightingTable->toDistribution1Sampler.set_ptr(NULL);
625     fragmentLightingTable->toFresnelSampler.set_ptr(NULL);
626 
627     if (resFragmentLightingTable.GetReflectanceRSampler().IsValid() && result.IsSuccess())
628     {
629         ::std::pair<ResLightingLookupTable, Result> copyResult =
630             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceRSampler());
631 
632         fragmentLightingTable->toReflectanceRSampler.set_ptr(copyResult.first.ptr());
633 
634         result |= copyResult.second;
635     }
636 
637     if (resFragmentLightingTable.GetReflectanceGSampler().IsValid() && result.IsSuccess())
638     {
639         ::std::pair<ResLightingLookupTable, Result> copyResult =
640             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceGSampler());
641 
642         fragmentLightingTable->toReflectanceGSampler.set_ptr(copyResult.first.ptr());
643 
644         result |= copyResult.second;
645     }
646 
647     if (resFragmentLightingTable.GetReflectanceBSampler().IsValid() && result.IsSuccess())
648     {
649         ::std::pair<ResLightingLookupTable, Result> copyResult =
650             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetReflectanceBSampler());
651 
652         fragmentLightingTable->toReflectanceBSampler.set_ptr(copyResult.first.ptr());
653 
654         result |= copyResult.second;
655     }
656 
657     if (resFragmentLightingTable.GetDistribution0Sampler().IsValid() && result.IsSuccess())
658     {
659         ::std::pair<ResLightingLookupTable, Result> copyResult =
660             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetDistribution0Sampler());
661 
662         fragmentLightingTable->toDistribution0Sampler.set_ptr(copyResult.first.ptr());
663 
664         result |= copyResult.second;
665     }
666 
667     if (resFragmentLightingTable.GetDistribution1Sampler().IsValid() && result.IsSuccess())
668     {
669         ::std::pair<ResLightingLookupTable, Result> copyResult =
670             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetDistribution1Sampler());
671 
672         fragmentLightingTable->toDistribution1Sampler.set_ptr(copyResult.first.ptr());
673 
674         result |= copyResult.second;
675     }
676 
677     if (resFragmentLightingTable.GetFresnelSampler().IsValid() && result.IsSuccess())
678     {
679         ::std::pair<ResLightingLookupTable, Result> copyResult =
680             this->CopyResLightingLookupTable(allocator, resFragmentLightingTable.GetFresnelSampler());
681 
682         fragmentLightingTable->toFresnelSampler.set_ptr(copyResult.first.ptr());
683 
684         result |= copyResult.second;
685     }
686 
687     return ::std::make_pair(ResFragmentLightingTable(fragmentLightingTable), result);
688 }
689 
690 //-----------------------------------------
691 ::std::pair<ResLightingLookupTable, Result>
CopyResLightingLookupTable(os::IAllocator * allocator,ResLightingLookupTable resLightingLookupTable)692 Material::CopyResLightingLookupTable(
693     os::IAllocator* allocator,
694     ResLightingLookupTable resLightingLookupTable)
695 {
696     Result result = INITIALIZE_RESULT_OK;
697 
698     void* tableMemory = allocator->Alloc(sizeof(ResLightingLookupTableData));
699 
700     if (tableMemory == NULL)
701     {
702         result |= Result::MASK_FAIL_BIT;
703         return ::std::make_pair(ResLightingLookupTable(NULL), result);
704     }
705 
706     ResLightingLookupTableData* lightingLookupTable =
707         new(tableMemory) ResLightingLookupTableData(resLightingLookupTable.ref());
708 
709     void* referenceTableMemory = allocator->Alloc(sizeof(ResReferenceLookupTableData));
710 
711     if (referenceTableMemory == NULL)
712     {
713         result |= Result::MASK_FAIL_BIT;
714         allocator->Free(lightingLookupTable);
715         return ::std::make_pair(ResLightingLookupTable(NULL), result);
716     }
717 
718     ResReferenceLookupTable sampler =
719         ut::ResStaticCast<ResReferenceLookupTable>(resLightingLookupTable.GetSampler());
720 
721     // TYPE_INFO などをコピーする。
722     ResReferenceLookupTableData* referenceLookupTable =
723         new (referenceTableMemory) ResReferenceLookupTableData(sampler.ref());
724 
725     referenceLookupTable->toTargetLut.set_ptr(sampler.GetTargetLut().ptr());
726     referenceLookupTable->toPath.set_ptr(sampler.GetPath());
727     referenceLookupTable->toTableName.set_ptr(sampler.GetTableName());
728 
729     lightingLookupTable->m_Input = resLightingLookupTable.GetInput();
730     lightingLookupTable->m_Scale = resLightingLookupTable.GetScale();
731     lightingLookupTable->toSampler.set_ptr(referenceLookupTable);
732 
733     return ::std::make_pair(ResLightingLookupTable(lightingLookupTable), result);
734 }
735 
736 //-----------------------------------------
737 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim,const ResMaterial resMaterial)738 Material::GetAnimTargetObject(const anim::ResAnimGroupMember& anim, const ResMaterial resMaterial)
739 {
740     u32 objectType = anim.GetObjectType();
741     ResMaterial mat = resMaterial;
742 
743     switch (objectType)
744     {
745     case anim::ResAnimGroupMember::OBJECT_TYPE_MATERIAL_COLOR:
746         {
747             anim::ResMaterialColorMember member = ResStaticCast<anim::ResMaterialColorMember>(anim);
748             const char* matName = member.GetMaterialName();
749 
750             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
751             ResMaterialColorData* ptr = mat.GetMaterialColor().ptr();
752             return ptr;
753         }
754 
755     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_SAMPLER:
756         {
757             anim::ResTextureSamplerMember member = ResStaticCast<anim::ResTextureSamplerMember>(anim);
758             const char* matName = member.GetMaterialName();
759             int mapperIndex = member.GetTextureMapperIndex();
760 
761             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
762 
763             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
764             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
765             // Samplerの変更を反映させるにはMapperのSetSampler()を呼ぶ必要があるので、
766             // Mapperのポインタを返す
767             ResPixelBasedTextureMapperData* ptr = mat.GetTextureMappers(mapperIndex).ptr();
768             return ptr;
769         }
770 
771     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_MAPPER:
772         {
773             anim::ResTextureMapperMember member = ResStaticCast<anim::ResTextureMapperMember>(anim);
774             const char* matName = member.GetMaterialName();
775             int mapperIndex = member.GetTextureMapperIndex();
776 
777             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
778             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
779 
780             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
781             ResPixelBasedTextureMapperData* ptr = mat.GetTextureMappers(mapperIndex).ptr();
782             return ptr;
783         }
784 
785     case anim::ResAnimGroupMember::OBJECT_TYPE_BLEND_OPERATION:
786         {
787             anim::ResBlendOperationMember member = ResStaticCast<anim::ResBlendOperationMember>(anim);
788             const char* matName = member.GetMaterialName();
789 
790             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
791             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
792 
793             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
794             ResBlendOperationData* ptr = mat.GetFragmentOperation().GetBlendOperation().ptr();
795             return ptr;
796         }
797 
798     case anim::ResAnimGroupMember::OBJECT_TYPE_TEXTURE_COORDINATOR:
799         {
800             anim::ResTextureCoordinatorMember member = ResStaticCast<anim::ResTextureCoordinatorMember>(anim);
801             const char* matName = member.GetMaterialName();
802             int coordinatorIndex = member.GetTextureCoordinatorIndex();
803 
804             //ResMaterial mat = GetMaterialOrBuffer(model, matName);
805             //member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
806 
807             member.SetResMaterialPtr(NW_ANY_TO_PTR_VALUE(mat.ptr()));
808             ResTextureCoordinatorData* ptr =mat.GetTextureCoordinators(coordinatorIndex).ptr();
809             return ptr;
810         }
811 
812     default:
813         NW_ASSERT(false);
814         return NULL;
815     }
816 }
817 
818 //-----------------------------------------
819 Result
Initialize(os::IAllocator * allocator)820 Material::Initialize(os::IAllocator* allocator)
821 {
822     Result result = INITIALIZE_RESULT_OK;
823 
824     result |= CreateBuffers(allocator);
825     NW_ENSURE_AND_RETURN(result);
826 
827     return result;
828 }
829 
830 } // namespace gfx
831 } // namespace nw
832