From e543320129950cceba99ec225314dd1f2ef0ff0b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 8 Feb 2019 19:28:01 -0400 Subject: [PATCH] Implement linear textures (#2089) --- .../renderer_opengl/gl_rasterizer_cache.cpp | 42 ++++++++++++++++--- .../renderer_opengl/gl_rasterizer_cache.h | 2 + 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index b77768c792..126dcbbb3f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -125,6 +125,9 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); + if (!params.is_tiled) { + params.pitch = config.tic.Pitch(); + } params.unaligned_height = config.tic.Height(); params.target = SurfaceTargetFromTextureType(config.tic.texture_type); params.identity = SurfaceClass::Uploaded; @@ -191,7 +194,13 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; params.component_type = ComponentTypeFromRenderTarget(config.format); params.type = GetFormatType(params.pixel_format); - params.width = config.width; + if (params.is_tiled) { + params.width = config.width; + } else { + params.pitch = config.width; + const u32 bpp = params.GetFormatBpp() / 8; + params.width = params.pitch / bpp; + } params.height = config.height; params.unaligned_height = config.height; params.target = SurfaceTarget::Texture2D; @@ -688,9 +697,20 @@ void CachedSurface::LoadGLBuffer() { for (u32 i = 0; i < params.max_mip_level; i++) SwizzleFunc(MortonSwizzleMode::MortonToLinear, params, gl_buffer[i], i); } else { - const auto texture_src_data{Memory::GetPointer(params.addr)}; - const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl}; - gl_buffer[0].assign(texture_src_data, texture_src_data_end); + const u32 bpp = params.GetFormatBpp() / 8; + const u32 copy_size = params.width * bpp; + if (params.pitch == copy_size) { + std::memcpy(gl_buffer[0].data(), Memory::GetPointer(params.addr), + params.size_in_bytes_gl); + } else { + const u8* start = Memory::GetPointer(params.addr); + u8* write_to = gl_buffer[0].data(); + for (u32 h = params.height; h > 0; h--) { + std::memcpy(write_to, start, copy_size); + start += params.pitch; + write_to += copy_size; + } + } } for (u32 i = 0; i < params.max_mip_level; i++) { ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), @@ -727,7 +747,19 @@ void CachedSurface::FlushGLBuffer() { SwizzleFunc(MortonSwizzleMode::LinearToMorton, params, gl_buffer[0], 0); } else { - std::memcpy(Memory::GetPointer(GetAddr()), gl_buffer[0].data(), GetSizeInBytes()); + const u32 bpp = params.GetFormatBpp() / 8; + const u32 copy_size = params.width * bpp; + if (params.pitch == copy_size) { + std::memcpy(Memory::GetPointer(params.addr), gl_buffer[0].data(), GetSizeInBytes()); + } else { + u8* start = Memory::GetPointer(params.addr); + const u8* read_to = gl_buffer[0].data(); + for (u32 h = params.height; h > 0; h--) { + std::memcpy(start, read_to, copy_size); + start += params.pitch; + read_to += copy_size; + } + } } } diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 490b8252eb..49ff99e2fb 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "common/alignment.h" @@ -272,6 +273,7 @@ struct SurfaceParams { u32 height; u32 depth; u32 unaligned_height; + u32 pitch; SurfaceTarget target; SurfaceClass identity; u32 max_mip_level;