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