Merged some FramebufferManager code into VideoCommon.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6417 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
2378b443c1
commit
0da42fcca7
|
@ -4,6 +4,7 @@ set(SRCS Src/BPMemory.cpp
|
||||||
Src/CPMemory.cpp
|
Src/CPMemory.cpp
|
||||||
Src/DLCache.cpp
|
Src/DLCache.cpp
|
||||||
Src/Fifo.cpp
|
Src/Fifo.cpp
|
||||||
|
Src/FramebufferManagerBase.cpp
|
||||||
Src/HiresTextures.cpp
|
Src/HiresTextures.cpp
|
||||||
Src/ImageWrite.cpp
|
Src/ImageWrite.cpp
|
||||||
Src/IndexGenerator.cpp
|
Src/IndexGenerator.cpp
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
|
||||||
|
#include "FramebufferManagerBase.h"
|
||||||
|
|
||||||
|
#include "Render.h"
|
||||||
|
#include "VideoConfig.h"
|
||||||
|
|
||||||
|
FramebufferManagerBase *g_framebuffer_manager;
|
||||||
|
|
||||||
|
XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode
|
||||||
|
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
|
||||||
|
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||||
|
|
||||||
|
FramebufferManagerBase::FramebufferManagerBase()
|
||||||
|
{
|
||||||
|
m_realXFBSource = NULL;
|
||||||
|
|
||||||
|
// can't hurt
|
||||||
|
memset(m_overlappingXFBArray, 0, sizeof(m_overlappingXFBArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferManagerBase::~FramebufferManagerBase()
|
||||||
|
{
|
||||||
|
VirtualXFBListType::iterator
|
||||||
|
it = m_virtualXFBList.begin(),
|
||||||
|
vlend = m_virtualXFBList.end();
|
||||||
|
for (; it != vlend; ++it)
|
||||||
|
delete it->xfbSource;
|
||||||
|
|
||||||
|
m_virtualXFBList.clear();
|
||||||
|
|
||||||
|
delete m_realXFBSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||||
|
{
|
||||||
|
if (g_ActiveConfig.bUseRealXFB)
|
||||||
|
return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
|
else
|
||||||
|
return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||||
|
{
|
||||||
|
xfbCount = 1;
|
||||||
|
|
||||||
|
if (!m_realXFBSource)
|
||||||
|
m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight);
|
||||||
|
|
||||||
|
m_realXFBSource->srcAddr = xfbAddr;
|
||||||
|
|
||||||
|
m_realXFBSource->srcWidth = MAX_XFB_WIDTH;
|
||||||
|
m_realXFBSource->srcHeight = MAX_XFB_HEIGHT;
|
||||||
|
|
||||||
|
m_realXFBSource->texWidth = fbWidth;
|
||||||
|
m_realXFBSource->texHeight = fbHeight;
|
||||||
|
|
||||||
|
// TODO: stuff only used by OGL... :/
|
||||||
|
// OpenGL texture coordinates originate at the lower left, which is why
|
||||||
|
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
||||||
|
m_realXFBSource->sourceRc.left = 0;
|
||||||
|
m_realXFBSource->sourceRc.top = fbHeight;
|
||||||
|
m_realXFBSource->sourceRc.right = fbWidth;
|
||||||
|
m_realXFBSource->sourceRc.bottom = 0;
|
||||||
|
|
||||||
|
// Decode YUYV data from GameCube RAM
|
||||||
|
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
|
||||||
|
|
||||||
|
m_overlappingXFBArray[0] = m_realXFBSource;
|
||||||
|
return &m_overlappingXFBArray[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||||
|
{
|
||||||
|
xfbCount = 0;
|
||||||
|
|
||||||
|
if (m_virtualXFBList.empty()) // no Virtual XFBs available
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
u32 srcLower = xfbAddr;
|
||||||
|
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
||||||
|
|
||||||
|
VirtualXFBListType::reverse_iterator
|
||||||
|
it = m_virtualXFBList.rbegin(),
|
||||||
|
vlend = m_virtualXFBList.rend();
|
||||||
|
for (; it != vlend; ++it)
|
||||||
|
{
|
||||||
|
VirtualXFB* vxfb = &*it;
|
||||||
|
|
||||||
|
u32 dstLower = vxfb->xfbAddr;
|
||||||
|
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||||
|
|
||||||
|
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||||
|
{
|
||||||
|
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
|
||||||
|
++xfbCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_overlappingXFBArray[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
|
{
|
||||||
|
if (g_ActiveConfig.bUseRealXFB)
|
||||||
|
g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
|
else
|
||||||
|
CopyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
|
{
|
||||||
|
VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
||||||
|
|
||||||
|
if (m_virtualXFBList.end() == vxfb)
|
||||||
|
{
|
||||||
|
if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB)
|
||||||
|
{
|
||||||
|
// create a new Virtual XFB and place it at the front of the list
|
||||||
|
VirtualXFB v;
|
||||||
|
m_virtualXFBList.push_front(v);
|
||||||
|
vxfb = m_virtualXFBList.begin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Replace the last virtual XFB
|
||||||
|
--vxfb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//else // replace existing virtual XFB
|
||||||
|
|
||||||
|
// move this Virtual XFB to the front of the list.
|
||||||
|
if (m_virtualXFBList.begin() != vxfb)
|
||||||
|
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb);
|
||||||
|
|
||||||
|
unsigned int target_width, target_height;
|
||||||
|
g_framebuffer_manager->GetTargetSize(&target_width, &target_height, sourceRc);
|
||||||
|
|
||||||
|
// recreate if needed
|
||||||
|
if (vxfb->xfbSource && (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height))
|
||||||
|
{
|
||||||
|
//delete vxfb->xfbSource;
|
||||||
|
//vxfb->xfbSource = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vxfb->xfbSource)
|
||||||
|
{
|
||||||
|
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
|
||||||
|
vxfb->xfbSource->texWidth = target_width;
|
||||||
|
vxfb->xfbSource->texHeight = target_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr;
|
||||||
|
vxfb->xfbSource->srcWidth = vxfb->xfbWidth = fbWidth;
|
||||||
|
vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
|
||||||
|
|
||||||
|
vxfb->xfbSource->sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||||
|
|
||||||
|
// keep stale XFB data from being used
|
||||||
|
ReplaceVirtualXFB();
|
||||||
|
|
||||||
|
Renderer::ResetAPIState(); // reset any game specific settings
|
||||||
|
|
||||||
|
// Copy EFB data to XFB and restore render target again
|
||||||
|
vxfb->xfbSource->CopyEFB();
|
||||||
|
|
||||||
|
Renderer::RestoreAPIState();
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||||
|
{
|
||||||
|
const u32 srcLower = xfbAddr;
|
||||||
|
const u32 srcUpper = xfbAddr + 2 * width * height;
|
||||||
|
|
||||||
|
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
||||||
|
for (; it != m_virtualXFBList.end(); ++it)
|
||||||
|
{
|
||||||
|
const u32 dstLower = it->xfbAddr;
|
||||||
|
const u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
|
|
||||||
|
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferManagerBase::ReplaceVirtualXFB()
|
||||||
|
{
|
||||||
|
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
||||||
|
|
||||||
|
const s32 srcLower = it->xfbAddr;
|
||||||
|
const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
|
const s32 lineSize = 2 * it->xfbWidth;
|
||||||
|
|
||||||
|
++it;
|
||||||
|
|
||||||
|
for (; it != m_virtualXFBList.end(); ++it)
|
||||||
|
{
|
||||||
|
s32 dstLower = it->xfbAddr;
|
||||||
|
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
|
|
||||||
|
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||||
|
{
|
||||||
|
// Invalidate the data
|
||||||
|
it->xfbAddr = 0;
|
||||||
|
it->xfbHeight = 0;
|
||||||
|
it->xfbWidth = 0;
|
||||||
|
}
|
||||||
|
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||||
|
{
|
||||||
|
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
||||||
|
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
||||||
|
|
||||||
|
if (upperOverlap > 0 && lowerOverlap < 0)
|
||||||
|
{
|
||||||
|
it->xfbAddr += lineSize * upperOverlap;
|
||||||
|
it->xfbHeight -= upperOverlap;
|
||||||
|
}
|
||||||
|
else if (lowerOverlap > 0)
|
||||||
|
{
|
||||||
|
it->xfbHeight -= lowerOverlap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
|
||||||
|
#ifndef _FRAMEBUFFERMANAGER_H
|
||||||
|
#define _FRAMEBUFFERMANAGER_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "VideoCommon.h"
|
||||||
|
|
||||||
|
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||||
|
{
|
||||||
|
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct XFBSourceBase
|
||||||
|
{
|
||||||
|
virtual ~XFBSourceBase() {}
|
||||||
|
|
||||||
|
// TODO: only DX9 uses the width/height params
|
||||||
|
virtual void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const = 0;
|
||||||
|
|
||||||
|
virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0;
|
||||||
|
|
||||||
|
virtual void CopyEFB() = 0;
|
||||||
|
|
||||||
|
u32 srcAddr;
|
||||||
|
u32 srcWidth;
|
||||||
|
u32 srcHeight;
|
||||||
|
|
||||||
|
int texWidth;
|
||||||
|
int texHeight;
|
||||||
|
|
||||||
|
// TODO: only used by OGL
|
||||||
|
TargetRectangle sourceRc;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FramebufferManagerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||||
|
// virtualize.
|
||||||
|
MAX_VIRTUAL_XFB = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
FramebufferManagerBase();
|
||||||
|
virtual ~FramebufferManagerBase();
|
||||||
|
|
||||||
|
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||||
|
static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct VirtualXFB
|
||||||
|
{
|
||||||
|
VirtualXFB() : xfbSource(NULL) {}
|
||||||
|
|
||||||
|
// Address and size in GameCube RAM
|
||||||
|
u32 xfbAddr;
|
||||||
|
u32 xfbWidth;
|
||||||
|
u32 xfbHeight;
|
||||||
|
|
||||||
|
XFBSourceBase *xfbSource;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::list<VirtualXFB> VirtualXFBListType;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
|
||||||
|
// TODO: figure out why OGL is different for this guy
|
||||||
|
virtual void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) = 0;
|
||||||
|
|
||||||
|
static VirtualXFBListType::iterator FindVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
||||||
|
|
||||||
|
static void ReplaceVirtualXFB();
|
||||||
|
|
||||||
|
// TODO: merge these virtual funcs, they are nearly all the same
|
||||||
|
virtual void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) = 0;
|
||||||
|
static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||||
|
|
||||||
|
static const XFBSourceBase* const* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||||
|
static const XFBSourceBase* const* GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||||
|
|
||||||
|
static XFBSourceBase *m_realXFBSource; // Only used in Real XFB mode
|
||||||
|
static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
||||||
|
|
||||||
|
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FramebufferManagerBase *g_framebuffer_manager;
|
||||||
|
|
||||||
|
#endif
|
|
@ -29,6 +29,7 @@ files = [
|
||||||
'VertexLoader_TextCoord.cpp',
|
'VertexLoader_TextCoord.cpp',
|
||||||
'TextureConversionShader.cpp',
|
'TextureConversionShader.cpp',
|
||||||
'ImageWrite.cpp',
|
'ImageWrite.cpp',
|
||||||
|
'FramebufferManagerBase.cpp',
|
||||||
'VertexManagerBase.cpp',
|
'VertexManagerBase.cpp',
|
||||||
'TextureCacheBase.cpp',
|
'TextureCacheBase.cpp',
|
||||||
'Statistics.cpp',
|
'Statistics.cpp',
|
||||||
|
|
|
@ -730,6 +730,14 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="Base"
|
Name="Base"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\FramebufferManagerBase.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\FramebufferManagerBase.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Src\TextureCacheBase.cpp"
|
RelativePath=".\Src\TextureCacheBase.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "PixelShaderCache.h"
|
#include "PixelShaderCache.h"
|
||||||
#include "VertexShaderCache.h"
|
#include "VertexShaderCache.h"
|
||||||
|
|
||||||
FramebufferManager g_framebufferManager;
|
FramebufferManager::Efb FramebufferManager::m_efb;
|
||||||
|
|
||||||
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; }
|
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; }
|
||||||
ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
|
ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
|
||||||
|
@ -33,10 +33,17 @@ D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex
|
||||||
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
|
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
|
||||||
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
|
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
|
||||||
|
|
||||||
void FramebufferManager::Create()
|
FramebufferManager::FramebufferManager()
|
||||||
{
|
{
|
||||||
|
m_efb.color_tex = NULL;
|
||||||
|
m_efb.color_staging_buf = NULL;
|
||||||
|
m_efb.depth_tex = NULL;
|
||||||
|
m_efb.depth_staging_buf = NULL;
|
||||||
|
m_efb.depth_read_texture = NULL;
|
||||||
|
|
||||||
unsigned int target_width = Renderer::GetFullTargetWidth();
|
unsigned int target_width = Renderer::GetFullTargetWidth();
|
||||||
unsigned int target_height = Renderer::GetFullTargetHeight();
|
unsigned int target_height = Renderer::GetFullTargetHeight();
|
||||||
|
|
||||||
ID3D11Texture2D* buf;
|
ID3D11Texture2D* buf;
|
||||||
D3D11_TEXTURE2D_DESC texdesc;
|
D3D11_TEXTURE2D_DESC texdesc;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -80,228 +87,72 @@ void FramebufferManager::Create()
|
||||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
|
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::Destroy()
|
FramebufferManager::~FramebufferManager()
|
||||||
{
|
{
|
||||||
SAFE_RELEASE(m_efb.color_tex);
|
SAFE_RELEASE(m_efb.color_tex);
|
||||||
SAFE_RELEASE(m_efb.color_staging_buf);
|
SAFE_RELEASE(m_efb.color_staging_buf);
|
||||||
SAFE_RELEASE(m_efb.depth_tex);
|
SAFE_RELEASE(m_efb.depth_tex);
|
||||||
SAFE_RELEASE(m_efb.depth_staging_buf);
|
SAFE_RELEASE(m_efb.depth_staging_buf);
|
||||||
SAFE_RELEASE(m_efb.depth_read_texture);
|
SAFE_RELEASE(m_efb.depth_read_texture);
|
||||||
|
|
||||||
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
|
||||||
SAFE_RELEASE(it->xfbSource.tex);
|
|
||||||
|
|
||||||
m_virtualXFBList.clear();
|
|
||||||
SAFE_RELEASE(m_realXFBSource.tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
{
|
|
||||||
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
|
||||||
}
|
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
FramebufferManager::VirtualXFBListType::iterator FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
|
||||||
{
|
|
||||||
u32 srcLower = xfbAddr;
|
|
||||||
u32 srcUpper = xfbAddr + 2 * width * height;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator it;
|
|
||||||
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
|
||||||
{
|
|
||||||
u32 dstLower = it->xfbAddr;
|
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// That address is not in the Virtual XFB list.
|
|
||||||
return m_virtualXFBList.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::replaceVirtualXFB()
|
|
||||||
{
|
|
||||||
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
|
||||||
|
|
||||||
s32 srcLower = it->xfbAddr;
|
|
||||||
s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
s32 lineSize = 2 * it->xfbWidth;
|
|
||||||
|
|
||||||
++it;
|
|
||||||
|
|
||||||
while (it != m_virtualXFBList.end())
|
|
||||||
{
|
|
||||||
s32 dstLower = it->xfbAddr;
|
|
||||||
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
{
|
|
||||||
// Invalidate the data
|
|
||||||
it->xfbAddr = 0;
|
|
||||||
it->xfbHeight = 0;
|
|
||||||
it->xfbWidth = 0;
|
|
||||||
}
|
|
||||||
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
|
||||||
{
|
|
||||||
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
|
||||||
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
|
||||||
|
|
||||||
if (upperOverlap > 0 && lowerOverlap < 0)
|
|
||||||
{
|
|
||||||
it->xfbAddr += lineSize * upperOverlap;
|
|
||||||
it->xfbHeight -= upperOverlap;
|
|
||||||
}
|
|
||||||
else if (lowerOverlap > 0)
|
|
||||||
{
|
|
||||||
it->xfbHeight -= lowerOverlap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
PanicAlert("copyToRealXFB not implemented, yet\n");
|
PanicAlert("CopyToRealXFB not implemented, yet\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||||
{
|
{
|
||||||
D3DTexture2D* xfbTex;
|
return new XFBSource(D3DTexture2D::Create(target_width, target_height,
|
||||||
HRESULT hr = 0;
|
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE),
|
||||||
|
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM));
|
||||||
|
}
|
||||||
|
|
||||||
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
|
||||||
|
{
|
||||||
|
const float scaleX = Renderer::GetXFBScaleX();
|
||||||
|
const float scaleY = Renderer::GetXFBScaleY();
|
||||||
|
|
||||||
if (it == m_virtualXFBList.end() && (int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
TargetRectangle targetSource;
|
||||||
{
|
|
||||||
// Replace the last virtual XFB (might cause glitches, but better than allocating 50 XFBs...)
|
|
||||||
// TODO: Reencode last virtual XFB to RAM to avoid glitches?
|
|
||||||
--it;
|
|
||||||
}
|
|
||||||
|
|
||||||
float scaleX = Renderer::GetXFBScaleX();
|
targetSource.top = (int)(sourceRc.top *scaleY);
|
||||||
float scaleY = Renderer::GetXFBScaleY();
|
targetSource.bottom = (int)(sourceRc.bottom *scaleY);
|
||||||
TargetRectangle targetSource,efbSource;
|
targetSource.left = (int)(sourceRc.left *scaleX);
|
||||||
efbSource = Renderer::ConvertEFBRectangle(sourceRc);
|
|
||||||
targetSource.top = (int)(sourceRc.top * scaleY);
|
|
||||||
targetSource.bottom = (int)(sourceRc.bottom * scaleY);
|
|
||||||
targetSource.left = (int)(sourceRc.left * scaleX);
|
|
||||||
targetSource.right = (int)(sourceRc.right * scaleX);
|
targetSource.right = (int)(sourceRc.right * scaleX);
|
||||||
unsigned int target_width = targetSource.right - targetSource.left;
|
|
||||||
unsigned int target_height = targetSource.bottom - targetSource.top;
|
|
||||||
if (it != m_virtualXFBList.end())
|
|
||||||
{
|
|
||||||
// Overwrite an existing Virtual XFB.
|
|
||||||
|
|
||||||
it->xfbAddr = xfbAddr;
|
*width = targetSource.right - targetSource.left;
|
||||||
it->xfbWidth = fbWidth;
|
*height = targetSource.bottom - targetSource.top;
|
||||||
it->xfbHeight = fbHeight;
|
}
|
||||||
|
|
||||||
it->xfbSource.srcAddr = xfbAddr;
|
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
it->xfbSource.srcWidth = fbWidth;
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
|
||||||
it->xfbSource.srcHeight = fbHeight;
|
{
|
||||||
|
D3D::drawShadedTexSubQuad(tex->GetSRV(), &sourcerc,
|
||||||
|
texWidth, texHeight, &drawrc, PixelShaderCache::GetColorCopyProgram(),
|
||||||
|
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
||||||
|
}
|
||||||
|
|
||||||
if (it->xfbSource.texWidth != target_width || it->xfbSource.texHeight != target_height || !(it->xfbSource.tex))
|
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||||
{
|
{
|
||||||
SAFE_RELEASE(it->xfbSource.tex);
|
// TODO:
|
||||||
it->xfbSource.tex = D3DTexture2D::Create(target_width, target_height, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
|
PanicAlert("RealXFB not implemented, yet\n");
|
||||||
if (it->xfbSource.tex == NULL) PanicAlert("Failed to create XFB texture\n");
|
}
|
||||||
}
|
|
||||||
xfbTex = it->xfbSource.tex;
|
|
||||||
|
|
||||||
it->xfbSource.texWidth = target_width;
|
|
||||||
it->xfbSource.texHeight = target_height;
|
|
||||||
|
|
||||||
// move this Virtual XFB to the front of the list.
|
|
||||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
|
||||||
|
|
||||||
// keep stale XFB data from being used
|
|
||||||
replaceVirtualXFB();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Create a new Virtual XFB and place it at the front of the list.
|
|
||||||
VirtualXFB newVirt;
|
|
||||||
|
|
||||||
newVirt.xfbSource.tex = D3DTexture2D::Create(target_width, target_height, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM);
|
|
||||||
if (newVirt.xfbSource.tex == NULL) PanicAlert("Failed to create a new virtual XFB");
|
|
||||||
|
|
||||||
newVirt.xfbAddr = xfbAddr;
|
|
||||||
newVirt.xfbWidth = fbWidth;
|
|
||||||
newVirt.xfbHeight = fbHeight;
|
|
||||||
|
|
||||||
xfbTex = newVirt.xfbSource.tex;
|
|
||||||
newVirt.xfbSource.texWidth = target_width;
|
|
||||||
newVirt.xfbSource.texHeight = target_height;
|
|
||||||
|
|
||||||
// Add the new Virtual XFB to the list
|
|
||||||
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
|
||||||
{
|
|
||||||
// List overflowed; delete the oldest.
|
|
||||||
m_virtualXFBList.back().xfbSource.tex->Release();
|
|
||||||
m_virtualXFBList.pop_back();
|
|
||||||
WARN_LOG(VIDEO, "Virtual XFB list overflown, releasing oldest virtual XFB");
|
|
||||||
}
|
|
||||||
m_virtualXFBList.push_front(newVirt);
|
|
||||||
}
|
|
||||||
if (!xfbTex->GetRTV()) return;
|
|
||||||
|
|
||||||
Renderer::ResetAPIState(); // reset any game specific settings
|
|
||||||
|
|
||||||
|
void XFBSource::CopyEFB()
|
||||||
|
{
|
||||||
// Copy EFB data to XFB and restore render target again
|
// Copy EFB data to XFB and restore render target again
|
||||||
D3D11_RECT sourcerect = CD3D11_RECT(efbSource.left, efbSource.top, efbSource.right, efbSource.bottom);
|
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
|
||||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)target_width, (float)target_height);
|
|
||||||
D3D::context->RSSetViewports(1, &vp);
|
D3D::context->RSSetViewports(1, &vp);
|
||||||
D3D::context->OMSetRenderTargets(1, &xfbTex->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL);
|
||||||
D3D::SetLinearCopySampler();
|
D3D::SetLinearCopySampler();
|
||||||
D3D::drawShadedTexQuad(GetEFBColorTexture()->GetSRV(), &sourcerect,
|
|
||||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(),
|
||||||
PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(),
|
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
||||||
VertexShaderCache::GetSimpleInputLayout());
|
PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(),
|
||||||
D3D::context->OMSetRenderTargets(1, &GetEFBColorTexture()->GetRTV(), GetEFBDepthTexture()->GetDSV());
|
VertexShaderCache::GetSimpleInputLayout());
|
||||||
Renderer::RestoreAPIState();
|
|
||||||
}
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
|
||||||
|
FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
PanicAlert("getRealXFBSource not implemented, yet\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
xfbCount = 0;
|
|
||||||
|
|
||||||
if (m_virtualXFBList.size() == 0)
|
|
||||||
{
|
|
||||||
// No Virtual XFBs available.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 srcLower = xfbAddr;
|
|
||||||
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator it;
|
|
||||||
for (it = m_virtualXFBList.end(); it != m_virtualXFBList.begin();)
|
|
||||||
{
|
|
||||||
--it;
|
|
||||||
|
|
||||||
u32 dstLower = it->xfbAddr;
|
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
|
||||||
{
|
|
||||||
m_overlappingXFBArray[xfbCount] = &(it->xfbSource);
|
|
||||||
xfbCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m_overlappingXFBArray[0];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
#ifndef _FBMANAGER_D3D_H_
|
#ifndef _FBMANAGER_D3D_H_
|
||||||
#define _FBMANAGER_D3D_H_
|
#define _FBMANAGER_D3D_H_
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
|
#include "D3DTexture.h"
|
||||||
|
#include "FramebufferManagerBase.h"
|
||||||
|
|
||||||
// On the GameCube, the game sends a request for the graphics processor to
|
// On the GameCube, the game sends a request for the graphics processor to
|
||||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||||
|
@ -52,82 +53,40 @@
|
||||||
|
|
||||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||||
// virtualize.
|
// virtualize.
|
||||||
const int MAX_VIRTUAL_XFB = 8;
|
|
||||||
|
|
||||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
struct XFBSource : public XFBSourceBase
|
||||||
{
|
{
|
||||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
XFBSource(D3DTexture2D *_tex) : tex(_tex) {}
|
||||||
}
|
~XFBSource() { tex->Release(); }
|
||||||
|
|
||||||
struct XFBSource
|
void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
{
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
|
||||||
XFBSource() : srcAddr(0), srcWidth(0), srcHeight(0), tex(NULL), texWidth(0), texHeight(0) {}
|
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||||
|
void CopyEFB();
|
||||||
|
|
||||||
u32 srcAddr;
|
D3DTexture2D* const tex;
|
||||||
u32 srcWidth;
|
|
||||||
u32 srcHeight;
|
|
||||||
|
|
||||||
D3DTexture2D* tex;
|
|
||||||
unsigned int texWidth;
|
|
||||||
unsigned int texHeight;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FramebufferManager
|
class FramebufferManager : public FramebufferManagerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FramebufferManager()
|
FramebufferManager();
|
||||||
{
|
~FramebufferManager();
|
||||||
m_efb.color_tex = NULL;
|
|
||||||
m_efb.color_staging_buf = NULL;
|
|
||||||
m_efb.depth_tex = NULL;
|
|
||||||
m_efb.depth_staging_buf = NULL;
|
|
||||||
m_efb.depth_read_texture = NULL;
|
|
||||||
|
|
||||||
m_realXFBSource.tex = NULL;
|
static D3DTexture2D* &GetEFBColorTexture();
|
||||||
}
|
static ID3D11Texture2D* &GetEFBColorStagingBuffer();
|
||||||
|
|
||||||
void Create();
|
static D3DTexture2D* &GetEFBDepthTexture();
|
||||||
void Destroy();
|
static D3DTexture2D* &GetEFBDepthReadTexture();
|
||||||
|
static ID3D11Texture2D* &GetEFBDepthStagingBuffer();
|
||||||
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
const XFBSource** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
|
|
||||||
D3DTexture2D* &GetEFBColorTexture();
|
|
||||||
ID3D11Texture2D* &GetEFBColorStagingBuffer();
|
|
||||||
|
|
||||||
D3DTexture2D* &GetEFBDepthTexture();
|
|
||||||
D3DTexture2D* &GetEFBDepthReadTexture();
|
|
||||||
ID3D11Texture2D* &GetEFBDepthStagingBuffer();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||||
|
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
|
||||||
|
|
||||||
struct VirtualXFB
|
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||||
{
|
|
||||||
// Address and size in GameCube RAM
|
|
||||||
u32 xfbAddr;
|
|
||||||
u32 xfbWidth;
|
|
||||||
u32 xfbHeight;
|
|
||||||
|
|
||||||
XFBSource xfbSource;
|
static struct Efb
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
|
||||||
|
|
||||||
void replaceVirtualXFB();
|
|
||||||
|
|
||||||
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
const XFBSource** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
|
|
||||||
XFBSource m_realXFBSource; // Only used in Real XFB mode
|
|
||||||
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
|
||||||
|
|
||||||
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
{
|
||||||
D3DTexture2D* color_tex;
|
D3DTexture2D* color_tex;
|
||||||
ID3D11Texture2D* color_staging_buf;
|
ID3D11Texture2D* color_staging_buf;
|
||||||
|
@ -138,6 +97,4 @@ private:
|
||||||
} m_efb;
|
} m_efb;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FramebufferManager g_framebufferManager;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -237,7 +237,7 @@ static const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
||||||
|
|
||||||
void SetupDeviceObjects()
|
void SetupDeviceObjects()
|
||||||
{
|
{
|
||||||
g_framebufferManager.Create();
|
g_framebuffer_manager = new FramebufferManager;
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
float colmat[20]= {0.0f};
|
float colmat[20]= {0.0f};
|
||||||
|
@ -319,7 +319,8 @@ void SetupDeviceObjects()
|
||||||
// Kill off all POOL_DEFAULT device objects.
|
// Kill off all POOL_DEFAULT device objects.
|
||||||
void TeardownDeviceObjects()
|
void TeardownDeviceObjects()
|
||||||
{
|
{
|
||||||
g_framebufferManager.Destroy();
|
delete g_framebuffer_manager;
|
||||||
|
|
||||||
SAFE_RELEASE(access_efb_cbuf);
|
SAFE_RELEASE(access_efb_cbuf);
|
||||||
SAFE_RELEASE(clearblendstates[0]);
|
SAFE_RELEASE(clearblendstates[0]);
|
||||||
SAFE_RELEASE(clearblendstates[1]);
|
SAFE_RELEASE(clearblendstates[1]);
|
||||||
|
@ -383,14 +384,14 @@ bool Renderer::Init()
|
||||||
D3D::gfxstate->samplerdesc[stage].MaxAnisotropy = g_ActiveConfig.iMaxAnisotropy;
|
D3D::gfxstate->samplerdesc[stage].MaxAnisotropy = g_ActiveConfig.iMaxAnisotropy;
|
||||||
|
|
||||||
float ClearColor[4] = { 0.f, 0.f, 0.f, 0.f };
|
float ClearColor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||||
D3D::context->ClearRenderTargetView(g_framebufferManager.GetEFBColorTexture()->GetRTV(), ClearColor);
|
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor);
|
||||||
D3D::context->ClearDepthStencilView(g_framebufferManager.GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
|
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
|
||||||
|
|
||||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)(s_Fulltarget_width - s_target_width) / 2.f,
|
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)(s_Fulltarget_width - s_target_width) / 2.f,
|
||||||
(float)(s_Fulltarget_height - s_target_height) / 2.f,
|
(float)(s_Fulltarget_height - s_target_height) / 2.f,
|
||||||
(float)s_target_width, (float)s_target_height);
|
(float)s_target_width, (float)s_target_height);
|
||||||
D3D::context->RSSetViewports(1, &vp);
|
D3D::context->RSSetViewports(1, &vp);
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), g_framebufferManager.GetEFBDepthTexture()->GetDSV());
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
D3D::BeginFrame();
|
D3D::BeginFrame();
|
||||||
D3D::gfxstate->rastdesc.ScissorEnable = TRUE;
|
D3D::gfxstate->rastdesc.ScissorEnable = TRUE;
|
||||||
|
|
||||||
|
@ -560,7 +561,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
|
||||||
// just use progressive.
|
// just use progressive.
|
||||||
if (g_ActiveConfig.bUseXFB)
|
if (g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
g_framebufferManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
FramebufferManager::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -700,9 +701,9 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, 1.f, 1.f);
|
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, 1.f, 1.f);
|
||||||
D3D::context->RSSetViewports(1, &vp);
|
D3D::context->RSSetViewports(1, &vp);
|
||||||
D3D::context->PSSetConstantBuffers(0, 1, &access_efb_cbuf);
|
D3D::context->PSSetConstantBuffers(0, 1, &access_efb_cbuf);
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBDepthReadTexture()->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), NULL);
|
||||||
D3D::SetPointCopySampler();
|
D3D::SetPointCopySampler();
|
||||||
D3D::drawShadedTexQuad(g_framebufferManager.GetEFBDepthTexture()->GetSRV(),
|
D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(),
|
||||||
&RectToLock,
|
&RectToLock,
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetFullTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetFullTargetHeight(),
|
||||||
|
@ -710,12 +711,12 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
VertexShaderCache::GetSimpleVertexShader(),
|
VertexShaderCache::GetSimpleVertexShader(),
|
||||||
VertexShaderCache::GetSimpleInputLayout());
|
VertexShaderCache::GetSimpleInputLayout());
|
||||||
|
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), g_framebufferManager.GetEFBDepthTexture()->GetDSV());
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
|
|
||||||
// copy to system memory
|
// copy to system memory
|
||||||
D3D11_BOX box = CD3D11_BOX(0, 0, 0, 1, 1, 1);
|
D3D11_BOX box = CD3D11_BOX(0, 0, 0, 1, 1, 1);
|
||||||
read_tex = g_framebufferManager.GetEFBDepthStagingBuffer();
|
read_tex = FramebufferManager::GetEFBDepthStagingBuffer();
|
||||||
D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, g_framebufferManager.GetEFBDepthReadTexture()->GetTex(), 0, &box);
|
D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBDepthReadTexture()->GetTex(), 0, &box);
|
||||||
|
|
||||||
RestoreAPIState(); // restore game state
|
RestoreAPIState(); // restore game state
|
||||||
|
|
||||||
|
@ -732,9 +733,9 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
else if (type == PEEK_COLOR)
|
else if (type == PEEK_COLOR)
|
||||||
{
|
{
|
||||||
// we can directly copy to system memory here
|
// we can directly copy to system memory here
|
||||||
read_tex = g_framebufferManager.GetEFBColorStagingBuffer();
|
read_tex = FramebufferManager::GetEFBColorStagingBuffer();
|
||||||
D3D11_BOX box = CD3D11_BOX(RectToLock.left, RectToLock.top, 0, RectToLock.right, RectToLock.bottom, 1);
|
D3D11_BOX box = CD3D11_BOX(RectToLock.left, RectToLock.top, 0, RectToLock.right, RectToLock.bottom, 1);
|
||||||
D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, g_framebufferManager.GetEFBColorTexture()->GetTex(), 0, &box);
|
D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBColorTexture()->GetTex(), 0, &box);
|
||||||
|
|
||||||
// read the data from system memory
|
// read the data from system memory
|
||||||
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
|
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
|
||||||
|
@ -755,7 +756,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
// TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet.
|
// TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet.
|
||||||
ResetAPIState();
|
ResetAPIState();
|
||||||
|
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), NULL);
|
||||||
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
||||||
- (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
|
- (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
|
||||||
(float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
(float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
||||||
|
@ -838,9 +839,11 @@ void UpdateViewport()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
|
||||||
g_framebufferManager.Destroy();
|
|
||||||
g_framebufferManager.Create();
|
delete g_framebuffer_manager;
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), g_framebufferManager.GetEFBDepthTexture()->GetDSV());
|
g_framebuffer_manager = new FramebufferManager;
|
||||||
|
|
||||||
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,7 +920,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
|
|
||||||
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
||||||
u32 xfbCount = 0;
|
u32 xfbCount = 0;
|
||||||
const XFBSource** xfbSourceList = g_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pCopiedToXFB(false);
|
g_VideoInitialize.pCopiedToXFB(false);
|
||||||
|
@ -956,7 +959,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
|
|
||||||
if(g_ActiveConfig.bUseXFB)
|
if(g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
const XFBSource* xfbSource;
|
const XFBSourceBase* xfbSource;
|
||||||
|
|
||||||
// draw each xfb source
|
// draw each xfb source
|
||||||
for (u32 i = 0; i < xfbCount; ++i)
|
for (u32 i = 0; i < xfbCount; ++i)
|
||||||
|
@ -1000,13 +1003,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
drawRc.right = 1;
|
drawRc.right = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D::drawShadedTexSubQuad(xfbSource->tex->GetSRV(), &sourceRc, xfbSource->texWidth, xfbSource->texHeight, &drawRc, PixelShaderCache::GetColorCopyProgram(),VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
xfbSource->Draw(sourceRc, drawRc, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc);
|
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc);
|
||||||
D3DTexture2D* read_texture = g_framebufferManager.GetEFBColorTexture();
|
D3DTexture2D* read_texture = FramebufferManager::GetEFBColorTexture();
|
||||||
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), PixelShaderCache::GetColorCopyProgram(),VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), PixelShaderCache::GetColorCopyProgram(),VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
||||||
}
|
}
|
||||||
// done with drawing the game stuff, good moment to save a screenshot
|
// done with drawing the game stuff, good moment to save a screenshot
|
||||||
|
@ -1140,14 +1143,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
s_target_height = (int)(EFB_HEIGHT * EFByScale);
|
s_target_height = (int)(EFB_HEIGHT * EFByScale);
|
||||||
|
|
||||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
|
||||||
g_framebufferManager.Destroy();
|
|
||||||
g_framebufferManager.Create();
|
delete g_framebuffer_manager;
|
||||||
|
g_framebuffer_manager = new FramebufferManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
// begin next frame
|
// begin next frame
|
||||||
Renderer::RestoreAPIState();
|
Renderer::RestoreAPIState();
|
||||||
D3D::BeginFrame();
|
D3D::BeginFrame();
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), g_framebufferManager.GetEFBDepthTexture()->GetDSV());
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
UpdateViewport();
|
UpdateViewport();
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
|
|
|
@ -147,12 +147,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
|
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
|
||||||
|
|
||||||
D3D::drawShadedTexQuad(
|
D3D::drawShadedTexQuad(
|
||||||
(bFromZBuffer) ? g_framebufferManager.GetEFBDepthTexture()->GetSRV() : g_framebufferManager.GetEFBColorTexture()->GetSRV(),
|
(bFromZBuffer) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
|
||||||
&sourcerect, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
&sourcerect, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
||||||
(bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(),
|
(bFromZBuffer) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram(),
|
||||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
||||||
|
|
||||||
D3D::context->OMSetRenderTargets(1, &g_framebufferManager.GetEFBColorTexture()->GetRTV(), g_framebufferManager.GetEFBDepthTexture()->GetDSV());
|
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
|
|
||||||
Renderer::RestoreAPIState();
|
Renderer::RestoreAPIState();
|
||||||
}
|
}
|
||||||
|
|
|
@ -501,15 +501,15 @@ static void DX9DebuggerUpdateScreen()
|
||||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(NULL);
|
D3D::dev->SetDepthStencilSurface(NULL);
|
||||||
|
|
||||||
D3D::dev->StretchRect(g_framebufferManager.GetEFBColorRTSurface(), NULL,
|
D3D::dev->StretchRect(FramebufferManager::GetEFBColorRTSurface(), NULL,
|
||||||
D3D::GetBackBufferSurface(), NULL,
|
D3D::GetBackBufferSurface(), NULL,
|
||||||
D3DTEXF_LINEAR);
|
D3DTEXF_LINEAR);
|
||||||
|
|
||||||
D3D::dev->EndScene();
|
D3D::dev->EndScene();
|
||||||
D3D::dev->Present(NULL, NULL, NULL, NULL);
|
D3D::dev->Present(NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
D3D::dev->BeginScene();
|
D3D::dev->BeginScene();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -23,117 +23,84 @@
|
||||||
#include "VertexShaderCache.h"
|
#include "VertexShaderCache.h"
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
|
|
||||||
|
// TODO: this is probably somewhere else
|
||||||
|
#define SAFE_RELEASE(p) if (p) { (p)->Release(); (p) = NULL; }
|
||||||
|
|
||||||
#undef CHECK
|
#undef CHECK
|
||||||
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
||||||
|
|
||||||
FramebufferManager g_framebufferManager;
|
FramebufferManager::Efb FramebufferManager::s_efb;
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
|
FramebufferManager::FramebufferManager()
|
||||||
{
|
{
|
||||||
return s_efb_color_surface;
|
s_efb.color_texture = NULL;
|
||||||
}
|
s_efb.colorRead_texture = NULL;
|
||||||
|
s_efb.depth_texture = NULL;
|
||||||
|
s_efb.depthRead_texture = NULL;
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
|
s_efb.depth_surface = NULL;
|
||||||
{
|
s_efb.color_surface = NULL;
|
||||||
return s_efb_depth_surface;
|
s_efb.color_ReadBuffer = NULL;
|
||||||
}
|
s_efb.depth_ReadBuffer = NULL;
|
||||||
|
s_efb.color_OffScreenReadBuffer = NULL;
|
||||||
|
s_efb.depth_OffScreenReadBuffer = NULL;
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
|
s_efb.color_surface_Format = D3DFMT_FORCE_DWORD;
|
||||||
{
|
s_efb.depth_surface_Format = D3DFMT_FORCE_DWORD;
|
||||||
return s_efb_color_OffScreenReadBuffer;
|
s_efb.depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
||||||
}
|
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
|
|
||||||
{
|
|
||||||
return s_efb_depth_OffScreenReadBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
|
|
||||||
{
|
|
||||||
return s_efb_color_ReadBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
|
|
||||||
{
|
|
||||||
return s_efb_depth_ReadBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat()
|
|
||||||
{
|
|
||||||
return s_efb_depth_surface_Format;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat()
|
|
||||||
{
|
|
||||||
return s_efb_depth_ReadBuffer_Format;
|
|
||||||
}
|
|
||||||
|
|
||||||
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat()
|
|
||||||
{
|
|
||||||
return s_efb_color_surface_Format;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture()
|
|
||||||
{
|
|
||||||
return s_efb_color_texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture()
|
|
||||||
{
|
|
||||||
return s_efb_depth_texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::Create()
|
|
||||||
{
|
|
||||||
// Simplest possible setup to start with.
|
// Simplest possible setup to start with.
|
||||||
int target_width = Renderer::GetFullTargetWidth();
|
int target_width = Renderer::GetFullTargetWidth();
|
||||||
int target_height = Renderer::GetFullTargetHeight();
|
int target_height = Renderer::GetFullTargetHeight();
|
||||||
|
|
||||||
s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
|
s_efb.color_surface_Format = D3DFMT_A8R8G8B8;
|
||||||
// Get the framebuffer texture
|
// Get the framebuffer texture
|
||||||
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||||
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
|
D3DPOOL_DEFAULT, &s_efb.color_texture, NULL);
|
||||||
if(s_efb_color_texture)
|
if (s_efb.color_texture)
|
||||||
{
|
{
|
||||||
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
|
hr = s_efb.color_texture->GetSurfaceLevel(0, &s_efb.color_surface);
|
||||||
}
|
}
|
||||||
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||||
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||||
D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL);
|
D3DPOOL_DEFAULT, &s_efb.colorRead_texture, NULL);
|
||||||
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
|
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
|
||||||
if(s_efb_colorRead_texture)
|
if (s_efb.colorRead_texture)
|
||||||
{
|
{
|
||||||
s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
|
s_efb.colorRead_texture->GetSurfaceLevel(0, &s_efb.color_ReadBuffer);
|
||||||
}
|
}
|
||||||
// Create an offscreen surface that we can lock to retrieve the data
|
// Create an offscreen surface that we can lock to retrieve the data
|
||||||
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL);
|
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb.color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb.color_OffScreenReadBuffer, NULL);
|
||||||
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
|
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
|
||||||
|
|
||||||
// Select a Z-buffer format with hardware support
|
// Select a Z-buffer format with hardware support
|
||||||
D3DFORMAT *DepthTexFormats = new D3DFORMAT[5];
|
D3DFORMAT DepthTexFormats[5] = {
|
||||||
DepthTexFormats[0] = FOURCC_INTZ;
|
FOURCC_INTZ,
|
||||||
DepthTexFormats[1] = FOURCC_DF24;
|
FOURCC_DF24,
|
||||||
DepthTexFormats[2] = FOURCC_RAWZ;
|
FOURCC_RAWZ,
|
||||||
DepthTexFormats[3] = FOURCC_DF16;
|
FOURCC_DF16,
|
||||||
DepthTexFormats[4] = D3DFMT_D24X8;
|
D3DFMT_D24X8
|
||||||
|
};
|
||||||
|
|
||||||
for(int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; ++i)
|
||||||
{
|
{
|
||||||
s_efb_depth_surface_Format = DepthTexFormats[i];
|
s_efb.depth_surface_Format = DepthTexFormats[i];
|
||||||
// Create the framebuffer depth texture
|
// Create the framebuffer depth texture
|
||||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
|
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb.depth_surface_Format,
|
||||||
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
|
D3DPOOL_DEFAULT, &s_efb.depth_texture, NULL);
|
||||||
if (!FAILED(hr))
|
if (!FAILED(hr))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||||
// Get the Surface
|
// Get the Surface
|
||||||
if(s_efb_depth_texture)
|
if (s_efb.depth_texture)
|
||||||
{
|
{
|
||||||
s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
|
s_efb.depth_texture->GetSurfaceLevel(0, &s_efb.depth_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a 4x4 pixel texture to work as a buffer for peeking
|
// Create a 4x4 pixel texture to work as a buffer for peeking
|
||||||
if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8)
|
if (s_efb.depth_surface_Format == FOURCC_RAWZ || s_efb.depth_surface_Format == D3DFMT_D24X8)
|
||||||
{
|
{
|
||||||
DepthTexFormats[0] = D3DFMT_A8R8G8B8;
|
DepthTexFormats[0] = D3DFMT_A8R8G8B8;
|
||||||
}
|
}
|
||||||
|
@ -141,161 +108,82 @@ void FramebufferManager::Create()
|
||||||
{
|
{
|
||||||
DepthTexFormats[0] = D3DFMT_R32F;
|
DepthTexFormats[0] = D3DFMT_R32F;
|
||||||
}
|
}
|
||||||
|
|
||||||
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
|
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
|
||||||
|
|
||||||
for(int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
s_efb_depth_ReadBuffer_Format = DepthTexFormats[i];
|
s_efb.depth_ReadBuffer_Format = DepthTexFormats[i];
|
||||||
// Get the framebuffer Depth texture
|
// Get the framebuffer Depth texture
|
||||||
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format,
|
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb.depth_ReadBuffer_Format,
|
||||||
D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL);
|
D3DPOOL_DEFAULT, &s_efb.depthRead_texture, NULL);
|
||||||
if (!FAILED(hr))
|
if (!FAILED(hr))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
|
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
|
||||||
if(s_efb_depthRead_texture)
|
if (s_efb.depthRead_texture)
|
||||||
{
|
{
|
||||||
s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
|
s_efb.depthRead_texture->GetSurfaceLevel(0, &s_efb.depth_ReadBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an offscreen surface that we can lock to retrieve the data
|
// Create an offscreen surface that we can lock to retrieve the data
|
||||||
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL);
|
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb.depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb.depth_OffScreenReadBuffer, NULL);
|
||||||
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
|
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
|
||||||
delete [] DepthTexFormats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::Destroy()
|
FramebufferManager::~FramebufferManager()
|
||||||
{
|
{
|
||||||
if (s_efb_depth_surface)
|
SAFE_RELEASE(s_efb.depth_surface);
|
||||||
s_efb_depth_surface->Release();
|
SAFE_RELEASE(s_efb.color_surface);
|
||||||
s_efb_depth_surface = NULL;
|
SAFE_RELEASE(s_efb.color_ReadBuffer);
|
||||||
|
SAFE_RELEASE(s_efb.depth_ReadBuffer);
|
||||||
if (s_efb_color_surface)
|
SAFE_RELEASE(s_efb.color_OffScreenReadBuffer);
|
||||||
s_efb_color_surface->Release();
|
SAFE_RELEASE(s_efb.depth_OffScreenReadBuffer);
|
||||||
s_efb_color_surface = NULL;
|
SAFE_RELEASE(s_efb.color_texture);
|
||||||
|
SAFE_RELEASE(s_efb.colorRead_texture);
|
||||||
if (s_efb_color_ReadBuffer)
|
SAFE_RELEASE(s_efb.depth_texture);
|
||||||
s_efb_color_ReadBuffer->Release();
|
SAFE_RELEASE(s_efb.depthRead_texture);
|
||||||
s_efb_color_ReadBuffer = NULL;
|
|
||||||
|
|
||||||
if (s_efb_depth_ReadBuffer)
|
|
||||||
s_efb_depth_ReadBuffer->Release();
|
|
||||||
s_efb_depth_ReadBuffer = NULL;
|
|
||||||
|
|
||||||
if (s_efb_color_OffScreenReadBuffer)
|
|
||||||
s_efb_color_OffScreenReadBuffer->Release();
|
|
||||||
s_efb_color_OffScreenReadBuffer = NULL;
|
|
||||||
|
|
||||||
if (s_efb_depth_OffScreenReadBuffer)
|
|
||||||
s_efb_depth_OffScreenReadBuffer->Release();
|
|
||||||
s_efb_depth_OffScreenReadBuffer = NULL;
|
|
||||||
|
|
||||||
if (s_efb_color_texture)
|
|
||||||
s_efb_color_texture->Release();
|
|
||||||
s_efb_color_texture = NULL;
|
|
||||||
|
|
||||||
if (s_efb_colorRead_texture)
|
|
||||||
s_efb_colorRead_texture->Release();
|
|
||||||
s_efb_colorRead_texture = NULL;
|
|
||||||
|
|
||||||
if (s_efb_depth_texture)
|
|
||||||
s_efb_depth_texture->Release();
|
|
||||||
s_efb_depth_texture = NULL;
|
|
||||||
|
|
||||||
if (s_efb_depthRead_texture)
|
|
||||||
s_efb_depthRead_texture->Release();
|
|
||||||
s_efb_depthRead_texture = NULL;
|
|
||||||
|
|
||||||
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
|
||||||
{
|
|
||||||
if(it->xfbSource.texture)
|
|
||||||
it->xfbSource.texture->Release();
|
|
||||||
}
|
|
||||||
m_virtualXFBList.clear();
|
|
||||||
if(m_realXFBSource.texture)
|
|
||||||
m_realXFBSource.texture->Release();
|
|
||||||
m_realXFBSource.texture = NULL;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||||
{
|
{
|
||||||
if (g_ActiveConfig.bUseRealXFB)
|
LPDIRECT3DTEXTURE9 tex;
|
||||||
copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET,
|
||||||
else
|
s_efb.color_surface_Format, D3DPOOL_DEFAULT, &tex, NULL);
|
||||||
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
|
||||||
|
return new XFBSource(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
if (g_ActiveConfig.bUseRealXFB)
|
const float scaleX = Renderer::GetXFBScaleX();
|
||||||
return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
const float scaleY = Renderer::GetXFBScaleY();
|
||||||
else
|
|
||||||
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
TargetRectangle targetSource;
|
||||||
|
|
||||||
|
targetSource.top = (int)(sourceRc.top *scaleY);
|
||||||
|
targetSource.bottom = (int)(sourceRc.bottom *scaleY);
|
||||||
|
targetSource.left = (int)(sourceRc.left *scaleX);
|
||||||
|
targetSource.right = (int)(sourceRc.right * scaleX);
|
||||||
|
|
||||||
|
*width = targetSource.right - targetSource.left;
|
||||||
|
*height = targetSource.bottom - targetSource.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferManager::VirtualXFBListType::iterator FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
|
||||||
{
|
{
|
||||||
u32 srcLower = xfbAddr;
|
D3D::drawShadedTexSubQuad(texture, &sourcerc, texWidth, texHeight, &drawrc, width , height,
|
||||||
u32 srcUpper = xfbAddr + 2 * width * height;
|
PixelShaderCache::GetColorCopyProgram(0), VertexShaderCache::GetSimpleVertexShader(0));
|
||||||
|
|
||||||
VirtualXFBListType::iterator it;
|
|
||||||
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
|
||||||
{
|
|
||||||
u32 dstLower = it->xfbAddr;
|
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// That address is not in the Virtual XFB list.
|
|
||||||
return m_virtualXFBList.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::replaceVirtualXFB()
|
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||||
{
|
{
|
||||||
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
|
||||||
|
|
||||||
s32 srcLower = it->xfbAddr;
|
|
||||||
s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
s32 lineSize = 2 * it->xfbWidth;
|
|
||||||
|
|
||||||
++it;
|
|
||||||
|
|
||||||
while (it != m_virtualXFBList.end())
|
|
||||||
{
|
|
||||||
s32 dstLower = it->xfbAddr;
|
|
||||||
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
{
|
|
||||||
// Invalidate the data
|
|
||||||
it->xfbAddr = 0;
|
|
||||||
it->xfbHeight = 0;
|
|
||||||
it->xfbWidth = 0;
|
|
||||||
}
|
|
||||||
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
|
||||||
{
|
|
||||||
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
|
||||||
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
|
||||||
|
|
||||||
if (upperOverlap > 0 && lowerOverlap < 0)
|
|
||||||
{
|
|
||||||
it->xfbAddr += lineSize * upperOverlap;
|
|
||||||
it->xfbHeight -= upperOverlap;
|
|
||||||
}
|
|
||||||
else if (lowerOverlap > 0)
|
|
||||||
{
|
|
||||||
it->xfbHeight -= lowerOverlap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
||||||
if (!xfb_in_ram)
|
if (!xfb_in_ram)
|
||||||
|
@ -308,190 +196,47 @@ void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
|
||||||
TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(), targetRc, xfb_in_ram, fbWidth, fbHeight);
|
TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(), targetRc, xfb_in_ram, fbWidth, fbHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
void XFBSource::CopyEFB()
|
||||||
{
|
{
|
||||||
LPDIRECT3DTEXTURE9 xfbTexture;
|
|
||||||
HRESULT hr = 0;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
|
||||||
|
|
||||||
if (it == m_virtualXFBList.end() && (int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
|
||||||
{
|
|
||||||
// Replace the last virtual XFB
|
|
||||||
--it;
|
|
||||||
}
|
|
||||||
|
|
||||||
float scaleX = Renderer::GetXFBScaleX();
|
|
||||||
float scaleY = Renderer::GetXFBScaleY();
|
|
||||||
TargetRectangle targetSource,efbSource;
|
|
||||||
efbSource = Renderer::ConvertEFBRectangle(sourceRc);
|
|
||||||
targetSource.top = (int)(sourceRc.top *scaleY);
|
|
||||||
targetSource.bottom = (int)(sourceRc.bottom *scaleY);
|
|
||||||
targetSource.left = (int)(sourceRc.left *scaleX);
|
|
||||||
targetSource.right = (int)(sourceRc.right * scaleX);
|
|
||||||
int target_width = targetSource.right - targetSource.left;
|
|
||||||
int target_height = targetSource.bottom - targetSource.top;
|
|
||||||
if (it != m_virtualXFBList.end())
|
|
||||||
{
|
|
||||||
// Overwrite an existing Virtual XFB.
|
|
||||||
|
|
||||||
it->xfbAddr = xfbAddr;
|
|
||||||
it->xfbWidth = fbWidth;
|
|
||||||
it->xfbHeight = fbHeight;
|
|
||||||
|
|
||||||
it->xfbSource.srcAddr = xfbAddr;
|
|
||||||
it->xfbSource.srcWidth = fbWidth;
|
|
||||||
it->xfbSource.srcHeight = fbHeight;
|
|
||||||
|
|
||||||
if(it->xfbSource.texWidth != target_width || it->xfbSource.texHeight != target_height || !(it->xfbSource.texture))
|
|
||||||
{
|
|
||||||
if(it->xfbSource.texture)
|
|
||||||
it->xfbSource.texture->Release();
|
|
||||||
it->xfbSource.texture = NULL;
|
|
||||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
|
||||||
D3DPOOL_DEFAULT, &(it->xfbSource.texture), NULL);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
xfbTexture = it->xfbSource.texture;
|
|
||||||
|
|
||||||
it->xfbSource.texWidth = target_width;
|
|
||||||
it->xfbSource.texHeight = target_height;
|
|
||||||
|
|
||||||
// Move this Virtual XFB to the front of the list.
|
|
||||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
|
||||||
|
|
||||||
// Keep stale XFB data from being used
|
|
||||||
replaceVirtualXFB();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Create a new Virtual XFB and place it at the front of the list.
|
|
||||||
|
|
||||||
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
|
||||||
D3DPOOL_DEFAULT, &xfbTexture, NULL);
|
|
||||||
VirtualXFB newVirt;
|
|
||||||
|
|
||||||
newVirt.xfbAddr = xfbAddr;
|
|
||||||
newVirt.xfbWidth = fbWidth;
|
|
||||||
newVirt.xfbHeight = fbHeight;
|
|
||||||
|
|
||||||
newVirt.xfbSource.texture = xfbTexture;
|
|
||||||
newVirt.xfbSource.texWidth = target_width;
|
|
||||||
newVirt.xfbSource.texHeight = target_height;
|
|
||||||
|
|
||||||
// Add the new Virtual XFB to the list
|
|
||||||
|
|
||||||
if ((int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
|
||||||
{
|
|
||||||
// List overflowed; delete the oldest.
|
|
||||||
m_virtualXFBList.back().xfbSource.texture->Release();
|
|
||||||
m_virtualXFBList.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_virtualXFBList.push_front(newVirt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy EFB data to XFB and restore render target again
|
// Copy EFB data to XFB and restore render target again
|
||||||
if(!xfbTexture)
|
|
||||||
return;
|
|
||||||
LPDIRECT3DTEXTURE9 read_texture = GetEFBColorTexture();
|
|
||||||
|
|
||||||
Renderer::ResetAPIState(); // Reset any game specific settings
|
|
||||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||||
|
texture->GetSurfaceLevel(0, &Rendersurf);
|
||||||
xfbTexture->GetSurfaceLevel(0, &Rendersurf);
|
|
||||||
D3D::dev->SetDepthStencilSurface(NULL);
|
D3D::dev->SetDepthStencilSurface(NULL);
|
||||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||||
|
|
||||||
D3DVIEWPORT9 vp;
|
D3DVIEWPORT9 vp;
|
||||||
|
|
||||||
vp.X = 0;
|
vp.X = 0;
|
||||||
vp.Y = 0;
|
vp.Y = 0;
|
||||||
vp.Width = target_width;
|
vp.Width = texWidth;
|
||||||
vp.Height = target_height;
|
vp.Height = texHeight;
|
||||||
vp.MinZ = 0.0f;
|
vp.MinZ = 0.0f;
|
||||||
vp.MaxZ = 1.0f;
|
vp.MaxZ = 1.0f;
|
||||||
D3D::dev->SetViewport(&vp);
|
D3D::dev->SetViewport(&vp);
|
||||||
|
|
||||||
RECT sourcerect;
|
RECT sourcerect;
|
||||||
sourcerect.bottom = efbSource.bottom;
|
sourcerect.bottom = sourceRc.bottom;
|
||||||
sourcerect.left = efbSource.left;
|
sourcerect.left = sourceRc.left;
|
||||||
sourcerect.right = efbSource.right;
|
sourcerect.right = sourceRc.right;
|
||||||
sourcerect.top = efbSource.top;
|
sourcerect.top = sourceRc.top;
|
||||||
|
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||||
|
|
||||||
D3D::drawShadedTexQuad(
|
D3D::drawShadedTexQuad(
|
||||||
read_texture,
|
FramebufferManager::GetEFBColorTexture(),
|
||||||
&sourcerect,
|
&sourcerect,
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetFullTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetFullTargetHeight(),
|
||||||
target_width,
|
texWidth,
|
||||||
target_height,
|
texHeight,
|
||||||
PixelShaderCache::GetColorCopyProgram( g_ActiveConfig.iMultisampleMode),
|
PixelShaderCache::GetColorCopyProgram( g_ActiveConfig.iMultisampleMode),
|
||||||
VertexShaderCache::GetSimpleVertexShader( g_ActiveConfig.iMultisampleMode));
|
VertexShaderCache::GetSimpleVertexShader( g_ActiveConfig.iMultisampleMode));
|
||||||
|
|
||||||
|
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||||
D3D::SetTexture(0, NULL);
|
D3D::SetTexture(0, NULL);
|
||||||
D3D::dev->SetRenderTarget(0, GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
Renderer::RestoreAPIState();
|
|
||||||
Rendersurf->Release();
|
Rendersurf->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
xfbCount = 1;
|
|
||||||
|
|
||||||
m_realXFBSource.texWidth = fbWidth;
|
|
||||||
m_realXFBSource.texHeight = fbHeight;
|
|
||||||
|
|
||||||
m_realXFBSource.srcAddr = xfbAddr;
|
|
||||||
m_realXFBSource.srcWidth = fbWidth;
|
|
||||||
m_realXFBSource.srcHeight = fbHeight;
|
|
||||||
|
|
||||||
if (!m_realXFBSource.texture)
|
|
||||||
{
|
|
||||||
D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
|
||||||
D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode YUYV data from GameCube RAM
|
|
||||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
|
||||||
|
|
||||||
m_overlappingXFBArray[0] = &m_realXFBSource;
|
|
||||||
|
|
||||||
return &m_overlappingXFBArray[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
xfbCount = 0;
|
|
||||||
|
|
||||||
if (m_virtualXFBList.size() == 0)
|
|
||||||
{
|
|
||||||
// No Virtual XFBs available.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 srcLower = xfbAddr;
|
|
||||||
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
|
||||||
|
|
||||||
VirtualXFBListType::reverse_iterator it;
|
|
||||||
for (it = m_virtualXFBList.rbegin(); it != m_virtualXFBList.rend(); ++it)
|
|
||||||
{
|
|
||||||
u32 dstLower = it->xfbAddr;
|
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
|
||||||
{
|
|
||||||
m_overlappingXFBArray[xfbCount] = &(it->xfbSource);
|
|
||||||
xfbCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m_overlappingXFBArray[0];
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef _FRAMEBUFFERMANAGER_D3D_H_
|
#ifndef _FRAMEBUFFERMANAGER_D3D_H_
|
||||||
#define _FRAMEBUFFERMANAGER_D3D_H_
|
#define _FRAMEBUFFERMANAGER_D3D_H_
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
|
#include "FramebufferManagerBase.h"
|
||||||
|
|
||||||
// On the GameCube, the game sends a request for the graphics processor to
|
// On the GameCube, the game sends a request for the graphics processor to
|
||||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||||
|
@ -50,124 +50,65 @@
|
||||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||||
|
|
||||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
struct XFBSource : public XFBSourceBase
|
||||||
// virtualize.
|
|
||||||
const int MAX_VIRTUAL_XFB = 8;
|
|
||||||
|
|
||||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
|
||||||
{
|
{
|
||||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
XFBSource(LPDIRECT3DTEXTURE9 tex) : texture(tex) {}
|
||||||
}
|
~XFBSource() { texture->Release(); }
|
||||||
|
|
||||||
struct XFBSource
|
void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
{
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
|
||||||
XFBSource()
|
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||||
{
|
void CopyEFB();
|
||||||
this->srcAddr = 0;
|
|
||||||
this->srcWidth = 0;
|
|
||||||
this->srcHeight = 0;
|
|
||||||
this->texture = 0;
|
|
||||||
this->texWidth = 0;
|
|
||||||
this->texHeight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 srcAddr;
|
LPDIRECT3DTEXTURE9 const texture;
|
||||||
u32 srcWidth;
|
|
||||||
u32 srcHeight;
|
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 texture;
|
|
||||||
int texWidth;
|
|
||||||
int texHeight;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FramebufferManager
|
class FramebufferManager : public FramebufferManagerBase
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
struct VirtualXFB
|
|
||||||
{
|
|
||||||
// Address and size in GameCube RAM
|
|
||||||
u32 xfbAddr;
|
|
||||||
u32 xfbWidth;
|
|
||||||
u32 xfbHeight;
|
|
||||||
|
|
||||||
XFBSource xfbSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
|
||||||
|
|
||||||
void replaceVirtualXFB();
|
|
||||||
|
|
||||||
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
const XFBSource** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
|
|
||||||
XFBSource m_realXFBSource; // Only used in Real XFB mode
|
|
||||||
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
|
||||||
|
|
||||||
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
|
|
||||||
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
|
|
||||||
LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
|
|
||||||
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
|
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
|
|
||||||
LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
|
|
||||||
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
|
|
||||||
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
|
|
||||||
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
|
||||||
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
|
||||||
|
|
||||||
D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
|
|
||||||
D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
|
|
||||||
D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
|
||||||
public:
|
public:
|
||||||
FramebufferManager()
|
FramebufferManager();
|
||||||
|
~FramebufferManager();
|
||||||
|
|
||||||
|
static LPDIRECT3DTEXTURE9 GetEFBColorTexture() { return s_efb.color_texture; }
|
||||||
|
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture() { return s_efb.depth_texture; }
|
||||||
|
|
||||||
|
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface() { return s_efb.color_surface; }
|
||||||
|
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface() { return s_efb.depth_surface; }
|
||||||
|
|
||||||
|
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface() { return s_efb.color_OffScreenReadBuffer; }
|
||||||
|
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface() { return s_efb.depth_OffScreenReadBuffer; }
|
||||||
|
|
||||||
|
static D3DFORMAT GetEFBDepthRTSurfaceFormat() { return s_efb.depth_surface_Format; }
|
||||||
|
static D3DFORMAT GetEFBColorRTSurfaceFormat() { return s_efb.color_surface_Format; }
|
||||||
|
static D3DFORMAT GetEFBDepthReadSurfaceFormat() { return s_efb.depth_ReadBuffer_Format; }
|
||||||
|
|
||||||
|
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface() { return s_efb.color_ReadBuffer; }
|
||||||
|
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface() { return s_efb.depth_ReadBuffer; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||||
|
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
|
||||||
|
|
||||||
|
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||||
|
|
||||||
|
static struct Efb
|
||||||
{
|
{
|
||||||
s_efb_color_texture = NULL;
|
LPDIRECT3DTEXTURE9 color_texture;//Texture thats contains the color data of the render target
|
||||||
s_efb_colorRead_texture = NULL;
|
LPDIRECT3DTEXTURE9 colorRead_texture;//1 pixel texture for temporal data store
|
||||||
s_efb_depth_texture = NULL;
|
LPDIRECT3DTEXTURE9 depth_texture;//Texture thats contains the depth data of the render target
|
||||||
s_efb_depthRead_texture = NULL;
|
LPDIRECT3DTEXTURE9 depthRead_texture;//4 pixel texture for temporal data store
|
||||||
|
|
||||||
s_efb_depth_surface = NULL;
|
|
||||||
s_efb_color_surface = NULL;
|
|
||||||
s_efb_color_ReadBuffer = NULL;
|
|
||||||
s_efb_depth_ReadBuffer = NULL;
|
|
||||||
s_efb_color_OffScreenReadBuffer = NULL;
|
|
||||||
s_efb_depth_OffScreenReadBuffer = NULL;
|
|
||||||
|
|
||||||
s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
|
|
||||||
s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
|
|
||||||
s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
|
||||||
m_realXFBSource.texture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Create();
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
const XFBSource** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 GetEFBColorTexture();
|
|
||||||
LPDIRECT3DTEXTURE9 GetEFBDepthTexture();
|
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
|
|
||||||
LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
|
|
||||||
LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
|
|
||||||
LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
|
|
||||||
D3DFORMAT GetEFBDepthRTSurfaceFormat();
|
|
||||||
D3DFORMAT GetEFBColorRTSurfaceFormat();
|
|
||||||
D3DFORMAT GetEFBDepthReadSurfaceFormat();
|
|
||||||
LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
|
|
||||||
LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
|
|
||||||
|
|
||||||
|
LPDIRECT3DSURFACE9 depth_surface;//Depth Surface
|
||||||
|
LPDIRECT3DSURFACE9 color_surface;//Color Surface
|
||||||
|
LPDIRECT3DSURFACE9 color_ReadBuffer;//Surface 0 of colorRead_texture
|
||||||
|
LPDIRECT3DSURFACE9 depth_ReadBuffer;//Surface 0 of depthRead_texture
|
||||||
|
LPDIRECT3DSURFACE9 color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||||
|
LPDIRECT3DSURFACE9 depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||||
|
|
||||||
|
D3DFORMAT color_surface_Format;//Format of the color Surface
|
||||||
|
D3DFORMAT depth_surface_Format;//Format of the Depth Surface
|
||||||
|
D3DFORMAT depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
||||||
|
} s_efb;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FramebufferManager g_framebufferManager;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -244,7 +244,7 @@ void SetupDeviceObjects()
|
||||||
{
|
{
|
||||||
D3D::font.Init();
|
D3D::font.Init();
|
||||||
VertexLoaderManager::Init();
|
VertexLoaderManager::Init();
|
||||||
g_framebufferManager.Create();
|
g_framebuffer_manager = new FramebufferManager;
|
||||||
|
|
||||||
VertexShaderManager::Dirty();
|
VertexShaderManager::Dirty();
|
||||||
PixelShaderManager::Dirty();
|
PixelShaderManager::Dirty();
|
||||||
|
@ -264,7 +264,7 @@ void TeardownDeviceObjects()
|
||||||
ScreenShootMEMSurface = NULL;
|
ScreenShootMEMSurface = NULL;
|
||||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
||||||
g_framebufferManager.Destroy();
|
delete g_framebuffer_manager;
|
||||||
D3D::font.Shutdown();
|
D3D::font.Shutdown();
|
||||||
TextureCache::Invalidate(false);
|
TextureCache::Invalidate(false);
|
||||||
VertexLoaderManager::Shutdown();
|
VertexLoaderManager::Shutdown();
|
||||||
|
@ -373,8 +373,8 @@ bool Renderer::Init()
|
||||||
D3D::dev->SetViewport(&vp);
|
D3D::dev->SetViewport(&vp);
|
||||||
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 0, 0);
|
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 0, 0);
|
||||||
|
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
vp.X = (s_Fulltarget_width - s_target_width) / 2;
|
vp.X = (s_Fulltarget_width - s_target_width) / 2;
|
||||||
vp.Y = (s_Fulltarget_height - s_target_height) / 2;
|
vp.Y = (s_Fulltarget_height - s_target_height) / 2;
|
||||||
vp.Width = s_target_width;
|
vp.Width = s_target_width;
|
||||||
|
@ -617,7 +617,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
|
||||||
// just use progressive.
|
// just use progressive.
|
||||||
if (g_ActiveConfig.bUseXFB)
|
if (g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
g_framebufferManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
FramebufferManager::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -729,15 +729,15 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
LPDIRECT3DSURFACE9 pEFBSurf, pBufferRT, pSystemBuf;
|
LPDIRECT3DSURFACE9 pEFBSurf, pBufferRT, pSystemBuf;
|
||||||
if(type == PEEK_Z || type == POKE_Z)
|
if(type == PEEK_Z || type == POKE_Z)
|
||||||
{
|
{
|
||||||
pEFBSurf = g_framebufferManager.GetEFBDepthRTSurface();
|
pEFBSurf = FramebufferManager::GetEFBDepthRTSurface();
|
||||||
pBufferRT = g_framebufferManager.GetEFBDepthReadSurface();
|
pBufferRT = FramebufferManager::GetEFBDepthReadSurface();
|
||||||
pSystemBuf = g_framebufferManager.GetEFBDepthOffScreenRTSurface();
|
pSystemBuf = FramebufferManager::GetEFBDepthOffScreenRTSurface();
|
||||||
}
|
}
|
||||||
else //if(type == PEEK_COLOR || type == POKE_COLOR)
|
else //if(type == PEEK_COLOR || type == POKE_COLOR)
|
||||||
{
|
{
|
||||||
pEFBSurf = g_framebufferManager.GetEFBColorRTSurface();
|
pEFBSurf = FramebufferManager::GetEFBColorRTSurface();
|
||||||
pBufferRT = g_framebufferManager.GetEFBColorReadSurface();
|
pBufferRT = FramebufferManager::GetEFBColorReadSurface();
|
||||||
pSystemBuf = g_framebufferManager.GetEFBColorOffScreenRTSurface();
|
pSystemBuf = FramebufferManager::GetEFBColorOffScreenRTSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer not found alert
|
// Buffer not found alert
|
||||||
|
@ -763,7 +763,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
RectToLock.top = targetPixelRc.top;
|
RectToLock.top = targetPixelRc.top;
|
||||||
if (type == PEEK_Z)
|
if (type == PEEK_Z)
|
||||||
{
|
{
|
||||||
if (g_framebufferManager.GetEFBDepthRTSurfaceFormat() == D3DFMT_D24X8)
|
if (FramebufferManager::GetEFBDepthRTSurfaceFormat() == D3DFMT_D24X8)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
RECT PixelRect;
|
RECT PixelRect;
|
||||||
|
@ -798,7 +798,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
float fConstAdd[4] = {0.0f};
|
float fConstAdd[4] = {0.0f};
|
||||||
colmat[0] = colmat[5] = colmat[10] = 1.0f;
|
colmat[0] = colmat[5] = colmat[10] = 1.0f;
|
||||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||||
LPDIRECT3DTEXTURE9 read_texture = g_framebufferManager.GetEFBDepthTexture();
|
LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBDepthTexture();
|
||||||
|
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||||
|
|
||||||
|
@ -808,13 +808,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetFullTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetFullTargetHeight(),
|
||||||
4, 4,
|
4, 4,
|
||||||
(g_framebufferManager.GetEFBDepthRTSurfaceFormat() == FOURCC_RAWZ) ? PixelShaderCache::GetColorMatrixProgram(0) : PixelShaderCache::GetDepthMatrixProgram(0),
|
(FramebufferManager::GetEFBDepthRTSurfaceFormat() == FOURCC_RAWZ) ? PixelShaderCache::GetColorMatrixProgram(0) : PixelShaderCache::GetDepthMatrixProgram(0),
|
||||||
VertexShaderCache::GetSimpleVertexShader(0));
|
VertexShaderCache::GetSimpleVertexShader(0));
|
||||||
|
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||||
|
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
RestoreAPIState();
|
RestoreAPIState();
|
||||||
|
|
||||||
// Retrieve the pixel data to the local memory buffer
|
// Retrieve the pixel data to the local memory buffer
|
||||||
|
@ -831,7 +831,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
float val = 0.0f;
|
float val = 0.0f;
|
||||||
u32 z = 0;
|
u32 z = 0;
|
||||||
|
|
||||||
switch (g_framebufferManager.GetEFBDepthReadSurfaceFormat())
|
switch (FramebufferManager::GetEFBDepthReadSurfaceFormat())
|
||||||
{
|
{
|
||||||
case D3DFMT_R32F:
|
case D3DFMT_R32F:
|
||||||
val = ((float*)drect.pBits)[6];
|
val = ((float*)drect.pBits)[6];
|
||||||
|
@ -973,10 +973,12 @@ void UpdateViewport()
|
||||||
{
|
{
|
||||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
||||||
g_framebufferManager.Destroy();
|
|
||||||
g_framebufferManager.Create();
|
delete g_framebuffer_manager;
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
g_framebuffer_manager = new FramebufferManager;
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
|
||||||
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vp.X = X;
|
vp.X = X;
|
||||||
|
@ -1052,7 +1054,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
|
|
||||||
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
||||||
u32 xfbCount = 0;
|
u32 xfbCount = 0;
|
||||||
const XFBSource** xfbSourceList = g_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
const XFBSourceBase *const *xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pCopiedToXFB(false);
|
g_VideoInitialize.pCopiedToXFB(false);
|
||||||
|
@ -1133,7 +1135,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||||
|
|
||||||
const XFBSource* xfbSource = NULL;
|
const XFBSourceBase* xfbSource = NULL;
|
||||||
|
|
||||||
if(g_ActiveConfig.bUseXFB)
|
if(g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
|
@ -1181,13 +1183,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
drawRc.right = 1;
|
drawRc.right = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D::drawShadedTexSubQuad(xfbSource->texture,&sourceRc,xfbSource->texWidth,xfbSource->texHeight,&drawRc,Width,Height,PixelShaderCache::GetColorCopyProgram(0),VertexShaderCache::GetSimpleVertexShader(0));
|
xfbSource->Draw(sourceRc, drawRc, Width, Height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
||||||
LPDIRECT3DTEXTURE9 read_texture = g_framebufferManager.GetEFBColorTexture();
|
LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBColorTexture();
|
||||||
D3D::drawShadedTexQuad(read_texture,targetRc.AsRECT(),Renderer::GetFullTargetWidth(),Renderer::GetFullTargetHeight(),Width,Height,PixelShaderCache::GetColorCopyProgram(g_Config.iMultisampleMode),VertexShaderCache::GetSimpleVertexShader(g_Config.iMultisampleMode));
|
D3D::drawShadedTexQuad(read_texture,targetRc.AsRECT(),Renderer::GetFullTargetWidth(),Renderer::GetFullTargetHeight(),Width,Height,PixelShaderCache::GetColorCopyProgram(g_Config.iMultisampleMode),VertexShaderCache::GetSimpleVertexShader(g_Config.iMultisampleMode));
|
||||||
}
|
}
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||||
|
@ -1375,11 +1377,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_framebufferManager.Destroy();
|
delete g_framebuffer_manager;
|
||||||
g_framebufferManager.Create();
|
g_framebuffer_manager = new FramebufferManager;
|
||||||
}
|
}
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place messages on the picture, then copy it to the screen
|
// Place messages on the picture, then copy it to the screen
|
||||||
|
@ -1407,8 +1409,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
D3D::BeginFrame();
|
D3D::BeginFrame();
|
||||||
RestoreAPIState();
|
RestoreAPIState();
|
||||||
|
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
UpdateViewport();
|
UpdateViewport();
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
// For testing zbuffer targets.
|
// For testing zbuffer targets.
|
||||||
|
|
|
@ -74,8 +74,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
bool bIsIntensityFmt, u32 copyfmt)
|
bool bIsIntensityFmt, u32 copyfmt)
|
||||||
{
|
{
|
||||||
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
|
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
|
||||||
g_framebufferManager.GetEFBDepthTexture() :
|
FramebufferManager::GetEFBDepthTexture() :
|
||||||
g_framebufferManager.GetEFBColorTexture();
|
FramebufferManager::GetEFBColorTexture();
|
||||||
|
|
||||||
if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture)
|
if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture)
|
||||||
{
|
{
|
||||||
|
@ -128,7 +128,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
D3DFORMAT bformat = g_framebufferManager.GetEFBDepthRTSurfaceFormat();
|
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
|
||||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||||
|
|
||||||
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
||||||
|
@ -163,8 +163,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||||
D3D::SetTexture(0, NULL);
|
D3D::SetTexture(0, NULL);
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
|
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
|
||||||
|
|
|
@ -325,7 +325,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
||||||
|
|
||||||
u8 *dest_ptr = Memory_GetPtr(address);
|
u8 *dest_ptr = Memory_GetPtr(address);
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? g_framebufferManager.GetEFBDepthTexture() : g_framebufferManager.GetEFBColorTexture();
|
LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture();
|
||||||
int width = (source.right - source.left) >> bScaleByHalf;
|
int width = (source.right - source.left) >> bScaleByHalf;
|
||||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||||
|
|
||||||
|
@ -374,8 +374,8 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
||||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||||
Renderer::ResetAPIState();
|
Renderer::ResetAPIState();
|
||||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
|
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
Renderer::RestoreAPIState();
|
Renderer::RestoreAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,8 +461,8 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
|
||||||
(float)Renderer::GetFullTargetHeight());
|
(float)Renderer::GetFullTargetHeight());
|
||||||
Renderer::ResetAPIState();
|
Renderer::ResetAPIState();
|
||||||
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
Renderer::RestoreAPIState();
|
Renderer::RestoreAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,8 +534,8 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||||
D3D::SetTexture(0,NULL);
|
D3D::SetTexture(0,NULL);
|
||||||
D3D::dev->SetRenderTarget(0, g_framebufferManager.GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(g_framebufferManager.GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
Renderer::RestoreAPIState();
|
Renderer::RestoreAPIState();
|
||||||
Rendersurf->Release();
|
Rendersurf->Release();
|
||||||
s_srcTexture->Release();
|
s_srcTexture->Release();
|
||||||
|
|
|
@ -10,8 +10,7 @@ set(SRCS Src/BPFunctions.cpp
|
||||||
Src/TextureCache.cpp
|
Src/TextureCache.cpp
|
||||||
Src/TextureConverter.cpp
|
Src/TextureConverter.cpp
|
||||||
Src/VertexShaderCache.cpp
|
Src/VertexShaderCache.cpp
|
||||||
Src/VertexManager.cpp
|
Src/VertexManager.cpp)
|
||||||
Src/XFB.cpp)
|
|
||||||
|
|
||||||
set(LIBS videocommon
|
set(LIBS videocommon
|
||||||
GLEW
|
GLEW
|
||||||
|
|
|
@ -781,14 +781,6 @@
|
||||||
RelativePath=".\Src\VertexShaderCache.h"
|
RelativePath=".\Src\VertexShaderCache.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\Src\XFB.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\Src\XFB.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="GUI"
|
Name="GUI"
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "XFB.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
namespace BPFunctions
|
namespace BPFunctions
|
||||||
|
|
|
@ -19,17 +19,39 @@
|
||||||
#include "FramebufferManager.h"
|
#include "FramebufferManager.h"
|
||||||
|
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "XFB.h"
|
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
|
|
||||||
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
|
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
|
||||||
|
|
||||||
FramebufferManager g_framebufferManager;
|
int FramebufferManager::m_targetWidth;
|
||||||
|
int FramebufferManager::m_targetHeight;
|
||||||
|
int FramebufferManager::m_msaaSamples;
|
||||||
|
int FramebufferManager::m_msaaCoverageSamples;
|
||||||
|
|
||||||
void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
GLuint FramebufferManager::m_efbFramebuffer;
|
||||||
|
GLuint FramebufferManager::m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
|
GLuint FramebufferManager::m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
|
|
||||||
|
// Only used in MSAA mode.
|
||||||
|
GLuint FramebufferManager::m_resolvedFramebuffer;
|
||||||
|
GLuint FramebufferManager::m_resolvedColorTexture;
|
||||||
|
GLuint FramebufferManager::m_resolvedDepthTexture;
|
||||||
|
|
||||||
|
GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
|
||||||
|
|
||||||
|
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
||||||
{
|
{
|
||||||
|
m_efbFramebuffer = 0;
|
||||||
|
m_efbColor = 0;
|
||||||
|
m_efbDepth = 0;
|
||||||
|
m_resolvedFramebuffer = 0;
|
||||||
|
m_resolvedColorTexture = 0;
|
||||||
|
m_resolvedDepthTexture = 0;
|
||||||
|
m_xfbFramebuffer = 0;
|
||||||
|
|
||||||
m_targetWidth = targetWidth;
|
m_targetWidth = targetWidth;
|
||||||
m_targetHeight = targetHeight;
|
m_targetHeight = targetHeight;
|
||||||
|
|
||||||
m_msaaSamples = msaaSamples;
|
m_msaaSamples = msaaSamples;
|
||||||
m_msaaCoverageSamples = msaaCoverageSamples;
|
m_msaaCoverageSamples = msaaCoverageSamples;
|
||||||
|
|
||||||
|
@ -147,7 +169,7 @@ void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples
|
||||||
// EFB framebuffer is currently bound.
|
// EFB framebuffer is currently bound.
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::Shutdown()
|
FramebufferManager::~FramebufferManager()
|
||||||
{
|
{
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
@ -164,11 +186,9 @@ void FramebufferManager::Shutdown()
|
||||||
|
|
||||||
glObj[0] = m_resolvedColorTexture;
|
glObj[0] = m_resolvedColorTexture;
|
||||||
glObj[1] = m_resolvedDepthTexture;
|
glObj[1] = m_resolvedDepthTexture;
|
||||||
glObj[2] = m_realXFBSource.texture;
|
glDeleteTextures(2, glObj);
|
||||||
glDeleteTextures(3, glObj);
|
|
||||||
m_resolvedColorTexture = 0;
|
m_resolvedColorTexture = 0;
|
||||||
m_resolvedDepthTexture = 0;
|
m_resolvedDepthTexture = 0;
|
||||||
m_realXFBSource.texture = 0;
|
|
||||||
|
|
||||||
glObj[0] = m_efbColor;
|
glObj[0] = m_efbColor;
|
||||||
glObj[1] = m_efbDepth;
|
glObj[1] = m_efbDepth;
|
||||||
|
@ -178,15 +198,9 @@ void FramebufferManager::Shutdown()
|
||||||
glDeleteRenderbuffersEXT(2, glObj);
|
glDeleteRenderbuffersEXT(2, glObj);
|
||||||
m_efbColor = 0;
|
m_efbColor = 0;
|
||||||
m_efbDepth = 0;
|
m_efbDepth = 0;
|
||||||
|
|
||||||
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &it->xfbSource.texture);
|
|
||||||
}
|
|
||||||
m_virtualXFBList.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc) const
|
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
{
|
{
|
||||||
|
@ -216,7 +230,7 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc) cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc) const
|
GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
{
|
{
|
||||||
|
@ -246,84 +260,7 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc) cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
{
|
|
||||||
if (g_ActiveConfig.bUseRealXFB)
|
|
||||||
copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
|
||||||
else
|
|
||||||
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
|
||||||
}
|
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
if (g_ActiveConfig.bUseRealXFB)
|
|
||||||
return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
|
||||||
else
|
|
||||||
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
FramebufferManager::VirtualXFBListType::iterator FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
|
||||||
{
|
|
||||||
u32 srcLower = xfbAddr;
|
|
||||||
u32 srcUpper = xfbAddr + 2 * width * height;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator it;
|
|
||||||
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
|
||||||
{
|
|
||||||
u32 dstLower = it->xfbAddr;
|
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// That address is not in the Virtual XFB list.
|
|
||||||
return m_virtualXFBList.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::replaceVirtualXFB()
|
|
||||||
{
|
|
||||||
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
|
||||||
|
|
||||||
s32 srcLower = it->xfbAddr;
|
|
||||||
s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
s32 lineSize = 2 * it->xfbWidth;
|
|
||||||
|
|
||||||
++it;
|
|
||||||
|
|
||||||
while (it != m_virtualXFBList.end())
|
|
||||||
{
|
|
||||||
s32 dstLower = it->xfbAddr;
|
|
||||||
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
{
|
|
||||||
// Invalidate the data
|
|
||||||
it->xfbAddr = 0;
|
|
||||||
it->xfbHeight = 0;
|
|
||||||
it->xfbWidth = 0;
|
|
||||||
}
|
|
||||||
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
|
||||||
{
|
|
||||||
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
|
||||||
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
|
||||||
|
|
||||||
if (upperOverlap > 0 && lowerOverlap < 0)
|
|
||||||
{
|
|
||||||
it->xfbAddr += lineSize * upperOverlap;
|
|
||||||
it->xfbHeight -= upperOverlap;
|
|
||||||
}
|
|
||||||
else if (lowerOverlap > 0)
|
|
||||||
{
|
|
||||||
it->xfbHeight -= lowerOverlap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
|
||||||
{
|
{
|
||||||
u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
||||||
if (!xfb_in_ram)
|
if (!xfb_in_ram)
|
||||||
|
@ -332,199 +269,8 @@ void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFB_Write(xfb_in_ram, sourceRc, fbWidth, fbHeight);
|
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||||
}
|
TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
|
||||||
|
|
||||||
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
|
||||||
{
|
|
||||||
GLuint xfbTexture;
|
|
||||||
|
|
||||||
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
|
||||||
|
|
||||||
if (it == m_virtualXFBList.end() && (int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
|
||||||
{
|
|
||||||
// Replace the last virtual XFB
|
|
||||||
--it;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it != m_virtualXFBList.end())
|
|
||||||
{
|
|
||||||
// Overwrite an existing Virtual XFB.
|
|
||||||
|
|
||||||
it->xfbAddr = xfbAddr;
|
|
||||||
it->xfbWidth = fbWidth;
|
|
||||||
it->xfbHeight = fbHeight;
|
|
||||||
|
|
||||||
it->xfbSource.srcAddr = xfbAddr;
|
|
||||||
it->xfbSource.srcWidth = fbWidth;
|
|
||||||
it->xfbSource.srcHeight = fbHeight;
|
|
||||||
|
|
||||||
it->xfbSource.texWidth = Renderer::GetTargetWidth();
|
|
||||||
it->xfbSource.texHeight = Renderer::GetTargetHeight();
|
|
||||||
it->xfbSource.sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
|
|
||||||
|
|
||||||
xfbTexture = it->xfbSource.texture;
|
|
||||||
|
|
||||||
// Move this Virtual XFB to the front of the list.
|
|
||||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
|
||||||
|
|
||||||
// Keep stale XFB data from being used
|
|
||||||
replaceVirtualXFB();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Create a new Virtual XFB and place it at the front of the list.
|
|
||||||
|
|
||||||
glGenTextures(1, &xfbTexture);
|
|
||||||
|
|
||||||
#if 0// XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
|
|
||||||
if (m_msaaSamples > 1)
|
|
||||||
#else
|
|
||||||
if (s_bHaveFramebufferBlit)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
|
|
||||||
// the image will be allocated by glCopyTexImage2D (later).
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
|
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualXFB newVirt;
|
|
||||||
|
|
||||||
newVirt.xfbAddr = xfbAddr;
|
|
||||||
newVirt.xfbWidth = fbWidth;
|
|
||||||
newVirt.xfbHeight = fbHeight;
|
|
||||||
|
|
||||||
newVirt.xfbSource.srcAddr = xfbAddr;
|
|
||||||
newVirt.xfbSource.srcWidth = fbWidth;
|
|
||||||
newVirt.xfbSource.srcHeight = fbHeight;
|
|
||||||
|
|
||||||
newVirt.xfbSource.texture = xfbTexture;
|
|
||||||
newVirt.xfbSource.texWidth = m_targetWidth;
|
|
||||||
newVirt.xfbSource.texHeight = m_targetHeight;
|
|
||||||
newVirt.xfbSource.sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
|
|
||||||
|
|
||||||
// Add the new Virtual XFB to the list
|
|
||||||
|
|
||||||
if ((int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
|
||||||
{
|
|
||||||
// List overflowed; delete the oldest.
|
|
||||||
glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture);
|
|
||||||
m_virtualXFBList.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_virtualXFBList.push_front(newVirt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy EFB data to XFB and restore render target again
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (m_msaaSamples <= 1)
|
|
||||||
#else
|
|
||||||
if (!s_bHaveFramebufferBlit)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
// Just copy the EFB directly.
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
|
|
||||||
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// OpenGL cannot copy directly from a multisampled framebuffer, so use
|
|
||||||
// EXT_framebuffer_blit.
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer);
|
|
||||||
|
|
||||||
// Bind texture.
|
|
||||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0);
|
|
||||||
GL_REPORT_FBO_ERROR();
|
|
||||||
|
|
||||||
glBlitFramebufferEXT(
|
|
||||||
0, 0, m_targetWidth, m_targetHeight,
|
|
||||||
0, 0, m_targetWidth, m_targetHeight,
|
|
||||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
|
||||||
);
|
|
||||||
|
|
||||||
// Unbind texture.
|
|
||||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
|
||||||
|
|
||||||
// Return to EFB.
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
xfbCount = 1;
|
|
||||||
|
|
||||||
m_realXFBSource.texWidth = MAX_XFB_WIDTH;
|
|
||||||
m_realXFBSource.texHeight = MAX_XFB_HEIGHT;
|
|
||||||
|
|
||||||
m_realXFBSource.srcAddr = xfbAddr;
|
|
||||||
m_realXFBSource.srcWidth = fbWidth;
|
|
||||||
m_realXFBSource.srcHeight = fbHeight;
|
|
||||||
|
|
||||||
// OpenGL texture coordinates originate at the lower left, which is why
|
|
||||||
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
|
||||||
m_realXFBSource.sourceRc.left = 0;
|
|
||||||
m_realXFBSource.sourceRc.top = fbHeight;
|
|
||||||
m_realXFBSource.sourceRc.right = fbWidth;
|
|
||||||
m_realXFBSource.sourceRc.bottom = 0;
|
|
||||||
|
|
||||||
if (!m_realXFBSource.texture)
|
|
||||||
{
|
|
||||||
glGenTextures(1, &m_realXFBSource.texture);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
|
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode YUYV data from GameCube RAM
|
|
||||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
|
||||||
|
|
||||||
m_overlappingXFBArray[0] = &m_realXFBSource;
|
|
||||||
|
|
||||||
return &m_overlappingXFBArray[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const XFBSource** FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
|
||||||
{
|
|
||||||
xfbCount = 0;
|
|
||||||
|
|
||||||
if (m_virtualXFBList.size() == 0)
|
|
||||||
{
|
|
||||||
// No Virtual XFBs available.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 srcLower = xfbAddr;
|
|
||||||
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
|
||||||
|
|
||||||
VirtualXFBListType::reverse_iterator it;
|
|
||||||
for (it = m_virtualXFBList.rbegin(); it != m_virtualXFBList.rend(); ++it)
|
|
||||||
{
|
|
||||||
u32 dstLower = it->xfbAddr;
|
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
|
||||||
|
|
||||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
|
||||||
{
|
|
||||||
m_overlappingXFBArray[xfbCount] = &(it->xfbSource);
|
|
||||||
xfbCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m_overlappingXFBArray[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::SetFramebuffer(GLuint fb)
|
void FramebufferManager::SetFramebuffer(GLuint fb)
|
||||||
|
@ -543,4 +289,110 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
|
||||||
return GetEFBDepthTexture(source_rect);
|
return GetEFBDepthTexture(source_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
|
||||||
|
{
|
||||||
|
// Texture map xfbSource->texture onto the main buffer
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(sourcerc.left, sourcerc.bottom);
|
||||||
|
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
|
||||||
|
glVertex2f(drawrc.left, drawrc.bottom);
|
||||||
|
|
||||||
|
glTexCoord2f(sourcerc.left, sourcerc.top);
|
||||||
|
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
|
||||||
|
glVertex2f(drawrc.left, drawrc.top);
|
||||||
|
|
||||||
|
glTexCoord2f(sourcerc.right, sourcerc.top);
|
||||||
|
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
|
||||||
|
glVertex2f(drawrc.right, drawrc.top);
|
||||||
|
|
||||||
|
glTexCoord2f(sourcerc.right, sourcerc.bottom);
|
||||||
|
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
|
||||||
|
glVertex2f(drawrc.right, drawrc.bottom);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
GL_REPORT_ERRORD();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||||
|
{
|
||||||
|
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XFBSource::CopyEFB()
|
||||||
|
{
|
||||||
|
// Copy EFB data to XFB and restore render target again
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (m_msaaSamples <= 1)
|
||||||
|
#else
|
||||||
|
if (!s_bHaveFramebufferBlit)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Just copy the EFB directly.
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||||
|
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OpenGL cannot copy directly from a multisampled framebuffer, so use
|
||||||
|
// EXT_framebuffer_blit.
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
|
||||||
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::GetXFBFramebuffer());
|
||||||
|
|
||||||
|
// Bind texture.
|
||||||
|
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
|
||||||
|
GL_REPORT_FBO_ERROR();
|
||||||
|
|
||||||
|
glBlitFramebufferEXT(
|
||||||
|
0, 0, texWidth, texHeight,
|
||||||
|
0, 0, texWidth, texHeight,
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unbind texture.
|
||||||
|
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||||
|
|
||||||
|
// Return to EFB.
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||||
|
{
|
||||||
|
GLuint texture;
|
||||||
|
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
|
||||||
|
#if 0// XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
|
||||||
|
if (m_msaaSamples > 1)
|
||||||
|
#else
|
||||||
|
if (s_bHaveFramebufferBlit)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
|
||||||
|
// the image will be allocated by glCopyTexImage2D (later).
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, target_width, target_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new XFBSource(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
|
||||||
|
{
|
||||||
|
*width = m_targetWidth;
|
||||||
|
*height = m_targetHeight;
|
||||||
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef _FRAMEBUFFERMANAGER_H_
|
#ifndef _FRAMEBUFFERMANAGER_H_
|
||||||
#define _FRAMEBUFFERMANAGER_H_
|
#define _FRAMEBUFFERMANAGER_H_
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
|
#include "FramebufferManagerBase.h"
|
||||||
|
|
||||||
// On the GameCube, the game sends a request for the graphics processor to
|
// On the GameCube, the game sends a request for the graphics processor to
|
||||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||||
|
@ -52,116 +52,70 @@
|
||||||
|
|
||||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||||
// virtualize.
|
// virtualize.
|
||||||
const int MAX_VIRTUAL_XFB = 8;
|
|
||||||
|
|
||||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
struct XFBSource : public XFBSourceBase
|
||||||
{
|
{
|
||||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
XFBSource(GLuint tex) : texture(tex) {}
|
||||||
}
|
~XFBSource() { glDeleteTextures(1, &texture); }
|
||||||
|
|
||||||
struct XFBSource
|
void CopyEFB();
|
||||||
{
|
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||||
XFBSource() :
|
void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
texture(0)
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
|
||||||
{}
|
|
||||||
|
|
||||||
u32 srcAddr;
|
const GLuint texture;
|
||||||
u32 srcWidth;
|
|
||||||
u32 srcHeight;
|
|
||||||
|
|
||||||
GLuint texture;
|
|
||||||
int texWidth;
|
|
||||||
int texHeight;
|
|
||||||
|
|
||||||
TargetRectangle sourceRc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FramebufferManager
|
class FramebufferManager : public FramebufferManagerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FramebufferManager() :
|
FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
|
||||||
m_efbFramebuffer(0),
|
~FramebufferManager();
|
||||||
m_efbColor(0),
|
|
||||||
m_efbDepth(0),
|
|
||||||
m_resolvedFramebuffer(0),
|
|
||||||
m_resolvedColorTexture(0),
|
|
||||||
m_resolvedDepthTexture(0),
|
|
||||||
m_xfbFramebuffer(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
|
|
||||||
const XFBSource** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
|
|
||||||
// To get the EFB in texture form, these functions may have to transfer
|
// To get the EFB in texture form, these functions may have to transfer
|
||||||
// the EFB to a resolved texture first.
|
// the EFB to a resolved texture first.
|
||||||
GLuint GetEFBColorTexture(const EFBRectangle& sourceRc) const;
|
static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||||
GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc) const;
|
static GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||||
|
|
||||||
GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; }
|
static GLuint GetEFBFramebuffer() { return m_efbFramebuffer; }
|
||||||
|
static GLuint GetXFBFramebuffer() { return m_xfbFramebuffer; }
|
||||||
|
|
||||||
// Resolved framebuffer is only used in MSAA mode.
|
// Resolved framebuffer is only used in MSAA mode.
|
||||||
GLuint GetResolvedFramebuffer() const { return m_resolvedFramebuffer; }
|
static GLuint GetResolvedFramebuffer() { return m_resolvedFramebuffer; }
|
||||||
|
|
||||||
void SetFramebuffer(GLuint fb);
|
static void SetFramebuffer(GLuint fb);
|
||||||
|
|
||||||
// If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID.
|
// If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID.
|
||||||
// Thus, this call may be expensive. Don't repeat it unnecessarily.
|
// Thus, this call may be expensive. Don't repeat it unnecessarily.
|
||||||
// If not in MSAA mode, will just return the render target texture ID.
|
// If not in MSAA mode, will just return the render target texture ID.
|
||||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||||
GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
|
static GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
|
||||||
|
|
||||||
// Same as above but for the depth Target.
|
// Same as above but for the depth Target.
|
||||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||||
GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
|
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||||
|
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
|
||||||
|
|
||||||
struct VirtualXFB
|
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
||||||
{
|
|
||||||
// Address and size in GameCube RAM
|
|
||||||
u32 xfbAddr;
|
|
||||||
u32 xfbWidth;
|
|
||||||
u32 xfbHeight;
|
|
||||||
|
|
||||||
XFBSource xfbSource;
|
static int m_targetWidth;
|
||||||
};
|
static int m_targetHeight;
|
||||||
|
static int m_msaaSamples;
|
||||||
|
static int m_msaaCoverageSamples;
|
||||||
|
|
||||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
static GLuint m_efbFramebuffer;
|
||||||
|
static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
|
|
||||||
void replaceVirtualXFB();
|
|
||||||
|
|
||||||
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
|
||||||
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
const XFBSource** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
|
||||||
|
|
||||||
int m_targetWidth;
|
|
||||||
int m_targetHeight;
|
|
||||||
int m_msaaSamples;
|
|
||||||
int m_msaaCoverageSamples;
|
|
||||||
|
|
||||||
GLuint m_efbFramebuffer;
|
|
||||||
GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
|
||||||
GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
|
||||||
|
|
||||||
// Only used in MSAA mode.
|
// Only used in MSAA mode.
|
||||||
GLuint m_resolvedFramebuffer;
|
static GLuint m_resolvedFramebuffer;
|
||||||
GLuint m_resolvedColorTexture;
|
static GLuint m_resolvedColorTexture;
|
||||||
GLuint m_resolvedDepthTexture;
|
static GLuint m_resolvedDepthTexture;
|
||||||
|
|
||||||
GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
static GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
||||||
XFBSource m_realXFBSource; // Only used in Real XFB mode
|
|
||||||
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
|
||||||
|
|
||||||
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FramebufferManager g_framebufferManager;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
#include "PostProcessing.h"
|
#include "PostProcessing.h"
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "XFB.h"
|
|
||||||
#include "OnScreenDisplay.h"
|
#include "OnScreenDisplay.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
@ -397,7 +396,7 @@ bool Renderer::Init()
|
||||||
bSuccess = false;
|
bSuccess = false;
|
||||||
|
|
||||||
// Initialize the FramebufferManager
|
// Initialize the FramebufferManager
|
||||||
g_framebufferManager.Init(s_target_width, s_target_height,
|
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
|
||||||
s_MSAASamples, s_MSAACoverageSamples);
|
s_MSAASamples, s_MSAACoverageSamples);
|
||||||
|
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
|
@ -529,7 +528,7 @@ void Renderer::Shutdown()
|
||||||
delete scrshotThread;
|
delete scrshotThread;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_framebufferManager.Shutdown();
|
delete g_framebuffer_manager;
|
||||||
|
|
||||||
#if defined _WIN32 || defined HAVE_AVCODEC
|
#if defined _WIN32 || defined HAVE_AVCODEC
|
||||||
if(s_bAVIDumping)
|
if(s_bAVIDumping)
|
||||||
|
@ -781,7 +780,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
|
||||||
// just use progressive.
|
// just use progressive.
|
||||||
if (g_ActiveConfig.bUseXFB)
|
if (g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
g_framebufferManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
FramebufferManager::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -893,8 +892,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
if (s_MSAASamples > 1)
|
if (s_MSAASamples > 1)
|
||||||
{
|
{
|
||||||
// Resolve our rectangle.
|
// Resolve our rectangle.
|
||||||
g_framebufferManager.GetEFBDepthTexture(efbPixelRc);
|
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_framebufferManager.GetResolvedFramebuffer());
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample from the center of the target region.
|
// Sample from the center of the target region.
|
||||||
|
@ -926,8 +925,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
if (s_MSAASamples > 1)
|
if (s_MSAASamples > 1)
|
||||||
{
|
{
|
||||||
// Resolve our rectangle.
|
// Resolve our rectangle.
|
||||||
g_framebufferManager.GetEFBColorTexture(efbPixelRc);
|
FramebufferManager::GetEFBColorTexture(efbPixelRc);
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_framebufferManager.GetResolvedFramebuffer());
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample from the center of the target region.
|
// Sample from the center of the target region.
|
||||||
|
@ -1125,7 +1124,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
|
|
||||||
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
||||||
u32 xfbCount = 0;
|
u32 xfbCount = 0;
|
||||||
const XFBSource** xfbSourceList = g_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pCopiedToXFB(false);
|
g_VideoInitialize.pCopiedToXFB(false);
|
||||||
|
@ -1164,7 +1163,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
// care of disabling it in that case. It returns false in case of no post processing.
|
// care of disabling it in that case. It returns false in case of no post processing.
|
||||||
bool applyShader = PostProcessing::ApplyShader();
|
bool applyShader = PostProcessing::ApplyShader();
|
||||||
|
|
||||||
const XFBSource* xfbSource = NULL;
|
const XFBSourceBase* xfbSource = NULL;
|
||||||
|
|
||||||
if(g_ActiveConfig.bUseXFB)
|
if(g_ActiveConfig.bUseXFB)
|
||||||
{
|
{
|
||||||
|
@ -1176,10 +1175,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
{
|
{
|
||||||
xfbSource = xfbSourceList[i];
|
xfbSource = xfbSourceList[i];
|
||||||
|
|
||||||
TargetRectangle sourceRc;
|
|
||||||
|
|
||||||
sourceRc = xfbSource->sourceRc;
|
|
||||||
|
|
||||||
MathUtil::Rectangle<float> drawRc;
|
MathUtil::Rectangle<float> drawRc;
|
||||||
|
|
||||||
if (!g_ActiveConfig.bUseRealXFB)
|
if (!g_ActiveConfig.bUseRealXFB)
|
||||||
|
@ -1214,57 +1209,25 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
// Tell the OSD Menu about the current internal resolution
|
// Tell the OSD Menu about the current internal resolution
|
||||||
OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight();
|
OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight();
|
||||||
|
|
||||||
// Texture map xfbSource->texture onto the main buffer
|
MathUtil::Rectangle<float> sourceRc;
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbSource->texture);
|
sourceRc.left = xfbSource->sourceRc.left;
|
||||||
|
sourceRc.right = xfbSource->sourceRc.right;
|
||||||
|
sourceRc.top = xfbSource->sourceRc.top;
|
||||||
|
sourceRc.bottom = xfbSource->sourceRc.bottom;
|
||||||
|
|
||||||
|
xfbSource->Draw(sourceRc, drawRc, 0, 0);
|
||||||
|
|
||||||
// We must call ApplyShader here even if no post proc is selected.
|
// We must call ApplyShader here even if no post proc is selected.
|
||||||
// It takes care of disabling it in that case. It returns false in
|
// It takes care of disabling it in that case. It returns false in
|
||||||
// case of no post processing.
|
// case of no post processing.
|
||||||
if (applyShader)
|
if (applyShader)
|
||||||
{
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glTexCoord2f(sourceRc.left, sourceRc.bottom);
|
|
||||||
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
|
|
||||||
glVertex2f(drawRc.left, drawRc.bottom);
|
|
||||||
|
|
||||||
glTexCoord2f(sourceRc.left, sourceRc.top);
|
|
||||||
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
|
|
||||||
glVertex2f(drawRc.left, drawRc.top);
|
|
||||||
|
|
||||||
glTexCoord2f(sourceRc.right, sourceRc.top);
|
|
||||||
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
|
|
||||||
glVertex2f(drawRc.right, drawRc.top);
|
|
||||||
|
|
||||||
glTexCoord2f(sourceRc.right, sourceRc.bottom);
|
|
||||||
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
|
|
||||||
glVertex2f(drawRc.right, drawRc.bottom);
|
|
||||||
glEnd();
|
|
||||||
PixelShaderCache::DisableShader();
|
PixelShaderCache::DisableShader();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glTexCoord2f(sourceRc.left, sourceRc.bottom);
|
|
||||||
glVertex2f(drawRc.left, drawRc.bottom);
|
|
||||||
|
|
||||||
glTexCoord2f(sourceRc.left, sourceRc.top);
|
|
||||||
glVertex2f(drawRc.left, drawRc.top);
|
|
||||||
|
|
||||||
glTexCoord2f(sourceRc.right, sourceRc.top);
|
|
||||||
glVertex2f(drawRc.right, drawRc.top);
|
|
||||||
|
|
||||||
glTexCoord2f(sourceRc.right, sourceRc.bottom);
|
|
||||||
glVertex2f(drawRc.right, drawRc.bottom);
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
GL_REPORT_ERRORD();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
||||||
GLuint read_texture = g_framebufferManager.ResolveAndGetRenderTarget(rc);
|
GLuint read_texture = FramebufferManager::ResolveAndGetRenderTarget(rc);
|
||||||
// Render to the real buffer now.
|
// Render to the real buffer now.
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
|
||||||
|
@ -1502,8 +1465,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
s_Fulltarget_width = s_target_width;
|
s_Fulltarget_width = s_target_width;
|
||||||
s_Fulltarget_height = s_target_height;
|
s_Fulltarget_height = s_target_height;
|
||||||
|
|
||||||
g_framebufferManager.Shutdown();
|
delete g_framebuffer_manager;
|
||||||
g_framebufferManager.Init(s_target_width, s_target_height,
|
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
|
||||||
s_MSAASamples, s_MSAACoverageSamples);
|
s_MSAASamples, s_MSAACoverageSamples);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
}
|
}
|
||||||
|
@ -1579,7 +1542,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
stats.ResetFrame();
|
stats.ResetFrame();
|
||||||
|
|
||||||
// Render to the framebuffer.
|
// Render to the framebuffer.
|
||||||
g_framebufferManager.SetFramebuffer(0);
|
FramebufferManager::SetFramebuffer(0);
|
||||||
|
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ files = [
|
||||||
'VertexShaderCache.cpp',
|
'VertexShaderCache.cpp',
|
||||||
'TextureConverter.cpp',
|
'TextureConverter.cpp',
|
||||||
'VertexManager.cpp',
|
'VertexManager.cpp',
|
||||||
'XFB.cpp',
|
|
||||||
'PostProcessing.cpp',
|
'PostProcessing.cpp',
|
||||||
'FramebufferManager.cpp',
|
'FramebufferManager.cpp',
|
||||||
'main.cpp',
|
'main.cpp',
|
||||||
|
|
|
@ -273,8 +273,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
|
|
||||||
// Make sure to resolve anything we need to read from.
|
// Make sure to resolve anything we need to read from.
|
||||||
const GLuint read_texture = bFromZBuffer ?
|
const GLuint read_texture = bFromZBuffer ?
|
||||||
g_framebufferManager.ResolveAndGetDepthTarget(source_rect) :
|
FramebufferManager::ResolveAndGetDepthTarget(source_rect) :
|
||||||
g_framebufferManager.ResolveAndGetRenderTarget(source_rect);
|
FramebufferManager::ResolveAndGetRenderTarget(source_rect);
|
||||||
|
|
||||||
// TODO: move
|
// TODO: move
|
||||||
const float xScale = Renderer::GetTargetScaleX();
|
const float xScale = Renderer::GetTargetScaleX();
|
||||||
|
@ -287,7 +287,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
if (s_TempFramebuffer == 0)
|
if (s_TempFramebuffer == 0)
|
||||||
glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
|
glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
|
||||||
|
|
||||||
g_framebufferManager.SetFramebuffer(s_TempFramebuffer);
|
FramebufferManager::SetFramebuffer(s_TempFramebuffer);
|
||||||
// Bind texture to temporary framebuffer
|
// Bind texture to temporary framebuffer
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
|
||||||
GL_REPORT_FBO_ERROR();
|
GL_REPORT_FBO_ERROR();
|
||||||
|
@ -334,7 +334,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
||||||
source_rect);
|
source_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_framebufferManager.SetFramebuffer(0);
|
FramebufferManager::SetFramebuffer(0);
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
DisableStage(0);
|
DisableStage(0);
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar
|
||||||
|
|
||||||
// switch to texture converter frame buffer
|
// switch to texture converter frame buffer
|
||||||
// attach render buffer as color destination
|
// attach render buffer as color destination
|
||||||
g_framebufferManager.SetFramebuffer(s_texConvFrameBuffer);
|
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
|
||||||
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
||||||
|
@ -264,7 +264,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
||||||
|
|
||||||
u8 *dest_ptr = Memory_GetPtr(address);
|
u8 *dest_ptr = Memory_GetPtr(address);
|
||||||
|
|
||||||
GLuint source_texture = bFromZBuffer ? g_framebufferManager.ResolveAndGetDepthTarget(source) : g_framebufferManager.ResolveAndGetRenderTarget(source);
|
GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source);
|
||||||
|
|
||||||
int width = (source.right - source.left) >> bScaleByHalf;
|
int width = (source.right - source.left) >> bScaleByHalf;
|
||||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||||
|
@ -310,7 +310,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
||||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||||
Renderer::ResetAPIState();
|
Renderer::ResetAPIState();
|
||||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
|
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
|
||||||
g_framebufferManager.SetFramebuffer(0);
|
FramebufferManager::SetFramebuffer(0);
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
TextureCache::DisableStage(0);
|
TextureCache::DisableStage(0);
|
||||||
|
@ -388,7 +388,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
|
||||||
{
|
{
|
||||||
Renderer::ResetAPIState();
|
Renderer::ResetAPIState();
|
||||||
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
||||||
g_framebufferManager.SetFramebuffer(0);
|
FramebufferManager::SetFramebuffer(0);
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
TextureCache::DisableStage(0);
|
TextureCache::DisableStage(0);
|
||||||
|
@ -413,7 +413,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
|
||||||
|
|
||||||
// switch to texture converter frame buffer
|
// switch to texture converter frame buffer
|
||||||
// attach destTexture as color destination
|
// attach destTexture as color destination
|
||||||
g_framebufferManager.SetFramebuffer(s_texConvFrameBuffer);
|
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
|
||||||
|
|
||||||
|
@ -460,7 +460,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
|
||||||
|
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
g_framebufferManager.SetFramebuffer(0);
|
FramebufferManager::SetFramebuffer(0);
|
||||||
|
|
||||||
Renderer::RestoreAPIState();
|
Renderer::RestoreAPIState();
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright (C) 2003 Dolphin Project.
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, version 2.0.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License 2.0 for more details.
|
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
|
||||||
// If not, see http://www.gnu.org/licenses/
|
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
|
||||||
// http://code.google.com/p/dolphin-emu/
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------------------
|
|
||||||
// This file handles the External Frame Buffer (XFB). The XFB is a storage point when the picture is resized
|
|
||||||
// by the system to the correct display format for output to the TV. In most cases its function can be
|
|
||||||
// supplemented by the equivalent adjustments in glScissor and glViewport (or their DirectX equivalents). But
|
|
||||||
// for some homebrew games these functions are necessary because the homebrew game communicate directly with
|
|
||||||
// them.
|
|
||||||
// ----------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "XFB.h"
|
|
||||||
#include "Render.h"
|
|
||||||
#include "TextureConverter.h"
|
|
||||||
#include "FramebufferManager.h"
|
|
||||||
|
|
||||||
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt)
|
|
||||||
{
|
|
||||||
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
|
||||||
TextureConverter::EncodeToRamYUYV(g_framebufferManager.ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, dstWd, dstHt);
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// Copyright (C) 2003 Dolphin Project.
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, version 2.0.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License 2.0 for more details.
|
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
|
||||||
// If not, see http://www.gnu.org/licenses/
|
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
|
||||||
// http://code.google.com/p/dolphin-emu/
|
|
||||||
|
|
||||||
#ifndef _XFB_H_
|
|
||||||
#define _XFB_H_
|
|
||||||
|
|
||||||
#include "GLUtil.h"
|
|
||||||
|
|
||||||
// write the EFB to the XFB
|
|
||||||
void XFB_Write(u8 *xfb_in_ram, const EFBRectangle& sourceRc, u32 dstWd, u32 dstHt);
|
|
||||||
|
|
||||||
#endif // _XFB_H_
|
|
|
@ -82,7 +82,6 @@ GFXConfigDialogOGL *m_ConfigFrame = NULL;
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
#include "VertexShaderCache.h"
|
#include "VertexShaderCache.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "XFB.h"
|
|
||||||
#include "XFBConvert.h"
|
#include "XFBConvert.h"
|
||||||
#include "CommandProcessor.h"
|
#include "CommandProcessor.h"
|
||||||
#include "PixelEngine.h"
|
#include "PixelEngine.h"
|
||||||
|
|
Loading…
Reference in New Issue