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

  ViewVC Help
Powered by ViewVC 1.1.22