OpenGL Renderer:
- Perform the RGBA6665 color space conversion of the 3D framebuffer on the GPU before pixel read back, and then read that 3D framebuffer directly.
This commit is contained in:
parent
9346ced34c
commit
d6ae36e068
|
@ -4220,9 +4220,15 @@ void GPUEngineA::_RenderLine_Layer(const u16 l, u16 *dstColorLine, const size_t
|
|||
// will be rendered as garbage pixels unless the DISPCNT.BG0_Enable flag is ignored.
|
||||
if (layerID == GPULayerID_BG0 && (this->_IORegisterMap->DISPCNT.BG0_3D != 0))
|
||||
{
|
||||
const FragmentColor *__restrict framebuffer3D = CurrentRenderer->GetFramebuffer();
|
||||
if (framebuffer3D == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo();
|
||||
const float customWidthScale = (float)dispInfo.customWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
const FragmentColor *__restrict srcLine = this->_3DFramebufferRGBA6665 + (dstLineIndex * dispInfo.customWidth);
|
||||
const FragmentColor *__restrict srcLine = framebuffer3D + (dstLineIndex * dispInfo.customWidth);
|
||||
u16 *__restrict dstColorLinePtr = dstColorLine;
|
||||
u8 *__restrict layerIDLine = this->_dstLayerID;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -292,7 +292,8 @@ enum OGLVertexAttributeID
|
|||
enum OGLTextureUnitID
|
||||
{
|
||||
// Main textures will always be on texture unit 0.
|
||||
OGLTextureUnitID_ToonTable = 1,
|
||||
OGLTextureUnitID_FinalColor = 1,
|
||||
OGLTextureUnitID_ToonTable,
|
||||
OGLTextureUnitID_GColor,
|
||||
OGLTextureUnitID_GDepth,
|
||||
OGLTextureUnitID_GPolyID,
|
||||
|
@ -425,13 +426,14 @@ struct OGLRenderRef
|
|||
GLuint texGPolyID;
|
||||
GLuint texGDepthStencilID;
|
||||
GLuint texPostprocessFogID;
|
||||
GLuint texFinalColorID;
|
||||
|
||||
GLuint rboMSGColorID;
|
||||
GLuint rboMSGDepthID;
|
||||
GLuint rboMSGPolyID;
|
||||
GLuint rboMSGFogAttrID;
|
||||
GLuint rboMSGDepthStencilID;
|
||||
GLuint rboMSPostprocessID;
|
||||
GLuint rboFramebufferRGBA6665ID;
|
||||
|
||||
GLuint fboClearImageID;
|
||||
GLuint fboRenderID;
|
||||
|
@ -446,10 +448,13 @@ struct OGLRenderRef
|
|||
|
||||
GLuint vertexEdgeMarkShaderID;
|
||||
GLuint vertexFogShaderID;
|
||||
GLuint vertexFramebufferOutputShaderID;
|
||||
GLuint fragmentEdgeMarkShaderID;
|
||||
GLuint fragmentFogShaderID;
|
||||
GLuint fragmentFramebufferOutputShaderID;
|
||||
GLuint programEdgeMarkID;
|
||||
GLuint programFogID;
|
||||
GLuint programFramebufferOutputID;
|
||||
|
||||
GLint uniformFramebufferSize;
|
||||
GLint uniformStateToonShadingMode;
|
||||
|
@ -566,6 +571,9 @@ private:
|
|||
unsigned int versionMinor;
|
||||
unsigned int versionRevision;
|
||||
|
||||
private:
|
||||
Render3DError _FlushFramebufferConvertOnCPU(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
|
||||
protected:
|
||||
// OpenGL-specific References
|
||||
OGLRenderRef *ref;
|
||||
|
@ -577,15 +585,16 @@ protected:
|
|||
bool isMultisampledFBOSupported;
|
||||
bool isShaderSupported;
|
||||
bool isVAOSupported;
|
||||
bool willConvertFramebufferOnGPU;
|
||||
|
||||
// Textures
|
||||
TexCacheItem *currTexture;
|
||||
|
||||
FragmentColor *_mappedFramebuffer;
|
||||
bool _pixelReadNeedsFinish;
|
||||
size_t _currentPolyIndex;
|
||||
|
||||
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcRGBA8888, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
Render3DError FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
|
||||
// OpenGL-specific methods
|
||||
virtual Render3DError CreateVBOs() = 0;
|
||||
|
@ -603,12 +612,19 @@ protected:
|
|||
virtual Render3DError InitTextures() = 0;
|
||||
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
|
||||
virtual Render3DError InitTables() = 0;
|
||||
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
|
||||
const std::string &edgeMarkFragShader,
|
||||
const std::string &fogVtxShader,
|
||||
const std::string &fogFragShader,
|
||||
const std::string &framebufferOutputVtxShader,
|
||||
const std::string &framebufferOutputFragShader) = 0;
|
||||
virtual Render3DError DestroyPostprocessingPrograms() = 0;
|
||||
virtual Render3DError InitEdgeMarkProgramBindings() = 0;
|
||||
virtual Render3DError InitEdgeMarkProgramShaderLocations() = 0;
|
||||
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader) = 0;
|
||||
virtual Render3DError InitFogProgramBindings() = 0;
|
||||
virtual Render3DError InitFogProgramShaderLocations() = 0;
|
||||
virtual Render3DError DestroyPostprocessingPrograms() = 0;
|
||||
virtual Render3DError InitFramebufferOutputProgramBindings() = 0;
|
||||
virtual Render3DError InitFramebufferOutputShaderLocations() = 0;
|
||||
|
||||
virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram) = 0;
|
||||
virtual Render3DError InitGeometryProgramBindings() = 0;
|
||||
|
@ -638,6 +654,8 @@ public:
|
|||
bool ValidateShaderProgramLink(GLuint theProgram) const;
|
||||
void GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const;
|
||||
void SetVersion(unsigned int major, unsigned int minor, unsigned int revision);
|
||||
|
||||
virtual FragmentColor* GetFramebuffer();
|
||||
};
|
||||
|
||||
class OpenGLRenderer_1_2 : public OpenGLRenderer
|
||||
|
@ -663,12 +681,19 @@ protected:
|
|||
virtual Render3DError InitGeometryProgramBindings();
|
||||
virtual Render3DError InitGeometryProgramShaderLocations();
|
||||
virtual void DestroyGeometryProgram();
|
||||
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
|
||||
const std::string &edgeMarkFragShader,
|
||||
const std::string &fogVtxShader,
|
||||
const std::string &fogFragShader,
|
||||
const std::string &framebufferOutputVtxShader,
|
||||
const std::string &framebufferOutputFragShader);
|
||||
virtual Render3DError DestroyPostprocessingPrograms();
|
||||
virtual Render3DError InitEdgeMarkProgramBindings();
|
||||
virtual Render3DError InitEdgeMarkProgramShaderLocations();
|
||||
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader);
|
||||
virtual Render3DError InitFogProgramBindings();
|
||||
virtual Render3DError InitFogProgramShaderLocations();
|
||||
virtual Render3DError DestroyPostprocessingPrograms();
|
||||
virtual Render3DError InitFramebufferOutputProgramBindings();
|
||||
virtual Render3DError InitFramebufferOutputShaderLocations();
|
||||
|
||||
virtual Render3DError CreateToonTable();
|
||||
virtual Render3DError DestroyToonTable();
|
||||
|
@ -728,19 +753,14 @@ class OpenGLRenderer_1_5 : public OpenGLRenderer_1_4
|
|||
protected:
|
||||
virtual Render3DError CreateVBOs();
|
||||
virtual void DestroyVBOs();
|
||||
virtual Render3DError CreatePBOs();
|
||||
virtual void DestroyPBOs();
|
||||
virtual Render3DError CreateVAOs();
|
||||
|
||||
virtual Render3DError EnableVertexAttributes();
|
||||
virtual Render3DError DisableVertexAttributes();
|
||||
virtual Render3DError BeginRender(const GFX3D &engine);
|
||||
virtual Render3DError ReadBackPixels();
|
||||
|
||||
|
||||
public:
|
||||
~OpenGLRenderer_1_5();
|
||||
|
||||
virtual Render3DError RenderFinish();
|
||||
};
|
||||
|
||||
class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5
|
||||
|
@ -748,12 +768,19 @@ class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5
|
|||
protected:
|
||||
virtual Render3DError InitExtensions();
|
||||
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
|
||||
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
|
||||
const std::string &edgeMarkFragShader,
|
||||
const std::string &fogVtxShader,
|
||||
const std::string &fogFragShader,
|
||||
const std::string &framebufferOutputVtxShader,
|
||||
const std::string &framebufferOutputFragShader);
|
||||
virtual Render3DError DestroyPostprocessingPrograms();
|
||||
virtual Render3DError InitEdgeMarkProgramBindings();
|
||||
virtual Render3DError InitEdgeMarkProgramShaderLocations();
|
||||
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader);
|
||||
virtual Render3DError InitFogProgramBindings();
|
||||
virtual Render3DError InitFogProgramShaderLocations();
|
||||
virtual Render3DError DestroyPostprocessingPrograms();
|
||||
virtual Render3DError InitFramebufferOutputProgramBindings();
|
||||
virtual Render3DError InitFramebufferOutputShaderLocations();
|
||||
|
||||
virtual Render3DError EnableVertexAttributes();
|
||||
virtual Render3DError DisableVertexAttributes();
|
||||
|
|
|
@ -439,6 +439,44 @@ static const char *FogFragShader_150 = {"\
|
|||
}\n\
|
||||
"};
|
||||
|
||||
// Vertex shader for the final framebuffer, GLSL 1.50
|
||||
static const char *FramebufferOutputVtxShader_150 = {"\
|
||||
#version 150\n\
|
||||
\n\
|
||||
in vec2 inPosition;\n\
|
||||
in vec2 inTexCoord0;\n\
|
||||
out vec2 texCoord;\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
texCoord = inTexCoord0;\n\
|
||||
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
// Fragment shader for the final framebuffer, GLSL 1.50
|
||||
static const char *FramebufferOutputFragShader_150 = {"\
|
||||
#version 150\n\
|
||||
\n\
|
||||
in vec2 texCoord;\n\
|
||||
\n\
|
||||
uniform sampler2D texInFragColor;\n\
|
||||
\n\
|
||||
out vec4 outFragColor;\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
// Note that we swap B and R since pixel readbacks are done in BGRA format for fastest\n\
|
||||
// performance. The final color is still in RGBA format.\n\
|
||||
vec4 colorRGBA6665 = texture(texInFragColor, texCoord).bgra;\n\
|
||||
colorRGBA6665 = floor((colorRGBA6665 * 255.0) + 0.5);\n\
|
||||
colorRGBA6665.rgb = floor(colorRGBA6665.rgb / 4.0);\n\
|
||||
colorRGBA6665.a = floor(colorRGBA6665.a / 8.0);\n\
|
||||
\n\
|
||||
outFragColor = (colorRGBA6665 / 255.0);\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr)
|
||||
{
|
||||
if (IsVersionSupported(3, 2, 0))
|
||||
|
@ -471,6 +509,9 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
|
|||
// Load and create shaders. Return on any error, since v3.2 Core Profile makes shaders mandatory.
|
||||
this->isShaderSupported = true;
|
||||
|
||||
// OpenGL v3.2 Core Profile should have all the necessary features to be able to convert the framebuffer.
|
||||
this->willConvertFramebufferOnGPU = true;
|
||||
|
||||
std::string vertexShaderProgram;
|
||||
std::string fragmentShaderProgram;
|
||||
error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram);
|
||||
|
@ -491,7 +532,14 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
|
|||
std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_150);
|
||||
std::string fogVtxShaderString = std::string(FogVtxShader_150);
|
||||
std::string fogFragShaderString = std::string(FogFragShader_150);
|
||||
error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString, edgeMarkFragShaderString, fogVtxShaderString, fogFragShaderString);
|
||||
std::string framebufferOutputVtxShaderString = std::string(FramebufferOutputVtxShader_150);
|
||||
std::string framebufferOutputFragShaderString = std::string(FramebufferOutputFragShader_150);
|
||||
error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString,
|
||||
edgeMarkFragShaderString,
|
||||
fogVtxShaderString,
|
||||
fogFragShaderString,
|
||||
framebufferOutputVtxShaderString,
|
||||
framebufferOutputFragShaderString);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->DestroyGeometryProgram();
|
||||
|
@ -551,6 +599,8 @@ Render3DError OpenGLRenderer_3_2::InitEdgeMarkProgramShaderLocations()
|
|||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
glUseProgram(OGLRef.programEdgeMarkID);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programEdgeMarkID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
|
@ -576,6 +626,8 @@ Render3DError OpenGLRenderer_3_2::InitFogProgramShaderLocations()
|
|||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
glUseProgram(OGLRef.programFogID);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programFogID, "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programFogID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
|
@ -589,6 +641,28 @@ Render3DError OpenGLRenderer_3_2::InitFogProgramShaderLocations()
|
|||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_3_2::InitFramebufferOutputProgramBindings()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
glBindAttribLocation(OGLRef.programFramebufferOutputID, OGLVertexAttributeID_Position, "inPosition");
|
||||
glBindAttribLocation(OGLRef.programFramebufferOutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
|
||||
glBindFragDataLocation(OGLRef.programFramebufferOutputID, 0, "outFragColor");
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_3_2::InitFramebufferOutputShaderLocations()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
glUseProgram(OGLRef.programFramebufferOutputID);
|
||||
|
||||
const GLint uniformTexFinalColor = glGetUniformLocation(OGLRef.programFramebufferOutputID, "texInFragColor");
|
||||
glUniform1i(uniformTexFinalColor, OGLTextureUnitID_FinalColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
@ -600,6 +674,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
glGenTextures(1, &OGLRef.texCIPolyID);
|
||||
glGenTextures(1, &OGLRef.texCIDepthStencilID);
|
||||
|
||||
glGenTextures(1, &OGLRef.texFinalColorID);
|
||||
glGenTextures(1, &OGLRef.texGColorID);
|
||||
glGenTextures(1, &OGLRef.texGDepthID);
|
||||
glGenTextures(1, &OGLRef.texGFogAttrID);
|
||||
|
@ -607,6 +682,14 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
glGenTextures(1, &OGLRef.texGDepthStencilID);
|
||||
glGenTextures(1, &OGLRef.texPostprocessFogID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
|
||||
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, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
@ -694,6 +777,11 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Set up RBOs
|
||||
glGenRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFramebufferRGBA6665ID);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
|
||||
|
||||
// Set up FBOs
|
||||
glGenFramebuffers(1, &OGLRef.fboClearImageID);
|
||||
glGenFramebuffers(1, &OGLRef.fboRenderID);
|
||||
|
@ -725,6 +813,8 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
glDeleteTextures(1, &OGLRef.texGFogAttrID);
|
||||
glDeleteTextures(1, &OGLRef.texGDepthStencilID);
|
||||
glDeleteTextures(1, &OGLRef.texPostprocessFogID);
|
||||
glDeleteTextures(1, &OGLRef.texFinalColorID);
|
||||
glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID);
|
||||
|
||||
OGLRef.fboClearImageID = 0;
|
||||
OGLRef.fboRenderID = 0;
|
||||
|
@ -762,6 +852,8 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
glDeleteTextures(1, &OGLRef.texGFogAttrID);
|
||||
glDeleteTextures(1, &OGLRef.texGDepthStencilID);
|
||||
glDeleteTextures(1, &OGLRef.texPostprocessFogID);
|
||||
glDeleteTextures(1, &OGLRef.texFinalColorID);
|
||||
glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID);
|
||||
|
||||
OGLRef.fboClearImageID = 0;
|
||||
OGLRef.fboRenderID = 0;
|
||||
|
@ -775,6 +867,8 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, OGLRef.rboFramebufferRGBA6665ID);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
|
@ -795,6 +889,8 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs()
|
|||
glDeleteTextures(1, &OGLRef.texGFogAttrID);
|
||||
glDeleteTextures(1, &OGLRef.texGDepthStencilID);
|
||||
glDeleteTextures(1, &OGLRef.texPostprocessFogID);
|
||||
glDeleteTextures(1, &OGLRef.texFinalColorID);
|
||||
glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID);
|
||||
|
||||
OGLRef.fboClearImageID = 0;
|
||||
OGLRef.fboRenderID = 0;
|
||||
|
@ -837,6 +933,8 @@ void OpenGLRenderer_3_2::DestroyFBOs()
|
|||
glDeleteTextures(1, &OGLRef.texGFogAttrID);
|
||||
glDeleteTextures(1, &OGLRef.texGDepthStencilID);
|
||||
glDeleteTextures(1, &OGLRef.texPostprocessFogID);
|
||||
glDeleteTextures(1, &OGLRef.texFinalColorID);
|
||||
glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID);
|
||||
|
||||
OGLRef.fboClearImageID = 0;
|
||||
OGLRef.fboRenderID = 0;
|
||||
|
@ -1018,6 +1116,8 @@ Render3DError OpenGLRenderer_3_2::InitGeometryProgramShaderLocations()
|
|||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
glUseProgram(OGLRef.programGeometryID);
|
||||
|
||||
// Set up render states UBO
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programGeometryID, "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
@ -1144,6 +1244,53 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO()
|
|||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_3_2::ReadBackPixels()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
// Perform the RGBA6665 color space conversion while we're still on the GPU so
|
||||
// that we can avoid having to do it on the CPU.
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
||||
glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT2);
|
||||
|
||||
glUseProgram(OGLRef.programFramebufferOutputID);
|
||||
|
||||
glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
|
||||
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Read back the pixels.
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT2);
|
||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
// Set the read and draw target buffers back to color attachment 0, which is always the default.
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
this->_pixelReadNeedsFinish = true;
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
@ -1565,6 +1712,16 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h)
|
|||
return OGLERROR_BEGINGL_FAILED;
|
||||
}
|
||||
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
||||
|
@ -1584,6 +1741,9 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h)
|
|||
glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFramebufferRGBA6665ID);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, w, h);
|
||||
|
||||
if (this->isMultisampledFBOSupported)
|
||||
{
|
||||
GLint maxSamples = 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2008-2015 DeSmuME team
|
||||
Copyright (C) 2008-2016 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
|
||||
|
@ -65,6 +65,8 @@ protected:
|
|||
virtual Render3DError InitEdgeMarkProgramShaderLocations();
|
||||
virtual Render3DError InitFogProgramBindings();
|
||||
virtual Render3DError InitFogProgramShaderLocations();
|
||||
virtual Render3DError InitFramebufferOutputProgramBindings();
|
||||
virtual Render3DError InitFramebufferOutputShaderLocations();
|
||||
virtual Render3DError CreateFBOs();
|
||||
virtual void DestroyFBOs();
|
||||
virtual Render3DError CreateMultisampledFBO();
|
||||
|
@ -81,6 +83,7 @@ protected:
|
|||
virtual Render3DError EnableVertexAttributes();
|
||||
virtual Render3DError DisableVertexAttributes();
|
||||
virtual Render3DError DownsampleFBO();
|
||||
virtual Render3DError ReadBackPixels();
|
||||
virtual Render3DError BeginRender(const GFX3D &engine);
|
||||
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
|
||||
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2009-2015 DeSmuME team
|
||||
Copyright (C) 2009-2016 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
|
||||
|
@ -1961,9 +1961,8 @@ Render3DError SoftRasterizerRenderer::EndRender(const u64 frameCount)
|
|||
this->RenderEdgeMarkingAndFog(this->postprocessParam[0]);
|
||||
}
|
||||
|
||||
FragmentColor *framebufferRGBA6665 = (this->_willFlushFramebufferRGBA6665) ? GPU->GetEngineMain()->Get3DFramebufferRGBA6665() : NULL;
|
||||
u16 *framebufferRGBA5551 = (this->_willFlushFramebufferRGBA5551) ? GPU->GetEngineMain()->Get3DFramebufferRGBA5551() : NULL;
|
||||
this->FlushFramebuffer(framebufferRGBA6665, framebufferRGBA5551);
|
||||
this->FlushFramebuffer(this->_framebufferColor, NULL, framebufferRGBA5551);
|
||||
}
|
||||
|
||||
return RENDER3DERROR_NOERR;
|
||||
|
@ -2007,9 +2006,8 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
|
|||
}
|
||||
}
|
||||
|
||||
FragmentColor *framebufferRGBA6665 = (this->_willFlushFramebufferRGBA6665) ? GPU->GetEngineMain()->Get3DFramebufferRGBA6665() : NULL;
|
||||
u16 *framebufferRGBA5551 = (this->_willFlushFramebufferRGBA5551) ? GPU->GetEngineMain()->Get3DFramebufferRGBA5551() : NULL;
|
||||
this->FlushFramebuffer(framebufferRGBA6665, framebufferRGBA5551);
|
||||
this->FlushFramebuffer(this->_framebufferColor, NULL, framebufferRGBA5551);
|
||||
|
||||
GPU->GetEventHandler()->DidRender3DEnd();
|
||||
return RENDER3DERROR_NOERR;
|
||||
|
@ -2017,19 +2015,14 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
|
|||
|
||||
Render3DError SoftRasterizerRenderer::SetFramebufferSize(size_t w, size_t h)
|
||||
{
|
||||
if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT)
|
||||
Render3DError error = Render3D::SetFramebufferSize(w, h);
|
||||
if (error != RENDER3DERROR_NOERR)
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
FragmentAttributesBuffer *oldFramebufferAttributes = this->_framebufferAttributes;
|
||||
FragmentAttributesBuffer *newFramebufferAttributes = new FragmentAttributesBuffer(w * h);
|
||||
|
||||
this->_framebufferWidth = w;
|
||||
this->_framebufferHeight = h;
|
||||
this->_framebufferColorSizeBytes = w * h * sizeof(FragmentColor);
|
||||
this->_framebufferColor = GPU->GetEngineMain()->Get3DFramebufferRGBA6665();
|
||||
this->_framebufferAttributes = newFramebufferAttributes;
|
||||
delete this->_framebufferAttributes;
|
||||
this->_framebufferAttributes = new FragmentAttributesBuffer(w * h);
|
||||
|
||||
if (rasterizerCores == 0 || rasterizerCores == 1)
|
||||
{
|
||||
|
@ -2046,9 +2039,7 @@ Render3DError SoftRasterizerRenderer::SetFramebufferSize(size_t w, size_t h)
|
|||
postprocessParam[i].endLine = (i < rasterizerCores - 1) ? (i + 1) * linesPerThread : h;
|
||||
}
|
||||
}
|
||||
|
||||
delete oldFramebufferAttributes;
|
||||
|
||||
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2008-2015 DeSmuME team
|
||||
Copyright (C) 2008-2016 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
|
||||
|
@ -274,7 +274,7 @@ Render3DError Render3D::SetFramebufferSize(size_t w, size_t h)
|
|||
this->_framebufferWidth = w;
|
||||
this->_framebufferHeight = h;
|
||||
this->_framebufferColorSizeBytes = w * h * sizeof(FragmentColor);
|
||||
this->_framebufferColor = GPU->GetEngineMain()->Get3DFramebufferRGBA6665();
|
||||
this->_framebufferColor = GPU->GetEngineMain()->Get3DFramebufferRGBA6665(); // Just use the buffer that is already present on the main GPU engine
|
||||
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
@ -316,13 +316,18 @@ Render3DError Render3D::EndRender(const u64 frameCount)
|
|||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError Render3D::FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551)
|
||||
Render3DError Render3D::FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551)
|
||||
{
|
||||
if ( (dstRGBA6665 == NULL) && (dstRGBA5551 == NULL) )
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
if (dstRGBA5551 != NULL)
|
||||
{
|
||||
for (size_t i = 0; i < (this->_framebufferWidth * this->_framebufferHeight); i++)
|
||||
{
|
||||
dstRGBA5551[i] = R6G6B6TORGB15(this->_framebufferColor[i].r, this->_framebufferColor[i].g, this->_framebufferColor[i].b) | ((this->_framebufferColor[i].a == 0) ? 0x0000 : 0x8000);
|
||||
dstRGBA5551[i] = R6G6B6TORGB15(srcFramebuffer[i].r, srcFramebuffer[i].g, srcFramebuffer[i].b) | ((srcFramebuffer[i].a == 0) ? 0x0000 : 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,7 +459,6 @@ Render3DError Render3D::Reset()
|
|||
if (this->_framebufferColor != NULL)
|
||||
{
|
||||
memset(this->_framebufferColor, 0, this->_framebufferColorSizeBytes);
|
||||
this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551());
|
||||
}
|
||||
|
||||
memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer));
|
||||
|
@ -515,15 +519,13 @@ Render3DError Render3D::VramReconfigureSignal()
|
|||
|
||||
#ifdef ENABLE_SSE2
|
||||
|
||||
Render3DError Render3D_SSE2::FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551)
|
||||
Render3DError Render3D_SSE2::FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551)
|
||||
{
|
||||
if ( (dstRGBA6665 == NULL) && (dstRGBA5551 == NULL) )
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
const __m128i zero_vec128 = _mm_setzero_si128();
|
||||
|
||||
size_t i = 0;
|
||||
const size_t pixCount = this->_framebufferWidth * this->_framebufferHeight;
|
||||
const size_t ssePixCount = pixCount - (pixCount % 4);
|
||||
|
@ -533,18 +535,18 @@ Render3DError Render3D_SSE2::FlushFramebuffer(FragmentColor *__restrict dstRGBA6
|
|||
for (; i < ssePixCount; i += 4)
|
||||
{
|
||||
// Convert to RGBA5551
|
||||
__m128i color = _mm_load_si128((__m128i *)(this->_framebufferColor + i));
|
||||
__m128i r = _mm_and_si128(color, _mm_set1_epi32(0x0000003E)); // Read from R
|
||||
r = _mm_srli_epi32(r, 1); // Shift to R
|
||||
__m128i color5551 = _mm_load_si128((__m128i *)(srcFramebuffer + i));
|
||||
__m128i r = _mm_and_si128(color5551, _mm_set1_epi32(0x0000003E)); // Read from R
|
||||
r = _mm_srli_epi32(r, 1); // Shift to R
|
||||
|
||||
__m128i g = _mm_and_si128(color, _mm_set1_epi32(0x00003E00)); // Read from G
|
||||
g = _mm_srli_epi32(g, 4); // Shift in G
|
||||
__m128i g = _mm_and_si128(color5551, _mm_set1_epi32(0x00003E00)); // Read from G
|
||||
g = _mm_srli_epi32(g, 4); // Shift in G
|
||||
|
||||
__m128i b = _mm_and_si128(color, _mm_set1_epi32(0x003E0000)); // Read from B
|
||||
b = _mm_srli_epi32(b, 7); // Shift to B
|
||||
__m128i b = _mm_and_si128(color5551, _mm_set1_epi32(0x003E0000)); // Read from B
|
||||
b = _mm_srli_epi32(b, 7); // Shift to B
|
||||
|
||||
__m128i a = _mm_and_si128(color, _mm_set1_epi32(0xFF000000)); // Read from A
|
||||
a = _mm_cmpeq_epi32(a, zero_vec128); // Determine A
|
||||
__m128i a = _mm_and_si128(color5551, _mm_set1_epi32(0xFF000000)); // Read from A
|
||||
a = _mm_cmpeq_epi32(a, _mm_setzero_si128()); // Determine A
|
||||
|
||||
// From here on, we're going to do an SSE2 trick to pack 32-bit down to unsigned
|
||||
// 16-bit. Since SSE2 only has packssdw (signed saturated 16-bit pack), using
|
||||
|
@ -558,21 +560,21 @@ Render3DError Render3D_SSE2::FlushFramebuffer(FragmentColor *__restrict dstRGBA6
|
|||
// packssdw, then shift the bit back to its original position. Then we por the
|
||||
// alpha vector with the post-packed color vector to get the final color.
|
||||
|
||||
a = _mm_andnot_si128(a, _mm_set1_epi32(0x00004000)); // Mask out the bit before A
|
||||
a = _mm_packs_epi32(a, zero_vec128); // Pack 32-bit down to 16-bit
|
||||
a = _mm_slli_epi16(a, 1); // Shift the A bit back to where it needs to be
|
||||
a = _mm_andnot_si128(a, _mm_set1_epi32(0x00004000)); // Mask out the bit before A
|
||||
a = _mm_packs_epi32(a, _mm_setzero_si128()); // Pack 32-bit down to 16-bit
|
||||
a = _mm_slli_epi16(a, 1); // Shift the A bit back to where it needs to be
|
||||
|
||||
// Assemble the RGB colors, pack the 32-bit color into a signed 16-bit color, then por the alpha bit back in.
|
||||
color = _mm_or_si128(_mm_or_si128(r, g), b);
|
||||
color = _mm_packs_epi32(color, zero_vec128);
|
||||
color = _mm_or_si128(color, a);
|
||||
color5551 = _mm_or_si128(_mm_or_si128(r, g), b);
|
||||
color5551 = _mm_packs_epi32(color5551, _mm_setzero_si128());
|
||||
color5551 = _mm_or_si128(color5551, a);
|
||||
|
||||
_mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color);
|
||||
_mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551);
|
||||
}
|
||||
|
||||
for (; i < pixCount; i++)
|
||||
{
|
||||
dstRGBA5551[i] = R6G6B6TORGB15(this->_framebufferColor[i].r, this->_framebufferColor[i].g, this->_framebufferColor[i].b) | ((this->_framebufferColor[i].a == 0) ? 0x0000 : 0x8000);
|
||||
dstRGBA5551[i] = R6G6B6TORGB15(srcFramebuffer[i].r, srcFramebuffer[i].g, srcFramebuffer[i].b) | ((srcFramebuffer[i].a == 0) ? 0x0000 : 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2007-2015 DeSmuME team
|
||||
Copyright (C) 2007-2016 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
|
||||
|
@ -122,7 +122,7 @@ protected:
|
|||
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
|
||||
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);
|
||||
virtual Render3DError EndRender(const u64 frameCount);
|
||||
virtual Render3DError FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
virtual Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
|
||||
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
|
||||
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const;
|
||||
|
@ -140,7 +140,6 @@ public:
|
|||
RendererID GetRenderID();
|
||||
std::string GetName();
|
||||
|
||||
FragmentColor* GetFramebuffer();
|
||||
size_t GetFramebufferWidth();
|
||||
size_t GetFramebufferHeight();
|
||||
|
||||
|
@ -159,6 +158,7 @@ public:
|
|||
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h); // Called whenever the output framebuffer size changes.
|
||||
|
||||
virtual FragmentColor* GetFramebuffer();
|
||||
virtual void GetFramebufferFlushStates(bool &willFlushRGBA6665, bool &willFlushRGBA5551);
|
||||
virtual void SetFramebufferFlushStates(bool willFlushRGBA6665, bool willFlushRGBA5551);
|
||||
};
|
||||
|
@ -168,7 +168,7 @@ public:
|
|||
class Render3D_SSE2 : public Render3D
|
||||
{
|
||||
protected:
|
||||
virtual Render3DError FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
virtual Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);
|
||||
|
||||
public:
|
||||
virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState);
|
||||
|
|
Loading…
Reference in New Issue