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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 191 - (show annotations) (download)
Mon Sep 20 05:35:51 2010 UTC (9 years, 9 months ago) by william
File size: 26736 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.3795 local: v0.9.7.186-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 //-------------------------- Includes
21 #if defined(_WIN32)
22 # include <windows.h>
23 # include "resource.h"
24 #endif
25
26 #include <stdlib.h>
27
28 #include "GS.h"
29 #include "Mem.h"
30 #include "x86.h"
31 #include "zerogs.h"
32 #include "targets.h"
33 #include "GLWin.h"
34 #include "ZZoglShaders.h"
35
36 //----------------------- Defines
37
38 //-------------------------- Typedefs
39 typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
40
41 //-------------------------- Extern variables
42
43 using namespace ZeroGS;
44
45 extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve;
46 extern char *libraryName;
47 extern int g_nFrame, g_nRealFrame;
48
49 //extern int s_nFullscreen;
50 //-------------------------- Variables
51
52 primInfo *prim;
53
54 inline u32 FtoDW(float f) { return (*((u32*)&f)); }
55
56 int g_nDepthUpdateCount = 0;
57
58 // Consts
59 const GLenum primtype[8] = { GL_POINTS, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, 0xffffffff };
60 static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA)
61
62 PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL;
63 PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
64 PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
65 PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
66 PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
67 PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL;
68 PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL;
69 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
70 PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
71 PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
72 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
73 PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL;
74 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
75 PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
76 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
77 PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
78 PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL;
79 PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL;
80
81 /////////////////////
82 // graphics resources
83
84 bool s_bTexFlush = false;
85 int s_nLastResolveReset = 0;
86 int s_nResolveCounts[30] = {0}; // resolve counts for last 30 frames
87
88 ////////////////////
89 // State parameters
90 int nBackbufferWidth, nBackbufferHeight; // ZZ
91
92 namespace ZeroGS
93 {
94 // = float4( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f));
95 // float4 g_vdepth = float4( 65536.0f*65536.0f, 256.0f*65536.0f, 65536.0f, 256.0f);
96
97 extern CRangeManager s_RangeMngr; // manages overwritten memory
98 GLenum GetRenderTargetFormat() { return GetRenderFormat() == RFT_byte8 ? 4 : g_internalRGBAFloat16Fmt; }
99
100 // returns the first and last addresses aligned to a page that cover
101 void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw);
102
103 int s_nNewWidth = -1, s_nNewHeight = -1;
104 void ChangeDeviceSize(int nNewWidth, int nNewHeight);
105
106 void ProcessMessages();
107 void RenderCustom(float fAlpha); // intro anim
108
109 struct MESSAGE
110 {
111 MESSAGE() {}
112
113 MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; }
114
115 char str[255];
116 u32 dwTimeStamp;
117 };
118
119 static list<MESSAGE> listMsgs;
120
121 ///////////////////////
122 // Method Prototypes //
123 ///////////////////////
124
125 void KickPoint();
126 void KickLine();
127 void KickTriangle();
128 void KickTriangleFan();
129 void KickSprite();
130 void KickDummy();
131
132 void ResolveInRange(int start, int end);
133
134 void ExtWrite();
135
136 void ResetRenderTarget(int index)
137 {
138 FBTexture(index);
139 }
140
141 DrawFn drawfn[8] = { KickDummy, KickDummy, KickDummy, KickDummy,
142 KickDummy, KickDummy, KickDummy, KickDummy
143 };
144
145 }; // end namespace
146
147 // does one time only initializing/destruction
148
149 class ZeroGSInit
150 {
151
152 public:
153 ZeroGSInit()
154 {
155 const u32 mem_size = MEMORY_END + 0x10000; // leave some room for out of range accesses (saves on the checks)
156 // clear
157 g_pbyGSMemory = (u8*)_aligned_malloc(mem_size, 1024);
158 memset(g_pbyGSMemory, 0, mem_size);
159
160 g_pbyGSClut = (u8*)_aligned_malloc(256 * 8, 1024); // need 512 alignment!
161 memset(g_pbyGSClut, 0, 256*8);
162 memset(&GLWin, 0, sizeof(GLWin));
163 }
164
165 ~ZeroGSInit()
166 {
167 _aligned_free(g_pbyGSMemory);
168 g_pbyGSMemory = NULL;
169
170 _aligned_free(g_pbyGSClut);
171 g_pbyGSClut = NULL;
172 }
173 };
174
175 static ZeroGSInit s_ZeroGSInit;
176
177 #ifndef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
178 #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
179 #endif
180
181 void ZeroGS::HandleGLError()
182 {
183 FUNCLOG
184 // check the error status of this framebuffer */
185 GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
186
187 // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort
188
189 if (error != 0)
190 {
191 int w = 0;
192 int h = 0;
193 GLint fmt;
194 glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt);
195 glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w);
196 glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h);
197
198 switch (error)
199 {
200 case GL_FRAMEBUFFER_COMPLETE_EXT:
201 break;
202
203 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
204 ZZLog::Error_Log("Error! missing a required image/buffer attachment!");
205 break;
206
207 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
208 ZZLog::Error_Log("Error! has no images/buffers attached!");
209 break;
210
211 // case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
212 // ZZLog::Error_Log("Error! has an image/buffer attached in multiple locations!");
213 // break;
214
215 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
216 ZZLog::Error_Log("Error! has mismatched image/buffer dimensions!");
217 break;
218
219 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
220 ZZLog::Error_Log("Error! colorbuffer attachments have different types!");
221 break;
222
223 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
224 ZZLog::Error_Log("Error! trying to draw to non-attached color buffer!");
225 break;
226
227 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
228 ZZLog::Error_Log("Error! trying to read from a non-attached color buffer!");
229 break;
230
231 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
232 ZZLog::Error_Log("Error! format is not supported by current graphics card/driver!");
233 break;
234
235 default:
236 ZZLog::Error_Log("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT(0x%x)!", error);
237 break;
238 }
239 }
240 }
241
242 void ZeroGS::GSStateReset()
243 {
244 FUNCLOG
245 icurctx = -1;
246
247 for (int i = 0; i < 2; ++i)
248 {
249 vb[i].Destroy();
250 memset(&vb[i], 0, sizeof(ZeroGS::VB));
251
252 vb[i].tex0.tw = 1;
253 vb[i].tex0.th = 1;
254 vb[i].scissor.x1 = 639;
255 vb[i].scissor.y1 = 479;
256 vb[i].tex0.tbw = 64;
257 vb[i].Init(VB_BUFFERSIZE);
258 }
259
260 s_RangeMngr.Clear();
261
262 g_MemTargs.Destroy();
263 s_RTs.Destroy();
264 s_DepthRTs.Destroy();
265 s_BitwiseTextures.Destroy();
266
267 vb[0].ictx = 0;
268 vb[1].ictx = 1;
269 }
270
271 void ZeroGS::Reset()
272 {
273 FUNCLOG
274 s_RTs.ResolveAll();
275 s_DepthRTs.ResolveAll();
276
277 vb[0].nCount = 0;
278 vb[1].nCount = 0;
279
280 memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
281 s_nLastResolveReset = 0;
282
283 icurctx = -1;
284 g_vsprog = g_psprog = 0;
285
286 GSStateReset();
287 Destroy(0);
288
289 drawfn[0] = KickDummy;
290 drawfn[1] = KickDummy;
291 drawfn[2] = KickDummy;
292 drawfn[3] = KickDummy;
293 drawfn[4] = KickDummy;
294 drawfn[5] = KickDummy;
295 drawfn[6] = KickDummy;
296 drawfn[7] = KickDummy;
297 }
298
299 void ZeroGS::GSReset()
300 {
301 FUNCLOG
302
303 memset(&gs, 0, sizeof(gs));
304
305 ZeroGS::GSStateReset();
306
307 gs.prac = 1;
308 prim = &gs._prim[0];
309 gs.nTriFanVert = -1;
310 gs.imageTransfer = -1;
311 gs.q = 1;
312 }
313
314 void ZeroGS::GSSoftReset(u32 mask)
315 {
316 FUNCLOG
317
318 if (mask & 1) memset(&gs.path[0], 0, sizeof(gs.path[0]));
319 if (mask & 2) memset(&gs.path[1], 0, sizeof(gs.path[1]));
320 if (mask & 4) memset(&gs.path[2], 0, sizeof(gs.path[2]));
321
322 gs.imageTransfer = -1;
323 gs.q = 1;
324 gs.nTriFanVert = -1;
325 }
326
327 void ZeroGS::AddMessage(const char* pstr, u32 ms)
328 {
329 FUNCLOG
330 listMsgs.push_back(MESSAGE(pstr, timeGetTime() + ms));
331 ZZLog::Log("%s\n", pstr);
332 }
333
334 extern RasterFont* font_p;
335 void ZeroGS::DrawText(const char* pstr, int left, int top, u32 color)
336 {
337 FUNCLOG
338 ZZshGLDisableProfile();
339
340 float4 v;
341 v.SetColor(color);
342 glColor3f(v.z, v.y, v.x);
343 //glColor3f(((color >> 16) & 0xff) / 255.0f, ((color >> 8) & 0xff)/ 255.0f, (color & 0xff) / 255.0f);
344
345 font_p->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight, 0);
346 ZZshGLEnableProfile();
347 }
348
349 void ZeroGS::ChangeWindowSize(int nNewWidth, int nNewHeight)
350 {
351 FUNCLOG
352 nBackbufferWidth = max(nNewWidth, 16);
353 nBackbufferHeight = max(nNewHeight, 16);
354
355 if (!(conf.fullscreen()))
356 {
357 conf.width = nNewWidth;
358 conf.height = nNewHeight;
359 }
360 }
361
362 void ZeroGS::SetChangeDeviceSize(int nNewWidth, int nNewHeight)
363 {
364 FUNCLOG
365 s_nNewWidth = nNewWidth;
366 s_nNewHeight = nNewHeight;
367
368 if (!(conf.fullscreen()))
369 {
370 conf.width = nNewWidth;
371 conf.height = nNewHeight;
372 }
373 }
374
375 void ZeroGS::ChangeDeviceSize(int nNewWidth, int nNewHeight)
376 {
377 FUNCLOG
378 //int oldscreen = s_nFullscreen;
379
380 int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight;
381
382 if (!Create(nNewWidth&~7, nNewHeight&~7))
383 {
384 ZZLog::Error_Log("Failed to recreate, changing to old device.");
385
386 if (Create(oldwidth, oldheight))
387 {
388 SysMessage("Failed to create device, exiting...");
389 exit(0);
390 }
391 }
392
393 for (int i = 0; i < 2; ++i)
394 {
395 vb[i].bNeedFrameCheck = vb[i].bNeedZCheck = 1;
396 vb[i].CheckFrame(0);
397 }
398
399 assert(vb[0].pBufferData != NULL && vb[1].pBufferData != NULL);
400 }
401
402 void ZeroGS::SetAA(int mode)
403 {
404 FUNCLOG
405 float f = 1.0f;
406
407 // need to flush all targets
408 s_RTs.ResolveAll();
409 s_RTs.Destroy();
410 s_DepthRTs.ResolveAll();
411 s_DepthRTs.Destroy();
412
413 AA.x = AA.y = 0; // This is code for x0, x2, x4, x8 and x16 anti-aliasing.
414
415 if (mode > 0)
416 {
417 // ( 1, 0 ) ; ( 1, 1 ) ; ( 2, 1 ) ; ( 2, 2 )
418 // it's used as a binary shift, so x >> AA.x, y >> AA.y
419 AA.x = (mode + 1) / 2;
420 AA.y = mode / 2;
421 f = 2.0f;
422 }
423
424 memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
425 s_nLastResolveReset = 0;
426
427 vb[0].prndr = NULL;
428 vb[0].pdepth = NULL;
429 vb[1].prndr = NULL;
430 vb[1].pdepth = NULL;
431
432 vb[0].bNeedFrameCheck = vb[0].bNeedZCheck = 1;
433 vb[1].bNeedFrameCheck = vb[1].bNeedZCheck = 1;
434
435 glPointSize(f);
436 }
437
438 void ZeroGS::Prim()
439 {
440 FUNCLOG
441
442 VB& curvb = vb[prim->ctxt];
443
444 if (curvb.CheckPrim()) Flush(prim->ctxt);
445
446 curvb.curprim._val = prim->_val;
447 curvb.curprim.prim = prim->prim;
448 }
449
450 void ZeroGS::ProcessMessages()
451 {
452 FUNCLOG
453
454 if (listMsgs.size() > 0)
455 {
456 int left = 25, top = 15;
457 list<MESSAGE>::iterator it = listMsgs.begin();
458
459 while (it != listMsgs.end())
460 {
461 DrawText(it->str, left + 1, top + 1, 0xff000000);
462 DrawText(it->str, left, top, 0xffffff30);
463 top += 15;
464
465 if ((int)(it->dwTimeStamp - timeGetTime()) < 0)
466 it = listMsgs.erase(it);
467 else ++it;
468 }
469 }
470 }
471
472 void ZeroGS::RenderCustom(float fAlpha)
473 {
474 FUNCLOG
475 GL_REPORT_ERROR();
476
477 fAlpha = 1;
478 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
479
480 DisableAllgl() ;
481 SetShaderCaller("RenderCustom");
482
483 glViewport(0, 0, nBackbufferWidth, nBackbufferHeight);
484
485 // play custom animation
486 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
487
488 // tex coords
489 float4 v = float4(1 / 32767.0f, 1 / 32767.0f, 0, 0);
490 ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltPos, v, "g_fBitBltPos");
491 v.x = (float)nLogoWidth;
492 v.y = (float)nLogoHeight;
493 ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex");
494
495 v.x = v.y = v.z = v.w = fAlpha;
496 ZZshSetParameter4fv(ppsBaseTexture.prog, ppsBaseTexture.sOneColor, v, "g_fOneColor");
497
498 if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
499
500 // inside vhDCb[0]'s target area, so render that region only
501 ZZshGLSetTextureParameter(ppsBaseTexture.prog, ppsBaseTexture.sFinal, ptexLogo, "Logo");
502 glBindBuffer(GL_ARRAY_BUFFER, vboRect);
503
504 SET_STREAM();
505
506 ZZshSetVertexShader(pvsBitBlt.prog);
507 ZZshSetPixelShader(ppsBaseTexture.prog);
508 DrawTriangleArray();
509
510 // restore
511 if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
512
513 ProcessMessages();
514
515 GLWin.SwapGLBuffers();
516
517 glEnable(GL_SCISSOR_TEST);
518 glEnable(GL_STENCIL_TEST);
519
520 vb[0].bSyncVars = 0;
521 vb[1].bSyncVars = 0;
522
523 GL_REPORT_ERROR();
524 }
525
526 //////////////////////////
527 // Internal Definitions //
528 //////////////////////////
529
530
531 __forceinline void MOVZ(VertexGPU *p, u32 gsz, const VB& curvb)
532 {
533 p->z = (curvb.zprimmask == 0xffff) ? min((u32)0xffff, gsz) : gsz;
534 }
535
536 __forceinline void MOVFOG(VertexGPU *p, Vertex gsf)
537 {
538 p->f = ((s16)(gsf).f << 7) | 0x7f;
539 }
540
541
542 int Values[100] = {0, };
543
544 void SET_VERTEX(VertexGPU *p, int Index, const VB& curvb)
545 {
546 int index = Index;
547 p->x = ((((int)gs.gsvertex[index].x - curvb.offset.x) >> 1) & 0xffff);
548 p->y = ((((int)gs.gsvertex[index].y - curvb.offset.y) >> 1) & 0xffff);
549 p->f = ((s16)gs.gsvertex[index].f << 7) | 0x7f;
550
551 MOVZ(p, gs.gsvertex[index].z, curvb);
552
553 p->rgba = prim->iip ? gs.gsvertex[index].rgba : gs.rgba;
554
555 // This code is somehow incorrect
556 // if ((gs.texa.aem) && ((p->rgba & 0xffffff ) == 0))
557 // p->rgba = 0;
558
559 if (conf.settings().texa)
560 {
561 u32 B = ((p->rgba & 0xfe000000) >> 1) +
562 (0x01000000 * curvb.fba.fba) ;
563 p->rgba = (p->rgba & 0xffffff) + B;
564 }
565
566 if (prim->tme)
567 {
568 if (prim->fst)
569 {
570 p->s = (float)gs.gsvertex[index].u * fiTexWidth[prim->ctxt];
571 p->t = (float)gs.gsvertex[index].v * fiTexHeight[prim->ctxt];
572 p->q = 1;
573 }
574 else
575 {
576 p->s = gs.gsvertex[index].s;
577 p->t = gs.gsvertex[index].t;
578 p->q = gs.gsvertex[index].q;
579 }
580 }
581 }
582
583 static __forceinline void OUTPUT_VERT(VertexGPU vert, u32 id)
584 {
585 #ifdef WRITE_PRIM_LOGS
586 ZZLog::Prim_Log("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)\n",
587 id == 0 ? '*' : ' ', id, prim->prim, vert.x / 8, vert.y / 8, vert.z, vert.f / 128,
588 vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10));
589 #endif
590 }
591
592 void ZeroGS::KickPoint()
593 {
594 FUNCLOG
595 assert(gs.primC >= 1);
596
597 VB& curvb = vb[prim->ctxt];
598
599 curvb.FlushTexData();
600
601 if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
602 {
603 assert(vb[prim->ctxt].nCount == 0);
604 Flush(!prim->ctxt);
605 }
606
607 curvb.NotifyWrite(1);
608
609 int last = gs.primNext(2);
610
611 VertexGPU* p = curvb.pBufferData + curvb.nCount;
612 SET_VERTEX(&p[0], last, curvb);
613 curvb.nCount++;
614
615 OUTPUT_VERT(p[0], 0);
616 }
617
618 void ZeroGS::KickLine()
619 {
620 FUNCLOG
621 assert(gs.primC >= 2);
622 VB& curvb = vb[prim->ctxt];
623
624 curvb.FlushTexData();
625
626 if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
627 {
628 assert(vb[prim->ctxt].nCount == 0);
629 Flush(!prim->ctxt);
630 }
631
632 curvb.NotifyWrite(2);
633
634 int next = gs.primNext();
635 int last = gs.primNext(2);
636
637 VertexGPU* p = curvb.pBufferData + curvb.nCount;
638 SET_VERTEX(&p[0], next, curvb);
639 SET_VERTEX(&p[1], last, curvb);
640
641 curvb.nCount += 2;
642
643 OUTPUT_VERT(p[0], 0);
644 OUTPUT_VERT(p[1], 1);
645 }
646
647 void ZeroGS::KickTriangle()
648 {
649 FUNCLOG
650 assert(gs.primC >= 3);
651 VB& curvb = vb[prim->ctxt];
652
653 curvb.FlushTexData();
654
655 if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
656 {
657 assert(vb[prim->ctxt].nCount == 0);
658 Flush(!prim->ctxt);
659 }
660
661 curvb.NotifyWrite(3);
662
663 VertexGPU* p = curvb.pBufferData + curvb.nCount;
664 SET_VERTEX(&p[0], 0, curvb);
665 SET_VERTEX(&p[1], 1, curvb);
666 SET_VERTEX(&p[2], 2, curvb);
667
668 curvb.nCount += 3;
669
670 OUTPUT_VERT(p[0], 0);
671 OUTPUT_VERT(p[1], 1);
672 OUTPUT_VERT(p[2], 2);
673 }
674
675 void ZeroGS::KickTriangleFan()
676 {
677 FUNCLOG
678 assert(gs.primC >= 3);
679 VB& curvb = vb[prim->ctxt];
680
681 curvb.FlushTexData();
682
683 if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
684 {
685 assert(vb[prim->ctxt].nCount == 0);
686 Flush(!prim->ctxt);
687 }
688
689 curvb.NotifyWrite(3);
690
691 VertexGPU* p = curvb.pBufferData + curvb.nCount;
692 SET_VERTEX(&p[0], 0, curvb);
693 SET_VERTEX(&p[1], 1, curvb);
694 SET_VERTEX(&p[2], 2, curvb);
695
696 curvb.nCount += 3;
697
698 // add 1 to skip the first vertex
699
700 if (gs.primIndex == gs.nTriFanVert) gs.primIndex = gs.primNext();
701
702 OUTPUT_VERT(p[0], 0);
703 OUTPUT_VERT(p[1], 1);
704 OUTPUT_VERT(p[2], 2);
705 }
706
707 void SetKickVertex(VertexGPU *p, Vertex v, int next, const VB& curvb)
708 {
709 SET_VERTEX(p, next, curvb);
710 MOVZ(p, v.z, curvb);
711 MOVFOG(p, v);
712 }
713
714 void ZeroGS::KickSprite()
715 {
716 FUNCLOG
717 assert(gs.primC >= 2);
718 VB& curvb = vb[prim->ctxt];
719
720 curvb.FlushTexData();
721
722 if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
723 {
724 assert(vb[prim->ctxt].nCount == 0);
725 Flush(!prim->ctxt);
726 }
727
728 curvb.NotifyWrite(6);
729 int next = gs.primNext();
730 int last = gs.primNext(2);
731
732 // sprite is too small and AA shows lines (tek4, Mana Khemia)
733 gs.gsvertex[last].x += (4 * AA.x);
734 gs.gsvertex[last].y += (4 * AA.y);
735
736 // might be bad sprite (KH dialog text)
737 //if( gs.gsvertex[next].x == gs.gsvertex[last].x || gs.gsvertex[next].y == gs.gsvertex[last].y )
738 //return;
739
740 VertexGPU* p = curvb.pBufferData + curvb.nCount;
741
742 SetKickVertex(&p[0], gs.gsvertex[last], next, curvb);
743 SetKickVertex(&p[3], gs.gsvertex[last], next, curvb);
744 SetKickVertex(&p[1], gs.gsvertex[last], last, curvb);
745 SetKickVertex(&p[4], gs.gsvertex[last], last, curvb);
746 SetKickVertex(&p[2], gs.gsvertex[last], next, curvb);
747
748 p[2].s = p[1].s;
749 p[2].x = p[1].x;
750
751 SetKickVertex(&p[5], gs.gsvertex[last], last, curvb);
752
753 p[5].s = p[0].s;
754 p[5].x = p[0].x;
755
756 curvb.nCount += 6;
757
758 OUTPUT_VERT(p[0], 0);
759 OUTPUT_VERT(p[1], 1);
760 }
761
762 void ZeroGS::KickDummy()
763 {
764 FUNCLOG
765 //ZZLog::Greg_Log("Kicking bad primitive: %.8x\n", *(u32*)prim);
766 }
767
768 void ZeroGS::SetFogColor(u32 fog)
769 {
770 FUNCLOG
771
772 // Always set the fog color, even if it was already set.
773 // if (gs.fogcol != fog)
774 // {
775 gs.fogcol = fog;
776
777 ZeroGS::FlushBoth();
778
779 SetShaderCaller("SetFogColor");
780 float4 v;
781
782 // set it immediately
783 v.SetColor(gs.fogcol);
784 ZZshSetParameter4fv(g_fparamFogColor, v, "g_fParamFogColor");
785
786 // }
787 }
788
789 void ZeroGS::SetFogColor(GIFRegFOGCOL* fog)
790 {
791 FUNCLOG
792
793 SetShaderCaller("SetFogColor");
794 float4 v;
795
796 v.x = fog->FCR / 255.0f;
797 v.y = fog->FCG / 255.0f;
798 v.z = fog->FCB / 255.0f;
799 ZZshSetParameter4fv(g_fparamFogColor, v, "g_fParamFogColor");
800 }
801
802 void ZeroGS::ExtWrite()
803 {
804 FUNCLOG
805 ZZLog::Warn_Log("A hollow voice says 'EXTWRITE'! Nothing happens.");
806
807 // use local DISPFB, EXTDATA, EXTBUF, and PMODE
808 // int bpp, start, end;
809 // tex0Info texframe;
810
811 // bpp = 4;
812 // if( texframe.psm == PSMT16S ) bpp = 3;
813 // else if (PSMT_ISHALF(texframe.psm)) bpp = 2;
814 //
815 // // get the start and end addresses of the buffer
816 // GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw);
817 }
818
819 ////////////
820 // Caches //
821 ////////////
822
823
824 // case 0: return false;
825 // case 1: break;
826 // case 2: m_CBP[0] = TEX0.CBP; break;
827 // case 3: m_CBP[1] = TEX0.CBP; break;
828 // case 4: if(m_CBP[0] == TEX0.CBP) return false; m_CBP[0] = TEX0.CBP; break;
829 // case 5: if(m_CBP[1] == TEX0.CBP) return false; m_CBP[1] = TEX0.CBP; break;
830 // case 6: ASSERT(0); return false; // ffx2 menu
831 // case 7: ASSERT(0); return false;
832 // default: __assume(0);
833
834 bool IsDirty(u32 highdword, u32 psm, int cld, int cbp)
835 {
836 int cpsm = ZZOglGet_cpsm_TexBits(highdword);
837 int csm = ZZOglGet_csm_TexBits(highdword);
838
839 if (cpsm > 1 || csm)
840 {
841 // Mana Khemia triggers this.
842 //ZZLog::Error_Log("16 bit clut not supported.");
843 return true;
844 }
845
846 int csa = ZZOglGet_csa_TexBits(highdword);
847
848 int entries = PSMT_IS8CLUT(psm) ? 256 : 16;
849
850 u64* src = (u64*)(g_pbyGSMemory + cbp * 256);
851 u64* dst = (u64*)(g_pbyGSClut + 64 * csa);
852
853 bool bRet = false;
854
855 // do a fast test with MMX
856 #ifdef _MSC_VER
857 int storeebx;
858 __asm
859 {
860 mov storeebx, ebx
861 mov edx, dst
862 mov ecx, src
863 mov ebx, entries
864
865 Start:
866 movq mm0, [edx]
867 movq mm1, [edx+8]
868 pcmpeqd mm0, [ecx]
869 pcmpeqd mm1, [ecx+16]
870
871 movq mm2, [edx+16]
872 movq mm3, [edx+24]
873 pcmpeqd mm2, [ecx+32]
874 pcmpeqd mm3, [ecx+48]
875
876 pand mm0, mm1
877 pand mm2, mm3
878 movq mm4, [edx+32]
879 movq mm5, [edx+40]
880 pcmpeqd mm4, [ecx+8]
881 pcmpeqd mm5, [ecx+24]
882
883 pand mm0, mm2
884 pand mm4, mm5
885 movq mm6, [edx+48]
886 movq mm7, [edx+56]
887 pcmpeqd mm6, [ecx+40]
888 pcmpeqd mm7, [ecx+56]
889
890 pand mm0, mm4
891 pand mm6, mm7
892 pand mm0, mm6
893
894 pmovmskb eax, mm0
895 cmp eax, 0xff
896 je Continue
897 mov bRet, 1
898 jmp Return
899
900 Continue:
901 cmp ebx, 16
902 jle Return
903
904 test ebx, 0x10
905 jz AddEcx
906 sub ecx, 448 // go back and down one column,
907
908 AddEcx:
909 add ecx, 256 // go to the right block
910
911
912 jne Continue1
913 add ecx, 256 // skip whole block
914
915 Continue1:
916 add edx, 64
917 sub ebx, 16
918 jmp Start
919
920 Return:
921 emms
922 mov ebx, storeebx
923 }
924
925 #else // linux
926 // do a fast test with MMX
927 __asm__(
928 ".intel_syntax\n"
929 "Start:\n"
930 "movq %%mm0, [%%ecx]\n"
931 "movq %%mm1, [%%ecx+8]\n"
932 "pcmpeqd %%mm0, [%%edx]\n"
933 "pcmpeqd %%mm1, [%%edx+16]\n"
934 "movq %%mm2, [%%ecx+16]\n"
935 "movq %%mm3, [%%ecx+24]\n"
936 "pcmpeqd %%mm2, [%%edx+32]\n"
937 "pcmpeqd %%mm3, [%%edx+48]\n"
938 "pand %%mm0, %%mm1\n"
939 "pand %%mm2, %%mm3\n"
940 "movq %%mm4, [%%ecx+32]\n"
941 "movq %%mm5, [%%ecx+40]\n"
942 "pcmpeqd %%mm4, [%%edx+8]\n"
943 "pcmpeqd %%mm5, [%%edx+24]\n"
944 "pand %%mm0, %%mm2\n"
945 "pand %%mm4, %%mm5\n"
946 "movq %%mm6, [%%ecx+48]\n"
947 "movq %%mm7, [%%ecx+56]\n"
948 "pcmpeqd %%mm6, [%%edx+40]\n"
949 "pcmpeqd %%mm7, [%%edx+56]\n"
950 "pand %%mm0, %%mm4\n"
951 "pand %%mm6, %%mm7\n"
952 "pand %%mm0, %%mm6\n"
953 "pmovmskb %%eax, %%mm0\n"
954 "cmp %%eax, 0xff\n"
955 "je Continue\n"
956 ".att_syntax\n"
957 "movb $1, %0\n"
958 ".intel_syntax\n"
959 "jmp Return\n"
960 "Continue:\n"
961 "cmp %%esi, 16\n"
962 "jle Return\n"
963 "test %%esi, 0x10\n"
964 "jz AddEcx\n"
965 "sub %%edx, 448\n" // go back and down one column
966 "AddEcx:\n"
967 "add %%edx, 256\n" // go to the right block
968 "cmp %%esi, 0x90\n"
969 "jne Continue1\n"
970 "add %%edx, 256\n" // skip whole block
971 "Continue1:\n"
972 "add %%ecx, 64\n"
973 "sub %%esi, 16\n"
974 "jmp Start\n"
975 "Return:\n"
976 "emms\n"
977
978 ".att_syntax\n" : "=m"(bRet) : "c"(dst), "d"(src), "S"(entries) : "eax", "memory");
979
980 #endif // _WIN32
981 return bRet;
982 }
983
984 // cld state:
985 // 000 - clut data is not loaded; data in the temp buffer is stored
986 // 001 - clut data is always loaded.
987 // 010 - clut data is always loaded; cbp0 = cbp.
988 // 011 - clut data is always loadedl cbp1 = cbp.
989 // 100 - cbp0 is compared with cbp. if different, clut data is loaded.
990 // 101 - cbp1 is compared with cbp. if different, clut data is loaded.
991
992 // GSdx sets cbp0 & cbp1 when checking for clut changes. ZeroGS sets them in texClutWrite.
993 bool ZeroGS::CheckChangeInClut(u32 highdword, u32 psm)
994 {
995 FUNCLOG
996 int cld = ZZOglGet_cld_TexBits(highdword);
997 int cbp = ZZOglGet_cbp_TexBits(highdword);
998
999 // processing the CLUT after tex0/2 are written
1000 //ZZLog::Error_Log("high == 0x%x; cld == %d", highdword, cld);
1001
1002 switch (cld)
1003 {
1004 case 0:
1005 return false;
1006
1007 case 1:
1008 break;
1009
1010 case 2:
1011 break;
1012
1013 case 3:
1014 break;
1015
1016 case 4:
1017 if (gs.cbp[0] == cbp) return false;
1018 break;
1019
1020 case 5:
1021 if (gs.cbp[1] == cbp) return false;
1022 break;
1023
1024 //case 4: return gs.cbp[0] != cbp;
1025 //case 5: return gs.cbp[1] != cbp;
1026
1027 // default: load
1028
1029 default:
1030 break;
1031 }
1032
1033 return IsDirty(highdword, psm, cld, cbp);
1034 }
1035
1036 void ZeroGS::texClutWrite(int ctx)
1037 {
1038 FUNCLOG
1039 s_bTexFlush = false;
1040
1041 tex0Info& tex0 = vb[ctx].tex0;
1042
1043 assert(PSMT_ISCLUT(tex0.psm));
1044
1045 // processing the CLUT after tex0/2 are written
1046 switch (tex0.cld)
1047 {
1048 case 0:
1049 return;
1050
1051 case 1:
1052 break; // tex0.cld is usually 1.
1053
1054 case 2:
1055 gs.cbp[0] = tex0.cbp;
1056 break;
1057
1058 case 3:
1059 gs.cbp[1] = tex0.cbp;
1060 break;
1061
1062 case 4:
1063 if (gs.cbp[0] == tex0.cbp) return;
1064 gs.cbp[0] = tex0.cbp;
1065 break;
1066
1067 case 5:
1068 if (gs.cbp[1] == tex0.cbp) return;
1069 gs.cbp[1] = tex0.cbp;
1070 break;
1071
1072 default: //ZZLog::Debug_Log("cld isn't 0-5!");
1073 break;
1074 }
1075
1076 Flush(!ctx);
1077
1078 int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16;
1079
1080 if (tex0.csm)
1081 {
1082 switch (tex0.cpsm)
1083 {
1084 // 16bit psm
1085 // eggomania uses non16bit textures for csm2
1086
1087 case PSMCT16:
1088 {
1089 u16* src = (u16*)g_pbyGSMemory + tex0.cbp * 128;
1090 u16 *dst = (u16*)(g_pbyGSClut + 32 * (tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0));
1091
1092 for (int i = 0; i < entries; ++i)
1093 {
1094 *dst = src[getPixelAddress16_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)];
1095 dst += 2;
1096
1097 // check for wrapping
1098
1099 if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut + 2);
1100 }
1101 break;
1102 }
1103
1104 case PSMCT16S:
1105 {
1106 u16* src = (u16*)g_pbyGSMemory + tex0.cbp * 128;
1107 u16 *dst = (u16*)(g_pbyGSClut + 32 * (tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0));
1108
1109 for (int i = 0; i < entries; ++i)
1110 {
1111 *dst = src[getPixelAddress16S_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)];
1112 dst += 2;
1113
1114 // check for wrapping
1115
1116 if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut + 2);
1117 }
1118 break;
1119 }
1120
1121 case PSMCT32:
1122 case PSMCT24:
1123 {
1124 u32* src = (u32*)g_pbyGSMemory + tex0.cbp * 64;
1125 u32 *dst = (u32*)(g_pbyGSClut + 64 * tex0.csa);
1126
1127 // check if address exceeds src
1128
1129 if (src + getPixelAddress32_0(gs.clut.cou + entries - 1, gs.clut.cov, gs.clut.cbw) >= (u32*)g_pbyGSMemory + 0x00100000)
1130 ZZLog::Error_Log("texClutWrite out of bounds.");
1131 else
1132 for (int i = 0; i < entries; ++i)
1133 {
1134 *dst = src[getPixelAddress32_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)];
1135 dst++;
1136 }
1137 break;
1138 }
1139
1140 default:
1141 {
1142 //ZZLog::Debug_Log("Unknown cpsm: %x (%x).", tex0.cpsm, tex0.psm);
1143 break;
1144 }
1145 }
1146 }
1147 else
1148 {
1149 u32* src = (u32*)(g_pbyGSMemory + 256 * tex0.cbp);
1150
1151 if (entries == 16)
1152 {
1153 switch (tex0.cpsm)
1154 {
1155 case PSMCT24:
1156 case PSMCT32:
1157 WriteCLUT_T32_I4_CSM1(src, (u32*)(g_pbyGSClut + 64 * tex0.csa));
1158 break;
1159
1160 default:
1161 WriteCLUT_T16_I4_CSM1(src, (u32*)(g_pbyGSClut + 32*(tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0)));
1162 break;
1163 }
1164 }
1165 else
1166 {
1167 switch (tex0.cpsm)
1168 {
1169 case PSMCT24:
1170 case PSMCT32:
1171 WriteCLUT_T32_I8_CSM1(src, (u32*)(g_pbyGSClut + 64 * tex0.csa));
1172 break;
1173
1174 default:
1175 // sse2 for 256 is more complicated, so use regular
1176 WriteCLUT_T16_I8_CSM1_c(src, (u32*)(g_pbyGSClut + 32*(tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0)));
1177 break;
1178 }
1179
1180 }
1181 }
1182 }
1183
1184

  ViewVC Help
Powered by ViewVC 1.1.22