mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00: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…
	
	Add table
		Add a link
		
	
		Reference in a new issue