GL: Improve error handling with texture creation

This commit is contained in:
Connor McLaughlin 2019-12-11 00:01:29 +10:00
parent 05e6d4c401
commit 6f78fea159
8 changed files with 328 additions and 213 deletions

View File

@ -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

View File

@ -1,15 +1,24 @@
#pragma once
#include <glad.h>
#include "../types.h"
#include <glad.h>
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;
};

View File

@ -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<void*>(static_cast<uintptr_t>(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<void*>(static_cast<uintptr_t>(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<GL::Texture>(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<GL::Texture>(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<GL::Texture>(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<GL::Texture>(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<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())), 0,
m_vram_texture->GetHeight(), m_vram_texture->GetWidth(),
-static_cast<s32>(m_vram_texture->GetHeight()), m_vram_texture->GetWidth(),
m_vram_texture->GetHeight(), 1.0f);
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), 0,
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
-static_cast<s32>(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<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())),
scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y,
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())),
scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y,
scaled_display_width, -static_cast<s32>(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<u32>((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<void*>(static_cast<uintptr_t>(m_display_texture->GetGLId())),
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
0, display_height, display_width, -static_cast<s32>(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<void*>(static_cast<uintptr_t>(m_display_texture->GetGLId())),
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
0, scaled_display_height, scaled_display_width,
-static_cast<s32>(scaled_display_height), m_display_texture->GetWidth(),
m_display_texture->GetHeight(), m_crtc_state.display_aspect_ratio);
-static_cast<s32>(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++;

View File

@ -46,13 +46,12 @@ private:
std::tuple<s32, s32> 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<GL::Texture> m_vram_texture;
std::unique_ptr<GL::Texture> m_vram_read_texture;
std::unique_ptr<GL::Texture> m_vram_encoding_texture;
std::unique_ptr<GL::Texture> 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<GL::StreamBuffer> m_vertex_stream_buffer;
GLuint m_vao_id = 0;

View File

@ -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<void*>(static_cast<uintptr_t>(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<void*>(static_cast<uintptr_t>(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<GL::Texture>(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<GL::Texture>(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<GL::Texture>(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<GL::Texture>(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<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())), 0,
m_vram_texture->GetHeight(), m_vram_texture->GetWidth(),
-static_cast<s32>(m_vram_texture->GetHeight()), m_vram_texture->GetWidth(),
m_vram_texture->GetHeight(), 1.0f);
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())), 0,
m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
-static_cast<s32>(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<void*>(static_cast<uintptr_t>(m_vram_texture->GetGLId())),
scaled_vram_offset_x, m_vram_texture->GetHeight() - scaled_vram_offset_y,
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())),
scaled_vram_offset_x, m_vram_texture.GetHeight() - scaled_vram_offset_y,
scaled_display_width, -static_cast<s32>(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<u32>((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<void*>(static_cast<uintptr_t>(m_display_texture->GetGLId())),
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
0, display_height, display_width, -static_cast<s32>(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<void*>(static_cast<uintptr_t>(m_display_texture->GetGLId())),
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
0, scaled_display_height, scaled_display_width,
-static_cast<s32>(scaled_display_height), m_display_texture->GetWidth(),
m_display_texture->GetHeight(), m_crtc_state.display_aspect_ratio);
-static_cast<s32>(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++;

View File

@ -5,7 +5,6 @@
#include "glad.h"
#include "gpu_hw.h"
#include <array>
#include <memory>
#include <tuple>
class GPU_HW_OpenGL_ES : public GPU_HW
@ -46,9 +45,8 @@ private:
std::tuple<s32, s32> 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<GL::Texture> m_vram_texture;
std::unique_ptr<GL::Texture> m_vram_read_texture;
std::unique_ptr<GL::Texture> m_vram_encoding_texture;
std::unique_ptr<GL::Texture> 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<BatchVertex> m_vertex_buffer;

View File

@ -339,8 +339,8 @@ void main()
glGenVertexArrays(1, &m_display_vao);
m_app_icon_texture =
std::make_unique<GL::Texture>(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);

View File

@ -52,7 +52,7 @@ private:
int m_window_width = 0;
int m_window_height = 0;
std::unique_ptr<GL::Texture> m_app_icon_texture = nullptr;
GL::Texture m_app_icon_texture;
GL::Program m_display_program;
GLuint m_display_vao = 0;