1 /*---------------------------------------------------------------------------*
2 
3   Copyright 2014 Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <math.h>
16 
17 #if defined(WIN32) || defined(WIN64)
18 #include <pc/gx2.h>
19 #include <pc/demo.h>
20 #endif
21 #include <cafe/os.h>
22 #include <cafe/mem.h>
23 #include <cafe/gx2.h>
24 #include <cafe/demo.h>
25 
26 #include <cafe/gfd.h>
27 #include <cafe/gx2ut.h>
28 
29 //Include generated shaders
30 #include "shaders/headers/gx2utExpandColor.h"
31 
32 
33 // ----- GX2 Shader
34 static const GX2VertexShader* const VS_SHADERS[] = { &gx2utExpandColor_VS,};
35 
36 static const GX2PixelShader* const PS_SHADERS[] = { &gx2utExpandColor_PS,
37 };
38 
39 static const u32 NUM_SHADERS = 1;
40 
41 typedef struct _ExpandColorShader {
42     // These variables hold the three types of shaders needed for a call to
43     // GX2SetShaders. The vertex and pixel shaders are loaded from the
44     // header, but since the fetch shader is generated at run-time
45     // it must be handled slightly differently.
46     const GX2VertexShader *pVertexShader;
47     const GX2PixelShader *pPixelShader;
48 
49     // The register locations where the offset uniforms are stored for
50     // the pixel and vertex shaders.
51     u32 u_positionLocation;
52     u32 u_texcoordLocation;
53 
54 } ExpandColorShader;
55 
56 static ExpandColorShader g_expandColorShader[NUM_SHADERS];
57 static GX2FetchShader fetchShader;
58 
59 #define FETCH_SHADER_SIZE 32  //hard code this value for now
60 ALIGNVAR(GX2_SHADER_ALIGNMENT) static u8 g_GX2UTFetchShader[FETCH_SHADER_SIZE];
61 
62 // ----- GX2 Texture
63 
64 typedef struct _VtxFmtF32x2 {
65     f32 texcoord[2];
66 } VtxFmtF32x2;
67 
68 static const VtxFmtF32x2 EXPAND_SURFACE_RECT_POSITION_DATA[] =
69 {
70     {0.0f,  0.0f},
71     {1.0f,  0.0f},
72     {1.0f,  1.0f},
73     {0.0f,  1.0f}
74 };
75 
76 // Same for both rect and triangle strips
77 static const u32 VERTEX_COUNT = sizeof(EXPAND_SURFACE_RECT_POSITION_DATA)
78                          / sizeof(EXPAND_SURFACE_RECT_POSITION_DATA[0]);
79 
80 // Initializes how surfaces will be copied
GX2UTExpandAAColorInit()81 void GX2UTExpandAAColorInit()
82 {
83     // Setup shaders
84     u32 i;
85 
86     for (i = 0; i < NUM_SHADERS; ++i)
87     {
88         g_expandColorShader[i].pVertexShader = VS_SHADERS[i];
89         g_expandColorShader[i].pPixelShader = PS_SHADERS[i];
90 
91         GX2Invalidate(GX2_INVALIDATE_CPU_SHADER,
92             g_expandColorShader[i].pVertexShader->shaderPtr,
93             g_expandColorShader[i].pVertexShader->shaderSize);
94 
95         GX2NotifyMemAlloc(g_expandColorShader[i].pVertexShader->shaderPtr,
96             g_expandColorShader[i].pVertexShader->shaderSize,
97             GX2_SHADER_ALIGNMENT);
98 
99         GX2Invalidate(GX2_INVALIDATE_CPU_SHADER,
100             g_expandColorShader[i].pPixelShader->shaderPtr,
101             g_expandColorShader[i].pPixelShader->shaderSize);
102 
103         GX2NotifyMemAlloc(g_expandColorShader[i].pPixelShader->shaderPtr,
104             g_expandColorShader[i].pPixelShader->shaderSize,
105             GX2_SHADER_ALIGNMENT);
106 
107         // Lookup the uniform locations in the vertex shader.
108         // The shader author chose the name "u_positions"
109         g_expandColorShader[i].u_positionLocation =
110             (u32)GX2GetVertexUniformVarOffset(g_expandColorShader[i].pVertexShader, "u_positions");
111         ASSERT((g_expandColorShader[i].u_positionLocation != GX2_UNIFORM_VAR_INVALID_OFFSET)
112             && "Couldn't find the correct vertex shader uniforms.");
113 
114     }
115 
116     ASSERT(GX2CalcFetchShaderSize(0) <= sizeof(g_GX2UTFetchShader) && "g_GX2UTFetchShader too small!\n");
117     GX2InitFetchShader(&fetchShader, g_GX2UTFetchShader, 0, NULL);
118 }
119 
GX2UTExpandAAColorBufferOp(GX2ColorBuffer * colorBuffer)120 void GX2UTExpandAAColorBufferOp(GX2ColorBuffer* colorBuffer)
121 {
122     static GX2Boolean initDone = GX2_FALSE;
123     u32 expandWidth;
124     u32 expandHeight;
125     u32 shaderIdx = 0;
126 
127     GX2UTDebugTagIndent(__func__);
128 
129     if (initDone == GX2_FALSE)
130     {
131         // Initialize the resources needed to expand a color buffer
132         GX2UTExpandAAColorInit();
133 
134         initDone = GX2_TRUE;
135     }
136 
137     ASSERT((colorBuffer != NULL));
138 
139     // Set shaders
140     GX2SetFetchShader(&fetchShader);
141     GX2SetVertexShader(g_expandColorShader[shaderIdx].pVertexShader);
142     GX2SetPixelShader(g_expandColorShader[shaderIdx].pPixelShader);
143 
144     // Set the uniforms to be used by the vertex shader
145     f32 position_base_scale[] =
146     {
147         -1.0f,
148          1.0f,
149          2.0f,
150         -2.0f,
151     };
152 
153     for (int i = 0; i < 4; i++)
154     {
155         f32 pos[] = {
156             position_base_scale[0] + position_base_scale[2] * EXPAND_SURFACE_RECT_POSITION_DATA[i].texcoord[0],
157             position_base_scale[1] + position_base_scale[3] * EXPAND_SURFACE_RECT_POSITION_DATA[i].texcoord[1],
158             0.0,
159             1.0
160         };
161 
162         GX2SetVertexUniformReg(g_expandColorShader[shaderIdx].u_positionLocation + i*4, 1*4, pos);
163     }
164 
165     // Invalidate the color buffer to guarantee all writes have been flushed
166     if ( colorBuffer->viewMip )
167         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, colorBuffer->surface.mipPtr, colorBuffer->surface.mipSize);
168     else
169         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, colorBuffer->surface.imagePtr, colorBuffer->surface.imageSize);
170 
171     GX2ColorBuffer cb = *colorBuffer;
172     for (int slice = colorBuffer->viewFirstSlice; slice < colorBuffer->viewNumSlices; slice++)
173     {
174         cb.viewFirstSlice = slice;
175         cb.viewNumSlices = 1;
176         GX2InitColorBufferRegs(&cb);
177 
178         // Copy the dimensions
179         expandWidth = cb.surface.width;
180         expandHeight = cb.surface.height;
181 
182         // Set the color buffer
183         GX2SetColorBuffer(&cb, GX2_RENDER_TARGET_0);
184 
185         // Render to destination surface dimensions
186         GX2SetViewport(0, 0, (f32)expandWidth, (f32)expandHeight, 0.0f, 1.0f);
187         GX2SetScissor(0, 0, expandWidth, expandHeight);
188 
189         // Draw a full quad that covers the display
190         GX2Draw(GX2_PRIMITIVE_RECTS, VERTEX_COUNT);
191     }
192 
193     // Invalidate the color buffer to guarantee all writes have been flushed
194     if ( colorBuffer->viewMip )
195         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, colorBuffer->surface.mipPtr, colorBuffer->surface.mipSize);
196     else
197         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, colorBuffer->surface.imagePtr, colorBuffer->surface.imageSize);
198 
199 
200     GX2UTDebugTagUndent();
201 }
202 
203 
204 //Setup all of the constant renderstate needed for the copy.
GX2UTSetExpandAAColorState(GX2Boolean enable)205 void GX2UTSetExpandAAColorState(GX2Boolean enable)
206 {
207     if (enable)
208     {
209         // If your application's steady state can be set to GX2UT common state
210         // using a small number of discrete GX2 calls, then customize here
211         // instead of using GX2UTSetCommonState().
212         GX2UTSetCommonState();
213 
214         // Set additional required GX2 state
215         GX2SetDepthStencilControl(GX2_FALSE,
216                                   GX2_FALSE,
217                                   GX2_COMPARE_NEVER,
218                                   GX2_FALSE,
219                                   GX2_FALSE,
220                                   GX2_COMPARE_NEVER,
221                                   GX2_STENCIL_KEEP,
222                                   GX2_STENCIL_KEEP,
223                                   GX2_STENCIL_KEEP,
224                                   GX2_COMPARE_NEVER,
225                                   GX2_STENCIL_KEEP,
226                                   GX2_STENCIL_KEEP,
227                                   GX2_STENCIL_KEEP);
228 
229         // Set Complex GX2 State for our operation
230         GX2SetSpecialState(GX2_SPECIAL_STATE_EXPAND_COLOR, GX2_TRUE);
231     }
232     else
233     {
234         // Disable any complex GX2 state
235         GX2SetSpecialState(GX2_SPECIAL_STATE_EXPAND_COLOR, GX2_FALSE);
236 
237         // The purpose of the following is to return the context to GX2 default
238         // state.  If your application uses a different "steady state", then
239         // customize
240         GX2SetDepthStencilControl(
241               GX2_TRUE,            //depthTestEnable
242               GX2_TRUE,            //depthWriteEnable
243               GX2_COMPARE_LESS,    //depthFunc
244               GX2_FALSE,           //stencilTestEnable
245               GX2_FALSE,           //backStencilEnable
246               GX2_COMPARE_ALWAYS,  //frontStencilFunc
247               GX2_STENCIL_REPLACE, //frontStencilZPass
248               GX2_STENCIL_REPLACE, //frontStencilZFail
249               GX2_STENCIL_REPLACE, //frontStencilFail
250               GX2_COMPARE_ALWAYS,  //backStencilFunc
251               GX2_STENCIL_REPLACE, //backStencilZPass
252               GX2_STENCIL_REPLACE, //backStencilZFail
253               GX2_STENCIL_REPLACE);//backStencilFail
254 
255     }
256 }
257