mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-19 12:19:40 -06:00
implement emulate efb format changes on ogl backend
This commit is contained in:
@ -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;
|
||||
@ -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);
|
||||
@ -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.
|
||||
|
||||
@ -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()
|
||||
@ -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)
|
||||
@ -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);
|
||||
|
Reference in New Issue
Block a user