GL: Improve error handling with texture creation
This commit is contained in:
parent
05e6d4c401
commit
6f78fea159
|
@ -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
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue