Skip to content

Commit

Permalink
Wire up support for external OpenGL textures for the embedder.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde committed Jan 9, 2019
1 parent b972f75 commit a812604
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 8 deletions.
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 2018 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
46 changes: 46 additions & 0 deletions shell/platform/embedder/embedder_external_texture_gl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2018 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_GL_H_
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_

#include "flutter/flow/texture.h"
#include "flutter/fml/macros.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSize.h"

namespace shell {

class EmbedderExternalTextureGL : public flow::Texture {
public:
using ExternalTextureCallback = std::function<
sk_sp<SkImage>(int64_t texture_identifier, GrContext*, const SkISize&)>;

EmbedderExternalTextureGL(int64_t texture_identifier,
ExternalTextureCallback callback);

~EmbedderExternalTextureGL();

private:
ExternalTextureCallback external_texture_callback_;
sk_sp<SkImage> last_image_;

// |flow::Texture|
void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) override;

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

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

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

FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureGL);
};

} // namespace shell

#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_

0 comments on commit a812604

Please sign in to comment.