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