Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
implement emulate efb format changes on ogl backend
  • Loading branch information
degasus committed Jul 22, 2013
1 parent a963c62 commit c6ae08f
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 15 deletions.
118 changes: 116 additions & 2 deletions Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
Expand Up @@ -29,6 +29,12 @@ GLuint FramebufferManager::m_resolvedDepthTexture;

GLuint FramebufferManager::m_xfbFramebuffer;

// reinterpret pixel format
GLuint FramebufferManager::m_pixel_format_vao;
GLuint FramebufferManager::m_pixel_format_vbo;
SHADER FramebufferManager::m_pixel_format_shaders[2];


FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{
m_efbFramebuffer = 0;
Expand Down Expand Up @@ -65,10 +71,11 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
{
// EFB targets will be textures in non-MSAA mode.

GLuint glObj[2];
glGenTextures(2, glObj);
GLuint glObj[3];
glGenTextures(3, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
m_resolvedColorTexture = glObj[2]; // needed for pixel format convertion

glBindTexture(getFbType(), m_efbColor);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
Expand All @@ -77,6 +84,10 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glBindTexture(getFbType(), m_efbDepth);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(getFbType(), 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);

glBindTexture(getFbType(), m_resolvedColorTexture);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(getFbType(), 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

// Bind target textures to the EFB framebuffer.

Expand Down Expand Up @@ -164,6 +175,60 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glClearColor(0.f, 0.f, 0.f, 1.f);
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

// reinterpret pixel format
glGenBuffers(1, &m_pixel_format_vbo);
glGenVertexArrays(1, &m_pixel_format_vao);
glBindVertexArray(m_pixel_format_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_pixel_format_vbo);
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*2, NULL);

float vertices[] = {
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

char vs[] =
"ATTRIN vec2 rawpos;\n"
"void main(void) {\n"
" gl_Position = vec4(rawpos,0,1);\n"
"}\n";

char ps_rgba6_to_rgb8[] =
"uniform sampler2DRect samp9;\n"
"COLOROUT(ocol0)\n"
"void main()\n"
"{\n"
" ivec4 src6 = ivec4(round(texture2DRect(samp9, gl_FragCoord.xy) * 63.f));\n"
" ivec4 dst8;\n"
" dst8.r = (src6.r << 2) | (src6.g >> 4);\n"
" dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n"
" dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n"
" dst8.a = 255;\n"
" ocol0 = float4(dst8) / 255.f;\n"
"}";

char ps_rgb8_to_rgba6[] =
"uniform sampler2DRect samp9;\n"
"COLOROUT(ocol0)\n"
"void main()\n"
"{\n"
" ivec4 src8 = ivec4(round(texture2DRect(samp9, gl_FragCoord.xy) * 255.f));\n"
" ivec4 dst6;\n"
" dst6.r = src8.r >> 2;\n"
" dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n"
" dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n"
" dst6.a = src8.b & 0x3F;\n"
" ocol0 = float4(dst6) / 63.f;\n"
"}";

ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6);
ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8);

}

FramebufferManager::~FramebufferManager()
Expand Down Expand Up @@ -195,6 +260,12 @@ FramebufferManager::~FramebufferManager()
glDeleteRenderbuffers(2, glObj);
m_efbColor = 0;
m_efbDepth = 0;

// reinterpret pixel format
glDeleteVertexArrays(1, &m_pixel_format_vao);
glDeleteBuffers(1, &m_pixel_format_vbo);
m_pixel_format_shaders[0].Destroy();
m_pixel_format_shaders[1].Destroy();
}

GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
Expand Down Expand Up @@ -286,6 +357,49 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
return GetEFBDepthTexture(source_rect);
}

