1 /*---------------------------------------------------------------------------*
2
3 Copyright (C) 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