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

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

Parent Directory Parent Directory | Revision Log Revision Log


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