1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     TriangleSimple.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  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   $Rev: 47228 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn.h>
17 #include <nn/gx.h>
18 #include <nn/math.h>
19 #include <nn/fs.h>
20 #include <nn/init.h>
21 #include <nn/fnd/fnd_ExpHeap.h>
22 
23 #include "demo.h"
24 
25 /* buffer id */
26 GLuint s_ArrayBufferID;
27 GLuint s_ElementArrayBufferID;
28 
29 /* program id */
30 GLuint s_PgID;
31 
32 /* shader id */
33 GLuint s_ShID;
34 
35 s32 s_Count = 0;
36 
37 /* ExpHeap for app. */
38 nn::fnd::ExpHeap s_AppHeap;
39 uptr s_HeapForGx;
40 const u32 s_GxHeapSize = 0x400000;
41 
42 demo::RenderSystem s_RenderSystem;
43 
44 /* Define in gx_CaptureUtil.cpp */
45 extern int SaveDisplayBufferSD(const wchar_t *dirname, const wchar_t *filename, u32 index,
46                                GLuint addr, const u32 width, const u32 height, u8 *work = NULL);
47 extern void GetProjectionForPartialCapture(nn::math::Matrix44* pOut, nn::math::Matrix44* proj,
48                                 s32 div, s32 indexH, s32 indexV, const f32 dist, nn::math::PivotDirection pivot);
49 
50 /* generate simple object */
LoadObjects(void)51 static void LoadObjects(void)
52 {
53     GLfloat coords[] = {
54          0.5f, 0.0f, 0.f, 1.f,
55         -0.5f, 0.5f, 0.f, 1.f,
56         -0.5f,-0.5f, 0.f, 1.f
57     };
58     GLfloat color[] = {
59         1.f, 0.0f, 0.0f,
60         0.f, 1.0f, 0.0f,
61         0.f, 0.0f, 1.0f
62     };
63 
64     GLushort idxs[] = {0, 1, 2};
65 
66     glGenBuffers(1, &s_ArrayBufferID);
67     glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferID);
68     glBufferData(GL_ARRAY_BUFFER, sizeof(coords) + sizeof(color), 0, GL_STATIC_DRAW);
69     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(coords), coords);
70     glBufferSubData(GL_ARRAY_BUFFER, sizeof(coords), sizeof(color), color);
71 
72     glGenBuffers(1, &s_ElementArrayBufferID);
73     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferID);
74     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxs), idxs, GL_STATIC_DRAW);
75 
76     glEnableVertexAttribArray(0);
77     glEnableVertexAttribArray(1);
78 
79     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0) ;
80     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)sizeof(coords));
81 }
82 
DrawDisplay0(void)83 void DrawDisplay0(void)
84 {
85     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
86     s_RenderSystem.Clear();
87 
88     nn::math::Matrix44 proj;
89     nn::math::MTX44Frustum(&proj, -0.02f, 0.02f, -0.02f*nn::gx::DISPLAY0_HEIGHT/nn::gx::DISPLAY0_WIDTH,
90                  0.02f*nn::gx::DISPLAY0_HEIGHT/nn::gx::DISPLAY0_WIDTH, 0.2f, 10.f);
91     glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
92 
93     nn::math::Matrix34 eye, rot;
94     nn::math::Vector3 camPos(0.f, 0.4f, 9.5f);
95     nn::math::Vector3 camUp(0.f, 1.f, 0.f);
96     nn::math::Vector3 target(0.f, 0.f, 0.f);
97     nn::math::Vector3 rotAxis(0.f, 1.f, 0.f);
98 
99     nn::math::MTX34Identity(&eye);
100     nn::math::MTX34LookAt(&eye, &camPos, &camUp, &target);
101     nn::math::MTX34RotAxisDeg(&rot, &rotAxis, -6.f * s_Count);
102 
103     nn::math::MTX34Mult(&eye, &eye, &rot);
104     nn::math::Matrix44 mv(eye);
105     glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uModelView"), 1, GL_TRUE, (f32*)(mv));
106 
107     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
108 
109     s_RenderSystem.SwapBuffers();
110 }
111 
DrawDisplay0AndSave(void)112 void DrawDisplay0AndSave(void)
113 {
114     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
115     s_RenderSystem.Clear();
116 
117     nn::math::Matrix44 proj, tmp;
118     s32 i, j;
119 
120     s32 div = 2;
121     int currDispBuf = 0;
122 
123     // Allocate the display buffer for SD saving and then obtain the address.
124     GLuint disp[2];
125     GLint addr[2];
126 
127     nngxGenDisplaybuffers(2, disp);
128     nngxBindDisplaybuffer(disp[0]);
129     nngxDisplaybufferStorage(GL_RGB8_OES, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT, NN_GX_MEM_FCRAM);
130     nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_ADDRESS, &addr[0]);
131     nngxBindDisplaybuffer(disp[1]);
132     nngxDisplaybufferStorage(GL_RGB8_OES, nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT, NN_GX_MEM_FCRAM);
133     nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_ADDRESS, &addr[1]);
134 
135     NN_TLOG_("Start saving...\n");
136     DEMO_ASSERT_GL_ERROR();
137 
138     nn::math::Matrix34 eye, rot;
139     nn::math::Vector3 camPos(0.f, 0.4f, 9.5f);
140     nn::math::Vector3 camUp(0.f, 1.f, 0.f);
141     nn::math::Vector3 target(0.f, 0.f, 0.f);
142     nn::math::Vector3 rotAxis(0.f, 1.f, 0.f);
143 
144     nn::math::MTX34Identity(&eye);
145     nn::math::MTX34LookAt(&eye, &camPos, &camUp, &target);
146     nn::math::MTX34RotAxisDeg(&rot, &rotAxis, -6.f * s_Count);
147 
148     nn::math::MTX34Mult(&eye, &eye, &rot);
149     nn::math::Matrix44 mv(eye);
150     glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uModelView"), 1, GL_TRUE, (f32*)(mv));
151 
152     void* buf = s_AppHeap.Allocate(nn::gx::DISPLAY0_HEIGHT * nn::gx::DISPLAY0_WIDTH *3 + 54);
153 
154     // Divide into div x div and render. Transfer the color buffer to the display buffer for SD writing.
155     for (i = 0; i < div; ++i)
156     {
157         for (j = 0; j < div; ++j)
158         {
159             s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
160             // Clear the color buffer held by the RenderSystem.
161             // If the buffer is not cleared, the previous render results are sent to the display buffer each time.
162             s_RenderSystem.Clear();
163 
164             // Create the perspective projection matrix.
165             // Disable rotation using pivot since the matrix can be decomposed using the GetProjectionForPartialCapture function.
166             nn::math::MTX44Frustum(&tmp, -0.02f, 0.02f, -0.02f*nn::gx::DISPLAY0_HEIGHT/nn::gx::DISPLAY0_WIDTH,
167                  0.02f*nn::gx::DISPLAY0_HEIGHT/nn::gx::DISPLAY0_WIDTH, 0.2f, 10.f);
168 
169             GetProjectionForPartialCapture(&proj, &tmp, 2, i, j, 0.0f, nn::math::PIVOT_NONE);
170 
171             glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uProjection"), 1, GL_TRUE, static_cast<f32*>(proj));
172             glUniformMatrix4fv(glGetUniformLocation(s_PgID, "uModelView"), 1, GL_TRUE, (f32*)(mv));
173 
174             glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
175             // Render to the color buffer held by RenderSystem.
176             // Waits for rendering to finish in this function.
177             s_RenderSystem.SwapBuffers();
178 
179             // Transfers the rendering results remaining in the RenderSystem color buffer to the display buffer for SD Card writes.
180             //
181             // Immediately after RenderSystem.SwapBuffers is called, the command list is stopped (by default), so call Run.
182             // To match the state after RenderSystem.SwapBuffers is called, clear the command list and stop.
183             nngxTransferRenderImage(disp[currDispBuf], NN_GX_ANTIALIASE_NOT_USED, GL_FALSE, 0, 0);
184             nngxRunCmdlist();
185             nngxWaitCmdlistDone();
186             nngxClearCmdlist();
187             nngxStopCmdlist();
188 
189             int err;
190             err = SaveDisplayBufferSD(L"sdmc:/test", L"test", i * div + j, addr[currDispBuf],
191                                       nn::gx::DISPLAY0_WIDTH, nn::gx::DISPLAY0_HEIGHT,
192                                       (u8 *)buf);
193 
194             if (err != 0)
195             {
196                 NN_TLOG_("SaveDisplayBufferSD failed. (err: %d)\n", err);
197                 nngxDeleteDisplaybuffers(2, disp);
198                 return;
199             }
200 
201             // If the same display buffer is used repeatedly, the previously written image will be corrupted because of cache issues. Use double buffering.
202             //
203             currDispBuf = (currDispBuf == 1 ? 0 : 1);
204             NN_TLOG_("save. section (%d, %d)\n", i, j);
205         }
206     }
207     s_AppHeap.Free(buf);
208 
209     NN_TLOG_("done.\n");
210     nngxDeleteDisplaybuffers(2, disp);
211 }
212 
DrawFrame(bool isCapture)213 int DrawFrame(bool isCapture)
214 {
215     if (isCapture)
216     {
217         DrawDisplay0AndSave();
218     }
219     else
220     {
221         DrawDisplay0();
222     }
223 
224     s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
225     s_RenderSystem.Clear();
226     s_RenderSystem.SwapBuffers();
227 
228     s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
229 
230     s_Count++;
231 
232     return !glGetError();
233 }
234 
235 /* initialization */
Initialize(void)236 int Initialize(void)
237 {
238 
239     // fs initialization
240     nn::fs::Initialize();
241 
242     // Will not work without SD Card
243     nn::Result result = nn::fs::MountSdmc();
244     if (result.IsFailure())
245     {
246         NN_PANIC("SD memory card is unavailable.");
247     }
248 
249     const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
250     static char buffer[ROMFS_BUFFER_SIZE];
251     NN_UTIL_PANIC_IF_FAILED(
252         nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
253 
254     nn::hid::Initialize();
255 
256     s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() );
257     s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
258     /* Initialize display */
259     s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
260 
261     s_PgID = glCreateProgram();
262     s_ShID = glCreateShader(GL_VERTEX_SHADER);
263 
264     nn::fs::FileReader file(L"rom:/shader.shbin");
265     size_t fileSize = file.GetSize();
266     void* buf = s_AppHeap.Allocate(fileSize);
267 
268     s32 read = file.Read(buf, fileSize);
269     glShaderBinary(1, &s_ShID, GL_PLATFORM_BINARY_DMP, buf, read);
270     file.Finalize();
271     s_AppHeap.Free(buf);
272 
273     glAttachShader(s_PgID, s_ShID);
274     glAttachShader(s_PgID, GL_DMP_FRAGMENT_SHADER_DMP);
275 
276     glBindAttribLocation(s_PgID, 0, "aPosition");
277     glBindAttribLocation(s_PgID, 1, "aColor");
278 
279     glLinkProgram(s_PgID);
280     glValidateProgram(s_PgID);
281     glUseProgram(s_PgID);
282 
283     glClearColor(0.36f, 0.42f, 0.5f, 1.0f);
284     glClearDepthf(1.f);
285 
286     glEnable(GL_DEPTH_TEST);
287     glDepthFunc(GL_LESS);
288     glFrontFace(GL_CCW);
289 
290     LoadObjects();
291 
292     glUniform3i(glGetUniformLocation(s_PgID, "dmp_TexEnv[0].srcRgb"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
293     glUniform3i(glGetUniformLocation(s_PgID, "dmp_TexEnv[0].srcAlpha"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
294 
295     return 0;
296 }
297 
Finalize(void)298 void Finalize(void)
299 {
300     /* shutdown_display */
301     s_RenderSystem.Finalize();
302     s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
303     s_AppHeap.Finalize();
304 }
305