Addressed smaller comments, fb color/depth separate

This commit is contained in:
tfarley 2015-05-16 23:46:46 -07:00
parent d517757053
commit dfc807daf9
14 changed files with 227 additions and 200 deletions

View File

@ -355,8 +355,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
// GX request DMA - typically used for copying memory from GSP heap to VRAM
case CommandId::REQUEST_DMA:
VideoCore::g_renderer->hw_rasterizer->NotifyPreCopy(Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
command.dma_request.size);
VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
command.dma_request.size);
memcpy(Memory::GetPointer(command.dma_request.dest_address),
Memory::GetPointer(command.dma_request.source_address),

View File

@ -131,10 +131,10 @@ inline void Write(u32 addr, const T data) {
u32 output_width = config.output_width / horizontal_scale;
u32 output_height = config.output_height / vertical_scale;
u32 input_size = config.input_height.Value() * config.input_width.Value() * GPU::Regs::BytesPerPixel(config.input_format.Value());
u32 output_size = output_height * output_width * GPU::Regs::BytesPerPixel(config.output_format.Value());
u32 input_size = config.input_height * config.input_width * GPU::Regs::BytesPerPixel(config.input_format);
u32 output_size = output_height * output_width * GPU::Regs::BytesPerPixel(config.output_format);
VideoCore::g_renderer->hw_rasterizer->NotifyPreCopy(config.GetPhysicalInputAddress(), input_size);
VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), input_size);
if (config.raw_copy) {
// Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions

View File

@ -15,10 +15,7 @@ public:
/// Initialize API-specific GPU objects
virtual void InitObjects() = 0;
/// Set the window (context) to draw with
virtual void SetWindow(EmuWindow* window) = 0;
/// Converts the triangle verts to hardware data format and adds them to the current batch
/// Queues the primitive formed by the given vertices for rendering
virtual void AddTriangle(const Pica::VertexShader::OutputVertex& v0,
const Pica::VertexShader::OutputVertex& v1,
const Pica::VertexShader::OutputVertex& v2) = 0;
@ -26,9 +23,9 @@ public:
/// Draw the current batch of triangles
virtual void DrawTriangles() = 0;
/// Notify rasterizer that a copy within 3DS memory will occur after this notification
virtual void NotifyPreCopy(u32 src_paddr, u32 size) = 0;
/// Notify rasterizer that the specified 3DS memory region will be read from after this notification
virtual void NotifyPreRead(u32 paddr, u32 size) = 0;
/// Notify rasterizer that a 3DS memory region has been changed
virtual void NotifyFlush(u32 paddr, u32 size) = 0;
virtual void NotifyFlush(u32 addr, u32 size) = 0;
};

View File

@ -500,6 +500,23 @@ struct Regs {
RGBA4 = 4,
};
// Returns the number of bytes in the specified color format
static unsigned BytesPerColorPixel(u32 format) {
switch (format) {
case ColorFormat::RGBA8:
return 4;
case ColorFormat::RGB8:
return 3;
case ColorFormat::RGB5A1:
case ColorFormat::RGB565:
case ColorFormat::RGBA4:
return 2;
default:
LOG_CRITICAL(HW_GPU, "Unknown color format %u", format);
UNIMPLEMENTED();
}
}
INSERT_PADDING_WORDS(0x6);
DepthFormat depth_format;

View File

