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:
Jordan Woyak
2010-11-14 23:31:53 +00:00
parent 2378b443c1
commit 0da42fcca7
27 changed files with 840 additions and 1319 deletions

View File

@ -10,8 +10,7 @@ set(SRCS Src/BPFunctions.cpp
Src/TextureCache.cpp
Src/TextureConverter.cpp
Src/VertexShaderCache.cpp
Src/VertexManager.cpp
Src/XFB.cpp)
Src/VertexManager.cpp)
set(LIBS videocommon
GLEW

View File

@ -781,14 +781,6 @@
RelativePath=".\Src\VertexShaderCache.h"
>
</File>
<File
RelativePath=".\Src\XFB.cpp"
>
</File>
<File
RelativePath=".\Src\XFB.h"
>
</File>
</Filter>
<Filter
Name="GUI"

View File

@ -24,7 +24,6 @@
#include "TextureCache.h"
#include "TextureConverter.h"
#include "VertexShaderManager.h"
#include "XFB.h"
#include "main.h"
namespace BPFunctions

View File

@ -19,17 +19,39 @@
#include "FramebufferManager.h"
#include "TextureConverter.h"
#include "XFB.h"
#include "Render.h"
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_targetHeight = targetHeight;
m_msaaSamples = msaaSamples;
m_msaaCoverageSamples = msaaCoverageSamples;
@ -147,7 +169,7 @@ void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples
// EFB framebuffer is currently bound.
}
void FramebufferManager::Shutdown()
FramebufferManager::~FramebufferManager()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@ -164,11 +186,9 @@ void FramebufferManager::Shutdown()
glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture;
glObj[2] = m_realXFBSource.texture;
glDeleteTextures(3, glObj);
glDeleteTextures(2, glObj);
m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0;
m_realXFBSource.texture = 0;
glObj[0] = m_efbColor;
glObj[1] = m_efbDepth;
@ -178,15 +198,9 @@ void FramebufferManager::Shutdown()
glDeleteRenderbuffersEXT(2, glObj);
m_efbColor = 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)
{
@ -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)
{
@ -246,84 +260,7 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc) cons
}
}
void FramebufferManager::CopyToXFB(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)
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
if (!xfb_in_ram)
@ -332,199 +269,8 @@ void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
return;
}
XFB_Write(xfb_in_ram, sourceRc, 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];
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
}
void FramebufferManager::SetFramebuffer(GLuint fb)
@ -543,4 +289,110 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
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;
}

View File

@ -18,8 +18,8 @@
#ifndef _FRAMEBUFFERMANAGER_H_
#define _FRAMEBUFFERMANAGER_H_
#include <list>
#include "GLUtil.h"
#include "FramebufferManagerBase.h"
// 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
@ -52,116 +52,70 @@
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
// 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
{
XFBSource() :
texture(0)
{}
void CopyEFB();
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
u32 srcAddr;
u32 srcWidth;
u32 srcHeight;
GLuint texture;
int texWidth;
int texHeight;
TargetRectangle sourceRc;
const GLuint texture;
};
class FramebufferManager
class FramebufferManager : public FramebufferManagerBase
{
public:
FramebufferManager() :
m_efbFramebuffer(0),
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);
FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
~FramebufferManager();
// To get the EFB in texture form, these functions may have to transfer
// the EFB to a resolved texture first.
GLuint GetEFBColorTexture(const EFBRectangle& sourceRc) const;
GLuint GetEFBDepthTexture(const EFBRectangle& sourceRc) const;
static GLuint GetEFBColorTexture(const EFBRectangle& sourceRc);
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.
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.
// Thus, this call may be expensive. Don't repeat it unnecessarily.
// 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.
GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
static GLuint ResolveAndGetRenderTarget(const EFBRectangle &rect);
// 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.
GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
private:
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
struct VirtualXFB
{
// Address and size in GameCube RAM
u32 xfbAddr;
u32 xfbWidth;
u32 xfbHeight;
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
XFBSource xfbSource;
};
static int m_targetWidth;
static int m_targetHeight;
static int m_msaaSamples;
static int m_msaaCoverageSamples;
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);
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
static GLuint m_efbFramebuffer;
static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode.
GLuint m_resolvedFramebuffer;
GLuint m_resolvedColorTexture;
GLuint m_resolvedDepthTexture;
static GLuint m_resolvedFramebuffer;
static GLuint m_resolvedColorTexture;
static GLuint m_resolvedDepthTexture;
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];
static GLuint m_xfbFramebuffer; // Only used in MSAA mode
};
extern FramebufferManager g_framebufferManager;
#endif

View File

