From 05dc633a8c35221ce8d6abe6ddf027f8b0bab6c2 Mon Sep 17 00:00:00 2001 From: tfarley Date: Mon, 18 May 2015 21:21:33 -0700 Subject: OpenGL renderer --- .../renderer_opengl/gl_rasterizer_cache.cpp | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/video_core/renderer_opengl/gl_rasterizer_cache.cpp (limited to 'src/video_core/renderer_opengl/gl_rasterizer_cache.cpp') diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp new file mode 100644 index 00000000..6f88a8b2 --- /dev/null +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -0,0 +1,77 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/make_unique.h" +#include "common/math_util.h" + +#include "core/memory.h" + +#include "video_core/renderer_opengl/gl_rasterizer_cache.h" +#include "video_core/renderer_opengl/pica_to_gl.h" +#include "video_core/debug_utils/debug_utils.h" +#include "video_core/math.h" + +RasterizerCacheOpenGL::~RasterizerCacheOpenGL() { + FullFlush(); +} + +void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned texture_unit, const Pica::Regs::FullTextureConfig& config) { + PAddr texture_addr = config.config.GetPhysicalAddress(); + + const auto cached_texture = texture_cache.find(texture_addr); + + if (cached_texture != texture_cache.end()) { + state.texture_units[texture_unit].texture_2d = cached_texture->second->texture.handle; + state.Apply(); + } else { + std::unique_ptr new_texture = Common::make_unique(); + + new_texture->texture.Create(); + 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_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); + + new_texture->width = info.width; + 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[]> temp_texture_buffer_rgba(new Math::Vec4[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(texture_src_data, x, info.height - 1 - y, info); + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp_texture_buffer_rgba.get()); + + texture_cache.emplace(texture_addr, std::move(new_texture)); + } +} + +void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size) { + // Flush any texture that falls in the flushed region + // TODO: Optimize by also inserting upper bound (addr + size) of each texture into the same map and also narrow using lower_bound + auto cache_upper_bound = texture_cache.upper_bound(addr + size); + for (auto it = texture_cache.begin(); it != cache_upper_bound;) { + if (MathUtil::IntervalsIntersect(addr, size, it->first, it->second->size)) { + it = texture_cache.erase(it); + } else { + ++it; + } + } +} + +void RasterizerCacheOpenGL::FullFlush() { + texture_cache.clear(); +} -- cgit v1.2.3