aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp19
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp16
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp111
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h110
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp13
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h29
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp19
8 files changed, 155 insertions, 167 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 518f7933..2db845da 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -2,10 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+#include <memory>
+
#include "common/color.h"
+#include "common/math_util.h"
-#include "core/settings.h"
#include "core/hw/gpu.h"
+#include "core/memory.h"
+#include "core/settings.h"
#include "video_core/pica.h"
#include "video_core/utils.h"
@@ -16,8 +21,6 @@
#include "generated/gl_3_2_core.h"
-#include <memory>
-
static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) {
return (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace &&
stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace &&
@@ -813,12 +816,16 @@ void RasterizerOpenGL::ReloadColorBuffer() {
}
void RasterizerOpenGL::ReloadDepthBuffer() {
+ PAddr depth_buffer_addr = Pica::g_state.regs.framebuffer.GetDepthBufferPhysicalAddress();
+
+ if (depth_buffer_addr == 0)
+ return;
+
// TODO: Appears to work, but double-check endianness of depth values and order of depth-stencil
- u8* depth_buffer = Memory::GetPhysicalPointer(Pica::g_state.regs.framebuffer.GetDepthBufferPhysicalAddress());
+ u8* depth_buffer = Memory::GetPhysicalPointer(depth_buffer_addr);
- if (depth_buffer == nullptr) {
+ if (depth_buffer == nullptr)
return;
- }
u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(fb_depth_texture.format);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index d7d422b1..ae7b26fc 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -4,7 +4,12 @@
#pragma once
+#include <vector>
+
+#include "common/common_types.h"
+
#include "video_core/hwrasterizer_base.h"
+#include "video_core/vertex_shader.h"
#include "gl_state.h"
#include "gl_rasterizer_cache.h"
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 2e4110a8..dc3ffdf2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -31,12 +31,18 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
state.texture_units[texture_unit].texture_2d = new_texture->texture.handle;
state.Apply();
- // TODO: Need to choose filters that correspond to PICA once register is declared
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, PicaToGL::TextureFilterMode(config.config.mag_filter));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, PicaToGL::TextureFilterMode(config.config.min_filter));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, PicaToGL::WrapMode(config.config.wrap_s));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, PicaToGL::WrapMode(config.config.wrap_t));
+ GLenum wrap_s = PicaToGL::WrapMode(config.config.wrap_s);
+ GLenum wrap_t = PicaToGL::WrapMode(config.config.wrap_t);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
+
+ if (wrap_s == GL_CLAMP_TO_BORDER || wrap_t == GL_CLAMP_TO_BORDER) {
+ auto border_color = PicaToGL::ColorRGBA8((u8*)&config.config.border_color.r);
+ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color.data());
+ }
const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format);
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp
deleted file mode 100644
index 8f4ae28a..00000000
--- a/src/video_core/renderer_opengl/gl_resource_manager.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "video_core/renderer_opengl/gl_resource_manager.h"
-#include "video_core/renderer_opengl/gl_shader_util.h"
-
-// Textures
-OGLTexture::OGLTexture() : handle(0) {
-}
-
-OGLTexture::~OGLTexture() {
- Release();
-}
-
-void OGLTexture::Create() {
- if (handle != 0) {
- return;
- }
-
- glGenTextures(1, &handle);
-}
-
-void OGLTexture::Release() {
- glDeleteTextures(1, &handle);
- handle = 0;
-}
-
-// Shaders
-OGLShader::OGLShader() : handle(0) {
-}
-
-OGLShader::~OGLShader() {
- Release();
-}
-
-void OGLShader::Create(const char* vert_shader, const char* frag_shader) {
- if (handle != 0) {
- return;
- }
-
- handle = ShaderUtil::LoadShaders(vert_shader, frag_shader);
-}
-
-void OGLShader::Release() {
- glDeleteProgram(handle);
- handle = 0;
-}
-
-// Buffer objects
-OGLBuffer::OGLBuffer() : handle(0) {
-}
-
-OGLBuffer::~OGLBuffer() {
- Release();
-}
-
-void OGLBuffer::Create() {
- if (handle != 0) {
- return;
- }
-
- glGenBuffers(1, &handle);
-}
-
-void OGLBuffer::Release() {
- glDeleteBuffers(1, &handle);
- handle = 0;
-}
-
-// Vertex array objects
-OGLVertexArray::OGLVertexArray() : handle(0) {
-}
-
-OGLVertexArray::~OGLVertexArray() {
- Release();
-}
-
-void OGLVertexArray::Create() {
- if (handle != 0) {
- return;
- }
-
- glGenVertexArrays(1, &handle);
-}
-
-void OGLVertexArray::Release() {
- glDeleteVertexArrays(1, &handle);
- handle = 0;
-}
-
-// Framebuffers
-OGLFramebuffer::OGLFramebuffer() : handle(0) {
-}
-
-OGLFramebuffer::~OGLFramebuffer() {
- Release();
-}
-
-void OGLFramebuffer::Create() {
- if (handle != 0) {
- return;
- }
-
- glGenFramebuffers(1, &handle);
-}
-
-void OGLFramebuffer::Release() {
- glDeleteFramebuffers(1, &handle);
- handle = 0;
-}
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index 975720d0..6f9dc012 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -4,76 +4,124 @@
#pragma once
+#include <utility>
+
#include "common/common_types.h"
-#include "generated/gl_3_2_core.h"
+#include "video_core/renderer_opengl/generated/gl_3_2_core.h"
+#include "video_core/renderer_opengl/gl_shader_util.h"
-class OGLTexture : public NonCopyable {
+class OGLTexture : private NonCopyable {
public:
- OGLTexture();
- ~OGLTexture();
+ OGLTexture() = default;
+ OGLTexture(OGLTexture&& o) { std::swap(handle, o.handle); }
+ ~OGLTexture() { Release(); }
+ OGLTexture& operator=(OGLTexture&& o) { std::swap(handle, o.handle); return *this; }
/// Creates a new internal OpenGL resource and stores the handle
- void Create();
+ void Create() {
+ if (handle != 0) return;
+ glGenTextures(1, &handle);
+ }
/// Deletes the internal OpenGL resource
- void Release();
+ void Release() {
+ if (handle == 0) return;
+ glDeleteTextures(1, &handle);
+ handle = 0;
+ }
- GLuint handle;
+ GLuint handle = 0;
};
-class OGLShader : public NonCopyable {
+class OGLShader : private NonCopyable {
public:
- OGLShader();
- ~OGLShader();
+ OGLShader() = default;
+ OGLShader(OGLShader&& o) { std::swap(handle, o.handle); }
+ ~OGLShader() { Release(); }
+ OGLShader& operator=(OGLShader&& o) { std::swap(handle, o.handle); return *this; }
/// Creates a new internal OpenGL resource and stores the handle
- void Create(const char* vert_shader, const char* frag_shader);
+ void Create(const char* vert_shader, const char* frag_shader) {
+ if (handle != 0) return;
+ handle = ShaderUtil::LoadShaders(vert_shader, frag_shader);
+ }
/// Deletes the internal OpenGL resource
- void Release();
+ void Release() {
+ if (handle == 0) return;
+ glDeleteProgram(handle);
+ handle = 0;
+ }
- GLuint handle;
+ GLuint handle = 0;
};
-class OGLBuffer : public NonCopyable {
+class OGLBuffer : private NonCopyable {
public:
- OGLBuffer();
- ~OGLBuffer();
+ OGLBuffer() = default;
+ OGLBuffer(OGLBuffer&& o) { std::swap(handle, o.handle); }
+ ~OGLBuffer() { Release(); }
+ OGLBuffer& operator=(OGLBuffer&& o) { std::swap(handle, o.handle); return *this; }
/// Creates a new internal OpenGL resource and stores the handle
- void Create();
+ void Create() {
+ if (handle != 0) return;
+ glGenBuffers(1, &handle);
+ }
/// Deletes the internal OpenGL resource
- void Release();
+ void Release() {
+ if (handle == 0) return;
+ glDeleteBuffers(1, &handle);
+ handle = 0;
+ }
- GLuint handle;
+ GLuint handle = 0;
};
-class OGLVertexArray : public NonCopyable {
+class OGLVertexArray : private NonCopyable {
public:
- OGLVertexArray();
- ~OGLVertexArray();
+ OGLVertexArray() = default;
+ OGLVertexArray(OGLVertexArray&& o) { std::swap(handle, o.handle); }
+ ~OGLVertexArray() { Release(); }
+ OGLVertexArray& operator=(OGLVertexArray&& o) { std::swap(handle, o.handle); return *this; }
/// Creates a new internal OpenGL resource and stores the handle
- void Create();
+ void Create() {
+ if (handle != 0) return;
+ glGenVertexArrays(1, &handle);
+ }
/// Deletes the internal OpenGL resource
- void Release();
+ void Release() {
+ if (handle == 0) return;
+ glDeleteVertexArrays(1, &handle);
+ handle = 0;
+ }
- GLuint handle;
+ GLuint handle = 0;
};
-class OGLFramebuffer : public NonCopyable {
+class OGLFramebuffer : private NonCopyable {
public:
- OGLFramebuffer();
- ~OGLFramebuffer();
+ OGLFramebuffer() = default;
+ OGLFramebuffer(OGLFramebuffer&& o) { std::swap(handle, o.handle); }
+ ~OGLFramebuffer() { Release(); }
+ OGLFramebuffer& operator=(OGLFramebuffer&& o) { std::swap(handle, o.handle); return *this; }
/// Creates a new internal OpenGL resource and stores the handle
- void Create();
+ void Create() {
+ if (handle != 0) return;
+ glGenFramebuffers(1, &handle);
+ }
/// Deletes the internal OpenGL resource
- void Release();
+ void Release() {
+ if (handle == 0) return;
+ glDeleteFramebuffers(1, &handle);
+ handle = 0;
+ }
- GLuint handle;
+ GLuint handle = 0;
};
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 3526e16d..9efc1533 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -147,20 +147,17 @@ void OpenGLState::Apply() {
// Textures
for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) {
- if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d) {
+ if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d ||
+ texture_units[texture_index].texture_2d != cur_state.texture_units[texture_index].texture_2d) {
+
glActiveTexture(GL_TEXTURE0 + texture_index);
if (texture_units[texture_index].enabled_2d) {
- glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture_units[texture_index].texture_2d);
} else {
- glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
}
-
- if (texture_units[texture_index].texture_2d != cur_state.texture_units[texture_index].texture_2d) {
- glActiveTexture(GL_TEXTURE0 + texture_index);
- glBindTexture(GL_TEXTURE_2D, texture_units[texture_index].texture_2d);
- }
}
// Framebuffer
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index e566f9f7..3b562da8 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -12,10 +12,37 @@
namespace PicaToGL {
+inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) {
+ static const GLenum filter_mode_table[] = {
+ GL_NEAREST, // TextureFilter::Nearest
+ GL_LINEAR // TextureFilter::Linear
+ };
+
+ // Range check table for input
+ if (mode >= ARRAY_SIZE(filter_mode_table)) {
+ LOG_CRITICAL(Render_OpenGL, "Unknown texture filtering mode %d", mode);
+ UNREACHABLE();
+
+ return GL_LINEAR;
+ }
+
+ GLenum gl_mode = filter_mode_table[mode];
+
+ // Check for dummy values indicating an unknown mode
+ if (gl_mode == 0) {
+ LOG_CRITICAL(Render_OpenGL, "Unknown texture filtering mode %d", mode);
+ UNIMPLEMENTED();
+
+ return GL_LINEAR;
+ }
+
+ return gl_mode;
+}
+
inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) {
static const GLenum wrap_mode_table[] = {
GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge
- 0, // Unknown
+ GL_CLAMP_TO_BORDER,// WrapMode::ClampToBorder
GL_REPEAT, // WrapMode::Repeat
GL_MIRRORED_REPEAT // WrapMode::MirroredRepeat
};
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 3399ca12..96e12839 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -2,22 +2,27 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+#include <cstddef>
+#include <cstdlib>
+
+#include "common/assert.h"
+#include "common/emu_window.h"
+#include "common/logging/log.h"
+#include "common/profiler_reporting.h"
+
#include "core/hw/gpu.h"
#include "core/hw/hw.h"
#include "core/hw/lcd.h"
#include "core/memory.h"
#include "core/settings.h"
-#include "common/emu_window.h"
-#include "common/logging/log.h"
-#include "common/profiler_reporting.h"
-
#include "video_core/video_core.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/gl_shaders.h"
-#include <algorithm>
+#include "video_core/debug_utils/debug_utils.h"
/**
* Vertex structure that the drawn screen rectangles are composed of.
@@ -126,6 +131,10 @@ void RendererOpenGL::SwapBuffers() {
hw_rasterizer->Reset();
}
}
+
+ if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
+ Pica::g_debug_context->recorder->FrameFinished();
+ }
}
/**