1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     lyt_GraphicsResource.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: 31411 $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 
20 #include <nw/lyt/lyt_GraphicsResource.h>
21 #include <nw/lyt/lyt_Common.h>
22 #include <nw/lyt/lyt_Layout.h>
23 #include <nw/lyt/lyt_Stopwatch.h>
24 
25 #if defined(NW_PLATFORM_CTRWIN)
26 #include    <cstdlib>
27 #endif
28 
29 #define ARRAY_LENGTH(a)   (sizeof(a) / sizeof((a)[0]))
30 
31 namespace nw
32 {
33 namespace lyt
34 {
35 
36 namespace
37 {
38 
39 enum ResouceFileID
40 {
41     RESOURCEFILEID_RECTDRAWERSHADER,
42 #ifdef NW_LYT_DMPGL_ENABLED
43     RESOURCEFILEID_FONTSHADER,
44     RESOURCEFILEID_PANESHADER,
45     RESOURCEFILEID_CONSTCOLORSHADER,
46 #endif
47 
48     RESOURCEFILEID_MAX
49 };
50 
51 const wchar_t* sResourceFiles[] =
52 {
53     L"/shaders/nwfont_RectDrawerShader.shbin",
54 #ifdef NW_LYT_DMPGL_ENABLED
55     L"/shaders/nwfont_TextWriterShader.shbin",
56     L"/shaders/nwlyt_PaneShader.shbin",
57     L"/shaders/nwlyt_ConstColorShader.shbin",
58 #endif
59 };
60 
61 NW_COMPILER_ASSERT(ARRAY_LENGTH(sResourceFiles) == RESOURCEFILEID_MAX);
62 
63 wchar_t sResourcePaths[RESOURCEFILEID_MAX][FILENAME_MAX];
64 bool sResourcePathsInitialized = false;
65 
66 #ifdef NW_TARGET_CTR_GL_FINAL
67   #define FEATURE_FINAL(x) x
68 #else
69   #define FEATURE_FINAL(x) NULL
70 #endif
71 
72 #ifdef NW_LYT_DMPGL_ENABLED
73 const char* s_UniformNames[] =
74 {
75     "uProjection",
76     "uModelView",
77     "uTexMtx0",
78     "uTexMtx1",
79     "uTexMtx2",
80     "uColor",
81     "uTransform",
82     "uFrameSpec",
83     "uVertexColor",
84     "uVertexTexCoord0",
85     "uVertexTexCoord1",
86     "uVertexTexCoord2",
87     "uRcpTexSize0",
88     "dmp_Texture[0].samplerType",
89     "dmp_Texture[1].samplerType",
90     "dmp_Texture[2].samplerType",
91     "dmp_Texture[3].samplerType",
92     "dmp_TexEnv[0].combineRgb",
93     "dmp_TexEnv[1].combineRgb",
94     "dmp_TexEnv[2].combineRgb",
95     FEATURE_FINAL("dmp_TexEnv[3].combineRgb"),
96     FEATURE_FINAL("dmp_TexEnv[4].combineRgb"),
97     FEATURE_FINAL("dmp_TexEnv[5].combineRgb"),
98     "dmp_TexEnv[0].combineAlpha",
99     "dmp_TexEnv[1].combineAlpha",
100     "dmp_TexEnv[2].combineAlpha",
101     FEATURE_FINAL("dmp_TexEnv[3].combineAlpha"),
102     FEATURE_FINAL("dmp_TexEnv[4].combineAlpha"),
103     FEATURE_FINAL("dmp_TexEnv[5].combineAlpha"),
104     "dmp_TexEnv[0].srcRgb",
105     "dmp_TexEnv[1].srcRgb",
106     "dmp_TexEnv[2].srcRgb",
107     FEATURE_FINAL("dmp_TexEnv[3].srcRgb"),
108     FEATURE_FINAL("dmp_TexEnv[4].srcRgb"),
109     FEATURE_FINAL("dmp_TexEnv[5].srcRgb"),
110     "dmp_TexEnv[0].srcAlpha",
111     "dmp_TexEnv[1].srcAlpha",
112     "dmp_TexEnv[2].srcAlpha",
113     FEATURE_FINAL("dmp_TexEnv[3].srcAlpha"),
114     FEATURE_FINAL("dmp_TexEnv[4].srcAlpha"),
115     FEATURE_FINAL("dmp_TexEnv[5].srcAlpha"),
116     "dmp_TexEnv[0].operandRgb",
117     "dmp_TexEnv[1].operandRgb",
118     "dmp_TexEnv[2].operandRgb",
119     FEATURE_FINAL("dmp_TexEnv[3].operandRgb"),
120     FEATURE_FINAL("dmp_TexEnv[4].operandRgb"),
121     FEATURE_FINAL("dmp_TexEnv[5].operandRgb"),
122     "dmp_TexEnv[0].operandAlpha",
123     "dmp_TexEnv[1].operandAlpha",
124     "dmp_TexEnv[2].operandAlpha",
125     FEATURE_FINAL("dmp_TexEnv[3].operandAlpha"),
126     FEATURE_FINAL("dmp_TexEnv[4].operandAlpha"),
127     FEATURE_FINAL("dmp_TexEnv[5].operandAlpha"),
128     "dmp_TexEnv[0].scaleRgb",
129     "dmp_TexEnv[1].scaleRgb",
130     "dmp_TexEnv[2].scaleRgb",
131     FEATURE_FINAL("dmp_TexEnv[3].scaleRgb"),
132     FEATURE_FINAL("dmp_TexEnv[4].scaleRgb"),
133     FEATURE_FINAL("dmp_TexEnv[5].scaleRgb"),
134     "dmp_TexEnv[0].scaleAlpha",
135     "dmp_TexEnv[1].scaleAlpha",
136     "dmp_TexEnv[2].scaleAlpha",
137     FEATURE_FINAL("dmp_TexEnv[3].scaleAlpha"),
138     FEATURE_FINAL("dmp_TexEnv[4].scaleAlpha"),
139     FEATURE_FINAL("dmp_TexEnv[5].scaleAlpha"),
140     "dmp_TexEnv[0].constRgba",
141     "dmp_TexEnv[1].constRgba",
142     "dmp_TexEnv[2].constRgba",
143     FEATURE_FINAL("dmp_TexEnv[3].constRgba"),
144     FEATURE_FINAL("dmp_TexEnv[4].constRgba"),
145     FEATURE_FINAL("dmp_TexEnv[5].constRgba"),
146     FEATURE_FINAL("dmp_TexEnv[0].bufferColor"),
147     FEATURE_FINAL("dmp_TexEnv[1].bufferInput"),
148     FEATURE_FINAL("dmp_TexEnv[2].bufferInput"),
149     FEATURE_FINAL("dmp_TexEnv[3].bufferInput"),
150     FEATURE_FINAL("dmp_TexEnv[4].bufferInput"),
151     "dmp_FragOperation.enableAlphaTest",
152     "dmp_FragOperation.alphaRefValue",
153     "dmp_FragOperation.alphaTestFunc",
154 };
155 NW_COMPILER_ASSERT(ARRAY_LENGTH(s_UniformNames) == GraphicsResource::UNIFORM_MAX);
156 #endif // NW_LYT_DMPGL_ENABLED
157 
StrCopy(wchar_t * dst,const wchar_t * src)158 wchar_t* StrCopy(wchar_t* dst, const wchar_t* src)
159 {
160     NW_NULL_ASSERT(dst);
161     NW_NULL_ASSERT(src);
162 
163     size_t i = 0;
164     for (; src[i] != L'\0'; ++i)
165     {
166         dst[i] = src[i];
167     }
168 
169     dst[i] = src[i];
170 
171     return dst + i;
172 }
173 
174 } // namespace
175 
GraphicsResource()176 GraphicsResource::GraphicsResource()
177 : m_pRectShaderBinary(NULL)
178 , m_RectShaderBinarySize(0)
179 #ifdef NW_LYT_DMPGL_ENABLED
180 , m_GlProgram(0)
181 , m_GlProgramDebug(0)
182 #endif
183 , m_Initialized(false)
184 {
185 }
186 
~GraphicsResource()187 GraphicsResource::~GraphicsResource()
188 {
189     this->Finalize();
190 }
191 
192 void
Finalize()193 GraphicsResource::Finalize()
194 {
195     if (!m_Initialized)
196     {
197         return;
198     }
199 
200     m_Initialized = false;
201 
202 #ifdef NW_LYT_DMPGL_ENABLED
203     glUseProgram(0);
204 
205     glDeleteProgram(m_GlProgram);
206     m_GlProgram = 0;
207 
208     glDeleteProgram(m_GlProgramDebug);
209     m_GlProgramDebug = 0;
210 
211     glDeleteBuffers(this->VBO_MAX, m_GlVertexBufferObject);
212 #endif
213 
214     if (NULL != m_pRectShaderBinary)
215     {
216         Layout::FreeMemory(m_pRectShaderBinary);
217     }
218     m_pRectShaderBinary = NULL;
219     m_RectShaderBinarySize = 0;
220 
221     m_TextWriter.SetTextWriterResource(0);
222     m_TextWriterResource.DeleteResource();
223 }
224 
225 const wchar_t*
GetResourcePath(int index)226 GraphicsResource::GetResourcePath(int index)
227 {
228     if (!sResourcePathsInitialized)
229     {
230 #if defined(NW_PLATFORM_CTR)
231         static const wchar_t* pResourceRoot = L"rom:";
232         for (int i = 0; i < RESOURCEFILEID_MAX; ++i)
233         {
234             wchar_t* buff = sResourcePaths[i];
235             buff = StrCopy(buff, pResourceRoot);
236             buff = StrCopy(buff, sResourceFiles[i]);
237         }
238 #endif
239 
240 #if defined(NW_PLATFORM_CTRWIN)
241         for (int i = 0; i < RESOURCEFILEID_MAX; ++i)
242         {
243             wchar_t* buff = sResourcePaths[i];
244             size_t bufferSize = 0;
245             _wgetenv_s(&bufferSize, buff, FILENAME_MAX, L"NW4C_ROOT");
246             NW_ASSERT(bufferSize > 0);
247             buff = StrCopy(buff + bufferSize - 1, sResourceFiles[i]);
248         }
249 #endif
250 
251         sResourcePathsInitialized = true;
252     }
253 
254     if (0 <= index && index < RESOURCEFILEID_MAX)
255     {
256         return sResourcePaths[index];
257     }
258     else
259     {
260         return NULL;
261     }
262 }
263 
264 void
SetResource(int index,void * content,u32 fileSize,bool bFree)265 GraphicsResource::SetResource(int index, void* content, u32 fileSize, bool bFree)
266 {
267     NW_MINMAX_ASSERT(index, 0, RESOURCEFILEID_MAX - 1);
268     NW_NULL_ASSERT(content);
269     NW_ASSERT(fileSize > 0);
270 
271     switch (index)
272     {
273     case RESOURCEFILEID_RECTDRAWERSHADER:
274         {
275             m_pRectShaderBinary = Layout::AllocMemory(fileSize);
276             NW_NULL_ASSERT(m_pRectShaderBinary);
277             m_RectShaderBinarySize = fileSize;
278             std::memcpy(m_pRectShaderBinary, content, fileSize);
279             if (bFree)
280             {
281                 Layout::FreeMemory(content);
282             }
283             return;
284         }
285 
286 #ifdef NW_LYT_DMPGL_ENABLED
287 
288     case RESOURCEFILEID_FONTSHADER:
289         {
290             m_TextWriterResource.InitResource(static_cast<u8*>(content), fileSize);
291             m_TextWriter.SetTextWriterResource(&m_TextWriterResource);
292             NW_GL_ASSERT();
293 
294             if (bFree)
295             {
296                 Layout::FreeMemory(content);
297             }
298             return;
299         }
300 
301     case RESOURCEFILEID_PANESHADER:
302         {
303             m_GlProgram = glCreateProgram();
304             NW_ASSERT(m_GlProgram != 0);
305             NW_GL_ASSERT();
306 
307             GLuint shader = glCreateShader(GL_VERTEX_SHADER);
308             NW_ASSERT(shader != 0);
309             NW_GL_ASSERT();
310 
311             glShaderBinary(1, &shader, GL_PLATFORM_BINARY_DMP, content, fileSize);
312             NW_GL_ASSERT();
313 
314             glAttachShader(m_GlProgram, shader);
315             glAttachShader(m_GlProgram, GL_DMP_FRAGMENT_SHADER_DMP);
316             NW_GL_ASSERT();
317 
318             // プログラムが削除されたらシェーダも削除されるように。
319             glDeleteShader(shader);
320             NW_GL_ASSERT();
321 
322             glBindAttribLocation(m_GlProgram, VERTEXATTR_VERTEX_INDEX, "aVertexIndex");
323             NW_GL_ASSERT();
324 
325             glLinkProgram(m_GlProgram);
326             NW_GL_ASSERT();
327 
328             glUseProgram(m_GlProgram);
329             // フラグメントシェーダを標準モードに設定。
330             glUniform1i(glGetUniformLocation(m_GlProgram, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GL_DMP);
331             // ライティングを無効化。
332             glUniform1i(glGetUniformLocation(m_GlProgram, "dmp_FragmentLighting.enabled"), GL_FALSE);
333             NW_GL_ASSERT();
334 
335             if (bFree)
336             {
337                 Layout::FreeMemory(content);
338             }
339             return;
340         }
341 
342     case RESOURCEFILEID_CONSTCOLORSHADER:
343         {
344             m_GlProgramDebug = glCreateProgram();
345             NW_ASSERT(m_GlProgramDebug != 0);
346             NW_GL_ASSERT();
347 
348             GLuint shader = glCreateShader(GL_VERTEX_SHADER);
349             NW_ASSERT(shader != 0);
350             NW_GL_ASSERT();
351 
352             glShaderBinary(1, &shader, GL_PLATFORM_BINARY_DMP, content, fileSize);
353             NW_GL_ASSERT();
354 
355             glAttachShader(m_GlProgramDebug, shader);
356             glAttachShader(m_GlProgramDebug, GL_DMP_FRAGMENT_SHADER_DMP);
357             NW_GL_ASSERT();
358 
359             // プログラムが削除されたらシェーダも削除されるように。
360             glDeleteShader(shader);
361             NW_GL_ASSERT();
362 
363             glBindAttribLocation(m_GlProgramDebug, VERTEXATTR_POS, "aPosition");
364             NW_GL_ASSERT();
365 
366             glLinkProgram(m_GlProgramDebug);
367             NW_GL_ASSERT();
368 
369             if (bFree)
370             {
371                 Layout::FreeMemory(content);
372             }
373             return;
374         }
375 
376 #endif // NW_LYT_DMPGL_ENABLED
377 
378     default:
379         NW_FATAL_ERROR("not implemented (%d).", index);
380     }
381 }
382 
383 void
StartSetup()384 GraphicsResource::StartSetup()
385 {
386     NW_ASSERT(!m_Initialized);
387 }
388 
389 bool
FinishSetup()390 GraphicsResource::FinishSetup()
391 {
392     NW_NULL_ASSERT(m_pRectShaderBinary);
393 
394 #ifdef NW_LYT_DMPGL_ENABLED
395 
396     NW_ASSERT(m_GlProgram != 0);
397     NW_ASSERT(m_GlProgramDebug != 0);
398 
399     math::MTX34Identity(&m_MtxModelView);
400 
401     this->InitVBO();
402 
403     for (int i = 0; i < this->UNIFORM_MAX; ++i)
404     {
405         if (s_UniformNames[i] == NULL)
406         {
407             m_UniformLocation[i] = 0;
408         }
409         else
410         {
411             m_UniformLocation[i] = glGetUniformLocation(m_GlProgram, s_UniformNames[i]);
412         }
413     }
414     NW_GL_ASSERT();
415 
416 #endif // NW_LYT_DMPGL_ENABLED
417 
418     m_Initialized = true;
419 
420     return true;
421 }
422 
423 #ifdef NW_LYT_DMPGL_ENABLED
424 
425 void
SetProjectionMtx(const nw::math::MTX44 & mtx)426 GraphicsResource::SetProjectionMtx(const nw::math::MTX44& mtx)
427 {
428     NW_ASSERT(this->Initialized());
429 
430     GLuint program = 0;
431 
432     program = this->GetGlProgram();
433     glUseProgram(program);
434     glUniformMatrix4fv(this->GetUniformLocation(this->UNIFORM_uProjection), 1, GL_TRUE, mtx.a);
435     NW_GL_ASSERT();
436 
437     program = this->GetGlProgramDebug();
438     glUseProgram(program);
439     glUniformMatrix4fv(glGetUniformLocation(program, "uProjection"), 1, GL_TRUE, mtx.a);
440     NW_GL_ASSERT();
441 
442     m_TextWriterResource.ActiveGlProgram();
443     m_TextWriterResource.SetProjectionMtx(mtx);
444     NW_GL_ASSERT();
445 }
446 
ResetGlProgramState()447 void GraphicsResource::ResetGlProgramState()
448 {
449     this->SetNumTexEnv(internal::TexEnvUnitMax);
450     this->SetTexEnvAuto(false);
451 }
452 
ResetGlState()453 void GraphicsResource::ResetGlState()
454 {
455     m_FirstDraw = true;
456 }
457 
458 void
ActiveVBO()459 GraphicsResource::ActiveVBO()
460 {
461     // 頂点インデックス
462     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->GetVBO(this->VBO_ELEMENT));
463 
464     // 頂点座標
465     glBindBuffer(GL_ARRAY_BUFFER, this->GetVBO(this->VBO_VERTEX_INDEX));
466     glEnableVertexAttribArray(VERTEXATTR_VERTEX_INDEX);
467     glVertexAttribPointer(VERTEXATTR_VERTEX_INDEX, VERTEXATTRSIZE_INDEX, GL_SHORT, GL_FALSE, 0, NULL);
468 }
469 
470 #endif // NW_LYT_DMPGL_ENABLED
471 
472 } // namespace nw::lyt
473 } // namespace nw
474