OpenGL Renderer:
- New feature: Support multisample antialiasing (MSAA). This can be enabled through the CommonSettings.GFX3D_Renderer_Multisample setting (disabled by default). - Do some cleanup of the init code.
This commit is contained in:
parent
c15911a1b1
commit
72eb5e6d12
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2008-2012 DeSmuME team
|
||||
Copyright (C) 2008-2013 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -489,6 +489,7 @@ extern struct TCommonSettings {
|
|||
, GFX3D_Texture(true)
|
||||
, GFX3D_LineHack(true)
|
||||
, GFX3D_Zelda_Shadow_Depth_Hack(0)
|
||||
, GFX3D_Renderer_Multisample(false)
|
||||
, UseExtBIOS(false)
|
||||
, SWIFromBIOS(false)
|
||||
, PatchSWI3(false)
|
||||
|
@ -539,6 +540,7 @@ extern struct TCommonSettings {
|
|||
bool GFX3D_Texture;
|
||||
bool GFX3D_LineHack;
|
||||
int GFX3D_Zelda_Shadow_Depth_Hack;
|
||||
bool GFX3D_Renderer_Multisample;
|
||||
|
||||
bool UseExtBIOS;
|
||||
char ARM9BIOS[256];
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include "OGLRender.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define VERT_INDEX_BUFFER_SIZE 8192
|
||||
#define OGLRENDER_MAX_MULTISAMPLES 16
|
||||
#define VERT_INDEX_BUFFER_SIZE 8192
|
||||
|
||||
bool (*oglrender_init)() = NULL;
|
||||
bool (*oglrender_beginOpenGL)() = NULL;
|
||||
|
@ -126,6 +127,7 @@ static GLfloat polyAlpha = 1.0f;
|
|||
static bool isVBOSupported = false;
|
||||
static bool isPBOSupported = false;
|
||||
static bool isFBOSupported = false;
|
||||
static bool isMultisampledFBOSupported = false;
|
||||
static bool isShaderSupported = false;
|
||||
static bool isVAOSupported = false;
|
||||
|
||||
|
@ -141,6 +143,12 @@ static GLuint texClearImageColorID;
|
|||
static GLuint texClearImageDepthStencilID;
|
||||
static GLuint fboClearImageID;
|
||||
|
||||
// Multisampled FBO
|
||||
static GLuint rboMultisampleColorID;
|
||||
static GLuint rboMultisampleDepthStencilID;
|
||||
static GLuint fboMultisampleRenderID;
|
||||
static GLuint selectedRenderingFBO = 0;
|
||||
|
||||
// Shader states
|
||||
static GLuint vertexShaderID;
|
||||
static GLuint fragmentShaderID;
|
||||
|
@ -324,6 +332,15 @@ static void* execReadPixelsTask(void *arg)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Downsample the multisampled FBO to the main framebuffer
|
||||
if (selectedRenderingFBO == fboMultisampleRenderID)
|
||||
{
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, selectedRenderingFBO);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||
glBlitFramebufferEXT(0, 0, 256, 192, 0, 0, 256, 192, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, 256, 192, GL_BGRA, GL_UNSIGNED_BYTE, pixBuffer);
|
||||
}
|
||||
|
||||
|
@ -383,99 +400,143 @@ static void _xglDisable(GLenum cap) {
|
|||
CTASSERT((cap-0x0B00)<0x100); \
|
||||
_xglDisable(cap); }
|
||||
|
||||
#define NOSHADERS(s) { isShaderSupported = false; INFO("%s\nOpenGL: Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n", s); return; }
|
||||
static bool OGLValidateShaderCompile(GLuint theShader)
|
||||
{
|
||||
bool isCompileValid = false;
|
||||
GLint status = GL_FALSE;
|
||||
|
||||
#define SHADER_COMPCHECK(s, t) { \
|
||||
GLint status = GL_TRUE; \
|
||||
glGetShaderiv(s, GL_COMPILE_STATUS, &status); \
|
||||
if(status != GL_TRUE) \
|
||||
{ \
|
||||
GLint logSize; \
|
||||
GLchar *log; \
|
||||
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &logSize); \
|
||||
log = new GLchar[logSize]; \
|
||||
glGetShaderInfoLog(s, logSize, &logSize, log); \
|
||||
INFO("OpenGL: SEVERE - FAILED TO COMPILE SHADER : %s\n", log); \
|
||||
delete[] log; \
|
||||
if(s)glDeleteShader(s); \
|
||||
NOSHADERS("OpenGL: Failed to compile the "t" shader."); \
|
||||
} \
|
||||
glGetShaderiv(theShader, GL_COMPILE_STATUS, &status);
|
||||
if(status == GL_TRUE)
|
||||
{
|
||||
isCompileValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint logSize;
|
||||
GLchar *log = NULL;
|
||||
|
||||
glGetShaderiv(theShader, GL_INFO_LOG_LENGTH, &logSize);
|
||||
log = new GLchar[logSize];
|
||||
glGetShaderInfoLog(theShader, logSize, &logSize, log);
|
||||
|
||||
INFO("OpenGL: SEVERE - FAILED TO COMPILE SHADER : %s\n", log);
|
||||
delete[] log;
|
||||
}
|
||||
|
||||
return isCompileValid;
|
||||
}
|
||||
|
||||
#define PROGRAM_COMPCHECK(p, s1, s2) { \
|
||||
GLint status = GL_TRUE; \
|
||||
glGetProgramiv(p, GL_LINK_STATUS, &status); \
|
||||
if(status != GL_TRUE) \
|
||||
{ \
|
||||
GLint logSize; \
|
||||
GLchar *log; \
|
||||
glGetProgramiv(p, GL_INFO_LOG_LENGTH, &logSize); \
|
||||
log = new GLchar[logSize]; \
|
||||
glGetProgramInfoLog(p, logSize, &logSize, log); \
|
||||
INFO("OpenGL: SEVERE - FAILED TO LINK SHADER PROGRAM : %s\n", log); \
|
||||
delete[] log; \
|
||||
if(s1)glDeleteShader(s1); \
|
||||
if(s2)glDeleteShader(s2); \
|
||||
NOSHADERS("OpenGL: Failed to link the shader program."); \
|
||||
} \
|
||||
static bool OGLValidateShaderProgramLink(GLuint theProgram)
|
||||
{
|
||||
bool isLinkValid = false;
|
||||
GLint status = GL_FALSE;
|
||||
|
||||
glGetProgramiv(theProgram, GL_LINK_STATUS, &status);
|
||||
if(status == GL_TRUE)
|
||||
{
|
||||
isLinkValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint logSize;
|
||||
GLchar *log = NULL;
|
||||
|
||||
glGetProgramiv(theProgram, GL_INFO_LOG_LENGTH, &logSize);
|
||||
log = new GLchar[logSize];
|
||||
glGetProgramInfoLog(theProgram, logSize, &logSize, log);
|
||||
|
||||
INFO("OpenGL: SEVERE - FAILED TO LINK SHADER PROGRAM : %s\n", log);
|
||||
delete[] log;
|
||||
}
|
||||
|
||||
return isLinkValid;
|
||||
}
|
||||
|
||||
/* Shaders init */
|
||||
|
||||
static void OGLInitShaders(const char *oglExtensionString)
|
||||
static bool OGLInitShaders(const char *oglExtensionString)
|
||||
{
|
||||
isShaderSupported = true;
|
||||
|
||||
#ifdef HAVE_LIBOSMESA
|
||||
NOSHADERS("OpenGL: Shaders aren't supported by OSMesa.");
|
||||
#endif
|
||||
|
||||
/* This check is just plain wrong. */
|
||||
/* It will always pass if you've OpenGL 2.0 or later, */
|
||||
/* even if your GFX card doesn't support shaders. */
|
||||
/* if (glCreateShader == NULL || //use ==NULL instead of !func to avoid always true warnings for some systems
|
||||
glShaderSource == NULL ||
|
||||
glCompileShader == NULL ||
|
||||
glCreateProgram == NULL ||
|
||||
glAttachShader == NULL ||
|
||||
glLinkProgram == NULL ||
|
||||
glUseProgram == NULL ||
|
||||
glGetShaderInfoLog == NULL)
|
||||
NOSHADERS("Shaders aren't supported by your system.");*/
|
||||
|
||||
#if !defined(GL_ARB_shader_objects) || \
|
||||
!defined(GL_ARB_vertex_shader) || \
|
||||
!defined(GL_ARB_fragment_shader) || \
|
||||
!defined(GL_ARB_vertex_program)
|
||||
|
||||
NOSHADERS("OpenGL: Shaders are unsupported.");
|
||||
bool isFeatureSupported = false;
|
||||
#else
|
||||
if ((strstr(oglExtensionString, "GL_ARB_shader_objects") == NULL) ||
|
||||
(strstr(oglExtensionString, "GL_ARB_vertex_shader") == NULL) ||
|
||||
(strstr(oglExtensionString, "GL_ARB_fragment_shader") == NULL) ||
|
||||
(strstr(oglExtensionString, "GL_ARB_vertex_program") == NULL) )
|
||||
NOSHADERS("OpenGL: Shaders are unsupported.");
|
||||
bool isFeatureSupported = (strstr(oglExtensionString, "GL_ARB_shader_objects") == NULL ||
|
||||
strstr(oglExtensionString, "GL_ARB_vertex_shader") == NULL ||
|
||||
strstr(oglExtensionString, "GL_ARB_fragment_shader") == NULL ||
|
||||
strstr(oglExtensionString, "GL_ARB_vertex_program") == NULL) ? false : true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBOSMESA
|
||||
isFeatureSupported = false;
|
||||
INFO("%s\nOpenGL: Shaders aren't supported by OSMesa.\n");
|
||||
|
||||
#endif
|
||||
|
||||
if (!isFeatureSupported)
|
||||
{
|
||||
INFO("OpenGL: Shaders are unsupported. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
if(!vertexShaderID)
|
||||
NOSHADERS("OpenGL: Failed to create the vertex shader.");
|
||||
{
|
||||
INFO("%s\nOpenGL: Failed to create the vertex shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
glShaderSource(vertexShaderID, 1, (const GLchar**)&vertexShader, NULL);
|
||||
glCompileShader(vertexShaderID);
|
||||
SHADER_COMPCHECK(vertexShaderID, "vertex");
|
||||
if (!OGLValidateShaderCompile(vertexShaderID))
|
||||
{
|
||||
INFO("%s\nOpenGL: Failed to compile the vertex shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
|
||||
glDeleteShader(vertexShaderID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if(!fragmentShaderID)
|
||||
NOSHADERS("OpenGL: Failed to create the fragment shader.");
|
||||
{
|
||||
INFO("%s\nOpenGL: Failed to create the fragment shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
|
||||
glDeleteShader(vertexShaderID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
glShaderSource(fragmentShaderID, 1, (const GLchar**)&fragmentShader, NULL);
|
||||
glCompileShader(fragmentShaderID);
|
||||
SHADER_COMPCHECK(fragmentShaderID, "fragment");
|
||||
if (!OGLValidateShaderCompile(fragmentShaderID))
|
||||
{
|
||||
INFO("%s\nOpenGL: Failed to compile the fragment shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
|
||||
glDeleteShader(vertexShaderID);
|
||||
glDeleteShader(fragmentShaderID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
shaderProgram = glCreateProgram();
|
||||
if(!shaderProgram)
|
||||
NOSHADERS("OpenGL: Failed to create the shader program.");
|
||||
{
|
||||
INFO("%s\nOpenGL: Failed to create the shader program. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
|
||||
glDeleteShader(vertexShaderID);
|
||||
glDeleteShader(fragmentShaderID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
glAttachShader(shaderProgram, vertexShaderID);
|
||||
glAttachShader(shaderProgram, fragmentShaderID);
|
||||
|
@ -485,12 +546,169 @@ static void OGLInitShaders(const char *oglExtensionString)
|
|||
glBindAttribLocation(shaderProgram, OGLVertexAttributeID_Color, "inColor");
|
||||
|
||||
glLinkProgram(shaderProgram);
|
||||
PROGRAM_COMPCHECK(shaderProgram, vertexShaderID, fragmentShaderID);
|
||||
if (!OGLValidateShaderProgramLink(shaderProgram))
|
||||
{
|
||||
INFO("OpenGL: Failed to link the shader program. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
|
||||
|
||||
glDetachShader(shaderProgram, vertexShaderID);
|
||||
glDetachShader(shaderProgram, fragmentShaderID);
|
||||
glDeleteProgram(shaderProgram);
|
||||
glDeleteShader(vertexShaderID);
|
||||
glDeleteShader(fragmentShaderID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
glValidateProgram(shaderProgram);
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
INFO("OpenGL: Successfully created shaders.\n");
|
||||
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
static bool OGLInitFBOs(const char *oglExtensionString)
|
||||
{
|
||||
// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
|
||||
#if !defined(GL_EXT_framebuffer_object) || \
|
||||
!defined(GL_EXT_framebuffer_blit) || \
|
||||
!defined(GL_EXT_packed_depth_stencil)
|
||||
|
||||
bool isFeatureSupported = false;
|
||||
#else
|
||||
bool isFeatureSupported = (strstr(oglExtensionString, "GL_EXT_framebuffer_object") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_framebuffer_blit") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_packed_depth_stencil") == NULL) ? false : true;
|
||||
#endif
|
||||
if (!isFeatureSupported)
|
||||
{
|
||||
INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n");
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
// Set up FBO render targets
|
||||
glGenTextures(1, &texClearImageColorID);
|
||||
glGenTextures(1, &texClearImageDepthStencilID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ClearImage);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texClearImageColorID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texClearImageDepthStencilID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, 256, 192, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Set up FBOs
|
||||
glGenFramebuffersEXT(1, &fboClearImageID);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboClearImageID);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texClearImageColorID, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texClearImageDepthStencilID, 0);
|
||||
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glDeleteFramebuffersEXT(1, &fboClearImageID);
|
||||
glDeleteTextures(1, &texClearImageColorID);
|
||||
glDeleteTextures(1, &texClearImageDepthStencilID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
INFO("OpenGL: Successfully created FBOs.\n");
|
||||
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
static bool OGLInitMultisampledFBO(const char *oglExtensionString)
|
||||
{
|
||||
// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
|
||||
#if !defined(GL_EXT_framebuffer_object) || \
|
||||
!defined(GL_EXT_framebuffer_multisample) || \
|
||||
!defined(GL_EXT_framebuffer_blit) || \
|
||||
!defined(GL_EXT_packed_depth_stencil)
|
||||
|
||||
bool isFeatureSupported = false;
|
||||
#else
|
||||
bool isFeatureSupported = (strstr(oglExtensionString, "GL_EXT_framebuffer_object") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_framebuffer_multisample") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_framebuffer_blit") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_packed_depth_stencil") == NULL) ? false : true;
|
||||
#endif
|
||||
if (!isFeatureSupported)
|
||||
{
|
||||
INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
// Check the maximum number of samples that the GPU supports and use that.
|
||||
// Since our target resolution is only 256x192 pixels, using the most samples
|
||||
// possible is the best thing to do.
|
||||
GLint maxSamples = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
|
||||
|
||||
if (maxSamples < 2)
|
||||
{
|
||||
INFO("OpenGL: GPU does not support at least 2x multisampled FBOs. Multisample antialiasing will be disabled.\n");
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
else if (maxSamples > OGLRENDER_MAX_MULTISAMPLES)
|
||||
{
|
||||
maxSamples = OGLRENDER_MAX_MULTISAMPLES;
|
||||
}
|
||||
|
||||
// Set up FBO render targets
|
||||
glGenRenderbuffersEXT(1, &rboMultisampleColorID);
|
||||
glGenRenderbuffersEXT(1, &rboMultisampleDepthStencilID);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboMultisampleColorID);
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, 256, 192);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboMultisampleDepthStencilID);
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, 256, 192);
|
||||
|
||||
// Set up multisampled rendering FBO
|
||||
glGenFramebuffersEXT(1, &fboMultisampleRenderID);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboMultisampleRenderID);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rboMultisampleColorID);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboMultisampleDepthStencilID);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboMultisampleDepthStencilID);
|
||||
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n");
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glDeleteFramebuffersEXT(1, &fboMultisampleRenderID);
|
||||
glDeleteRenderbuffersEXT(1, &rboMultisampleColorID);
|
||||
glDeleteRenderbuffersEXT(1, &rboMultisampleDepthStencilID);
|
||||
|
||||
isFeatureSupported = false;
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
INFO("OpenGL: Successfully created multisampled FBO.\n");
|
||||
|
||||
return isFeatureSupported;
|
||||
}
|
||||
|
||||
//=================================================
|
||||
|
@ -808,7 +1026,7 @@ static char OGLInit(void)
|
|||
}
|
||||
|
||||
// Shader Setup
|
||||
OGLInitShaders(oglExtensionString);
|
||||
isShaderSupported = OGLInitShaders(oglExtensionString);
|
||||
if(isShaderSupported)
|
||||
{
|
||||
// The toon table is a special 1D texture where each pixel corresponds
|
||||
|
@ -887,69 +1105,10 @@ static char OGLInit(void)
|
|||
}
|
||||
|
||||
// FBO Setup
|
||||
// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
|
||||
#if !defined(GL_EXT_framebuffer_object) || \
|
||||
!defined(GL_EXT_framebuffer_blit) || \
|
||||
!defined(GL_EXT_packed_depth_stencil)
|
||||
isFBOSupported = OGLInitFBOs(oglExtensionString);
|
||||
|
||||
isFBOSupported = false;
|
||||
#else
|
||||
isFBOSupported = (strstr(oglExtensionString, "GL_EXT_framebuffer_object") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_framebuffer_blit") == NULL ||
|
||||
strstr(oglExtensionString, "GL_EXT_packed_depth_stencil") == NULL) ? false : true;
|
||||
#endif
|
||||
if (isFBOSupported)
|
||||
{
|
||||
// Set up FBO render targets
|
||||
glGenTextures(1, &texClearImageColorID);
|
||||
glGenTextures(1, &texClearImageDepthStencilID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ClearImage);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texClearImageColorID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texClearImageDepthStencilID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, 256, 192, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Set up FBOs
|
||||
glGenFramebuffersEXT(1, &fboClearImageID);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboClearImageID);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texClearImageColorID, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texClearImageDepthStencilID, 0);
|
||||
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
INFO("OpenGL: Successfully created FBOs.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
|
||||
isFBOSupported = false;
|
||||
|
||||
glDeleteFramebuffersEXT(1, &fboClearImageID);
|
||||
glDeleteTextures(1, &texClearImageColorID);
|
||||
glDeleteTextures(1, &texClearImageDepthStencilID);
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n");
|
||||
}
|
||||
// Multisampled FBO Setup
|
||||
isMultisampledFBOSupported = OGLInitMultisampledFBO(oglExtensionString);
|
||||
|
||||
ENDGL();
|
||||
|
||||
|
@ -1062,6 +1221,17 @@ static void OGLClose()
|
|||
isFBOSupported = false;
|
||||
}
|
||||
|
||||
if (isMultisampledFBOSupported)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glDeleteFramebuffersEXT(1, &fboMultisampleRenderID);
|
||||
glDeleteRenderbuffersEXT(1, &rboMultisampleColorID);
|
||||
glDeleteRenderbuffersEXT(1, &rboMultisampleDepthStencilID);
|
||||
|
||||
selectedRenderingFBO = 0;
|
||||
isMultisampledFBOSupported = false;
|
||||
}
|
||||
|
||||
//kill the tex cache to free all the texture ids
|
||||
TexCache_Reset();
|
||||
|
||||
|
@ -1357,6 +1527,17 @@ static void Control()
|
|||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (isMultisampledFBOSupported && CommonSettings.GFX3D_Renderer_Multisample)
|
||||
{
|
||||
selectedRenderingFBO = fboMultisampleRenderID;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedRenderingFBO = 0;
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, selectedRenderingFBO);
|
||||
}
|
||||
|
||||
static void GL_ReadFramebuffer()
|
||||
|
@ -1375,6 +1556,15 @@ static void GL_ReadFramebuffer()
|
|||
{
|
||||
if(!BEGINGL()) return;
|
||||
|
||||
// Downsample the multisampled FBO to the main framebuffer
|
||||
if (selectedRenderingFBO == fboMultisampleRenderID)
|
||||
{
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, selectedRenderingFBO);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||
glBlitFramebufferEXT(0, 0, 256, 192, 0, 0, 256, 192, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboRenderDataID[bufferIndex]);
|
||||
glReadPixels(0, 0, 256, 192, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
|
||||
|
@ -1476,7 +1666,7 @@ static void HandleClearImage()
|
|||
// Copy the clear image to the main framebuffer
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboClearImageID);
|
||||
glBlitFramebufferEXT(0, 0, pixelsPerLine, lineCount, 0, 0, pixelsPerLine, lineCount, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, selectedRenderingFBO);
|
||||
}
|
||||
|
||||
static void OGLRender()
|
||||
|
|
Loading…
Reference in New Issue