1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ResVertex.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/ut/ut_ResUtil.h>
21 #include <nw/ut/ut_ResDictionary.h>
22 #include <nw/gfx/gfx_SceneObject.h>
23 #include <nw/gfx/res/gfx_ResVertex.h>
24 #include <nw/gfx/gfx_Common.h>
25 #include <GLES2/gl2.h>
26 
27 #include <nn/gx.h>
28 
29 namespace nw {
30 namespace gfx {
31 namespace res {
32 
33 //---------------------------------------------------------------------------
34 //! @brief        必要であれば頂点バッファのコピー用のメモリを確保し、転送をおこないます。
35 //!
36 //! @param[in]    bufferID     メモリ確保用の頂点バッファIDです。
37 //! @param[in]    resStream    頂点ストリームリソースです。
38 //! @param[in]    loadFlag     頂点バッファの配置メモリフラグです。
39 //---------------------------------------------------------------------------
40 static void
BufferData(u32 bufferID,ResVertexStreamBase resStream,u32 loadFlag)41 BufferData( u32 bufferID, ResVertexStreamBase resStream, u32 loadFlag )
42 {
43     u32 size = resStream.GetStreamCount();
44     GLenum transtype = loadFlag & 0xFFFF0000;
45     void* address = NULL;
46     const u32 NN_GX_MEM_MASK = 0x00030000;
47 
48     switch (transtype)
49     {
50     case (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP):
51         nngxUpdateBuffer( resStream.GetStream(), size );
52         break;
53 
54     case (NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP):
55     case (NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP):
56         {
57             GLuint area = (transtype & NN_GX_MEM_MASK);
58             address = __dmpgl_allocator(area, NN_GX_MEM_VERTEXBUFFER, bufferID, size);
59             nngxAddVramDmaCommand( resStream.GetStream(), address, size );
60 
61             resStream.SetLocationAddress( address );
62             resStream.ref().m_MemoryArea = area;
63         }
64         break;
65 
66     case (NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP):
67         {
68             address = __dmpgl_allocator(NN_GX_MEM_FCRAM, NN_GX_MEM_VERTEXBUFFER, bufferID, size);
69             nw::os::MemCpy( address, resStream.GetStream(), size );
70             nngxUpdateBuffer( address, size );
71 
72             resStream.SetLocationAddress( address );
73             resStream.ref().m_MemoryArea = NN_GX_MEM_FCRAM;
74         }
75         break;
76 
77     case (NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP):
78     case (NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP):
79         NW_FATAL_ERROR("GL_COPY_DMA is not supported!");
80         break;
81 
82     default:
83         break;
84     }
85 }
86 
87 static void
DeleteBuffer(u32 bufferID,ResVertexStreamBase resStream)88 DeleteBuffer( u32 bufferID, ResVertexStreamBase resStream )
89 {
90     GLuint area = resStream.ref().m_MemoryArea;
91 
92     if (area != ResVertexStreamBaseData::AREA_NO_MALLOC)
93     {
94         void* address = reinterpret_cast<void*>( resStream.GetLocationAddress() );
95         __dmpgl_deallocator( area, NN_GX_MEM_VERTEXBUFFER, bufferID, address );
96         resStream.SetLocationAddress( static_cast<u32>(NULL) );
97     }
98 }
99 
100 
101 //-----------------------------------------------------------------------------
102 void
Setup()103 ResVertexAttribute::Setup()
104 {
105     NW_ASSERT( this->IsValid() );
106 
107     if ( this->GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM )
108     {
109         ResStaticCast<ResVertexParamAttribute>( *this ).Setup();
110     }
111     else if ( this->GetFlags() & ResVertexAttributeData::FLAG_INTERLEAVE )
112     {
113         ResStaticCast<ResInterleavedVertexStream>( *this ).Setup();
114     }
115     else
116     {
117         ResStaticCast<ResVertexStream>( *this ).Setup();
118     }
119 }
120 
121 //-----------------------------------------------------------------------------
122 void
Cleanup()123 ResVertexAttribute::Cleanup()
124 {
125     NW_ASSERT( this->IsValid() );
126 
127     if ( this->GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM )
128     {
129         ResStaticCast<ResVertexParamAttribute>( *this ).Cleanup();
130     }
131     else if ( this->GetFlags() & ResVertexAttributeData::FLAG_INTERLEAVE )
132     {
133         ResStaticCast<ResInterleavedVertexStream>(*this).Cleanup();
134     }
135     else
136     {
137         ResStaticCast<ResVertexStream>(*this).Cleanup();
138     }
139 }
140 
141 //----------------------------------------------------------
142 u32
GetVertexCount()143 ResVertexAttribute::GetVertexCount()
144 {
145     NW_ASSERT( this->IsValid() );
146 
147     if ( this->GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM )
148     {
149         // 頂点を持っていないので 0 を返す。
150         return 0;
151     }
152     else if ( this->GetFlags() & ResVertexAttributeData::FLAG_INTERLEAVE )
153     {
154         ResInterleavedVertexStream stream =
155             ResStaticCast<ResInterleavedVertexStream>( *this );
156         return stream.GetStreamCount() / stream.GetStride();
157     }
158     else
159     {
160         ResVertexStream stream = ResStaticCast<ResVertexStream>( *this );
161 
162         size_t sizePerVertex;
163         switch (stream.GetFormatType())
164         {
165         case GL_BYTE:
166         case GL_UNSIGNED_BYTE:
167             sizePerVertex = 1;
168             break;
169         case GL_SHORT:
170             // case GL_UNSIGNED_SHORT: 対応していない。
171             sizePerVertex = 2;
172             break;
173         case GL_INT:
174         case GL_UNSIGNED_INT:
175         case GL_FLOAT:
176             sizePerVertex = 4;
177             break;
178         default:
179             NW_FATAL_ERROR("Unsupported format\n");
180         }
181 
182         sizePerVertex *= stream.GetDimension();
183 
184         return stream.GetStreamCount() / sizePerVertex;
185     }
186 }
187 
188 //-----------------------------------------------------------------------------
189 void
Setup()190 ResVertexParamAttribute::Setup()
191 {
192 }
193 
194 //-----------------------------------------------------------------------------
195 void
Cleanup()196 ResVertexParamAttribute::Cleanup()
197 {
198 }
199 
200 //-----------------------------------------------------------------------------
201 void
Setup()202 ResVertexStream::Setup()
203 {
204     if (ref().m_BufferObject)
205     {
206         return;
207     }
208 
209     ResVertexStreamData* dataPtr = ptr();
210     u32 bufferID = reinterpret_cast<u32>( dataPtr );
211     this->ref().m_BufferObject = bufferID;
212 
213     // 既にアドレスが設定されている場合にはデータのコピーをおこなわない。
214     if (this->GetLocationAddress() != NULL)
215     {
216         ref().m_MemoryArea = ResVertexStreamBaseData::AREA_NO_MALLOC;
217         return;
218     }
219 
220     u32 size = this->GetStreamCount();
221 
222     // 頂点バッファのメモリへの読み込み指定
223     int loadFlag = this->GetLocationFlag();
224 
225     // デフォルトは、FCRAM から NO_COPY。
226     if (loadFlag == 0)
227     {
228         loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
229     }
230 
231     BufferData( bufferID, *this, loadFlag );
232 }
233 
234 //-----------------------------------------------------------------------------
235 void
Cleanup()236 ResVertexStream::Cleanup()
237 {
238     GLuint bufferID = this->GetBufferObject();
239 
240     if ( bufferID == 0 )
241     {
242         return;
243     }
244 
245     DeleteBuffer( bufferID, *this );
246     this->SetBufferObject( 0 );
247 }
248 
249 //-----------------------------------------------------------------------------
250 void
Setup()251 ResInterleavedVertexStream::Setup()
252 {
253     if (ref().m_BufferObject)
254     {
255         return;
256     }
257 
258     u32 bufferID = reinterpret_cast<u32>( this->ptr() );
259     this->ref().m_BufferObject = bufferID;
260 
261     // 既にアドレスが設定されている場合にはデータのコピーをおこなわない。
262     if ( this->GetLocationAddress() != NULL )
263     {
264         ref().m_MemoryArea = ResVertexStreamBaseData::AREA_NO_MALLOC;
265         return;
266     }
267 
268     u32 size = this->GetStreamCount();
269 
270     // 頂点バッファのメモリへの読み込み指定
271     int loadFlag = this->GetLocationFlag();
272 
273     // デフォルトは、FCRAM から NO_COPY。
274     if (loadFlag == 0)
275     {
276         loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
277     }
278 
279     BufferData( bufferID, *this, loadFlag );
280 }
281 
282 //-----------------------------------------------------------------------------
283 void
Cleanup()284 ResInterleavedVertexStream::Cleanup()
285 {
286     GLuint bufferID = this->GetBufferObject();
287 
288     if ( bufferID == 0 )
289     {
290         return;
291     }
292 
293     DeleteBuffer( bufferID, *this );
294     this->SetBufferObject( 0 );
295 }
296 
297 
298 //----------------------------------------------------------
299 u32
GetVertexCount()300 ResIndexStream::GetVertexCount()
301 {
302     NW_ASSERT( this->IsValid() );
303 
304     size_t sizePerVertex;
305     switch (this->GetFormatType())
306     {
307     case GL_BYTE:
308     case GL_UNSIGNED_BYTE:
309         sizePerVertex = 1;
310         break;
311     case GL_SHORT:
312         // case GL_UNSIGNED_SHORT: 対応していない。
313         sizePerVertex = 2;
314         break;
315     case GL_INT:
316     case GL_UNSIGNED_INT:
317     case GL_FLOAT:
318         sizePerVertex = 4;
319         break;
320     default:
321         NW_FATAL_ERROR("Unsupported format\n");
322     }
323 
324     return this->GetStreamCount() / sizePerVertex;
325 }
326 
327 } /* namespace res */
328 } /* namespace gfx */
329 } /* namespace nw */
330 
331