blob: d9441f6b85127b1b768ab394be4031f2fd7711c2 [file] [log] [blame] [edit]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/blit_pass.h"
#include <memory>
#include <utility>
#include "impeller/base/strings.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/host_buffer.h"
#include "impeller/renderer/blit_command.h"
namespace impeller {
BlitPass::BlitPass() : transients_buffer_(HostBuffer::Create()) {}
BlitPass::~BlitPass() = default;
HostBuffer& BlitPass::GetTransientsBuffer() {
return *transients_buffer_;
}
void BlitPass::SetLabel(std::string label) {
if (label.empty()) {
return;
}
transients_buffer_->SetLabel(SPrintF("%s Transients", label.c_str()));
OnSetLabel(std::move(label));
}
bool BlitPass::AddCopy(std::shared_ptr<Texture> source,
std::shared_ptr<Texture> destination,
std::optional<IRect> source_region,
IPoint destination_origin,
std::string label) {
if (!source) {
VALIDATION_LOG << "Attempted to add a texture blit with no source.";
return false;
}
if (!destination) {
VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
return false;
}
if (source->GetTextureDescriptor().sample_count !=
destination->GetTextureDescriptor().sample_count) {
VALIDATION_LOG << SPrintF(
"The source sample count (%d) must match the destination sample count "
"(%d) for blits.",
static_cast<int>(source->GetTextureDescriptor().sample_count),
static_cast<int>(destination->GetTextureDescriptor().sample_count));
return false;
}
if (source->GetTextureDescriptor().format !=
destination->GetTextureDescriptor().format) {
VALIDATION_LOG << SPrintF(
"The source pixel format (%s) must match the destination pixel format "
"(%s) "
"for blits.",
PixelFormatToString(source->GetTextureDescriptor().format),
PixelFormatToString(destination->GetTextureDescriptor().format));
return false;
}
if (!source_region.has_value()) {
source_region = IRect::MakeSize(source->GetSize());
}
// Clip the source image.
source_region =
source_region->Intersection(IRect::MakeSize(source->GetSize()));
if (!source_region.has_value()) {
return true; // Nothing to blit.
}
// Clip the destination image.
source_region = source_region->Intersection(
IRect::MakeOriginSize(-destination_origin, destination->GetSize()));
if (!source_region.has_value()) {
return true; // Nothing to blit.
}
return OnCopyTextureToTextureCommand(
std::move(source), std::move(destination), source_region.value(),
destination_origin, std::move(label));
}
bool BlitPass::AddCopy(std::shared_ptr<Texture> source,
std::shared_ptr<DeviceBuffer> destination,
std::optional<IRect> source_region,
size_t destination_offset,
std::string label) {
if (!source) {
VALIDATION_LOG << "Attempted to add a texture blit with no source.";
return false;
}
if (!destination) {
VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
return false;
}
if (!source_region.has_value()) {
source_region = IRect::MakeSize(source->GetSize());
}
auto bytes_per_pixel =
BytesPerPixelForPixelFormat(source->GetTextureDescriptor().format);
auto bytes_per_image = source_region->size.Area() * bytes_per_pixel;
if (destination_offset + bytes_per_image >
destination->GetDeviceBufferDescriptor().size) {
VALIDATION_LOG
<< "Attempted to add a texture blit with out of bounds access.";
return false;
}
// Clip the source image.
source_region =
source_region->Intersection(IRect::MakeSize(source->GetSize()));
if (!source_region.has_value()) {
return true; // Nothing to blit.
}
return OnCopyTextureToBufferCommand(std::move(source), std::move(destination),
source_region.value(), destination_offset,
std::move(label));
}
bool BlitPass::AddCopy(BufferView source,
std::shared_ptr<Texture> destination,
IPoint destination_origin,
std::string label) {
if (!destination) {
VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
return false;
}
auto bytes_per_pixel =
BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format);
auto bytes_per_image =
destination->GetTextureDescriptor().size.Area() * bytes_per_pixel;
if (source.range.length != bytes_per_image) {
VALIDATION_LOG
<< "Attempted to add a texture blit with out of bounds access.";
return false;
}
return OnCopyBufferToTextureCommand(std::move(source), std::move(destination),
destination_origin, std::move(label));
}
bool BlitPass::GenerateMipmap(std::shared_ptr<Texture> texture,
std::string label) {
if (!texture) {
VALIDATION_LOG << "Attempted to add an invalid mipmap generation command "
"with no texture.";
return false;
}
return OnGenerateMipmapCommand(std::move(texture), std::move(label));
}
} // namespace impeller