Skip to content

Commit d89ccf9

Browse files
mardyWinterMute
authored andcommitted
TEV: store raster color output in a TEV register
The GX_CC_RASC and GX_CA_RASA constants do not refer to the untextured vertex color, but only to the color being generated by the color channel associated with the current stage: while in some situation these two entities coincide, in the case of a lit object we do have two active color channels, and these constants can only be used to refer to one of them at a time. Furthermore, when we enter the texturing stage on a lit geometry, we pass GX_COLORNULL, meaning that no rasterizer color channel is associated, and here GX_CC_RASC and GX_CA_RASA only render black. Yet, the texture environment operations in OpenGL sometimes need to operate on the color emitted on the vertex by the rasterizer. The solution is to emit the result of the lighting operations not on GX_TEVPREV (which gets changed at each stage), but on a well-named register (one of GX_TEVREG0 - GX_TEVREG2), which later stages can then refer to.
1 parent 342d989 commit d89ccf9

File tree

3 files changed

+53
-38
lines changed

3 files changed

+53
-38
lines changed

src/gc_gl.c

+13-5
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,14 @@ static void setup_fog()
20412041

20422042
bool _ogx_setup_render_stages()
20432043
{
2044+
u8 raster_output, raster_reg_index;
2045+
if (glparamstate.texture_enabled) {
2046+
raster_reg_index = _ogx_gpu_resources->tevreg_first++;
2047+
raster_output = GX_TEVREG0 + raster_reg_index;
2048+
} else {
2049+
raster_output = GX_TEVPREV;
2050+
}
2051+
20442052
if (glparamstate.lighting.enabled) {
20452053
LightMasks light_mask = prepare_lighting();
20462054

@@ -2135,14 +2143,14 @@ bool _ogx_setup_render_stages()
21352143
GX_SetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
21362144
GX_SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_APREV, GX_CA_RASA, GX_CA_ZERO);
21372145
// Operation: Sum a + d
2138-
GX_SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
2139-
GX_SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
2146+
GX_SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, raster_output);
2147+
GX_SetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, raster_output);
21402148
// Select COLOR1A1 for the rasterizer, disable all textures
21412149
GX_SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORDNULL, GX_TEXMAP_DISABLE, GX_COLOR1A1);
21422150

