diff --git a/src/common/gl/texture.cpp b/src/common/gl/texture.cpp index 890121f9f..f40c845a8 100644 --- a/src/common/gl/texture.cpp +++ b/src/common/gl/texture.cpp @@ -5,32 +5,96 @@ Log_SetChannel(GL); namespace GL { -Texture::Texture(u32 width, u32 height, GLenum format, GLenum type, const void* data /* = nullptr */, - bool linear_filter /* = false */, bool create_framebuffer /* = false */) - : m_width(width), m_height(height) +Texture::Texture() = default; + +Texture::Texture(Texture&& moved) + : m_id(moved.m_id), m_width(moved.m_width), m_height(moved.m_height), m_fbo_id(moved.m_fbo_id) { - glGenTextures(1, &m_id); - glBindTexture(GL_TEXTURE_2D, m_id); + moved.m_id = 0; + moved.m_width = 0; + moved.m_height = 0; + moved.m_fbo_id = 0; +} + +Texture::~Texture() +{ + Destroy(); +} + +bool Texture::Create(u32 width, u32 height, GLenum format, GLenum type, const void* data, bool linear_filter) +{ + glGetError(); + + GLuint id; + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D, id); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - if (create_framebuffer) + if (glGetError() != GL_NO_ERROR) { - glGenFramebuffers(1, &m_fbo_id); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_id, 0); - Assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + glDeleteTextures(1, &id); + return false; } + + if (IsValid()) + Destroy(); + + m_id = id; + m_width = width; + m_height = height; + return true; } -Texture::~Texture() +void Texture::SetLinearFilter(bool enabled) { + Bind(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, enabled ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, enabled ? GL_LINEAR : GL_NEAREST); +} + +bool Texture::CreateFramebuffer() +{ + if (!IsValid()) + return false; + + glGetError(); + + GLuint fbo_id; + glGenFramebuffers(1, &fbo_id); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_id, 0); + if (glGetError() != GL_NO_ERROR || glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + glDeleteFramebuffers(1, &fbo_id); + return false; + } + if (m_fbo_id != 0) glDeleteFramebuffers(1, &m_fbo_id); - glDeleteTextures(1, &m_id); + m_fbo_id = fbo_id; + return true; +} + +void Texture::Destroy() +{ + if (m_fbo_id != 0) + { + glDeleteFramebuffers(1, &m_fbo_id); + m_fbo_id = 0; + } + if (m_id != 0) + { + glDeleteTextures(1, &m_id); + m_id = 0; + } + + m_width = 0; + m_height = 0; } void Texture::Bind() @@ -49,4 +113,20 @@ void Texture::Unbind() glBindTexture(GL_TEXTURE_2D, 0); } +Texture& Texture::operator=(Texture&& moved) +{ + Destroy(); + + m_id = moved.m_id; + m_width = moved.m_width; + m_height = moved.m_height; + m_fbo_id = moved.m_fbo_id; + + moved.m_id = 0; + moved.m_width = 0; + moved.m_height = 0; + moved.m_fbo_id = 0; + return *this; +} + } // namespace GL \ No newline at end of file diff --git a/src/common/gl/texture.h b/src/common/gl/texture.h index d1ce6311a..e7e0ca1be 100644 --- a/src/common/gl/texture.h +++ b/src/common/gl/texture.h @@ -1,15 +1,24 @@ #pragma once -#include #include "../types.h" +#include namespace GL { class Texture { public: - Texture(u32 width, u32 height, GLenum format, GLenum type, const void* data = nullptr, bool linear_filter = false, - bool create_framebuffer = false); + Texture(); + Texture(Texture&& moved); ~Texture(); + bool Create(u32 width, u32 height, GLenum format, GLenum type, const void* data = nullptr, + bool linear_filter = false); + bool CreateFramebuffer(); + + void Destroy(); + + void SetLinearFilter(bool enabled); + + bool IsValid() const { return m_id != 0; } GLuint GetGLId() const { return m_id; } u32 GetWidth() const { return m_width; } u32 GetHeight() const { return m_height; } @@ -21,10 +30,14 @@ public: static void Unbind(); + Texture& operator=(const Texture& copy) = delete; + Texture& operator=(Texture&& moved); + private: - GLuint m_id; - u32 m_width; - u32 m_height; + + GLuint m_id = 0; + u32 m_width = 0; + u32 m_height = 0; GLuint m_fbo_id = 0; }; diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index e8e71bfb0..3d222d86f 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -41,16 +41,39 @@ bool GPU_HW_OpenGL::Initialize(HostDisplay* host_display, System* system, DMA* d if (!GPU_HW::Initialize(host_display, system, dma, interrupt_controller, timers)) return false; - CreateFramebuffer(); - CreateVertexBuffer(); - CreateUniformBuffer(); - CreateTextureBuffer(); - if (!CompilePrograms()) + if (!CreateFramebuffer()) + { + Log_ErrorPrintf("Failed to create framebuffer"); return false; + } - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture->GetGLId())), 0, 0, - m_display_texture->GetWidth(), m_display_texture->GetHeight(), - m_display_texture->GetWidth(), m_display_texture->GetHeight(), 1.0f); + if (!CreateVertexBuffer()) + { + Log_ErrorPrintf("Failed to create vertex buffer"); + return false; + } + + if (!CreateUniformBuffer()) + { + Log_ErrorPrintf("Failed to create uniform buffer"); + return false; + } + + if (!CreateTextureBuffer()) + { + Log_ErrorPrintf("Failed to create texture buffer"); + return false; + } + + if (!CompilePrograms()) + { + Log_ErrorPrintf("Failed to compile programs"); + return false; + } + + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture.GetGLId())), 0, 0, + m_display_texture.GetWidth(), m_display_texture.GetHeight(), + m_display_texture.GetWidth(), m_display_texture.GetHeight(), 1.0f); RestoreGraphicsAPIState(); return true; } @@ -76,8 +99,8 @@ void GPU_HW_OpenGL::ResetGraphicsAPIState() void GPU_HW_OpenGL::RestoreGraphicsAPIState() { - m_vram_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight()); + m_vram_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + glViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); @@ -162,47 +185,50 @@ void GPU_HW_OpenGL::SetCapabilities(HostDisplay* host_display) Log_WarningPrintf("Dual-source blending is not supported, this may break some mask effects."); } -void GPU_HW_OpenGL::CreateFramebuffer() +bool GPU_HW_OpenGL::CreateFramebuffer() { // save old vram texture/fbo, in case we're changing scale - auto old_vram_texture = std::move(m_vram_texture); - DestroyFramebuffer(); + GL::Texture old_vram_texture = std::move(m_vram_texture); // scale vram size to internal resolution const u32 texture_width = VRAM_WIDTH * m_resolution_scale; const u32 texture_height = VRAM_HEIGHT * m_resolution_scale; - m_vram_texture = - std::make_unique(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); - - // do we need to restore the framebuffer after a size change? - if (old_vram_texture) + if (!m_vram_texture.Create(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_vram_texture.CreateFramebuffer()) { - const bool linear_filter = old_vram_texture->GetWidth() > m_vram_texture->GetWidth(); - Log_DevPrintf("Scaling %ux%u VRAM texture to %ux%u using %s filter", old_vram_texture->GetWidth(), - old_vram_texture->GetHeight(), m_vram_texture->GetWidth(), m_vram_texture->GetHeight(), - linear_filter ? "linear" : "nearest"); - glDisable(GL_SCISSOR_TEST); - old_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); - glBlitFramebuffer(0, 0, old_vram_texture->GetWidth(), old_vram_texture->GetHeight(), 0, 0, - m_vram_texture->GetWidth(), m_vram_texture->GetHeight(), GL_COLOR_BUFFER_BIT, - linear_filter ? GL_LINEAR : GL_NEAREST); - - glEnable(GL_SCISSOR_TEST); - old_vram_texture.reset(); + return false; } - m_vram_read_texture = - std::make_unique(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); + // do we need to restore the framebuffer after a size change? + if (old_vram_texture.IsValid()) + { + const bool linear_filter = old_vram_texture.GetWidth() > m_vram_texture.GetWidth(); + Log_DevPrintf("Scaling %ux%u VRAM texture to %ux%u using %s filter", old_vram_texture.GetWidth(), + old_vram_texture.GetHeight(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), + linear_filter ? "linear" : "nearest"); + glDisable(GL_SCISSOR_TEST); + old_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); + glBlitFramebuffer(0, 0, old_vram_texture.GetWidth(), old_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(), + m_vram_texture.GetHeight(), GL_COLOR_BUFFER_BIT, linear_filter ? GL_LINEAR : GL_NEAREST); - m_vram_encoding_texture = - std::make_unique(VRAM_WIDTH, VRAM_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); + glEnable(GL_SCISSOR_TEST); + old_vram_texture.Destroy(); + } - m_display_texture = - std::make_unique(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); + if (!m_vram_read_texture.Create(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_vram_read_texture.CreateFramebuffer() || + !m_vram_encoding_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_vram_encoding_texture.CreateFramebuffer() || + !m_display_texture.Create(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_display_texture.CreateFramebuffer()) + { + return false; + } - m_vram_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); SetFullVRAMDirtyRectangle(); + return true; } void GPU_HW_OpenGL::ClearFramebuffer() @@ -214,19 +240,11 @@ void GPU_HW_OpenGL::ClearFramebuffer() SetFullVRAMDirtyRectangle(); } -void GPU_HW_OpenGL::DestroyFramebuffer() -{ - m_vram_read_texture.reset(); - m_vram_texture.reset(); - m_vram_encoding_texture.reset(); - m_display_texture.reset(); -} - -void GPU_HW_OpenGL::CreateVertexBuffer() +bool GPU_HW_OpenGL::CreateVertexBuffer() { m_vertex_stream_buffer = GL::StreamBuffer::Create(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE); if (!m_vertex_stream_buffer) - Panic("Failed to create vertex streaming buffer"); + return false; m_vertex_stream_buffer->Bind(); @@ -244,21 +262,24 @@ void GPU_HW_OpenGL::CreateVertexBuffer() glBindVertexArray(0); glGenVertexArrays(1, &m_attributeless_vao_id); + return true; } -void GPU_HW_OpenGL::CreateUniformBuffer() +bool GPU_HW_OpenGL::CreateUniformBuffer() { m_uniform_stream_buffer = GL::StreamBuffer::Create(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE); if (!m_uniform_stream_buffer) - Panic("Failed to create uniform buffer"); + return false; + + return true; } -void GPU_HW_OpenGL::CreateTextureBuffer() +bool GPU_HW_OpenGL::CreateTextureBuffer() { // We use the pixel unpack buffer here because we share it with CPU-decoded VRAM writes. m_texture_stream_buffer = GL::StreamBuffer::Create(GL_PIXEL_UNPACK_BUFFER, VRAM_UPDATE_TEXTURE_BUFFER_SIZE); if (!m_texture_stream_buffer) - Panic("Failed to create texture stream buffer"); + return false; if (m_max_texture_buffer_size > 0) { @@ -268,6 +289,7 @@ void GPU_HW_OpenGL::CreateTextureBuffer() } m_texture_stream_buffer->Unbind(); + return true; } bool GPU_HW_OpenGL::CompilePrograms() @@ -396,7 +418,7 @@ void GPU_HW_OpenGL::SetDrawState(BatchRenderMode render_mode) prog.Bind(); if (m_batch.texture_mode != TextureMode::Disabled) - m_vram_read_texture->Bind(); + m_vram_read_texture.Bind(); if (m_batch.transparency_mode == TransparencyMode::Disabled || render_mode == BatchRenderMode::OnlyOpaque) { @@ -433,7 +455,7 @@ void GPU_HW_OpenGL::SetScissorFromDrawingArea() const int width = right - left; const int height = bottom - top; const int x = left; - const int y = m_vram_texture->GetHeight() - bottom; + const int y = m_vram_texture.GetHeight() - bottom; Log_DebugPrintf("SetScissor: (%d-%d, %d-%d)", x, x + width, y, y + height); glScissor(x, y, width, height); @@ -456,10 +478,10 @@ void GPU_HW_OpenGL::UpdateDisplay() if (m_system->GetSettings().debugging.show_vram) { - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture->GetGLId())), 0, - m_vram_texture->GetHeight(), m_vram_texture->GetWidth(), - -static_cast(m_vram_texture->GetHeight()), m_vram_texture->GetWidth(), - m_vram_texture->GetHeight(), 1.0f); + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture.GetGLId())), 0, + m_vram_texture.GetHeight(), m_vram_texture.GetWidth(), + -static_cast(m_vram_texture.GetHeight()), m_vram_texture.GetWidth(), + m_vram_texture.GetHeight(), 1.0f); } else { @@ -479,17 +501,17 @@ void GPU_HW_OpenGL::UpdateDisplay() } else if (!m_GPUSTAT.display_area_color_depth_24 && !interlaced) { - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture->GetGLId())), - scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y, + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture.GetGLId())), + scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y, scaled_display_width, -static_cast(scaled_display_height), - m_vram_texture->GetWidth(), m_vram_texture->GetHeight(), + m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), m_crtc_state.display_aspect_ratio); } else { const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - display_height; const u32 scaled_flipped_vram_offset_y = - m_vram_texture->GetHeight() - scaled_vram_offset_y - scaled_display_height; + m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height; const u32 field_offset = BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field); glDisable(GL_BLEND); @@ -504,15 +526,15 @@ void GPU_HW_OpenGL::UpdateDisplay() { const u32 copy_width = std::min((display_width * 3) / 2, VRAM_WIDTH - vram_offset_x); const u32 scaled_copy_width = copy_width * m_resolution_scale; - m_vram_encoding_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_encoding_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glBlitFramebuffer(scaled_vram_offset_x, scaled_flipped_vram_offset_y, scaled_vram_offset_x + scaled_copy_width, scaled_flipped_vram_offset_y + scaled_display_height, vram_offset_x, flipped_vram_offset_y, vram_offset_x + copy_width, flipped_vram_offset_y + display_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); - m_display_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_encoding_texture->Bind(); + m_display_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_encoding_texture.Bind(); glViewport(0, field_offset, display_width, display_height); @@ -522,15 +544,15 @@ void GPU_HW_OpenGL::UpdateDisplay() glDrawArrays(GL_TRIANGLES, 0, 3); - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture->GetGLId())), + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture.GetGLId())), 0, display_height, display_width, -static_cast(display_height), - m_display_texture->GetWidth(), m_display_texture->GetHeight(), + m_display_texture.GetWidth(), m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio); } else { - m_display_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->Bind(); + m_display_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.Bind(); glViewport(0, field_offset, scaled_display_width, scaled_display_height); @@ -540,15 +562,15 @@ void GPU_HW_OpenGL::UpdateDisplay() glDrawArrays(GL_TRIANGLES, 0, 3); - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture->GetGLId())), + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture.GetGLId())), 0, scaled_display_height, scaled_display_width, - -static_cast(scaled_display_height), m_display_texture->GetWidth(), - m_display_texture->GetHeight(), m_crtc_state.display_aspect_ratio); + -static_cast(scaled_display_height), m_display_texture.GetWidth(), + m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio); } // restore state - m_vram_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight()); + m_vram_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + glViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); glEnable(GL_SCISSOR_TEST); } } @@ -564,8 +586,8 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height) // Encode the 24-bit texture as 16-bit. const u32 uniforms[4] = {copy_rect.left, VRAM_HEIGHT - copy_rect.top - copy_rect.GetHeight(), copy_rect.GetWidth(), copy_rect.GetHeight()}; - m_vram_encoding_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->Bind(); + m_vram_encoding_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.Bind(); m_vram_read_program.Bind(); UploadUniformBlock(uniforms, sizeof(uniforms)); glDisable(GL_BLEND); @@ -574,7 +596,7 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height) glDrawArrays(GL_TRIANGLES, 0, 3); // Readback encoded texture. - m_vram_encoding_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_encoding_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glPixelStorei(GL_PACK_ALIGNMENT, 2); glPixelStorei(GL_PACK_ROW_LENGTH, VRAM_WIDTH / 2); glReadPixels(0, 0, encoded_width, encoded_height, GL_RGBA, GL_UNSIGNED_BYTE, @@ -594,7 +616,7 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) width *= m_resolution_scale; height *= m_resolution_scale; - glScissor(x, m_vram_texture->GetHeight() - y - height, width, height); + glScissor(x, m_vram_texture.GetHeight() - y - height, width, height); // drop precision unless true colour is enabled if (!m_true_color) @@ -635,7 +657,7 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* const u32 scaled_height = height * m_resolution_scale; const u32 scaled_x = x * m_resolution_scale; const u32 scaled_y = y * m_resolution_scale; - const u32 scaled_flipped_y = m_vram_texture->GetHeight() - scaled_y - scaled_height; + const u32 scaled_flipped_y = m_vram_texture.GetHeight() - scaled_y - scaled_height; glViewport(scaled_x, scaled_flipped_y, scaled_width, scaled_height); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); @@ -679,9 +701,9 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* // have to write to the 1x texture first if (m_resolution_scale > 1) - m_vram_encoding_texture->Bind(); + m_vram_encoding_texture.Bind(); else - m_vram_texture->Bind(); + m_vram_texture.Bind(); // lower-left origin flip happens here const u32 flipped_y = VRAM_HEIGHT - y - height; @@ -698,9 +720,9 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* const u32 scaled_height = height * m_resolution_scale; const u32 scaled_x = x * m_resolution_scale; const u32 scaled_y = y * m_resolution_scale; - const u32 scaled_flipped_y = m_vram_texture->GetHeight() - scaled_y - scaled_height; + const u32 scaled_flipped_y = m_vram_texture.GetHeight() - scaled_y - scaled_height; glDisable(GL_SCISSOR_TEST); - m_vram_encoding_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_encoding_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glBlitFramebuffer(x, flipped_y, x + width, flipped_y + height, scaled_x, scaled_flipped_y, scaled_x + scaled_width, scaled_flipped_y + scaled_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); @@ -720,23 +742,23 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid height *= m_resolution_scale; // lower-left origin flip - src_y = m_vram_texture->GetHeight() - src_y - height; - dst_y = m_vram_texture->GetHeight() - dst_y - height; + src_y = m_vram_texture.GetHeight() - src_y - height; + dst_y = m_vram_texture.GetHeight() - dst_y - height; if (GLAD_GL_VERSION_4_3) { - glCopyImageSubData(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, src_x, src_y, 0, m_vram_texture->GetGLId(), + glCopyImageSubData(m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, src_x, src_y, 0, m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, dst_x, dst_y, 0, width, height, 1); } else if (GLAD_GL_EXT_copy_image) { - glCopyImageSubDataEXT(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, src_x, src_y, 0, m_vram_texture->GetGLId(), + glCopyImageSubDataEXT(m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, src_x, src_y, 0, m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, dst_x, dst_y, 0, width, height, 1); } else { glDisable(GL_SCISSOR_TEST); - m_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glBlitFramebuffer(src_x, src_y, src_x + width, src_y + height, dst_x, dst_y, dst_x + width, dst_y + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); @@ -749,26 +771,26 @@ void GPU_HW_OpenGL::UpdateVRAMReadTexture() const u32 width = scaled_rect.GetWidth(); const u32 height = scaled_rect.GetHeight(); const u32 x = scaled_rect.left; - const u32 y = m_vram_texture->GetHeight() - scaled_rect.top - height; + const u32 y = m_vram_texture.GetHeight() - scaled_rect.top - height; if (GLAD_GL_VERSION_4_3) { - glCopyImageSubData(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, m_vram_read_texture->GetGLId(), + glCopyImageSubData(m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, m_vram_read_texture.GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, width, height, 1); } else if (GLAD_GL_EXT_copy_image) { - glCopyImageSubDataEXT(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, m_vram_read_texture->GetGLId(), + glCopyImageSubDataEXT(m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, m_vram_read_texture.GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, width, height, 1); } else { - m_vram_read_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_read_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glDisable(GL_SCISSOR_TEST); glBlitFramebuffer(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); - m_vram_texture->BindFramebuffer(GL_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_FRAMEBUFFER); } m_renderer_stats.num_vram_read_texture_updates++; diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h index 877cc34d1..c7c938d09 100644 --- a/src/core/gpu_hw_opengl.h +++ b/src/core/gpu_hw_opengl.h @@ -46,13 +46,12 @@ private: std::tuple ConvertToFramebufferCoordinates(s32 x, s32 y); void SetCapabilities(HostDisplay* host_display); - void CreateFramebuffer(); + bool CreateFramebuffer(); void ClearFramebuffer(); - void DestroyFramebuffer(); - void CreateVertexBuffer(); - void CreateUniformBuffer(); - void CreateTextureBuffer(); + bool CreateVertexBuffer(); + bool CreateUniformBuffer(); + bool CreateTextureBuffer(); bool CompilePrograms(); void SetDrawState(BatchRenderMode render_mode); @@ -60,10 +59,10 @@ private: void UploadUniformBlock(const void* data, u32 data_size); // downsample texture - used for readbacks at >1xIR. - std::unique_ptr m_vram_texture; - std::unique_ptr m_vram_read_texture; - std::unique_ptr m_vram_encoding_texture; - std::unique_ptr m_display_texture; + GL::Texture m_vram_texture; + GL::Texture m_vram_read_texture; + GL::Texture m_vram_encoding_texture; + GL::Texture m_display_texture; std::unique_ptr m_vertex_stream_buffer; GLuint m_vao_id = 0; diff --git a/src/core/gpu_hw_opengl_es.cpp b/src/core/gpu_hw_opengl_es.cpp index b1a01d844..ac08861a9 100644 --- a/src/core/gpu_hw_opengl_es.cpp +++ b/src/core/gpu_hw_opengl_es.cpp @@ -33,13 +33,21 @@ bool GPU_HW_OpenGL_ES::Initialize(HostDisplay* host_display, System* system, DMA if (!GPU_HW::Initialize(host_display, system, dma, interrupt_controller, timers)) return false; - CreateFramebuffer(); - if (!CompilePrograms()) + if (!CreateFramebuffer()) + { + Log_ErrorPrintf("Failed to create framebuffer"); return false; + } - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture->GetGLId())), 0, 0, - m_display_texture->GetWidth(), m_display_texture->GetHeight(), - m_display_texture->GetWidth(), m_display_texture->GetHeight(), 1.0f); + if (!CompilePrograms()) + { + Log_ErrorPrintf("Failed to compile programs"); + return false; + } + + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture.GetGLId())), 0, 0, + m_display_texture.GetWidth(), m_display_texture.GetHeight(), + m_display_texture.GetWidth(), m_display_texture.GetHeight(), 1.0f); RestoreGraphicsAPIState(); return true; } @@ -69,8 +77,8 @@ void GPU_HW_OpenGL_ES::ResetGraphicsAPIState() void GPU_HW_OpenGL_ES::RestoreGraphicsAPIState() { - m_vram_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight()); + m_vram_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + glViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); @@ -127,47 +135,50 @@ void GPU_HW_OpenGL_ES::SetCapabilities(HostDisplay* host_display) m_supports_dual_source_blend = false; } -void GPU_HW_OpenGL_ES::CreateFramebuffer() +bool GPU_HW_OpenGL_ES::CreateFramebuffer() { // save old vram texture/fbo, in case we're changing scale - auto old_vram_texture = std::move(m_vram_texture); - DestroyFramebuffer(); + GL::Texture old_vram_texture = std::move(m_vram_texture); // scale vram size to internal resolution const u32 texture_width = VRAM_WIDTH * m_resolution_scale; const u32 texture_height = VRAM_HEIGHT * m_resolution_scale; - m_vram_texture = - std::make_unique(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); - - // do we need to restore the framebuffer after a size change? - if (old_vram_texture) + if (!m_vram_texture.Create(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_vram_texture.CreateFramebuffer()) { - const bool linear_filter = old_vram_texture->GetWidth() > m_vram_texture->GetWidth(); - Log_DevPrintf("Scaling %ux%u VRAM texture to %ux%u using %s filter", old_vram_texture->GetWidth(), - old_vram_texture->GetHeight(), m_vram_texture->GetWidth(), m_vram_texture->GetHeight(), - linear_filter ? "linear" : "nearest"); - glDisable(GL_SCISSOR_TEST); - old_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); - glBlitFramebuffer(0, 0, old_vram_texture->GetWidth(), old_vram_texture->GetHeight(), 0, 0, - m_vram_texture->GetWidth(), m_vram_texture->GetHeight(), GL_COLOR_BUFFER_BIT, - linear_filter ? GL_LINEAR : GL_NEAREST); - - glEnable(GL_SCISSOR_TEST); - old_vram_texture.reset(); + return false; } - m_vram_read_texture = - std::make_unique(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); + // do we need to restore the framebuffer after a size change? + if (old_vram_texture.IsValid()) + { + const bool linear_filter = old_vram_texture.GetWidth() > m_vram_texture.GetWidth(); + Log_DevPrintf("Scaling %ux%u VRAM texture to %ux%u using %s filter", old_vram_texture.GetWidth(), + old_vram_texture.GetHeight(), m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), + linear_filter ? "linear" : "nearest"); + glDisable(GL_SCISSOR_TEST); + old_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); + glBlitFramebuffer(0, 0, old_vram_texture.GetWidth(), old_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(), + m_vram_texture.GetHeight(), GL_COLOR_BUFFER_BIT, linear_filter ? GL_LINEAR : GL_NEAREST); - m_vram_encoding_texture = - std::make_unique(VRAM_WIDTH, VRAM_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); + glEnable(GL_SCISSOR_TEST); + old_vram_texture.Destroy(); + } - m_display_texture = - std::make_unique(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false, true); + if (!m_vram_read_texture.Create(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_vram_read_texture.CreateFramebuffer() || + !m_vram_encoding_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_vram_encoding_texture.CreateFramebuffer() || + !m_display_texture.Create(texture_width, texture_height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) || + !m_display_texture.CreateFramebuffer()) + { + return false; + } - m_vram_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); SetFullVRAMDirtyRectangle(); + return true; } void GPU_HW_OpenGL_ES::ClearFramebuffer() @@ -179,14 +190,6 @@ void GPU_HW_OpenGL_ES::ClearFramebuffer() SetFullVRAMDirtyRectangle(); } -void GPU_HW_OpenGL_ES::DestroyFramebuffer() -{ - m_vram_read_texture.reset(); - m_vram_texture.reset(); - m_vram_encoding_texture.reset(); - m_display_texture.reset(); -} - bool GPU_HW_OpenGL_ES::CompilePrograms() { GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_texture_filtering, @@ -290,7 +293,7 @@ void GPU_HW_OpenGL_ES::SetDrawState(BatchRenderMode render_mode) prog.Bind(); if (m_batch.texture_mode != TextureMode::Disabled) - m_vram_read_texture->Bind(); + m_vram_read_texture.Bind(); if (m_batch.transparency_mode == TransparencyMode::Disabled || render_mode == BatchRenderMode::OnlyOpaque) { @@ -332,7 +335,7 @@ void GPU_HW_OpenGL_ES::SetScissorFromDrawingArea() const int width = right - left; const int height = bottom - top; const int x = left; - const int y = m_vram_texture->GetHeight() - bottom; + const int y = m_vram_texture.GetHeight() - bottom; Log_DebugPrintf("SetScissor: (%d-%d, %d-%d)", x, x + width, y, y + height); glScissor(x, y, width, height); @@ -344,10 +347,10 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() if (m_system->GetSettings().debugging.show_vram) { - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture->GetGLId())), 0, - m_vram_texture->GetHeight(), m_vram_texture->GetWidth(), - -static_cast(m_vram_texture->GetHeight()), m_vram_texture->GetWidth(), - m_vram_texture->GetHeight(), 1.0f); + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture.GetGLId())), 0, + m_vram_texture.GetHeight(), m_vram_texture.GetWidth(), + -static_cast(m_vram_texture.GetHeight()), m_vram_texture.GetWidth(), + m_vram_texture.GetHeight(), 1.0f); } else { @@ -367,17 +370,17 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() } else if (!m_GPUSTAT.display_area_color_depth_24 && !interlaced) { - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture->GetGLId())), - scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y, + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_vram_texture.GetGLId())), + scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y, scaled_display_width, -static_cast(scaled_display_height), - m_vram_texture->GetWidth(), m_vram_texture->GetHeight(), + m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), m_crtc_state.display_aspect_ratio); } else { const u32 flipped_vram_offset_y = VRAM_HEIGHT - vram_offset_y - display_height; const u32 scaled_flipped_vram_offset_y = - m_vram_texture->GetHeight() - scaled_vram_offset_y - scaled_display_height; + m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height; const u32 field_offset = BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field); glDisable(GL_BLEND); @@ -392,15 +395,15 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() { const u32 copy_width = std::min((display_width * 3) / 2, VRAM_WIDTH - vram_offset_x); const u32 scaled_copy_width = copy_width * m_resolution_scale; - m_vram_encoding_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_encoding_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glBlitFramebuffer(scaled_vram_offset_x, scaled_flipped_vram_offset_y, scaled_vram_offset_x + scaled_copy_width, scaled_flipped_vram_offset_y + scaled_display_height, vram_offset_x, flipped_vram_offset_y, vram_offset_x + copy_width, flipped_vram_offset_y + display_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); - m_display_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_encoding_texture->Bind(); + m_display_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_encoding_texture.Bind(); glViewport(0, field_offset, display_width, display_height); @@ -410,15 +413,15 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() glDrawArrays(GL_TRIANGLES, 0, 3); - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture->GetGLId())), + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture.GetGLId())), 0, display_height, display_width, -static_cast(display_height), - m_display_texture->GetWidth(), m_display_texture->GetHeight(), + m_display_texture.GetWidth(), m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio); } else { - m_display_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->Bind(); + m_display_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.Bind(); glViewport(0, field_offset, scaled_display_width, scaled_display_height); @@ -428,15 +431,15 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() glDrawArrays(GL_TRIANGLES, 0, 3); - m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture->GetGLId())), + m_host_display->SetDisplayTexture(reinterpret_cast(static_cast(m_display_texture.GetGLId())), 0, scaled_display_height, scaled_display_width, - -static_cast(scaled_display_height), m_display_texture->GetWidth(), - m_display_texture->GetHeight(), m_crtc_state.display_aspect_ratio); + -static_cast(scaled_display_height), m_display_texture.GetWidth(), + m_display_texture.GetHeight(), m_crtc_state.display_aspect_ratio); } // restore state - m_vram_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight()); + m_vram_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + glViewport(0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); glEnable(GL_SCISSOR_TEST); } } @@ -450,8 +453,8 @@ void GPU_HW_OpenGL_ES::ReadVRAM(u32 x, u32 y, u32 width, u32 height) const u32 encoded_height = copy_rect.GetHeight(); // Encode the 24-bit texture as 16-bit. - m_vram_encoding_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->Bind(); + m_vram_encoding_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.Bind(); m_vram_read_program.Bind(); m_vram_read_program.Uniform2i(0, copy_rect.left, VRAM_HEIGHT - copy_rect.top - copy_rect.GetHeight()); m_vram_read_program.Uniform2i(1, copy_rect.GetWidth(), copy_rect.GetHeight()); @@ -461,7 +464,7 @@ void GPU_HW_OpenGL_ES::ReadVRAM(u32 x, u32 y, u32 width, u32 height) glDrawArrays(GL_TRIANGLES, 0, 3); // Readback encoded texture. - m_vram_encoding_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_encoding_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glPixelStorei(GL_PACK_ALIGNMENT, 2); glPixelStorei(GL_PACK_ROW_LENGTH, VRAM_WIDTH / 2); glReadPixels(0, 0, encoded_width, encoded_height, GL_RGBA, GL_UNSIGNED_BYTE, @@ -481,7 +484,7 @@ void GPU_HW_OpenGL_ES::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) width *= m_resolution_scale; height *= m_resolution_scale; - glScissor(x, m_vram_texture->GetHeight() - y - height, width, height); + glScissor(x, m_vram_texture.GetHeight() - y - height, width, height); // drop precision unless true colour is enabled if (!m_true_color) @@ -533,9 +536,9 @@ void GPU_HW_OpenGL_ES::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const voi // have to write to the 1x texture first if (m_resolution_scale > 1) - m_vram_encoding_texture->Bind(); + m_vram_encoding_texture.Bind(); else - m_vram_texture->Bind(); + m_vram_texture.Bind(); // lower-left origin flip happens here const u32 flipped_y = VRAM_HEIGHT - y - height; @@ -550,9 +553,9 @@ void GPU_HW_OpenGL_ES::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const voi const u32 scaled_height = height * m_resolution_scale; const u32 scaled_x = x * m_resolution_scale; const u32 scaled_y = y * m_resolution_scale; - const u32 scaled_flipped_y = m_vram_texture->GetHeight() - scaled_y - scaled_height; + const u32 scaled_flipped_y = m_vram_texture.GetHeight() - scaled_y - scaled_height; glDisable(GL_SCISSOR_TEST); - m_vram_encoding_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_encoding_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glBlitFramebuffer(x, flipped_y, x + width, flipped_y + height, scaled_x, scaled_flipped_y, scaled_x + scaled_width, scaled_flipped_y + scaled_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); @@ -571,18 +574,18 @@ void GPU_HW_OpenGL_ES::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 height *= m_resolution_scale; // lower-left origin flip - src_y = m_vram_texture->GetHeight() - src_y - height; - dst_y = m_vram_texture->GetHeight() - dst_y - height; + src_y = m_vram_texture.GetHeight() - src_y - height; + dst_y = m_vram_texture.GetHeight() - dst_y - height; if (GLAD_GL_EXT_copy_image) { - glCopyImageSubDataEXT(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, src_x, src_y, 0, m_vram_texture->GetGLId(), + glCopyImageSubDataEXT(m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, src_x, src_y, 0, m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, dst_x, dst_y, 0, width, height, 1); } else { glDisable(GL_SCISSOR_TEST); - m_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glBlitFramebuffer(src_x, src_y, src_x + width, src_y + height, dst_x, dst_y, dst_x + width, dst_y + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); @@ -595,21 +598,21 @@ void GPU_HW_OpenGL_ES::UpdateVRAMReadTexture() const u32 width = scaled_rect.GetWidth(); const u32 height = scaled_rect.GetHeight(); const u32 x = scaled_rect.left; - const u32 y = m_vram_texture->GetHeight() - scaled_rect.top - height; + const u32 y = m_vram_texture.GetHeight() - scaled_rect.top - height; if (GLAD_GL_EXT_copy_image) { - glCopyImageSubDataEXT(m_vram_texture->GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, m_vram_read_texture->GetGLId(), + glCopyImageSubDataEXT(m_vram_texture.GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, m_vram_read_texture.GetGLId(), GL_TEXTURE_2D, 0, x, y, 0, width, height, 1); } else { - m_vram_read_texture->BindFramebuffer(GL_DRAW_FRAMEBUFFER); - m_vram_texture->BindFramebuffer(GL_READ_FRAMEBUFFER); + m_vram_read_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_READ_FRAMEBUFFER); glDisable(GL_SCISSOR_TEST); glBlitFramebuffer(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); - m_vram_texture->BindFramebuffer(GL_FRAMEBUFFER); + m_vram_texture.BindFramebuffer(GL_FRAMEBUFFER); } m_renderer_stats.num_vram_read_texture_updates++; diff --git a/src/core/gpu_hw_opengl_es.h b/src/core/gpu_hw_opengl_es.h index 5f49374e3..0c1c5e954 100644 --- a/src/core/gpu_hw_opengl_es.h +++ b/src/core/gpu_hw_opengl_es.h @@ -5,7 +5,6 @@ #include "glad.h" #include "gpu_hw.h" #include -#include #include class GPU_HW_OpenGL_ES : public GPU_HW @@ -46,9 +45,8 @@ private: std::tuple ConvertToFramebufferCoordinates(s32 x, s32 y); void SetCapabilities(HostDisplay* host_display); - void CreateFramebuffer(); + bool CreateFramebuffer(); void ClearFramebuffer(); - void DestroyFramebuffer(); bool CompilePrograms(); void SetVertexPointers(); @@ -56,10 +54,10 @@ private: void SetScissorFromDrawingArea(); // downsample texture - used for readbacks at >1xIR. - std::unique_ptr m_vram_texture; - std::unique_ptr m_vram_read_texture; - std::unique_ptr m_vram_encoding_texture; - std::unique_ptr m_display_texture; + GL::Texture m_vram_texture; + GL::Texture m_vram_read_texture; + GL::Texture m_vram_encoding_texture; + GL::Texture m_display_texture; std::vector m_vertex_buffer; diff --git a/src/duckstation/opengl_host_display.cpp b/src/duckstation/opengl_host_display.cpp index 40bdc93a7..d4f1c1f30 100644 --- a/src/duckstation/opengl_host_display.cpp +++ b/src/duckstation/opengl_host_display.cpp @@ -339,8 +339,8 @@ void main() glGenVertexArrays(1, &m_display_vao); - m_app_icon_texture = - std::make_unique(APP_ICON_WIDTH, APP_ICON_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, APP_ICON_DATA, true); + if (!m_app_icon_texture.Create(APP_ICON_WIDTH, APP_ICON_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, APP_ICON_DATA, true)) + return false; // samplers glGenSamplers(1, &m_display_nearest_sampler); diff --git a/src/duckstation/opengl_host_display.h b/src/duckstation/opengl_host_display.h index 0bdd74d87..9b03ecc27 100644 --- a/src/duckstation/opengl_host_display.h +++ b/src/duckstation/opengl_host_display.h @@ -52,7 +52,7 @@ private: int m_window_width = 0; int m_window_height = 0; - std::unique_ptr m_app_icon_texture = nullptr; + GL::Texture m_app_icon_texture; GL::Program m_display_program; GLuint m_display_vao = 0;