|
|
|
@ -120,10 +120,6 @@ public: |
|
|
|
return {}; |
|
|
|
} |
|
|
|
|
|
|
|
if (regs.color_mask[index].raw == 0) { |
|
|
|
return {}; |
|
|
|
} |
|
|
|
|
|
|
|
auto surface_view = GetSurface(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index), |
|
|
|
preserve_contents); |
|
|
|
if (render_targets[index].target) |
|
|
|
@ -165,7 +161,9 @@ public: |
|
|
|
const Tegra::Engines::Fermi2D::Regs::Surface& dst_config, |
|
|
|
const Common::Rectangle<u32>& src_rect, |
|
|
|
const Common::Rectangle<u32>& dst_rect) { |
|
|
|
ImageBlit(GetFermiSurface(src_config), GetFermiSurface(dst_config), src_rect, dst_rect); |
|
|
|
TSurface dst_surface = GetFermiSurface(dst_config); |
|
|
|
ImageBlit(GetFermiSurface(src_config), dst_surface, src_rect, dst_rect); |
|
|
|
dst_surface->MarkAsModified(true, Tick()); |
|
|
|
} |
|
|
|
|
|
|
|
TSurface TryFindFramebufferSurface(const u8* host_ptr) { |
|
|
|
@ -270,10 +268,6 @@ private: |
|
|
|
|
|
|
|
RecycleStrategy PickStrategy(std::vector<TSurface>& overlaps, const SurfaceParams& params, |
|
|
|
const GPUVAddr gpu_addr, const bool untopological) { |
|
|
|
// Untopological decision |
|
|
|
if (untopological) { |
|
|
|
return RecycleStrategy::Ignore; |
|
|
|
} |
|
|
|
// 3D Textures decision |
|
|
|
if (params.block_depth > 1 || params.target == SurfaceTarget::Texture3D) { |
|
|
|
return RecycleStrategy::Flush; |
|
|
|
@ -284,12 +278,16 @@ private: |
|
|
|
return RecycleStrategy::Flush; |
|
|
|
} |
|
|
|
} |
|
|
|
// Untopological decision |
|
|
|
if (untopological) { |
|
|
|
return RecycleStrategy::Ignore; |
|
|
|
} |
|
|
|
return RecycleStrategy::Ignore; |
|
|
|
} |
|
|
|
|
|
|
|
std::pair<TSurface, TView> RecycleSurface(std::vector<TSurface>& overlaps, |
|
|
|
const SurfaceParams& params, const GPUVAddr gpu_addr, |
|
|
|
const u8* host_ptr, const bool preserve_contents, |
|
|
|
const bool preserve_contents, |
|
|
|
const bool untopological) { |
|
|
|
for (auto surface : overlaps) { |
|
|
|
Unregister(surface); |
|
|
|
@ -328,6 +326,7 @@ private: |
|
|
|
} |
|
|
|
Unregister(current_surface); |
|
|
|
Register(new_surface); |
|
|
|
new_surface->MarkAsModified(current_surface->IsModified(), Tick()); |
|
|
|
return {new_surface, new_surface->GetMainView()}; |
|
|
|
} |
|
|
|
|
|
|
|
@ -351,6 +350,7 @@ private: |
|
|
|
if (params.target == SurfaceTarget::Texture3D) { |
|
|
|
return {}; |
|
|
|
} |
|
|
|
bool modified = false; |
|
|
|
TSurface new_surface = GetUncachedSurface(gpu_addr, params); |
|
|
|
for (auto surface : overlaps) { |
|
|
|
const SurfaceParams& src_params = surface->GetSurfaceParams(); |
|
|
|
@ -358,7 +358,7 @@ private: |
|
|
|
// We send this cases to recycle as they are more complex to handle |
|
|
|
return {}; |
|
|
|
} |
|
|
|
const std::size_t candidate_size = src_params.GetGuestSizeInBytes(); |
|
|
|
const std::size_t candidate_size = surface->GetSizeInBytes(); |
|
|
|
auto mipmap_layer{new_surface->GetLayerMipmap(surface->GetGpuAddr())}; |
|
|
|
if (!mipmap_layer) { |
|
|
|
return {}; |
|
|
|
@ -368,6 +368,7 @@ private: |
|
|
|
if (new_surface->GetMipmapSize(mipmap) != candidate_size) { |
|
|
|
return {}; |
|
|
|
} |
|
|
|
modified |= surface->IsModified(); |
|
|
|
// Now we got all the data set up |
|
|
|
const u32 dst_width{params.GetMipWidth(mipmap)}; |
|
|
|
const u32 dst_height{params.GetMipHeight(mipmap)}; |
|
|
|
@ -381,6 +382,7 @@ private: |
|
|
|
force_reconfiguration |= surface->IsProtected(); |
|
|
|
Unregister(surface, true); |
|
|
|
} |
|
|
|
new_surface->MarkAsModified(modified, Tick()); |
|
|
|
Register(new_surface); |
|
|
|
return {{new_surface, new_surface->GetMainView()}}; |
|
|
|
} |
|
|
|
@ -399,8 +401,7 @@ private: |
|
|
|
|
|
|
|
for (auto surface : overlaps) { |
|
|
|
if (!surface->MatchesTopology(params)) { |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, |
|
|
|
true); |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -418,27 +419,26 @@ private: |
|
|
|
} |
|
|
|
} |
|
|
|
if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) { |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, |
|
|
|
false); |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
|
|
|
} |
|
|
|
std::optional<TView> view = current_surface->EmplaceView(params, gpu_addr); |
|
|
|
std::optional<TView> view = |
|
|
|
current_surface->EmplaceView(params, gpu_addr, candidate_size); |
|
|
|
if (view.has_value()) { |
|
|
|
const bool is_mirage = !current_surface->MatchFormat(params.pixel_format); |
|
|
|
if (is_mirage) { |
|
|
|
LOG_CRITICAL(HW_GPU, "Mirage View Unsupported"); |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, |
|
|
|
false); |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
|
|
|
} |
|
|
|
return {current_surface, *view}; |
|
|
|
} |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, false); |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
|
|
|
} else { |
|
|
|
std::optional<std::pair<TSurface, TView>> view = |
|
|
|
ReconstructSurface(overlaps, params, gpu_addr, host_ptr); |
|
|
|
if (view.has_value()) { |
|
|
|
return *view; |
|
|
|
} |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, host_ptr, preserve_contents, false); |
|
|
|
return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|