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