mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-12-25 00:23:04 -06:00
Support for textures smaller than 8*8
This commit is contained in:
parent
be1d0cee1e
commit
7f1aec8fbb
2 changed files with 55 additions and 35 deletions
|
@ -449,27 +449,18 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su
|
||||||
bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
|
bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
|
||||||
return (other_surface.addr == addr && other_surface.width == width &&
|
return (other_surface.addr == addr && other_surface.width == width &&
|
||||||
other_surface.height == height && other_surface.stride == stride &&
|
other_surface.height == height && other_surface.stride == stride &&
|
||||||
other_surface.pixel_format == pixel_format && other_surface.is_tiled == is_tiled);
|
other_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
|
||||||
|
other_surface.is_tiled == is_tiled);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
|
bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
|
||||||
if (sub_surface.addr < addr || sub_surface.end > end || sub_surface.stride != stride ||
|
return (sub_surface.addr >= addr && sub_surface.end <= end &&
|
||||||
sub_surface.pixel_format != pixel_format || sub_surface.is_tiled != is_tiled ||
|
sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
|
||||||
(sub_surface.addr - addr) * 8 % GetFormatBpp() != 0)
|
sub_surface.is_tiled == is_tiled &&
|
||||||
return false;
|
(sub_surface.addr - addr) * 8 % GetFormatBpp() == 0 &&
|
||||||
|
(!is_tiled || PixelsInBytes(sub_surface.addr - addr) % 64 == 0) &&
|
||||||
auto rect = GetSubRect(sub_surface);
|
(sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) &&
|
||||||
|
GetSubRect(sub_surface).left + sub_surface.width <= stride);
|
||||||
if (rect.left + sub_surface.width > stride) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_tiled) {
|
|
||||||
return PixelsInBytes(sub_surface.addr - addr) % 64 == 0 && sub_surface.height % 8 == 0 &&
|
|
||||||
sub_surface.width % 8 == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const {
|
bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const {
|
||||||
|
@ -1006,15 +997,6 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
|
||||||
if (expandable != nullptr && expandable->res_scale > target_res_scale) {
|
if (expandable != nullptr && expandable->res_scale > target_res_scale) {
|
||||||
target_res_scale = expandable->res_scale;
|
target_res_scale = expandable->res_scale;
|
||||||
}
|
}
|
||||||
// Keep res_scale when reinterpreting d24s8 -> rgba8
|
|
||||||
if (params.pixel_format == PixelFormat::RGBA8) {
|
|
||||||
find_params.pixel_format = PixelFormat::D24S8;
|
|
||||||
expandable = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>(
|
|
||||||
surface_cache, find_params, match_res_scale);
|
|
||||||
if (expandable != nullptr && expandable->res_scale > target_res_scale) {
|
|
||||||
target_res_scale = expandable->res_scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SurfaceParams new_params = params;
|
SurfaceParams new_params = params;
|
||||||
new_params.res_scale = target_res_scale;
|
new_params.res_scale = target_res_scale;
|
||||||
|
@ -1057,17 +1039,29 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SurfaceParams aligned_params = params;
|
||||||
|
if (params.is_tiled) {
|
||||||
|
aligned_params.height = Common::AlignUp(params.height, 8);
|
||||||
|
aligned_params.width = Common::AlignUp(params.width, 8);
|
||||||
|
aligned_params.stride = Common::AlignUp(params.stride, 8);
|
||||||
|
aligned_params.UpdateParams();
|
||||||
|
}
|
||||||
|
|
||||||
// Check for a surface we can expand before creating a new one
|
// Check for a surface we can expand before creating a new one
|
||||||
if (surface == nullptr) {
|
if (surface == nullptr) {
|
||||||
surface = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>(surface_cache, params,
|
surface = FindMatch<MatchFlags::Expand | MatchFlags::Invalid>(surface_cache, aligned_params,
|
||||||
match_res_scale);
|
match_res_scale);
|
||||||
if (surface != nullptr) {
|
if (surface != nullptr) {
|
||||||
|
aligned_params.width = aligned_params.stride;
|
||||||
|
aligned_params.UpdateParams();
|
||||||
|
|
||||||
SurfaceParams new_params = *surface;
|
SurfaceParams new_params = *surface;
|
||||||
new_params.addr = std::min(params.addr, surface->addr);
|
new_params.addr = std::min(aligned_params.addr, surface->addr);
|
||||||
new_params.end = std::max(params.end, surface->end);
|
new_params.end = std::max(aligned_params.end, surface->end);
|
||||||
new_params.size = new_params.end - new_params.addr;
|
new_params.size = new_params.end - new_params.addr;
|
||||||
new_params.height = new_params.size / params.BytesInPixels(params.stride);
|
new_params.height =
|
||||||
ASSERT(new_params.size % params.BytesInPixels(params.stride) == 0);
|
new_params.size / aligned_params.BytesInPixels(aligned_params.stride);
|
||||||
|
ASSERT(new_params.size % aligned_params.BytesInPixels(aligned_params.stride) == 0);
|
||||||
|
|
||||||
Surface new_surface = CreateSurface(new_params);
|
Surface new_surface = CreateSurface(new_params);
|
||||||
DuplicateSurface(surface, new_surface);
|
DuplicateSurface(surface, new_surface);
|
||||||
|
@ -1083,14 +1077,14 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams&
|
||||||
|
|
||||||
// No subrect found - create and return a new surface
|
// No subrect found - create and return a new surface
|
||||||
if (surface == nullptr) {
|
if (surface == nullptr) {
|
||||||
SurfaceParams new_params = params;
|
SurfaceParams new_params = aligned_params;
|
||||||
// Can't have gaps in a surface
|
// Can't have gaps in a surface
|
||||||
new_params.width = params.stride;
|
new_params.width = aligned_params.stride;
|
||||||
new_params.UpdateParams();
|
new_params.UpdateParams();
|
||||||
// GetSurface will create the new surface and possibly adjust res_scale if necessary
|
// GetSurface will create the new surface and possibly adjust res_scale if necessary
|
||||||
surface = GetSurface(new_params, match_res_scale, load_if_create);
|
surface = GetSurface(new_params, match_res_scale, load_if_create);
|
||||||
} else if (load_if_create) {
|
} else if (load_if_create) {
|
||||||
ValidateSurface(surface, params.addr, params.size);
|
ValidateSurface(surface, aligned_params.addr, aligned_params.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_tuple(surface, surface->GetScaledSubRect(params));
|
return std::make_tuple(surface, surface->GetScaledSubRect(params));
|
||||||
|
@ -1108,6 +1102,23 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(
|
||||||
params.is_tiled = true;
|
params.is_tiled = true;
|
||||||
params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(info.format);
|
params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(info.format);
|
||||||
params.UpdateParams();
|
params.UpdateParams();
|
||||||
|
|
||||||
|
if (info.width % 8 != 0 || info.height % 8 != 0) {
|
||||||
|
Surface src_surface;
|
||||||
|
MathUtil::Rectangle<u32> rect;
|
||||||
|
std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
|
||||||
|
|
||||||
|
params.res_scale = src_surface->res_scale;
|
||||||
|
Surface tmp_surface = CreateSurface(params);
|
||||||
|
BlitTextures(src_surface->texture.handle, rect, tmp_surface->texture.handle,
|
||||||
|
tmp_surface->GetScaledRect(),
|
||||||
|
SurfaceParams::GetFormatType(params.pixel_format), read_framebuffer.handle,
|
||||||
|
draw_framebuffer.handle);
|
||||||
|
|
||||||
|
remove_surfaces.emplace(tmp_surface);
|
||||||
|
return tmp_surface;
|
||||||
|
}
|
||||||
|
|
||||||
return GetSurface(params, ScaleMatch::Ignore, true);
|
return GetSurface(params, ScaleMatch::Ignore, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,11 +1433,19 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) {
|
void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) {
|
||||||
|
if (surface->registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
surface->registered = true;
|
||||||
surface_cache.add({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) {
|
||||||
|
if (!surface->registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
surface->registered = false;
|
||||||
UpdatePagesCachedCount(surface->addr, surface->size, -1);
|
UpdatePagesCachedCount(surface->addr, surface->size, -1);
|
||||||
surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}});
|
surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}});
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,6 +265,7 @@ struct CachedSurface : SurfaceParams {
|
||||||
return (invalid_regions & GetInterval()) == SurfaceRegions(GetInterval());
|
return (invalid_regions & GetInterval()) == SurfaceRegions(GetInterval());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool registered = false;
|
||||||
SurfaceRegions invalid_regions;
|
SurfaceRegions invalid_regions;
|
||||||
|
|
||||||
u32 fill_size = 0; /// Number of bytes to read from fill_data
|
u32 fill_size = 0; /// Number of bytes to read from fill_data
|
||||||
|
|
Loading…
Reference in a new issue