diff --git a/plugins/zzogl-pg/opengl/ZZoglFlushHack.h b/plugins/zzogl-pg/opengl/ZZoglFlushHack.h index 9087f2a3a9..999f399db6 100644 --- a/plugins/zzogl-pg/opengl/ZZoglFlushHack.h +++ b/plugins/zzogl-pg/opengl/ZZoglFlushHack.h @@ -28,6 +28,7 @@ #include "GS.h" #include "zerogs.h" +#include "targets.h" extern int g_SkipFlushFrame; diff --git a/plugins/zzogl-pg/opengl/targets.h b/plugins/zzogl-pg/opengl/targets.h index 7701b7dce8..ef2000f31c 100644 --- a/plugins/zzogl-pg/opengl/targets.h +++ b/plugins/zzogl-pg/opengl/targets.h @@ -27,10 +27,318 @@ #define GL_TEXTURE_RECTANGLE GL_TEXTURE_RECTANGLE_NV #endif +#define VB_BUFFERSIZE 0x400 + +// managers render-to-texture targets +class CRenderTarget +{ + + public: + CRenderTarget(); + virtual ~CRenderTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + // set the GPU_POSXY variable, scissor rect, and current render target + void SetTarget(int fbplocal, const Rect2& scissor, int context); + void SetViewport(); + + // copies/creates the feedback contents + inline void CreateFeedback() + { + if (ptexFeedback == 0 || !(status&TS_FeedbackReady)) + _CreateFeedback(); + } + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* pdepth); + virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0 + virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2 + + virtual bool IsDepth() { return false; } + + void SetRenderTarget(int targ); + + void* psys; // system data used for comparison + u32 ptex; + + int fbp, fbw, fbh, fbhCalc; // if fbp is negative, virtual target (not mapped to any real addr) + int start, end; // in bytes + u32 lastused; // time stamp since last used + float4 vposxy; + + u32 fbm; + u16 status; + u8 psm; + u8 resv0; + Rect scissorrect; + + u8 created; // Check for object destruction/creating for r201. + + //int startresolve, endresolve; + u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only) + + // this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself) + u32 ptexFeedback; + + enum TargetStatus + { + TS_Resolved = 1, + TS_NeedUpdate = 2, + TS_Virtual = 4, // currently not mapped to memory + TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated + TS_NeedConvert32 = 16, + TS_NeedConvert16 = 32, + }; + inline float4 DefaultBitBltPos(); + inline float4 DefaultBitBltTex(); + + private: + void _CreateFeedback(); + inline bool InitialiseDefaultTexture(u32 *p_ptr, int fbw, int fbh) ; +}; + +// manages zbuffers + +class CDepthTarget : public CRenderTarget +{ + + public: + CDepthTarget(); + virtual ~CDepthTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* prndr); + + virtual bool IsDepth() { return true; } + + void SetDepthStencilSurface(); + + u32 pdepth; // 24 bit, will contain the stencil buffer if possible + u32 pstencil; // if not 0, contains the stencil buffer + int icount; // internal counter +}; + +// manages contiguous chunks of memory (width is always 1024) + +class CMemoryTarget +{ + public: + struct TEXTURE + { + inline TEXTURE() : tex(0), memptr(NULL), ref(0) {} + inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); } + + u32 tex; + u8* memptr; // GPU memory used for comparison + int ref; + }; + + inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0) {} + + inline CMemoryTarget(const CMemoryTarget& r) + { + ptex = r.ptex; + + if (ptex != NULL) ptex->ref++; + + starty = r.starty; + height = r.height; + realy = r.realy; + realheight = r.realheight; + usedstamp = r.usedstamp; + psm = r.psm; + cpsm = r.cpsm; + clut = r.clut; + clearminy = r.clearminy; + clearmaxy = r.clearmaxy; + widthmult = r.widthmult; + texH = r.texH; + texW = r.texW; + channels = r.channels; + validatecount = r.validatecount; + fmt = r.fmt; + } + + ~CMemoryTarget() { Destroy(); } + + inline void Destroy() + { + if (ptex != NULL && ptex->ref > 0) + { + if (--ptex->ref <= 0) delete ptex; + } + + ptex = NULL; + } + + // returns true if clut data is synced + bool ValidateClut(const tex0Info& tex0); + // returns true if tex data is synced + bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex); + + // realy is offset in pixels from start of valid region + // so texture in memory is [realy,starty+height] + // valid texture is [starty,starty+height] + // offset in mem [starty-realy, height] + TEXTURE* ptex; // can be 16bit + + int starty, height; // assert(starty >= realy) + int realy, realheight; // this is never touched once allocated + // realy is start pointer of data in 4M data block (start) and size (end-start). + + u32 usedstamp; + u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters + + u32 fmt; + + int widthmult; // Either 1 or 2. + int channels; // The number of pixels per PSM format word. channels == PIXELS_PER_WORD(psm) + // This is the real drawing size in pixels of the texture in renderbuffer. + int texW; // (realheight + widthmult - 1)/widthmult == realheight or [(realheight+1)/2] + int texH; // GPU_TEXWIDTH *widthmult * channels; + + int clearminy, clearmaxy; // when maxy > 0, need to check for clearing + + int validatecount; // count how many times has been validated, if too many, destroy + + vector clut; // if nonzero, texture uses CLUT +}; + + +struct VB +{ + VB(); + ~VB(); + + void Destroy(); + + inline bool CheckPrim() + { + static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA) + + if ((PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim]) + return nCount > 0; + + return false; + } + + void CheckFrame(int tbp); + + // context specific state + Point offset; + Rect2 scissor; + tex0Info tex0; + tex1Info tex1; + miptbpInfo miptbp0; + miptbpInfo miptbp1; + alphaInfo alpha; + fbaInfo fba; + clampInfo clamp; + pixTest test; + u32 ptexClamp[2]; // textures for x and y dir region clamping + +public: + void FlushTexData(); + inline int CheckFrameAddConstraints(int tbp); + inline void CheckScissors(int maxpos); + inline void CheckFrame32bitRes(int maxpos); + inline int FindMinimalMemoryConstrain(int tbp, int maxpos); + inline int FindZbufferMemoryConstrain(int tbp, int maxpos); + inline int FindMinimalHeightConstrain(int maxpos); + + inline int CheckFrameResolveRender(int tbp); + inline void CheckFrame16vs32Conversion(); + inline int CheckFrameResolveDepth(int tbp); + + inline void FlushTexUnchangedClutDontUpdate() ; + inline void FlushTexClutDontUpdate() ; + inline void FlushTexClutting() ; + inline void FlushTexSetNewVars(u32 psm) ; + + // notify VB that nVerts need to be written to pbuf + inline void NotifyWrite(int nVerts) + { + assert(pBufferData != NULL && nCount <= nNumVertices && nVerts > 0); + + if (nCount + nVerts > nNumVertices) + { + // recreate except with a bigger count + VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nNumVertices * 2, 256); + memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount); + nNumVertices *= 2; + assert(nCount + nVerts <= nNumVertices); + _aligned_free(pBufferData); + pBufferData = ptemp; + } + } + + void Init(int nVerts) + { + if (pBufferData == NULL && nVerts > 0) + { + pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nVerts, 256); + nNumVertices = nVerts; + } + + nCount = 0; + } + + u8 bNeedFrameCheck; + u8 bNeedZCheck; + u8 bNeedTexCheck; + u8 dummy0; + + union + { + struct + { + u8 bTexConstsSync; // only pixel shader constants that context owns + u8 bVarsTexSync; // texture info + u8 bVarsSetTarg; + u8 dummy1; + }; + + u32 bSyncVars; + }; + + int ictx; + VertexGPU* pBufferData; // current allocated data + + int nNumVertices; // size of pBufferData in terms of VertexGPU objects + int nCount; + primInfo curprim; // the previous prim the current buffers are set to + + zbufInfo zbuf; + frameInfo gsfb; // the real info set by FRAME cmd + frameInfo frame; + int zprimmask; // zmask for incoming points + +union +{ + u32 uCurTex0Data[2]; // current tex0 data + GIFRegTEX0 uCurTex0; +}; + u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1 + + //int nFrameHeights[8]; // frame heights for the past frame changes + int nNextFrameHeight; + + CMemoryTarget* pmemtarg; // the current mem target set + CRenderTarget* prndr; + CDepthTarget* pdepth; + +}; + inline u32 GetFrameKey(int fbp, int fbw, VB& curvb); // manages render targets - class CRenderTargetMngr { public: @@ -384,4 +692,6 @@ static __forceinline void setRectWrap2(GLint type) glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, type); } +// VB variables +extern VB vb[2]; #endif diff --git a/plugins/zzogl-pg/opengl/zerogs.h b/plugins/zzogl-pg/opengl/zerogs.h index 5a662f4db5..dfc8070e67 100644 --- a/plugins/zzogl-pg/opengl/zerogs.h +++ b/plugins/zzogl-pg/opengl/zerogs.h @@ -35,11 +35,11 @@ #include "GS.h" #include "CRC.h" #include "rasterfont.h" // simple font +#include "targets.h" using namespace std; //------------------------ Constants ---------------------- -#define VB_BUFFERSIZE 0x400 // Used in a logarithmic Z-test, as (1-o(1))/log(MAX_U32). const float g_filog32 = 0.999f / (32.0f * logf(2.0f)); @@ -98,319 +98,9 @@ extern int nBackbufferWidth, nBackbufferHeight; typedef void (*DrawFn)(); -// managers render-to-texture targets - -class CRenderTarget -{ - - public: - CRenderTarget(); - virtual ~CRenderTarget(); - - virtual bool Create(const frameInfo& frame); - virtual void Destroy(); - - // set the GPU_POSXY variable, scissor rect, and current render target - void SetTarget(int fbplocal, const Rect2& scissor, int context); - void SetViewport(); - - // copies/creates the feedback contents - inline void CreateFeedback() - { - if (ptexFeedback == 0 || !(status&TS_FeedbackReady)) - _CreateFeedback(); - } - - virtual void Resolve(); - virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range - virtual void Update(int context, CRenderTarget* pdepth); - virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0 - virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2 - - virtual bool IsDepth() { return false; } - - void SetRenderTarget(int targ); - - void* psys; // system data used for comparison - u32 ptex; - - int fbp, fbw, fbh, fbhCalc; // if fbp is negative, virtual target (not mapped to any real addr) - int start, end; // in bytes - u32 lastused; // time stamp since last used - float4 vposxy; - - u32 fbm; - u16 status; - u8 psm; - u8 resv0; - Rect scissorrect; - - u8 created; // Check for object destruction/creating for r201. - - //int startresolve, endresolve; - u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only) - - // this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself) - u32 ptexFeedback; - - enum TargetStatus - { - TS_Resolved = 1, - TS_NeedUpdate = 2, - TS_Virtual = 4, // currently not mapped to memory - TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated - TS_NeedConvert32 = 16, - TS_NeedConvert16 = 32, - }; - inline float4 DefaultBitBltPos(); - inline float4 DefaultBitBltTex(); - - private: - void _CreateFeedback(); - inline bool InitialiseDefaultTexture(u32 *p_ptr, int fbw, int fbh) ; -}; - -// manages zbuffers - -class CDepthTarget : public CRenderTarget -{ - - public: - CDepthTarget(); - virtual ~CDepthTarget(); - - virtual bool Create(const frameInfo& frame); - virtual void Destroy(); - - virtual void Resolve(); - virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range - virtual void Update(int context, CRenderTarget* prndr); - - virtual bool IsDepth() { return true; } - - void SetDepthStencilSurface(); - - u32 pdepth; // 24 bit, will contain the stencil buffer if possible - u32 pstencil; // if not 0, contains the stencil buffer - int icount; // internal counter -}; - -// manages contiguous chunks of memory (width is always 1024) - -class CMemoryTarget -{ - public: - struct TEXTURE - { - inline TEXTURE() : tex(0), memptr(NULL), ref(0) {} - inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); } - - u32 tex; - u8* memptr; // GPU memory used for comparison - int ref; - }; - - inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0) {} - - inline CMemoryTarget(const CMemoryTarget& r) - { - ptex = r.ptex; - - if (ptex != NULL) ptex->ref++; - - starty = r.starty; - height = r.height; - realy = r.realy; - realheight = r.realheight; - usedstamp = r.usedstamp; - psm = r.psm; - cpsm = r.cpsm; - clut = r.clut; - clearminy = r.clearminy; - clearmaxy = r.clearmaxy; - widthmult = r.widthmult; - texH = r.texH; - texW = r.texW; - channels = r.channels; - validatecount = r.validatecount; - fmt = r.fmt; - } - - ~CMemoryTarget() { Destroy(); } - - inline void Destroy() - { - if (ptex != NULL && ptex->ref > 0) - { - if (--ptex->ref <= 0) delete ptex; - } - - ptex = NULL; - } - - // returns true if clut data is synced - bool ValidateClut(const tex0Info& tex0); - // returns true if tex data is synced - bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex); - - // realy is offset in pixels from start of valid region - // so texture in memory is [realy,starty+height] - // valid texture is [starty,starty+height] - // offset in mem [starty-realy, height] - TEXTURE* ptex; // can be 16bit - - int starty, height; // assert(starty >= realy) - int realy, realheight; // this is never touched once allocated - // realy is start pointer of data in 4M data block (start) and size (end-start). - - u32 usedstamp; - u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters - - u32 fmt; - - int widthmult; // Either 1 or 2. - int channels; // The number of pixels per PSM format word. channels == PIXELS_PER_WORD(psm) - // This is the real drawing size in pixels of the texture in renderbuffer. - int texW; // (realheight + widthmult - 1)/widthmult == realheight or [(realheight+1)/2] - int texH; // GPU_TEXWIDTH *widthmult * channels; - - int clearminy, clearmaxy; // when maxy > 0, need to check for clearing - - int validatecount; // count how many times has been validated, if too many, destroy - - vector clut; // if nonzero, texture uses CLUT -}; - - -struct VB -{ - VB(); - ~VB(); - - void Destroy(); - - inline bool CheckPrim() - { - static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA) - - if ((PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim]) - return nCount > 0; - - return false; - } - - void CheckFrame(int tbp); - - // context specific state - Point offset; - Rect2 scissor; - tex0Info tex0; - tex1Info tex1; - miptbpInfo miptbp0; - miptbpInfo miptbp1; - alphaInfo alpha; - fbaInfo fba; - clampInfo clamp; - pixTest test; - u32 ptexClamp[2]; // textures for x and y dir region clamping - -public: - void FlushTexData(); - inline int CheckFrameAddConstraints(int tbp); - inline void CheckScissors(int maxpos); - inline void CheckFrame32bitRes(int maxpos); - inline int FindMinimalMemoryConstrain(int tbp, int maxpos); - inline int FindZbufferMemoryConstrain(int tbp, int maxpos); - inline int FindMinimalHeightConstrain(int maxpos); - - inline int CheckFrameResolveRender(int tbp); - inline void CheckFrame16vs32Conversion(); - inline int CheckFrameResolveDepth(int tbp); - - inline void FlushTexUnchangedClutDontUpdate() ; - inline void FlushTexClutDontUpdate() ; - inline void FlushTexClutting() ; - inline void FlushTexSetNewVars(u32 psm) ; - - // notify VB that nVerts need to be written to pbuf - inline void NotifyWrite(int nVerts) - { - assert(pBufferData != NULL && nCount <= nNumVertices && nVerts > 0); - - if (nCount + nVerts > nNumVertices) - { - // recreate except with a bigger count - VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nNumVertices * 2, 256); - memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount); - nNumVertices *= 2; - assert(nCount + nVerts <= nNumVertices); - _aligned_free(pBufferData); - pBufferData = ptemp; - } - } - - void Init(int nVerts) - { - if (pBufferData == NULL && nVerts > 0) - { - pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU) * nVerts, 256); - nNumVertices = nVerts; - } - - nCount = 0; - } - - u8 bNeedFrameCheck; - u8 bNeedZCheck; - u8 bNeedTexCheck; - u8 dummy0; - - union - { - struct - { - u8 bTexConstsSync; // only pixel shader constants that context owns - u8 bVarsTexSync; // texture info - u8 bVarsSetTarg; - u8 dummy1; - }; - - u32 bSyncVars; - }; - - int ictx; - VertexGPU* pBufferData; // current allocated data - - int nNumVertices; // size of pBufferData in terms of VertexGPU objects - int nCount; - primInfo curprim; // the previous prim the current buffers are set to - - zbufInfo zbuf; - frameInfo gsfb; // the real info set by FRAME cmd - frameInfo frame; - int zprimmask; // zmask for incoming points - -union -{ - u32 uCurTex0Data[2]; // current tex0 data - GIFRegTEX0 uCurTex0; -}; - u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1 - - //int nFrameHeights[8]; // frame heights for the past frame changes - int nNextFrameHeight; - - CMemoryTarget* pmemtarg; // the current mem target set - CRenderTarget* prndr; - CDepthTarget* pdepth; - -}; - // visible members extern DrawFn drawfn[8]; -// VB variables -extern VB vb[2]; extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height extern vector g_vboBuffers; // VBOs for all drawing commands extern GLuint vboRect;