Fixup: + getters, - redundant makecurrents/trackers

This commit is contained in:
tfarley 2016-05-02 20:02:30 -04:00
parent e2c74e8ea5
commit d7cc5bdcc1
7 changed files with 170 additions and 97 deletions

View File

@ -149,8 +149,6 @@ void RasterizerOpenGL::DrawTriangles() {
if (vertex_batch.empty()) if (vertex_batch.empty())
return; return;
state.MakeCurrent();
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
// Sync and bind the framebuffer surfaces // Sync and bind the framebuffer surfaces
@ -247,8 +245,6 @@ void RasterizerOpenGL::DrawTriangles() {
void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
state.MakeCurrent();
switch(id) { switch(id) {
// Culling // Culling
case PICA_REG_INDEX(cull_mode): case PICA_REG_INDEX(cull_mode):
@ -612,17 +608,15 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
SurfaceType dst_type = CachedSurface::GetFormatType(dst_surface->pixel_format); SurfaceType dst_type = CachedSurface::GetFormatType(dst_surface->pixel_format);
OpenGLState* old_state = OpenGLState::GetCurrentState(); OpenGLState* cur_state = OpenGLState::GetCurrentState();
utility_state.MakeCurrent(); OpenGLState old_state = OpenGLState::ApplyTransferState(0, cur_state->GetReadFramebuffer(), dst_surface->texture.handle, framebuffer.handle);
utility_state.SetDrawFramebuffer(framebuffer.handle);
if (dst_type == SurfaceType::Color || dst_type == SurfaceType::Texture) { if (dst_type == SurfaceType::Color || dst_type == SurfaceType::Texture) {
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_surface->texture.handle, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_surface->texture.handle, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
@ -640,7 +634,7 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
color_values[2] = config.value_24bit_b / 255.0f; color_values[2] = config.value_24bit_b / 255.0f;
break; break;
default: default:
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
} else if (config.fill_32bit) { } else if (config.fill_32bit) {
@ -654,7 +648,7 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
color_values[3] = (value & 0xFF) / 255.0f; color_values[3] = (value & 0xFF) / 255.0f;
break; break;
default: default:
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
} else { } else {
@ -694,12 +688,11 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
color_values[1] = (value_16bit & 0xFF) / 255.0f; color_values[1] = (value_16bit & 0xFF) / 255.0f;
break; break;
default: default:
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
} }
utility_state.SetColorMask(true, true, true, true);
glClearBufferfv(GL_COLOR, 0, color_values); glClearBufferfv(GL_COLOR, 0, color_values);
} else if (dst_type == SurfaceType::Depth) { } else if (dst_type == SurfaceType::Depth) {
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
@ -707,7 +700,7 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
@ -718,26 +711,23 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
value_float = config.value_32bit / 16777215.0f; // 2^24 - 1 value_float = config.value_32bit / 16777215.0f; // 2^24 - 1
} }
utility_state.SetDepthWriteMask(true);
glClearBufferfv(GL_DEPTH, 0, &value_float); glClearBufferfv(GL_DEPTH, 0, &value_float);
} else if (dst_type == SurfaceType::DepthStencil) { } else if (dst_type == SurfaceType::DepthStencil) {
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst_surface->texture.handle, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst_surface->texture.handle, 0);
if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
GLfloat value_float = (config.value_32bit & 0xFFFFFF) / 16777215.0f; // 2^24 - 1 GLfloat value_float = (config.value_32bit & 0xFFFFFF) / 16777215.0f; // 2^24 - 1
GLint value_int = (config.value_32bit >> 24); GLint value_int = (config.value_32bit >> 24);
utility_state.SetDepthWriteMask(true);
utility_state.SetStencilWriteMask(true);
glClearBufferfi(GL_DEPTH_STENCIL, 0, value_float, value_int); glClearBufferfi(GL_DEPTH_STENCIL, 0, value_float, value_int);
} }
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
dst_surface->dirty = true; dst_surface->dirty = true;
res_cache.FlushRegion(dst_surface->addr, dst_surface->size, dst_surface, true); res_cache.FlushRegion(dst_surface->addr, dst_surface->size, dst_surface, true);
@ -821,8 +811,6 @@ void RasterizerOpenGL::SetShader() {
PicaShaderConfig config = PicaShaderConfig::CurrentConfig(); PicaShaderConfig config = PicaShaderConfig::CurrentConfig();
std::unique_ptr<PicaShader> shader = std::make_unique<PicaShader>(); std::unique_ptr<PicaShader> shader = std::make_unique<PicaShader>();
state.MakeCurrent();
// Find (or generate) the GLSL shader for the current TEV state // Find (or generate) the GLSL shader for the current TEV state
auto cached_shader = shader_cache.find(config); auto cached_shader = shader_cache.find(config);
if (cached_shader != shader_cache.end()) { if (cached_shader != shader_cache.end()) {
@ -921,18 +909,20 @@ void RasterizerOpenGL::SyncBlendEnabled() {
void RasterizerOpenGL::SyncBlendFuncs() { void RasterizerOpenGL::SyncBlendFuncs() {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
state.SetBlendFunc(PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_rgb), state.SetBlendFunc(std::make_tuple<>(
PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_rgb),
PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_rgb), PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_rgb),
PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_a), PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_a),
PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_a)); PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_a)));
} }
void RasterizerOpenGL::SyncBlendColor() { void RasterizerOpenGL::SyncBlendColor() {
auto blend_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.output_merger.blend_const.raw); auto blend_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.output_merger.blend_const.raw);
state.SetBlendColor(blend_color[0], state.SetBlendColor(std::make_tuple<>(
blend_color[0],
blend_color[1], blend_color[1],
blend_color[2], blend_color[2],
blend_color[3]); blend_color[3]));
} }
void RasterizerOpenGL::SyncAlphaTest() { void RasterizerOpenGL::SyncAlphaTest() {
@ -954,10 +944,11 @@ void RasterizerOpenGL::SyncColorWriteMask() {
return (regs.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE : GL_FALSE; return (regs.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE : GL_FALSE;
}; };
state.SetColorMask(IsColorWriteEnabled(regs.output_merger.red_enable), state.SetColorMask(std::make_tuple<>(
IsColorWriteEnabled(regs.output_merger.red_enable),
IsColorWriteEnabled(regs.output_merger.green_enable), IsColorWriteEnabled(regs.output_merger.green_enable),
IsColorWriteEnabled(regs.output_merger.blue_enable), IsColorWriteEnabled(regs.output_merger.blue_enable),
IsColorWriteEnabled(regs.output_merger.alpha_enable)); IsColorWriteEnabled(regs.output_merger.alpha_enable)));
} }
void RasterizerOpenGL::SyncStencilWriteMask() { void RasterizerOpenGL::SyncStencilWriteMask() {
@ -977,12 +968,14 @@ void RasterizerOpenGL::SyncDepthWriteMask() {
void RasterizerOpenGL::SyncStencilTest() { void RasterizerOpenGL::SyncStencilTest() {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
state.SetStencilTestEnabled(regs.output_merger.stencil_test.enable && regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8); state.SetStencilTestEnabled(regs.output_merger.stencil_test.enable && regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8);
state.SetStencilFunc(PicaToGL::CompareFunc(regs.output_merger.stencil_test.func), state.SetStencilFunc(std::make_tuple<>(
PicaToGL::CompareFunc(regs.output_merger.stencil_test.func),
regs.output_merger.stencil_test.reference_value, regs.output_merger.stencil_test.reference_value,
regs.output_merger.stencil_test.input_mask); regs.output_merger.stencil_test.input_mask));
state.SetStencilOp(PicaToGL::StencilOp(regs.output_merger.stencil_test.action_stencil_fail), state.SetStencilOp(std::make_tuple<>(
PicaToGL::StencilOp(regs.output_merger.stencil_test.action_stencil_fail),
PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_fail), PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_fail),
PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_pass)); PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_pass)));
} }
void RasterizerOpenGL::SyncDepthTest() { void RasterizerOpenGL::SyncDepthTest() {

View File

@ -351,7 +351,6 @@ private:
void SyncLightPosition(int light_index); void SyncLightPosition(int light_index);
OpenGLState state; OpenGLState state;
OpenGLState utility_state;
RasterizerCacheOpenGL res_cache; RasterizerCacheOpenGL res_cache;

View File

@ -105,15 +105,7 @@ static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width,
bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedSurface::SurfaceType type, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) { bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedSurface::SurfaceType type, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) {
using SurfaceType = CachedSurface::SurfaceType; using SurfaceType = CachedSurface::SurfaceType;
OpenGLState* old_state = OpenGLState::GetCurrentState(); OpenGLState old_state = OpenGLState::ApplyTransferState(src_tex, transfer_framebuffers[0].handle, dst_tex, transfer_framebuffers[1].handle);
utility_state.MakeCurrent();
// Make sure textures aren't bound to texture units, since going to bind them to framebuffer components
OpenGLState::ResetTexture(src_tex);
OpenGLState::ResetTexture(dst_tex);
utility_state.SetReadFramebuffer(transfer_framebuffers[0].handle);
utility_state.SetDrawFramebuffer(transfer_framebuffers[1].handle);
u32 buffers = 0; u32 buffers = 0;
@ -146,12 +138,12 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS
} }
if (OpenGLState::CheckBoundFBStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (OpenGLState::CheckBoundFBStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (OpenGLState::CheckBoundFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return false; return false;
} }
@ -159,7 +151,7 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS
dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom,
buffers, buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); buffers, buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST);
old_state->MakeCurrent(); OpenGLState::UndoTransferState(old_state);
return true; return true;
} }
@ -178,11 +170,11 @@ void RasterizerCacheOpenGL::AllocateSurfaceTexture(GLuint texture, CachedSurface
// Allocate an uninitialized texture of appropriate size and format for the surface // Allocate an uninitialized texture of appropriate size and format for the surface
using SurfaceType = CachedSurface::SurfaceType; using SurfaceType = CachedSurface::SurfaceType;
OpenGLState* old_state = OpenGLState::GetCurrentState(); OpenGLState* cur_state = OpenGLState::GetCurrentState();
utility_state.MakeCurrent(); GLenum old_active_texture = cur_state->GetActiveTextureUnit();
cur_state->SetActiveTextureUnit(GL_TEXTURE0);
utility_state.SetActiveTextureUnit(GL_TEXTURE0); GLuint old_texture = cur_state->GetTexture2D();
utility_state.SetTexture2D(texture); cur_state->SetTexture2D(texture);
SurfaceType type = CachedSurface::GetFormatType(pixel_format); SurfaceType type = CachedSurface::GetFormatType(pixel_format);
@ -206,7 +198,8 @@ void RasterizerCacheOpenGL::AllocateSurfaceTexture(GLuint texture, CachedSurface
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 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_WRAP_T, GL_CLAMP_TO_EDGE);
old_state->MakeCurrent(); cur_state->SetTexture2D(old_texture);
cur_state->SetActiveTextureUnit(old_active_texture);
} }
MICROPROFILE_DEFINE(OpenGL_SurfaceUpload, "OpenGL", "Surface Upload", MP_RGB(128, 64, 192)); MICROPROFILE_DEFINE(OpenGL_SurfaceUpload, "OpenGL", "Surface Upload", MP_RGB(128, 64, 192));
@ -288,11 +281,11 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo
Memory::RasterizerFlushRegion(params.addr, params_size); Memory::RasterizerFlushRegion(params.addr, params_size);
// Load data from memory to the new surface // Load data from memory to the new surface
OpenGLState* old_state = OpenGLState::GetCurrentState(); OpenGLState* cur_state = OpenGLState::GetCurrentState();
utility_state.MakeCurrent(); GLenum old_active_texture = cur_state->GetActiveTextureUnit();
cur_state->SetActiveTextureUnit(GL_TEXTURE0);
utility_state.SetActiveTextureUnit(GL_TEXTURE0); GLuint old_texture = cur_state->GetTexture2D();
utility_state.SetTexture2D(new_surface->texture.handle); cur_state->SetTexture2D(new_surface->texture.handle);
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)new_surface->stride); glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)new_surface->stride);
if (!new_surface->is_tiled) { if (!new_surface->is_tiled) {
@ -374,7 +367,8 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 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_WRAP_T, GL_CLAMP_TO_EDGE);
old_state->MakeCurrent(); cur_state->SetTexture2D(old_texture);
cur_state->SetActiveTextureUnit(old_active_texture);
} }
Memory::RasterizerMarkRegionCached(new_surface->addr, new_surface->size, 1); Memory::RasterizerMarkRegionCached(new_surface->addr, new_surface->size, 1);
@ -596,9 +590,6 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) {
return; return;
} }
OpenGLState* old_state = OpenGLState::GetCurrentState();
utility_state.MakeCurrent();
OGLTexture unscaled_tex; OGLTexture unscaled_tex;
GLuint texture_to_flush = surface->texture.handle; GLuint texture_to_flush = surface->texture.handle;
@ -614,8 +605,11 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) {
texture_to_flush = unscaled_tex.handle; texture_to_flush = unscaled_tex.handle;
} }
utility_state.SetActiveTextureUnit(GL_TEXTURE0); OpenGLState* cur_state = OpenGLState::GetCurrentState();
utility_state.SetTexture2D(texture_to_flush); GLenum old_active_texture = cur_state->GetActiveTextureUnit();
cur_state->SetActiveTextureUnit(GL_TEXTURE0);
GLuint old_texture = cur_state->GetTexture2D();
cur_state->SetTexture2D(texture_to_flush);
glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)surface->stride); glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)surface->stride);
if (!surface->is_tiled) { if (!surface->is_tiled) {
@ -664,7 +658,8 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) {
surface->dirty = false; surface->dirty = false;
old_state->MakeCurrent(); cur_state->SetTexture2D(old_texture);
cur_state->SetActiveTextureUnit(old_active_texture);
} }
void RasterizerCacheOpenGL::FlushRegion(PAddr addr, u32 size, const CachedSurface* skip_surface, bool invalidate) { void RasterizerCacheOpenGL::FlushRegion(PAddr addr, u32 size, const CachedSurface* skip_surface, bool invalidate) {

View File

@ -219,8 +219,6 @@ public:
private: private:
void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pixel_format, u32 width, u32 height); void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pixel_format, u32 width, u32 height);
OpenGLState utility_state;
SurfaceCache surface_cache; SurfaceCache surface_cache;
OGLFramebuffer transfer_framebuffers[2]; OGLFramebuffer transfer_framebuffers[2];
}; };

