浏览代码

external texture layer support.

/siyaoH-1.17-PlatformMessage
Kevin Gu 4 年前
当前提交
c22a6999
共有 17 个文件被更改,包括 956 次插入5 次删除
  1. 25
      com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs
  2. 16
      com.unity.uiwidgets/Runtime/ui2/compositing.cs
  3. 6
      engine/Build.bee.cs
  4. 6
      engine/src/lib/ui/compositing/scene_builder.cc
  5. 29
      engine/src/shell/platform/unity/uiwidgets_panel.cc
  6. 4
      engine/src/shell/platform/unity/uiwidgets_panel.h
  7. 6
      engine/src/shell/platform/unity/unity_surface_manager.h
  8. 198
      engine/src/lib/ui/painting/codec.cc
  9. 46
      engine/src/lib/ui/painting/codec.h
  10. 22
      engine/src/lib/ui/painting/frame_info.cc
  11. 25
      engine/src/lib/ui/painting/frame_info.h
  12. 194
      engine/src/lib/ui/painting/multi_frame_codec.cc
  13. 69
      engine/src/lib/ui/painting/multi_frame_codec.h
  14. 110
      engine/src/lib/ui/painting/single_frame_codec.cc
  15. 40
      engine/src/lib/ui/painting/single_frame_codec.h
  16. 119
      engine/src/shell/platform/unity/unity_external_texture_gl.cc
  17. 46
      engine/src/shell/platform/unity/unity_external_texture_gl.h

25
com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs


protected virtual void main() {
}
public void entryPoint() {
void _entryPoint() {
try {
isolate = Isolate.current;
Window.instance._panel = this;

_renderTexture = null;
}
public int registerTexture(Texture texture) {
return UIWidgetsPanel_registerTexture(_ptr, texture.GetNativeTexturePtr());
}
public void unregisterTexture(int textureId) {
UIWidgetsPanel_unregisterTexture(_ptr, textureId);
}
public void markNewFrameAvailable(int textureId) {
UIWidgetsPanel_markNewFrameAvailable(_ptr, textureId);
}
delegate void UIWidgetsPanel_EntrypointCallback(IntPtr handle);
[MonoPInvokeCallback(typeof(UIWidgetsPanel_EntrypointCallback))]

panel.entryPoint();
panel._entryPoint();
}
[DllImport(NativeBindings.dllName)]

[DllImport(NativeBindings.dllName)]
static extern void UIWidgetsPanel_onRenderTexture(
IntPtr ptr, IntPtr nativeTexturePtr, int width, int height, float dpi);
[DllImport(NativeBindings.dllName)]
static extern int UIWidgetsPanel_registerTexture(IntPtr ptr, IntPtr nativeTexturePtr);
[DllImport(NativeBindings.dllName)]
static extern void UIWidgetsPanel_unregisterTexture(IntPtr ptr, int textureId);
[DllImport(NativeBindings.dllName)]
static extern void UIWidgetsPanel_markNewFrameAvailable(IntPtr ptr, int textureId);
}
}

16
com.unity.uiwidgets/Runtime/ui2/compositing.cs


SceneBuilder_addPicture(_ptr, offset.dx, offset.dy, picture._ptr, hints);
}
public void addTexture(
int textureId,
Offset offset = null,
float width = 0.0f,
float height = 0.0f,
bool freeze = false
) {
offset = offset ?? Offset.zero;
SceneBuilder_addTexture(_ptr, offset.dx, offset.dy, width, height, textureId, freeze);
}
[DllImport(NativeBindings.dllName)]
static extern IntPtr SceneBuilder_constructor();

[DllImport(NativeBindings.dllName)]
static extern IntPtr SceneBuilder_addPicture(IntPtr ptr, float dx, float dy, IntPtr picture, int hints);
[DllImport(NativeBindings.dllName)]
static extern void SceneBuilder_addTexture(IntPtr ptr, float dx, float dy, float width, float height,
int textureId, bool freeze);
[DllImport(NativeBindings.dllName)]
static extern void SceneBuilder_addRetained(IntPtr ptr, IntPtr retainedLayer);

6
engine/Build.bee.cs


