GLES2N64: Enabled Framebuffer (and lowres) rendering
[mupen64plus-pandora.git] / source / gles2n64 / src / ShaderCombiner.cpp
CommitLineData
34cf4058 1
2#include <stdlib.h>
3#include "OpenGL.h"
4#include "ShaderCombiner.h"
5#include "Common.h"
6#include "Textures.h"
7#include "Config.h"
8
9
10//(sa - sb) * m + a
11static const u32 saRGBExpanded[] =
12{
13 COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
14 SHADE, ENVIRONMENT, ONE, NOISE,
15 ZERO, ZERO, ZERO, ZERO,
16 ZERO, ZERO, ZERO, ZERO
17};
18
19static const u32 sbRGBExpanded[] =
20{
21 COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
22 SHADE, ENVIRONMENT, CENTER, K4,
23 ZERO, ZERO, ZERO, ZERO,
24 ZERO, ZERO, ZERO, ZERO
25};
26
27static const u32 mRGBExpanded[] =
28{
29 COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
30 SHADE, ENVIRONMENT, SCALE, COMBINED_ALPHA,
31 TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA, SHADE_ALPHA,
32 ENV_ALPHA, LOD_FRACTION, PRIM_LOD_FRAC, K5,
33 ZERO, ZERO, ZERO, ZERO,
34 ZERO, ZERO, ZERO, ZERO,
35 ZERO, ZERO, ZERO, ZERO,
36 ZERO, ZERO, ZERO, ZERO
37};
38
39static const u32 aRGBExpanded[] =
40{
41 COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
42 SHADE, ENVIRONMENT, ONE, ZERO
43};
44
45static const u32 saAExpanded[] =
46{
47 COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
48 SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
49};
50
51static const u32 sbAExpanded[] =
52{
53 COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
54 SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
55};
56
57static const u32 mAExpanded[] =
58{
59 LOD_FRACTION, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
60 SHADE_ALPHA, ENV_ALPHA, PRIM_LOD_FRAC, ZERO,
61};
62
63static const u32 aAExpanded[] =
64{
65 COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
66 SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
67};
68
69int CCEncodeA[] = {0, 1, 2, 3, 4, 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 6, 15 };
70int CCEncodeB[] = {0, 1, 2, 3, 4, 5, 6, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15 };
71int CCEncodeC[] = {0, 1, 2, 3, 4, 5, 31, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31, 31, 15, 31, 31};
72int CCEncodeD[] = {0, 1, 2, 3, 4, 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 6, 15};
73int ACEncodeA[] = {7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 6, 7};
74int ACEncodeB[] = {7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 6, 7};
75int ACEncodeC[] = {7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 6, 7, 7, 7, 7, 7};
76int ACEncodeD[] = {7, 7, 7, 7, 7, 7, 7, 7, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 6, 7};
77
78ShaderProgram *scProgramRoot = NULL;
79ShaderProgram *scProgramCurrent = NULL;
80int scProgramChanged = 0;
81int scProgramCount = 0;
82
83GLint _vertex_shader = 0;
84
85const char *_frag_header = " \n"\
86"uniform sampler2D uTex0; \n"\
87"uniform sampler2D uTex1; \n"\
88"uniform sampler2D uNoise; \n"\
89"uniform lowp vec4 uEnvColor; \n"\
90"uniform lowp vec4 uPrimColor; \n"\
91"uniform lowp vec4 uFogColor; \n"\
92"uniform highp float uAlphaRef; \n"\
93"uniform lowp float uPrimLODFrac; \n"\
94"uniform lowp float uK4; \n"\
95"uniform lowp float uK5; \n"\
96" \n"\
97"varying lowp float vFactor; \n"\
98"varying lowp vec4 vShadeColor; \n"\
99"varying mediump vec2 vTexCoord0; \n"\
100"varying mediump vec2 vTexCoord1; \n"\
101" \n"\
102"void main() \n"\
103"{ \n"\
104"lowp vec4 lFragColor; \n";
105
106
107const char *_vert = " \n"\
108"attribute highp vec4 aPosition; \n"\
109"attribute lowp vec4 aColor; \n"\
110"attribute highp vec2 aTexCoord0; \n"\
111"attribute highp vec2 aTexCoord1; \n"\
112" \n"\
113"uniform bool uEnableFog; \n"\
114"uniform float uFogMultiplier, uFogOffset; \n"\
115"uniform float uRenderState; \n"\
116" \n"\
117"uniform mediump vec2 uTexScale; \n"\
118"uniform mediump vec2 uTexOffset[2]; \n"\
119"uniform mediump vec2 uCacheShiftScale[2]; \n"\
120"uniform mediump vec2 uCacheScale[2]; \n"\
121"uniform mediump vec2 uCacheOffset[2]; \n"\
122" \n"\
123"varying lowp float vFactor; \n"\
124"varying lowp vec4 vShadeColor; \n"\
125"varying mediump vec2 vTexCoord0; \n"\
126"varying mediump vec2 vTexCoord1; \n"\
127" \n"\
128"void main() \n"\
129"{ \n"\
130"gl_Position = aPosition; \n"\
131"vShadeColor = aColor; \n"\
132" \n"\
133"if (uRenderState == 1.0) \n"\
134"{ \n"\
135"vTexCoord0 = (aTexCoord0 * (uTexScale[0] * \n"\
136" uCacheShiftScale[0]) + (uCacheOffset[0] - \n"\
137" uTexOffset[0])) * uCacheScale[0]; \n"\
138"vTexCoord1 = (aTexCoord0 * (uTexScale[1] * \n"\
139" uCacheShiftScale[1]) + (uCacheOffset[1] - \n"\
140" uTexOffset[1])) * uCacheScale[1]; \n"\
141"} \n"\
142"else \n"\
143"{ \n"\
144"vTexCoord0 = aTexCoord0; \n"\
145"vTexCoord1 = aTexCoord1; \n"\
146"} \n"\
147" \n";
148
149const char * _vertfog = " \n"\
150"if (uEnableFog) \n"\
151"{ \n"\
152"vFactor = max(-1.0, aPosition.z / aPosition.w) \n"\
153" * uFogMultiplier + uFogOffset; \n"\
154"vFactor = clamp(vFactor, 0.0, 1.0); \n"\
155"} \n";
156
157const char * _vertzhack = " \n"\
158"if (uRenderState == 1.0) \n"\
159"{ \n"\
160"gl_Position.z = (gl_Position.z + gl_Position.w*9.0) * 0.1; \n"\
161"} \n";
162
163
164const char * _color_param_str(int param)
165{
166 switch(param)
167 {
168 case COMBINED: return "lFragColor.rgb";
169 case TEXEL0: return "lTex0.rgb";
170 case TEXEL1: return "lTex1.rgb";
171 case PRIMITIVE: return "uPrimColor.rgb";
172 case SHADE: return "vShadeColor.rgb";
173 case ENVIRONMENT: return "uEnvColor.rgb";
174 case CENTER: return "vec3(0.0)";
175 case SCALE: return "vec3(0.0)";
176 case COMBINED_ALPHA: return "vec3(lFragColor.a)";
177 case TEXEL0_ALPHA: return "vec3(lTex0.a)";
178 case TEXEL1_ALPHA: return "vec3(lTex1.a)";
179 case PRIMITIVE_ALPHA: return "vec3(uPrimColor.a)";
180 case SHADE_ALPHA: return "vec3(vShadeColor.a)";
181 case ENV_ALPHA: return "vec3(uEnvColor.a)";
182 case LOD_FRACTION: return "vec3(0.0)";
183 case PRIM_LOD_FRAC: return "vec3(uPrimLODFrac)";
184 case NOISE: return "lNoise.rgb";
185 case K4: return "vec3(uK4)";
186 case K5: return "vec3(uK5)";
187 case ONE: return "vec3(1.0)";
188 case ZERO: return "vec3(0.0)";
189 default:
190 return "vec3(0.0)";
191 }
192}
193
194const char * _alpha_param_str(int param)
195{
196 switch(param)
197 {
198 case COMBINED: return "lFragColor.a";
199 case TEXEL0: return "lTex0.a";
200 case TEXEL1: return "lTex1.a";
201 case PRIMITIVE: return "uPrimColor.a";
202 case SHADE: return "vShadeColor.a";
203 case ENVIRONMENT: return "uEnvColor.a";
204 case CENTER: return "0.0";
205 case SCALE: return "0.0";
206 case COMBINED_ALPHA: return "lFragColor.a";
207 case TEXEL0_ALPHA: return "lTex0.a";
208 case TEXEL1_ALPHA: return "lTex1.a";
209 case PRIMITIVE_ALPHA: return "uPrimColor.a";
210 case SHADE_ALPHA: return "vShadeColor.a";
211 case ENV_ALPHA: return "uEnvColor.a";
212 case LOD_FRACTION: return "0.0";
213 case PRIM_LOD_FRAC: return "uPrimLODFrac";
214 case NOISE: return "lNoise.a";
215 case K4: return "uK4";
216 case K5: return "uK5";
217 case ONE: return "1.0";
218 case ZERO: return "0.0";
219 default:
220 return "0.0";
221 }
222}
223
224#define MAX_CACHE 16
225ShaderProgram* prog_cache[MAX_CACHE];
226u64 mux_cache[MAX_CACHE];
227int flag_cache[MAX_CACHE];
228int old_cache[MAX_CACHE];
229static int cache_turn=0;
230
231DecodedMux::DecodedMux(u64 mux, bool cycle2)
232{
233 combine.mux = mux;
234 flags = 0;
235
236 //set to ZERO.
237 for(int i=0;i<4;i++)
238 for(int j=0; j< 4; j++)
239 decode[i][j] = ZERO;
240
241 //rgb cycle 0
242 decode[0][0] = saRGBExpanded[combine.saRGB0];
243 decode[0][1] = sbRGBExpanded[combine.sbRGB0];
244 decode[0][2] = mRGBExpanded[combine.mRGB0];
245 decode[0][3] = aRGBExpanded[combine.aRGB0];
246 decode[1][0] = saAExpanded[combine.saA0];
247 decode[1][1] = sbAExpanded[combine.sbA0];
248 decode[1][2] = mAExpanded[combine.mA0];
249 decode[1][3] = aAExpanded[combine.aA0];
250 if (cycle2)
251 {
252 //rgb cycle 1
253 decode[2][0] = saRGBExpanded[combine.saRGB1];
254 decode[2][1] = sbRGBExpanded[combine.sbRGB1];
255 decode[2][2] = mRGBExpanded[combine.mRGB1];
256 decode[2][3] = aRGBExpanded[combine.aRGB1];
257 decode[3][0] = saAExpanded[combine.saA1];
258 decode[3][1] = sbAExpanded[combine.sbA1];
259 decode[3][2] = mAExpanded[combine.mA1];
260 decode[3][3] = aAExpanded[combine.aA1];
261
262 //texel 0/1 are swapped in 2nd cycle.
263 swap(1, TEXEL0, TEXEL1);
264 swap(1, TEXEL0_ALPHA, TEXEL1_ALPHA);
265 }
266
267 //simplifying mux:
268 if (replace(G_CYC_1CYCLE, LOD_FRACTION, ZERO) || replace(G_CYC_2CYCLE, LOD_FRACTION, ZERO))
269 LOG(LOG_VERBOSE, "SC Replacing LOD_FRACTION with ZERO\n");
270#if 1
271 if (replace(G_CYC_1CYCLE, K4, ZERO) || replace(G_CYC_2CYCLE, K4, ZERO))
272 LOG(LOG_VERBOSE, "SC Replacing K4 with ZERO\n");
273
274 if (replace(G_CYC_1CYCLE, K5, ZERO) || replace(G_CYC_2CYCLE, K5, ZERO))
275 LOG(LOG_VERBOSE, "SC Replacing K5 with ZERO\n");
276#endif
277
278 if (replace(G_CYC_1CYCLE, CENTER, ZERO) || replace(G_CYC_2CYCLE, CENTER, ZERO))
279 LOG(LOG_VERBOSE, "SC Replacing CENTER with ZERO\n");
280
281 if (replace(G_CYC_1CYCLE, SCALE, ZERO) || replace(G_CYC_2CYCLE, SCALE, ZERO))
282 LOG(LOG_VERBOSE, "SC Replacing SCALE with ZERO\n");
283
284 //Combiner has initial value of zero in cycle 0
285 if (replace(G_CYC_1CYCLE, COMBINED, ZERO))
286 LOG(LOG_VERBOSE, "SC Setting CYCLE1 COMBINED to ZERO\n");
287
288 if (replace(G_CYC_1CYCLE, COMBINED_ALPHA, ZERO))
289 LOG(LOG_VERBOSE, "SC Setting CYCLE1 COMBINED_ALPHA to ZERO\n");
290
291 if (!config.enableNoise)
292 {
293 if (replace(G_CYC_1CYCLE, NOISE, ZERO))
294 LOG(LOG_VERBOSE, "SC Setting CYCLE1 NOISE to ZERO\n");
295
296 if (replace(G_CYC_2CYCLE, NOISE, ZERO))
297 LOG(LOG_VERBOSE, "SC Setting CYCLE2 NOISE to ZERO\n");
298
299 }
300
301 //mutiplying by zero: (A-B)*0 + C = C
302 for(int i=0 ; i<4; i++)
303 {
304 if (decode[i][2] == ZERO)
305 {
306 decode[i][0] = ZERO;
307 decode[i][1] = ZERO;
308 }
309 }
310
311 //(A1-B1)*C1 + D1
312 //(A2-B2)*C2 + D2
313 //1. ((A1-B1)*C1 + D1 - B2)*C2 + D2 = A1*C1*C2 - B1*C1*C2 + D1*C2 - B2*C2 + D2
314 //2. (A2 - (A1-B1)*C1 - D1)*C2 + D2 = A2*C2 - A1*C1*C2 + B1*C1*C2 - D1*C2 + D2
315 //3. (A2 - B2)*((A1-B1)*C1 + D1) + D2 = A2*A1*C1 - A2*B1*C1 + A2*D1 - B2*A1*C1 + B2*B1*C1 - B2*D1 + D2
316 //4. (A2-B2)*C2 + (A1-B1)*C1 + D1 = A2*C2 - B2*C2 + A1*C1 - B1*C1 + D1
317
318 if (cycle2)
319 {
320
321 if (!find(2, COMBINED))
322 flags |= SC_IGNORE_RGB0;
323
324 if (!(find(2, COMBINED_ALPHA) || find(3, COMBINED_ALPHA) || find(3, COMBINED)))
325 flags |= SC_IGNORE_ALPHA0;
326
327 if (decode[2][0] == ZERO && decode[2][1] == ZERO && decode[2][2] == ZERO && decode[2][3] == COMBINED)
328 {
329 flags |= SC_IGNORE_RGB1;
330 }
331
332 if (decode[3][0] == ZERO && decode[3][1] == ZERO && decode[3][2] == ZERO &&
333 (decode[3][3] == COMBINED_ALPHA || decode[3][3] == COMBINED))
334 {
335 flags |= SC_IGNORE_ALPHA1;
336 }
337
338 }
339}
340
341bool DecodedMux::find(int index, int src)
342{
343 for(int j=0;j<4;j++)
344 {
345 if (decode[index][j] == src) return true;
346 }
347 return false;
348}
349
350bool DecodedMux::replace(int cycle, int src, int dest)
351{
352 int r = false;
353 for(int i=0;i<2;i++)
354 {
355 int ii = (cycle == 0) ? i : (2+i);
356 for(int j=0;j<4;j++)
357 {
358 if (decode[ii][j] == src) {decode[ii][j] = dest; r=true;}
359 }
360 }
361 return r;
362}
363
364bool DecodedMux::swap(int cycle, int src0, int src1)
365{
366 int r = false;
367 for(int i=0;i<2;i++)
368 {
369 int ii = (cycle == 0) ? i : (2+i);
370 for(int j=0;j<4;j++)
371 {
372 if (decode[ii][j] == src0) {decode[ii][j] = src1; r=true;}
373 else if (decode[ii][j] == src1) {decode[ii][j] = src0; r=true;}
374 }
375 }
376 return r;
377}
378
379void DecodedMux::hack()
380{
381 if (config.hackZelda)
382 {
383 if(combine.mux == 0xfffd923800ffadffLL)
384 {
385 replace(G_CYC_1CYCLE, TEXEL1, TEXEL0);
386 replace(G_CYC_2CYCLE, TEXEL1, TEXEL0);
387 }
388 else if (combine.mux == 0xff5bfff800121603LL)
389 {
390 replace(G_CYC_1CYCLE, TEXEL1, ZERO);
391 replace(G_CYC_2CYCLE, TEXEL1, ZERO);
392 }
393 }
394
395}
396
397
398int _program_compare(ShaderProgram *prog, DecodedMux *dmux, u32 flags)
399{
400 if (prog)
401 return ((prog->combine.mux == dmux->combine.mux) && (prog->flags == flags));
402 else
403 return 1;
404}
405
406void _glcompiler_error(GLint shader)
407{
408 int len, i;
409 char* log;
410
411 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
412 log = (char*) malloc(len + 1);
413 glGetShaderInfoLog(shader, len, &i, log);
414 log[len] = 0;
415 LOG(LOG_ERROR, "COMPILE ERROR: %s \n", log);
416 free(log);
417}
418
419void _gllinker_error(GLint program)
420{
421 int len, i;
422 char* log;
423
424 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
425 log = (char*) malloc(len + 1);
426 glGetProgramInfoLog(program, len, &i, log);
427 log[len] = 0;
428 LOG(LOG_ERROR, "LINK ERROR: %s \n", log);
429 free(log);
430};
431
432void _locate_attributes(ShaderProgram *p)
433{
434 glBindAttribLocation(p->program, SC_POSITION, "aPosition");
435 glBindAttribLocation(p->program, SC_COLOR, "aColor");
436 glBindAttribLocation(p->program, SC_TEXCOORD0, "aTexCoord0");
437 glBindAttribLocation(p->program, SC_TEXCOORD1, "aTexCoord1");
438};
439
440#define LocateUniform(A) \
441 p->uniforms.A.loc = glGetUniformLocation(p->program, #A);
442
443void _locate_uniforms(ShaderProgram *p)
444{
445 LocateUniform(uTex0);
446 LocateUniform(uTex1);
447 LocateUniform(uNoise);
448 LocateUniform(uEnvColor);
449 LocateUniform(uPrimColor);
450 LocateUniform(uPrimLODFrac);
451 LocateUniform(uK4);
452 LocateUniform(uK5);
453 LocateUniform(uFogColor);
454 LocateUniform(uEnableFog);
455 LocateUniform(uRenderState);
456 LocateUniform(uFogMultiplier);
457 LocateUniform(uFogOffset);
458 LocateUniform(uAlphaRef);
459 LocateUniform(uTexScale);
460 LocateUniform(uTexOffset[0]);
461 LocateUniform(uTexOffset[1]);
462 LocateUniform(uCacheShiftScale[0]);
463 LocateUniform(uCacheShiftScale[1]);
464 LocateUniform(uCacheScale[0]);
465 LocateUniform(uCacheScale[1]);
466 LocateUniform(uCacheOffset[0]);
467 LocateUniform(uCacheOffset[1]);
468}
469
470void _force_uniforms()
471{
472 SC_ForceUniform1i(uTex0, 0);
473 SC_ForceUniform1i(uTex1, 1);
474 SC_ForceUniform1i(uNoise, 2);
475 SC_ForceUniform4fv(uEnvColor, &gDP.envColor.r);
476 SC_ForceUniform4fv(uPrimColor, &gDP.primColor.r);
477 SC_ForceUniform1f(uPrimLODFrac, gDP.primColor.l);
478 SC_ForceUniform1f(uK4, gDP.convert.k4);
479 SC_ForceUniform1f(uK5, gDP.convert.k5);
480 SC_ForceUniform4fv(uFogColor, &gDP.fogColor.r);
481 SC_ForceUniform1i(uEnableFog, ((config.enableFog==1) && (gSP.geometryMode & G_FOG)));
482 SC_ForceUniform1f(uRenderState, OGL.renderState);
483 SC_ForceUniform1f(uFogMultiplier, (float) gSP.fog.multiplier / 255.0f);
484 SC_ForceUniform1f(uFogOffset, (float) gSP.fog.offset / 255.0f);
485 SC_ForceUniform1f(uAlphaRef, (gDP.otherMode.cvgXAlpha) ? 0.5 : gDP.blendColor.a);
486 SC_ForceUniform2f(uTexScale, gSP.texture.scales, gSP.texture.scalet);
487
488 if (gSP.textureTile[0]){
489 SC_ForceUniform2f(uTexOffset[0], gSP.textureTile[0]->fuls, gSP.textureTile[0]->fult);
490 } else {
491 SC_ForceUniform2f(uTexOffset[0], 0.0f, 0.0f);
492 }
493
494 if (gSP.textureTile[1])
495 {
496 SC_ForceUniform2f(uTexOffset[1], gSP.textureTile[1]->fuls, gSP.textureTile[1]->fult);
497 }
498 else
499 {
500 SC_ForceUniform2f(uTexOffset[1], 0.0f, 0.0f);
501 }
502
503 if (cache.current[0])
504 {
505 SC_ForceUniform2f(uCacheShiftScale[0], cache.current[0]->shiftScaleS, cache.current[0]->shiftScaleT);
506 SC_ForceUniform2f(uCacheScale[0], cache.current[0]->scaleS, cache.current[0]->scaleT);
507 SC_ForceUniform2f(uCacheOffset[0], cache.current[0]->offsetS, cache.current[0]->offsetT);
508 }
509 else
510 {
511 SC_ForceUniform2f(uCacheShiftScale[0], 1.0f, 1.0f);
512 SC_ForceUniform2f(uCacheScale[0], 1.0f, 1.0f);
513 SC_ForceUniform2f(uCacheOffset[0], 0.0f, 0.0f);
514 }
515
516 if (cache.current[1])
517 {
518 SC_ForceUniform2f(uCacheShiftScale[1], cache.current[1]->shiftScaleS, cache.current[1]->shiftScaleT);
519 SC_ForceUniform2f(uCacheScale[1], cache.current[1]->scaleS, cache.current[1]->scaleT);
520 SC_ForceUniform2f(uCacheOffset[1], cache.current[1]->offsetS, cache.current[1]->offsetT);
521 }
522 else
523 {
524 SC_ForceUniform2f(uCacheShiftScale[1], 1.0f, 1.0f);
525 SC_ForceUniform2f(uCacheScale[1], 1.0f, 1.0f);
526 SC_ForceUniform2f(uCacheOffset[1], 0.0f, 0.0f);
527 }
528}
529
530void _update_uniforms()
531{
532 SC_SetUniform4fv(uEnvColor, &gDP.envColor.r);
533 SC_SetUniform4fv(uPrimColor, &gDP.primColor.r);
534 SC_SetUniform1f(uPrimLODFrac, gDP.primColor.l);
535 SC_SetUniform4fv(uFogColor, &gDP.fogColor.r);
536 SC_SetUniform1i(uEnableFog, (config.enableFog && (gSP.geometryMode & G_FOG)));
537 SC_SetUniform1f(uRenderState, OGL.renderState);
538 SC_SetUniform1f(uFogMultiplier, (float) gSP.fog.multiplier / 255.0f);
539 SC_SetUniform1f(uFogOffset, (float) gSP.fog.offset / 255.0f);
540 SC_SetUniform1f(uAlphaRef, (gDP.otherMode.cvgXAlpha) ? 0.5 : gDP.blendColor.a);
541 SC_SetUniform1f(uK4, gDP.convert.k4);
542 SC_SetUniform1f(uK5, gDP.convert.k5);
543
544 //for some reason i must force these...
545 SC_ForceUniform2f(uTexScale, gSP.texture.scales, gSP.texture.scalet);
546 if (scProgramCurrent->usesT0)
547 {
548 if (gSP.textureTile[0])
549 {
550 SC_ForceUniform2f(uTexOffset[0], gSP.textureTile[0]->fuls, gSP.textureTile[0]->fult);
551 }
552 if (cache.current[0])
553 {
554 SC_ForceUniform2f(uCacheShiftScale[0], cache.current[0]->shiftScaleS, cache.current[0]->shiftScaleT);
555 SC_ForceUniform2f(uCacheScale[0], cache.current[0]->scaleS, cache.current[0]->scaleT);
556 SC_ForceUniform2f(uCacheOffset[0], cache.current[0]->offsetS, cache.current[0]->offsetT);
557 }
558 }
559
560 if (scProgramCurrent->usesT1)
561 {
562 if (gSP.textureTile[1])
563 {
564 SC_ForceUniform2f(uTexOffset[1], gSP.textureTile[1]->fuls, gSP.textureTile[1]->fult);
565 }
566 if (cache.current[1])
567 {
568 SC_ForceUniform2f(uCacheShiftScale[1], cache.current[1]->shiftScaleS, cache.current[1]->shiftScaleT);
569 SC_ForceUniform2f(uCacheScale[1], cache.current[1]->scaleS, cache.current[1]->scaleT);
570 SC_ForceUniform2f(uCacheOffset[1], cache.current[1]->offsetS, cache.current[1]->offsetT);
571 }
572 }
573};
574
575void ShaderCombiner_Init()
576{
577 //compile vertex shader:
578 GLint success;
579 const char *src[1];
580 char buff[4096];
581 char *str = buff;
582
583 str += sprintf(str, "%s", _vert);
584 if (config.enableFog)
585 {
586 str += sprintf(str, "%s", _vertfog);
587 }
588 if (config.zHack)
589 {
590 str += sprintf(str, "%s", _vertzhack);
591 }
592
593 str += sprintf(str, "}\n\n");
594
595#ifdef PRINT_SHADER
596 LOG(LOG_VERBOSE, "=============================================================\n");
597 LOG(LOG_VERBOSE, "Vertex Shader:\n");
598 LOG(LOG_VERBOSE, "=============================================================\n");
599 LOG(LOG_VERBOSE, "%s", buff);
600 LOG(LOG_VERBOSE, "=============================================================\n");
601#endif
602
603 src[0] = buff;
604 _vertex_shader = glCreateShader(GL_VERTEX_SHADER);
605 glShaderSource(_vertex_shader, 1, (const char**) src, NULL);
606 glCompileShader(_vertex_shader);
607 glGetShaderiv(_vertex_shader, GL_COMPILE_STATUS, &success);
608 if (!success)
609 {
610 _glcompiler_error(_vertex_shader);
611 }
612
613 // prepare prog cache
614 for (int i=0; i<MAX_CACHE; i++) {
615 prog_cache[i]=NULL;
616 flag_cache[i]=0;
617 mux_cache[i]=0;
618 old_cache[i]=0;
619 }
620 cache_turn=0;
621};
622
623void ShaderCombiner_DeletePrograms(ShaderProgram *prog)
624{
625 if (prog)
626 {
627 ShaderCombiner_DeletePrograms(prog->left);
628 ShaderCombiner_DeletePrograms(prog->right);
629 glDeleteProgram(prog->program);
630 //glDeleteShader(prog->fragment);
631 free(prog);
632 scProgramCount--;
633 }
634}
635
636void ShaderCombiner_Destroy()
637{
638 ShaderCombiner_DeletePrograms(scProgramRoot);
639 glDeleteShader(_vertex_shader);
640 scProgramCount = scProgramChanged = 0;
641 scProgramRoot = scProgramCurrent = NULL;
642}
643
644void ShaderCombiner_Set(u64 mux, int flags)
645{
646 //banjo tooie hack
647 if ((gDP.otherMode.cycleType == G_CYC_1CYCLE) && (mux == 0x00ffe7ffffcf9fcfLL))
648 {
649 mux = EncodeCombineMode( 0, 0, 0, 0, TEXEL0, 0, PRIMITIVE, 0,
650 0, 0, 0, 0, TEXEL0, 0, PRIMITIVE, 0 );
651 }
652
653 //determine flags
654 if (flags == -1)
655 {
656 flags = 0;
657 if ((config.enableFog) && (gSP.geometryMode & G_FOG))
658 flags |= SC_FOGENABLED;
659
660 if (config.enableAlphaTest)
661 {
662 if ((gDP.otherMode.alphaCompare == G_AC_THRESHOLD) && !(gDP.otherMode.alphaCvgSel)){
663 flags |= SC_ALPHAENABLED;
664 if (gDP.blendColor.a > 0.0f) flags |= SC_ALPHAGREATER;
665 } else if (gDP.otherMode.cvgXAlpha){
666 flags |= SC_ALPHAENABLED;
667 flags |= SC_ALPHAGREATER;
668 }
669 }
670
671 if (gDP.otherMode.cycleType == G_CYC_2CYCLE)
672 flags |= SC_2CYCLE;
673 }
674
675
676 DecodedMux dmux(mux, flags&SC_2CYCLE);
677 dmux.hack();
678
679 //if already bound:
680 if (scProgramCurrent)
681 {
682 if (_program_compare(scProgramCurrent, &dmux, flags))
683 {
684 scProgramChanged = 0;
685 return;
686 }
687 }
688
689 //traverse binary tree for cached programs
690 scProgramChanged = 1;
691 ShaderProgram *root = scProgramRoot;
692 ShaderProgram *prog = root;
693 while(!_program_compare(prog, &dmux, flags))
694 {
695 root = prog;
696 if (prog->combine.mux < dmux.combine.mux)
697 prog = prog->right;
698 else
699 prog = prog->left;
700 }
701
702 //build new program
703 if (!prog)
704 {
705 scProgramCount++;
706 prog = ShaderCombiner_Compile(&dmux, flags);
707 if (!root)
708 scProgramRoot = prog;
709 else if (root->combine.mux < dmux.combine.mux)
710 root->right = prog;
711 else
712 root->left = prog;
713
714 }
715
716 prog->lastUsed = OGL.frame_dl;
717 scProgramCurrent = prog;
718 glUseProgram(prog->program);
719 _force_uniforms();
720}
721
722ShaderProgram *ShaderCombiner_Compile(DecodedMux *dmux, int flags)
723{
724 GLint success;
725 char frag[4096];
726 char *buffer = frag;
727 ShaderProgram *prog = (ShaderProgram*) malloc(sizeof(ShaderProgram));
728
729 prog->left = prog->right = NULL;
730 prog->usesT0 = prog->usesT1 = prog->usesCol = prog->usesNoise = 0;
731 prog->combine = dmux->combine;
732 prog->flags = flags;
733 prog->vertex = _vertex_shader;
734
735 for(int i=0; i < ((flags & SC_2CYCLE) ? 4 : 2); i++)
736 {
737 //make sure were not ignoring cycle:
738 if ((dmux->flags&(1<<i)) == 0)
739 {
740 for(int j=0;j<4;j++)
741 {
742 prog->usesT0 |= (dmux->decode[i][j] == TEXEL0 || dmux->decode[i][j] == TEXEL0_ALPHA);
743 prog->usesT1 |= (dmux->decode[i][j] == TEXEL1 || dmux->decode[i][j] == TEXEL1_ALPHA);
744 prog->usesCol |= (dmux->decode[i][j] == SHADE || dmux->decode[i][j] == SHADE_ALPHA);
745 prog->usesNoise |= (dmux->decode[i][j] == NOISE);
746 }
747 }
748 }
749
750 buffer += sprintf(buffer, "%s", _frag_header);
751 if (prog->usesT0)
752 buffer += sprintf(buffer, "lowp vec4 lTex0 = texture2D(uTex0, vTexCoord0); \n");
753 if (prog->usesT1)
754 buffer += sprintf(buffer, "lowp vec4 lTex1 = texture2D(uTex1, vTexCoord1); \n");
755 if (prog->usesNoise)
756 buffer += sprintf(buffer, "lowp vec4 lNoise = texture2D(uNoise, (1.0 / 1024.0) * gl_FragCoord.st); \n");
757
758 for(int i = 0; i < ((flags & SC_2CYCLE) ? 2 : 1); i++)
759 {
760 if ((dmux->flags&(1<<(i*2))) == 0)
761 {
762 buffer += sprintf(buffer, "lFragColor.rgb = (%s - %s) * %s + %s; \n",
763 _color_param_str(dmux->decode[i*2][0]),
764 _color_param_str(dmux->decode[i*2][1]),
765 _color_param_str(dmux->decode[i*2][2]),
766 _color_param_str(dmux->decode[i*2][3])
767 );
768 }
769
770 if ((dmux->flags&(1<<(i*2+1))) == 0)
771 {
772 buffer += sprintf(buffer, "lFragColor.a = (%s - %s) * %s + %s; \n",
773 _alpha_param_str(dmux->decode[i*2+1][0]),
774 _alpha_param_str(dmux->decode[i*2+1][1]),
775 _alpha_param_str(dmux->decode[i*2+1][2]),
776 _alpha_param_str(dmux->decode[i*2+1][3])
777 );
778 }
779 buffer += sprintf(buffer, "gl_FragColor = lFragColor; \n");
780 };
781
782 //fog
783 if (flags&SC_FOGENABLED)
784 {
785 buffer += sprintf(buffer, "gl_FragColor = mix(gl_FragColor, uFogColor, vFactor); \n");
786 }
787
788 //alpha function
789 if (flags&SC_ALPHAENABLED)
790 {
791 if (flags&SC_ALPHAGREATER)
792 buffer += sprintf(buffer, "if (gl_FragColor.a < uAlphaRef) %s;\n", config.hackAlpha ? "gl_FragColor.a = 0" : "discard");
793 else
794 buffer += sprintf(buffer, "if (gl_FragColor.a <= uAlphaRef) %s;\n", config.hackAlpha ? "gl_FragColor.a = 0" : "discard");
795 }
796 buffer += sprintf(buffer, "} \n\n");
797 *buffer = 0;
798
799#ifdef PRINT_SHADER
800 LOG(LOG_VERBOSE, "=============================================================\n");
801 LOG(LOG_VERBOSE, "Combine=0x%llx flags=0x%x dmux flags=0x%x\n", prog->combine.mux, flags, dmux->flags);
802 LOG(LOG_VERBOSE, "Num=%i \t usesT0=%i usesT1=%i usesCol=%i usesNoise=%i\n", scProgramCount, prog->usesT0, prog->usesT1, prog->usesCol, prog->usesNoise);
803 LOG(LOG_VERBOSE, "=============================================================\n");
804 LOG(LOG_VERBOSE, "%s", frag);
805 LOG(LOG_VERBOSE, "=============================================================\n");
806#endif
807
808 prog->program = glCreateProgram();
809
810 //Compile:
811 char *src[1];
812 src[0] = frag;
813 GLint len[1];
814 len[0] = min(4096, strlen(frag));
815 prog->fragment = glCreateShader(GL_FRAGMENT_SHADER);
816
817 glShaderSource(prog->fragment, 1, (const char**) src, len);
818 glCompileShader(prog->fragment);
819
820
821 glGetShaderiv(prog->fragment, GL_COMPILE_STATUS, &success);
822 if (!success)
823 {
824 _glcompiler_error(prog->fragment);
825 }
826
827 //link
828 _locate_attributes(prog);
829 glAttachShader(prog->program, prog->fragment);
830 glAttachShader(prog->program, prog->vertex);
831 glLinkProgram(prog->program);
832 glGetProgramiv(prog->program, GL_LINK_STATUS, &success);
833 if (!success)
834 {
835 _gllinker_error(prog->program);
836 }
837
838 //remove fragment shader:
839 glDeleteShader(prog->fragment);
840
841 _locate_uniforms(prog);
842 return prog;
843}
844