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/gx2utResolveColor.h"
31 
32 #define MAX(a, b) ((a) > (b) ? (a) : (b))
33 
34 // ----- GX2 Shader
35 static const GX2VertexShader* const VS_SHADERS[] = { &gx2utResolveColor_VS,};
36 
37 static const GX2PixelShader* const PS_SHADERS[] = { &gx2utResolveColor_PS,
38 };
39 
40 static const u32 NUM_SHADERS = 1;
41 
42 typedef struct _ResolveColorShader {
43     // These variables hold the three types of shaders needed for a call to
44     // GX2SetShaders. The vertex and pixel shaders are loaded from the
45     // header, but since the fetch shader is generated at run-time
46     // it must be handled slightly differently.
47     const GX2VertexShader *pVertexShader;
48     const GX2PixelShader *pPixelShader;
49 
50     // The register locations where the offset uniforms are stored for
51     // the pixel and vertex shaders.
52     u32 u_positionLocation;
53     u32 u_texcoordLocation;
54 
55 } ResolveColorShader;
56 
57 static ResolveColorShader g_resolveColorShader[NUM_SHADERS];
58 static GX2FetchShader fetchShader;
59 
60 #define FETCH_SHADER_SIZE 32  //hard code this value for now
61 ALIGNVAR(GX2_SHADER_ALIGNMENT) static u8 g_GX2UTFetchShader[FETCH_SHADER_SIZE];
62 
63 // ----- GX2 Texture
64 
65 typedef struct _VtxFmtF32x2 {
66     f32 texcoord[2];
67 } VtxFmtF32x2;
68 
69 static const VtxFmtF32x2 RESOLVE_SURFACE_RECT_POSITION_DATA[] =
70 {
71     {0.0f,  0.0f},
72     {1.0f,  0.0f},
73     {1.0f,  1.0f},
74     {0.0f,  1.0f}
75 };
76 
77 // Same for both rect and triangle strips
78 static const u32 VERTEX_COUNT = sizeof(RESOLVE_SURFACE_RECT_POSITION_DATA)
79                          / sizeof(RESOLVE_SURFACE_RECT_POSITION_DATA[0]);
80 
81 // Initializes how surfaces will be copied
GX2UTResolveColorInit()82 void GX2UTResolveColorInit()
83 {
84     // Setup shaders
85     u32 i;
86 
87     for (i = 0; i < NUM_SHADERS; ++i)
88     {
89         g_resolveColorShader[i].pVertexShader = VS_SHADERS[i];
90         g_resolveColorShader[i].pPixelShader = PS_SHADERS[i];
91 
92         GX2Invalidate(GX2_INVALIDATE_CPU_SHADER,
93             g_resolveColorShader[i].pVertexShader->shaderPtr,
94             g_resolveColorShader[i].pVertexShader->shaderSize);
95 
96         GX2NotifyMemAlloc(g_resolveColorShader[i].pVertexShader->shaderPtr,
97             g_resolveColorShader[i].pVertexShader->shaderSize,
98             GX2_SHADER_ALIGNMENT);
99 
100         GX2Invalidate(GX2_INVALIDATE_CPU_SHADER,
101             g_resolveColorShader[i].pPixelShader->shaderPtr,
102             g_resolveColorShader[i].pPixelShader->shaderSize);
103 
104         GX2NotifyMemAlloc(g_resolveColorShader[i].pPixelShader->shaderPtr,
105             g_resolveColorShader[i].pPixelShader->shaderSize,
106             GX2_SHADER_ALIGNMENT);
107 
108         // Lookup the uniform locations in the vertex shader.
109         // The shader author chose the name "u_positions"
110         g_resolveColorShader[i].u_positionLocation =
111             (u32)GX2GetVertexUniformVarOffset(g_resolveColorShader[i].pVertexShader, "u_positions");
112         ASSERT((g_resolveColorShader[i].u_positionLocation != GX2_UNIFORM_VAR_INVALID_OFFSET)
113             && "Couldn't find the correct vertex shader uniforms.");
114 
115     }
116 
117     ASSERT(GX2CalcFetchShaderSize(0) <= sizeof(g_GX2UTFetchShader) && "g_GX2UTFetchShader too small!\n");
118     GX2InitFetchShader(&fetchShader, g_GX2UTFetchShader, 0, NULL);
119 }
120 
GX2UTResolveAAColorBufferRectOp(const GX2ColorBuffer * colorBuffer,GX2Surface * dstSurface,u32 dstMip,u32 dstSlice,GX2UTRect * subRect)121 void GX2UTResolveAAColorBufferRectOp(const GX2ColorBuffer* colorBuffer,
122                                      GX2Surface *dstSurface, u32 dstMip,
123                                      u32 dstSlice, GX2UTRect *subRect)
124 {
125     static GX2Boolean initDone = GX2_FALSE;
126     GX2ColorBuffer dstBuffer;
127     u32 resolveWidth, resolveHeight, dstMipWidth, dstMipHeight;
128     u32 shaderIdx = 0;
129 
130     GX2UTDebugTagIndent(__func__);
131 
132     if (initDone == GX2_FALSE)
133     {
134         // Initialize the resources needed to resolve a color buffer
135         GX2UTResolveColorInit();
136 
137         initDone = GX2_TRUE;
138     }
139 
140     // Require all pointers to be passed
141     ASSERT((colorBuffer != NULL) && (dstSurface != NULL) && (subRect != NULL));
142     // Require equally sized surfaces
143     ASSERT(colorBuffer->surface.width == dstSurface->width);
144     ASSERT(colorBuffer->surface.height == dstSurface->height);
145     // Require at least 2x2 alignment
146     ASSERT(!(subRect->top & 0x1) &&
147            !(subRect->left & 0x1));
148 
149     // Get the dimensions
150     resolveWidth = subRect->right - subRect->left;
151     resolveHeight = subRect->bottom - subRect->top;
152     dstMipWidth  = GX2Max(1, dstSurface->width  >> dstMip);
153     dstMipHeight = GX2Max(1, dstSurface->height >> dstMip);
154 
155     // Validate subRect
156     ASSERT((subRect->bottom > subRect->top) &&
157            (subRect->right > subRect->left) && "Invalid source region!");
158     ASSERT((subRect->top >= 0) && (subRect->top <= dstMipHeight));
159     ASSERT((subRect->bottom >= 0) && (subRect->bottom <= dstMipHeight));
160     ASSERT((subRect->left >= 0) && (subRect->left <= dstMipWidth));
161     ASSERT((subRect->right >= 0) && (subRect->right <= dstMipWidth));
162 
163     // Set shaders
164     GX2SetFetchShader(&fetchShader);
165     GX2SetVertexShader(g_resolveColorShader[shaderIdx].pVertexShader);
166     GX2SetPixelShader(g_resolveColorShader[shaderIdx].pPixelShader);
167 
168     // Set the uniforms to be used by the vertex shader
169     f32 position_base_scale[] =
170     {
171         -1.0f + 2.0f * (f32)subRect->left / (f32)dstMipWidth,
172          1.0f - 2.0f * (f32)subRect->top / (f32)dstMipHeight,
173          2.0f * (f32)resolveWidth / (f32)dstMipWidth,
174         -2.0f * (f32)resolveHeight / (f32)dstMipHeight,
175     };
176 
177     for (int i = 0; i < 4; i++)
178     {
179         f32 pos[] = {
180             position_base_scale[0] + position_base_scale[2] * RESOLVE_SURFACE_RECT_POSITION_DATA[i].texcoord[0],
181             position_base_scale[1] + position_base_scale[3] * RESOLVE_SURFACE_RECT_POSITION_DATA[i].texcoord[1],
182             0.0,
183             1.0
184         };
185 
186         GX2SetVertexUniformReg(g_resolveColorShader[shaderIdx].u_positionLocation + i*4, 1*4, pos);
187     }
188 
189     // Invalidate the color buffer to guarantee all writes have been flushed
190     if (colorBuffer->viewMip)
191         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, colorBuffer->surface.mipPtr, colorBuffer->surface.mipSize);
192     else
193         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, colorBuffer->surface.imagePtr, colorBuffer->surface.imageSize);
194 
195     for (int slice = 0; slice < colorBuffer->viewNumSlices; slice++)
196     {
197         // Setup the source color buffer first slice
198         GX2ColorBuffer srcColor = *colorBuffer;
199         srcColor.viewFirstSlice = slice;
200         srcColor.viewNumSlices = 1;
201         GX2InitColorBufferRegs(&srcColor);
202 
203         // Create shallow copy of dest surface to be used as render target
204         dstBuffer.surface = *dstSurface;
205         dstBuffer.surface.use = GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE;
206         dstBuffer.viewMip = dstMip;
207         dstBuffer.viewFirstSlice = dstSlice + slice;
208         dstBuffer.viewNumSlices = 1;
209         dstBuffer.auxPtr = NULL;
210         dstBuffer.auxSize = 0;
211         GX2CalcSurfaceSizeAndAlignment(&dstBuffer.surface);
212         GX2InitColorBufferRegs(&dstBuffer);
213 
214         // Set the color buffers
215         GX2SetColorBuffer(&srcColor, GX2_RENDER_TARGET_0);
216         GX2SetColorBuffer(&dstBuffer, GX2_RENDER_TARGET_1);
217 
218         // Render to destination surface dimensions
219         GX2SetViewport(0, 0, (f32)dstMipWidth, (f32)dstMipHeight, 0.0f, 1.0f);
220         GX2SetScissor(0, 0, dstMipWidth, dstMipHeight);
221 
222         // Draw a full quad that covers the display
223         GX2Draw(GX2_PRIMITIVE_RECTS, VERTEX_COUNT);
224     }
225 
226     // Invalidate the color buffer to guarantee all writes have been flushed
227     if (dstMip)
228         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, dstSurface->mipPtr, dstSurface->mipSize);
229     else
230         GX2Invalidate(GX2_INVALIDATE_COLOR_BUFFER, dstSurface->imagePtr, dstSurface->imageSize);
231 
232 
233     GX2UTDebugTagUndent();
234 }
235 
236 
237 //Setup all of the constant renderstate needed for the copy.
GX2UTSetResolveAAColorState(GX2Boolean enable)238 void GX2UTSetResolveAAColorState(GX2Boolean enable)
239 {
240     if (enable)
241     {
242         // If your application's steady state can be set to GX2UT common state
243         // using a small number of discrete GX2 calls, then customize here
244         // instead of using GX2UTSetCommonState().
245         GX2UTSetCommonState();
246 
247         // Set additional required GX2 state
248         GX2SetDepthStencilControl(GX2_FALSE,
249                                   GX2_FALSE,
250                                   GX2_COMPARE_NEVER,
251                                   GX2_FALSE,
252                                   GX2_FALSE,
253                                   GX2_COMPARE_NEVER,
254                                   GX2_STENCIL_KEEP,
255                                   GX2_STENCIL_KEEP,
256                                   GX2_STENCIL_KEEP,
257                                   GX2_COMPARE_NEVER,
258                                   GX2_STENCIL_KEEP,
259                                   GX2_STENCIL_KEEP,
260                                   GX2_STENCIL_KEEP);
261 
262         GX2SetBlendControl(GX2_RENDER_TARGET_0,
263                            GX2_BLEND_ONE,
264                            GX2_BLEND_ZERO,
265                            GX2_BLEND_COMBINE_ADD,
266                            GX2_FALSE,
267                            GX2_BLEND_ONE,
268                            GX2_BLEND_ZERO,
269                            GX2_BLEND_COMBINE_ADD);
270 
271         GX2SetBlendControl(GX2_RENDER_TARGET_1,
272                            GX2_BLEND_ONE,
273                            GX2_BLEND_ZERO,
274                            GX2_BLEND_COMBINE_ADD,
275                            GX2_FALSE,
276                            GX2_BLEND_ONE,
277                            GX2_BLEND_ZERO,
278                            GX2_BLEND_COMBINE_ADD);
279 
280         GX2SetTargetChannelMasks(GX2_CHANNEL_MASK_RGBA,
281                                  GX2_CHANNEL_MASK_NONE,
282                                  GX2_CHANNEL_MASK_NONE,
283                                  GX2_CHANNEL_MASK_NONE,
284                                  GX2_CHANNEL_MASK_NONE,
285                                  GX2_CHANNEL_MASK_NONE,
286                                  GX2_CHANNEL_MASK_NONE,
287                                  GX2_CHANNEL_MASK_NONE);
288 
289         // Set Complex GX2 State for our operation
290         GX2SetSpecialState(GX2_SPECIAL_STATE_RESOLVE_COLOR, GX2_ENABLE);
291     }
292     else
293     {
294         // Disable any complex GX2 state
295         GX2SetSpecialState(GX2_SPECIAL_STATE_RESOLVE_COLOR, GX2_DISABLE);
296 
297         // The purpose of the following is to return the context to GX2 default state
298         // If your application uses a different "steady state", then customize
299         GX2SetDepthStencilControl(
300               GX2_TRUE,            //depthTestEnable
301               GX2_TRUE,            //depthWriteEnable
302               GX2_COMPARE_LESS,    //depthFunc
303               GX2_FALSE,           //stencilTestEnable
304               GX2_FALSE,           //backStencilEnable
305               GX2_COMPARE_ALWAYS,  //frontStencilFunc
306               GX2_STENCIL_REPLACE, //frontStencilZPass
307               GX2_STENCIL_REPLACE, //frontStencilZFail
308               GX2_STENCIL_REPLACE, //frontStencilFail
309               GX2_COMPARE_ALWAYS,  //backStencilFunc
310               GX2_STENCIL_REPLACE, //backStencilZPass
311               GX2_STENCIL_REPLACE, //backStencilZFail
312               GX2_STENCIL_REPLACE);//backStencilFail
313 
314         GX2SetBlendControl(GX2_RENDER_TARGET_0,
315                            GX2_BLEND_SRC_ALPHA,
316                            GX2_BLEND_ONE_MINUS_SRC_ALPHA,
317                            GX2_BLEND_COMBINE_ADD,
318                            GX2_ENABLE,
319                            GX2_BLEND_SRC_ALPHA,
320                            GX2_BLEND_ONE_MINUS_SRC_ALPHA,
321                            GX2_BLEND_COMBINE_ADD);
322 
323         GX2SetBlendControl(GX2_RENDER_TARGET_1,
324                            GX2_BLEND_SRC_ALPHA,
325                            GX2_BLEND_ONE_MINUS_SRC_ALPHA,
326                            GX2_BLEND_COMBINE_ADD,
327                            GX2_ENABLE,
328                            GX2_BLEND_SRC_ALPHA,
329                            GX2_BLEND_ONE_MINUS_SRC_ALPHA,
330                            GX2_BLEND_COMBINE_ADD);
331 
332         GX2SetTargetChannelMasks(GX2_CHANNEL_MASK_RGBA,
333                                  GX2_CHANNEL_MASK_RGBA,
334                                  GX2_CHANNEL_MASK_RGBA,
335                                  GX2_CHANNEL_MASK_RGBA,
336                                  GX2_CHANNEL_MASK_RGBA,
337                                  GX2_CHANNEL_MASK_RGBA,
338                                  GX2_CHANNEL_MASK_RGBA,
339                                  GX2_CHANNEL_MASK_RGBA);
340     }
341 }
342