/[pcsx2_0.9.7]/trunk/plugins/zzogl-pg/opengl/ZZoglFlush.cpp
ViewVC logotype

Contents of /trunk/plugins/zzogl-pg/opengl/ZZoglFlush.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 401 - (show annotations) (download)
Fri Feb 25 17:31:09 2011 UTC (8 years, 11 months ago) by william
File size: 74494 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4358 local: v0.9.7.313-latest) in ./trunk
1 /* ZZ Open GL graphics plugin
2 * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
3 * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 // Realization of Flush -- drawing function of GS
21
22 #include <stdlib.h>
23
24 #include "GS.h"
25 #include "Mem.h"
26 #include "targets.h"
27 #include "ZZoglFlushHack.h"
28 #include "ZZoglShaders.h"
29 #include "ZZClut.h"
30 #include <math.h>
31
32 //------------------ Defines
33 #ifndef ZEROGS_DEVBUILD
34
35 #define INC_GENVARS()
36 #define INC_TEXVARS()
37 #define INC_ALPHAVARS()
38 #define INC_RESOLVE()
39
40 #define g_bUpdateEffect 0
41 #define g_bSaveTex 0
42 bool g_bSaveTrans = 0;
43 #define g_bSaveResolved 0
44
45 #else // defined(ZEROGS_DEVBUILD)
46
47 #define INC_GENVARS() ++g_nGenVars
48 #define INC_TEXVARS() ++g_nTexVars
49 #define INC_ALPHAVARS() ++g_nAlphaVars
50 #define INC_RESOLVE() ++g_nResolve
51
52 bool g_bSaveTrans = 0;
53 bool g_bUpdateEffect = 0;
54 bool g_bSaveTex = 0; // saves the curent texture
55 bool g_bSaveResolved = 0;
56 #endif // !defined(ZEROGS_DEVBUILD)
57
58 #define STENCIL_ALPHABIT 1 // if set, dest alpha >= 0x80
59 #define STENCIL_PIXELWRITE 2 // if set, pixel just written (reset after every Flush)
60 #define STENCIL_FBA 4 // if set, just written pixel's alpha >= 0 (reset after every Flush)
61 #define STENCIL_SPECIAL 8 // if set, indicates that pixel passed its alpha test (reset after every Flush)
62 //#define STENCIL_PBE 16
63 #define STENCIL_CLEAR (2|4|8|16)
64
65 void Draw(const VB& curvb)
66 {
67 glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount);
68 }
69
70 #define GL_BLEND_RGB(src, dst) { \
71 s_srcrgb = src; \
72 s_dstrgb = dst; \
73 zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
74 }
75
76 #define GL_BLEND_ALPHA(src, dst) { \
77 s_srcalpha = src; \
78 s_dstalpha = dst; \
79 zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
80 }
81
82 #define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \
83 s_srcrgb = srcrgb; \
84 s_dstrgb = dstrgb; \
85 s_srcalpha = srcalpha; \
86 s_dstalpha = dstalpha; \
87 zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
88 }
89
90 #define GL_ZTEST(enable) { \
91 if (enable) glEnable(GL_DEPTH_TEST); \
92 else glDisable(GL_DEPTH_TEST); \
93 }
94
95 #define GL_ALPHATEST(enable) { \
96 if( enable ) glEnable(GL_ALPHA_TEST); \
97 else glDisable(GL_ALPHA_TEST); \
98 }
99
100 #define GL_BLENDEQ_RGB(eq) { \
101 s_rgbeq = eq; \
102 zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
103 }
104
105 #define GL_BLENDEQ_ALPHA(eq) { \
106 s_alphaeq = eq; \
107 zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
108 }
109
110 #define COLORMASK_RED 1
111 #define COLORMASK_GREEN 2
112 #define COLORMASK_BLUE 4
113 #define COLORMASK_ALPHA 8
114 #define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA))
115
116 // ----------------- Types
117 //------------------ Dummies
118
119 //------------------ variables
120
121 extern int g_nDepthBias;
122 extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it.
123 bool g_bUpdateStencil = 1;
124
125 extern ZZshProgram g_psprog; // 2 -- ZZ
126
127 // local alpha blending settings
128 static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT // ZZ
129
130
131 static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT }; // ZZ
132 static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; //ZZ
133 static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL }; // ZZ
134
135 // used for afail case
136 static const u32 g_dwReverseAlphaCmp[] = { GL_ALWAYS, GL_NEVER, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_EQUAL };
137 static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER };
138
139 /////////////////////
140 // graphics resources
141 #define s_bForceTexFlush 1 // ZZ
142 static u32 s_ptexCurSet[2] = {0};
143 static u32 s_ptexNextSet[2] = {0}; // ZZ
144
145
146 extern vector<u32> s_vecTempTextures; // temporary textures, released at the end of every frame
147 extern bool s_bTexFlush;
148 extern int g_nCurVBOIndex;
149 bool s_bWriteDepth = false;
150 bool s_bDestAlphaTest = false;
151 int s_ClutResolve = 0; // ZZ
152 int g_nDepthUsed = 0; // ffx2 pal movies
153 int s_nWriteDepthCount = 0; // ZZ
154 int s_nWriteDestAlphaTest = 0; // ZZ
155
156 ////////////////////
157 // State parameters
158 static float4 vAlphaBlendColor; // used for GPU_COLOR
159
160 static bool bNeedBlendFactorInAlpha; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80)
161 static u32 s_dwColorWrite = 0xf; // the color write mask of the current target
162
163 typedef union
164 {
165 struct
166 {
167 u8 _bNeedAlphaColor; // set if vAlphaBlendColor needs to be set
168 u8 _b2XAlphaTest; // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values
169 // otherwise alpha testing needs to be done separately.
170 u8 _bDestAlphaColor; // set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1.
171 u8 _bAlphaClamping; // if first bit is set, do min; if second bit, do max
172 };
173
174 u32 _bAlphaState;
175 } g_flag_vars;
176
177 g_flag_vars g_vars;
178
179 //#define bNeedAlphaColor g_vars._bNeedAlphaColor
180 #define b2XAlphaTest g_vars._b2XAlphaTest
181 #define bDestAlphaColor g_vars._bDestAlphaColor
182 #define bAlphaClamping g_vars._bAlphaClamping
183
184 int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY // ZZ
185
186 //static alphaInfo s_alphaInfo; // ZZ
187
188 extern u8* g_pbyGSClut;
189 extern int ppf;
190
191 int s_nWireframeCount = 0;
192
193 //------------------ Namespace
194
195 VB vb[2];
196 float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
197 extern vector<GLuint> g_vboBuffers; // VBOs for all drawing commands
198
199 //u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set
200 Point AA = {0,0};
201
202 int icurctx = -1;
203
204 extern CRangeManager s_RangeMngr; // manages overwritten memory // zz
205 void FlushTransferRanges(const tex0Info* ptex); //zz
206
207 // use to update the state
208 void SetTexVariables(int context, FRAGMENTSHADER* pfragment); // zz
209 void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint); // zz
210 void SetAlphaVariables(const alphaInfo& ainfo); // zzz
211 //void ResetAlphaVariables();
212
213 inline void SetAlphaTestInt(pixTest curtest);
214
215 inline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor);
216 inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting);
217 inline void ProcessStencil(const VB& curvb);
218 inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor);
219 inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor); // zz
220
221 void SetContextTarget(int context);
222
223 void SetWriteDepth();
224 bool IsWriteDepth();
225 void SetDestAlphaTest();
226
227 //------------------ Code
228
229 inline float AlphaReferedValue(int aref)
230 {
231 return b2XAlphaTest ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ;
232 }
233
234 inline void SetAlphaTest(const pixTest& curtest)
235 {
236 // if s_dwColorWrite is nontrivial, than we should not off alphatest.
237 // This fix GOW and Okami.
238 if (!curtest.ate && USEALPHATESTING && (s_dwColorWrite != 2 && s_dwColorWrite != 14))
239 {
240 glDisable(GL_ALPHA_TEST);
241 }
242 else
243 {
244 glEnable(GL_ALPHA_TEST);
245 glAlphaFunc(g_dwAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref));
246 }
247 }
248
249 // Return, if tcc, aem or psm mode told us, than Alpha test should be used
250 // if tcc == 0 than no alpha used, aem used for alpha expanding and I am not sure
251 // that it's correct, psm -- color mode,
252 inline bool IsAlphaTestExpansion(tex0Info tex0)
253 {
254 return (tex0.tcc && gs.texa.aem && PSMT_ALPHAEXP(PIXEL_STORAGE_FORMAT(tex0)));
255 }
256
257 // Switch wireframe rendering off for first flush, so it's draw few solid primitives
258 inline void SwitchWireframeOff()
259 {
260 if (conf.wireframe())
261 {
262 if (s_nWireframeCount > 0)
263 {
264 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
265 }
266 }
267 }
268
269 // Switch wireframe rendering on, look at previous function
270 inline void SwitchWireframeOn()
271 {
272 if (conf.wireframe())
273 {
274 if (s_nWireframeCount > 0)
275 {
276 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
277 --s_nWireframeCount;
278 }
279 }
280 }
281
282 extern u32 ptexBilinearBlocks;
283
284 int GetTexFilter(const tex1Info& tex1)
285 {
286 // always force
287 if (conf.bilinear == 2) return 1;
288
289 int texfilter = 0;
290
291 if (conf.bilinear && ptexBilinearBlocks != 0)
292 {
293 if (tex1.mmin <= 1)
294 texfilter = tex1.mmin | tex1.mmag;
295 else
296 texfilter = tex1.mmag ? ((tex1.mmin + 2) & 5) : tex1.mmin;
297
298 texfilter = texfilter == 1 || texfilter == 4 || texfilter == 5;
299 }
300
301 return texfilter;
302 }
303
304 void ReloadEffects()
305 {
306 #ifdef ZEROGS_DEVBUILD
307
308 for (int i = 0; i < ArraySize(ppsTexture); ++i)
309 {
310 SAFE_RELEASE_PROG(ppsTexture[i].prog);
311 }
312
313 memset(ppsTexture, 0, sizeof(ppsTexture));
314
315 ZZshLoadExtraEffects();
316 #endif
317 }
318
319 long BufferNumber = 0;
320
321 // This is a debug function. It prints all buffer info and save current texture into the file, then prints the file name.
322 inline void VisualBufferMessage(int context)
323 {
324 #if defined(WRITE_PRIM_LOGS) && defined(_DEBUG)
325 BufferNumber++;
326 VB& curvb = vb[context];
327 static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"};
328 static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" };
329 static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" };
330 ZZLog::Debug_Log("**Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d", context, vb[context].nCount, curvb.prndr->fbp, curvb.zbuf.zbp, curvb.prndr->psm, curvb.zbuf.psm, curvb.prndr->fbw);
331 ZZLog::Debug_Log("prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x",
332 curvb.curprim.prim, curvb.curprim.iip, curvb.curprim.tme, curvb.curprim.fge, curvb.curprim.abe, curvb.curprim.aa1, curvb.curprim.fst, curvb.curprim.ctxt, curvb.curprim.fix);
333 ZZLog::Debug_Log("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d",
334 curvb.test.ate, patst[curvb.test.atst], curvb.test.aref, pafail[curvb.test.afail], curvb.test.date, curvb.test.datm, curvb.test.zte, pztst[curvb.test.ztst], curvb.fba.fba);
335 ZZLog::Debug_Log("alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d\n", curvb.alpha.a, curvb.alpha.b, curvb.alpha.c, curvb.alpha.d, curvb.alpha.fix, gs.pabe, gs.texa.aem, gs.texa.ta[0], gs.texa.ta[1]);
336 ZZLog::Debug_Log("tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d",
337 curvb.tex0.tbp0, curvb.tex0.tbw, curvb.tex0.psm, curvb.tex0.tw,
338 curvb.tex0.th, curvb.tex0.tcc, curvb.tex0.tfx, curvb.tex0.cbp,
339 curvb.tex0.cpsm, curvb.tex0.csm, curvb.tex0.csa, curvb.tex0.cld);
340 char* Name;
341 Name = NamedSaveTex(&curvb.tex0, 1);
342 ZZLog::Error_Log("TGA name '%s'.", Name);
343 free(Name);
344 ZZLog::Debug_Log("buffer %ld.\n", BufferNumber);
345 #endif
346 }
347
348 inline void SaveRendererTarget(VB& curvb)
349 {
350 #ifdef _DEBUG
351
352 // Needs a # after rndr to work...
353 // char str[255];
354 // sprintf(str, "rndr.tga");
355 // SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0);
356
357 #endif
358 }
359
360 // Stop effects in Developers mode
361 inline void FlushUpdateEffect()
362 {
363 #if defined(DEVBUILD)
364
365 if (g_bUpdateEffect)
366 {
367 ReloadEffects();
368 g_bUpdateEffect = 0;
369 }
370
371 #endif
372 }
373
374 // Check, maybe we cold skip flush
375 inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest)
376 {
377 if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || IsBadFrame(curvb))
378 {
379 curvb.nCount = 0;
380 return true;
381 }
382
383 return false;
384 }
385
386 // Transfer targets, that are located in current texture.
387 inline void FlushTransferRangesHelper(VB& curvb)
388 {
389 if (s_RangeMngr.ranges.size() > 0)
390 {
391 // don't want infinite loop, so set nCount to 0.
392 u32 prevcount = curvb.nCount;
393 curvb.nCount = 0;
394
395 FlushTransferRanges(curvb.curprim.tme ? &curvb.tex0 : NULL);
396
397 curvb.nCount += prevcount;
398 }
399 }
400
401 // If set bit for texture checking, do it. Maybe it's all.
402 inline bool FushTexDataHelper(VB& curvb)
403 {
404 if (curvb.bNeedFrameCheck || curvb.bNeedZCheck)
405 {
406 curvb.CheckFrame(curvb.curprim.tme ? curvb.tex0.tbp0 : 0);
407 }
408
409 if (curvb.bNeedTexCheck) // Zeydlitz want to try this
410 {
411 curvb.FlushTexData();
412
413 if (curvb.nCount == 0) return true;
414 }
415
416 return false;
417 }
418
419 // Null target mean that we do something really bad.
420 inline bool FlushCheckForNULLTarget(VB& curvb, int context)
421 {
422 if ((curvb.prndr == NULL) || (curvb.pdepth == NULL))
423 {
424 ERROR_LOG_SPAMA("Current render target NULL (ctx: %d)", context);
425 curvb.nCount = 0;
426 return true;
427 }
428
429 return false;
430 }
431
432 // O.k. A set of resolutions, we do before real flush. We do RangeManager, FrameCheck and
433 // ZCheck before this.
434 inline bool FlushInitialTest(VB& curvb, const pixTest& curtest, int context)
435 {
436 GL_REPORT_ERRORD();
437 assert(context >= 0 && context <= 1);
438
439 FlushUpdateEffect();
440
441 if (IsFlushNoNeed(curvb, curtest)) return true;
442
443 FlushTransferRangesHelper(curvb);
444
445 if (FushTexDataHelper(curvb)) return true;
446
447 GL_REPORT_ERRORD();
448
449 if (FlushCheckForNULLTarget(curvb, context)) return true;
450
451 return false;
452 }
453
454 inline void TargetLog(int& tbw, int& tbp0, int& tpsm, VB& curvb, bool miss)
455 {
456 #ifdef _DEBUG
457 if (tbp0 == 0x3600 && tbw == 0x100)
458 {
459 if (miss)
460 {
461 ZZLog::Debug_Log("Miss %x 0x%x %d", tbw, tbp0, tpsm);
462
463 typedef map<u32, CRenderTarget*> MAPTARGETS;
464
465 for (MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew)
466 {
467 ZZLog::Debug_Log("\tRender %x 0x%x %x", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
468 }
469
470 for (MAPTARGETS::iterator itnew = s_DepthRTs.mapTargets.begin(); itnew != s_DepthRTs.mapTargets.end(); ++itnew)
471 {
472 ZZLog::Debug_Log("\tDepth %x 0x%x %x", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
473 }
474
475 ZZLog::Debug_Log("\tCurvb 0x%x 0x%x 0x%x %x", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw);
476 }
477 else
478 ZZLog::Debug_Log("Hit %x 0x%x %x", tbw, tbp0, tpsm);
479 }
480 #endif
481 }
482
483 // Try to different approach if texture target was not found
484 inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb)
485 {
486 // This was incorrect code
487 CRenderTarget* ptextarg = NULL;
488
489 if (PSMT_ISZTEX(tpsm))
490 {
491 // try depth
492 ptextarg = s_DepthRTs.GetTarg(tbp0, tbw);
493 }
494
495 // I wonder if either of these hacks are useful, or if I can just remove them?
496 if ((conf.settings().reget) && (tpsm == PSMT8))
497 {
498 // check for targets with half the width. Break Valkyrie Chronicles
499 ptextarg = s_RTs.GetTarg(tbp0, tbw / 2);
500
501 if (ptextarg == NULL)
502 {
503 tbp0 &= ~0x7ff;
504 ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); // mgs3 hack
505
506 if (ptextarg == NULL)
507 {
508 // check the next level (mgs3)
509 tbp0 &= ~0xfff;
510 ptextarg = s_RTs.GetTarg(tbp0, tbw / 2); // mgs3 hack
511 }
512
513 if (ptextarg != NULL && ptextarg->start > tbp0*256)
514 {
515 // target beyond range, so ignore
516 ptextarg = NULL;
517 }
518 }
519 }
520
521 if ((conf.settings().texture_targs) && (ptextarg == NULL))
522 {
523 // check if any part of the texture intersects the current target
524 if (!PSMT_ISCLUT(tpsm) && (curvb.tex0.tbp0 >= curvb.frame.fbp) && ((curvb.tex0.tbp0) < curvb.prndr->end))
525 {
526 ptextarg = curvb.prndr;
527 }
528 }
529
530 TargetLog(tbw, tbp0, tpsm, curvb, (ptextarg == NULL));
531
532 return ptextarg;
533 }
534
535 // Find target to draw a texture.
536 inline CRenderTarget* FlushGetTarget(VB& curvb)
537 {
538 int tbw, tbp0, tpsm;
539
540 CRenderTarget* ptextarg = NULL;
541
542 if (!curvb.curprim.tme) return ptextarg; // Which would be NULL, currently.
543
544 if (curvb.bNeedTexCheck)
545 {
546 ZZLog::Error_Log("How it is possible?");
547 // not yet initied, but still need to get correct target! (xeno3 ingame)
548 tbp0 = ZZOglGet_tbp0_TexBits(curvb.uNextTex0Data[0]);
549 tbw = ZZOglGet_tbw_TexBitsMult(curvb.uNextTex0Data[0]);
550 tpsm = ZZOglGet_psm_TexBitsFix(curvb.uNextTex0Data[0]);
551 }
552 else
553 {
554 tbw = curvb.tex0.tbw;
555 tbp0 = curvb.tex0.tbp0;
556 tpsm = curvb.tex0.psm;
557 }
558
559 ptextarg = s_RTs.GetTarg(tbp0, tbw);
560
561 if (ptextarg == NULL) ptextarg = FlushReGetTarget(tbw, tbp0, tpsm, curvb);
562
563 if ((ptextarg != NULL) && !(ptextarg->status & CRenderTarget::TS_NeedUpdate))
564 {
565 if (PSMT_BITMODE(tpsm) == 4) // handle 8h cluts
566 {
567 // don't support clut targets, read from mem
568 // 4hl - kh2 check - from dx version -- arcum42
569
570 if (tpsm == PSMT4 && s_ClutResolve <= 1)
571 {
572 // xenosaga requires 2 resolves
573 u32 prevcount = curvb.nCount;
574 curvb.nCount = 0;
575 ptextarg->Resolve();
576 s_ClutResolve++;
577 curvb.nCount += prevcount;
578 }
579
580 ptextarg = NULL;
581 }
582 else
583 {
584 if (ptextarg == curvb.prndr)
585 {
586 // need feedback
587 curvb.prndr->CreateFeedback();
588
589 if (s_bWriteDepth && (curvb.pdepth != NULL))
590 curvb.pdepth->SetRenderTarget(1);
591 else
592 ResetRenderTarget(1);
593 }
594 }
595 }
596 else
597 {
598 // If a texture needs updating, clear it.
599 ptextarg = NULL;
600 }
601
602 return ptextarg;
603 }
604
605 // Set target for current context
606 inline void FlushSetContextTarget(VB& curvb, int context)
607 {
608 if (!curvb.bVarsSetTarg)
609 {
610 SetContextTarget(context);
611 }
612 else
613 {
614 assert(curvb.pdepth != NULL);
615
616 if (curvb.pdepth->status & CRenderTarget::TS_Virtual)
617 {
618 if (!curvb.zbuf.zmsk)
619 {
620 CRenderTarget* ptemp = s_DepthRTs.Promote(GetFrameKey(curvb.pdepth));
621 assert(ptemp == curvb.pdepth);
622 }
623 else
624 {
625 curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate;
626 }
627 }
628
629 if ((curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) || (curvb.prndr->status & CRenderTarget::TS_NeedUpdate))
630 SetContextTarget(context);
631 }
632
633 assert(!(curvb.prndr->status&CRenderTarget::TS_NeedUpdate));
634
635 curvb.prndr->status = 0;
636
637 if (curvb.pdepth != NULL)
638 {
639 #ifdef _DEBUG
640 // Reduce an assert to a warning.
641 if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)
642 {
643 ZZLog::Debug_Log("In FlushSetContextTarget, pdepth has TS_NeedUpdate set.");
644 }
645 #endif
646 if (!curvb.zbuf.zmsk)
647 {
648 assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual));
649 curvb.pdepth->status = 0;
650 }
651 }
652 }
653
654 inline void FlushSetStream(VB& curvb)
655 {
656 glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]);
657 g_nCurVBOIndex = (g_nCurVBOIndex + 1) % g_vboBuffers.size();
658 glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW);
659 // void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
660 // memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU));
661 // glUnmapBuffer(GL_ARRAY_BUFFER);
662 SET_STREAM();
663
664 GL_REPORT_ERRORD();
665 }
666
667 int SetMaskR = 0x0;
668 int SetMaskG = 0x0;
669 int SetMaskB = 0x0;
670 // Set color mask. Really, it's not as good as PS2 one.
671 inline void FlushSetColorMask(VB& curvb)
672 {
673 s_dwColorWrite = (PSMT_BITMODE(curvb.prndr->psm) == 1) ? (COLORMASK_BLUE | COLORMASK_GREEN | COLORMASK_RED) : 0xf;
674
675 int maskR = ZZOglGet_fbmRed_FrameBits(curvb.frame.fbm);
676 int maskG = ZZOglGet_fbmGreen_FrameBits(curvb.frame.fbm);
677 int maskB = ZZOglGet_fbmBlue_FrameBits(curvb.frame.fbm);
678 int maskA = ZZOglGet_fbmAlpha_FrameBits(curvb.frame.fbm);
679
680 if (maskR == 0xff) s_dwColorWrite &= ~COLORMASK_RED;
681 if (maskG == 0xff) s_dwColorWrite &= ~COLORMASK_GREEN;
682 if (maskB == 0xff) s_dwColorWrite &= ~COLORMASK_BLUE;
683
684 if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == 2 && curvb.test.aref == 128)))
685 s_dwColorWrite &= ~COLORMASK_ALPHA;
686
687 GL_COLORMASK(s_dwColorWrite);
688 }
689
690 // Set Scissors for scissor test.
691 inline void FlushSetScissorRect(VB& curvb)
692 {
693 Rect& scissor = curvb.prndr->scissorrect;
694 glScissor(scissor.x, scissor.y, scissor.w, scissor.h);
695 }
696
697 // Prior really doing something check context
698 inline void FlushDoContextJob(VB& curvb, int context)
699 {
700 SaveRendererTarget(curvb);
701
702 FlushSetContextTarget(curvb, context);
703 icurctx = context;
704
705 FlushSetStream(curvb);
706 FlushSetColorMask(curvb);
707 FlushSetScissorRect(curvb);
708 }
709
710 // Set 1 is Alpha test is EQUAL and alpha should be proceed with care.
711 inline int FlushGetExactcolor(const pixTest curtest)
712 {
713 if (!(g_nPixelShaderVer&SHADER_REDUCED))
714 // ffx2 breaks when ==7
715 return ((curtest.ate && curtest.aref <= 128) && (curtest.atst == 4));//||curtest.atst==7);
716
717 return 0;
718 }
719
720 // fill the buffer by decoding the clut
721 inline void FlushDecodeClut(VB& curvb, GLuint& ptexclut)
722 {
723 glGenTextures(1, &ptexclut);
724 glBindTexture(GL_TEXTURE_2D, ptexclut);
725
726 if (ptexclut != 0)
727 {
728 int clutsize;
729 int entries = PSMT_IS8CLUT(curvb.tex0.psm) ? 256 : 16;
730
731 if (curvb.tex0.csm && curvb.tex0.csa) ZZLog::Debug_Log("ERROR, csm1.");
732
733 if (PSMT_IS32BIT(curvb.tex0.cpsm)) {
734 __aligned16 u32 data[256];
735 clutsize = min(entries, 256 - curvb.tex0.csa * 16) * 4;
736
737 ClutBuffer_to_Array<u32>((u32*)data, curvb.tex0.csa, clutsize);
738
739 Texture2D(4, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
740 } else {
741 __aligned16 u16 data[256];
742 clutsize = min(entries, 512 - curvb.tex0.csa * 16) * 2;
743
744 ClutBuffer_to_Array<u16>((u16*)data, curvb.tex0.csa, clutsize);
745
746 Texture2D(4, 256, 1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data);
747 }
748
749 s_vecTempTextures.push_back(ptexclut);
750
751 if (g_bSaveTex) SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1);
752
753 setTex2DWrap(GL_REPEAT);
754 setTex2DFilters(GL_LINEAR);
755 }
756 }
757
758 inline int FlushGetShaderType(VB& curvb, CRenderTarget* ptextarg, GLuint& ptexclut)
759 {
760 if (PSMT_ISCLUT(curvb.tex0.psm) && !(conf.settings().no_target_clut))
761 {
762 FlushDecodeClut(curvb, ptexclut);
763
764 if (!(g_nPixelShaderVer&SHADER_REDUCED) && PSMT_ISHALF(ptextarg->psm))
765 {
766 return 4;
767 }
768 else
769 {
770 // Valkyrie
771 return 2;
772 }
773 }
774
775 if (PSMT_ISHALF_STORAGE(curvb.tex0) != PSMT_ISHALF(ptextarg->psm) && (!(g_nPixelShaderVer&SHADER_REDUCED) || !curvb.curprim.fge))
776 {
777 if (PSMT_ISHALF_STORAGE(curvb.tex0))
778 {
779 // converting from 32->16
780 // Radiata Chronicles
781 return 3;
782 }
783 else
784 {
785 // converting from 16->32
786 // Star Ward: Force
787 return 0;
788 }
789 }
790
791 return 1;
792 }
793
794
795 //Set page offsets depends on shader type.
796 inline float4 FlushSetPageOffset(FRAGMENTSHADER* pfragment, int shadertype, CRenderTarget* ptextarg)
797 {
798 SetShaderCaller("FlushSetPageOffset");
799
800 float4 vpageoffset;
801 vpageoffset.w = 0;
802
803 switch (shadertype)
804 {
805 case 3:
806 vpageoffset.x = -0.1f / 256.0f;
807 vpageoffset.y = -0.001f / 256.0f;
808 vpageoffset.z = -0.1f / (ptextarg->fbh);
809 vpageoffset.w = 0.0f;
810 break;
811
812 case 4:
813 vpageoffset.x = 2;
814 vpageoffset.y = 1;
815 vpageoffset.z = 0;
816 vpageoffset.w = 0.0001f;
817 break;
818 }
819
820 // zoe2
821 if (PSMT_ISZTEX(ptextarg->psm)) vpageoffset.w = -1.0f;
822
823 ZZshSetParameter4fv(pfragment->fPageOffset, vpageoffset, "g_fPageOffset");
824
825 return vpageoffset;
826 }
827
828 //Set texture offsets depends omn shader type.
829 inline float4 FlushSetTexOffset(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
830 {
831 SetShaderCaller("FlushSetTexOffset");
832 float4 v;
833
834 if (shadertype == 3)
835 {
836 float4 v;
837 v.x = 16.0f / (float)curvb.tex0.tw;
838 v.y = 16.0f / (float)curvb.tex0.th;
839 v.z = 0.5f * v.x;
840 v.w = 0.5f * v.y;
841 ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
842 }
843 else if (shadertype == 4)
844 {
845 float4 v;
846 v.x = 16.0f / (float)ptextarg->fbw;
847 v.y = 16.0f / (float)ptextarg->fbh;
848 v.z = -1;
849 v.w = 8.0f / (float)ptextarg->fbh;
850 ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
851 }
852
853 return v;
854 }
855
856 // Set dimension (Real!) of texture. z and w
857 inline float4 FlushTextureDims(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
858 {
859 SetShaderCaller("FlushTextureDims");
860 float4 vTexDims;
861 vTexDims.x = (float)RW(curvb.tex0.tw) ;
862 vTexDims.y = (float)RH(curvb.tex0.th) ;
863
864 // look at the offset of tbp0 from fbp
865
866 if (curvb.tex0.tbp0 <= ptextarg->fbp)
867 {
868 vTexDims.z = 0;//-0.5f/(float)ptextarg->fbw;
869 vTexDims.w = 0;//0.2f/(float)ptextarg->fbh;
870 }
871 else
872 {
873 //u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page
874 int blockheight = PSMT_ISHALF(ptextarg->psm) ? 64 : 32;
875 int ycoord = ((curvb.tex0.tbp0 - ptextarg->fbp) / (32 * (ptextarg->fbw >> 6))) * blockheight;
876 int xcoord = (((curvb.tex0.tbp0 - ptextarg->fbp) % (32 * (ptextarg -> fbw >> 6)))) * 2;
877 vTexDims.z = (float)xcoord;
878 vTexDims.w = (float)ycoord;
879 }
880
881 if (shadertype == 4)
882 vTexDims.z += 8.0f;
883
884 ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims");
885
886 return vTexDims;
887 }
888
889 // Apply TEX1 mmag and mmin -- filter for expanding/reducing texture
890 // We ignore all settings, only NEAREST (0) is used
891 inline void FlushApplyResizeFilter(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int context)
892 {
893 u32 ptexset = (ptextarg == curvb.prndr) ? ptextarg->ptexFeedback : ptextarg->ptex;
894 s_ptexCurSet[context] = ptexset;
895
896 if ((!curvb.tex1.mmag) || (!curvb.tex1.mmin))
897 glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset);
898
899 if (!curvb.tex1.mmag)
900 {
901 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
902 dwFilterOpts |= 1;
903 }
904
905 if (!curvb.tex1.mmin)
906 {
907 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
908 dwFilterOpts |= 2;
909 }
910 }
911
912
913 // Usage existing targets depends on several tricks, 32-16 conversion and CLUTing, so we need to handle it.
914 inline FRAGMENTSHADER* FlushUseExistRenderTarget(VB& curvb, CRenderTarget* ptextarg, u32& dwFilterOpts, int exactcolor, int context)
915 {
916 if (ptextarg->IsDepth())
917 SetWriteDepth();
918
919 GLuint ptexclut = 0;
920
921 //int psm = PIXEL_STORAGE_FORMAT(curvb.tex0);
922 int shadertype = FlushGetShaderType(curvb, ptextarg, ptexclut);
923
924 FRAGMENTSHADER* pfragment = ZZshLoadShadeEffect(shadertype, 0, curvb.curprim.fge,
925 IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL);
926
927 float4 vpageoffset = FlushSetPageOffset(pfragment, shadertype, ptextarg);
928
929 float4 v = FlushSetTexOffset(pfragment, shadertype, curvb, ptextarg);
930
931 float4 vTexDims = FlushTextureDims(pfragment, shadertype, curvb, ptextarg);
932
933 if (pfragment->sCLUT != NULL && ptexclut != 0)
934 ZZshGLSetTextureParameter(pfragment->sCLUT, ptexclut, "CLUT");
935
936 FlushApplyResizeFilter(curvb, dwFilterOpts, ptextarg, context);
937
938 if (g_bSaveTex)
939 SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV,
940 ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex, RW(ptextarg->fbw), RH(ptextarg->fbh));
941
942 return pfragment;
943 }
944
945 // Usage most major shader.
946 inline FRAGMENTSHADER* FlushMadeNewTarget(VB& curvb, int exactcolor, int context)
947 {
948 // save the texture
949 if (g_bSaveTex)
950 {
951 // FIXME: I suspect one of g_bSaveTex test variable is wrong
952 if (g_bSaveTex == 1)
953 {
954 SaveTex(&curvb.tex0, 1);
955 /*CMemoryTarget* pmemtarg = */
956 g_MemTargs.GetMemoryTarget(curvb.tex0, 0);
957 }
958 else
959 {
960 SaveTex(&curvb.tex0, 0);
961 }
962 }
963
964 FRAGMENTSHADER* pfragment = ZZshLoadShadeEffect(0, GetTexFilter(curvb.tex1), curvb.curprim.fge,
965 IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL);
966
967 if (pfragment == NULL)
968 ZZLog::Error_Log("Could not find memory target shader.");
969
970 return pfragment;
971 }
972
973 // We made an shader, so now need to put all common variables.
974 inline void FlushSetTexture(VB& curvb, FRAGMENTSHADER* pfragment, CRenderTarget* ptextarg, int context)
975 {
976 SetTexVariables(context, pfragment);
977 SetTexInt(context, pfragment, ptextarg == NULL);
978
979 // have to enable the texture parameters(curtest.atst)
980 if( curvb.ptexClamp[0] != 0 )
981 ZZshGLSetTextureParameter(pfragment->sBitwiseANDX, curvb.ptexClamp[0], "Clamp 0");
982
983 if( curvb.ptexClamp[1] != 0 )
984 ZZshGLSetTextureParameter(pfragment->sBitwiseANDY, curvb.ptexClamp[1], "Clamp 1");
985
986 if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0)
987 ZZshGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context], "Clamp memory");
988
989 }
990
991 // Reset program and texture variables;
992 inline void FlushBindProgramm(FRAGMENTSHADER* pfragment, int context)
993 {
994 vb[context].bTexConstsSync = 0;
995 vb[context].bVarsTexSync = 0;
996
997 ZZshSetPixelShader(pfragment->prog);
998 }
999
1000 inline FRAGMENTSHADER* FlushRendererStage(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int exactcolor, int context)
1001 {
1002
1003 FRAGMENTSHADER* pfragment = NULL;
1004
1005 // set the correct pixel shaders
1006
1007 if (curvb.curprim.tme)
1008 {
1009 if (ptextarg != NULL)
1010 pfragment = FlushUseExistRenderTarget(curvb, ptextarg, dwFilterOpts, exactcolor, context);
1011 else
1012 pfragment = FlushMadeNewTarget(curvb, exactcolor, context);
1013
1014 if (pfragment == NULL)
1015 {
1016 ZZLog::Error_Log("Shader is not found.");
1017 // return NULL;
1018 }
1019
1020 FlushSetTexture(curvb, pfragment, ptextarg, context);
1021 }
1022 else
1023 {
1024 pfragment = &ppsRegular[curvb.curprim.fge + 2 * s_bWriteDepth];
1025 }
1026
1027 GL_REPORT_ERRORD();
1028
1029 // set the shaders
1030 SetShaderCaller("FlushRendererStage");
1031 ZZshSetVertexShader(pvs[2 * ((curvb.curprim._val >> 1) & 3) + 8 * s_bWriteDepth + context]);
1032 FlushBindProgramm(pfragment, context);
1033
1034 GL_REPORT_ERRORD();
1035 return pfragment;
1036 }
1037
1038 inline bool AlphaCanRenderStencil(VB& curvb)
1039 {
1040 return g_bUpdateStencil && (PSMT_BITMODE(curvb.prndr->psm) != 1) &&
1041 !ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(conf.settings().no_stencil);
1042 }
1043
1044 inline void AlphaSetStencil(bool DoIt)
1045 {
1046 if (DoIt)
1047 {
1048 glEnable(GL_STENCIL_TEST);
1049 GL_STENCILFUNC(GL_ALWAYS, 0, 0);
1050 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1051 }
1052 else glDisable(GL_STENCIL_TEST);
1053 }
1054
1055 //inline u32 FtoDW(float f) { return (*((u32*)&f)); }
1056
1057 inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment)
1058 {
1059 glDepthMask(!curvb.zbuf.zmsk && curtest.zte);
1060 // && curtest.zte && (curtest.ztst > 1) );
1061
1062 if (curtest.zte)
1063 {
1064 if (curtest.ztst > 1) g_nDepthUsed = 2;
1065 if ((curtest.ztst == 2) ^(g_nDepthBias != 0))
1066 {
1067 g_nDepthBias = (curtest.ztst == 2);
1068 //SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f));
1069 }
1070
1071 glDepthFunc(g_dwZCmp[curtest.ztst]);
1072 }
1073
1074 GL_ZTEST(curtest.zte);
1075
1076 if (s_bWriteDepth)
1077 {
1078 if (!curvb.zbuf.zmsk)
1079 curvb.pdepth->SetRenderTarget(1);
1080 else
1081 ResetRenderTarget(1);
1082 }
1083 }
1084
1085 inline u32 AlphaSetupBlendTest(VB& curvb)
1086 {
1087 if (curvb.curprim.abe)
1088 SetAlphaVariables(curvb.alpha);
1089 else
1090 glDisable(GL_BLEND);
1091
1092 u32 oldabe = curvb.curprim.abe;
1093
1094 if (gs.pabe)
1095 {
1096 //ZZLog::Error_Log("PABE!");
1097 curvb.curprim.abe = 1;
1098 glEnable(GL_BLEND);
1099 }
1100
1101 return oldabe;
1102 }
1103
1104 inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
1105 {
1106 // needs to be before RenderAlphaTest
1107 if ((gs.pabe) || (curvb.fba.fba && !ZZOglGet_fbmHighByte(curvb.frame.fbm)) || (s_bDestAlphaTest && bCanRenderStencil))
1108 {
1109 RenderFBA(curvb, pfragment->sOneColor);
1110 }
1111
1112 }
1113
1114 inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor)
1115 {
1116 SetShaderCaller("AlphaRenderAlpha");
1117 u32 dwUsingSpecialTesting = 0;
1118
1119 if (curvb.curprim.abe)
1120 {
1121 if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > 1) && (curtest.aref > 0x80))))
1122 {
1123 // need special stencil processing for the alpha
1124 RenderAlphaTest(curvb, pfragment->sOneColor);
1125 dwUsingSpecialTesting = 1;
1126 }
1127
1128 // harvest fishing
1129 float4 v = vAlphaBlendColor;
1130
1131 if (exactcolor)
1132 {
1133 v.y *= 255;
1134 v.w *= 255;
1135 }
1136
1137 ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
1138 }
1139 else
1140 {
1141 // not using blending so set to defaults
1142 float4 v = exactcolor ? float4(1, 510 * 255.0f / 256.0f, 0, 0) : float4(1, 2 * 255.0f / 256.0f, 0, 0);
1143 ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
1144
1145 }
1146
1147 return dwUsingSpecialTesting;
1148 }
1149
1150 inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRenderStencil, u32 dwUsingSpecialTesting)
1151 {
1152 if (s_bDestAlphaTest && bCanRenderStencil)
1153 {
1154 // if not 24bit and can write to high alpha bit
1155 RenderStencil(curvb, dwUsingSpecialTesting);
1156 }
1157 else
1158 {
1159 s_stencilref = STENCIL_SPECIAL;
1160 s_stencilmask = STENCIL_SPECIAL;
1161
1162 // setup the stencil to only accept the test pixels
1163
1164 if (dwUsingSpecialTesting)
1165 {
1166 glEnable(GL_STENCIL_TEST);
1167 glStencilMask(STENCIL_PIXELWRITE);
1168 GL_STENCILFUNC(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL);
1169 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1170 }
1171 }
1172
1173 #ifdef _DEBUG
1174 if (bDestAlphaColor == 1)
1175 {
1176 ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here.");
1177 }
1178
1179 #endif
1180
1181 if (bCanRenderStencil && gs.pabe)
1182 {
1183 // only render the pixels with alpha values >= 0x80
1184 GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA);
1185 }
1186
1187 GL_REPORT_ERRORD();
1188 }
1189
1190 inline void AlphaTest(VB& curvb)
1191 {
1192 // ZZLog::Debug_Log("%d %d %d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst );
1193
1194 // return;
1195 // Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack."
1196 if (curvb.test.ate == 1 && curvb.test.atst == 1 && curvb.test.date == 1)
1197 {
1198 if (curvb.test.datm == 1)
1199 {
1200 glAlphaFunc(GL_GREATER, 1.0f);
1201 }
1202 else
1203 {
1204 glAlphaFunc(GL_LESS, 1.0f);
1205 ZZLog::Debug_Log("%d %d %d", curvb.test.date, curvb.test.datm, gs.texa.aem);
1206 }
1207 }
1208
1209 if (!curvb.test.ate || curvb.test.atst > 0)
1210 {
1211 Draw(curvb);
1212 }
1213
1214 GL_REPORT_ERRORD();
1215 }
1216
1217 inline void AlphaPabe(VB& curvb, FRAGMENTSHADER* pfragment, int exactcolor)
1218 {
1219 if (gs.pabe)
1220 {
1221 SetShaderCaller("AlphaPabe");
1222 // only render the pixels with alpha values < 0x80
1223 glDisable(GL_BLEND);
1224 GL_STENCILFUNC_SET();
1225
1226 float4 v;
1227 v.x = 1;
1228 v.y = 2;
1229 v.z = 0;
1230 v.w = 0;
1231
1232 if (exactcolor) v.y *= 255;
1233
1234 ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
1235
1236 Draw(curvb);
1237
1238 // reset
1239 if (!s_stencilmask) s_stencilfunc = GL_ALWAYS;
1240
1241 GL_STENCILFUNC_SET();
1242 }
1243
1244 GL_REPORT_ERRORD();
1245 }
1246
1247 // Alpha Failure does not work properly on this cases. True means that no failure job should be done.
1248 // First three cases are trivial manual.
1249 inline bool AlphaFailureIgnore(const pixTest curtest)
1250 {
1251 if ((!curtest.ate) || (curtest.atst == 1) || (curtest.afail == 0)) return true;
1252
1253 if (conf.settings().no_alpha_fail && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64))))
1254 return true;
1255
1256 // old and seemingly incorrect code.
1257 // if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1)
1258 // return true;
1259 // if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(conf.settings() & GAME_REGETHACK))
1260 // return true;
1261 return false;
1262 }
1263
1264 // more work on alpha failure case
1265 inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor, bool bCanRenderStencil, int oldabe)
1266 {
1267 // Note, case when ate == 1, atst == 0 and afail > 0 in documentation wrote as failure case. But it seems that
1268 // either doc's are incorrect or this case has some issues.
1269 if (AlphaFailureIgnore(curtest)) return;
1270
1271 #ifdef NOALFAFAIL
1272 ZZLog::Error_Log("Alpha job here %d %d %d %d %d %d", s_dwColorWrite, curtest.atst, curtest.afail, curtest.aref, gs.pabe, s_bWriteDepth);
1273
1274 // return;
1275 #endif
1276
1277 SetShaderCaller("AlphaFailureTestJob");
1278
1279 // need to reverse the test and disable some targets
1280 glAlphaFunc(g_dwReverseAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref));
1281
1282 if (curtest.afail & 1) // front buffer update only
1283 {
1284 if (curtest.afail == 3) glColorMask(1, 1, 1, 0);// disable alpha
1285
1286 glDepthMask(0);
1287
1288 if (s_bWriteDepth) ResetRenderTarget(1);
1289 }
1290 else
1291 {
1292 // zbuffer update only
1293 glColorMask(0, 0, 0, 0);
1294 }
1295
1296 if (gs.pabe && bCanRenderStencil)
1297 {
1298 // only render the pixels with alpha values >= 0x80
1299 float4 v = vAlphaBlendColor;
1300
1301 if (exactcolor) { v.y *= 255; v.w *= 255; }
1302
1303 ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
1304
1305 glEnable(GL_BLEND);
1306 GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA);
1307 }
1308
1309 Draw(curvb);
1310
1311 GL_REPORT_ERRORD();
1312
1313 if (gs.pabe)
1314 {
1315 // only render the pixels with alpha values < 0x80
1316 glDisable(GL_BLEND);
1317 GL_STENCILFUNC_SET();
1318
1319 float4 v;
1320 v.x = 1;
1321 v.y = 2;
1322 v.z = 0;
1323 v.w = 0;
1324
1325 if (exactcolor) v.y *= 255;
1326
1327 ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
1328
1329 Draw(curvb);
1330
1331 // reset
1332 if (oldabe) glEnable(GL_BLEND);
1333
1334 if (!s_stencilmask) s_stencilfunc = GL_ALWAYS;
1335
1336 GL_STENCILFUNC_SET();
1337 }
1338
1339 // restore
1340 if ((curtest.afail & 1) && !curvb.zbuf.zmsk)
1341 {
1342 glDepthMask(1);
1343
1344 if (s_bWriteDepth)
1345 {
1346 assert(curvb.pdepth != NULL);
1347 curvb.pdepth->SetRenderTarget(1);
1348 }
1349 }
1350
1351 GL_COLORMASK(s_dwColorWrite);
1352
1353 // not needed anymore since rest of ops concentrate on image processing
1354
1355 GL_REPORT_ERRORD();
1356 }
1357
1358 inline void AlphaSpecialTesting(VB& curvb, FRAGMENTSHADER* pfragment, u32 dwUsingSpecialTesting, int exactcolor)
1359 {
1360 if (dwUsingSpecialTesting)
1361 {
1362 SetShaderCaller("AlphaSpecialTesting");
1363
1364 // render the real alpha
1365 glDisable(GL_ALPHA_TEST);
1366 glColorMask(0, 0, 0, 1);
1367
1368 if (s_bWriteDepth)
1369 {
1370 ResetRenderTarget(1);
1371 }
1372
1373 glDepthMask(0);
1374
1375 glStencilFunc(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL | STENCIL_PIXELWRITE);
1376 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1377
1378 float4 v = float4(0, exactcolor ? 510.0f : 2.0f, 0, 0);
1379 ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
1380 Draw(curvb);
1381
1382 // don't need to restore
1383 }
1384
1385 GL_REPORT_ERRORD();
1386 }
1387
1388 inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
1389 {
1390 if (s_bDestAlphaTest)
1391 {
1392 if ((s_dwColorWrite & COLORMASK_ALPHA))
1393 {
1394 if (curvb.fba.fba)
1395 ProcessFBA(curvb, pfragment->sOneColor);
1396 else if (bCanRenderStencil)
1397 // finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case)
1398 ProcessStencil(curvb);
1399 }
1400 }
1401 else if ((s_dwColorWrite & COLORMASK_ALPHA) && curvb.fba.fba)
1402 ProcessFBA(curvb, pfragment->sOneColor);
1403
1404 if (bDestAlphaColor == 1)
1405 {
1406 // need to reset the dest colors to their original counter parts
1407 //WARN_LOG("Need to reset dest alpha color\n");
1408 }
1409 }
1410
1411 inline void AlphaSaveTarget(VB& curvb)
1412 {
1413 #ifdef _DEBUG
1414 return; // Do nothing
1415
1416 //#ifdef _WIN32
1417 // CreateDirectory("frames", NULL);
1418 //#else
1419 // char* strdir="";
1420 // sprintf(strdir, "mkdir %s", "frames");
1421 // system(strdir);
1422 //#endif
1423 // char str[255];
1424
1425 // Needs a # after frame to work properly.
1426 // sprintf(str, "frames/frame.tga");
1427
1428 // //glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
1429 // //glFlush();
1430 // //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh));
1431 // SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0);
1432 #endif
1433 }
1434
1435 inline void FlushUndoFiter(u32 dwFilterOpts)
1436 {
1437 if (dwFilterOpts)
1438 {
1439 // undo filter changes (binding didn't change)
1440 if (dwFilterOpts & 1) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1441 if (dwFilterOpts & 2) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1442 }
1443 }
1444
1445 // This is the most important function! It draws all collected info onscreen.
1446 void Flush(int context)
1447 {
1448 FUNCLOG
1449 VB& curvb = vb[context];
1450 const pixTest curtest = curvb.test;
1451
1452 if (FlushInitialTest(curvb, curtest, context)) return;
1453
1454 VisualBufferMessage(context);
1455
1456 GL_REPORT_ERRORD();
1457
1458 CRenderTarget* ptextarg = FlushGetTarget(curvb);
1459
1460 SwitchWireframeOff();
1461 FlushDoContextJob(curvb, context);
1462
1463 u32 dwUsingSpecialTesting = 0, dwFilterOpts = 0;
1464 int exactcolor = FlushGetExactcolor(curtest);
1465
1466 FRAGMENTSHADER* pfragment = FlushRendererStage(curvb, dwFilterOpts, ptextarg, exactcolor, context);
1467
1468 bool bCanRenderStencil = AlphaCanRenderStencil(curvb);
1469
1470 if (curtest.date || gs.pabe) SetDestAlphaTest();
1471
1472 AlphaSetStencil(s_bDestAlphaTest && bCanRenderStencil);
1473 AlphaSetDepthTest(curvb, curtest, pfragment); // Error!
1474 SetAlphaTest(curtest);
1475
1476 u32 oldabe = AlphaSetupBlendTest(curvb); // Unavoidable
1477
1478 // needs to be before RenderAlphaTest
1479 AlphaRenderFBA(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
1480
1481 dwUsingSpecialTesting = AlphaRenderAlpha(curvb, curtest, pfragment, exactcolor); // Unavoidable
1482 AlphaRenderStencil(curvb, s_bDestAlphaTest, bCanRenderStencil, dwUsingSpecialTesting);
1483 AlphaTest(curvb); // Unavoidable
1484 AlphaPabe(curvb, pfragment, exactcolor);
1485 AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, bCanRenderStencil, oldabe);
1486 AlphaSpecialTesting(curvb, pfragment, dwUsingSpecialTesting, exactcolor);
1487 AlphaDestinationTest(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
1488 AlphaSaveTarget(curvb);
1489
1490 GL_REPORT_ERRORD();
1491
1492 FlushUndoFiter(dwFilterOpts);
1493
1494 ppf += curvb.nCount + 0x100000;
1495
1496 curvb.nCount = 0;
1497 curvb.curprim.abe = oldabe;
1498
1499 SwitchWireframeOn();
1500
1501 GL_REPORT_ERRORD();
1502 }
1503
1504 void FlushBoth()
1505 {
1506 Flush(0);
1507 Flush(1);
1508 }
1509
1510 inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor)
1511 {
1512 // add fba to all pixels
1513 GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff);
1514 glStencilMask(STENCIL_CLEAR);
1515 glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE);
1516
1517 glDisable(GL_DEPTH_TEST);
1518 glDepthMask(0);
1519 glColorMask(0, 0, 0, 0);
1520
1521 if (s_bWriteDepth) ResetRenderTarget(1);
1522
1523 SetShaderCaller("RenderFBA");
1524
1525 glEnable(GL_ALPHA_TEST);
1526
1527 glAlphaFunc(GL_GEQUAL, 1);
1528
1529 float4 v(1,2,0,0);
1530
1531 ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
1532
1533 Draw(curvb);
1534
1535 SetAlphaTest(curvb.test);
1536
1537 // reset (not necessary)
1538 GL_COLORMASK(s_dwColorWrite);
1539
1540 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1541
1542 if (!curvb.zbuf.zmsk)
1543 {
1544 glDepthMask(1);
1545
1546 assert(curvb.pdepth != NULL);
1547
1548 if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
1549 }
1550
1551 GL_ZTEST(curvb.test.zte);
1552 }
1553
1554 __forceinline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
1555 {
1556 if (!g_bUpdateStencil) return;
1557
1558 if ((curvb.test.ate) && (curvb.test.afail == 1)) glDisable(GL_ALPHA_TEST);
1559
1560 glDepthMask(0);
1561
1562 glColorMask(0, 0, 0, 0);
1563
1564 if (s_bWriteDepth) ResetRenderTarget(1);
1565
1566 SetShaderCaller("RenderAlphaTest");
1567
1568 float4 v(1,2,0,0);
1569
1570 ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
1571
1572 // or a 1 to the stencil buffer wherever alpha passes
1573 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1574
1575 s_stencilfunc = GL_ALWAYS;
1576
1577 glEnable(GL_STENCIL_TEST);
1578
1579 if (!s_bDestAlphaTest)
1580 {
1581 // clear everything
1582 s_stencilref = 0;
1583 glStencilMask(STENCIL_CLEAR);
1584 glDisable(GL_ALPHA_TEST);
1585 GL_STENCILFUNC_SET();
1586 Draw(curvb);
1587
1588 if (curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
1589 }
1590
1591 if (curvb.test.ate && curvb.test.atst > 1 && curvb.test.aref > 0x80)
1592 {
1593 v = float4(1,1,0,0);
1594 ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
1595 glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
1596 }
1597
1598 s_stencilref = STENCIL_SPECIAL;
1599
1600 glStencilMask(STENCIL_SPECIAL);
1601 GL_STENCILFUNC_SET();
1602 glDisable(GL_DEPTH_TEST);
1603
1604 Draw(curvb);
1605
1606 if (curvb.test.zte) glEnable(GL_DEPTH_TEST);
1607
1608 GL_ALPHATEST(0);
1609
1610 GL_COLORMASK(s_dwColorWrite);
1611
1612 if (!curvb.zbuf.zmsk)
1613 {
1614 glDepthMask(1);
1615
1616 // set rt next level
1617
1618 if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
1619 }
1620 }
1621
1622 inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting)
1623 {
1624 //NOTE: This stencil hack for dest alpha testing ONLY works when
1625 // the geometry in one DrawPrimitive call does not overlap
1626
1627 // mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff)
1628 // mark 4 if a pixel was written (so that the stencil buf can be changed with new values)
1629 glStencilMask(STENCIL_PIXELWRITE);
1630 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1631
1632 s_stencilmask = (curvb.test.date ? STENCIL_ALPHABIT : 0) | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0);
1633 s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS;
1634
1635 s_stencilref = curvb.test.date * curvb.test.datm | STENCIL_PIXELWRITE | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0);
1636 GL_STENCILFUNC_SET();
1637 }
1638
1639 inline void ProcessStencil(const VB& curvb)
1640 {
1641 assert(!curvb.fba.fba);
1642
1643 // set new alpha bit
1644 glStencilMask(STENCIL_ALPHABIT);
1645 GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE, STENCIL_PIXELWRITE | STENCIL_FBA);
1646 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1647
1648 glDisable(GL_DEPTH_TEST);
1649 glDepthMask(0);
1650 glColorMask(0, 0, 0, 0);
1651
1652 if (s_bWriteDepth) ResetRenderTarget(1);
1653
1654 GL_ALPHATEST(0);
1655
1656 SetShaderCaller("ProcessStencil");
1657
1658 ZZshSetPixelShader(ppsOne.prog);
1659 Draw(curvb);
1660
1661 // process when alpha >= 0xff
1662 GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE | STENCIL_FBA | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
1663 Draw(curvb);
1664
1665 // clear STENCIL_PIXELWRITE bit
1666 glStencilMask(STENCIL_CLEAR);
1667
1668 GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
1669 Draw(curvb);
1670
1671 // restore state
1672 GL_COLORMASK(s_dwColorWrite);
1673
1674 if (curvb.test.ate && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
1675
1676 if (!curvb.zbuf.zmsk)
1677 {
1678 glDepthMask(1);
1679
1680 if (s_bWriteDepth)
1681 {
1682 assert(curvb.pdepth != NULL);
1683 curvb.pdepth->SetRenderTarget(1);
1684 }
1685 }
1686
1687 GL_ZTEST(curvb.test.zte);
1688
1689 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1690 }
1691
1692 __forceinline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
1693 {
1694 if ((curvb.frame.fbm&0x80000000)) return;
1695
1696 // add fba to all pixels that were written and alpha was less than 0xff
1697 glStencilMask(STENCIL_ALPHABIT);
1698 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
1699 GL_STENCILFUNC(GL_EQUAL, STENCIL_FBA | STENCIL_PIXELWRITE | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
1700 glDisable(GL_DEPTH_TEST);
1701
1702 glDepthMask(0);
1703 glColorMask(0, 0, 0, 1);
1704
1705 if (s_bWriteDepth) ResetRenderTarget(1);
1706
1707 SetShaderCaller("ProcessFBA");
1708
1709 // processes the pixels with ALPHA < 0x80*2
1710 glEnable(GL_ALPHA_TEST);
1711 glAlphaFunc(GL_LEQUAL, 1);
1712
1713 // add 1 to dest
1714 GL_BLEND_ALPHA(GL_ONE, GL_ONE);
1715 GL_BLENDEQ_ALPHA(GL_FUNC_ADD);
1716
1717 float f = 1;
1718 ZZshSetParameter4fv(sOneColor, &f, "g_fOneColor");
1719 ZZshSetPixelShader(ppsOne.prog);
1720 Draw(curvb);
1721 glDisable(GL_ALPHA_TEST);
1722
1723 // reset bits
1724 glStencilMask(STENCIL_CLEAR);
1725 GL_STENCILFUNC(GL_GREATER, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
1726 glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
1727 Draw(curvb);
1728
1729 if (curvb.test.atst && USEALPHATESTING)
1730 {
1731 glEnable(GL_ALPHA_TEST);
1732 glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
1733 }
1734
1735 // restore (SetAlphaVariables)
1736 GL_BLEND_ALPHA(GL_ONE, GL_ZERO);
1737
1738 if (vAlphaBlendColor.y < 0) GL_BLENDEQ_ALPHA(GL_FUNC_REVERSE_SUBTRACT);
1739
1740 // reset (not necessary)
1741 GL_COLORMASK(s_dwColorWrite);
1742
1743 if (!curvb.zbuf.zmsk)
1744 {
1745 glDepthMask(1);
1746
1747 if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
1748 }
1749
1750 GL_ZTEST(curvb.test.zte);
1751 }
1752
1753 void SetContextTarget(int context)
1754 {
1755 FUNCLOG
1756 VB& curvb = vb[context];
1757 GL_REPORT_ERRORD();
1758
1759 if (curvb.prndr == NULL)
1760 curvb.prndr = s_RTs.GetTarg(curvb.frame, 0, get_maxheight(curvb.gsfb.fbp, curvb.gsfb.fbw, curvb.gsfb.psm));
1761
1762 // make sure targets are valid
1763 if (curvb.pdepth == NULL)
1764 {
1765 frameInfo f;
1766 f.fbp = curvb.zbuf.zbp;
1767 f.fbw = curvb.frame.fbw;
1768 f.fbh = curvb.prndr->fbh;
1769 f.psm = curvb.zbuf.psm;
1770 f.fbm = 0;
1771 curvb.pdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer | CRenderTargetMngr::TO_StrictHeight |
1772 (curvb.zbuf.zmsk ? CRenderTargetMngr::TO_Virtual : 0), get_maxheight(curvb.zbuf.zbp, curvb.gsfb.fbw, 0));
1773 }
1774
1775 assert(curvb.prndr != NULL && curvb.pdepth != NULL);
1776
1777 if (curvb.pdepth->fbh != curvb.prndr->fbh) ZZLog::Debug_Log("(curvb.pdepth->fbh(0x%x) != curvb.prndr->fbh(0x%x))", curvb.pdepth->fbh, curvb.prndr->fbh);
1778 //assert(curvb.pdepth->fbh == curvb.prndr->fbh);
1779
1780 if (curvb.pdepth->status & CRenderTarget::TS_Virtual)
1781 {
1782
1783 if (!curvb.zbuf.zmsk)
1784 {
1785 CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp | (curvb.pdepth->fbw << 16));
1786 assert(ptemp == curvb.pdepth);
1787 }
1788 else
1789 {
1790 curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate;
1791 }
1792 }
1793
1794 bool bSetTarg = 1;
1795
1796 if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)
1797 {
1798 assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual));
1799
1800 // don't update if virtual
1801 curvb.pdepth->Update(context, curvb.prndr);
1802 bSetTarg = 0;
1803 }
1804
1805 GL_REPORT_ERRORD();
1806
1807 if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate)
1808 {
1809 /* if(bSetTarg) {
1810 * ZZLog::Debug_Log( " Here ");
1811 * if(s_bWriteDepth) {
1812 * curvb.pdepth->SetRenderTarget(1);
1813 * curvb.pdepth->SetDepthStencilSurface();
1814 * }
1815 * else
1816 * curvb.pdepth->SetDepthStencilSurface();
1817 * }*/
1818 curvb.prndr->Update(context, curvb.pdepth);
1819 }
1820 else
1821 {
1822
1823 //if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg )
1824 curvb.prndr->SetRenderTarget(0);
1825 //if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) )
1826 curvb.pdepth->SetDepthStencilSurface();
1827
1828 if (conf.mrtdepth && IsWriteDepth()) curvb.pdepth->SetRenderTarget(1);
1829 if (s_ptexCurSet[0] == curvb.prndr->ptex) s_ptexCurSet[0] = 0;
1830 if (s_ptexCurSet[1] == curvb.prndr->ptex) s_ptexCurSet[1] = 0;
1831
1832 curvb.prndr->SetViewport();
1833 }
1834
1835 curvb.prndr->SetTarget(curvb.frame.fbp, curvb.scissor, context);
1836
1837 if ((curvb.zbuf.zbp - curvb.pdepth->fbp) != (curvb.frame.fbp - curvb.prndr->fbp) && curvb.test.zte)
1838 ZZLog::Warn_Log("Frame and zbuf not aligned.");
1839
1840 curvb.bVarsSetTarg = true;
1841
1842 if (vb[!context].prndr != curvb.prndr) vb[!context].bVarsSetTarg = false;
1843
1844 #ifdef _DEBUG
1845 // These conditions happen often enough that we'll just warn about it rather then abort in Debug mode.
1846 if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate)
1847 {
1848 ZZLog::Debug_Log("In SetContextTarget, prndr is ending with TS_NeedUpdate set.");
1849 }
1850
1851 if (curvb.pdepth != NULL && (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate))
1852 {
1853 ZZLog::Debug_Log("In SetContextTarget, pdepth is ending with TS_NeedUpdate set.");
1854 }
1855 #endif
1856
1857 GL_REPORT_ERRORD();
1858 }
1859
1860
1861 void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint)
1862 {
1863 FUNCLOG
1864
1865 if (settexint)
1866 {
1867 tex0Info& tex0 = vb[context].tex0;
1868
1869 if (vb[context].bVarsTexSync) {
1870 SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, true, pfragment, s_bForceTexFlush);
1871 } else {
1872 SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, false, pfragment, s_bForceTexFlush);
1873
1874 INC_TEXVARS();
1875 }
1876 vb[context].bVarsTexSync = true;
1877 }
1878 else
1879 {
1880 vb[context].bVarsTexSync = false;
1881 }
1882 }
1883
1884 // clamp relies on texture width
1885 void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
1886 {
1887 FUNCLOG
1888 SetShaderCaller("SetTexClamping");
1889 clampInfo* pclamp = &vb[context].clamp;
1890 float4 v, v2;
1891 v.x = v.y = 0;
1892 u32* ptex = vb[context].ptexClamp;
1893 ptex[0] = ptex[1] = 0;
1894
1895 float fw = vb[context].tex0.tw ;
1896 float fh = vb[context].tex0.th ;
1897
1898 switch (pclamp->wms)
1899 {
1900 case 0:
1901 v2.x = -1e10;
1902 v2.z = 1e10;
1903 break;
1904
1905 case 1: // pclamp
1906 // suikoden5 movie text
1907 v2.x = 0;
1908 v2.z = 1 - 0.5f / fw;
1909 break;
1910
1911 case 2: // reg pclamp
1912 v2.x = (pclamp->minu + 0.5f) / fw;
1913 v2.z = (pclamp->maxu - 0.5f) / fw;
1914 break;
1915
1916 case 3: // region rep x
1917 v.x = 0.9999f;
1918 v.z = (float)fw;
1919 v2.x = (float)GPU_TEXMASKWIDTH / fw;
1920 v2.z = pclamp->maxu / fw;
1921 int correctMinu = pclamp->minu & (~pclamp->maxu); // (A && B) || C == (A && (B && !C)) + C
1922
1923 if (correctMinu != g_PrevBitwiseTexX)
1924 {
1925 g_PrevBitwiseTexX = correctMinu;
1926 ptex[0] = s_BitwiseTextures.GetTex(correctMinu, 0);
1927 }
1928
1929 break;
1930 }
1931
1932 switch (pclamp->wmt)
1933 {
1934
1935 case 0:
1936 v2.y = -1e10;
1937 v2.w = 1e10;
1938 break;
1939
1940 case 1: // pclamp
1941 // suikoden5 movie text
1942 v2.y = 0;
1943 v2.w = 1 - 0.5f / fh;
1944 break;
1945
1946 case 2: // reg pclamp
1947 v2.y = (pclamp->minv + 0.5f) / fh;
1948 v2.w = (pclamp->maxv - 0.5f) / fh;
1949 break;
1950
1951 case 3: // region rep y
1952 v.y = 0.9999f;
1953 v.w = (float)fh;
1954 v2.y = (float)GPU_TEXMASKWIDTH / fh;
1955 v2.w = pclamp->maxv / fh;
1956 int correctMinv = pclamp->minv & (~pclamp->maxv); // (A && B) || C == (A && (B && !C)) + C
1957
1958 if (correctMinv != g_PrevBitwiseTexY)
1959 {
1960 g_PrevBitwiseTexY = correctMinv;
1961 ptex[1] = s_BitwiseTextures.GetTex(correctMinv, ptex[0]);
1962 }
1963 break;
1964 }
1965
1966 if (pfragment->fTexWrapMode != 0)
1967 ZZshSetParameter4fv(pfragment->fTexWrapMode, v, "g_fTexWrapMode");
1968
1969 if (pfragment->fClampExts != 0)
1970 ZZshSetParameter4fv(pfragment->fClampExts, v2, "g_fClampExts");
1971
1972
1973 }
1974
1975 int CheckTexArray[4][2][2][2] = {{{{0, }}}};
1976 void SetTexVariables(int context, FRAGMENTSHADER* pfragment)
1977 {
1978 FUNCLOG
1979
1980 if (!vb[context].curprim.tme) return;
1981
1982 assert(!vb[context].bNeedTexCheck);
1983
1984 float4 v, v2;
1985
1986 tex0Info& tex0 = vb[context].tex0;
1987
1988 //float fw = (float)tex0.tw;
1989 //float fh = (float)tex0.th;
1990
1991 if (!vb[context].bTexConstsSync)
1992 {
1993 SetShaderCaller("SetTexVariables");
1994
1995 // alpha and texture highlighting
1996 float4 valpha, valpha2 ;
1997
1998 // if clut, use the frame format
1999 int psm = PIXEL_STORAGE_FORMAT(tex0);
2000
2001 // ZZLog::Error_Log( "A %d psm, is-clut %d. cpsm %d | %d %d", psm, PSMT_ISCLUT(psm), tex0.cpsm, tex0.tfx, tex0.tcc );
2002
2003 float4 vblack;
2004 vblack.x = vblack.y = vblack.z = vblack.w = 10;
2005
2006 /* tcc -- Tecture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM
2007 * tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2)
2008 *
2009 * valpha2 = 0 0 2 1 0 0 2 1
2010 * 1 0 0 0 1 1 0 0
2011 * 0 0 2 0 0 1 2 0
2012 * 0 0 2 0 0 1 2 0
2013 *
2014 * 0 1,!nNeed 1, psm=2, 10 1, psm=1
2015 * valpha = 0 0 0 1 0 2 0 0 2ta0 2ta1-2ta0 0 0 2ta0 0 0 0
2016 * 0 0 0 1 0 1 0 0 ta0 ta1-ta0 0 0 ta0 0 0 0
2017 * 0 0 1 1 0 1 1 1 1 1 ta0 0 1 1
2018 * 0 0 1 1 0 1 1 0 1 0 ta0 0 1 0
2019 */
2020
2021 valpha2.x = (tex0.tfx == 1) ;
2022 valpha2.y = (tex0.tcc == 1) && (tex0.tfx != 0) ;
2023 valpha2.z = (tex0.tfx != 1) * 2 ;
2024 valpha2.w = (tex0.tfx == 0) ;
2025
2026 if (tex0.tcc == 0 || !PSMT_ALPHAEXP(psm))
2027 {
2028 valpha.x = 0 ;
2029 valpha.y = (!!tex0.tcc) * (1 + (tex0.tfx == 0)) ;
2030 }
2031 else
2032 {
2033 valpha.x = (gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ;
2034 valpha.y = (gs.texa.fta[psm != PSMCT24] - gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ;
2035
2036 }
2037
2038 valpha.z = (tex0.tfx >= 3) ;
2039
2040 valpha.w = (tex0.tcc == 0) || (tex0.tcc == 1 && tex0.tfx == 2) ;
2041
2042 if (tex0.tcc && gs.texa.aem && psm == PSMCT24)
2043 vblack.w = 0;
2044
2045 /*
2046 // Test, old code.
2047 float4 valpha3, valpha4;
2048 switch(tex0.tfx) {
2049 case 0:
2050 valpha3.z = 0; valpha3.w = 0;
2051 valpha4.x = 0; valpha4.y = 0;
2052 valpha4.z = 2; valpha4.w = 1;
2053
2054 break;
2055 case 1:
2056 valpha3.z = 0; valpha3.w = 1;
2057 valpha4.x = 1; valpha4.y = 0;
2058 valpha4.z = 0; valpha4.w = 0;
2059
2060 break;
2061 case 2:
2062 valpha3.z = 1; valpha3.w = 1.0f;
2063 valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
2064 valpha4.z = 2; valpha4.w = 0;
2065
2066 break;
2067
2068 case 3:
2069 valpha3.z = 1; valpha3.w = tex0.tcc ? 0.0f : 1.0f;
2070 valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
2071 valpha4.z = 2; valpha4.w = 0;
2072
2073 break;
2074 }
2075 if( tex0.tcc ) {
2076
2077 if( tex0.tfx == 1 ) {
2078 //mode.x = 10;
2079 valpha3.z = 0; valpha3.w = 0;
2080 valpha4.x = 1; valpha4.y = 1;
2081 valpha4.z = 0; valpha4.w = 0;
2082 }
2083
2084 if( PSMT_ALPHAEXP(psm) ) {
2085
2086 if( tex0.tfx == 0 ) {
2087 // make sure alpha is mult by two when the output is Cv = Ct*Cf
2088 valpha3.x = 2*gs.texa.fta[0];
2089 // if 24bit, always choose ta[0]
2090 valpha3.y = 2*gs.texa.fta[psm != 1];
2091 valpha3.y -= valpha.x;
2092 }
2093 else {
2094 valpha3.x = gs.texa.fta[0];
2095 // if 24bit, always choose ta[0]
2096 valpha3.y = gs.texa.fta[psm != 1];
2097 valpha3.y -= valpha.x;
2098 }
2099 }
2100 else {
2101 if( tex0.tfx == 0 ) {
2102 valpha3.x = 0;
2103 valpha3.y = 2;
2104 }
2105 else {
2106 valpha3.x = 0;
2107 valpha3.y = 1;
2108 }
2109 }
2110 }
2111 else {
2112
2113 // reset alpha to color
2114 valpha3.x = valpha3.y = 0;
2115 valpha3.w = 1;
2116 }
2117
2118 if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) {
2119 if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == 0) {
2120 ZZLog::Debug_Log ( "Good issue %d %d %d %d", tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm) );
2121 CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm) ] = 1;
2122 }
2123 }
2124 else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == -1) {
2125 ZZLog::Debug_Log ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f",
2126 tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm),
2127 valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w,
2128 valpha.x, valpha.y, valpha.z, valpha.w, valpha2.x, valpha2.y, valpha2.z, valpha2.w);
2129 CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] = -1 ;
2130 }
2131
2132 // Test;*/
2133
2134 ZZshSetParameter4fv(pfragment->fTexAlpha, valpha, "g_fTexAlpha");
2135 ZZshSetParameter4fv(pfragment->fTexAlpha2, valpha2, "g_fTexAlpha2");
2136
2137 if (IsAlphaTestExpansion(tex0))
2138 ZZshSetParameter4fv(pfragment->fTestBlack, vblack, "g_fTestBlack");
2139
2140 SetTexClamping(context, pfragment);
2141
2142 vb[context].bTexConstsSync = true;
2143 }
2144
2145 if (s_bTexFlush)
2146 {
2147 if (PSMT_ISCLUT(tex0.psm))
2148 texClutWrite(context);
2149 else
2150 s_bTexFlush = false;
2151 }
2152 }
2153
2154 void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force)
2155 {
2156 FUNCLOG
2157 float4 v;
2158 CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1);
2159
2160 assert( pmemtarg != NULL && pfragment != NULL && pmemtarg->ptex != NULL);
2161 if (pmemtarg == NULL || pfragment == NULL || pmemtarg->ptex == NULL)
2162 {
2163 ZZLog::Error_Log("SetTexVariablesInt error.");
2164 return;
2165 }
2166
2167 if (CheckVB && vb[context].pmemtarg == pmemtarg) return;
2168
2169 SetShaderCaller("SetTexVariablesInt");
2170
2171 float fw = (float)tex0.tw;
2172 float fh = (float)tex0.th;
2173
2174 bool bUseBilinear = bilinear > 1 || (bilinear && conf.bilinear);
2175
2176 if (bUseBilinear)
2177 {
2178 v.x = (float)fw;
2179 v.y = (float)fh;
2180 v.z = 1.0f / (float)fw;
2181 v.w = 1.0f / (float)fh;
2182
2183 if (pfragment->fRealTexDims)
2184 ZZshSetParameter4fv(pfragment->fRealTexDims, v, "g_fRealTexDims");
2185 else
2186 ZZshSetParameter4fv(cgGetNamedParameter(pfragment->prog,"g_fRealTexDims"),v, "g_fRealTexDims");
2187 }
2188
2189 if (m_Blocks[tex0.psm].bpp == 0)
2190 {
2191 ZZLog::Error_Log("Undefined tex psm 0x%x!", tex0.psm);
2192 return;
2193 }
2194
2195 const BLOCK& b = m_Blocks[tex0.psm];
2196
2197 float fbw = (float)tex0.tbw;
2198
2199 float4 vTexDims;
2200
2201 vTexDims.x = b.vTexDims.x * (fw);
2202 vTexDims.y = b.vTexDims.y * (fh);
2203 vTexDims.z = (float)BLOCK_TEXWIDTH * (0.002f / 64.0f + 0.01f / 128.0f);
2204 vTexDims.w = (float)BLOCK_TEXHEIGHT * 0.1f / 512.0f;
2205
2206 if (bUseBilinear)
2207 {
2208 vTexDims.x *= 1 / 128.0f;
2209 vTexDims.y *= 1 / 512.0f;
2210 vTexDims.z *= 1 / 128.0f;
2211 vTexDims.w *= 1 / 512.0f;
2212 }
2213
2214 float g_fitexwidth = g_fiGPU_TEXWIDTH / (float)pmemtarg->widthmult;
2215
2216 //float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult;
2217
2218 float fpage = tex0.tbp0 * (64.0f * g_fitexwidth);// + 0.05f * g_fitexwidth;
2219 float fpageint = floorf(fpage);
2220 //int starttbp = (int)fpage;
2221
2222 // 2048 is number of words to span one page
2223 //float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
2224
2225 float fblockstride = (2048.0f / (float)(GPU_TEXWIDTH * (float)pmemtarg->widthmult * BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
2226
2227 assert(fblockstride >= 1.0f);
2228
2229 v.x = (float)(2048 * g_fitexwidth);
2230 v.y = fblockstride;
2231 v.z = g_fBlockMult / (float)pmemtarg->widthmult;
2232 v.w = fpage - fpageint ;
2233
2234 if (g_fBlockMult > 1)
2235 {
2236 // make sure to divide by mult (since the G16R16 texture loses info)
2237 v.z *= b.bpp * (1 / 32.0f);
2238 }
2239
2240 ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims");
2241
2242 // ZZshSetParameter4fv(pfragment->fTexBlock, b.vTexBlock, "g_fTexBlock"); // I change it, and it's working. Seems casting from float4 to float[4] is ok.
2243 ZZshSetParameter4fv(pfragment->fTexBlock, &b.vTexBlock.x, "g_fTexBlock");
2244 ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
2245
2246 // get hardware texture dims
2247 //int texheight = pmemtarg->texH;
2248 int texwidth = pmemtarg->texW;
2249
2250 v.y = 1.0f;
2251 v.x = (fpageint - (float)pmemtarg->realy / (float)pmemtarg->widthmult + 0.5f);//*v.y;
2252 v.z = (float)texwidth;
2253
2254 /* if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) {
2255 if (tex0.psm == PSMT4 )
2256 v.w = 0.0f;
2257 else
2258 v.w = 0.25f;
2259 }
2260 else
2261 v.w = 0.5f;*/
2262 v.w = 0.5f;
2263
2264 ZZshSetParameter4fv(pfragment->fPageOffset, v, "g_fPageOffset");
2265
2266 if (force)
2267 s_ptexCurSet[context] = pmemtarg->ptex->tex;
2268 else
2269 s_ptexNextSet[context] = pmemtarg->ptex->tex;
2270
2271 vb[context].pmemtarg = pmemtarg;
2272
2273 vb[context].bVarsTexSync = false;
2274 }
2275
2276 #define SET_ALPHA_COLOR_FACTOR(sign) \
2277 { \
2278 switch(a.c) \
2279 { \
2280 case 0: \
2281 vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \
2282 s_srcalpha = GL_ONE; \
2283 s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \
2284 break; \
2285 \
2286 case 1: \
2287 /* if in 24 bit mode, dest alpha should be one */ \
2288 switch(PSMT_BITMODE(vb[icurctx].prndr->psm)) \
2289 { \
2290 case 0: \
2291 bDestAlphaColor = (a.d!=2)&&((a.a==a.d)||(a.b==a.d)); \
2292 break; \
2293 \
2294 case 1: \
2295 /* dest alpha should be one */ \
2296 bDestAlphaColor = 2; \
2297 break; \
2298 /* default: 16bit surface, so returned alpha is ok */ \
2299 } \
2300 break; \
2301 \
2302 case 2: \
2303 bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */ \
2304 vAlphaBlendColor.y = 0; \
2305 vAlphaBlendColor.w = (sign) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f); \
2306 usec = 0; /* change so that alpha comes from source*/ \
2307 break; \
2308 } \
2309 } \
2310
2311 //if( a.fix <= 0x80 ) { \
2312 // dwTemp = (a.fix*2)>255?255:(a.fix*2); \
2313 // dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \
2314 // ZZLog::Debug_Log("bfactor: %8.8x", dwTemp); \
2315 // glBlendColorEXT(dwTemp); \
2316 // } \
2317 // else { \
2318
2319 //void ResetAlphaVariables() {
2320 // FUNCLOG
2321 //}
2322
2323 inline void NeedFactor(int w)
2324 {
2325 if (bDestAlphaColor == 2)
2326 {
2327 bNeedBlendFactorInAlpha = (w + 1) ? true : false;
2328 vAlphaBlendColor.y = 0;
2329 vAlphaBlendColor.w = (float)w;
2330 }
2331 }
2332
2333 //static int CheckArray[48][2] = {{0,}};
2334
2335 void SetAlphaVariables(const alphaInfo& a)
2336 {
2337 FUNCLOG
2338 bool alphaenable = true;
2339
2340 // TODO: negative color when not clamping turns to positive???
2341 g_vars._bAlphaState = 0; // set all to zero
2342 bNeedBlendFactorInAlpha = false;
2343 b2XAlphaTest = 1;
2344 //u32 dwTemp = 0xffffffff;
2345 bDestAlphaColor = 0;
2346
2347 // default
2348 s_srcalpha = GL_ONE;
2349 s_dstalpha = GL_ZERO;
2350 s_alphaeq = GL_FUNC_ADD;
2351 s_rgbeq = 1;
2352
2353 // s_alphaInfo = a;
2354 vAlphaBlendColor = float4(1, 2 * 255.0f / 256.0f, 0, 0);
2355 u32 usec = a.c;
2356
2357
2358 /*
2359 * Alpha table
2360 * a + b + d
2361 * S D
2362 * 0 a -a 1 | 0 0 0
2363 * 1 0 0 0 | a -a 1
2364 * 2 0 0 0 | 0 0 0
2365 *
2366 * d = 0 Cs
2367 * a b 0 Cs 1 Cd 2 0
2368 * | |
2369 * 0 000: a+-a+ 1 | 0+ 0+ 0 = 1 | 010: a+ 0+ 1 | 0+-a+ 0 = 1-(-a)(+)(-a) | 020: a+ 0+ 1 | 0+ 0+ 0 = 1-(-a) (+) 0
2370 * 1 100: 0+-a+ 1 | a+ 0+ 0 = 1-a (+) a | 110: 0+ 0+ 1 | a+-a+ 0 = 1 | 120: 0+ 0+ 1 | a+ 0+ 0 = 1 (+) a
2371 * 2 200: 0+-a+ 1 | 0+ 0+ 0 = 1-a (+) 0 | 210: 0+ 0+ 1 | 0+-a+ 0 = 1 (-) a | 220: 0+ 0+ 1 | 0+ 0+ 0 = 1
2372 *
2373 * d = 1 Cd
2374 * 0 | 1 | 2
2375 * 0 001: a+-a+ 0 | 0+ 0+ 1 = 0 (+) 1 | 011: a+ 0+ 0 | 0+-a+ 1 = a (+) 1-a | 021: a+ 0+ 0 | 0+ 0+ 1 = a (+) 1
2376 * 1 101: 0+-a+ 0 | a+ 0+ 1 = (-a)(+) 1-(-a) | 111: 0+ 0+ 0 | a+-a+ 1 = 0 (+) 1 | 121: 0+ 0+ 0 | a+ 0+ 1 = 0 (+) 1-(-a)
2377 * 2 201: 0+-a+ 0 | 0+ 0+ 1 = a (R-)1 | 211: 0+ 0+ 0 | 0+-a+ 1 = 0 (+) 1-a | 221: 0+ 0+ 0 | 0+ 0+ 1 = 0 (+) 1
2378 *
2379 * d = 2 0
2380 * 0 | 1 | 2
2381 * 0 002: a+-a+ 0 | 0+ 0+ 0 = 0 | 012: a+ 0+ 0 | 0+-a+ 0 = a (-) a | 022: a+ 0+ 0 | 0+ 0+ 0 = a (+) 0
2382 * 1 102: 0+-a+ 0 | a+ 0+ 0 = a (R-) a | 112: 0+ 0+ 0 | a+-a+ 0 = 0 | 122: 0+ 0+ 0 | a+ 0+ 0 = 0 (+) a
2383 * 2 202: 0+-a+ 0 | 0+ 0+ 0 = a (R-) 0 | 212: 0+ 0+ 0 | 0+-a+ 0 = 0 (-) a | 222: 0+ 0+ 0 | 0+ 0+ 0 = 0
2384 *
2385 * Formulae is: (a-b) * (c /32) + d
2386 * 0 1 2
2387 * a Cs Cd 0
2388 * b Cs Cd 0
2389 * c As Ad ALPHA.FIX
2390 * d Cs Cd 0
2391 *
2392 * We want to emulate Cs * F1(alpha) + Cd * F2(alpha) by OpenGl blending: (Cs * Ss (+,-,R-) Cd * Sd)
2393 * SET_ALPHA_COLOR_FACTOR(sign) set Set A (as As>>7, Ad>>7 or FIX>>7) with sign.
2394 * So we could use 1+a as one_minus_alpha and -a as alpha.
2395 *
2396 */
2397 int code = (a.a * 16) + (a.b * 4) + a.d ;
2398
2399 #define one_minus_alpha (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec]
2400 #define alpha (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec]
2401 #define one (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]
2402 #define zero (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]
2403
2404 switch (code)
2405 {
2406
2407 case 0: // 000 // Cs -- nothing changed
2408 case 20: // 110 = 16+4=20 // Cs
2409 case 40: // 220 = 32+8=40 // Cs
2410 {
2411 alphaenable = false;
2412 break;
2413 }
2414
2415 case 2: //002 // 0 -- should be zero
2416 case 22: //112 // 0
2417 case 42: //222 = 32+8+2 =42 // 0
2418 {
2419 s_rgbeq = GL_FUNC_ADD;
2420 s_srcrgb = GL_ZERO;
2421 s_dstrgb = GL_ZERO;
2422 break;
2423 }
2424
2425 case 1: //001 // Cd -- Should be destination alpha
2426 case 21: //111, // Cd -- 0*Source + 1*Desrinarion
2427 case 41: //221 = 32+8+1=41 // Cd --
2428 {
2429 s_rgbeq = GL_FUNC_ADD;
2430 s_srcrgb = GL_ZERO;
2431 s_dstrgb = GL_ONE;
2432 break;
2433 }
2434
2435 case 4: // 010 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A
2436 {
2437 bAlphaClamping = 3;
2438 SET_ALPHA_COLOR_FACTOR(0); // a = -A
2439
2440 s_rgbeq = GL_FUNC_ADD; // Cs*(1-a)+Cd*a
2441 s_srcrgb = one_minus_alpha ;
2442 s_dstrgb = alpha;
2443
2444 NeedFactor(-1);
2445 break;
2446 }
2447
2448 case 5: // 011 // (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A)
2449 {
2450 bAlphaClamping = 3; // all testing
2451 SET_ALPHA_COLOR_FACTOR(1);
2452
2453 s_rgbeq = GL_FUNC_ADD;
2454 s_srcrgb = alpha;
2455 s_dstrgb = one_minus_alpha;
2456
2457 NeedFactor(1);
2458 break;
2459 }
2460
2461 case 6: //012 // (Cs-Cd)*FIX
2462 {
2463 bAlphaClamping = 3;
2464 SET_ALPHA_COLOR_FACTOR(1);
2465
2466 s_rgbeq = GL_FUNC_SUBTRACT;
2467 s_srcrgb = alpha;
2468 s_dstrgb = alpha;
2469
2470 break;
2471 }
2472
2473 case 8: //020 // Cs*A+Cs = Cs * (1+A)
2474 {
2475 bAlphaClamping = 2; // max testing
2476 SET_ALPHA_COLOR_FACTOR(0); // Zeyflitz change this! a = -A
2477
2478 s_rgbeq = GL_FUNC_ADD;
2479 s_srcrgb = one_minus_alpha; // Cs*(1-a).
2480 s_dstrgb = GL_ZERO;
2481
2482 // NeedFactor(1);
2483 break;
2484 }
2485
2486 case 9: //021 // Cs*A+Cd
2487 {
2488 bAlphaClamping = 2; // max testing
2489 SET_ALPHA_COLOR_FACTOR(1);
2490
2491 s_rgbeq = GL_FUNC_ADD;
2492 s_srcrgb = alpha; // ZZ change it to.
2493 s_dstrgb = GL_ONE;
2494 break;
2495 }
2496
2497 case 10: //022 // Cs*A
2498 {
2499 bAlphaClamping = 2; // max testing
2500 SET_ALPHA_COLOR_FACTOR(1);
2501
2502 s_rgbeq = GL_FUNC_ADD;
2503 s_srcrgb = alpha;
2504 s_dstrgb = GL_ZERO;
2505 break;
2506 }
2507
2508 case 16: //100
2509 {
2510 bAlphaClamping = 3;
2511 SET_ALPHA_COLOR_FACTOR(1);
2512
2513 s_rgbeq = GL_FUNC_ADD;
2514 s_srcrgb = one_minus_alpha;
2515 s_dstrgb = alpha;
2516
2517 NeedFactor(1);
2518 break;
2519 }
2520
2521 case 17: //101
2522 {
2523 bAlphaClamping = 3; // all testing
2524 SET_ALPHA_COLOR_FACTOR(0);
2525
2526 s_rgbeq = GL_FUNC_ADD;
2527 s_srcrgb = alpha;
2528 s_dstrgb = one_minus_alpha;
2529
2530 NeedFactor(-1);
2531 break;
2532 }
2533
2534 case 18: //102
2535 {
2536 bAlphaClamping = 3;
2537 SET_ALPHA_COLOR_FACTOR(1);
2538
2539 s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
2540 s_srcrgb = alpha;
2541 s_dstrgb = alpha;
2542
2543 break;
2544 }
2545
2546 case 24: //120 = 16+8
2547 {
2548 bAlphaClamping = 2; // max testing
2549 SET_ALPHA_COLOR_FACTOR(1);
2550
2551 s_rgbeq = GL_FUNC_ADD;
2552 s_srcrgb = GL_ONE;
2553 s_dstrgb = alpha;
2554 break;
2555 }
2556
2557 case 25: //121 // Cd*(1+A)
2558 {
2559 bAlphaClamping = 2; // max testing
2560 SET_ALPHA_COLOR_FACTOR(0);
2561
2562 s_rgbeq = GL_FUNC_ADD;
2563 s_srcrgb = GL_ZERO;
2564 s_dstrgb = one_minus_alpha;
2565
2566 // NeedFactor(-1);
2567 break;
2568 }
2569
2570 case 26: //122
2571 {
2572 bAlphaClamping = 2;
2573 SET_ALPHA_COLOR_FACTOR(1);
2574
2575 s_rgbeq = GL_FUNC_ADD;
2576 s_srcrgb = GL_ZERO;
2577 s_dstrgb = alpha;
2578 break;
2579 }
2580
2581 case 32: // 200 = 32
2582 {
2583 bAlphaClamping = 1; // min testing
2584 SET_ALPHA_COLOR_FACTOR(1);
2585
2586 s_rgbeq = GL_FUNC_ADD;
2587 s_srcrgb = one_minus_alpha;
2588 s_dstrgb = GL_ZERO;
2589 break;
2590 }
2591
2592 case 33: //201 // -Cs*A + Cd
2593 {
2594 bAlphaClamping = 1; // min testing
2595 SET_ALPHA_COLOR_FACTOR(1);
2596
2597 s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
2598 s_srcrgb = alpha;
2599 s_dstrgb = GL_ONE;
2600 break;
2601 }
2602
2603 case 34: //202
2604 case 38: //212
2605 {
2606 bAlphaClamping = 1; // min testing -- negative values
2607
2608 s_rgbeq = GL_FUNC_ADD;
2609 s_srcrgb = GL_ZERO;
2610 s_dstrgb = GL_ZERO;
2611 break;
2612 }
2613
2614 case 36: //210
2615 {
2616 bAlphaClamping = 1; // min testing
2617 SET_ALPHA_COLOR_FACTOR(1);
2618
2619 s_rgbeq = GL_FUNC_SUBTRACT;
2620 s_srcrgb = GL_ONE;
2621 s_dstrgb = alpha;
2622 break;
2623 }
2624
2625 case 37: //211
2626 {
2627 bAlphaClamping = 1; // min testing
2628 SET_ALPHA_COLOR_FACTOR(1);
2629
2630 s_rgbeq = GL_FUNC_ADD;
2631 s_srcrgb = GL_ZERO;
2632 s_dstrgb = one_minus_alpha;
2633 break;
2634 }
2635
2636 default:
2637 {
2638 ZZLog::Error_Log("Bad alpha code %d | %d %d %d", code, a.a, a.b, a.d);
2639 }
2640 }
2641
2642 /*
2643 int t_rgbeq = GL_FUNC_ADD;
2644 int t_srcrgb = GL_ONE;
2645 int t_dstrgb = GL_ZERO;
2646 int tAlphaClamping = 0;
2647
2648 if( a.a == a.b )
2649 { // just d remains
2650 if( a.d == 0 ) {}
2651 else
2652 {
2653 t_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO;
2654 t_srcrgb = GL_ZERO;
2655 t_rgbeq = GL_FUNC_ADD; //a) (001) (111) (221) b) (002) (112) (222)
2656 }
2657 goto EndSetAlpha;
2658 }
2659 else if( a.d == 2 )
2660 { // zero
2661 if( a.a == 2 )
2662 {
2663 // zero all color
2664 t_srcrgb = GL_ZERO;
2665 t_dstrgb = GL_ZERO;
2666 goto EndSetAlpha; // (202) (212)
2667 }
2668 else if( a.b == 2 )
2669 {
2670 //b2XAlphaTest = 1; // a) (022) // b) (122)
2671 SET_ALPHA_COLOR_FACTOR(1);
2672
2673 if( bDestAlphaColor == 2 )
2674 {
2675 t_rgbeq = GL_FUNC_ADD;
2676 t_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO;
2677 t_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE;
2678 }
2679 else
2680 {
2681 tAlphaClamping = 2;
2682 t_rgbeq = GL_FUNC_ADD;
2683 t_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO;
2684 t_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec];
2685 }
2686
2687 goto EndSetAlpha;
2688 }
2689
2690 // nothing is zero, so must do some real blending //b2XAlphaTest = 1; //a) (012) //b) (102)
2691 tAlphaClamping = 3;
2692
2693 SET_ALPHA_COLOR_FACTOR(1);
2694
2695 t_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT;
2696 t_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
2697 t_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
2698 }
2699 else if( a.a == 2 )
2700 { // zero
2701
2702 //b2XAlphaTest = 1;
2703 tAlphaClamping = 1; // min testing
2704
2705 SET_ALPHA_COLOR_FACTOR(1);
2706
2707 if( a.b == a.d )
2708 {
2709 // can get away with 1-A
2710 // a.a == a.d == 2!! (200) (211)
2711 t_rgbeq = GL_FUNC_ADD;
2712 t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO;
2713 t_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec];
2714 }
2715 else
2716 {
2717 // a) (201) b)(210)
2718 t_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT;
2719 t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
2720 t_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec];
2721 }
2722 }
2723 else if( a.b == 2 )
2724 {
2725 tAlphaClamping = 2; // max testing
2726
2727 SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
2728
2729 if( a.a == a.d )
2730 {
2731 // can get away with 1+A, but need to set alpha to negative
2732 // a)(020)
2733 // b)(121)
2734 t_rgbeq = GL_FUNC_ADD;
2735
2736 if( bDestAlphaColor == 2 )
2737 {
2738 t_srcrgb = (a.a == 0) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO;
2739 t_dstrgb = (a.a == 0) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA;
2740 }
2741 else
2742 {
2743 t_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO;
2744 t_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec];
2745 }
2746 }
2747 else
2748 {
2749 //a)(021) //b)(120) //b2XAlphaTest = 1;
2750 t_rgbeq = GL_FUNC_ADD;
2751 t_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
2752 t_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec];
2753 }
2754 }
2755 else
2756 {
2757 // all 3 components are valid!
2758 tAlphaClamping = 3; // all testing
2759 SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
2760
2761 if( a.a == a.d )
2762 {
2763 // can get away with 1+A, but need to set alpha to negative // a) 010, // b) 101
2764 t_rgbeq = GL_FUNC_ADD;
2765
2766 if( bDestAlphaColor == 2 )
2767 {
2768 // all ones
2769 t_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
2770 t_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
2771 }
2772 else
2773 {
2774 t_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec];
2775 t_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec];
2776 }
2777 }
2778 else
2779 {
2780 t_rgbeq = GL_FUNC_ADD; // a) 011 // b) 100 //
2781 if( bDestAlphaColor == 2 )
2782 {
2783 // all ones
2784 t_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
2785 t_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
2786 }
2787 else
2788 {
2789 //b2XAlphaTest = 1;
2790 t_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec];
2791 t_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec];
2792 }
2793 }
2794 }
2795 EndSetAlpha:
2796
2797
2798 if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) {
2799 if (CheckArray[code][(bDestAlphaColor==2)] != -1) {
2800 ZZLog::Debug_Log( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor );
2801 ZZLog::Debug_Log( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d",
2802 code, a.a, a.b, a.d,
2803 t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping);
2804 CheckArray[code][(bDestAlphaColor==2)] = -1;
2805 }
2806 }
2807 else
2808 if (CheckArray[code][(bDestAlphaColor==2)] == 0){
2809 ZZLog::Debug_Log( "Add good code %d %d, psm %d destA %d", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor);
2810 CheckArray[code][(bDestAlphaColor==2)] = 1;
2811 }*/
2812
2813
2814 if (alphaenable)
2815 {
2816 zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
2817 zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq);
2818 glEnable(GL_BLEND); // always set
2819 }
2820 else
2821 {
2822 glDisable(GL_BLEND);
2823 }
2824
2825 INC_ALPHAVARS();
2826 }
2827
2828 void SetWriteDepth()
2829 {
2830 FUNCLOG
2831
2832 if (conf.mrtdepth)
2833 {
2834 s_bWriteDepth = true;
2835 s_nWriteDepthCount = 4;
2836 }
2837 }
2838
2839 bool IsWriteDepth()
2840 {
2841 FUNCLOG
2842 return s_bWriteDepth;
2843 }
2844
2845 bool IsWriteDestAlphaTest()
2846 {
2847 FUNCLOG
2848 return s_bDestAlphaTest;
2849 }
2850
2851 void SetDestAlphaTest()
2852 {
2853 FUNCLOG
2854 s_bDestAlphaTest = true;
2855 s_nWriteDestAlphaTest = 4;
2856 }
2857
2858 void SetTexFlush()
2859 {
2860 FUNCLOG
2861 s_bTexFlush = true;
2862
2863 // if( PSMT_ISCLUT(vb[0].tex0.psm) )
2864 // texClutWrite(0);
2865 // if( PSMT_ISCLUT(vb[1].tex0.psm) )
2866 // texClutWrite(1);
2867
2868 if (!s_bForceTexFlush)
2869 {
2870 if (s_ptexCurSet[0] != s_ptexNextSet[0]) s_ptexCurSet[0] = s_ptexNextSet[0];
2871 if (s_ptexCurSet[1] != s_ptexNextSet[1]) s_ptexCurSet[1] = s_ptexNextSet[1];
2872 }
2873 }
2874

  ViewVC Help
Powered by ViewVC 1.1.22