@ -12,83 +12,86 @@
namespace PicaToGL {
static GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) {
switch (mode) {
case Pica::Regs::TextureConfig::WrapMode::ClampToEdge:
inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) {
static const GLenum wrap_mode_table[] = {
GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge
0, // Unknown
GL_REPEAT, // WrapMode::Repeat
GL_MIRRORED_REPEAT // WrapMode::MirroredRepeat
};
// Range check table for input
if (mode >= sizeof(wrap_mode_table) / sizeof(GLenum)) {
LOG_CRITICAL(Render_OpenGL, "Unknown texture wrap mode %d", mode);
UNREACHABLE();
return GL_CLAMP_TO_EDGE;
case Pica::Regs::TextureConfig::WrapMode::Repeat:
return GL_REPEAT;
case Pica::Regs::TextureConfig::WrapMode::MirroredRepeat:
return GL_MIRRORED_REPEAT;
default:
}
GLenum gl_mode = wrap_mode_table[mode];
// Check for dummy values indicating an unknown mode
if (gl_mode == 0) {
LOG_CRITICAL(Render_OpenGL, "Unknown texture wrap mode %d", mode);
UNIMPLEMENTED();
return GL_CLAMP_TO_EDGE;
}
return gl_mode;
}
static GLenum BlendFunc(u32 factor) {
switch (factor) {
case Pica::registers.output_merger.alpha_blending.Zero:
return GL_ZERO;
case Pica::registers.output_merger.alpha_blending.One:
return GL_ONE;
case Pica::registers.output_merger.alpha_blending.SourceColor:
return GL_SRC_COLOR;
case Pica::registers.output_merger.alpha_blending.OneMinusSourceColor:
return GL_ONE_MINUS_SRC_COLOR;
case Pica::registers.output_merger.alpha_blending.DestColor:
return GL_DST_COLOR;
case Pica::registers.output_merger.alpha_blending.OneMinusDestColor:
return GL_ONE_MINUS_DST_COLOR;
case Pica::registers.output_merger.alpha_blending.SourceAlpha:
return GL_SRC_ALPHA;
case Pica::registers.output_merger.alpha_blending.OneMinusSourceAlpha:
return GL_ONE_MINUS_SRC_ALPHA;
case Pica::registers.output_merger.alpha_blending.DestAlpha:
return GL_DST_ALPHA;
case Pica::registers.output_merger.alpha_blending.OneMinusDestAlpha:
return GL_ONE_MINUS_DST_ALPHA;
case Pica::registers.output_merger.alpha_blending.ConstantColor:
return GL_CONSTANT_COLOR;
case Pica::registers.output_merger.alpha_blending.OneMinusConstantColor:
return GL_ONE_MINUS_CONSTANT_COLOR;
case Pica::registers.output_merger.alpha_blending.ConstantAlpha:
return GL_CONSTANT_ALPHA;
case Pica::registers.output_merger.alpha_blending.OneMinusConstantAlpha:
return GL_ONE_MINUS_CONSTANT_ALPHA;
case Pica::registers.output_merger.alpha_blending.SourceAlphaSaturate:
return GL_SRC_ALPHA_SATURATE;
default:
inline GLenum BlendFunc(u32 factor) {
static const GLenum blend_func_table[] = {
GL_ZERO, // BlendFactor::Zero
GL_ONE, // BlendFactor::One
GL_SRC_COLOR, // BlendFactor::SourceColor
GL_ONE_MINUS_SRC_COLOR, // BlendFactor::OneMinusSourceColor
GL_DST_COLOR, // BlendFactor::DestColor
GL_ONE_MINUS_DST_COLOR, // BlendFactor::OneMinusDestColor
GL_SRC_ALPHA, // BlendFactor::SourceAlpha
GL_ONE_MINUS_SRC_ALPHA, // BlendFactor::OneMinusSourceAlpha
GL_DST_ALPHA, // BlendFactor::DestAlpha
GL_ONE_MINUS_DST_ALPHA, // BlendFactor::OneMinusDestAlpha
GL_CONSTANT_COLOR, // BlendFactor::ConstantColor
GL_ONE_MINUS_CONSTANT_COLOR, // BlendFactor::OneMinusConstantColor
GL_CONSTANT_ALPHA, // BlendFactor::ConstantAlpha
GL_ONE_MINUS_CONSTANT_ALPHA, // BlendFactor::OneMinusConstantAlpha
GL_SRC_ALPHA_SATURATE, // BlendFactor::SourceAlphaSaturate
};
// Range check table for input
if (factor >= sizeof(blend_func_table) / sizeof(GLenum)) {
LOG_CRITICAL(Render_OpenGL, "Unknown blend factor %d", factor);
UNIMPLEMENTED();
UNREACHABLE();
return GL_ONE;
}
return blend_func_table[factor];
}
static GLenum CompareFunc(u32 func) {
switch (func) {
case Pica::registers.output_merger.Never:
return GL_NEVER;
case Pica::registers.output_merger.Always:
return GL_ALWAYS;
case Pica::registers.output_merger.Equal:
return GL_EQUAL;
case Pica::registers.output_merger.NotEqual:
return GL_NOTEQUAL;
case Pica::registers.output_merger.LessThan:
return GL_LESS;
case Pica::registers.output_merger.LessThanOrEqual:
return GL_LEQUAL;
case Pica::registers.output_merger.GreaterThan:
return GL_GREATER;
case Pica::registers.output_merger.GreaterThanOrEqual:
return GL_GEQUAL;
default:
inline GLenum CompareFunc(u32 func) {
static const GLenum compare_func_table[] = {
GL_NEVER, // CompareFunc::Never
GL_ALWAYS, // CompareFunc::Always
GL_EQUAL, // CompareFunc::Equal
GL_NOTEQUAL, // CompareFunc::NotEqual
GL_LESS, // CompareFunc::LessThan
GL_LEQUAL, // CompareFunc::LessThanOrEqual
GL_GREATER, // CompareFunc::GreaterThan
GL_GEQUAL, // CompareFunc::GreaterThanOrEqual
};
// Range check table for input
if (func >= sizeof(compare_func_table) / sizeof(GLenum)) {
LOG_CRITICAL(Render_OpenGL, "Unknown compare function %d", func);
UNIMPLEMENTED();
UNREACHABLE();
return GL_ALWAYS;
}
return compare_func_table[func];
}
} // namespace

View File

@ -17,32 +17,12 @@
#include <memory>
u32 ColorFormatBytesPerPixel(u32 format) {
switch (format) {
case Pica::registers.framebuffer.RGBA8:
return 4;
case Pica::registers.framebuffer.RGB8:
return 3;
case Pica::registers.framebuffer.RGB5A1:
case Pica::registers.framebuffer.RGB565:
case Pica::registers.framebuffer.RGBA4:
return 2;
default:
LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer color format %x", format);
UNIMPLEMENTED();
break;
}
return 0;
}
RasterizerOpenGL::RasterizerOpenGL() : last_fb_color_addr(0), last_fb_depth_addr(0) {
}
RasterizerOpenGL::~RasterizerOpenGL() {
// Set context for automatic resource destruction
render_window->MakeCurrent();
}
void RasterizerOpenGL::InitObjects() {
@ -109,7 +89,7 @@ void RasterizerOpenGL::InitObjects() {
// Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation
fb_color_texture.texture.Create();
ReconfigColorTexture(fb_color_texture, Pica::registers.framebuffer.RGBA8, 1, 1);
ReconfigureColorTexture(fb_color_texture, Pica::registers.framebuffer.RGBA8, 1, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -117,7 +97,7 @@ void RasterizerOpenGL::InitObjects() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
fb_depth_texture.texture.Create();
ReconfigDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1);
ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -138,13 +118,8 @@ void RasterizerOpenGL::InitObjects() {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_color_texture.texture.GetHandle(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fb_depth_texture.texture.GetHandle(), 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_CRITICAL(Render_OpenGL, "Framebuffer setup failed, status %X", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
}
void RasterizerOpenGL::SetWindow(EmuWindow* window) {
render_window = window;
ASSERT_MSG(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
"OpenGL rasterizer framebuffer setup failed, status %X", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
void RasterizerOpenGL::AddTriangle(const Pica::VertexShader::OutputVertex& v0,
@ -156,8 +131,6 @@ void RasterizerOpenGL::AddTriangle(const Pica::VertexShader::OutputVertex& v0,
}
void RasterizerOpenGL::DrawTriangles() {
render_window->MakeCurrent();
state.Apply();
SyncFramebuffer();
@ -169,16 +142,14 @@ void RasterizerOpenGL::DrawTriangles() {
vertex_batch.clear();
}
void RasterizerOpenGL::NotifyPreCopy(PAddr src_addr, u32 size) {
void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) {
if (!Settings::values.use_hw_renderer)
return;
render_window->MakeCurrent();
state.Apply();
PAddr cur_fb_color_addr = Pica::registers.framebuffer.GetColorBufferPhysicalAddress();
u32 cur_fb_color_size = ColorFormatBytesPerPixel(Pica::registers.framebuffer.color_format)
u32 cur_fb_color_size = Pica::registers.framebuffer.BytesPerColorPixel(Pica::registers.framebuffer.color_format)
* Pica::registers.framebuffer.GetWidth() * Pica::registers.framebuffer.GetHeight();
PAddr cur_fb_depth_addr = Pica::registers.framebuffer.GetDepthBufferPhysicalAddress();
@ -186,18 +157,18 @@ void RasterizerOpenGL::NotifyPreCopy(PAddr src_addr, u32 size) {
* Pica::registers.framebuffer.GetWidth() * Pica::registers.framebuffer.GetHeight();
// If source memory region overlaps 3DS framebuffers, commit them before the copy happens
PAddr max_low_addr_bound = std::max(src_addr, cur_fb_color_addr);
PAddr min_hi_addr_bound = std::min(src_addr + size, cur_fb_color_addr + cur_fb_color_size);
PAddr max_low_addr_bound = std::max(addr, cur_fb_color_addr);
PAddr min_hi_addr_bound = std::min(addr + size, cur_fb_color_addr + cur_fb_color_size);
if (max_low_addr_bound <= min_hi_addr_bound) {
CommitFramebuffer();
CommitColorBuffer();
}
max_low_addr_bound = std::max(src_addr, cur_fb_depth_addr);
min_hi_addr_bound = std::min(src_addr + size, cur_fb_depth_addr + cur_fb_depth_size);
max_low_addr_bound = std::max(addr, cur_fb_depth_addr);
min_hi_addr_bound = std::min(addr + size, cur_fb_depth_addr + cur_fb_depth_size);
if (max_low_addr_bound <= min_hi_addr_bound) {
CommitFramebuffer();
CommitDepthBuffer();
}
}
@ -205,12 +176,10 @@ void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
if (!Settings::values.use_hw_renderer)
return;
render_window->MakeCurrent();
state.Apply();
PAddr cur_fb_color_addr = Pica::registers.framebuffer.GetColorBufferPhysicalAddress();
u32 cur_fb_color_size = ColorFormatBytesPerPixel(Pica::registers.framebuffer.color_format)
u32 cur_fb_color_size = Pica::registers.framebuffer.BytesPerColorPixel(Pica::registers.framebuffer.color_format)
* Pica::registers.framebuffer.GetWidth() * Pica::registers.framebuffer.GetHeight();
PAddr cur_fb_depth_addr = Pica::registers.framebuffer.GetDepthBufferPhysicalAddress();
@ -236,7 +205,7 @@ void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
res_cache.NotifyFlush(addr, size);
}
void RasterizerOpenGL::ReconfigColorTexture(TextureInfo& texture, u32 format, u32 width, u32 height) {
void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, u32 format, u32 width, u32 height) {
GLint internal_format;
texture.format = format;
@ -293,7 +262,7 @@ void RasterizerOpenGL::ReconfigColorTexture(TextureInfo& texture, u32 format, u3
texture.gl_format, texture.gl_type, nullptr);
}
void RasterizerOpenGL::ReconfigDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) {
void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) {
GLint internal_format;
texture.format = format;
@ -351,15 +320,16 @@ void RasterizerOpenGL::SyncFramebuffer() {
// Commit if fb modified in any way
if (fb_modified) {
CommitFramebuffer();
CommitColorBuffer();
CommitDepthBuffer();
}
// Reconfigure framebuffer textures if any property has changed
if (fb_prop_changed) {
ReconfigColorTexture(fb_color_texture, new_fb_color_format,
ReconfigureColorTexture(fb_color_texture, new_fb_color_format,
Pica::registers.framebuffer.GetWidth(), Pica::registers.framebuffer.GetHeight());
ReconfigDepthTexture(fb_depth_texture, new_fb_depth_format,
ReconfigureDepthTexture(fb_depth_texture, new_fb_depth_format,
Pica::registers.framebuffer.GetWidth(), Pica::registers.framebuffer.GetHeight());
// Only attach depth buffer as stencil if it supports stencil
@ -385,10 +355,6 @@ void RasterizerOpenGL::SyncFramebuffer() {
last_fb_color_addr = cur_fb_color_addr;
last_fb_depth_addr = cur_fb_depth_addr;
// Currently not needed b/c of reloading buffers below, but will be needed for high-res rendering
//glDepthMask(GL_TRUE);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ReloadColorBuffer();
ReloadDepthBuffer();
}
@ -549,7 +515,7 @@ void RasterizerOpenGL::ReloadColorBuffer() {
if (color_buffer == nullptr)
return;
u32 bytes_per_pixel = ColorFormatBytesPerPixel(fb_color_texture.format);
u32 bytes_per_pixel = Pica::registers.framebuffer.BytesPerColorPixel(fb_color_texture.format);
std::unique_ptr<u8[]> temp_fb_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]);
@ -626,12 +592,12 @@ void RasterizerOpenGL::ReloadDepthBuffer() {
fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_fb_depth_buffer.get());
}
void RasterizerOpenGL::CommitFramebuffer() {
void RasterizerOpenGL::CommitColorBuffer() {
if (last_fb_color_addr != 0) {
u8* color_buffer = Memory::GetPhysicalPointer(last_fb_color_addr);
if (color_buffer != nullptr) {
u32 bytes_per_pixel = ColorFormatBytesPerPixel(fb_color_texture.format);
u32 bytes_per_pixel = Pica::registers.framebuffer.BytesPerColorPixel(fb_color_texture.format);
std::unique_ptr<u8[]> temp_gl_color_buffer(new u8[fb_color_texture.width * fb_color_texture.height * bytes_per_pixel]);
@ -656,7 +622,9 @@ void RasterizerOpenGL::CommitFramebuffer() {
}
}
}
}
void RasterizerOpenGL::CommitDepthBuffer() {
if (last_fb_depth_addr != 0) {
// TODO: Output seems correct visually, but doesn't quite match sw renderer output. One of them is wrong.
u8* depth_buffer = Memory::GetPhysicalPointer(last_fb_depth_addr);

View File

@ -18,10 +18,7 @@ public:
/// Initialize API-specific GPU objects
void InitObjects() override;
/// Set the window (context) to draw with
void SetWindow(EmuWindow* window) override;
/// Converts the triangle verts to hardware data format and adds them to the current batch
/// Queues the primitive formed by the given vertices for rendering
void AddTriangle(const Pica::VertexShader::OutputVertex& v0,
const Pica::VertexShader::OutputVertex& v1,
const Pica::VertexShader::OutputVertex& v2) override;
@ -29,8 +26,8 @@ public:
/// Draw the current batch of triangles
void DrawTriangles() override;
/// Notify rasterizer that a copy within 3DS memory will occur after this notification
void NotifyPreCopy(PAddr src_addr, u32 size) override;
/// Notify rasterizer that the specified 3DS memory region will be read from after this notification
void NotifyPreRead(PAddr addr, u32 size) override;
/// Notify rasterizer that a 3DS memory region has been changed
void NotifyFlush(PAddr addr, u32 size) override;
@ -95,10 +92,10 @@ private:
};
/// Reconfigure the OpenGL color texture to use the given format and dimensions
void ReconfigColorTexture(TextureInfo& texture, u32 format, u32 width, u32 height);
void ReconfigureColorTexture(TextureInfo& texture, u32 format, u32 width, u32 height);
/// Reconfigure the OpenGL depth texture to use the given format and dimensions
void ReconfigDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height);
void ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height);
/// Syncs the state and contents of the OpenGL framebuffer to match the current PICA framebuffer
void SyncFramebuffer();
@ -113,13 +110,19 @@ private:
void ReloadDepthBuffer();
/**
* Save the current OpenGL framebuffer to the current PICA framebuffer in 3ds memory
* Save the current OpenGL color framebuffer to the current PICA framebuffer in 3ds memory
* Loads the OpenGL framebuffer textures into temporary buffers
* Then copies into the 3ds framebuffer using proper Morton order
*/
void CommitFramebuffer();
void CommitColorBuffer();
/**
* Save the current OpenGL depth framebuffer to the current PICA framebuffer in 3ds memory
* Loads the OpenGL framebuffer textures into temporary buffers
* Then copies into the 3ds framebuffer using proper Morton order
*/
void CommitDepthBuffer();
EmuWindow* render_window;
RasterizerCacheOpenGL res_cache;
std::vector<HardwareVertex> vertex_batch;

View File

@ -2,7 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/make_unique.h"
#include "core/memory.h"
#include "video_core/renderer_opengl/gl_pica_to_gl.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/debug_utils/debug_utils.h"
@ -21,7 +24,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, int texture_u
state.texture_units[texture_unit].texture_2d = cached_texture->second->texture.GetHandle();
state.Apply();
} else {
std::unique_ptr<CachedTexture> new_texture(new CachedTexture());
std::unique_ptr<CachedTexture> new_texture = Common::make_unique<CachedTexture>();
new_texture->texture.Create();
state.texture_units[texture_unit].texture_2d = new_texture->texture.GetHandle();
@ -31,8 +34,8 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, int texture_u
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_WRAP_S, PicaToGL::WrapMode(config.config.wrap_s.Value()));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, PicaToGL::WrapMode(config.config.wrap_t.Value()));
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));
const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format);
@ -40,11 +43,12 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, int texture_u
new_texture->height = info.height;
new_texture->size = info.width * info.height * Pica::Regs::NibblesPerPixel(info.format);
u8* texture_src_data = Memory::GetPhysicalPointer(texture_addr);
std::unique_ptr<Math::Vec4<u8>[]> temp_texture_buffer_rgba(new Math::Vec4<u8>[info.width * info.height]);
for (int y = 0; y < info.height; ++y) {
for (int x = 0; x < info.width; ++x) {
temp_texture_buffer_rgba[x + info.width * y] = Pica::DebugUtils::LookupTexture(Memory::GetPhysicalPointer(texture_addr), x, info.height - 1 - y, info);
temp_texture_buffer_rgba[x + info.width * y] = Pica::DebugUtils::LookupTexture(texture_src_data, x, info.height - 1 - y, info);
}
}
@ -56,7 +60,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, int texture_u
void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size) {
// Flush any texture that falls in the flushed region
for (auto it = texture_cache.begin(); it != texture_cache.end();) {
for (auto it = texture_cache.begin(); it != texture_cache.upper_bound(addr + size);) {
PAddr max_low_addr_bound = std::max(addr, it->first);
PAddr min_hi_addr_bound = std::min(addr + size, it->first + it->second->size);

View File

@ -5,20 +5,11 @@
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
// OGLResource base class
OGLResource::OGLResource() : handle(0) {
}
OGLResource::~OGLResource() {
}
void OGLResource::Release() {
}
// Textures
OGLTexture::OGLTexture() : handle(0) {
}
OGLTexture::~OGLTexture() {
Release();
}
@ -37,6 +28,10 @@ void OGLTexture::Release() {
}
// Shaders
OGLShader::OGLShader() : handle(0) {
}
OGLShader::~OGLShader() {
Release();
}
@ -55,6 +50,10 @@ void OGLShader::Release() {
}
// Buffer objects
OGLBuffer::OGLBuffer() : handle(0) {
}
OGLBuffer::~OGLBuffer() {
Release();
}
@ -73,6 +72,10 @@ void OGLBuffer::Release() {
}
// Vertex array objects
OGLVertexArray::OGLVertexArray() : handle(0) {
}
OGLVertexArray::~OGLVertexArray() {
Release();
}
@ -91,6 +94,10 @@ void OGLVertexArray::Release() {
}
// Framebuffers
OGLFramebuffer::OGLFramebuffer() : handle(0) {
}
OGLFramebuffer::~OGLFramebuffer() {
Release();
}

View File

@ -8,74 +8,102 @@
#include "generated/gl_3_2_core.h"
class OGLResource : NonCopyable {
class OGLTexture : public NonCopyable {
public:
OGLResource();
virtual ~OGLResource();
OGLTexture();
~OGLTexture();
/// Returns the internal OpenGL resource handle for this resource
inline GLuint GetHandle() {
return handle;
}
/// Creates a new internal OpenGL resource and stores the handle
void Create();
/// Deletes the internal OpenGL resource
virtual void Release();
void Release();
protected:
GLuint handle;
};
class OGLTexture : public OGLResource {
class OGLShader : public NonCopyable {
public:
~OGLTexture() override;
OGLShader();
~OGLShader();
/// Creates a new internal OpenGL resource and stores the handle
void Create();
/// Deletes the internal OpenGL resource
void Release() override;
};
class OGLShader : public OGLResource {
public:
~OGLShader() override;
/// Returns the internal OpenGL resource handle for this resource
inline GLuint GetHandle() {
return handle;
}
/// Creates a new internal OpenGL resource and stores the handle
void Create(const char* vert_shader, const char* frag_shader);
/// Deletes the internal OpenGL resource
void Release() override;
void Release();
protected:
GLuint handle;
};
class OGLBuffer : public OGLResource {
class OGLBuffer : public NonCopyable {
public:
~OGLBuffer() override;
OGLBuffer();
~OGLBuffer();
/// Returns the internal OpenGL resource handle for this resource
inline GLuint GetHandle() {
return handle;
}
/// Creates a new internal OpenGL resource and stores the handle
void Create();
/// Deletes the internal OpenGL resource
void Release() override;
void Release();
protected:
GLuint handle;
};
class OGLVertexArray : public OGLResource {
class OGLVertexArray : public NonCopyable {
public:
~OGLVertexArray() override;
OGLVertexArray();
~OGLVertexArray();
/// Returns the internal OpenGL resource handle for this resource
inline GLuint GetHandle() {
return handle;
}
/// Creates a new internal OpenGL resource and stores the handle
void Create();
/// Deletes the internal OpenGL resource
void Release() override;
void Release();
protected:
GLuint handle;
};
class OGLFramebuffer : public OGLResource {
class OGLFramebuffer : public NonCopyable {
public:
~OGLFramebuffer() override;
OGLFramebuffer();
~OGLFramebuffer();
/// Returns the internal OpenGL resource handle for this resource
inline GLuint GetHandle() {
return handle;
}
/// Creates a new internal OpenGL resource and stores the handle
void Create();
/// Deletes the internal OpenGL resource
void Release() override;
void Release();
protected:
GLuint handle;
};

View File

@ -191,33 +191,33 @@ vec4 GetSource(int source) {
return g_last_tex_env_out;
}
return vec4(0.0, 0.0, 0.0, 0.0);
return vec4(0.0);
}
vec3 GetColorModifier(int factor, vec4 color) {
if (factor == COLORMODIFIER_SOURCECOLOR) {
return color.rgb;
} else if (factor == COLORMODIFIER_ONEMINUSSOURCECOLOR) {
return vec3(1.0, 1.0, 1.0) - color.rgb;
return vec3(1.0) - color.rgb;
} else if (factor == COLORMODIFIER_SOURCEALPHA) {
return color.aaa;
} else if (factor == COLORMODIFIER_ONEMINUSSOURCEALPHA) {
return vec3(1.0, 1.0, 1.0) - color.aaa;
return vec3(1.0) - color.aaa;
} else if (factor == COLORMODIFIER_SOURCERED) {
return color.rrr;
} else if (factor == COLORMODIFIER_ONEMINUSSOURCERED) {
return vec3(1.0, 1.0, 1.0) - color.rrr;
return vec3(1.0) - color.rrr;
} else if (factor == COLORMODIFIER_SOURCEGREEN) {
return color.ggg;
} else if (factor == COLORMODIFIER_ONEMINUSSOURCEGREEN) {
return vec3(1.0, 1.0, 1.0) - color.ggg;
return vec3(1.0) - color.ggg;
} else if (factor == COLORMODIFIER_SOURCEBLUE) {
return color.bbb;
} else if (factor == COLORMODIFIER_ONEMINUSSOURCEBLUE) {
return vec3(1.0, 1.0, 1.0) - color.bbb;
return vec3(1.0) - color.bbb;
}
return vec3(0.0, 0.0, 0.0);
return vec3(0.0);
}
float GetAlphaModifier(int factor, vec4 color) {
@ -250,9 +250,9 @@ vec3 ColorCombine(int op, vec3 color[3]) {
} else if (op == OPERATION_ADD) {
return min(color[0] + color[1], 1.0);
} else if (op == OPERATION_ADDSIGNED) {
return clamp(color[0] + color[1] - vec3(0.5, 0.5, 0.5), 0.0, 1.0);
return clamp(color[0] + color[1] - vec3(0.5), 0.0, 1.0);
} else if (op == OPERATION_LERP) {
return color[0] * color[2] + color[1] * (vec3(1.0, 1.0, 1.0) - color[2]);
return color[0] * color[2] + color[1] * (vec3(1.0) - color[2]);
} else if (op == OPERATION_SUBTRACT) {
return max(color[0] - color[1], 0.0);
} else if (op == OPERATION_MULTIPLYTHENADD) {
@ -261,7 +261,7 @@ vec3 ColorCombine(int op, vec3 color[3]) {
return min(color[0] + color[1], 1.0) * color[2];
}
return vec3(0.0, 0.0, 0.0);
return vec3(0.0);
}
float AlphaCombine(int op, float alpha[3]) {

View File

@ -42,7 +42,7 @@ OpenGLState::OpenGLState() {
draw.shader_program = 0;
}
void OpenGLState::Apply() {
const void OpenGLState::Apply() {
// Culling
if (cull.enabled) {
if (cull.enabled != cur_state.cull.enabled) {

View File

@ -42,6 +42,7 @@ public:
} color; // GL_BLEND_COLOR
} blend;
// 3 texture units - one for each that is used in PICA fragment shader emulation
struct {
bool enabled_2d; // GL_TEXTURE_2D
GLuint texture_2d; // GL_TEXTURE_BINDING_2D
@ -57,12 +58,12 @@ public:
OpenGLState();
/// Get the currently active OpenGL state
static OpenGLState GetCurState() {
static const OpenGLState& GetCurState() {
return cur_state;
}
/// Apply this state as the current OpenGL state
void Apply();
const void Apply();
private:
static OpenGLState cur_state;

View File

@ -348,7 +348,6 @@ void RendererOpenGL::UpdateFramerate() {
*/
void RendererOpenGL::SetWindow(EmuWindow* window) {
render_window = window;
hw_rasterizer->SetWindow(window);
}
/// Initialize the renderer