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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22