blob: 88574548d6c11773f407c2c7b8c093067a4d51a0 [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 "flutter/shell/platform/android/image_external_texture_vk.h"
#include <cstdint>
#include "flutter/impeller/core/formats.h"
#include "flutter/impeller/core/texture_descriptor.h"
#include "flutter/impeller/display_list/dl_image_impeller.h"
#include "flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h"
#include "flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h"
#include "flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h"
#include "flutter/impeller/renderer/backend/vulkan/texture_vk.h"
#include "flutter/impeller/toolkit/android/hardware_buffer.h"
namespace flutter {
ImageExternalTextureVK::ImageExternalTextureVK(
const std::shared_ptr<impeller::ContextVK>& impeller_context,
int64_t id,
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
: ImageExternalTexture(id, image_texture_entry, jni_facade),
impeller_context_(impeller_context) {}
ImageExternalTextureVK::~ImageExternalTextureVK() {}
void ImageExternalTextureVK::Attach(PaintContext& context) {
if (state_ == AttachmentState::kUninitialized) {
// First processed frame we are attached.
state_ = AttachmentState::kAttached;
}
}
void ImageExternalTextureVK::Detach() {}
void ImageExternalTextureVK::ProcessFrame(PaintContext& context,
const SkRect& bounds) {
JavaLocalRef image = AcquireLatestImage();
if (image.is_null()) {
return;
}
JavaLocalRef hardware_buffer = HardwareBufferFor(image);
AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer);
auto hb_desc =
impeller::android::HardwareBuffer::Describe(latest_hardware_buffer);
std::optional<HardwareBufferKey> key =
impeller::android::HardwareBuffer::GetSystemUniqueID(
latest_hardware_buffer);
auto existing_image = image_lru_.FindImage(key);
if (existing_image != nullptr || !hb_desc.has_value()) {
dl_image_ = existing_image;
CloseHardwareBuffer(hardware_buffer);
return;
}
auto texture_source = std::make_shared<impeller::AHBTextureSourceVK>(
impeller_context_, latest_hardware_buffer, hb_desc.value());
if (!texture_source->IsValid()) {
CloseHardwareBuffer(hardware_buffer);
return;
}
auto texture =
std::make_shared<impeller::TextureVK>(impeller_context_, texture_source);
// Transition the layout to shader read.
{
auto buffer = impeller_context_->CreateCommandBuffer();
impeller::CommandBufferVK& buffer_vk =
impeller::CommandBufferVK::Cast(*buffer);
impeller::BarrierVK barrier;
barrier.cmd_buffer = buffer_vk.GetEncoder()->GetCommandBuffer();
barrier.src_access = impeller::vk::AccessFlagBits::eColorAttachmentWrite |
impeller::vk::AccessFlagBits::eTransferWrite;
barrier.src_stage =
impeller::vk::PipelineStageFlagBits::eColorAttachmentOutput |
impeller::vk::PipelineStageFlagBits::eTransfer;
barrier.dst_access = impeller::vk::AccessFlagBits::eShaderRead;
barrier.dst_stage = impeller::vk::PipelineStageFlagBits::eFragmentShader;
barrier.new_layout = impeller::vk::ImageLayout::eShaderReadOnlyOptimal;
if (!texture->SetLayout(barrier)) {
return;
}
if (!impeller_context_->GetCommandQueue()->Submit({buffer}).ok()) {
return;
}
}
dl_image_ = impeller::DlImageImpeller::Make(texture);
if (key.has_value()) {
image_lru_.AddImage(dl_image_, key.value());
}
CloseHardwareBuffer(hardware_buffer);
}
} // namespace flutter