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