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