View File

@ -82,26 +82,26 @@ void OpenGLState::MakeCurrent() {
return; return;
} }
SetCullEnabled(cull.enabled); SetCullEnabled(GetCullEnabled());
SetCullMode(cull.mode); SetCullMode(GetCullMode());
SetCullFrontFace(cull.front_face); SetCullFrontFace(GetCullFrontFace());
SetDepthTestEnabled(depth.test_enabled); SetDepthTestEnabled(GetDepthTestEnabled());
SetDepthFunc(depth.test_func); SetDepthFunc(GetDepthFunc());
SetDepthWriteMask(depth.write_mask); SetDepthWriteMask(GetDepthWriteMask());
SetColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled, color_mask.alpha_enabled); SetColorMask(GetColorMask());
SetStencilTestEnabled(stencil.test_enabled); SetStencilTestEnabled(GetStencilTestEnabled());
SetStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); SetStencilFunc(GetStencilFunc());
SetStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail, stencil.action_depth_pass); SetStencilOp(GetStencilOp());
SetStencilWriteMask(stencil.write_mask); SetStencilWriteMask(GetStencilWriteMask());
SetBlendEnabled(blend.enabled); SetBlendEnabled(GetBlendEnabled());
SetBlendFunc(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); SetBlendFunc(GetBlendFunc());
SetBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); SetBlendColor(GetBlendColor());
SetLogicOp(logic_op); SetLogicOp(GetLogicOp());
GLenum prev_active_texture_unit = active_texture_unit; GLenum prev_active_texture_unit = active_texture_unit;
for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) {
@ -114,14 +114,14 @@ void OpenGLState::MakeCurrent() {
active_texture_unit = prev_active_texture_unit; active_texture_unit = prev_active_texture_unit;
glActiveTexture(cur_state->active_texture_unit); glActiveTexture(cur_state->active_texture_unit);
SetActiveTextureUnit(active_texture_unit); SetActiveTextureUnit(GetActiveTextureUnit());
SetReadFramebuffer(draw.read_framebuffer); SetReadFramebuffer(GetReadFramebuffer());
SetDrawFramebuffer(draw.draw_framebuffer); SetDrawFramebuffer(GetDrawFramebuffer());
SetVertexArray(draw.vertex_array); SetVertexArray(GetVertexArray());
SetVertexBuffer(draw.vertex_buffer); SetVertexBuffer(GetVertexBuffer());
SetUniformBuffer(draw.uniform_buffer); SetUniformBuffer(GetUniformBuffer());
SetShaderProgram(draw.shader_program); SetShaderProgram(GetShaderProgram());
cur_state = this; cur_state = this;
} }
@ -176,7 +176,10 @@ void OpenGLState::SetDepthWriteMask(GLboolean n_write_mask) {
depth.write_mask = n_write_mask; depth.write_mask = n_write_mask;
} }
void OpenGLState::SetColorMask(GLboolean n_red_enabled, GLboolean n_green_enabled, GLboolean n_blue_enabled, GLboolean n_alpha_enabled) { void OpenGLState::SetColorMask(std::tuple<GLboolean, GLboolean, GLboolean, GLboolean> n_rgba_enabled) {
GLboolean n_red_enabled, n_green_enabled, n_blue_enabled, n_alpha_enabled;
std::tie(n_red_enabled, n_green_enabled, n_blue_enabled, n_alpha_enabled) = n_rgba_enabled;
if (n_red_enabled != cur_state->color_mask.red_enabled || if (n_red_enabled != cur_state->color_mask.red_enabled ||
n_green_enabled != cur_state->color_mask.green_enabled || n_green_enabled != cur_state->color_mask.green_enabled ||
n_blue_enabled != cur_state->color_mask.blue_enabled || n_blue_enabled != cur_state->color_mask.blue_enabled ||
@ -201,7 +204,11 @@ void OpenGLState::SetStencilTestEnabled(bool n_test_enabled) {
stencil.test_enabled = n_test_enabled; stencil.test_enabled = n_test_enabled;
} }
void OpenGLState::SetStencilFunc(GLenum n_test_func, GLint n_test_ref, GLuint n_test_mask) { void OpenGLState::SetStencilFunc(std::tuple<GLenum, GLint, GLint> n_funcs) {
GLenum n_test_func;
GLint n_test_ref, n_test_mask;
std::tie(n_test_func, n_test_ref, n_test_mask) = n_funcs;
if (n_test_func != cur_state->stencil.test_func || if (n_test_func != cur_state->stencil.test_func ||
n_test_ref != cur_state->stencil.test_ref || n_test_ref != cur_state->stencil.test_ref ||
n_test_mask != cur_state->stencil.test_mask) { n_test_mask != cur_state->stencil.test_mask) {
@ -212,7 +219,10 @@ void OpenGLState::SetStencilFunc(GLenum n_test_func, GLint n_test_ref, GLuint n_
stencil.test_mask = n_test_mask; stencil.test_mask = n_test_mask;
} }
void OpenGLState::SetStencilOp(GLenum n_action_stencil_fail, GLenum n_action_depth_fail, GLenum n_action_depth_pass) { void OpenGLState::SetStencilOp(std::tuple<GLenum, GLenum, GLenum> n_actions) {
GLenum n_action_stencil_fail, n_action_depth_fail, n_action_depth_pass;
std::tie(n_action_stencil_fail, n_action_depth_fail, n_action_depth_pass) = n_actions;
if (n_action_stencil_fail != cur_state->stencil.action_stencil_fail || if (n_action_stencil_fail != cur_state->stencil.action_stencil_fail ||
n_action_depth_fail != cur_state->stencil.action_depth_fail || n_action_depth_fail != cur_state->stencil.action_depth_fail ||
n_action_depth_pass != cur_state->stencil.action_depth_pass) { n_action_depth_pass != cur_state->stencil.action_depth_pass) {
@ -245,7 +255,10 @@ void OpenGLState::SetBlendEnabled(bool n_enabled) {
blend.enabled = n_enabled; blend.enabled = n_enabled;
} }
void OpenGLState::SetBlendFunc(GLenum n_src_rgb_func, GLenum n_dst_rgb_func, GLenum n_src_a_func, GLenum n_dst_a_func) { void OpenGLState::SetBlendFunc(std::tuple<GLenum, GLenum, GLenum, GLenum> n_funcs) {
GLenum n_src_rgb_func, n_dst_rgb_func, n_src_a_func, n_dst_a_func;
std::tie(n_src_rgb_func, n_dst_rgb_func, n_src_a_func, n_dst_a_func) = n_funcs;
if (n_src_rgb_func != cur_state->blend.src_rgb_func || if (n_src_rgb_func != cur_state->blend.src_rgb_func ||
n_dst_rgb_func != cur_state->blend.dst_rgb_func || n_dst_rgb_func != cur_state->blend.dst_rgb_func ||
n_src_a_func != cur_state->blend.src_a_func || n_src_a_func != cur_state->blend.src_a_func ||
@ -259,7 +272,10 @@ void OpenGLState::SetBlendFunc(GLenum n_src_rgb_func, GLenum n_dst_rgb_func, GLe
blend.dst_a_func = n_dst_a_func; blend.dst_a_func = n_dst_a_func;
} }
void OpenGLState::SetBlendColor(GLclampf n_red, GLclampf n_green, GLclampf n_blue, GLclampf n_alpha) { void OpenGLState::SetBlendColor(std::tuple<GLclampf, GLclampf, GLclampf, GLclampf> n_color) {
GLclampf n_red, n_green, n_blue, n_alpha;
std::tie(n_red, n_green, n_blue, n_alpha) = n_color;
if (n_red != cur_state->blend.color.red || if (n_red != cur_state->blend.color.red ||
n_green != cur_state->blend.color.green || n_green != cur_state->blend.color.green ||
n_blue != cur_state->blend.color.blue || n_blue != cur_state->blend.color.blue ||
@ -477,3 +493,31 @@ GLenum OpenGLState::CheckBoundFBStatus(GLenum target) {
return fb_status; return fb_status;
} }
OpenGLState OpenGLState::ApplyTransferState(GLuint src_tex, GLuint read_framebuffer, GLuint dst_tex, GLuint draw_framebuffer) {
OpenGLState old_state = *cur_state;
cur_state->SetColorMask(std::make_tuple<>(true, true, true, true));
cur_state->SetDepthWriteMask(true);
cur_state->SetStencilWriteMask(true);
if (src_tex != 0) {
cur_state->ResetTexture(src_tex);
}
cur_state->SetReadFramebuffer(read_framebuffer);
if (dst_tex != 0) {
cur_state->ResetTexture(dst_tex);
}
cur_state->SetDrawFramebuffer(draw_framebuffer);
return old_state;
}
void OpenGLState::UndoTransferState(OpenGLState &old_state) {
cur_state->SetColorMask(old_state.GetColorMask());
cur_state->SetDepthWriteMask(old_state.GetDepthWriteMask());
cur_state->SetStencilWriteMask(old_state.GetStencilWriteMask());
cur_state->SetReadFramebuffer(old_state.GetReadFramebuffer());
cur_state->SetDrawFramebuffer(old_state.GetDrawFramebuffer());
// NOTE: Textures that were reset in ApplyTransferState() are NOT restored
}

View File

@ -17,39 +17,74 @@ public:
/// Apply this state as the current OpenGL state /// Apply this state as the current OpenGL state
void MakeCurrent(); void MakeCurrent();
/// Setter functions for OpenGL state /// Getter and setter functions for OpenGL state
inline bool GetCullEnabled() { return cull.enabled; }
void SetCullEnabled(bool n_enabled); void SetCullEnabled(bool n_enabled);
inline GLenum GetCullMode() { return cull.mode; }
void SetCullMode(GLenum n_mode); void SetCullMode(GLenum n_mode);
inline GLenum GetCullFrontFace() { return cull.front_face; }
void SetCullFrontFace(GLenum n_front_face); void SetCullFrontFace(GLenum n_front_face);
inline bool GetDepthTestEnabled() { return depth.test_enabled; }
void SetDepthTestEnabled(bool n_test_enabled); void SetDepthTestEnabled(bool n_test_enabled);
inline GLenum GetDepthFunc() { return depth.test_func; }
void SetDepthFunc(GLenum n_test_func); void SetDepthFunc(GLenum n_test_func);
inline GLboolean GetDepthWriteMask() { return depth.write_mask; }
void SetDepthWriteMask(GLboolean n_write_mask); void SetDepthWriteMask(GLboolean n_write_mask);
void SetColorMask(GLboolean n_red_enabled, GLboolean n_green_enabled, GLboolean n_blue_enabled, GLboolean n_alpha_enabled); inline std::tuple<GLboolean, GLboolean, GLboolean, GLboolean> GetColorMask() {
return std::make_tuple(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled, color_mask.alpha_enabled);
}
void SetColorMask(std::tuple<GLboolean, GLboolean, GLboolean, GLboolean> n_rgba_enabled);
inline bool GetStencilTestEnabled() { return stencil.test_enabled; }
void SetStencilTestEnabled(bool n_test_enabled); void SetStencilTestEnabled(bool n_test_enabled);
void SetStencilFunc(GLenum n_test_func, GLint n_test_ref, GLuint n_test_mask); inline std::tuple<GLenum, GLint, GLint> GetStencilFunc() {
void SetStencilOp(GLenum n_action_stencil_fail, GLenum n_action_depth_fail, GLenum n_action_depth_pass); return std::make_tuple(stencil.test_func, stencil.test_ref, stencil.test_mask);
}
void SetStencilFunc(std::tuple<GLenum, GLint, GLint> n_funcs);
inline std::tuple<GLenum, GLenum, GLenum> GetStencilOp() {
return std::make_tuple(stencil.action_stencil_fail, stencil.action_depth_fail, stencil.action_depth_pass);
}
void SetStencilOp(std::tuple<GLenum, GLenum, GLenum> n_actions);
inline GLuint GetStencilWriteMask() { return stencil.write_mask; }
void SetStencilWriteMask(GLuint n_write_mask); void SetStencilWriteMask(GLuint n_write_mask);
inline bool GetBlendEnabled() { return blend.enabled; }
void SetBlendEnabled(bool n_enabled); void SetBlendEnabled(bool n_enabled);
void SetBlendFunc(GLenum n_src_rgb_func, GLenum n_dst_rgb_func, GLenum n_src_a_func, GLenum n_dst_a_func); inline std::tuple<GLenum, GLenum, GLenum, GLenum> GetBlendFunc() {
void SetBlendColor(GLclampf n_red, GLclampf n_green, GLclampf n_blue, GLclampf n_alpha); return std::make_tuple(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func);
}
void SetBlendFunc(std::tuple<GLenum, GLenum, GLenum, GLenum> n_funcs);
inline std::tuple<GLclampf, GLclampf, GLclampf, GLclampf> GetBlendColor() {
return std::make_tuple(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
}
void SetBlendColor(std::tuple<GLclampf, GLclampf, GLclampf, GLclampf> n_color);
inline GLenum GetLogicOp() { return logic_op; }
void SetLogicOp(GLenum n_logic_op); void SetLogicOp(GLenum n_logic_op);
inline GLuint GetTexture1D() { return texture_units[active_texture_unit - GL_TEXTURE0].texture_1d; }
void SetTexture1D(GLuint n_texture_1d); void SetTexture1D(GLuint n_texture_1d);
inline GLuint GetTexture2D() { return texture_units[active_texture_unit - GL_TEXTURE0].texture_2d; }
void SetTexture2D(GLuint n_texture_2d); void SetTexture2D(GLuint n_texture_2d);
inline GLuint GetSampler() { return texture_units[active_texture_unit - GL_TEXTURE0].sampler; }
void SetSampler(GLuint n_sampler); void SetSampler(GLuint n_sampler);
inline GLenum GetActiveTextureUnit() { return active_texture_unit; }
void SetActiveTextureUnit(GLenum n_active_texture_unit); void SetActiveTextureUnit(GLenum n_active_texture_unit);
inline GLuint GetReadFramebuffer() { return draw.read_framebuffer; }
void SetReadFramebuffer(GLuint n_read_framebuffer); void SetReadFramebuffer(GLuint n_read_framebuffer);
inline GLuint GetDrawFramebuffer() { return draw.draw_framebuffer; }
void SetDrawFramebuffer(GLuint n_draw_framebuffer); void SetDrawFramebuffer(GLuint n_draw_framebuffer);
inline GLuint GetVertexArray() { return draw.vertex_array; }
void SetVertexArray(GLuint n_vertex_array); void SetVertexArray(GLuint n_vertex_array);
inline GLuint GetVertexBuffer() { return draw.vertex_buffer; }
void SetVertexBuffer(GLuint n_vertex_buffer); void SetVertexBuffer(GLuint n_vertex_buffer);
inline GLuint GetUniformBuffer() { return draw.uniform_buffer; }
void SetUniformBuffer(GLuint n_uniform_buffer); void SetUniformBuffer(GLuint n_uniform_buffer);
inline GLuint GetShaderProgram() { return draw.shader_program; }
void SetShaderProgram(GLuint n_shader_program); void SetShaderProgram(GLuint n_shader_program);
/// Resets and unbinds any references to the given resource across all existing states /// Resets and unbinds any references to the given resource across all existing states
@ -63,6 +98,12 @@ public:
/// Check the status of the currently bound OpenGL read or draw framebuffer configuration /// Check the status of the currently bound OpenGL read or draw framebuffer configuration
static GLenum CheckBoundFBStatus(GLenum target); static GLenum CheckBoundFBStatus(GLenum target);
/// Manipulates the current state to prepare for pixel transfer, and returns a copy of the old state
static OpenGLState ApplyTransferState(GLuint src_tex, GLuint read_framebuffer, GLuint dst_tex, GLuint draw_framebuffer);
/// Returns the old state before transfer state changes were made
static void UndoTransferState(OpenGLState &old_state);
private: private:
struct { struct {
bool enabled; // GL_CULL_FACE bool enabled; // GL_CULL_FACE

View File

@ -108,6 +108,7 @@ RendererOpenGL::~RendererOpenGL() {
/// Swap buffers (render frame) /// Swap buffers (render frame)
void RendererOpenGL::SwapBuffers() { void RendererOpenGL::SwapBuffers() {
OpenGLState* old_state = OpenGLState::GetCurrentState();
state.MakeCurrent(); state.MakeCurrent();
for (int i : {0, 1}) { for (int i : {0, 1}) {
@ -157,6 +158,8 @@ void RendererOpenGL::SwapBuffers() {
profiler.BeginFrame(); profiler.BeginFrame();
old_state->MakeCurrent();
RefreshRasterizerSetting(); RefreshRasterizerSetting();
if (Pica::g_debug_context && Pica::g_debug_context->recorder) { if (Pica::g_debug_context && Pica::g_debug_context->recorder) {