Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Wire up support for external OpenGL textures for the embedder. #7087

Merged
merged 3 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder.cc
FILE: ../../../flutter/shell/platform/embedder/embedder.h
FILE: ../../../flutter/shell/platform/embedder/embedder_engine.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_engine.h
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.h
FILE: ../../../flutter/shell/platform/embedder/embedder_include.c
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ source_set("embedder") {
"embedder.h",
"embedder_engine.cc",
"embedder_engine.h",
"embedder_external_texture_gl.cc",
"embedder_external_texture_gl.h",
"embedder_include.c",
"embedder_surface.cc",
"embedder_surface.h",
Expand All @@ -33,6 +35,7 @@ source_set("embedder") {
":embedder_gpu_configuration",
"$flutter_root/assets",
"$flutter_root/common",
"$flutter_root/flow",
"$flutter_root/fml",
"$flutter_root/lib/snapshot",
"$flutter_root/shell/common",
Expand Down
102 changes: 97 additions & 5 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,65 @@ FlutterResult FlutterEngineRun(size_t version,
return std::make_unique<shell::Rasterizer>(shell.GetTaskRunners());
};

// TODO(chinmaygarde): This is the wrong spot for this. It belongs in the
// platform view jump table.
shell::EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback;
if (config->type == kOpenGL) {
const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
nullptr) != nullptr) {
external_texture_callback =
[ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
int64_t texture_identifier, GrContext* context,
const SkISize& size) -> sk_sp<SkImage> {
FlutterOpenGLTexture texture = {};

if (!ptr(user_data, texture_identifier, size.width(), size.height(),
&texture)) {
return nullptr;
}

GrGLTextureInfo gr_texture_info = {texture.target, texture.name,
texture.format};

GrBackendTexture gr_backend_texture(size.width(), size.height(),
GrMipMapped::kNo, gr_texture_info);
SkImage::TextureReleaseProc release_proc = texture.destruction_callback;
auto image = SkImage::MakeFromTexture(
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 image;
};
}
}

// Step 1: Create the engine.
auto embedder_engine =
std::make_unique<shell::EmbedderEngine>(std::move(thread_host), //
std::move(task_runners), //
settings, //
on_create_platform_view, //
on_create_rasterizer //
std::make_unique<shell::EmbedderEngine>(std::move(thread_host), //
std::move(task_runners), //
settings, //
on_create_platform_view, //
on_create_rasterizer, //
external_texture_callback //
);

if (!embedder_engine->IsValid()) {
Expand Down Expand Up @@ -524,3 +576,43 @@ FlutterResult __FlutterEngineFlushPendingTasksNow() {
fml::MessageLoop::GetCurrent().RunExpiredTasksNow();
return kSuccess;
}

FlutterResult FlutterEngineRegisterExternalTexture(FlutterEngine engine,
int64_t texture_identifier) {
if (engine == nullptr || texture_identifier == 0) {
return kInvalidArguments;
}
if (!reinterpret_cast<shell::EmbedderEngine*>(engine)->RegisterTexture(
texture_identifier)) {
return kInternalInconsistency;
}
return kSuccess;
}

FlutterResult FlutterEngineUnregisterExternalTexture(
FlutterEngine engine,
int64_t texture_identifier) {
if (engine == nullptr || texture_identifier == 0) {
return kInvalidArguments;
}

if (!reinterpret_cast<shell::EmbedderEngine*>(engine)->UnregisterTexture(
texture_identifier)) {
return kInternalInconsistency;
}

return kSuccess;
}

FlutterResult FlutterEngineMarkExternalTextureFrameAvailable(
FlutterEngine engine,
int64_t texture_identifier) {
if (engine == nullptr || texture_identifier == 0) {
return kInvalidArguments;
}
if (!reinterpret_cast<shell::EmbedderEngine*>(engine)
->MarkTextureFrameAvailable(texture_identifier)) {
return kInternalInconsistency;
}
return kSuccess;
}
48 changes: 48 additions & 0 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ typedef enum {
kSuccess = 0,
kInvalidLibraryVersion,
kInvalidArguments,
kInternalInconsistency,
} FlutterResult;

typedef enum {
Expand Down Expand Up @@ -53,6 +54,22 @@ typedef struct {
double pers2;
} FlutterTransformation;

typedef void (*VoidCallback)(void* /* user data */);

typedef struct {
// Target texture of the active texture unit (example GL_TEXTURE_2D).
uint32_t target;
// The name of the texture.
uint32_t name;
// The texture format (example GL_RGBA8).
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;
} FlutterOpenGLTexture;

typedef bool (*BoolCallback)(void* /* user data */);
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
typedef uint32_t (*UIntCallback)(void* /* user data */);
Expand All @@ -61,6 +78,11 @@ typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,
size_t /* row bytes */,
size_t /* height */);
typedef void* (*ProcResolver)(void* /* user data */, const char* /* name */);
typedef bool (*TextureFrameCallback)(void* /* user data */,
int64_t /* texture identifier */,
size_t /* width */,
size_t /* height */,
FlutterOpenGLTexture* /* texture out */);

typedef struct {
// The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Expand All @@ -79,6 +101,11 @@ typedef struct {
// operations. This callback is optional.
TransformationCallback surface_transformation;
ProcResolver gl_proc_resolver;
// 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 suppplied to the engine for subsequent
// composition.
TextureFrameCallback gl_external_texture_frame_callback;
} FlutterOpenGLRendererConfig;

typedef struct {
Expand Down Expand Up @@ -220,6 +247,27 @@ FlutterResult FlutterEngineSendPlatformMessageResponse(
FLUTTER_EXPORT
FlutterResult __FlutterEngineFlushPendingTasksNow();

// Register an external texture with a unique (per engine) identifier. Only
// rendering backends that support external textures accept external texture
// registrations. After the external texture is registered, the application can
// mark that a frame is available by calling
// |FlutterEngineMarkExternalTextureFrameAvailable|.
FLUTTER_EXPORT
FlutterResult FlutterEngineRegisterExternalTexture(FlutterEngine engine,
int64_t texture_identifier);

// Unregister a previous texture registration.
FLUTTER_EXPORT
FlutterResult FlutterEngineUnregisterExternalTexture(
FlutterEngine engine,
int64_t texture_identifier);

// Mark that a new texture frame is available for a given texture identifier.
FLUTTER_EXPORT
FlutterResult FlutterEngineMarkExternalTextureFrameAvailable(
FlutterEngine engine,
int64_t texture_identifier);

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
33 changes: 31 additions & 2 deletions shell/platform/embedder/embedder_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ EmbedderEngine::EmbedderEngine(
blink::TaskRunners task_runners,
blink::Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer)
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback)
: thread_host_(std::move(thread_host)),
shell_(Shell::Create(std::move(task_runners),
std::move(settings),
on_create_platform_view,
on_create_rasterizer)) {
on_create_rasterizer)),
external_texture_callback_(external_texture_callback) {
is_valid_ = shell_ != nullptr;
}

Expand Down Expand Up @@ -112,4 +115,30 @@ bool EmbedderEngine::SendPlatformMessage(
return true;
}

bool EmbedderEngine::RegisterTexture(int64_t texture) {
if (!IsValid() || !external_texture_callback_) {
return false;
}
shell_->GetPlatformView()->RegisterTexture(
std::make_unique<EmbedderExternalTextureGL>(texture,
external_texture_callback_));
return true;
}

bool EmbedderEngine::UnregisterTexture(int64_t texture) {
if (!IsValid() || !external_texture_callback_) {
return false;
}
shell_->GetPlatformView()->UnregisterTexture(texture);
return true;
}

bool EmbedderEngine::MarkTextureFrameAvailable(int64_t texture) {
if (!IsValid() || !external_texture_callback_) {
return false;
}
shell_->GetPlatformView()->MarkTextureFrameAvailable(texture);
return true;
}

} // namespace shell
13 changes: 12 additions & 1 deletion shell/platform/embedder/embedder_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/embedder_external_texture_gl.h"

namespace shell {

Expand All @@ -22,7 +23,9 @@ class EmbedderEngine {
blink::TaskRunners task_runners,
blink::Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer);
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback);

~EmbedderEngine();

Expand All @@ -41,9 +44,17 @@ class EmbedderEngine {

bool SendPlatformMessage(fml::RefPtr<blink::PlatformMessage> message);

bool RegisterTexture(int64_t texture);

bool UnregisterTexture(int64_t texture);

bool MarkTextureFrameAvailable(int64_t texture);

private:
const ThreadHost thread_host_;
std::unique_ptr<Shell> shell_;
const EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback_;
bool is_valid_ = false;

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

#include "flutter/fml/logging.h"

namespace shell {

EmbedderExternalTextureGL::EmbedderExternalTextureGL(
int64_t texture_identifier,
ExternalTextureCallback callback)
: Texture(texture_identifier), external_texture_callback_(callback) {
FML_DCHECK(external_texture_callback_);
}

EmbedderExternalTextureGL::~EmbedderExternalTextureGL() = default;

// |flow::Texture|
void EmbedderExternalTextureGL::Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze) {
if (auto image = external_texture_callback_(
Id(), //
canvas.getGrContext(), //
SkISize::Make(bounds.width(), bounds.height()) //
)) {
last_image_ = image;
}

if (last_image_) {
canvas.drawImage(last_image_, bounds.x(), bounds.y());
}
}

// |flow::Texture|
void EmbedderExternalTextureGL::OnGrContextCreated() {}

// |flow::Texture|
void EmbedderExternalTextureGL::OnGrContextDestroyed() {}

// |flow::Texture|
void EmbedderExternalTextureGL::MarkNewFrameAvailable() {}

} // namespace shell
Loading