void FramebufferManager::ReinterpretPixelData(unsigned int convtype)
{
g_renderer->ResetAPIState();

GLuint src_texture = 0;

if(m_msaaSamples > 1)
{
// MSAA mode, so resolve first
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
glBlitFramebuffer(
0, 0, m_targetWidth, m_targetHeight,
0, 0, m_targetWidth, m_targetHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);

// Return to EFB.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_efbFramebuffer);

src_texture = m_resolvedColorTexture;
}
else
{
// non-MSAA mode, so switch textures
src_texture = m_efbColor;
m_efbColor = m_resolvedColorTexture;
m_resolvedColorTexture = src_texture;

// also switch them on fbo
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getFbType(), m_efbColor, 0);
}
glViewport(0,0, m_targetWidth, m_targetHeight);
glActiveTexture(GL_TEXTURE0 + 9);
glBindTexture(getFbType(), src_texture);

m_pixel_format_shaders[convtype ? 1 : 0].Bind();
glBindVertexArray(m_pixel_format_vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

g_renderer->RestoreAPIState();
}

XFBSource::~XFBSource()
{
glDeleteRenderbuffers(1, &renderbuf);
Expand Down
14 changes: 12 additions & 2 deletions Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.h
Expand Up @@ -7,6 +7,7 @@

#include "GLUtil.h"
#include "FramebufferManagerBase.h"
#include "ProgramShaderCache.h"
#include "Render.h"

// On the GameCube, the game sends a request for the graphics processor to
Expand Down Expand Up @@ -95,6 +96,10 @@ class FramebufferManager : public FramebufferManagerBase
// 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.
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);

// Convert EFB content on pixel format change.
// convtype=0 -> rgb8->rgba6, convtype=2 -> rgba6->rgb8
static void ReinterpretPixelData(unsigned int convtype);

private:
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
Expand All @@ -111,12 +116,17 @@ class FramebufferManager : public FramebufferManagerBase
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.
static GLuint m_resolvedFramebuffer;
// Only used in MSAA mode and to convert pixel format
static GLuint m_resolvedFramebuffer; // will be hot swapped with m_efbColor on non-msaa pixel format change
static GLuint m_resolvedColorTexture;
static GLuint m_resolvedDepthTexture;

static GLuint m_xfbFramebuffer; // Only used in MSAA mode

// For pixel format draw
static GLuint m_pixel_format_vbo;
static GLuint m_pixel_format_vao;
static SHADER m_pixel_format_shaders[2];
};

} // namespace OGL
Expand Down
24 changes: 14 additions & 10 deletions Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
Expand Up @@ -547,13 +547,6 @@ Renderer::Renderer()
// options while running
g_Config.bRunning = true;

if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;

// Initialize the FramebufferManager
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);

if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;

Expand Down Expand Up @@ -601,12 +594,12 @@ Renderer::~Renderer()
if (scrshotThread.joinable())
scrshotThread.join();
#endif

delete g_framebuffer_manager;
}

void Renderer::Shutdown()
{
delete g_framebuffer_manager;

g_Config.bRunning = false;
UpdateActiveConfig();

Expand All @@ -621,6 +614,10 @@ void Renderer::Shutdown()

void Renderer::Init()
{
// Initialize the FramebufferManager
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);

s_pfont = new RasterFont();

ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
Expand Down Expand Up @@ -1123,7 +1120,14 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE

void Renderer::ReinterpretPixelData(unsigned int convtype)
{
// TODO
if (convtype == 0 || convtype == 2)
{
FramebufferManager::ReinterpretPixelData(convtype);
}
else
{
ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
}
}

void Renderer::SetBlendMode(bool forceUpdate)
Expand Down
2 changes: 1 addition & 1 deletion Source/Plugins/Plugin_VideoOGL/Src/main.cpp
Expand Up @@ -130,7 +130,7 @@ void InitBackendInfo()
g_Config.backend_info.bUseMinimalMipCount = false;
g_Config.backend_info.bSupports3DVision = false;
//g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu dependent and must be set in renderer
g_Config.backend_info.bSupportsFormatReinterpretation = false;
g_Config.backend_info.bSupportsFormatReinterpretation = true;
g_Config.backend_info.bSupportsPixelLighting = true;
//g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer

Expand Down

0 comments on commit c6ae08f

Please sign in to comment.