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

  ViewVC Help
Powered by ViewVC 1.1.22