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