mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-27 01:30:06 +00:00
res scale fixed + cleanup
This commit is contained in:
parent
926abc6ddb
commit
8969245e2e
@ -240,7 +240,7 @@ void RasterizerOpenGL::DrawTriangles() {
|
|||||||
const bool using_color_fb = regs.framebuffer.framebuffer.GetColorBufferPhysicalAddress() != 0 &&
|
const bool using_color_fb = regs.framebuffer.framebuffer.GetColorBufferPhysicalAddress() != 0 &&
|
||||||
write_color_fb;
|
write_color_fb;
|
||||||
const bool using_depth_fb = regs.framebuffer.framebuffer.GetDepthBufferPhysicalAddress() != 0 &&
|
const bool using_depth_fb = regs.framebuffer.framebuffer.GetDepthBufferPhysicalAddress() != 0 &&
|
||||||
(state.depth.test_enabled || write_depth_fb);
|
(write_depth_fb || state.depth.test_enabled || (has_stencil && state.stencil.test_enabled));
|
||||||
|
|
||||||
// Sync and bind the framebuffer surfaces
|
// Sync and bind the framebuffer surfaces
|
||||||
Surface color_surface;
|
Surface color_surface;
|
||||||
|
@ -314,8 +314,8 @@ static bool FillSurface(const Surface& surface, const u8* fill_data) {
|
|||||||
|
|
||||||
MathUtil::Rectangle<u32> CachedSurface::GetSubRect(const SurfaceParams& sub_surface) const {
|
MathUtil::Rectangle<u32> CachedSurface::GetSubRect(const SurfaceParams& sub_surface) const {
|
||||||
const u32 begin_pixel_index = PixelsInBytes(sub_surface.addr - addr);
|
const u32 begin_pixel_index = PixelsInBytes(sub_surface.addr - addr);
|
||||||
const int x0 = begin_pixel_index % width;
|
const int x0 = begin_pixel_index % stride;
|
||||||
const int y0 = begin_pixel_index / width;
|
const int y0 = begin_pixel_index / stride;
|
||||||
|
|
||||||
if (is_tiled)
|
if (is_tiled)
|
||||||
return MathUtil::Rectangle<u32>(x0, height - y0 - sub_surface.height, x0 + sub_surface.width, height - y0); // Bottom to top
|
return MathUtil::Rectangle<u32>(x0, height - y0 - sub_surface.height, x0 + sub_surface.width, height - y0); // Bottom to top
|
||||||
@ -361,6 +361,9 @@ bool CachedSurface::CanCopy(const SurfaceParams& dest_surface) const {
|
|||||||
if (type == SurfaceType::Fill && IsRegionValid(dest_surface.GetInterval()) &&
|
if (type == SurfaceType::Fill && IsRegionValid(dest_surface.GetInterval()) &&
|
||||||
dest_surface.addr >= addr && dest_surface.end <= end) { // dest_surface is within our fill range
|
dest_surface.addr >= addr && dest_surface.end <= end) { // dest_surface is within our fill range
|
||||||
if (fill_size != dest_surface.bytes_per_pixel) {
|
if (fill_size != dest_surface.bytes_per_pixel) {
|
||||||
|
if (dest_surface.is_tiled && GetFormatBpp(dest_surface.pixel_format) * 8 % fill_size != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Check if bits repeat for our fill_size
|
// Check if bits repeat for our fill_size
|
||||||
const u32 dest_bytes_per_pixel = std::max(dest_surface.bytes_per_pixel, 1u); // Take care of 4bpp formats
|
const u32 dest_bytes_per_pixel = std::max(dest_surface.bytes_per_pixel, 1u); // Take care of 4bpp formats
|
||||||
std::vector<u8> fill_test(fill_size * dest_bytes_per_pixel);
|
std::vector<u8> fill_test(fill_size * dest_bytes_per_pixel);
|
||||||
@ -383,17 +386,34 @@ bool CachedSurface::CanCopy(const SurfaceParams& dest_surface) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CachedSurface::CanExpand(const SurfaceParams& expanded_surface) const {
|
||||||
|
if (pixel_format != expanded_surface.pixel_format ||
|
||||||
|
is_tiled != expanded_surface.is_tiled ||
|
||||||
|
addr > expanded_surface.end || expanded_surface.addr > end ||
|
||||||
|
stride != expanded_surface.stride)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 begin_pixel_index =
|
||||||
|
PixelsInBytes(std::max(expanded_surface.addr, addr) -
|
||||||
|
std::min(expanded_surface.addr, addr));
|
||||||
|
const int x0 = begin_pixel_index % stride;
|
||||||
|
const int y0 = begin_pixel_index / stride;
|
||||||
|
|
||||||
|
return x0 == 0 && (!is_tiled || y0 % 8 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool CachedSurface::CanTexCopy(const SurfaceParams& texcopy_params) const {
|
bool CachedSurface::CanTexCopy(const SurfaceParams& texcopy_params) const {
|
||||||
|
// TODO: Accept "Fill" surfaces
|
||||||
if (pixel_format == PixelFormat::Invalid ||
|
if (pixel_format == PixelFormat::Invalid ||
|
||||||
addr > texcopy_params.addr || end < texcopy_params.end ||
|
addr > texcopy_params.addr || end < texcopy_params.end ||
|
||||||
((texcopy_params.addr - addr) * 8) % SurfaceParams::GetFormatBpp(pixel_format) != 0 ||
|
((texcopy_params.addr - addr) * 8) % GetFormatBpp(pixel_format) != 0 ||
|
||||||
(texcopy_params.width * 8) % SurfaceParams::GetFormatBpp(pixel_format) != 0 ||
|
(texcopy_params.width * 8) % GetFormatBpp(pixel_format) != 0 ||
|
||||||
(texcopy_params.stride * 8) % SurfaceParams::GetFormatBpp(pixel_format) != 0)
|
(texcopy_params.stride * 8) % GetFormatBpp(pixel_format) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const u32 begin_pixel_index = PixelsInBytes(texcopy_params.addr - addr);
|
const u32 begin_pixel_index = PixelsInBytes(texcopy_params.addr - addr);
|
||||||
const int x0 = begin_pixel_index % width;
|
const int x0 = begin_pixel_index % stride;
|
||||||
const int y0 = begin_pixel_index / width;
|
const int y0 = begin_pixel_index / stride;
|
||||||
|
|
||||||
if (!is_tiled)
|
if (!is_tiled)
|
||||||
return (PixelsInBytes(texcopy_params.stride) == stride &&
|
return (PixelsInBytes(texcopy_params.stride) == stride &&
|
||||||
@ -619,7 +639,8 @@ enum MatchFlags {
|
|||||||
Exact = 1 << 1, // Surfaces perfectly match
|
Exact = 1 << 1, // Surfaces perfectly match
|
||||||
SubRect = 1 << 2, // Surface encompasses params
|
SubRect = 1 << 2, // Surface encompasses params
|
||||||
Copy = 1 << 3, // Surface we can copy from
|
Copy = 1 << 3, // Surface we can copy from
|
||||||
TexCopy = 1 << 4 // Surface that will match a display transfer "texture copy" parameters
|
Expand = 1 << 4, // Surface that can expand params
|
||||||
|
TexCopy = 1 << 5 // Surface that will match a display transfer "texture copy" parameters
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr MatchFlags operator | (MatchFlags lhs, MatchFlags rhs) {
|
constexpr MatchFlags operator | (MatchFlags lhs, MatchFlags rhs) {
|
||||||
@ -632,6 +653,7 @@ Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params
|
|||||||
Surface match_surface = nullptr;
|
Surface match_surface = nullptr;
|
||||||
bool match_valid = false;
|
bool match_valid = false;
|
||||||
u32 match_scale = 0;
|
u32 match_scale = 0;
|
||||||
|
u32 match_size = 0;
|
||||||
|
|
||||||
for (auto& pair : RangeFromInterval(surface_cache, params.GetInterval())) {
|
for (auto& pair : RangeFromInterval(surface_cache, params.GetInterval())) {
|
||||||
for (auto& surface : pair.second) {
|
for (auto& surface : pair.second) {
|
||||||
@ -643,28 +665,45 @@ Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params
|
|||||||
if (!(find_flags & MatchFlags::Invalid) && !is_valid)
|
if (!(find_flags & MatchFlags::Invalid) && !is_valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto IsMatch_Helper = [&](MatchFlags check_type, auto match_fn) {
|
auto IsMatch_Helper = [&](MatchFlags check_type, auto match_fn) {
|
||||||
if (!(find_flags & check_type))
|
if (!(find_flags & check_type) || !match_fn())
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (!match_fn())
|
if (!res_scale_matched &&
|
||||||
return false;
|
match_scale_type != ScaleMatch::Ignore &&
|
||||||
|
surface->type != SurfaceType::Fill)
|
||||||
|
return;
|
||||||
|
|
||||||
if (match_scale_type == ScaleMatch::Ignore || res_scale_matched || surface->type == SurfaceType::Fill) { // Found a match
|
// Found a match, update only if this is better than the previous one
|
||||||
if (is_valid && !match_valid) {
|
auto UpdateMatch = [&] {
|
||||||
match_scale = 0;
|
|
||||||
match_valid = true;
|
|
||||||
}
|
|
||||||
if (surface->res_scale > match_scale) {
|
|
||||||
match_scale = surface->res_scale;
|
|
||||||
match_surface = surface;
|
match_surface = surface;
|
||||||
|
match_valid = is_valid;
|
||||||
|
match_scale = surface->res_scale;
|
||||||
|
match_size = surface->size;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (surface->res_scale > match_scale) {
|
||||||
|
UpdateMatch();
|
||||||
|
return;
|
||||||
|
} else if (surface->res_scale < match_scale) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_valid && !match_valid) {
|
||||||
|
UpdateMatch();
|
||||||
|
return;
|
||||||
|
} else if (is_valid != match_valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->size > match_size) {
|
||||||
|
UpdateMatch();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
IsMatch_Helper(MatchFlags::Exact, [&] { return surface->ExactMatch(params); });
|
IsMatch_Helper(MatchFlags::Exact, [&] { return surface->ExactMatch(params); });
|
||||||
IsMatch_Helper(MatchFlags::SubRect, [&] { return surface->CanSubRect(params); });
|
IsMatch_Helper(MatchFlags::SubRect, [&] { return surface->CanSubRect(params); });
|
||||||
IsMatch_Helper(MatchFlags::Copy, [&] { return surface->CanCopy(params); });
|
IsMatch_Helper(MatchFlags::Copy, [&] { return surface->CanCopy(params); });
|
||||||
|
IsMatch_Helper(MatchFlags::Expand, [&] { return surface->CanExpand(params); });
|
||||||
IsMatch_Helper(MatchFlags::TexCopy, [&] { return surface->CanTexCopy(params); });
|
IsMatch_Helper(MatchFlags::TexCopy, [&] { return surface->CanTexCopy(params); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -702,72 +741,105 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for an exact or subrect match in existing surfaces
|
|
||||||
Surface surface_match = FindMatch<MatchFlags::Exact | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
|
||||||
|
|
||||||
if (surface_match != nullptr) {
|
|
||||||
if (load_if_create) {
|
|
||||||
ValidateSurface(surface_match, params.addr, params.size);
|
|
||||||
}
|
|
||||||
return surface_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(params.width == params.stride); // Use GetSurfaceSubRect instead
|
ASSERT(params.width == params.stride); // Use GetSurfaceSubRect instead
|
||||||
|
|
||||||
Surface new_surface = CreateSurface(params);
|
// Check for an exact match in existing surfaces
|
||||||
if (load_if_create)
|
Surface surface = FindMatch<MatchFlags::Exact | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
||||||
ValidateSurface(new_surface, params.addr, params.size);
|
|
||||||
|
|
||||||
RegisterSurface(new_surface);
|
Surface expandable = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
||||||
|
u16 target_res_scale = surface == nullptr ? params.res_scale : surface->res_scale;
|
||||||
|
if (match_res_scale != ScaleMatch::Exact &&
|
||||||
|
expandable != nullptr &&
|
||||||
|
expandable->res_scale > params.res_scale) {
|
||||||
|
target_res_scale = expandable->res_scale;
|
||||||
|
}
|
||||||
|
|
||||||
return new_surface;
|
if (surface == nullptr || target_res_scale != surface->res_scale) {
|
||||||
|
SurfaceParams new_params = params;
|
||||||
|
new_params.res_scale = target_res_scale;
|
||||||
|
|
||||||
|
surface = CreateSurface(new_params);
|
||||||
|
RegisterSurface(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load_if_create) {
|
||||||
|
ValidateSurface(surface, params.addr, params.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params,
|
SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params,
|
||||||
ScaleMatch match_res_scale,
|
ScaleMatch match_res_scale,
|
||||||
bool load_if_create) {
|
bool load_if_create) {
|
||||||
MathUtil::Rectangle<u32> out_rect{};
|
Surface surface = nullptr;
|
||||||
|
MathUtil::Rectangle<u32> rect{};
|
||||||
|
|
||||||
if (params.addr == 0 || params.height * params.width == 0) {
|
if (params.addr == 0 || params.height * params.width == 0) {
|
||||||
return std::make_tuple(nullptr, out_rect);
|
return { surface, rect };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to find encompassing surface
|
// Attempt to find encompassing surface
|
||||||
Surface subrect_match = FindMatch<MatchFlags::SubRect | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
surface = FindMatch<MatchFlags::SubRect | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
||||||
|
|
||||||
// Return the best subrect surface if found
|
// Check if FindMatch failed because of res scaling
|
||||||
if (subrect_match != nullptr) {
|
// If that's the case create a new surface with
|
||||||
if (load_if_create) {
|
// the dimensions of the lower res_scale surface
|
||||||
ValidateSurface(subrect_match, params.addr, params.size);
|
// to suggest it should not be used again
|
||||||
|
if (surface == nullptr && match_res_scale != ScaleMatch::Ignore) {
|
||||||
|
surface = FindMatch<MatchFlags::SubRect | MatchFlags::Invalid>(surface_cache, params, ScaleMatch::Ignore);
|
||||||
|
if (surface != nullptr) {
|
||||||
|
ASSERT(surface->res_scale < params.res_scale);
|
||||||
|
SurfaceParams new_params = *surface;
|
||||||
|
new_params.res_scale = params.res_scale;
|
||||||
|
|
||||||
|
surface = CreateSurface(new_params);
|
||||||
|
RegisterSurface(surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out_rect = subrect_match->GetScaledSubRect(params);
|
// Check for a surface we can expand before creating a new one
|
||||||
// Tiled surfaces are flipped vertically in the rasterizer vs. 3DS memory.
|
if (surface == nullptr) {
|
||||||
if (params.is_tiled)
|
surface = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
||||||
std::swap(out_rect.top, out_rect.bottom);
|
if (surface != nullptr) {
|
||||||
|
SurfaceParams new_params = *surface;
|
||||||
|
new_params.addr = std::min(params.addr, surface->addr);
|
||||||
|
new_params.end = std::max(params.end, surface->end);
|
||||||
|
new_params.size = new_params.end - new_params.addr;
|
||||||
|
new_params.height = new_params.size / (SurfaceParams::GetFormatBpp(params.pixel_format) * params.stride / 8);
|
||||||
|
|
||||||
return std::make_tuple(subrect_match, out_rect);
|
Surface new_surface = CreateSurface(new_params);
|
||||||
|
RegisterSurface(new_surface);
|
||||||
|
|
||||||
|
// TODO: Delete the expanded surface, this can't be done safely yet
|
||||||
|
// because it may still be in use
|
||||||
|
BlitSurfaces(surface, surface->GetScaledRect(), new_surface, new_surface->GetScaledSubRect(*surface));
|
||||||
|
new_surface->invalid_regions -= surface->GetInterval();
|
||||||
|
new_surface->invalid_regions += surface->invalid_regions;
|
||||||
|
surface = new_surface;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No subrect found - create and return a new surface
|
// No subrect found - create and return a new surface
|
||||||
|
if (surface == nullptr) {
|
||||||
SurfaceParams new_params = params;
|
SurfaceParams new_params = params;
|
||||||
new_params.width = params.stride; // Can't have gaps in a surface
|
new_params.width = params.stride; // Can't have gaps in a surface
|
||||||
new_params.UpdateParams();
|
new_params.UpdateParams();
|
||||||
|
|
||||||
out_rect = new_params.GetScaledRect();
|
surface = CreateSurface(new_params);
|
||||||
if (new_params.is_tiled)
|
RegisterSurface(surface);
|
||||||
std::swap(out_rect.top, out_rect.bottom);
|
}
|
||||||
|
|
||||||
// If stride was bigger than width we need to adjust our output rect
|
if (load_if_create) {
|
||||||
out_rect.right = static_cast<int>(params.width * new_params.res_scale);
|
ValidateSurface(surface, params.addr, params.size);
|
||||||
|
}
|
||||||
|
|
||||||
Surface new_surface = CreateSurface(new_params);
|
rect = surface->GetScaledSubRect(params);
|
||||||
if (load_if_create)
|
// Tiled surfaces are flipped vertically in the rasterizer vs. 3DS memory.
|
||||||
ValidateSurface(new_surface, new_params.addr, new_params.size);
|
if (surface->is_tiled)
|
||||||
|
std::swap(rect.top, rect.bottom);
|
||||||
|
|
||||||
RegisterSurface(new_surface);
|
return { surface, rect };
|
||||||
|
|
||||||
return std::make_tuple(new_surface, out_rect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config) {
|
Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config) {
|
||||||
@ -796,15 +868,14 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool usin
|
|||||||
|
|
||||||
// Make sur that framebuffers don't overlap if both color and depth are being used
|
// Make sur that framebuffers don't overlap if both color and depth are being used
|
||||||
u32 fb_area = config.GetWidth() * config.GetHeight();
|
u32 fb_area = config.GetWidth() * config.GetHeight();
|
||||||
bool framebuffers_overlap = config.GetColorBufferPhysicalAddress() != 0 &&
|
bool framebuffers_overlap = using_color_fb && using_depth_fb &&
|
||||||
config.GetDepthBufferPhysicalAddress() != 0 &&
|
|
||||||
MathUtil::IntervalsIntersect(
|
MathUtil::IntervalsIntersect(
|
||||||
config.GetColorBufferPhysicalAddress(),
|
config.GetColorBufferPhysicalAddress(),
|
||||||
fb_area * GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(config.color_format.Value())),
|
fb_area * GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(config.color_format.Value())),
|
||||||
config.GetDepthBufferPhysicalAddress(),
|
config.GetDepthBufferPhysicalAddress(),
|
||||||
fb_area * Pica::FramebufferRegs::BytesPerDepthPixel(config.depth_format));
|
fb_area * Pica::FramebufferRegs::BytesPerDepthPixel(config.depth_format));
|
||||||
|
|
||||||
if (framebuffers_overlap && using_color_fb && using_depth_fb) {
|
if (framebuffers_overlap) {
|
||||||
LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; overlapping framebuffers not supported!");
|
LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; overlapping framebuffers not supported!");
|
||||||
using_depth_fb = false;
|
using_depth_fb = false;
|
||||||
}
|
}
|
||||||
@ -856,7 +927,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool usin
|
|||||||
std::tie(depth_surface, rect) = GetSurfaceSubRect(depth_params, ScaleMatch::Exact, true);
|
std::tie(depth_surface, rect) = GetSurfaceSubRect(depth_params, ScaleMatch::Exact, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_tuple(color_surface, depth_surface, rect);
|
return { color_surface, depth_surface, rect };
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface RasterizerCacheOpenGL::GetFillSurface(const GPU::Regs::MemoryFillConfig& config) {
|
Surface RasterizerCacheOpenGL::GetFillSurface(const GPU::Regs::MemoryFillConfig& config) {
|
||||||
@ -901,7 +972,7 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetTexCopySurface(const SurfaceParams&
|
|||||||
std::swap(rect.top, rect.bottom);
|
std::swap(rect.top, rect.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_tuple(match_surface, rect);
|
return { match_surface, rect };
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, PAddr addr, u32 size) {
|
void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, PAddr addr, u32 size) {
|
||||||
@ -1015,6 +1086,8 @@ void RasterizerCacheOpenGL::InvalidateRegion(PAddr addr, u32 size, const Surface
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SurfaceSet remove_surfaces;
|
||||||
|
|
||||||
const auto invalid_interval = SurfaceInterval::right_open(addr, addr + size);
|
const auto invalid_interval = SurfaceInterval::right_open(addr, addr + size);
|
||||||
|
|
||||||
if (region_owner != nullptr) {
|
if (region_owner != nullptr) {
|
||||||
@ -1056,13 +1129,12 @@ void RasterizerCacheOpenGL::InvalidateRegion(PAddr addr, u32 size, const Surface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (region_owner != nullptr)
|
if (region_owner != nullptr)
|
||||||
dirty_regions.set(std::make_pair(invalid_interval, region_owner));
|
dirty_regions.set({ invalid_interval, region_owner });
|
||||||
else
|
else
|
||||||
dirty_regions.erase(invalid_interval);
|
dirty_regions.erase(invalid_interval);
|
||||||
|
|
||||||
for (auto& remove_surface : remove_surfaces)
|
for (auto& remove_surface : remove_surfaces)
|
||||||
UnregisterSurface(remove_surface);
|
UnregisterSurface(remove_surface);
|
||||||
remove_surfaces.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
||||||
@ -1090,13 +1162,13 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) {
|
void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) {
|
||||||
surface_cache.add(std::make_pair(surface->GetInterval(), SurfaceSet({ surface })));
|
surface_cache.add({ surface->GetInterval(), SurfaceSet{ surface } });
|
||||||
UpdatePagesCachedCount(surface->addr, surface->size, 1);
|
UpdatePagesCachedCount(surface->addr, surface->size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) {
|
void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) {
|
||||||
UpdatePagesCachedCount(surface->addr, surface->size, -1);
|
UpdatePagesCachedCount(surface->addr, surface->size, -1);
|
||||||
surface_cache.subtract(std::make_pair(surface->GetInterval(), SurfaceSet({ surface })));
|
surface_cache.subtract({ surface->GetInterval(), SurfaceSet{ surface } });
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerCacheOpenGL::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
|
void RasterizerCacheOpenGL::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) {
|
||||||
@ -1107,7 +1179,7 @@ void RasterizerCacheOpenGL::UpdatePagesCachedCount(PAddr addr, u32 size, int del
|
|||||||
// Interval maps will erase segments if count reaches 0, so if delta is negative we have to subtract after iterating
|
// Interval maps will erase segments if count reaches 0, so if delta is negative we have to subtract after iterating
|
||||||
const auto pages_interval = PageMap::interval_type::right_open(page_start, page_end);
|
const auto pages_interval = PageMap::interval_type::right_open(page_start, page_end);
|
||||||
if (delta > 0)
|
if (delta > 0)
|
||||||
cached_pages.add(std::make_pair(pages_interval, delta));
|
cached_pages.add({ pages_interval, delta });
|
||||||
|
|
||||||
for (auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
|
for (auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
|
||||||
const auto interval = pair.first & pages_interval;
|
const auto interval = pair.first & pages_interval;
|
||||||
@ -1126,5 +1198,5 @@ void RasterizerCacheOpenGL::UpdatePagesCachedCount(PAddr addr, u32 size, int del
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (delta < 0)
|
if (delta < 0)
|
||||||
cached_pages.add(std::make_pair(pages_interval, delta));
|
cached_pages.add({ pages_interval, delta });
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ struct SurfaceParams {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int GetFormatBpp(SurfaceParams::PixelFormat format) {
|
static unsigned int GetFormatBpp(SurfaceParams::PixelFormat format) {
|
||||||
static const std::array<unsigned int, 18> bpp_table = {
|
static constexpr std::array<unsigned int, 18> bpp_table = {
|
||||||
32, // RGBA8
|
32, // RGBA8
|
||||||
24, // RGB8
|
24, // RGB8
|
||||||
16, // RGB5A1
|
16, // RGB5A1
|
||||||
@ -110,8 +110,8 @@ struct SurfaceParams {
|
|||||||
32, // D24S8
|
32, // D24S8
|
||||||
};
|
};
|
||||||
|
|
||||||
ASSERT((unsigned int)format < ARRAY_SIZE(bpp_table));
|
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
||||||
return bpp_table[(unsigned int)format];
|
return bpp_table[static_cast<size_t>(format)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) {
|
static PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) {
|
||||||
@ -236,6 +236,7 @@ struct CachedSurface : SurfaceParams {
|
|||||||
bool ExactMatch(const SurfaceParams& other_surface) const;
|
bool ExactMatch(const SurfaceParams& other_surface) const;
|
||||||
bool CanSubRect(const SurfaceParams& sub_surface) const;
|
bool CanSubRect(const SurfaceParams& sub_surface) const;
|
||||||
bool CanCopy(const SurfaceParams& dest_surface) const;
|
bool CanCopy(const SurfaceParams& dest_surface) const;
|
||||||
|
bool CanExpand(const SurfaceParams& expanded_surface) const;
|
||||||
bool CanTexCopy(const SurfaceParams& texcopy_params) const;
|
bool CanTexCopy(const SurfaceParams& texcopy_params) const;
|
||||||
|
|
||||||
MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const;
|
MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const;
|
||||||
@ -330,5 +331,4 @@ private:
|
|||||||
SurfaceCache surface_cache;
|
SurfaceCache surface_cache;
|
||||||
SurfaceMap dirty_regions;
|
SurfaceMap dirty_regions;
|
||||||
PageMap cached_pages;
|
PageMap cached_pages;
|
||||||
SurfaceSet remove_surfaces;
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user