mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-07-11 02:14:43 -06:00
video_core: harden fill surface uploads
This commit is contained in:
parent
3330f835f4
commit
33bda94b8c
@ -96,7 +96,7 @@ if (BUNDLE_TARGET_EXECUTE)
|
||||
# Some local filesystem providers attach FinderInfo/resource-fork xattrs during copy,
|
||||
# which causes codesign to reject the bundle.
|
||||
find_program(xattr_executable xattr REQUIRED)
|
||||
execute_process(COMMAND "${xattr_executable}" -cr "${executable_path}"
|
||||
execute_process(COMMAND find "${executable_path}" -exec "${xattr_executable}" -c "{}" "+"
|
||||
RESULT_VARIABLE xattr_result)
|
||||
if (NOT xattr_result EQUAL "0")
|
||||
message(FATAL_ERROR "xattr cleanup failed: ${xattr_result}")
|
||||
|
||||
@ -1150,6 +1150,9 @@ void RasterizerCache<T>::DownloadFillSurface(Surface& surface, SurfaceInterval i
|
||||
const u32 flush_start = boost::icl::first(interval);
|
||||
const u32 flush_end = boost::icl::last_next(interval);
|
||||
ASSERT(flush_start >= surface.addr && flush_end <= surface.end);
|
||||
if (surface.fill_size == 0 || surface.fill_size > surface.fill_data.size()) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryRef dest_ptr = memory.GetPhysicalRef(flush_start);
|
||||
if (!dest_ptr) [[unlikely]] {
|
||||
@ -1159,21 +1162,9 @@ void RasterizerCache<T>::DownloadFillSurface(Surface& surface, SurfaceInterval i
|
||||
const u32 start_offset = flush_start - surface.addr;
|
||||
const u32 download_size =
|
||||
std::clamp(flush_end - flush_start, 0u, static_cast<u32>(dest_ptr.GetSize()));
|
||||
const u32 coarse_start_offset = start_offset - (start_offset % surface.fill_size);
|
||||
const u32 backup_bytes = start_offset % surface.fill_size;
|
||||
|
||||
std::array<u8, 4> backup_data;
|
||||
if (backup_bytes) {
|
||||
std::memcpy(backup_data.data(), &dest_ptr[coarse_start_offset], backup_bytes);
|
||||
}
|
||||
|
||||
for (u32 offset = coarse_start_offset; offset < download_size; offset += surface.fill_size) {
|
||||
std::memcpy(&dest_ptr[offset], &surface.fill_data[0],
|
||||
std::min(surface.fill_size, download_size - offset));
|
||||
}
|
||||
|
||||
if (backup_bytes) {
|
||||
std::memcpy(&dest_ptr[coarse_start_offset], &backup_data[0], backup_bytes);
|
||||
const u32 fill_start = start_offset % surface.fill_size;
|
||||
for (u32 offset = 0; offset < download_size; ++offset) {
|
||||
dest_ptr[offset] = surface.fill_data[(fill_start + offset) % surface.fill_size];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,13 @@
|
||||
#include "video_core/texture/texture_decode.h"
|
||||
|
||||
namespace VideoCore {
|
||||
namespace {
|
||||
|
||||
bool IsValidFillSize(u32 fill_size) {
|
||||
return fill_size != 0 && fill_size <= sizeof(SurfaceBase::fill_data);
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
SurfaceBase::SurfaceBase(const SurfaceParams& params, const SurfaceFlagBits& initial_flag_bits)
|
||||
: SurfaceParams{params}, flags(initial_flag_bits) {}
|
||||
@ -20,6 +27,9 @@ bool SurfaceBase::CanFill(const SurfaceParams& dest_surface, SurfaceInterval fil
|
||||
boost::icl::last_next(fill_interval) <= end && // dest_surface is within our fill range
|
||||
dest_surface.FromInterval(fill_interval).GetInterval() ==
|
||||
fill_interval) { // make sure interval is a rectangle in dest surface
|
||||
if (!IsValidFillSize(fill_size)) {
|
||||
return false;
|
||||
}
|
||||
if (fill_size * 8 != dest_surface.GetFormatBpp()) {
|
||||
// Check if bits repeat for our fill_size
|
||||
const u32 dest_bytes_per_pixel = std::max(dest_surface.GetFormatBpp() / 8, 1u);
|
||||
@ -130,6 +140,7 @@ bool SurfaceBase::HasNormalMap() const noexcept {
|
||||
ClearValue SurfaceBase::MakeClearValue(PAddr copy_addr, PixelFormat dst_format) {
|
||||
const SurfaceType dst_type = GetFormatType(dst_format);
|
||||
const std::array fill_buffer = MakeFillBuffer(copy_addr);
|
||||
const bool valid_fill = IsValidFillSize(fill_size);
|
||||
|
||||
ClearValue result{};
|
||||
switch (dst_type) {
|
||||
@ -141,7 +152,8 @@ ClearValue SurfaceBase::MakeClearValue(PAddr copy_addr, PixelFormat dst_format)
|
||||
const std::size_t tile_size = Pica::Texture::CalculateTileSize(tex_info.format);
|
||||
std::vector<u8> fill_tile(std::max(tile_size, fill_buffer.size()));
|
||||
for (std::size_t i = 0; i < fill_tile.size(); i++) {
|
||||
fill_tile[i] = fill_data[(copy_addr - addr + i) % fill_size];
|
||||
fill_tile[i] = valid_fill ? fill_data[(copy_addr - addr + i) % fill_size]
|
||||
: fill_buffer[i % fill_buffer.size()];
|
||||
}
|
||||
const auto color = Pica::Texture::LookupTexture(fill_tile.data(), 0, 0, tex_info);
|
||||
result.color = color / 255.f;
|
||||
@ -173,9 +185,12 @@ ClearValue SurfaceBase::MakeClearValue(PAddr copy_addr, PixelFormat dst_format)
|
||||
}
|
||||
|
||||
std::array<u8, 4> SurfaceBase::MakeFillBuffer(PAddr copy_addr) {
|
||||
const PAddr fill_offset = (copy_addr - addr) % fill_size;
|
||||
std::array<u8, 4> fill_buffer;
|
||||
std::array<u8, 4> fill_buffer{};
|
||||
if (!IsValidFillSize(fill_size)) {
|
||||
return fill_buffer;
|
||||
}
|
||||
|
||||
const PAddr fill_offset = (copy_addr - addr) % fill_size;
|
||||
u32 fill_buff_pos = fill_offset;
|
||||
for (std::size_t i = 0; i < fill_buffer.size(); i++) {
|
||||
fill_buffer[i] = fill_data[fill_buff_pos++ % fill_size];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user