1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     SmPrimitive.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: 1 $
14  *---------------------------------------------------------------------------*/
15 #include <nn/os.h>
16 #include <nn/fs.h>
17 
18 #include <nw/types.h>
19 //#include <nw/demo.h>
20 #include <nw/dev.h>
21 #include <nw/gfx.h>
22 #include <nw/ut.h>
23 
24 #include "../include/SmDef.h"
25 #include "../include/SmPrimitive.h"
26 
27 
28 // Singleton
29 SmOgl*      s_SmOgl = NULL;
30 
31 
32 namespace
33 {
34 
35 //----------------------------------------
36 // SmOgl の初期化
InitializeSmOgl(const wchar_t * shaderName)37 SmOgl* SmOgl::InitializeSmOgl( const wchar_t* shaderName )
38 {
39      if ( s_SmOgl )
40     {
41         NW_FATAL_ERROR("SmOgl instance is exsit.\n");
42     }
43 
44     s_SmOgl = new SmOgl( shaderName );
45     NW_NULL_ASSERT( s_SmOgl );
46 
47     return s_SmOgl;
48 }
49 
50 
51 //----------------------------------------
52 // SmOgl の終了
TerminateSmOgl()53 void SmOgl::TerminateSmOgl()
54 {
55      if ( !s_SmOgl )
56     {
57         NW_FATAL_ERROR("SmOgl instance is not exsit.\n");
58     }
59 
60     delete s_SmOgl;
61     s_SmOgl = NULL;
62 }
63 
64 
65 
66 //----------------------------------------
67 // コンストラクタ
SmOgl(const wchar_t * shaderName)68 SmOgl::SmOgl( const wchar_t* shaderName )
69 : m_ProgramID( 0 ),
70   m_ShaderID( 0 )
71 {
72     NW_NULL_ASSERT( shaderName );
73 
74     m_ProjectionMatrix.Identity();
75     m_ViewMatrix.Identity();
76 
77      if ( s_SmOgl )
78     {
79         NW_FATAL_ERROR("SmOgl instance is exsit.\n");
80     }
81 
82     // シェーダファイルをロード
83     if ( !m_ShaderFile.Read( shaderName, m_Allocator ) )
84     {
85         NW_FATAL_ERROR("can not read shader file.");
86     }
87 
88     if ( m_ProgramID == 0 )
89     {
90         m_ProgramID = glCreateProgram();
91     }
92 
93     if ( m_ShaderID == 0 )
94     {
95         m_ShaderID = glCreateShader( GL_VERTEX_SHADER );
96     }
97 
98     glShaderBinary( 1, &m_ShaderID, GL_PLATFORM_BINARY_DMP, m_ShaderFile.Buffer(), m_ShaderFile.Size() );
99     NW_GL_ASSERT();
100 
101     glAttachShader( m_ProgramID, m_ShaderID );
102     glAttachShader( m_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP );
103 
104     glBindAttribLocation(m_ProgramID, SMP_ATTR_POSITION,  "aPosition");
105     glBindAttribLocation(m_ProgramID, SMP_ATTR_COLOR,     "aColor");
106     glBindAttribLocation(m_ProgramID, SMP_ATTR_OFFSET,    "aOffset");
107 
108     glLinkProgram(m_ProgramID);
109     glUseProgram(m_ProgramID);
110 
111     glEnableVertexAttribArray( SMP_ATTR_POSITION );
112     glDisableVertexAttribArray( SMP_ATTR_COLOR );
113     glDisableVertexAttribArray( SMP_ATTR_TEXCOORD0 );
114     NW_GL_ASSERT();
115 
116     // todo:understand
117     SetupMaterial();
118     SetupTexEnv();
119 
120     // インスタンスを登録
121     s_SmOgl = this;
122 
123     // 正射影マトリクスの生成
124     {
125         nw::math::MTX44OrthoPivot( &m_ProjectionMatrix, 0.f,
126                         SM_LOWER_SCREEN_SIZE_W, SM_LOWER_SCREEN_SIZE_H, 0.f, -100.f, 100.f, nw::math::PIVOT_UPSIDE_TO_TOP);
127     }
128 
129     // ビューマトリクス
130     {
131         const nw::math::VEC3 camPos(0.0f, 0.0f, 1.0f);
132         const nw::math::VEC3 aimPos(0.0f, 0.0f, 0.0f);
133         const nw::math::VEC3 camUp(0.0f, 1.0f, 0.0f);
134         nw::math::MTX34LookAt( reinterpret_cast<nw::math::MTX34*>(&m_ViewMatrix), &camPos, &camUp, &aimPos );
135     }
136 }
137 
138 
139 //----------------------------------------
140 // デストラクタ
~SmOgl()141 SmOgl::~SmOgl()
142 {
143     s_SmOgl = NULL;
144 
145     // メモリを解放
146     m_ShaderFile.Release();
147 
148     SmStaticCommandCache::DestroyCopiedCmdCache( m_CopiedCmdCache );
149     // todo:glDeleteProgoram 等
150 }
151 
152 
153 //--------------------------------------------------------------------------
154 void
SetupMaterial()155 SmOgl::SetupMaterial()
156 {
157     glDisable(GL_CULL_FACE);
158     glDisable(GL_DEPTH_TEST);
159     glDisable(GL_STENCIL_TEST);
160     glDisable(GL_BLEND);
161     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
162 }
163 
164 
165 //--------------------------------------------------------------------------
166 void
SetupTexEnv()167 SmOgl::SetupTexEnv()
168 {
169     glUniform3i(glGetUniformLocation(m_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
170     glUniform3i(glGetUniformLocation(m_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
171 }
172 
173 
174 //----------------------------------------
175 // 2D エントリ開始
SetBegin2D()176 void SmOgl::SetBegin2D()
177 {
178      if ( !m_CopiedCmdCache.IsCopied() )
179     {
180         // まずはキャッシュを生成
181         SmStaticCommandCache::StartStaticCmdCache( m_SetBeginCmd );
182         {
183             // シェーダプログラム変更
184             glUseProgram(m_ProgramID);
185 
186             // ビューやプロジェクションの変更
187             {
188                 GLint location;
189 
190                 location = glGetUniformLocation( m_ProgramID, "uProjection" );
191                 glUniform4fv( location, 4, m_ProjectionMatrix );
192 
193                 location = glGetUniformLocation( m_ProgramID, "uModelView" );
194                 glUniform4fv( location, 4, m_ViewMatrix );
195                 NW_GL_ASSERT();
196             }
197 
198             glDisable(GL_CULL_FACE);
199             glDisable(GL_DEPTH_TEST);
200             glDisable(GL_STENCIL_TEST);
201             glDisable(GL_BLEND);
202             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
203         }
204         SmStaticCommandCache::EndStaticCmdCache( m_SetBeginCmd );
205 
206         // キャッシュのコピーを生成
207         SmStaticCommandCache::CreateCopiedCmdCache( m_CopiedCmdCache );
208     }
209 
210     // todo:キャッシュに入れると、処理バーが描画されない
211     {
212             // バッファの整理
213             glBindBuffer(GL_ARRAY_BUFFER, 0);
214             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
215 
216             // 有効/無効
217             glEnableVertexAttribArray( SmOgl::SMP_ATTR_POSITION );
218             glEnableVertexAttribArray( SmOgl::SMP_ATTR_COLOR );
219             glDisableVertexAttribArray( SmOgl::SMP_ATTR_TEXCOORD0 );
220     }
221 
222     // コマンドキャッシュを利用してセット
223      if ( m_CopiedCmdCache.IsCopied() )
224     {
225         SmStaticCommandCache::UseCopiedCmdCache( m_CopiedCmdCache );
226     }
227 }
228 
229 
230 
231 
232 
233 
234 
235 
236 //----------------------------------------
237 // コンストラクタ
Sm2DPrimPC(uint vertexCnt)238 Sm2DPrimPC::Sm2DPrimPC( uint vertexCnt )
239 : m_pVertex( NULL ),
240   m_VertexCnt( vertexCnt ),
241   m_VertexUpdate( false )
242 {
243     // ASSERT:m_VertexCnt != 0
244     NW_NULL_ASSERT( m_Allocator );
245 
246     m_CopiedCmdCache.Init();
247 
248     m_pVertex = static_cast<SmVertexPC*>(m_Allocator->Alloc( sizeof( SmVertexPC ) * m_VertexCnt ));
249     NW_NULL_ASSERT( m_pVertex );
250 }
251 
252 
253 //----------------------------------------
254 // デストラクタ
~Sm2DPrimPC()255 Sm2DPrimPC::~Sm2DPrimPC()
256 {
257     SmStaticCommandCache::DestroyCopiedCmdCache( m_CopiedCmdCache );
258     nw::os::SafeFree( m_pVertex, m_Allocator );
259 }
260 
261 
262 //----------------------------------------
263 // 現在積まれている頂点で更新する
Update()264 void Sm2DPrimPC::Update()
265 {
266 
267 }
268 
269 
270 //----------------------------------------
271 // 描画
Render(GLenum entryMode,f32 posX,f32 posY)272 void Sm2DPrimPC::Render( GLenum entryMode, f32 posX, f32 posY )
273 {
274     // オフセット位置
275     {
276         nw::math::VEC4 offset;
277         offset.x = posX;
278         offset.y = posY;
279         offset.z = 0.f;
280         offset.w = 0.f;
281         glVertexAttrib4fv( SmOgl::SMP_ATTR_OFFSET, offset );
282     }
283 
284     // コマンドキャッシュコピーを生成する
285      if ( m_VertexUpdate )
286     {
287         // まずはキャッシュを生成
288         SmStaticCommandCache::StartStaticCmdCache( m_CmdCache );
289         {
290             RenderSub( entryMode );
291         }
292         SmStaticCommandCache::EndStaticCmdCache( m_CmdCache );
293 
294         // 生成済みがあれば破棄
295          if ( m_CopiedCmdCache.IsCopied() )
296         {
297             SmStaticCommandCache::DestroyCopiedCmdCache( m_CopiedCmdCache );
298         }
299 
300         // キャッシュのコピーを生成
301         SmStaticCommandCache::CreateCopiedCmdCache( m_CopiedCmdCache );
302 
303         m_VertexUpdate = false;
304     }
305 
306     // コマンドキャッシュを利用して描画
307      if ( m_CopiedCmdCache.IsCopied() )
308     {
309         SmStaticCommandCache::UseCopiedCmdCache( m_CopiedCmdCache );
310     }
311     else
312     {
313         RenderSub( entryMode );
314     }
315 
316     NW_GL_ASSERT();
317 }
318 
319 
320 //----------------------------------------
321 // 描画 下請け
RenderSub(GLenum entryMode)322 void Sm2DPrimPC::RenderSub( GLenum entryMode )
323 {
324     // 基準のアドレス
325     const u8* basePtr = reinterpret_cast<u8*>(m_pVertex);
326 
327     // position
328     glVertexAttribPointer( SmOgl::SMP_ATTR_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(SmVertexPC), basePtr );
329 
330     // color
331     glVertexAttribPointer( SmOgl::SMP_ATTR_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(SmVertexPC), basePtr + offsetof(SmVertexPC, color) );
332 
333     // draw
334     glDrawArrays( entryMode, 0, m_VertexCnt );
335 
336     NW_GL_ASSERT();
337 }
338 
339 
340 //----------------------------------------
341 // 頂点を登録する
SetVertex(uint vertexIdx,f32 x,f32 y,nw::ut::Color8 color)342 void Sm2DPrimPC::SetVertex( uint vertexIdx, f32 x, f32 y, nw::ut::Color8 color )
343 {
344     NW_ASSERT( m_VertexCnt > vertexIdx );
345 
346     m_pVertex[vertexIdx].position.x = x;
347     m_pVertex[vertexIdx].position.y = y;
348 
349     m_pVertex[vertexIdx].color      = color;
350 }
351 
352 //----------------------------------------
353 // 頂点カラーを登録する
SetVertexColor(nw::ut::Color8 color)354 void Sm2DPrimPC::SetVertexColor( nw::ut::Color8 color )
355 {
356     uint i = 0;
357 
358     for ( i = 0; i < m_VertexCnt; i ++ )
359     {
360         m_pVertex[i].color = color;
361     }
362 }
363 
364 
365 
366 
367 //----------------------------------------
368 // コンストラクタ
Sm2DDynamicPrimPC()369 Sm2DDynamicPrimPC::Sm2DDynamicPrimPC()
370 : m_pPrimitive( NULL ),
371   m_VertexCnt( 0 ),
372   m_EntryCnt( 0 ),
373   m_EntryMode( 0 ),
374   m_OffsetX( 0.f ),
375   m_OffsetY( 0.f ){}
376 
377 
378 //----------------------------------------
379 // エントリ開始
Begin(uint vertexCnt,GLenum entryMode,f32 posX,f32 posY)380 bool Sm2DDynamicPrimPC::Begin(  uint                vertexCnt,
381                                 GLenum              entryMode,
382                                 f32                 posX,
383                                 f32                 posY )
384 {
385      if ( m_pPrimitive ) return false;
386      if ( vertexCnt == 0 ) return false;
387 
388     m_pPrimitive = new Sm2DPrimPC( vertexCnt );
389     NW_NULL_ASSERT( m_pPrimitive );
390 
391     m_EntryCnt = 0;
392     m_VertexCnt = vertexCnt;
393     m_EntryMode = entryMode;
394     m_OffsetX   = posX;
395     m_OffsetY   = posY;
396 
397     return true;
398 }
399 
400 
401 //----------------------------------------
402 // 頂点を登録する
SetVertex(f32 x,f32 y,nw::ut::Color8 color)403 void Sm2DDynamicPrimPC::SetVertex( f32 x, f32 y, nw::ut::Color8 color )
404 {
405     m_pPrimitive->SetVertex( m_EntryCnt, x, y, color );
406     m_EntryCnt++;
407 }
408 
409 
410 //----------------------------------------
411 // エントリ終了
End()412 void Sm2DDynamicPrimPC::End()
413 {
414      if ( m_VertexCnt != m_EntryCnt ) return;
415 
416     m_pPrimitive->Render( m_EntryMode, m_OffsetX, m_OffsetY );
417 
418     delete m_pPrimitive;
419     m_pPrimitive = NULL;
420 }
421 
422 } // namespace
423 
424 
425