@ -52,7 +52,6 @@
#include "VertexLoader.h"
#include "PostProcessing.h"
#include "TextureConverter.h"
#include "XFB.h"
#include "OnScreenDisplay.h"
#include "Timer.h"
#include "StringUtil.h"
@ -397,7 +396,7 @@ bool Renderer::Init()
bSuccess = false;
// 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);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
@ -529,7 +528,7 @@ void Renderer::Shutdown()
delete scrshotThread;
#endif
g_framebufferManager.Shutdown();
delete g_framebuffer_manager;
#if defined _WIN32 || defined HAVE_AVCODEC
if(s_bAVIDumping)
@ -781,7 +780,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
// just use progressive.
if (g_ActiveConfig.bUseXFB)
{
g_framebufferManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
FramebufferManager::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
}
else
{
@ -893,8 +892,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
if (s_MSAASamples > 1)
{
// Resolve our rectangle.
g_framebufferManager.GetEFBDepthTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_framebufferManager.GetResolvedFramebuffer());
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
}
// 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)
{
// Resolve our rectangle.
g_framebufferManager.GetEFBColorTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_framebufferManager.GetResolvedFramebuffer());
FramebufferManager::GetEFBColorTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
}
// 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;
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)
{
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.
bool applyShader = PostProcessing::ApplyShader();
const XFBSource* xfbSource = NULL;
const XFBSourceBase* xfbSource = NULL;
if(g_ActiveConfig.bUseXFB)
{
@ -1176,10 +1175,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
{
xfbSource = xfbSourceList[i];
TargetRectangle sourceRc;
sourceRc = xfbSource->sourceRc;
MathUtil::Rectangle<float> drawRc;
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
OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight();
// Texture map xfbSource->texture onto the main buffer
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbSource->texture);
MathUtil::Rectangle<float> sourceRc;
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.
// It takes care of disabling it in that case. It returns false in
// case of no post processing.
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();
}
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
{
TargetRectangle targetRc = ConvertEFBRectangle(rc);
GLuint read_texture = g_framebufferManager.ResolveAndGetRenderTarget(rc);
GLuint read_texture = FramebufferManager::ResolveAndGetRenderTarget(rc);
// Render to the real buffer now.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
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_height = s_target_height;
g_framebufferManager.Shutdown();
g_framebufferManager.Init(s_target_width, s_target_height,
delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
@ -1579,7 +1542,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
stats.ResetFrame();
// Render to the framebuffer.
g_framebufferManager.SetFramebuffer(0);
FramebufferManager::SetFramebuffer(0);
GL_REPORT_ERRORD();

View File

@ -16,7 +16,6 @@ files = [
'VertexShaderCache.cpp',
'TextureConverter.cpp',
'VertexManager.cpp',
'XFB.cpp',
'PostProcessing.cpp',
'FramebufferManager.cpp',
'main.cpp',

View File

@ -273,8 +273,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
// Make sure to resolve anything we need to read from.
const GLuint read_texture = bFromZBuffer ?
g_framebufferManager.ResolveAndGetDepthTarget(source_rect) :
g_framebufferManager.ResolveAndGetRenderTarget(source_rect);
FramebufferManager::ResolveAndGetDepthTarget(source_rect) :
FramebufferManager::ResolveAndGetRenderTarget(source_rect);
// TODO: move
const float xScale = Renderer::GetTargetScaleX();
@ -287,7 +287,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
if (s_TempFramebuffer == 0)
glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
g_framebufferManager.SetFramebuffer(s_TempFramebuffer);
FramebufferManager::SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
GL_REPORT_FBO_ERROR();
@ -334,7 +334,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
source_rect);
}
g_framebufferManager.SetFramebuffer(0);
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
DisableStage(0);

View File

@ -174,7 +174,7 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar
// switch to texture converter frame buffer
// attach render buffer as color destination
g_framebufferManager.SetFramebuffer(s_texConvFrameBuffer);
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
glBindRenderbufferEXT(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);
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 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);
Renderer::ResetAPIState();
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
g_framebufferManager.SetFramebuffer(0);
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0);
@ -388,7 +388,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
{
Renderer::ResetAPIState();
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
g_framebufferManager.SetFramebuffer(0);
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0);
@ -413,7 +413,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
// switch to texture converter frame buffer
// attach destTexture as color destination
g_framebufferManager.SetFramebuffer(s_texConvFrameBuffer);
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
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();
g_framebufferManager.SetFramebuffer(0);
FramebufferManager::SetFramebuffer(0);
Renderer::RestoreAPIState();
GL_REPORT_ERRORD();

View File

@ -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);
}

View File

@ -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_

View File

@ -82,7 +82,6 @@ GFXConfigDialogOGL *m_ConfigFrame = NULL;
#include "PixelShaderManager.h"
#include "VertexShaderCache.h"
#include "VertexShaderManager.h"
#include "XFB.h"
#include "XFBConvert.h"
#include "CommandProcessor.h"
#include "PixelEngine.h"