Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/Blender.cpp
2 views
1
/*
2
Copyright (C) 2003 Rice1964
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
*/
18
19
#include "Render.h"
20
21
const char * sc_szBlClr[4] = { "In", "Mem", "Bl", "Fog" };
22
const char * sc_szBlA1[4] = { "AIn", "AFog", "AShade", "0" };
23
const char * sc_szBlA2[4] = { "1-A", "AMem", "1", "0" };
24
25
//========================================================================
26
void CBlender::InitBlenderMode(void) // Set Alpha Blender mode
27
{
28
//1. Z_COMPARE -- Enable / Disable Zbuffer compare
29
// 1 - Enable ZBuffer
30
// 0 - Disable ZBuffer
31
32
//2. Z_UPDATE -- Enable / Disable Zbuffer update
33
// 1 - Enable ZBuffer writeable
34
// 0 - Zbuffer not writeable
35
36
//3. AA_EN and IM_RD -- Anti-Alias
37
// AA_EN - Enable anti-aliase
38
// AA_EN | IM_RD - Reduced anti-aliase
39
// IM_RD - ??
40
// - - Disable anti-aliase
41
42
//4. ZMode
43
// #define ZMODE_OPA 0 -- Usually used with Z_COMPARE and Z_UPDATE
44
// or used without neither Z_COMPARE or Z_UPDATE
45
// if used with Z_COMPARE and Z_UPDATE, then this is
46
// the regular ZBuffer mode, with compare and update
47
// #define ZMODE_INTER 0x400
48
// #define ZMODE_XLU 0x800 -- Usually used with Z_COMPARE, but not with Z_UPDATE
49
// Do only compare, no zbuffer update.
50
// Not output if the z value is the same
51
// #define ZMODE_DEC 0xc00 -- Usually used with Z_COMPARE, but not with Z_UPDATE
52
// Do only compare, no update, but because this is
53
// decal mode, so image should be updated even
54
// the z value is the same as compared.
55
56
CRender *render = CRender::g_pRender;
57
58
// Alpha Blender Modes
59
60
/*
61
6. FORCE_BL - Alpha blending at blender stage
62
1 - Enable alpha blending at blender
63
0 - Disable alpha blending at blender
64
65
Alpha blending at blender is usually used to render XLU surface
66
if enabled, then use the blending setting of C1 and C2
67
68
7. ALPHA_CVG_SEL - Output full alpha from the color combiner, usually not used together
69
with FORCE_BL. If it is used together with FORCE_BL, then ignore this
70
71
8. CVG_X_ALPHA - Before output the color from color combiner, mod it with alpha
72
73
9. TEX_EDGE - Ignore this
74
75
10.CLR_ON_CVG - Used with XLU surfaces, ignore it
76
77
11.CVG_DST
78
#define CVG_DST_CLAMP 0 - Usually used with OPA surface
79
#define CVG_DST_WRAP 0x100 - Usually used with XLU surface or OPA line
80
#define CVG_DST_FULL 0x200 - ?
81
#define CVG_DST_SAVE 0x300 - ?
82
83
84
Possible Blending Inputs:
85
86
In - Input from color combiner
87
Mem - Input from current frame buffer
88
Fog - Fog generator
89
BL - Blender
90
91
Possible Blending Factors:
92
A-IN - Alpha from color combiner
93
A-MEM - Alpha from current frame buffer
94
(1-A) -
95
A-FOG - Alpha of fog color
96
A-SHADE - Alpha of shade
97
1 - 1
98
0 - 0
99
*/
100
#define BLEND_NOOP 0x0000
101
102
#define BLEND_NOOP5 0xcc48 // Fog * 0 + Mem * 1
103
#define BLEND_NOOP4 0xcc08 // Fog * 0 + In * 1
104
#define BLEND_FOG_ASHADE 0xc800
105
#define BLEND_FOG_3 0xc000 // Fog * AIn + In * 1-A
106
#define BLEND_FOG_MEM 0xc440 // Fog * AFog + Mem * 1-A
107
#define BLEND_FOG_APRIM 0xc400 // Fog * AFog + In * 1-A
108
109
#define BLEND_BLENDCOLOR 0x8c88
110
#define BLEND_BI_AFOG 0x8400 // Bl * AFog + In * 1-A
111
#define BLEND_BI_AIN 0x8040 // Bl * AIn + Mem * 1-A
112
113
#define BLEND_MEM 0x4c40 // Mem*0 + Mem*(1-0)?!
114
#define BLEND_FOG_MEM_3 0x44c0 // Mem * AFog + Fog * 1-A
115
116
#define BLEND_NOOP3 0x0c48 // In * 0 + Mem * 1
117
#define BLEND_PASS 0x0c08 // In * 0 + In * 1
118
#define BLEND_FOG_MEM_IN_MEM 0x0440 // In * AFog + Mem * 1-A
119
#define BLEND_FOG_MEM_FOG_MEM 0x04c0 // In * AFog + Fog * 1-A
120
#define BLEND_OPA 0x0044 // In * AIn + Mem * AMem
121
#define BLEND_XLU 0x0040
122
#define BLEND_MEM_ALPHA_IN 0x4044 // Mem * AIn + Mem * AMem
123
124
125
uint32 blendmode_1 = (uint32)( gRDP.otherMode.blender & 0xcccc );
126
uint32 blendmode_2 = (uint32)( gRDP.otherMode.blender & 0x3333 );
127
uint32 cycletype = gRDP.otherMode.cycle_type;
128
129
switch( cycletype )
130
{
131
case CYCLE_TYPE_FILL:
132
//BlendFunc(BLEND_ONE, BLEND_ZERO);
133
//Enable();
134
Disable();
135
break;
136
case CYCLE_TYPE_COPY:
137
//Disable();
138
BlendFunc(BLEND_ONE, BLEND_ZERO);
139
Enable();
140
break;
141
case CYCLE_TYPE_2:
142
if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp )
143
{
144
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
145
Enable();
146
break;
147
}
148
149
/*
150
if( gRDP.otherMode.alpha_cvg_sel && gRDP.otherMode.cvg_x_alpha==0 )
151
{
152
BlendFunc(BLEND_ONE, BLEND_ZERO);
153
Enable();
154
break;
155
}
156
*/
157
158
switch( blendmode_1+blendmode_2 )
159
{
160
case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1
161
case BLEND_FOG_APRIM+(BLEND_PASS>>2):
162
BlendFunc(BLEND_ONE, BLEND_ZERO);
163
if( gRDP.otherMode.alpha_cvg_sel )
164
{
165
Enable();
166
}
167
else
168
{
169
Disable();
170
}
171
172
render->SetAlphaTestEnable( ((gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3)==1 ? TRUE : FALSE);
173
break;
174
case BLEND_PASS+(BLEND_OPA>>2):
175
// 0x0c19
176
// Cycle1: In * 0 + In * 1
177
// Cycle2: In * AIn + Mem * AMem
178
if( gRDP.otherMode.cvg_x_alpha && gRDP.otherMode.alpha_cvg_sel )
179
{
180
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
181
Enable();
182
}
183
else
184
{
185
BlendFunc(BLEND_ONE, BLEND_ZERO);
186
Enable();
187
}
188
break;
189
case BLEND_PASS + (BLEND_XLU>>2):
190
// 0x0c18
191
// Cycle1: In * 0 + In * 1
192
// Cycle2: In * AIn + Mem * 1-A
193
case BLEND_FOG_ASHADE + (BLEND_XLU>>2):
194
//Cycle1: Fog * AShade + In * 1-A
195
//Cycle2: In * AIn + Mem * 1-A
196
case BLEND_FOG_APRIM + (BLEND_XLU>>2):
197
//Cycle1: Fog * AFog + In * 1-A
198
//Cycle2: In * AIn + Mem * 1-A
199
//case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
200
//Cycle1: In * AFog + Fog * 1-A
201
//Cycle2: In * AIn + Mem * AMem
202
case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2):
203
//Cycle1: In * AFog + Fog * 1-A
204
//Cycle2: In * 0 + In * 1
205
case BLEND_XLU + (BLEND_XLU>>2):
206
//Cycle1: Fog * AFog + In * 1-A
207
//Cycle2: In * AIn + Mem * 1-A
208
case BLEND_BI_AFOG + (BLEND_XLU>>2):
209
//Cycle1: Bl * AFog + In * 1-A
210
//Cycle2: In * AIn + Mem * 1-A
211
case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2):
212
//Cycle1: In * AIn + Mem * 1-A
213
//Cycle2: In * AFog + Mem * 1-A
214
case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2):
215
//Cycle1: In * 0 + In * 1
216
//Cycle2: In * AFog + Mem * 1-A
217
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
218
Enable();
219
break;
220
case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
221
//Cycle1: In * AFog + Fog * 1-A
222
//Cycle2: In * AIn + Mem * AMem
223
BlendFunc(BLEND_ONE, BLEND_ZERO);
224
Enable();
225
break;
226
227
case BLEND_FOG_APRIM + (BLEND_OPA>>2):
228
// For Golden Eye
229
//Cycle1: Fog * AFog + In * 1-A
230
//Cycle2: In * AIn + Mem * AMem
231
case BLEND_FOG_ASHADE + (BLEND_OPA>>2):
232
//Cycle1: Fog * AShade + In * 1-A
233
//Cycle2: In * AIn + Mem * AMem
234
case BLEND_BI_AFOG + (BLEND_OPA>>2):
235
//Cycle1: Bl * AFog + In * 1-A
236
//Cycle2: In * AIn + Mem * 1-AMem
237
case BLEND_FOG_ASHADE + (BLEND_NOOP>>2):
238
//Cycle1: Fog * AShade + In * 1-A
239
//Cycle2: In * AIn + In * 1-A
240
case BLEND_NOOP + (BLEND_OPA>>2):
241
//Cycle1: In * AIn + In * 1-A
242
//Cycle2: In * AIn + Mem * AMem
243
case BLEND_NOOP4 + (BLEND_NOOP>>2):
244
//Cycle1: Fog * AIn + In * 1-A
245
//Cycle2: In * 0 + In * 1
246
case BLEND_FOG_ASHADE+(BLEND_PASS>>2):
247
//Cycle1: Fog * AShade + In * 1-A
248
//Cycle2: In * 0 + In * 1
249
case BLEND_FOG_3+(BLEND_PASS>>2):
250
BlendFunc(BLEND_ONE, BLEND_ZERO);
251
Enable();
252
break;
253
case BLEND_FOG_ASHADE+0x0301:
254
// c800 - Cycle1: Fog * AShade + In * 1-A
255
// 0301 - Cycle2: In * 0 + In * AMem
256
BlendFunc(BLEND_SRCALPHA, BLEND_ZERO);
257
Enable();
258
break;
259
case 0x0c08+0x1111:
260
// 0c08 - Cycle1: In * 0 + In * 1
261
// 1111 - Cycle2: Mem * AFog + Mem * AMem
262
BlendFunc(BLEND_ZERO, BLEND_DESTALPHA);
263
Enable();
264
break;
265
default:
266
#ifdef DEBUGGER
267
if( pauseAtNext )
268
{
269
uint32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3;
270
uint32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3;
271
uint32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3;
272
uint32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3;
273
274
uint32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3;
275
uint32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3;
276
uint32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3;
277
uint32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3;
278
279
TRACE0("Unknown Blender Mode: 2 cycle");
280
DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t%04x - Cycle2:\t%s * %s + %s * %s", blendmode_1,
281
sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1], blendmode_2,
282
sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]);
283
284
}
285
#endif
286
if( blendmode_2 == (BLEND_PASS>>2) )
287
{
288
BlendFunc(BLEND_ONE, BLEND_ZERO);
289
}
290
else
291
{
292
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
293
}
294
Enable();
295
break;
296
}
297
break;
298
default: // 1/2 Cycle or Copy
299
if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp && blendmode_1 != BLEND_FOG_ASHADE )
300
{
301
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
302
Enable();
303
break;
304
}
305
if( gRDP.otherMode.force_bl && options.enableHackForGames == HACK_FOR_COMMANDCONQUER )
306
{
307
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
308
Enable();
309
break;
310
}
311
312
#ifdef DEBUGGER
313
//if( (blendmode_1>>2) != blendmode_2 )
314
//{
315
// DebuggerAppendMsg("Warning: in 1 cycle mode, blend1!=blend2");
316
//}
317
#endif
318
319
switch ( blendmode_1 )
320
//switch ( blendmode_2<<2 )
321
{
322
case BLEND_XLU: // IN * A_IN + MEM * (1-A_IN)
323
case BLEND_BI_AIN: // Bl * AIn + Mem * 1-A
324
case BLEND_FOG_MEM: // c440 - Cycle1: Fog * AFog + Mem * 1-A
325
case BLEND_FOG_MEM_IN_MEM: // c440 - Cycle1: In * AFog + Mem * 1-A
326
case BLEND_BLENDCOLOR: //Bl * 0 + Bl * 1
327
case 0x00c0: //In * AIn + Fog * 1-A
328
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
329
Enable();
330
break;
331
case BLEND_MEM_ALPHA_IN: // Mem * AIn + Mem * AMem
332
BlendFunc(BLEND_ZERO, BLEND_DESTALPHA);
333
Enable();
334
break;
335
case BLEND_PASS: // IN * 0 + IN * 1
336
BlendFunc(BLEND_ONE, BLEND_ZERO);
337
if( gRDP.otherMode.alpha_cvg_sel )
338
{
339
Enable();
340
}
341
else
342
{
343
Disable();
344
}
345
break;
346
case BLEND_OPA: // IN * A_IN + MEM * A_MEM
347
if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
348
{
349
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
350
}
351
else
352
{
353
BlendFunc(BLEND_ONE, BLEND_ZERO);
354
}
355
Enable();
356
break;
357
case BLEND_NOOP: // IN * A_IN + IN * (1 - A_IN)
358
case BLEND_FOG_ASHADE: // Fog * AShade + In * 1-A
359
case BLEND_FOG_MEM_3: // Mem * AFog + Fog * 1-A
360
case BLEND_BI_AFOG: // Bl * AFog + In * 1-A
361
BlendFunc(BLEND_ONE, BLEND_ZERO);
362
Enable();
363
break;
364
case BLEND_FOG_APRIM: // Fog * AFog + In * 1-A
365
BlendFunc(BLEND_INVSRCALPHA, BLEND_ZERO);
366
Enable();
367
break;
368
case BLEND_NOOP3: // In * 0 + Mem * 1
369
case BLEND_NOOP5: // Fog * 0 + Mem * 1
370
BlendFunc(BLEND_ZERO, BLEND_ONE);
371
Enable();
372
break;
373
case BLEND_MEM: // Mem * 0 + Mem * 1-A
374
// WaveRace
375
BlendFunc(BLEND_ZERO, BLEND_ONE);
376
Enable();
377
break;
378
default:
379
#ifdef DEBUGGER
380
if( pauseAtNext )
381
{
382
uint32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3;
383
uint32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3;
384
uint32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3;
385
uint32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3;
386
387
uint32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3;
388
uint32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3;
389
uint32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3;
390
uint32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3;
391
392
TRACE0("Unknown Blender Mode: 1 cycle");
393
DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t\tCycle2:\t%s * %s + %s * %s", blendmode_1,
394
sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1],
395
sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]);
396
}
397
#endif
398
BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
399
Enable();
400
render->SetAlphaTestEnable(TRUE);
401
break;
402
}
403
}
404
}
405
406
407