"src/shell/platform/unity/gfx_worker_task_runner.cc",
"src/shell/platform/unity/gfx_worker_task_runner.h",
"src/shell/platform/unity/unity_surface_manager.cc",
"src/shell/platform/unity/unity_surface_manager.h",
"src/shell/platform/unity/unity_external_texture_gl.cc",
"src/shell/platform/unity/unity_external_texture_gl.h",
"src/shell/platform/unity/unity_surface_manager.cc",
"src/shell/platform/unity/unity_surface_manager.h",
"src/shell/platform/unity/win32_task_runner.cc",
"src/shell/platform/unity/win32_task_runner.h",

6
engine/src/lib/ui/compositing/scene_builder.cc


ptr->addPicture(dx, dy, picture, hints);
}
UIWIDGETS_API(void)
SceneBuilder_addTexture(SceneBuilder* ptr, float dx, float dy, float width,
float height, int texture_id, bool freeze) {
ptr->addTexture(dx, dy, width, height, texture_id, freeze);
}
} // namespace uiwidgets

29
engine/src/shell/platform/unity/uiwidgets_panel.cc


#include "runtime/mono_api.h"
#include "shell/platform/embedder/embedder_engine.h"
#include "uiwidgets_system.h"
#include "unity_external_texture_gl.h"
namespace uiwidgets {

reinterpret_cast<EmbedderEngine*>(engine_)->SetViewportMetrics(metrics);
}
int UIWidgetsPanel::RegisterTexture(void* native_texture_ptr) {
int texture_identifier = 0;
texture_identifier++;
auto* engine = reinterpret_cast<EmbedderEngine*>(engine_);
engine->GetShell().GetPlatformView()->RegisterTexture(
std::make_unique<UnityExternalTextureGL>(
texture_identifier, native_texture_ptr, surface_manager_.get()));
return texture_identifier;
}
void UIWidgetsPanel::UnregisterTexture(int texture_id) {
auto* engine = reinterpret_cast<EmbedderEngine*>(engine_);
engine->GetShell().GetPlatformView()->UnregisterTexture(texture_id);
}
std::chrono::nanoseconds UIWidgetsPanel::ProcessMessages() {
return std::chrono::nanoseconds(task_runner_->ProcessTasks().count());
}

UIWidgetsPanel_onRenderTexture(UIWidgetsPanel* panel, void* native_texture_ptr,
int width, int height, float dpi) {
panel->OnRenderTexture(native_texture_ptr, width, height, dpi);
}
UIWIDGETS_API(int)
UIWidgetsPanel_registerTexture(UIWidgetsPanel* panel,
void* native_texture_ptr) {
return panel->RegisterTexture(native_texture_ptr);
}
UIWIDGETS_API(void)
UIWidgetsPanel_unregisterTexture(UIWidgetsPanel* panel, int texture_id) {
return panel->UnregisterTexture(texture_id);
}
} // namespace uiwidgets

4
engine/src/shell/platform/unity/uiwidgets_panel.h


void OnRenderTexture(void* native_texture_ptr, size_t width, size_t height,
float dpi);
int RegisterTexture(void* native_texture_ptr);
void UnregisterTexture(int texture_id);
std::chrono::nanoseconds ProcessMessages();
void ProcessVSync();

6
engine/src/shell/platform/unity/unity_surface_manager.h


void DestroyRenderSurface();
bool ClearCurrent();
EGLDisplay GetEGLDisplay() const { return egl_display_; }
ID3D11Device* GetD3D11Device() const { return d3d11_device_; }
FML_DISALLOW_COPY_AND_ASSIGN(UnitySurfaceManager);

198
engine/src/lib/ui/painting/codec.cc


