|
|
@@ -177,9 +177,9 @@ void ApplyTextureDefaults(const SurfaceParams& params, GLuint texture) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-OGLTexture CreateTexture(const SurfaceParams& params, GLenum internal_format) {
|
|
|
+OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum internal_format) {
|
|
|
OGLTexture texture;
|
|
|
- texture.Create(GetTextureTarget(params));
|
|
|
+ texture.Create(target);
|
|
|
|
|
|
switch (params.GetTarget()) {
|
|
|
case SurfaceTarget::Texture1D:
|
|
|
@@ -241,7 +241,8 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
|
|
|
format = tuple.format;
|
|
|
type = tuple.type;
|
|
|
is_compressed = tuple.compressed;
|
|
|
- texture = CreateTexture(params, internal_format);
|
|
|
+ target = GetTextureTarget(params);
|
|
|
+ texture = CreateTexture(params, target, internal_format);
|
|
|
staging_buffer.resize(params.GetHostSizeInBytes());
|
|
|
}
|
|
|
|
|
|
@@ -504,9 +505,53 @@ TextureCacheOpenGL::~TextureCacheOpenGL() = default;
|
|
|
CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView(
|
|
|
VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params, bool preserve_contents,
|
|
|
const std::vector<CachedSurface*>& overlaps) {
|
|
|
+ if (overlaps.size() > 1) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ const auto& old_surface{overlaps[0]};
|
|
|
+ const auto& old_params{old_surface->GetSurfaceParams()};
|
|
|
+ const auto& new_params{params};
|
|
|
+
|
|
|
+ if (old_params.GetTarget() == new_params.GetTarget() &&
|
|
|
+ old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 &&
|
|
|
+ old_params.GetNumLevels() == new_params.GetNumLevels() &&
|
|
|
+ old_params.GetPixelFormat() == new_params.GetPixelFormat()) {
|
|
|
+ return SurfaceCopy(cpu_addr, host_ptr, new_params, old_surface, old_params);
|
|
|
+ }
|
|
|
+
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
+CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(VAddr cpu_addr, u8* host_ptr,
|
|
|
+ const SurfaceParams& new_params,
|
|
|
+ CachedSurface* old_surface,
|
|
|
+ const SurfaceParams& old_params) {
|
|
|
+ CachedSurface* const new_surface{GetUncachedSurface(new_params)};
|
|
|
+ Register(new_surface, cpu_addr, host_ptr);
|
|
|
+
|
|
|
+ const u32 min_width{
|
|
|
+ std::max(old_params.GetDefaultBlockWidth(), new_params.GetDefaultBlockWidth())};
|
|
|
+ const u32 min_height{
|
|
|
+ std::max(old_params.GetDefaultBlockHeight(), new_params.GetDefaultBlockHeight())};
|
|
|
+ for (u32 level = 0; level < old_params.GetNumLevels(); ++level) {
|
|
|
+ const u32 width{std::min(old_params.GetMipWidth(level), new_params.GetMipWidth(level))};
|
|
|
+ const u32 height{std::min(old_params.GetMipHeight(level), new_params.GetMipHeight(level))};
|
|
|
+ if (width < min_width || height < min_height) {
|
|
|
+ // Avoid copies that are too small to be handled in OpenGL
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ glCopyImageSubData(old_surface->GetTexture(), old_surface->GetTarget(), level, 0, 0, 0,
|
|
|
+ new_surface->GetTexture(), new_surface->GetTarget(), level, 0, 0, 0,
|
|
|
+ width, height, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ new_surface->MarkAsModified(true);
|
|
|
+
|
|
|
+ // TODO(Rodrigo): Add an entry to directly get the superview
|
|
|
+ return new_surface->GetView(cpu_addr, new_params);
|
|
|
+}
|
|
|
+
|
|
|
std::unique_ptr<CachedSurface> TextureCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
|
|
return std::make_unique<CachedSurface>(params);
|
|
|
}
|