Skip to content

Commit

Permalink
[Tizen] Support extenal vulkan texture for skia
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaowei-guan committed Nov 14, 2024
1 parent 547521a commit c9d57df
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 2 deletions.
2 changes: 2 additions & 0 deletions shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ template("embedder_source_set") {

if (embedder_enable_vulkan) {
sources += [
"embedder_external_texture_vulkan.cc",
"embedder_external_texture_vulkan.h",
"embedder_surface_vulkan.cc",
"embedder_surface_vulkan.h",
]
Expand Down
22 changes: 22 additions & 0 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2056,6 +2056,28 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
external_texture_metal_callback);
}
}
#endif
#ifdef SHELL_ENABLE_VULKAN
flutter::EmbedderExternalTextureVulkan::ExternalTextureCallback
external_texture_vulkan_callback;
if (config->type == kVulkan) {
const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan;
if (SAFE_ACCESS(vulkan_config, external_texture_frame_callback, nullptr)) {
external_texture_vulkan_callback =
[ptr = vulkan_config->external_texture_frame_callback, user_data](
int64_t texture_identifier, size_t width,
size_t height) -> std::unique_ptr<FlutterVulkanTexture> {
std::unique_ptr<FlutterVulkanTexture> texture =
std::make_unique<FlutterVulkanTexture>();
if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
return nullptr;
}
return texture;
};
external_texture_resolver = std::make_unique<ExternalTextureResolver>(
external_texture_vulkan_callback);
}
}
#endif
auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
auto thread_config_callback = [&custom_task_runners](
Expand Down
35 changes: 33 additions & 2 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,10 +758,37 @@ typedef bool (*FlutterVulkanPresentCallback)(
void* /* user data */,
const FlutterVulkanImage* /* image */);

typedef struct {
/// Handle to the VkImage that is owned by the embedder. The engine will
/// bind this image for writing the frame.
FlutterVulkanImageHandle image;
/// The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM).
uint32_t format;
/// User data to be returned on the invocation of the destruction callback.
void* user_data;
/// Callback invoked (on an engine managed thread) that asks the embedder to
/// collect the texture.
VoidCallback destruction_callback;
/// Optional parameters for texture height/width, default is 0, non-zero means
/// the texture has the specified width/height.
/// Width of the texture.
size_t width;
/// Height of the texture.
size_t height;
} FlutterVulkanTexture;

/// Callback to provide an external texture for a given texture_id.
/// See: external_texture_frame_callback.
typedef bool (*FlutterVulkanTextureFrameCallback)(
void* /* user data */,
int64_t /* texture identifier */,
size_t /* width */,
size_t /* height */,
FlutterVulkanTexture* /* texture out */);

typedef struct {
/// The size of this struct. Must be sizeof(FlutterVulkanRendererConfig).
size_t struct_size;

/// The Vulkan API version. This should match the value set in
/// VkApplicationInfo::apiVersion when the VkInstance was created.
uint32_t version;
Expand Down Expand Up @@ -821,7 +848,11 @@ typedef struct {
/// without any additional synchronization.
/// Not used if a FlutterCompositor is supplied in FlutterProjectArgs.
FlutterVulkanPresentCallback present_image_callback;

/// When the embedder specifies that a texture has a frame available, the
/// engine will call this method (on an internal engine managed thread) so
/// that external texture details can be supplied to the engine for subsequent
/// composition.
FlutterVulkanTextureFrameCallback external_texture_frame_callback;
} FlutterVulkanRendererConfig;

typedef struct {
Expand Down
13 changes: 13 additions & 0 deletions shell/platform/embedder/embedder_external_texture_resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ EmbedderExternalTextureResolver::EmbedderExternalTextureResolver(
: metal_callback_(std::move(metal_callback)) {}
#endif

#ifdef SHELL_ENABLE_VULKAN
EmbedderExternalTextureResolver::EmbedderExternalTextureResolver(
EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback)
: vulkan_callback_(std::move(vulkan_callback)) {}
#endif

std::unique_ptr<Texture>
EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) {
#ifdef SHELL_ENABLE_GL
Expand All @@ -48,6 +54,13 @@ EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) {
}
#endif

#ifdef SHELL_ENABLE_VULKAN
if (vulkan_callback_) {
return std::make_unique<EmbedderExternalTextureVulkan>(
texture_id, vulkan_callback_);
}
#endif

return nullptr;
}

Expand Down
13 changes: 13 additions & 0 deletions shell/platform/embedder/embedder_external_texture_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#include "flutter/shell/platform/embedder/embedder_external_texture_metal.h"
#endif

#ifdef SHELL_ENABLE_VULKAN
#include "flutter/shell/platform/embedder/embedder_external_texture_vulkan.h"
#endif

namespace flutter {
class EmbedderExternalTextureResolver {
public:
Expand All @@ -35,6 +39,11 @@ class EmbedderExternalTextureResolver {
EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback);
#endif

#ifdef SHELL_ENABLE_VULKAN
explicit EmbedderExternalTextureResolver(
EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback);
#endif

std::unique_ptr<Texture> ResolveExternalTexture(int64_t texture_id);

bool SupportsExternalTextures();
Expand All @@ -47,6 +56,10 @@ class EmbedderExternalTextureResolver {
#ifdef SHELL_ENABLE_METAL
EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback_;
#endif

#ifdef SHELL_ENABLE_VULKAN
EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback_;
#endif
bool enable_impeller_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureResolver);
Expand Down
158 changes: 158 additions & 0 deletions shell/platform/embedder/embedder_external_texture_vulkan.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// 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/embedder/embedder_external_texture_vulkan.h"

#include "flutter/fml/logging.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/renderer/context.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "third_party/skia/include/core/SkAlphaType.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkColorType.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"

namespace flutter {
EmbedderExternalTextureVulkan::EmbedderExternalTextureVulkan(
int64_t texture_identifier,
const ExternalTextureCallback& callback)
: Texture(texture_identifier), external_texture_callback_(callback) {
FML_DCHECK(external_texture_callback_);
}

// |flutter::Texture|
void EmbedderExternalTextureVulkan::Paint(PaintContext& context,
const SkRect& bounds,
bool freeze,
const DlImageSampling sampling) {
if (last_image_ == nullptr) {
last_image_ =
ResolveTexture(Id(), //
context.gr_context, //
context.aiks_context, //
SkISize::Make(bounds.width(), bounds.height()) //
);
}

DlCanvas* canvas = context.canvas;
const DlPaint* paint = context.paint;

if (last_image_) {
SkRect image_bounds = SkRect::Make(last_image_->bounds());
if (bounds != image_bounds) {
canvas->DrawImageRect(last_image_, image_bounds, bounds, sampling, paint);
} else {
canvas->DrawImage(last_image_, {bounds.x(), bounds.y()}, sampling, paint);
}
}
}

sk_sp<DlImage> EmbedderExternalTextureVulkan::ResolveTexture(
int64_t texture_id,
GrDirectContext* context,
impeller::AiksContext* aiks_context,
const SkISize& size) {
if (!!aiks_context) {
return ResolveTextureImpeller(texture_id, aiks_context, size);
} else {
return ResolveTextureSkia(texture_id, context, size);
}
}

sk_sp<DlImage> EmbedderExternalTextureVulkan::ResolveTextureSkia(
int64_t texture_id,
GrDirectContext* context,
const SkISize& size) {
context->flushAndSubmit();
context->resetContext(kAll_GrBackendState);
std::unique_ptr<FlutterVulkanTexture> texture;

if (!texture) {
return nullptr;
}

size_t width = size.width();
size_t height = size.height();

if (texture->width != 0 && texture->height != 0) {
width = texture->width;
height = texture->height;
}

GrVkImageInfo image_info = {
.fImage = reinterpret_cast<VkImage>(texture->image),
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.fFormat = static_cast<VkFormat>(texture->format),
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT,
.fSampleCount = 1,
.fLevelCount = 1,
};

auto gr_backend_texture =
GrBackendTextures::MakeVk(width, height, image_info);
SkImages::TextureReleaseProc release_proc = texture->destruction_callback;
auto image =
SkImages::BorrowTextureFrom(context, // context
gr_backend_texture, // texture handle
kTopLeft_GrSurfaceOrigin, // origin
kRGBA_8888_SkColorType, // color type
kPremul_SkAlphaType, // alpha type
nullptr, // colorspace
release_proc, // texture release proc
texture->user_data // texture release context
);

if (!image) {
// In case Skia rejects the image, call the release proc so that
// embedders can perform collection of intermediates.
if (release_proc) {
release_proc(texture->user_data);
}
FML_LOG(ERROR) << "Could not create external texture->";
return nullptr;
}

return DlImage::Make(std::move(image));
}

sk_sp<DlImage> EmbedderExternalTextureVulkan::ResolveTextureImpeller(
int64_t texture_id,
impeller::AiksContext* aiks_context,
const SkISize& size) {
std::unique_ptr<FlutterVulkanTexture> texture =
external_texture_callback_(texture_id, size.width(), size.height());
if(!texture){
return nullptr;
}
return nullptr;
}

EmbedderExternalTextureVulkan::~EmbedderExternalTextureVulkan() = default;

// |flutter::Texture|
void EmbedderExternalTextureVulkan::OnGrContextCreated() {}

// |flutter::Texture|
void EmbedderExternalTextureVulkan::OnGrContextDestroyed() {}

// |flutter::Texture|
void EmbedderExternalTextureVulkan::MarkNewFrameAvailable() {
last_image_ = nullptr;
}

// |flutter::Texture|
void EmbedderExternalTextureVulkan::OnTextureUnregistered() {}

} // namespace flutter
61 changes: 61 additions & 0 deletions shell/platform/embedder/embedder_external_texture_vulkan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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.

#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_

#include "flutter/common/graphics/texture.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "third_party/skia/include/core/SkSize.h"

namespace flutter {

class EmbedderExternalTextureVulkan : public flutter::Texture {
public:
using ExternalTextureCallback = std::function<
std::unique_ptr<FlutterVulkanTexture>(int64_t, size_t, size_t)>;
EmbedderExternalTextureVulkan(int64_t texture_identifier,
const ExternalTextureCallback& callback);

~EmbedderExternalTextureVulkan();

private:
const ExternalTextureCallback& external_texture_callback_;

sk_sp<DlImage> last_image_;

sk_sp<DlImage> ResolveTexture(int64_t texture_id,
GrDirectContext* context,
impeller::AiksContext* aiks_context,
const SkISize& size);
sk_sp<DlImage> ResolveTextureSkia(int64_t texture_id,
GrDirectContext* context,
const SkISize& size);
sk_sp<DlImage> ResolveTextureImpeller(int64_t texture_id,
impeller::AiksContext* aiks_context,
const SkISize& size);
// |flutter::Texture|
void Paint(PaintContext& context,
const SkRect& bounds,
bool freeze,
const DlImageSampling sampling) override;

// |flutter::Texture|
void OnGrContextCreated() override;

// |flutter::Texture|
void OnGrContextDestroyed() override;

// |flutter::Texture|
void MarkNewFrameAvailable() override;

// |flutter::Texture|
void OnTextureUnregistered() override;

FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureVulkan);
};
} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_VULKAN_H_

0 comments on commit c9d57df

Please sign in to comment.