#include "codec.h"
#include <variant>
#include "common/task_runners.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/trace_event.h"
#include "frame_info.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkPixelRef.h"
#include "multi_frame_codec.h"
#include "single_frame_codec.h"
#if OS_ANDROID
#include <sys/mman.h>
#endif
namespace uiwidgets {
namespace {
// This must be kept in sync with the enum in painting.dart
enum PixelFormat {
kRGBA8888,
kBGRA8888,
};
#if OS_ANDROID
// Compressed image buffers are allocated on the UI thread but are deleted on a
// decoder worker thread. Android's implementation of malloc appears to
// continue growing the native heap size when the allocating thread is
// different from the freeing thread. To work around this, create an SkData
// backed by an anonymous mapping.
sk_sp<SkData> MakeSkDataWithCopy(const void* data, size_t length) {
if (length == 0) {
return SkData::MakeEmpty();
}
size_t mapping_length = length + sizeof(size_t);
void* mapping = ::mmap(nullptr, mapping_length, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (mapping == MAP_FAILED) {
return SkData::MakeEmpty();
}
*reinterpret_cast<size_t*>(mapping) = mapping_length;
void* mapping_data = reinterpret_cast<char*>(mapping) + sizeof(size_t);
::memcpy(mapping_data, data, length);
SkData::ReleaseProc proc = [](const void* ptr, void* context) {
size_t* size_ptr = reinterpret_cast<size_t*>(context);
FML_DCHECK(ptr == size_ptr + 1);
if (::munmap(const_cast<void*>(context), *size_ptr) == -1) {
FML_LOG(ERROR) << "munmap of codec SkData failed";
}
};
return SkData::MakeWithProc(mapping_data, length, proc, mapping);
}
#else
sk_sp<SkData> MakeSkDataWithCopy(const void* data, size_t length) {
return SkData::MakeWithCopy(data, length);
}
#endif // OS_ANDROID
} // anonymous namespace
static std::variant<ImageDecoder::ImageInfo, std::string> ConvertImageInfo(
Codec::_ImageInfo _image_info) {
PixelFormat pixel_format = static_cast<PixelFormat>(_image_info.format);
SkColorType color_type = kUnknown_SkColorType;
switch (pixel_format) {
case kRGBA8888:
color_type = kRGBA_8888_SkColorType;
break;
case kBGRA8888:
color_type = kBGRA_8888_SkColorType;
break;
}
if (color_type == kUnknown_SkColorType) {
return "Invalid pixel format";
}
int width = _image_info.width;
if (width <= 0) {
return "width must be greater than zero";
}
int height = _image_info.height;
if (height <= 0) {
return "height must be greater than zero";
}
ImageDecoder::ImageInfo image_info;
image_info.sk_info =
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
image_info.row_bytes = _image_info.rowBytes;
if (image_info.row_bytes < image_info.sk_info.minRowBytes()) {
return "rowBytes does not match the width of the image";
}
return image_info;
}
UIWIDGETS_API(const char*)
Codec_instantiateImageCodec(uint8_t* data, int data_length,
Codec::InstantiateImageCodecCallback callback,
Mono_Handle callback_handle,
Codec::_ImageInfo _image_info, bool has_image_info,
int target_width, int target_height) {
if (!callback || !callback_handle) {
return "Callback must be a function";
}
std::optional<ImageDecoder::ImageInfo> image_info;
if (has_image_info) {
auto image_info_results = ConvertImageInfo(_image_info);
if (auto value =
std::get_if<ImageDecoder::ImageInfo>(&image_info_results)) {
image_info = *value;
} else if (auto error = std::get_if<std::string>(&image_info_results)) {
return error->c_str();
}
}
sk_sp<SkData> buffer = MakeSkDataWithCopy(data, data_length);
if (image_info) {
const auto expected_size =
image_info->row_bytes * image_info->sk_info.height();
if (buffer->size() < expected_size) {
return "Pixel buffer size does not match image size";
}
}
const int targetWidth = target_width;
const int targetHeight = target_height;
std::unique_ptr<SkCodec> codec;
bool single_frame;
if (image_info) {
single_frame = true;
} else {
codec = SkCodec::MakeFromData(buffer);
if (!codec) {
return "Could not instantiate image codec.";
}
single_frame = codec->getFrameCount() == 1;
}
fml::RefPtr<Codec> ui_codec;
if (single_frame) {
ImageDecoder::ImageDescriptor descriptor;
descriptor.decompressed_image_info = image_info;
if (targetWidth > 0) {
descriptor.target_width = targetWidth;
}
if (targetHeight > 0) {
descriptor.target_height = targetHeight;
}
descriptor.data = std::move(buffer);
ui_codec = fml::MakeRefCounted<SingleFrameCodec>(std::move(descriptor));
} else {
ui_codec = fml::MakeRefCounted<MultiFrameCodec>(std::move(codec));
}
ui_codec->AddRef();
callback(callback_handle, ui_codec.get());
return nullptr;
}
void Codec::dispose() {}
UIWIDGETS_API(void) Codec_dispose(Codec* ptr) { ptr->Release(); }
UIWIDGETS_API(int) Codec_frameCount(Codec* ptr) { return ptr->frameCount(); }
UIWIDGETS_API(int) Codec_repetitionCount(Codec* ptr) {
return ptr->repetitionCount();
}
UIWIDGETS_API(const char*)
Codec_getNextFrame(Codec* ptr, Codec::GetNextFrameCallback callback,
Mono_Handle callback_handle) {
return ptr->getNextFrame(callback, callback_handle);
}
} // namespace uiwidgets

46
engine/src/lib/ui/painting/codec.h


#pragma once
#include "frame_info.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkImage.h"
#include "runtime/mono_state.h"
namespace uiwidgets {
class Codec : public fml::RefCountedThreadSafe<Codec> {
public:
virtual ~Codec() {}
virtual int frameCount() const = 0;
virtual int repetitionCount() const = 0;
typedef void (*InstantiateImageCodecCallback)(Mono_Handle callback_handle,
Codec* codec);
typedef void (*GetNextFrameCallback)(Mono_Handle callback_handle,
FrameInfo* frame_info);
virtual const char* getNextFrame(GetNextFrameCallback callback,
Mono_Handle callback_handle) = 0;
virtual size_t GetAllocationSize() { return 0; }
void dispose();
struct _ImageInfo {
int width;
int height;
int format;
int rowBytes;
};
struct PendingCallback {
std::weak_ptr<MonoState> mono_state;
GetNextFrameCallback callback;
Mono_Handle callback_handle;
};
};
} // namespace uiwidgets

22
engine/src/lib/ui/painting/frame_info.cc


#include "frame_info.h"
namespace uiwidgets {
FrameInfo::FrameInfo(fml::RefPtr<CanvasImage> image, int durationMillis)
: image_(std::move(image)), durationMillis_(durationMillis) {}
FrameInfo::~FrameInfo() {}
UIWIDGETS_API(void) FrameInfo_dispose(FrameInfo* ptr) { ptr->Release(); }
UIWIDGETS_API(int) FrameInfo_durationMillis(FrameInfo* ptr) {
return ptr->durationMillis();
}
UIWIDGETS_API(CanvasImage*) FrameInfo_image(FrameInfo* ptr) {
auto image = ptr->image();
image->AddRef();
return image.get();
}
} // namespace uiwidgets

25
engine/src/lib/ui/painting/frame_info.h


#pragma once
#include "image.h"
namespace uiwidgets {
// A single animation frame.
class FrameInfo final : public fml::RefCountedThreadSafe<FrameInfo> {
public:
int durationMillis() { return durationMillis_; }
fml::RefPtr<CanvasImage> image() { return image_; }
private:
FrameInfo(fml::RefPtr<CanvasImage> image, int durationMillis);
~FrameInfo();
const fml::RefPtr<CanvasImage> image_;
const int durationMillis_;
FML_FRIEND_MAKE_REF_COUNTED(FrameInfo);
FML_FRIEND_REF_COUNTED_THREAD_SAFE(FrameInfo);
};
} // namespace uiwidgets

194
engine/src/lib/ui/painting/multi_frame_codec.cc


#include "multi_frame_codec.h"
#include "flutter/fml/make_copyable.h"
#include "include/core/SkPixelRef.h"
#include "lib/ui/ui_mono_state.h"
namespace uiwidgets {
MultiFrameCodec::MultiFrameCodec(std::unique_ptr<SkCodec> codec)
: state_(new State(std::move(codec))) {}
MultiFrameCodec::~MultiFrameCodec() = default;
MultiFrameCodec::State::State(std::unique_ptr<SkCodec> codec)
: codec_(std::move(codec)),
frameCount_(codec_->getFrameCount()),
repetitionCount_(codec_->getRepetitionCount()),
nextFrameIndex_(0) {}
static void InvokeNextFrameCallback(
fml::RefPtr<FrameInfo> frameInfo,
std::unique_ptr<Codec::PendingCallback> callback, size_t trace_id) {
std::shared_ptr<MonoState> mono_state = callback->mono_state.lock();
if (!mono_state) {
FML_DLOG(ERROR) << "Could not acquire Mono state while attempting to fire "
"next frame callback.";
callback->callback(callback->callback_handle, nullptr);
return;
}
MonoState::Scope scope(mono_state);
if (!frameInfo) {
callback->callback(callback->callback_handle, nullptr);
} else {
frameInfo->AddRef();
callback->callback(callback->callback_handle, frameInfo.get());
}
}
// Copied the source bitmap to the destination. If this cannot occur due to
// running out of memory or the image info not being compatible, returns false.
static bool CopyToBitmap(SkBitmap* dst, SkColorType dstColorType,
const SkBitmap& src) {
SkPixmap srcPM;
if (!src.peekPixels(&srcPM)) {
return false;
}
SkBitmap tmpDst;
SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
if (!tmpDst.setInfo(dstInfo)) {
return false;
}
if (!tmpDst.tryAllocPixels()) {
return false;
}
SkPixmap dstPM;
if (!tmpDst.peekPixels(&dstPM)) {
return false;
}
if (!srcPM.readPixels(dstPM)) {
return false;
}
dst->swap(tmpDst);
return true;
}
sk_sp<SkImage> MultiFrameCodec::State::GetNextFrameImage(
fml::WeakPtr<GrContext> resourceContext) {
SkBitmap bitmap = SkBitmap();
SkImageInfo info = codec_->getInfo().makeColorType(kN32_SkColorType);
if (info.alphaType() == kUnpremul_SkAlphaType) {
info = info.makeAlphaType(kPremul_SkAlphaType);
}
bitmap.allocPixels(info);
SkCodec::Options options;
options.fFrameIndex = nextFrameIndex_;
SkCodec::FrameInfo frameInfo;
codec_->getFrameInfo(nextFrameIndex_, &frameInfo);
const int requiredFrameIndex = frameInfo.fRequiredFrame;
if (requiredFrameIndex != SkCodec::kNoFrame) {
if (lastRequiredFrame_ == nullptr) {
FML_LOG(ERROR) << "Frame " << nextFrameIndex_ << " depends on frame "
<< requiredFrameIndex
<< " and no required frames are cached.";
return nullptr;
} else if (lastRequiredFrameIndex_ != requiredFrameIndex) {
FML_DLOG(INFO) << "Required frame " << requiredFrameIndex
<< " is not cached. Using " << lastRequiredFrameIndex_
<< " instead";
}
if (lastRequiredFrame_->getPixels() &&
CopyToBitmap(&bitmap, lastRequiredFrame_->colorType(),
*lastRequiredFrame_)) {
options.fPriorFrame = requiredFrameIndex;
}
}
if (SkCodec::kSuccess != codec_->getPixels(info, bitmap.getPixels(),
bitmap.rowBytes(), &options)) {
FML_LOG(ERROR) << "Could not getPixels for frame " << nextFrameIndex_;
return nullptr;
}
// Hold onto this if we need it to decode future frames.
if (frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kKeep) {
lastRequiredFrame_ = std::make_unique<SkBitmap>(bitmap);
lastRequiredFrameIndex_ = nextFrameIndex_;
}
if (resourceContext) {
SkPixmap pixmap(bitmap.info(), bitmap.pixelRef()->pixels(),
bitmap.pixelRef()->rowBytes());
return SkImage::MakeCrossContextFromPixmap(resourceContext.get(), pixmap,
true);
} else {
// Defer decoding until time of draw later on the raster thread. Can happen
// when GL operations are currently forbidden such as in the background
// on iOS.
return SkImage::MakeFromBitmap(bitmap);
}
}
void MultiFrameCodec::State::GetNextFrameAndInvokeCallback(
std::unique_ptr<PendingCallback> callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner,
fml::WeakPtr<GrContext> resourceContext,
fml::RefPtr<SkiaUnrefQueue> unref_queue, size_t trace_id) {
fml::RefPtr<FrameInfo> frameInfo = NULL;
sk_sp<SkImage> skImage = GetNextFrameImage(resourceContext);
if (skImage) {
fml::RefPtr<CanvasImage> image = CanvasImage::Create();
image->set_image({skImage, std::move(unref_queue)});
SkCodec::FrameInfo skFrameInfo;
codec_->getFrameInfo(nextFrameIndex_, &skFrameInfo);
frameInfo =
fml::MakeRefCounted<FrameInfo>(std::move(image), skFrameInfo.fDuration);
}
nextFrameIndex_ = (nextFrameIndex_ + 1) % frameCount_;
ui_task_runner->PostTask(fml::MakeCopyable(
[callback = std::move(callback), frameInfo, trace_id]() mutable {
InvokeNextFrameCallback(frameInfo, std::move(callback), trace_id);
}));
}
const char* MultiFrameCodec::getNextFrame(GetNextFrameCallback callback,
Mono_Handle callback_handle) {
static size_t trace_counter = 1;
const size_t trace_id = trace_counter++;
if (!callback || !callback_handle) {
return "Callback must be a function";
}
auto* mono_state = UIMonoState::Current();
const auto& task_runners = mono_state->GetTaskRunners();
task_runners.GetIOTaskRunner()->PostTask(fml::MakeCopyable(
[callback = std::make_unique<PendingCallback>(PendingCallback{
MonoState::Current()->GetWeakPtr(), callback, callback_handle}),
weak_state = std::weak_ptr<MultiFrameCodec::State>(state_), trace_id,
ui_task_runner = task_runners.GetUITaskRunner(),
io_manager = mono_state->GetIOManager()]() mutable {
auto state = weak_state.lock();
if (!state) {
ui_task_runner->PostTask(
fml::MakeCopyable([callback = std::move(callback)]() {
callback->callback(callback->callback_handle, nullptr);
}));
return;
}
state->GetNextFrameAndInvokeCallback(
std::move(callback), std::move(ui_task_runner),
io_manager->GetResourceContext(), io_manager->GetSkiaUnrefQueue(),
trace_id);
}));
return nullptr;
}
int MultiFrameCodec::frameCount() const { return state_->frameCount_; }
int MultiFrameCodec::repetitionCount() const {
return state_->repetitionCount_;
}
} // namespace uiwidgets

69
engine/src/lib/ui/painting/multi_frame_codec.h


#pragma once
#include "codec.h"
#include "flutter/fml/macros.h"
#include "runtime/mono_state.h"
namespace uiwidgets {
class MultiFrameCodec : public Codec {
public:
MultiFrameCodec(std::unique_ptr<SkCodec> codec);
~MultiFrameCodec() override;
// |Codec|
int frameCount() const override;
// |Codec|
int repetitionCount() const override;
// |Codec|
const char* getNextFrame(GetNextFrameCallback callback,
Mono_Handle callback_handle) override;
private:
// Captures the state shared between the IO and UI task runners.
//
// The state is initialized on the UI task runner when the Dart object is
// created. Decoding occurs on the IO task runner. Since it is possible for
// the UI object to be collected independently of the IO task runner work,
// it is not safe for this state to live directly on the MultiFrameCodec.
// Instead, the MultiFrameCodec creates this object when it is constructed,
// shares it with the IO task runner's decoding work, and sets the live_
// member to false when it is destructed.
struct State {
State(std::unique_ptr<SkCodec> codec);
const std::unique_ptr<SkCodec> codec_;
const int frameCount_;
const int repetitionCount_;
// The non-const members and functions below here are only read or written
// to on the IO thread. They are not safe to access or write on the UI
// thread.
int nextFrameIndex_;
// The last decoded frame that's required to decode any subsequent frames.
std::unique_ptr<SkBitmap> lastRequiredFrame_;
// The index of the last decoded required frame.
int lastRequiredFrameIndex_ = -1;
sk_sp<SkImage> GetNextFrameImage(fml::WeakPtr<GrContext> resourceContext);
void GetNextFrameAndInvokeCallback(
std::unique_ptr<PendingCallback> callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner,
fml::WeakPtr<GrContext> resourceContext,
fml::RefPtr<SkiaUnrefQueue> unref_queue, size_t trace_id);
};
// Shared across the UI and IO task runners.
std::shared_ptr<State> state_;
FML_FRIEND_MAKE_REF_COUNTED(MultiFrameCodec);
FML_FRIEND_REF_COUNTED_THREAD_SAFE(MultiFrameCodec);
};
} // namespace uiwidgets

110
engine/src/lib/ui/painting/single_frame_codec.cc


#include "single_frame_codec.h"
#include "frame_info.h"
#include "lib/ui/ui_mono_state.h"
namespace uiwidgets {
SingleFrameCodec::SingleFrameCodec(ImageDecoder::ImageDescriptor descriptor)
: status_(Status::kNew), descriptor_(std::move(descriptor)) {}
SingleFrameCodec::~SingleFrameCodec() = default;
int SingleFrameCodec::frameCount() const { return 1; }
int SingleFrameCodec::repetitionCount() const { return 0; }
const char* SingleFrameCodec::getNextFrame(GetNextFrameCallback callback,
Mono_Handle callback_handle) {
if (!callback || !callback_handle) {
return "Callback must be a function";
}
if (status_ == Status::kComplete) {
cached_frame_->AddRef();
callback(callback_handle, cached_frame_.get());
return nullptr;
}
// This has to be valid because this method is called from Dart.
auto* mono_state = UIMonoState::Current();
pending_callbacks_.emplace_back(PendingCallback{mono_state->GetWeakPtr(), callback, callback_handle});
if (status_ == Status::kInProgress) {
// Another call to getNextFrame is in progress and will invoke the
// pending callbacks when decoding completes.
return nullptr;
}
auto decoder = mono_state->GetImageDecoder();
if (!decoder) {
return "Image decoder not available.";
}
// The SingleFrameCodec must be deleted on the UI thread. Allocate a RefPtr
// on the heap to ensure that the SingleFrameCodec remains alive until the
// decoder callback is invoked on the UI thread. The callback can then
// drop the reference.
fml::RefPtr<SingleFrameCodec>* raw_codec_ref =
new fml::RefPtr<SingleFrameCodec>(this);
decoder->Decode(descriptor_, [raw_codec_ref](auto image) {
std::unique_ptr<fml::RefPtr<SingleFrameCodec>> codec_ref(raw_codec_ref);
fml::RefPtr<SingleFrameCodec> codec(std::move(*codec_ref));
auto state = codec->pending_callbacks_.front().mono_state.lock();
if (!state) {
// This is probably because the isolate has been terminated before the
// image could be decoded.
for (const auto& entry : codec->pending_callbacks_) {
entry.callback(entry.callback_handle, nullptr);
}
codec->pending_callbacks_.clear();
return;
}
MonoState::Scope scope(state.get());
if (image.get()) {
auto canvas_image = fml::MakeRefCounted<CanvasImage>();
canvas_image->set_image(std::move(image));
codec->cached_frame_ = fml::MakeRefCounted<FrameInfo>(
std::move(canvas_image), 0 /* duration */);
}
// The cached frame is now available and should be returned to any future
// callers.
codec->status_ = Status::kComplete;
// Invoke any callbacks that were provided before the frame was decoded.
for (const auto& entry : codec->pending_callbacks_) {
codec->cached_frame_->AddRef();
entry.callback(entry.callback_handle, codec->cached_frame_.get());
}
codec->pending_callbacks_.clear();
});
// The encoded data is no longer needed now that it has been handed off
// to the decoder.
descriptor_.data.reset();
status_ = Status::kInProgress;
return nullptr;
}
size_t SingleFrameCodec::GetAllocationSize() {
const auto& data = descriptor_.data;
const auto data_byte_size = data ? data->size() : 0;
const auto frame_byte_size = (cached_frame_ && cached_frame_->image())
? cached_frame_->image()->GetAllocationSize()
: 0;
return data_byte_size + frame_byte_size + sizeof(this);
}
} // namespace uiwidgets

40
engine/src/lib/ui/painting/single_frame_codec.h


#pragma once
#include "codec.h"
#include "flutter/fml/macros.h"
#include "frame_info.h"
#include "image_decoder.h"
namespace uiwidgets {
class SingleFrameCodec : public Codec {
public:
SingleFrameCodec(ImageDecoder::ImageDescriptor descriptor);
~SingleFrameCodec() override;
// |Codec|
int frameCount() const override;
// |Codec|
int repetitionCount() const override;
// |Codec|
const char* getNextFrame(GetNextFrameCallback callback,
Mono_Handle callback_handle) override;
size_t GetAllocationSize() override;
private:
enum class Status { kNew, kInProgress, kComplete };
Status status_;
ImageDecoder::ImageDescriptor descriptor_;
fml::RefPtr<FrameInfo> cached_frame_;
std::vector<PendingCallback> pending_callbacks_;
FML_FRIEND_MAKE_REF_COUNTED(SingleFrameCodec);
FML_FRIEND_REF_COUNTED_THREAD_SAFE(SingleFrameCodec);
};
} // namespace uiwidgets

119
engine/src/shell/platform/unity/unity_external_texture_gl.cc


#include "unity_external_texture_gl.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglext_angle.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <d3d11.h>
#include "flutter/fml/logging.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContext.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "src/gpu/gl/GrGLDefines.h"
#include "uiwidgets_system.h"
namespace uiwidgets {
UnityExternalTextureGL::UnityExternalTextureGL(
int64_t texture_identifier, void* native_texture_ptr,
UnitySurfaceManager* unity_surface_manager)
: Texture(texture_identifier),
unity_surface_manager_(unity_surface_manager) {
auto* graphics = UIWidgetsSystem::GetInstancePtr()
->GetUnityInterfaces()
->Get<IUnityGraphics>();
FML_DCHECK(graphics->GetRenderer() == kUnityGfxRendererD3D11);
auto* src_d3d11_texture = static_cast<ID3D11Texture2D*>(native_texture_ptr);
IDXGIResource* src_d3d11_resource;
HRESULT hr = src_d3d11_texture->QueryInterface(
__uuidof(IDXGIResource), reinterpret_cast<void**>(&src_d3d11_resource));
FML_CHECK(SUCCEEDED(hr));
HANDLE shared_image_handle;
hr = src_d3d11_resource->GetSharedHandle(&shared_image_handle);
FML_CHECK(SUCCEEDED(hr));
src_d3d11_resource->Release();
IDXGIResource* d3d11_resource;
unity_surface_manager_->GetD3D11Device()->OpenSharedResource(
shared_image_handle, __uuidof(ID3D11Resource),
reinterpret_cast<void**>(&d3d11_resource));
d3d11_resource->QueryInterface(__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(&d3d11_texture_));
d3d11_resource->Release();
const EGLint attribs[] = {EGL_NONE};
egl_image_ =
eglCreateImageKHR(unity_surface_manager_->GetEGLDisplay(), EGL_NO_CONTEXT,
EGL_D3D11_TEXTURE_ANGLE,
static_cast<EGLClientBuffer>(d3d11_texture_), attribs);
gl_texture_ = 0;
}
UnityExternalTextureGL::~UnityExternalTextureGL() {
last_image_ = nullptr;
if (gl_texture_) {
glDeleteTextures(1, &gl_texture_);
gl_texture_ = 0;
}
eglDestroyImageKHR(unity_surface_manager_->GetEGLDisplay(), egl_image_);
d3d11_texture_->Release();
}
// |flutter::Texture|
void UnityExternalTextureGL::Paint(SkCanvas& canvas, const SkRect& bounds,
bool freeze, GrContext* context) {
if (!last_image_) {
if (!gl_texture_) {
glGenTextures(1, &gl_texture_);
glBindTexture(GL_TEXTURE_2D, gl_texture_);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
}
GrGLTextureInfo texture_info;
texture_info.fTarget = GR_GL_TEXTURE_2D;
texture_info.fID = gl_texture_;
texture_info.fFormat = GR_GL_RGBA8;
GrBackendTexture backend_tex = GrBackendTexture(
bounds.width(), bounds.height(), GrMipMapped::kNo, texture_info);
last_image_ = SkImage::MakeFromTexture(
context, backend_tex, kBottomLeft_GrSurfaceOrigin,
kRGBA_8888_SkColorType, kOpaque_SkAlphaType, nullptr);
}
if (last_image_) {
if (bounds != SkRect::Make(last_image_->bounds())) {
canvas.drawImageRect(last_image_, bounds, nullptr);
} else {
canvas.drawImage(last_image_, bounds.x(), bounds.y());
}
}
}
// |flutter::Texture|
void UnityExternalTextureGL::OnGrContextCreated() {}
// |flutter::Texture|
void UnityExternalTextureGL::OnGrContextDestroyed() {}
// |flutter::Texture|
void UnityExternalTextureGL::MarkNewFrameAvailable() {}
// |flutter::Texture|
void UnityExternalTextureGL::OnTextureUnregistered() {}
} // namespace uiwidgets

46
engine/src/shell/platform/unity/unity_external_texture_gl.h


#pragma once
#include "flow/texture.h"
#include "flutter/fml/macros.h"
#include "include/core/SkImage.h"
#include "include/core/SkSize.h"
#include "unity_surface_manager.h"
namespace uiwidgets {
class UnityExternalTextureGL : public Texture {
public:
UnityExternalTextureGL(int64_t texture_identifier, void* native_texture_ptr,
UnitySurfaceManager* unity_surface_manager);
~UnityExternalTextureGL() override;
private:
UnitySurfaceManager* unity_surface_manager_;
bool gr_context_created_ = false;
ID3D11Texture2D* d3d11_texture_;
EGLImage egl_image_;
GLuint gl_texture_;
sk_sp<SkImage> last_image_;
// |flutter::Texture|
void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze,
GrContext* context) 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(UnityExternalTextureGL);
};
} // namespace uiwidgets
正在加载...
取消
保存