21432151
if (glparamstate.texture_enabled) {
2144-
// Do not select any raster value, Texture 0 for texture rasterizer and TEXCOORD0 slot for tex coordinates
2145-
_ogx_setup_texture_stages(GX_CC_CPREV, GX_CA_APREV, GX_COLORNULL);
2152+
// Do not select any raster color channel
2153+
_ogx_setup_texture_stages(raster_reg_index, GX_COLORNULL);
21462154
}
21472155
} else {
21482156
// Unlit scene
@@ -2167,7 +2175,7 @@ bool _ogx_setup_render_stages()
21672175

21682176
if (glparamstate.texture_enabled) {
21692177
// Select COLOR0A0 for the rasterizer, Texture 0 for texture rasterizer and TEXCOORD0 slot for tex coordinates
2170-
_ogx_setup_texture_stages(GX_CC_RASC, GX_CA_RASA, GX_COLOR0A0);
2178+
_ogx_setup_texture_stages(raster_reg_index, GX_COLOR0A0);
21712179
} else {
21722180
// Use one stage only
21732181
_ogx_gpu_resources->tevstage_first += 1;

src/texture_unit.c

+39-31
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ typedef struct {
7878
} TevSource;
7979

8080
static TevSource gl_rgbsource_to_gx(GLenum source, GLenum operand,
81-
u8 prev_rgb, u8 prev_alpha)
81+
u8 prev_rgb, u8 prev_alpha,
82+
u8 raster_rgb, u8 raster_alpha)
8283
{
8384
TevSource ret = { GX_CC_ZERO, false };
8485
if (operand == GL_ONE_MINUS_SRC_COLOR) {
@@ -105,16 +106,16 @@ static TevSource gl_rgbsource_to_gx(GLenum source, GLenum operand,
105106
case GL_CONSTANT: ret.source = GX_CC_KONST; break;
106107
case GL_PRIMARY_COLOR:
107108
switch (operand) {
108-
case GL_SRC_COLOR: ret.source = GX_CC_RASC; break;
109-
case GL_SRC_ALPHA: ret.source = GX_CC_RASA; break;
109+
case GL_SRC_COLOR: ret.source = raster_rgb; break;
110+
case GL_SRC_ALPHA: ret.source = raster_alpha; break;
110111
}
111112
break;
112113
}
113114
return ret;
114115
}
115116

116117
static TevSource gl_alphasource_to_gx(GLenum source, GLenum operand,
117-
u8 prev_alpha)
118+
u8 prev_alpha, u8 raster_alpha)
118119
{
119120
TevSource ret = { GX_CA_ZERO, false };
120121
/* For the alpha channel, operand can only be either GL_SRC_ALPHA or
@@ -127,7 +128,7 @@ static TevSource gl_alphasource_to_gx(GLenum source, GLenum operand,
127128
case GL_TEXTURE: ret.source = GX_CA_TEXA; break;
128129
case GL_PREVIOUS: ret.source = prev_alpha; break;
129130
case GL_CONSTANT: ret.source = GX_CA_KONST; break;
130-
case GL_PRIMARY_COLOR: ret.source = GX_CA_RASA; break;
131+
case GL_PRIMARY_COLOR: ret.source = raster_alpha; break;
131132
}
132133
return ret;
133134
}
@@ -339,28 +340,21 @@ static TevInput compute_tev_input(GLenum combine_func, u8 stage, GXColor color,
339340
return ret;
340341
}
341342

342-
static void setup_combine_operation(const OgxTextureUnit *te,
343-
u8 stage)
343+
static void setup_combine_operation(const OgxTextureUnit *te, u8 stage,
344+
u8 prev_rgb, u8 prev_alpha,
345+
u8 raster_rgb, u8 raster_alpha)
344346
{
345347
TevSource source_rgb[3];
346348
TevSource source_alpha[3];
347349

348-
u8 prev_rgb, prev_alpha;
349-
if (stage == GX_TEVSTAGE0) {
350-
prev_rgb = GX_CC_RASC;
351-
prev_alpha = GX_CA_RASA;
352-
} else {
353-
prev_rgb = GX_CC_CPREV;
354-
prev_alpha = GX_CA_APREV;
355-
}
356-
357350
for (int i = 0; i < 3; i++) {
358351
source_rgb[i] = gl_rgbsource_to_gx(te->source_rgb[i],
359352
te->operand_rgb[i],
360-
prev_rgb, prev_alpha);
353+
prev_rgb, prev_alpha,
354+
raster_rgb, raster_alpha);
361355
source_alpha[i] = gl_alphasource_to_gx(te->source_alpha[i],
362356
te->operand_alpha[i],
363-
prev_alpha);
357+
prev_alpha, raster_alpha);
364358
}
365359

366360
TevInput rgb = compute_tev_input(te->combine_rgb, stage, te->color,
@@ -379,7 +373,8 @@ static void setup_combine_operation(const OgxTextureUnit *te,
379373

380374
static void setup_texture_stage(const OgxTextureUnit *tu,
381375
u8 stage, u8 tex_coord, u8 tex_map,
382-
u8 raster_color, u8 raster_alpha,
376+
u8 prev_rgb, u8 prev_alpha,
377+
u8 raster_rgb, u8 raster_alpha,
383378
u8 channel)
384379
{
385380
switch (tu->mode) {
@@ -391,25 +386,26 @@ static void setup_texture_stage(const OgxTextureUnit *tu,
391386
case GL_ADD:
392387
/* In data: d: Texture Color a: raster value, Operation: a+d
393388
* Alpha gets multiplied. */
394-
GX_SetTevColorIn(stage, raster_color, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
395-
GX_SetTevAlphaIn(stage, GX_CA_ZERO, raster_alpha, GX_CA_TEXA, GX_CA_ZERO);
389+
GX_SetTevColorIn(stage, prev_rgb, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
390+
GX_SetTevAlphaIn(stage, GX_CA_ZERO, prev_alpha, GX_CA_TEXA, GX_CA_ZERO);
396391
break;
397392
case GL_BLEND:
398393
/* In data: c: Texture Color, a: raster value, b: tex env
399394
* Operation: a(1-c)+b*c
400395
* Until we implement GL_TEXTURE_ENV_COLOR, use white (GX_CC_ONE) for
401396
* the tex env color. */
402-
GX_SetTevColorIn(stage, raster_color, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
403-
GX_SetTevAlphaIn(stage, GX_CA_ZERO, raster_alpha, GX_CA_TEXA, GX_CA_ZERO);
397+
GX_SetTevColorIn(stage, prev_rgb, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
398+
GX_SetTevAlphaIn(stage, GX_CA_ZERO, prev_alpha, GX_CA_TEXA, GX_CA_ZERO);
404399
break;
405400
case GL_COMBINE:
406-
setup_combine_operation(tu, stage);
401+
setup_combine_operation(tu, stage, prev_rgb, prev_alpha,
402+
raster_rgb, raster_alpha);
407403
break;
408404
case GL_MODULATE:
409405
default:
410406
// In data: c: Texture Color b: raster value, Operation: b*c
411-
GX_SetTevColorIn(stage, GX_CC_ZERO, raster_color, GX_CC_TEXC, GX_CC_ZERO);
412-
GX_SetTevAlphaIn(stage, GX_CA_ZERO, raster_alpha, GX_CA_TEXA, GX_CA_ZERO);
407+
GX_SetTevColorIn(stage, GX_CC_ZERO, prev_rgb, GX_CC_TEXC, GX_CC_ZERO);
408+
GX_SetTevAlphaIn(stage, GX_CA_ZERO, prev_alpha, GX_CA_TEXA, GX_CA_ZERO);
413409
break;
414410
}
415411
if (!tu->mode != GL_COMBINE) {
@@ -437,9 +433,20 @@ static void setup_texture_stage_matrix(const OgxTextureUnit *tu,
437433
GX_LoadTexMtxImm(m, dtt_matrix, GX_MTX3x4);
438434
}
439435

440-
void _ogx_setup_texture_stages(u8 raster_color, u8 raster_alpha,
441-
u8 channel)
436+
void _ogx_setup_texture_stages(u8 raster_reg_index, u8 channel)
442437
{
438+
u8 raster_rgb, raster_alpha;
439+
if (channel != GX_COLORNULL) {
440+
raster_rgb = GX_CC_RASC;
441+
raster_alpha = GX_CA_RASA;
442+
} else {
443+
raster_rgb = GX_CC_C0 + raster_reg_index * 2;
444+
raster_alpha = GX_CA_A0 + raster_reg_index;
445+
}
446+
447+
u8 prev_rgb = raster_rgb;
448+
u8 prev_alpha = raster_alpha;
449+
443450
/* This variable holds the number of enabled texture units for which the
444451
* client provided texture coordinates (not generated, but literally a
445452
* GX_VA_TEX* array was specified). */
@@ -466,7 +473,8 @@ void _ogx_setup_texture_stages(u8 raster_color, u8 raster_alpha,
466473
u8 dtt_matrix = GX_DTTMTX0 + _ogx_gpu_resources->dttmtx_first++ * 3;
467474

468475
setup_texture_stage(tu, stage, tex_coord, tex_map,
469-
raster_color, raster_alpha, channel);
476+
prev_rgb, prev_alpha,
477+
raster_rgb, raster_alpha, channel);
470478

471479
setup_texture_stage_matrix(tu, dtt_matrix);
472480
if (tu->gen_enabled) {
@@ -478,7 +486,7 @@ void _ogx_setup_texture_stages(u8 raster_color, u8 raster_alpha,
478486

479487
/* All texture stages after the first one get their vertex color from
480488
* the previous stage */
481-
raster_color = GX_CC_CPREV;
482-
raster_alpha = GX_CA_APREV;
489+
prev_rgb = GX_CC_CPREV;
490+
prev_alpha = GX_CA_APREV;
483491
}
484492
}

src/texture_unit.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
3636
extern "C" {
3737
#endif
3838

39-
void _ogx_setup_texture_stages(u8 raster_color, u8 raster_alpha,
40-
u8 channel);
39+
void _ogx_setup_texture_stages(u8 raster_reg_index, u8 channel);
4140

4241
#ifdef __cplusplus
4342
} // extern C

0 commit comments

Comments
 (0)