mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 11:31:04 +00:00
Addressed smaller comments, fb color/depth separate
This commit is contained in:
parent
d517757053
commit
dfc807daf9
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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]) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -348,7 +348,6 @@ void RendererOpenGL::UpdateFramerate() {
|
||||
*/
|
||||
void RendererOpenGL::SetWindow(EmuWindow* window) {
|
||||
render_window = window;
|
||||
hw_rasterizer->SetWindow(window);
|
||||
}
|
||||
|
||||
/// Initialize the renderer
|
||||
|
Loading…
Reference in New Issue
Block a user