blob: 0126c6566ca483eaa6bc2bccf96d27ab3b65b2d9 [file] [log] [blame]
// 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"
namespace impeller {
BlitPass::BlitPass() {}
BlitPass::~BlitPass() = default;
void BlitPass::SetLabel(std::string label) {
if (label.empty()) {
return;
}
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->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,
std::optional<IRect> destination_region,
std::string label,
uint32_t slice,
bool convert_to_read) {
if (!destination) {
VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
return false;
}
ISize destination_size = destination->GetSize();
IRect destination_region_value =
destination_region.value_or(IRect::MakeSize(destination_size));
if (destination_region_value.GetX() < 0 ||
destination_region_value.GetY() < 0 ||
destination_region_value.GetRight() > destination_size.width ||
destination_region_value.GetBottom() > destination_size.height) {
VALIDATION_LOG << "Blit region cannot be larger than destination texture.";
return false;
}
auto bytes_per_pixel =
BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format);
auto bytes_per_region = destination_region_value.Area() * bytes_per_pixel;
if (source.range.length != bytes_per_region) {
VALIDATION_LOG
<< "Attempted to add a texture blit with out of bounds access.";
return false;
}
if (slice > 5) {
VALIDATION_LOG << "Invalid value for slice: " << slice;
return false;
}
return OnCopyBufferToTextureCommand(std::move(source), std::move(destination),
destination_region_value,
std::move(label), slice, convert_to_read);
}
bool BlitPass::ConvertTextureToShaderRead(
const std::shared_ptr<Texture>& texture) {
return true;
}
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