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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 133 - (show annotations) (download)
Fri Sep 10 12:49:21 2010 UTC (9 years, 11 months ago) by william
File size: 79675 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.3745 local: v0.9.7.128) in ./trunk
1 /* ZZ Open GL graphics plugin
2 * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
3 * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 // Realization of Flush -- drawing function of GS
21
22 #include <stdlib.h>
23
24 #include "GS.h"
25 #include "Mem.h"
26 #include "zerogs.h"
27 #include "targets.h"
28
29 using namespace ZeroGS;
30
31 //------------------ Defines
32 #ifndef ZEROGS_DEVBUILD
33
34 #define INC_GENVARS()
35 #define INC_TEXVARS()
36 #define INC_ALPHAVARS()
37 #define INC_RESOLVE()
38
39 #define g_bUpdateEffect 0
40 #define g_bSaveTex 0
41 bool g_bSaveTrans = 0;
42 #define g_bSaveResolved 0
43
44 #else // defined(ZEROGS_DEVBUILD)
45
46 #define INC_GENVARS() ++g_nGenVars
47 #define INC_TEXVARS() ++g_nTexVars
48 #define INC_ALPHAVARS() ++g_nAlphaVars
49 #define INC_RESOLVE() ++g_nResolve
50
51 bool g_bSaveTrans = 0;
52 bool g_bUpdateEffect = 0;
53 bool g_bSaveTex = 0; // saves the curent texture
54 bool g_bSaveResolved = 0;
55 #endif // !defined(ZEROGS_DEVBUILD)
56
57 #define STENCIL_ALPHABIT 1 // if set, dest alpha >= 0x80
58 #define STENCIL_PIXELWRITE 2 // if set, pixel just written (reset after every Flush)
59 #define STENCIL_FBA 4 // if set, just written pixel's alpha >= 0 (reset after every Flush)
60 #define STENCIL_SPECIAL 8 // if set, indicates that pixel passed its alpha test (reset after every Flush)
61 //#define STENCIL_PBE 16
62 #define STENCIL_CLEAR (2|4|8|16)
63
64 void Draw(const VB& curvb)
65 {
66 glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount);
67 }
68
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 extern int g_nDepthBias;
121 extern float g_fBlockMult;
122 bool g_bUpdateStencil = 1;
123 //u32 g_SaveFrameNum = 0; // ZZ
124
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 static u32 s_ptexCurSet[2] = {0};
146 static u32 s_ptexNextSet[2] = {0}; // ZZ
147
148
149 extern vector<u32> s_vecTempTextures; // temporary textures, released at the end of every frame
150 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 static bool bNeedBlendFactorInAlpha; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80)
163 static u32 s_dwColorWrite = 0xf; // the color write mask of the current target
164
165 typedef union
166 {
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 } g_flag_vars;
178
179 g_flag_vars g_vars;
180
181 //#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 //static alphaInfo s_alphaInfo; // ZZ
189
190 extern u8* g_pbyGSClut;
191 extern int ppf;
192
193 int s_nWireframeCount = 0;
194
195 //------------------ 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 if (conf.wireframe())
256 {
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 if (conf.wireframe())
268 {
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 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 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 ZZLog::Debug_Log("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d",
327 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 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 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 // ZZLog::Debug_Log("frame: %d, buffer %ld.\n", g_SaveFrameNum, BufferNumber);
343 ZZLog::Debug_Log("buffer %ld.\n", BufferNumber);
344 #endif
345 }
346
347 inline void SaveRendererTarget(VB& curvb)
348 {
349 #ifdef _DEBUG
350
351 // 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
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 if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0))
379 {
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 // If set bit for texture checking, do it. Maybe it's all.
403 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 if ((ptextarg == NULL) && (tpsm == PSMT8) && (conf.settings().reget))
462 {
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 if ((ptextarg == NULL) && (conf.settings().texture_targs))
494 {
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 #ifdef _DEBUG
503 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 #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 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
661 GL_REPORT_ERRORD();
662 }
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 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 s_vecTempTextures.push_back(ptexclut);
782
783 if (g_bSaveTex) SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1);
784
785 setTex2DWrap(GL_REPEAT);
786 setTex2DFilters(GL_LINEAR);
787 }
788 }
789
790 inline int FlushGetShaderType(VB& curvb, CRenderTarget* ptextarg, GLuint& ptexclut)
791 {
792 if (PSMT_ISCLUT(curvb.tex0.psm) && !(conf.settings().no_target_clut))
793 {
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 //Set page offsets depends on shader type.
828 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 // 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 {
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 pfragment = FlushUseExistRenderTarget(curvb, ptextarg, dwFilterOpts, exactcolor, context);
1055 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 !ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(conf.settings().no_stencil);
1086 }
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 Draw(curvb);
1257 }
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 Draw(curvb);
1282
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 if ((!curtest.ate) || (curtest.atst == 1) || (curtest.afail == 0)) return true;
1297
1298 if (conf.settings().no_alpha_fail && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64))))
1299 return true;
1300
1301 // old and seemingly incorrect code.
1302 // if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1)
1303 // return true;
1304 // if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(conf.settings() & GAME_REGETHACK))
1305 // 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 Draw(curvb);
1355
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 Draw(curvb);
1375
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 Draw(curvb);
1426
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 //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 {
1487 //ZZLog::Error_Log("Clamped.");
1488 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 Draw(curvb);
1513 }
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 Draw(curvb);
1522 }
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 u32 dwUsingSpecialTesting = 0, dwFilterOpts = 0;
1570 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 void ZeroGS::FlushBoth()
1612 {
1613 Flush(0);
1614 Flush(1);
1615 }
1616
1617 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 Draw(curvb);
1641
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 Draw(curvb);
1694
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 Draw(curvb);
1712
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 Draw(curvb);
1767
1768 // process when alpha >= 0xff
1769 GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE | STENCIL_FBA | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
1770 Draw(curvb);
1771
1772 // clear STENCIL_PIXELWRITE bit
1773 glStencilMask(STENCIL_CLEAR);
1774
1775 GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
1776 Draw(curvb);
1777
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 Draw(curvb);
1828 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 Draw(curvb);
1835
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 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
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 #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
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 v.z = (float)fw;
2035 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 v.w = (float)fh;
2070 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.0f ;
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.0f + (tex0.tfx == 0)) ;
2155 }
2156 else
2157 {
2158 valpha.x = (gs.texa.fta[0]) * (1.0f + (tex0.tfx == 0)) ;
2159 valpha.y = (gs.texa.fta[psm!=1] - gs.texa.fta[0]) * (1.0f + (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 bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */ \
2425 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 bNeedBlendFactorInAlpha = (w + 1) ? true : false;
2449 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 bNeedBlendFactorInAlpha = false;
2464 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 // s_alphaInfo = a;
2475 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; // Cs*(1-a).
2601 s_dstrgb = GL_ZERO;
2602
2603 // NeedFactor(1);
2604 break;
2605 }
2606
2607 case 9: //021 // Cs*A+Cd
2608 {
2609 bAlphaClamping = 2; // max testing
2610 SET_ALPHA_COLOR_FACTOR(1);
2611
2612 s_rgbeq = GL_FUNC_ADD;
2613 s_srcrgb = alpha; // ZZ change it to.
2614 s_dstrgb = GL_ONE;
2615 break;
2616 }
2617
2618 case 10: //022 // Cs*A
2619 {
2620 bAlphaClamping = 2; // max testing
2621 SET_ALPHA_COLOR_FACTOR(1);
2622
2623 s_rgbeq = GL_FUNC_ADD;
2624 s_srcrgb = alpha;
2625 s_dstrgb = GL_ZERO;
2626 break;
2627 }
2628
2629 case 16: //100
2630 {
2631 bAlphaClamping = 3;
2632 SET_ALPHA_COLOR_FACTOR(1);
2633
2634 s_rgbeq = GL_FUNC_ADD;
2635 s_srcrgb = one_minus_alpha;
2636 s_dstrgb = alpha;
2637
2638 NeedFactor(1);
2639 break;
2640 }
2641
2642 case 17: //101
2643 {
2644 bAlphaClamping = 3; // all testing
2645 SET_ALPHA_COLOR_FACTOR(0);
2646
2647 s_rgbeq = GL_FUNC_ADD;
2648 s_srcrgb = alpha;
2649 s_dstrgb = one_minus_alpha;
2650
2651 NeedFactor(-1);
2652 break;
2653 }
2654
2655 case 18: //102
2656 {
2657 bAlphaClamping = 3;
2658 SET_ALPHA_COLOR_FACTOR(1);
2659
2660 s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
2661 s_srcrgb = alpha;
2662 s_dstrgb = alpha;
2663
2664 break;
2665 }
2666
2667 case 24: //120 = 16+8
2668 {
2669 bAlphaClamping = 2; // max testing
2670 SET_ALPHA_COLOR_FACTOR(1);
2671
2672 s_rgbeq = GL_FUNC_ADD;
2673 s_srcrgb = GL_ONE;
2674 s_dstrgb = alpha;
2675 break;
2676 }
2677
2678 case 25: //121 // Cd*(1+A)
2679 {
2680 bAlphaClamping = 2; // max testing
2681 SET_ALPHA_COLOR_FACTOR(0);
2682
2683 s_rgbeq = GL_FUNC_ADD;
2684 s_srcrgb = GL_ZERO;
2685 s_dstrgb = one_minus_alpha;
2686
2687 // NeedFactor(-1);
2688 break;
2689 }
2690
2691 case 26: //122
2692 {
2693 bAlphaClamping = 2;
2694 SET_ALPHA_COLOR_FACTOR(1);
2695
2696 s_rgbeq = GL_FUNC_ADD;
2697 s_srcrgb = GL_ZERO;
2698 s_dstrgb = alpha;
2699 break;
2700 }
2701
2702 case 32: // 200 = 32
2703 {
2704 bAlphaClamping = 1; // min testing
2705 SET_ALPHA_COLOR_FACTOR(1);
2706
2707 s_rgbeq = GL_FUNC_ADD;
2708 s_srcrgb = one_minus_alpha;
2709 s_dstrgb = GL_ZERO;
2710 break;
2711 }
2712
2713 case 33: //201 // -Cs*A + Cd
2714 {
2715 bAlphaClamping = 1; // min testing
2716 SET_ALPHA_COLOR_FACTOR(1);
2717
2718 s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
2719 s_srcrgb = alpha;
2720 s_dstrgb = GL_ONE;
2721 break;
2722 }
2723
2724 case 34: //202
2725 case 38: //212
2726 {
2727 bAlphaClamping = 1; // min testing -- negative values
2728
2729 s_rgbeq = GL_FUNC_ADD;
2730 s_srcrgb = GL_ZERO;
2731 s_dstrgb = GL_ZERO;
2732 break;
2733 }
2734
2735 case 36: //210
2736 {
2737 bAlphaClamping = 1; // min testing
2738 SET_ALPHA_COLOR_FACTOR(1);
2739
2740 s_rgbeq = GL_FUNC_SUBTRACT;
2741 s_srcrgb = GL_ONE;
2742 s_dstrgb = alpha;
2743 break;
2744 }
2745
2746 case 37: //211
2747 {
2748 bAlphaClamping = 1; // min testing
2749 SET_ALPHA_COLOR_FACTOR(1);
2750
2751 s_rgbeq = GL_FUNC_ADD;
2752 s_srcrgb = GL_ZERO;
2753 s_dstrgb = one_minus_alpha;
2754 break;
2755 }
2756
2757 default:
2758 {
2759 ZZLog::Error_Log("Bad alpha code %d | %d %d %d", code, a.a, a.b, a.d);
2760 }
2761 }
2762
2763 /*
2764 int t_rgbeq = GL_FUNC_ADD;
2765 int t_srcrgb = GL_ONE;
2766 int t_dstrgb = GL_ZERO;
2767 int tAlphaClamping = 0;
2768
2769 if( a.a == a.b )
2770 { // just d remains
2771 if( a.d == 0 ) {}
2772 else
2773 {
2774 t_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO;
2775 t_srcrgb = GL_ZERO;
2776 t_rgbeq = GL_FUNC_ADD; //a) (001) (111) (221) b) (002) (112) (222)
2777 }
2778 goto EndSetAlpha;
2779 }
2780 else if( a.d == 2 )
2781 { // zero
2782 if( a.a == 2 )
2783 {
2784 // zero all color
2785 t_srcrgb = GL_ZERO;
2786 t_dstrgb = GL_ZERO;
2787 goto EndSetAlpha; // (202) (212)
2788 }
2789 else if( a.b == 2 )
2790 {
2791 //b2XAlphaTest = 1; // a) (022) // b) (122)
2792 SET_ALPHA_COLOR_FACTOR(1);
2793
2794 if( bDestAlphaColor == 2 )
2795 {
2796 t_rgbeq = GL_FUNC_ADD;
2797 t_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO;
2798 t_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE;
2799 }
2800 else
2801 {
2802 tAlphaClamping = 2;
2803 t_rgbeq = GL_FUNC_ADD;
2804 t_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO;
2805 t_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec];
2806 }
2807
2808 goto EndSetAlpha;
2809 }
2810
2811 // nothing is zero, so must do some real blending //b2XAlphaTest = 1; //a) (012) //b) (102)
2812 tAlphaClamping = 3;
2813
2814 SET_ALPHA_COLOR_FACTOR(1);
2815
2816 t_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT;
2817 t_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
2818 t_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
2819 }
2820 else if( a.a == 2 )
2821 { // zero
2822
2823 //b2XAlphaTest = 1;
2824 tAlphaClamping = 1; // min testing
2825
2826 SET_ALPHA_COLOR_FACTOR(1);
2827
2828 if( a.b == a.d )
2829 {
2830 // can get away with 1-A
2831 // a.a == a.d == 2!! (200) (211)
2832 t_rgbeq = GL_FUNC_ADD;
2833 t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO;
2834 t_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec];
2835 }
2836 else
2837 {
2838 // a) (201) b)(210)
2839 t_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT;
2840 t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
2841 t_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec];
2842 }
2843 }
2844 else if( a.b == 2 )
2845 {
2846 tAlphaClamping = 2; // max testing
2847
2848 SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
2849
2850 if( a.a == a.d )
2851 {
2852 // can get away with 1+A, but need to set alpha to negative
2853 // a)(020)
2854 // b)(121)
2855 t_rgbeq = GL_FUNC_ADD;
2856
2857 if( bDestAlphaColor == 2 )
2858 {
2859 t_srcrgb = (a.a == 0) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO;
2860 t_dstrgb = (a.a == 0) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA;
2861 }
2862 else
2863 {
2864 t_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO;
2865 t_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec];
2866 }
2867 }
2868 else
2869 {
2870 //a)(021) //b)(120) //b2XAlphaTest = 1;
2871 t_rgbeq = GL_FUNC_ADD;
2872 t_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
2873 t_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec];
2874 }
2875 }
2876 else
2877 {
2878 // all 3 components are valid!
2879 tAlphaClamping = 3; // all testing
2880 SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
2881
2882 if( a.a == a.d )
2883 {
2884 // can get away with 1+A, but need to set alpha to negative // a) 010, // b) 101
2885 t_rgbeq = GL_FUNC_ADD;
2886
2887 if( bDestAlphaColor == 2 )
2888 {
2889 // all ones
2890 t_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
2891 t_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
2892 }
2893 else
2894 {
2895 t_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec];
2896 t_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec];
2897 }
2898 }
2899 else
2900 {
2901 t_rgbeq = GL_FUNC_ADD; // a) 011 // b) 100 //
2902 if( bDestAlphaColor == 2 )
2903 {
2904 // all ones
2905 t_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
2906 t_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
2907 }
2908 else
2909 {
2910 //b2XAlphaTest = 1;
2911 t_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec];
2912 t_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec];
2913 }
2914 }
2915 }
2916 EndSetAlpha:
2917
2918
2919 if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) {
2920 if (CheckArray[code][(bDestAlphaColor==2)] != -1) {
2921 printf ( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d\n", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor );
2922 printf ( " Difference %d %d %d %d | 0x%x 0x%x | 0x%x 0x%x | 0x%x 0x%x | %d %d\n",
2923 code, a.a, a.b, a.d,
2924 t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping);
2925 CheckArray[code][(bDestAlphaColor==2)] = -1;
2926 }
2927 }
2928 else
2929 if (CheckArray[code][(bDestAlphaColor==2)] == 0){
2930 printf ( "Add good code %d %d, psm %d destA %d\n", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor);
2931 CheckArray[code][(bDestAlphaColor==2)] = 1;
2932 }*/
2933
2934
2935 if (alphaenable)
2936 {
2937 zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
2938 zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq);
2939 glEnable(GL_BLEND); // always set
2940 }
2941 else
2942 {
2943 glDisable(GL_BLEND);
2944 }
2945
2946 INC_ALPHAVARS();
2947 }
2948
2949 void ZeroGS::SetWriteDepth()
2950 {
2951 FUNCLOG
2952
2953 if (conf.mrtdepth)
2954 {
2955 s_bWriteDepth = true;
2956 s_nWriteDepthCount = 4;
2957 }
2958 }
2959
2960 bool ZeroGS::IsWriteDepth()
2961 {
2962 FUNCLOG
2963 return s_bWriteDepth;
2964 }
2965
2966 bool ZeroGS::IsWriteDestAlphaTest()
2967 {
2968 FUNCLOG
2969 return s_bDestAlphaTest;
2970 }
2971
2972 void ZeroGS::SetDestAlphaTest()
2973 {
2974 FUNCLOG
2975 s_bDestAlphaTest = true;
2976 s_nWriteDestAlphaTest = 4;
2977 }
2978
2979 void ZeroGS::SetTexFlush()
2980 {
2981 FUNCLOG
2982 s_bTexFlush = true;
2983
2984 // if( PSMT_ISCLUT(vb[0].tex0.psm) )
2985 // texClutWrite(0);
2986 // if( PSMT_ISCLUT(vb[1].tex0.psm) )
2987 // texClutWrite(1);
2988
2989 if (!s_bForceTexFlush)
2990 {
2991 if (s_ptexCurSet[0] != s_ptexNextSet[0]) s_ptexCurSet[0] = s_ptexNextSet[0];
2992 if (s_ptexCurSet[1] != s_ptexNextSet[1]) s_ptexCurSet[1] = s_ptexNextSet[1];
2993 }
2994 }
2995

  ViewVC Help
Powered by ViewVC 1.1.22