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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 2 months ago) by william
File size: 22946 byte(s)
re-commit (had local access denied errors when committing)
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 // Realisation of RenderCRTC function ONLY.
21 // It draw picture direct on screen, so here we have interlacing and frame skipping.
22
23 //------------------ Includes
24 #include "Util.h"
25 #include "ZZoglCRTC.h"
26 #include "GLWin.h"
27 #include "ZZoglShaders.h"
28 #include "ZZoglShoots.h"
29 #include "ZZoglDrawing.h"
30 #include "rasterfont.h" // simple font
31 #include <math.h>
32 #include "ZZoglVB.h"
33
34 //------------------ Defines
35 #if !defined(ZEROGS_DEVBUILD)
36 #define g_bSaveFrame 0
37 #define g_bSaveFinalFrame 0
38 #else
39 bool g_bSaveFrame = 0; // saves the current psurfTarget
40 bool g_bSaveFinalFrame = 0; // saves the input to the CRTC
41 #endif // !defined(ZEROGS_DEVBUILD)
42
43 extern int maxmin;
44 extern bool g_bCRTCBilinear;
45 bool g_bDisplayFPS = false;
46 int g_nFrameRender = 10, g_nFramesSkipped = 0, s_nResolved = 0; // s_nResolved == number of targets resolved this frame
47 // Helper for skip frames.
48 int TimeLastSkip = 0;
49
50 vector<u32> s_vecTempTextures; // temporary textures, released at the end of every frame
51
52 // Snapshot variables.
53 extern bool g_bMakeSnapshot;
54 extern string strSnapshot;
55
56 extern void ExtWrite();
57 extern void ZZDestroy();
58 extern void ChangeDeviceSize(int nNewWidth, int nNewHeight);
59
60 extern GLuint vboRect;
61 // Adjusts vertex shader BitBltPos vector v to preserve aspect ratio. It used to emulate 4:3 or 16:9.
62 void AdjustTransToAspect(float4& v)
63 {
64 double temp;
65 float f;
66 const float mult = 1 / 32767.0f;
67
68 if (conf.width * GLWin.backbuffer.h > conf.height * GLWin.backbuffer.w) // limited by width
69 {
70 // change in ratio
71 f = ((float)GLWin.backbuffer.w / (float)conf.width) / ((float)GLWin.backbuffer.h / (float)conf.height);
72 v.y *= f;
73 v.w *= f;
74
75 // scanlines mess up when not aligned right
76 v.y += (1 - (float)modf(v.y * (float)GLWin.backbuffer.h * 0.5f + 0.05f, &temp)) * 2.0f / (float)GLWin.backbuffer.h;
77 v.w += (1 - (float)modf(v.w * (float)GLWin.backbuffer.h * 0.5f + 0.05f, &temp)) * 2.0f / (float)GLWin.backbuffer.h;
78 }
79 else // limited by height
80 {
81 f = ((float)GLWin.backbuffer.h / (float)conf.height) / ((float)GLWin.backbuffer.w / (float)conf.width);
82 f -= (float)modf(f * GLWin.backbuffer.w, &temp) / (float)GLWin.backbuffer.w;
83 v.x *= f;
84 v.z *= f;
85 }
86
87 v *= mult;
88 }
89
90 inline bool FrameSkippingHelper()
91 {
92 bool ShouldSkip = false;
93
94 if (g_nFrameRender > 0)
95 {
96 if (g_nFrameRender < 8)
97 {
98 g_nFrameRender++;
99
100 if (g_nFrameRender <= 3)
101 {
102 g_nFramesSkipped++;
103 ShouldSkip = true;
104 }
105 }
106 }
107 else
108 {
109 if (g_nFrameRender < -1)
110 {
111 g_nFramesSkipped++;
112 ShouldSkip = true;
113 }
114
115 g_nFrameRender--;
116 }
117
118 #if defined _DEBUG
119 if (timeGetTime() - TimeLastSkip > 15000 && ShouldSkip)
120 {
121 ZZLog::Debug_Log("ZZogl Skipped frames.");
122 TimeLastSkip = timeGetTime();
123 }
124 #endif
125
126 return ShouldSkip;
127 }
128
129 // helper function for save frame in picture.
130 inline void FrameSavingHelper()
131 {
132 if (g_bSaveFrame)
133 {
134 if (vb[0].prndr != NULL)
135 {
136 SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, vb[0].prndr->ptex, RW(vb[0].prndr->fbw), RH(vb[0].prndr->fbh));
137 }
138
139 if (vb[1].prndr != NULL && vb[0].prndr != vb[1].prndr)
140 {
141 SaveTexture("frame2.tga", GL_TEXTURE_RECTANGLE_NV, vb[1].prndr->ptex, RW(vb[1].prndr->fbw), RH(vb[1].prndr->fbh));
142 }
143
144 #ifdef _WIN32
145 else
146 {
147 DeleteFile("frame2.tga");
148 }
149 #endif
150 }
151 }
152
153 // Function populated tex0Info[2] array
154 inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo)
155 {
156 for (int i = 0; i < 2; ++i)
157 {
158
159 if (!(*(u32*)(PMODE) & (1 << i)))
160 {
161 dispinfo[i].tw = 0;
162 dispinfo[i].th = 0;
163 continue;
164 }
165
166 GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1;
167 GSRegDISPLAY* pd = i ? DISPLAY2 : DISPLAY1;
168 int magh = pd->MAGH + 1;
169 int magv = pd->MAGV + 1;
170
171 dispinfo[i].tbp0 = pfb->FBP << 5;
172 dispinfo[i].tbw = pfb->FBW << 6;
173 dispinfo[i].tw = (pd->DW + 1) / magh;
174 dispinfo[i].th = (pd->DH + 1) / magv;
175 dispinfo[i].psm = pfb->PSM;
176
177 // hack!!
178 // 2 * dispinfo[i].tw / dispinfo[i].th <= 1, metal slug 4
179
180 if (bInterlace && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(conf.settings().interlace_2x))
181 {
182 dispinfo[i].th >>= 1;
183 }
184 }
185 }
186
187 extern bool s_bWriteDepth;
188
189 // Something should be done before Renderering the picture.
190 inline void RenderStartHelper(u32 bInterlace)
191 {
192 if (conf.mrtdepth && pvs[8] == NULL)
193 {
194 conf.mrtdepth = 0;
195 s_bWriteDepth = false;
196
197 ZZLog::Debug_Log("Disabling MRT depth writing\n");
198 }
199
200 FlushBoth();
201
202 FrameSavingHelper();
203
204 if (s_RangeMngr.ranges.size() > 0) FlushTransferRanges(NULL);
205
206 SetShaderCaller("RenderStartHelper");
207
208 // reset fba after every frame
209 vb[0].fba.fba = 0;
210 vb[1].fba.fba = 0;
211
212 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
213
214 glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h);
215
216 // if interlace, only clear every other vsync
217 if (!bInterlace)
218 {
219 //u32 color = COLOR_ARGB(0, BGCOLOR->R, BGCOLOR->G, BGCOLOR->B);
220 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
221 }
222
223 ZZshSetVertexShader(pvsBitBlt.prog);
224
225 glBindBuffer(GL_ARRAY_BUFFER, vboRect);
226 SET_STREAM();
227 GL_REPORT_ERRORD();
228
229 if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
230
231 DisableAllgl();
232
233 GL_REPORT_ERRORD();
234
235 if (bInterlace) g_PrevBitwiseTexX = -1; // reset since will be using
236 }
237
238 // Settings for interlace texture multiplied vector;
239 // The idea is: (x, y) -- position on screen, then interlaced texture get F = 1 or 0 depending
240 // on image y coords. So if we write valpha.z * F + valpha.w + 0.5, it would be switching odd
241 // and even strings at each frame.
242 // valpha.x and y are used for image blending.
243 inline float4 RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTSHADER* prog)
244 {
245 SetShaderCaller("RenderGetForClip");
246
247 float4 valpha;
248 // first render the current render targets, then from ptexMem
249
250 if (psm == 1)
251 {
252 valpha.x = 1;
253 valpha.y = 0;
254 }
255 else
256 {
257 valpha.x = 0;
258 valpha.y = 1;
259 }
260
261 if (bInterlace)
262 {
263 if (interlace == (conf.interlace & 1))
264 {
265 // pass if odd
266 valpha.z = 1.0f;
267 valpha.w = -0.4999f;
268 }
269 else
270 {
271 // pass if even
272 valpha.z = -1.0f;
273 valpha.w = 0.5001f;
274 }
275 }
276 else
277 {
278 // always pass interlace test
279 valpha.z = 0;
280 valpha.w = 1;
281 }
282
283 ZZshSetParameter4fv(prog->prog, prog->sOneColor, valpha, "g_fOneColor");
284
285 return valpha;
286 }
287
288 // Put interlaced texture in use for shader prog.
289 // Note: if frame interlaced it's th is halved, so we should x2 it.
290 inline void RenderCreateInterlaceTex(u32 bInterlace, int th, FRAGMENTSHADER* prog)
291 {
292 if (!bInterlace) return;
293
294 int interlacetex = CreateInterlaceTex(2 * th);
295
296 ZZshGLSetTextureParameter(prog->prog, prog->sInterlace, interlacetex, "Interlace");
297 }
298
299 // Well, do blending setup prior to second pass of half-frame drawing
300 inline void RenderSetupBlending()
301 {
302 // setup right blending
303 glEnable(GL_BLEND);
304 zgsBlendEquationSeparateEXT(GL_FUNC_ADD, GL_FUNC_ADD);
305
306 if (PMODE->MMOD)
307 {
308 glBlendColorEXT(PMODE->ALP*(1 / 255.0f), PMODE->ALP*(1 / 255.0f), PMODE->ALP*(1 / 255.0f), 0.5f);
309 s_srcrgb = GL_CONSTANT_COLOR_EXT;
310 s_dstrgb = GL_ONE_MINUS_CONSTANT_COLOR_EXT;
311 }
312 else
313 {
314 s_srcrgb = GL_SRC_ALPHA;
315 s_dstrgb = GL_ONE_MINUS_SRC_ALPHA;
316 }
317
318 if (PMODE->AMOD)
319 {
320 s_srcalpha = GL_ZERO;
321 s_dstalpha = GL_ONE;
322 }
323 else
324 {
325 s_srcalpha = GL_ONE;
326 s_dstalpha = GL_ZERO;
327 }
328
329 zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
330 }
331
332 // each frame could be drawn in two stages, so blending should be different for them
333 inline void RenderSetupStencil(int i)
334 {
335 glStencilMask(1 << i);
336 s_stencilmask = 1 << i;
337 GL_STENCILFUNC_SET();
338 }
339
340 // do stencil check for each found target i -- texturing stage
341 inline void RenderUpdateStencil(int i, bool* bUsingStencil)
342 {
343 if (!(*bUsingStencil)) glClear(GL_STENCIL_BUFFER_BIT);
344
345 *bUsingStencil = 1;
346
347 glEnable(GL_STENCIL_TEST);
348 GL_STENCILFUNC(GL_NOTEQUAL, 3, 1 << i);
349 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
350 glStencilMask(1 << i);
351 }
352
353 // CRTC24 could not be rendered
354 inline void RenderCRTC24helper(u32 bInterlace, int interlace, int psm)
355 {
356 ZZLog::Debug_Log("ZZogl: CRTC24!!! I'm trying to show something.");
357 SetShaderCaller("RenderCRTC24helper");
358 // assume that data is already in ptexMem (do Resolve?)
359 RenderGetForClip(bInterlace, interlace, psm, &ppsCRTC24[bInterlace]);
360 ZZshSetPixelShader(ppsCRTC24[bInterlace].prog);
361
362 DrawTriangleArray();
363 }
364
365 // Maybe I do this function global-defined. Calculate bits per pixel for
366 // each psm. It's the only place with PSMCT16 which have a different bpp.
367 // FIXME: check PSMCT16S
368 inline int RenderGetBpp(int psm)
369 {
370 if (psm == PSMCT16S)
371 {
372 //ZZLog::Debug_Log("ZZogl: 16S target.");
373 return 3;
374 }
375
376 if (PSMT_ISHALF(psm)) return 2;
377
378 return 4;
379 }
380
381 // We want to draw ptarg on screen, that could be disaligned to viewport.
382 // So we do aligning it by height.
383 inline int RenderGetOffsets(int* dby, int* movy, tex0Info& texframe, CRenderTarget* ptarg, int bpp)
384 {
385 *dby += (256 / bpp) * (texframe.tbp0 - ptarg->fbp) / texframe.tbw;
386
387 if (*dby < 0)
388 {
389 *movy = -*dby;
390 *dby = 0;
391 }
392
393 return min(ptarg->fbh - *dby, texframe.th - *movy);
394 }
395
396 // BltBit shader calculate vertex (4 coord's pixel) position at the viewport.
397 inline float4 RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace)
398 {
399 SetShaderCaller("RenderSetTargetBitPos");
400 float4 v;
401 // dest rect
402 v.x = 1;
403 v.y = dh / (float)th;
404 v.z = 0;
405 v.w = 1 - v.y;
406
407 if (movy > 0) v.w -= movy / (float)th;
408
409 AdjustTransToAspect(v);
410
411 if (isInterlace)
412 {
413 // move down by 1 pixel
414 v.w += 1.0f / (float)dh ;
415 }
416
417 ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltPos, v, "g_fBitBltPos");
418
419 return v;
420 }
421
422 // Important stuff. We could use these coordinates to change viewport position on the frame.
423 // For example, use tw / X and tw / X magnify the viewport.
424 // Interlaced output is little out of VB, it could be seen as an evil blinking line on top
425 // and bottom, so we try to remove it.
426 inline float4 RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool isInterlace)
427 {
428 SetShaderCaller("RenderSetTargetBitTex");
429
430 float4 v;
431 v = float4(th, tw, dh, dw);
432
433 // Incorrect Aspect ratio on interlaced frames
434
435 if (isInterlace)
436 {
437 v.y -= 1.0f / conf.height;
438 v.w += 1.0f / conf.height;
439 }
440
441 ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex");
442
443 return v;
444 }
445
446 // Translator for POSITION coordinates (-1.0:+1.0f at x axis, +1.0f:-1.0y at y) into target frame ones.
447 // We don't need x coordinate, because interlacing is y-axis only.
448 inline float4 RenderSetTargetBitTrans(int th)
449 {
450 SetShaderCaller("RenderSetTargetBitTrans");
451 float4 v = float4(float(th), -float(th), float(th), float(th));
452 ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.fBitBltTrans, v, "g_fBitBltTrans");
453 return v;
454 }
455
456 // use g_fInvTexDims to store inverse texture dims
457 // Seems, that Targ shader does not use it
458 inline float4 RenderSetTargetInvTex(int bInterlace, int tw, int th, FRAGMENTSHADER* prog)
459 {
460 SetShaderCaller("RenderSetTargetInvTex");
461
462 float4 v = float4(0, 0, 0, 0);
463
464 if (prog->sInvTexDims)
465 {
466 v.x = 1.0f / (float)tw;
467 v.y = 1.0f / (float)th;
468 v.z = (float)0.0;
469 v.w = -0.5f / (float)th;
470 ZZshSetParameter4fv(prog->prog, prog->sInvTexDims, v, "g_fInvTexDims");
471 }
472
473 return v;
474 }
475
476 // Metal Slug 5 hack (as was written). If target tbp not equal to framed fbp, than we look for a better possibility,
477 // Note, than after true result iterator it could not be used.
478 inline bool RenderLookForABetterTarget(int fbp, int tbp, list<CRenderTarget*>& listTargs, list<CRenderTarget*>::iterator& it)
479 {
480 if (fbp == tbp) return false;
481
482 // look for a better target (metal slug 5)
483 list<CRenderTarget*>::iterator itbetter;
484
485 for (itbetter = listTargs.begin(); itbetter != listTargs.end(); ++itbetter)
486 {
487 if ((*itbetter)->fbp == tbp) break;
488 }
489
490 if (itbetter != listTargs.end())
491 {
492 it = listTargs.erase(it);
493 return true;
494 }
495
496 return false;
497 }
498
499 inline void RenderCheckForMemory(tex0Info& texframe, list<CRenderTarget*>& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace);
500
501 // First try to draw frame from targets.
502 inline void RenderCheckForTargets(tex0Info& texframe, list<CRenderTarget*>& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace)
503 {
504 // get the start and end addresses of the buffer
505 int bpp = RenderGetBpp(texframe.psm);
506 GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1;
507
508 int start, end;
509 GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw);
510
511 // We need share list of targets between functions
512 s_RTs.GetTargs(start, end, listTargs);
513
514 for (list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end();)
515 {
516 CRenderTarget* ptarg = *it;
517
518 if (ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256 / bpp)*(texframe.tbp0 - ptarg->fbp)) % texframe.tbw == 0)
519 {
520 int dby = pfb->DBY;
521 int movy = 0;
522
523 if (RenderLookForABetterTarget(ptarg->fbp, texframe.tbp0, listTargs, it)) continue;
524
525 if (g_bSaveFinalFrame) SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptarg->ptex, RW(ptarg->fbw), RH(ptarg->fbh));
526
527 // determine the rectangle to render
528 int dh = RenderGetOffsets(&dby, &movy, texframe, ptarg, bpp);
529
530 if (dh >= 64)
531 {
532
533 if (ptarg->fbh - dby < texframe.th - movy && !(*bUsingStencil))
534 RenderUpdateStencil(i, bUsingStencil);
535 else if (ptarg->fbh - dby > 2 * ( texframe.th - movy ))
536 {
537 // Sometimes calculated position onscreen is misaligned, ie in FFX-2 intro. In such case some part of image are out of
538 // border's and we should move it manually.
539 dby -= ((ptarg->fbh - dby) >> 2) - ((texframe.th + movy) >> 1) ;
540 }
541
542 SetShaderCaller("RenderCheckForTargets");
543
544 // Texture
545 float4 v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby), INTERLACE_COUNT);
546
547 // dest rect
548 v = RenderSetTargetBitPos(dh, texframe.th, movy, INTERLACE_COUNT);
549 v = RenderSetTargetBitTrans(ptarg->fbh);
550 v = RenderSetTargetInvTex(bInterlace, texframe.tbw, ptarg->fbh, &ppsCRTCTarg[bInterlace]) ; // FIXME. This is no use
551
552 float4 valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTCTarg[bInterlace]);
553
554 // inside vb[0]'s target area, so render that region only
555 ZZshGLSetTextureParameter(ppsCRTCTarg[bInterlace].prog, ppsCRTCTarg[bInterlace].sFinal, ptarg->ptex, "CRTC target");
556 RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTCTarg[bInterlace]);
557
558 ZZshSetPixelShader(ppsCRTCTarg[bInterlace].prog);
559
560 DrawTriangleArray();
561
562 if (abs(dh - (int)texframe.th) <= 1) return;
563
564 if (abs(dh - (int)ptarg->fbh) <= 1)
565 {
566 it = listTargs.erase(it);
567 continue;
568 }
569 }
570 }
571
572 ++it;
573 }
574 RenderCheckForMemory(texframe, listTargs, i, bUsingStencil, interlace, bInterlace);
575 }
576
577
578 // The same as the previous, but from memory.
579 // If you ever wondered why a picture from a minute ago suddenly flashes on the screen (say, in Mana Khemia),
580 // this is the function that does it.
581 inline void RenderCheckForMemory(tex0Info& texframe, list<CRenderTarget*>& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace)
582 {
583 float4 v;
584
585 for (list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end(); ++it)
586 {
587 (*it)->Resolve();
588 }
589
590 // context has to be 0
591 if (bInterlace >= 2) ZZLog::Error_Log("CRCR Check for memory shader fault.");
592
593 //if (!(*bUsingStencil)) RenderUpdateStencil(i, bUsingStencil);
594
595 SetShaderCaller("RenderCheckForMemory");
596
597 float w1, h1, w2, h2;
598 if (g_bCRTCBilinear)
599 {
600 w1 = texframe.tw;
601 h1 = texframe.th;
602 w2 = -0.5f;
603 h2 = -0.5f;
604 SetTexVariablesInt(0, 2, texframe, false, &ppsCRTC[bInterlace], 1);
605 }
606 else
607 {
608 w1 = 1;
609 h1 = 1;
610 w2 = -0.5f / (float)texframe.tw;
611 h2 = -0.5f / (float)texframe.th;
612 SetTexVariablesInt(0, 0, texframe, false, &ppsCRTC[bInterlace], 1);
613 }
614
615 if (g_bSaveFinalFrame) SaveTex(&texframe, g_bSaveFinalFrame - 1 > 0);
616
617 // Fixme: Why is this here?
618 // We should probably call RenderSetTargetBitTex instead.
619 v = RenderSetTargetBitTex(w1, h1, w2, h2, INTERLACE_COUNT);
620
621 // finally render from the memory (note that the stencil buffer will keep previous regions)
622 v = RenderSetTargetBitPos(1, 1, 0, INTERLACE_COUNT);
623 v = RenderSetTargetBitTrans(texframe.th);
624 v = RenderSetTargetInvTex(bInterlace, texframe.tw, texframe.th, &ppsCRTC[bInterlace]);
625 float4 valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTC[bInterlace]);
626
627 ZZshGLSetTextureParameter(ppsCRTC[bInterlace].prog, ppsCRTC[bInterlace].sMemory, vb[0].pmemtarg->ptex->tex, "CRTC memory");
628 RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTC[bInterlace]);
629 ZZshSetPixelShader(ppsCRTC[bInterlace].prog);
630
631 DrawTriangleArray();
632 }
633
634 extern RasterFont* font_p;
635
636 void DrawText(const char* pstr, int left, int top, u32 color)
637 {
638 FUNCLOG
639 ZZshGLDisableProfile();
640
641 float4 v;
642 v.SetColor(color);
643 glColor3f(v.z, v.y, v.x);
644
645 font_p->printString(pstr, left * 2.0f / (float)GLWin.backbuffer.w - 1, 1 - top * 2.0f / (float)GLWin.backbuffer.h, 0);
646 ZZshGLEnableProfile();
647 }
648
649 // Put FPS counter on screen (not in window title)
650 inline void DisplayFPS()
651 {
652 char str[64];
653 int left = 10, top = 15;
654 sprintf(str, "%.1f fps", fFPS);
655
656 DrawText(str, left + 1, top + 1, 0xff000000);
657 DrawText(str, left, top, 0xffc0ffff);
658 }
659
660 // SnapeShoot helper
661 inline void MakeSnapshot()
662 {
663
664 if (!g_bMakeSnapshot) return;
665
666 char str[64];
667 int left = 200, top = 15;
668 sprintf(str, "ZeroGS %d.%d.%d - %.1f fps %s", zgsrevision, zgsbuild, zgsminor, fFPS, s_frameskipping ? " - frameskipping" : "");
669
670 DrawText(str, left + 1, top + 1, 0xff000000);
671 DrawText(str, left, top, 0xffc0ffff);
672
673 if (SaveRenderTarget(strSnapshot != "" ? strSnapshot.c_str() : "temp.jpg", GLWin.backbuffer.w, -GLWin.backbuffer.h, 0)) //(conf.options.tga_snap)?0:1) ) {
674 {
675 char str[255];
676 sprintf(str, "saved %s\n", strSnapshot.c_str());
677 ZZAddMessage(str, 500);
678 }
679
680 g_bMakeSnapshot = false;
681 }
682
683 // call to destroy video resources
684 void ZZReset()
685 {
686 FUNCLOG
687 s_RTs.ResolveAll();
688 s_DepthRTs.ResolveAll();
689
690 vb[0].nCount = 0;
691 vb[1].nCount = 0;
692
693 memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
694 s_nLastResolveReset = 0;
695
696 icurctx = -1;
697 g_vsprog = g_psprog = 0;
698
699 ZZGSStateReset();
700 ZZDestroy();
701 //clear_drawfn();
702 if (ZZKick != NULL) delete ZZKick;
703 }
704
705 // Put new values on statistic variable
706 inline void CountStatistics()
707 {
708 if (s_nWriteDepthCount > 0)
709 {
710 assert(conf.mrtdepth);
711
712 if (--s_nWriteDepthCount <= 0)
713 {
714 s_bWriteDepth = false;
715 }
716 }
717
718 if (s_nWriteDestAlphaTest > 0)
719 {
720 if (--s_nWriteDestAlphaTest <= 0)
721 {
722 s_bDestAlphaTest = false;
723 }
724 }
725
726 if (g_nDepthUsed > 0) --g_nDepthUsed;
727
728 s_ClutResolve = 0;
729 g_nDepthUpdateCount = 0;
730 }
731
732 // This all could be easily forefeit
733 inline void AfterRendererUnimportantJob()
734 {
735 ProcessMessages();
736
737 if (g_bDisplayFPS) DisplayFPS();
738
739 // Swapping buffers, so we could use another window
740 GLWin.SwapGLBuffers();
741
742 // clear all targets
743 if (conf.wireframe()) s_nWireframeCount = 1;
744
745 if (g_bMakeSnapshot) MakeSnapshot();
746
747 CaptureFrame();
748 CountStatistics();
749
750 if (s_nNewWidth >= 0 && s_nNewHeight >= 0)
751 {
752 // If needed reset
753 ZZReset();
754
755 ChangeDeviceSize(s_nNewWidth, s_nNewHeight);
756 s_nNewWidth = s_nNewHeight = -1;
757 }
758
759 maxmin = 608;
760 }
761
762 extern u32 s_uFramebuffer;
763
764 // Swich Framebuffers
765 inline void AfterRendererSwitchBackToTextures()
766 {
767 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
768
769 g_MemTargs.DestroyCleared();
770
771 if (s_vecTempTextures.size() > 0)
772 glDeleteTextures((GLsizei)s_vecTempTextures.size(), &s_vecTempTextures[0]);
773
774 s_vecTempTextures.clear();
775
776 if (EXTWRITE->WRITE & 1)
777 {
778 ZZLog::Warn_Log("EXTWRITE!");
779 ExtWrite();
780 EXTWRITE->WRITE = 0;
781 }
782
783 if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
784
785 glEnable(GL_SCISSOR_TEST);
786
787 if (icurctx >= 0)
788 {
789 vb[icurctx].bVarsSetTarg = false;
790 vb[icurctx].bVarsTexSync = false;
791 vb[0].bVarsTexSync = false;
792 }
793 }
794
795 // Reset Targets Helper, for hack.
796 inline void AfterRendererAutoresetTargets()
797 {
798 if (conf.settings().auto_reset)
799 {
800 s_nResolveCounts[s_nCurResolveIndex] = s_nResolved;
801 s_nCurResolveIndex = (s_nCurResolveIndex + 1) % ArraySize(s_nResolveCounts);
802
803 int total = 0;
804
805 for (int i = 0; i < ArraySize(s_nResolveCounts); ++i) total += s_nResolveCounts[i];
806
807 if (total / ArraySize(s_nResolveCounts) > 3)
808 {
809 if (s_nLastResolveReset > (int)(fFPS * 8))
810 {
811 // reset
812 ZZLog::Error_Log("Video memory reset.");
813 s_nLastResolveReset = 0;
814 memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
815
816 s_RTs.ResolveAll();
817 return;
818 // s_RTs.Destroy();
819 // s_DepthRTs.ResolveAll();
820 // s_DepthRTs.Destroy();
821 //
822 // vb[0].prndr = NULL;
823 // vb[0].pdepth = NULL;
824 // vb[0].bNeedFrameCheck = 1;
825 // vb[0].bNeedZCheck = 1;
826 // vb[1].prndr = NULL;
827 // vb[1].pdepth = NULL;
828 // vb[1].bNeedFrameCheck = 1;
829 // vb[1].bNeedZCheck = 1;
830 }
831 }
832
833 s_nLastResolveReset++;
834 }
835
836 if (s_nResolved > 8)
837 s_nResolved = 2;
838 else if (s_nResolved > 0)
839 --s_nResolved;
840 }
841
842 int count = 0;
843 // The main renderer function
844 void RenderCRTC(int interlace)
845 {
846 if (FrameSkippingHelper()) return;
847
848 u32 bInterlace = SMODE2->INT && SMODE2->FFMD && (conf.interlace < 2);
849
850 RenderStartHelper(bInterlace);
851
852 bool bUsingStencil = false;
853 tex0Info dispinfo[2];
854
855 FrameObtainDispinfo(bInterlace, dispinfo);
856
857 // start from the last circuit
858 for (int i = !PMODE->SLBG; i >= 0; --i)
859 {
860 tex0Info& texframe = dispinfo[i];
861
862 if (texframe.th <= 1) continue;
863 if (SMODE2->INT && SMODE2->FFMD)
864 {
865 texframe.th >>= 1;
866
867 // Final Fantasy X-2 issue here.
868 if (conf.interlace == 2 && texframe.th >= 512)
869 texframe.th >>= 1;
870 }
871
872 if (i == 0) RenderSetupBlending();
873 if (bUsingStencil) RenderSetupStencil(i);
874
875 if (texframe.psm == 0x12)
876 {
877 RenderCRTC24helper(bInterlace, interlace, texframe.psm);
878 continue;
879 }
880
881 // We shader targets between two functions, so declare it here;
882 list<CRenderTarget*> listTargs;
883
884 // if we could not draw image from target's do it from memory
885 RenderCheckForTargets(texframe, listTargs, i, &bUsingStencil, interlace, bInterlace);
886 }
887
888 GL_REPORT_ERRORD();
889
890 glDisable(GL_BLEND);
891
892 AfterRendererUnimportantJob();
893 AfterRendererSwitchBackToTextures();
894 AfterRendererAutoresetTargets();
895 }

  ViewVC Help
Powered by ViewVC 1.1.22