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

Commit 182aece

Browse files
committed
Wire up support for external OpenGL textures for the embedder.
1 parent 7375a0f commit 182aece

7 files changed

+283
-8
lines changed

shell/platform/embedder/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ source_set("embedder") {
1818
"embedder.h",
1919
"embedder_engine.cc",
2020
"embedder_engine.h",
21+
"embedder_external_texture_gl.cc",
22+
"embedder_external_texture_gl.h",
2123
"embedder_include.c",
2224
"embedder_surface.cc",
2325
"embedder_surface.h",
@@ -33,6 +35,7 @@ source_set("embedder") {
3335
":embedder_gpu_configuration",
3436
"$flutter_root/assets",
3537
"$flutter_root/common",
38+
"$flutter_root/flow",
3639
"$flutter_root/fml",
3740
"$flutter_root/lib/snapshot",
3841
"$flutter_root/shell/common",

shell/platform/embedder/embedder.cc

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,13 +362,65 @@ FlutterResult FlutterEngineRun(size_t version,
362362
return std::make_unique<shell::Rasterizer>(shell.GetTaskRunners());
363363
};
364364

365+
// TODO(chinmaygarde): This is the wrong spot for this. It belong in the
366+
// platform view jump table.
367+
shell::EmbedderExternalTextureGL::ExternalTextureCallback
368+
external_texture_callback;
369+
if (config->type == kOpenGL) {
370+
const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
371+
if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
372+
nullptr) != nullptr) {
373+
external_texture_callback =
374+
[ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
375+
int64_t texture_identifier, GrContext* context,
376+
const SkISize& size) -> sk_sp<SkImage> {
377+
FlutterOpenGLTexture texture = {};
378+
379+
if (!ptr(user_data, texture_identifier, size.width(), size.height(),
380+
&texture)) {
381+
return nullptr;
382+
}
383+
384+
GrGLTextureInfo gr_texture_info = {texture.target, texture.name,
385+
texture.format};
386+
387+
GrBackendTexture gr_backend_texture(size.width(), size.height(),
388+
GrMipMapped::kNo, gr_texture_info);
389+
SkImage::TextureReleaseProc release_proc = texture.destruction_callback;
390+
auto image = SkImage::MakeFromTexture(
391+
context, // context
392+
gr_backend_texture, // texture handle
393+
kTopLeft_GrSurfaceOrigin, // origin
394+
kRGBA_8888_SkColorType, // color type
395+
kPremul_SkAlphaType, // alpha type
396+
nullptr, // colorspace
397+
release_proc, // texture release proc
398+
texture.user_data // texture release context
399+
);
400+
401+
if (!image) {
402+
// In case Skia reject the image, call the release proc so that
403+
// embedders can perform collection of intermediates.
404+
if (release_proc) {
405+
release_proc(texture.user_data);
406+
}
407+
FML_LOG(ERROR) << "Could not create external texture.";
408+
return nullptr;
409+
}
410+
411+
return image;
412+
};
413+
}
414+
}
415+
365416
// Step 1: Create the engine.
366417
auto embedder_engine =
367-
std::make_unique<shell::EmbedderEngine>(std::move(thread_host), //
368-
std::move(task_runners), //
369-
settings, //
370-
on_create_platform_view, //
371-
on_create_rasterizer //
418+
std::make_unique<shell::EmbedderEngine>(std::move(thread_host), //
419+
std::move(task_runners), //
420+
settings, //
421+
on_create_platform_view, //
422+
on_create_rasterizer, //
423+
external_texture_callback //
372424
);
373425

374426
if (!embedder_engine->IsValid()) {
@@ -527,3 +579,43 @@ FlutterResult __FlutterEngineFlushPendingTasksNow() {
527579
fml::MessageLoop::GetCurrent().RunExpiredTasksNow();
528580
return kSuccess;
529581
}
582+
583+
FlutterResult FlutterEngineRegisterExternalTexture(FlutterEngine engine,
584+
int64_t texture_identifier) {
585+
if (engine == nullptr || texture_identifier == 0) {
586+
return kInvalidArguments;
587+
}
588+
if (!reinterpret_cast<shell::EmbedderEngine*>(engine)->RegisterTexture(
589+
texture_identifier)) {
590+
return kInternalInconsistency;
591+
}
592+
return kSuccess;
593+
}
594+
595+
FlutterResult FlutterEngineUnregisterExternalTexture(
596+
FlutterEngine engine,
597+
int64_t texture_identifier) {
598+
if (engine == nullptr || texture_identifier == 0) {
599+
return kInvalidArguments;
600+
}
601+
602+
if (!reinterpret_cast<shell::EmbedderEngine*>(engine)->UnregisterTexture(
603+
texture_identifier)) {
604+
return kInternalInconsistency;
605+
}
606+
607+
return kSuccess;
608+
}
609+
610+
FlutterResult FlutterEngineMarkExternalTextureFrameAvailable(
611+
FlutterEngine engine,
612+
int64_t texture_identifier) {
613+
if (engine == nullptr || texture_identifier == 0) {
614+
return kInvalidArguments;
615+
}
616+
if (!reinterpret_cast<shell::EmbedderEngine*>(engine)
617+
->MarkTextureFrameAvailable(texture_identifier)) {
618+
return kInternalInconsistency;
619+
}
620+
return kSuccess;
621+
}

shell/platform/embedder/embedder.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ typedef enum {
2323
kSuccess = 0,
2424
kInvalidLibraryVersion,
2525
kInvalidArguments,
26+
kInternalInconsistency,
2627
} FlutterResult;
2728

2829
typedef enum {
@@ -53,6 +54,22 @@ typedef struct {
5354
double pers2;
5455
} FlutterTransformation;
5556

57+
typedef void (*VoidCallback)(void* /* user data */);
58+
59+
typedef struct {
60+
// Target texture of the active texture unit (example GL_TEXTURE_2D).
61+
uint32_t target;
62+
// The name of the texture.
63+
uint32_t name;
64+
// The texture format (example GL_RGBA8).
65+
uint32_t format;
66+
// User data to be returned on the invocation of the destruction callback.
67+
void* user_data;
68+
// Callback invoked (on an engine managed thread) that asks the embedder to
69+
// collect the texture.
70+
VoidCallback destruction_callback;
71+
} FlutterOpenGLTexture;
72+
5673
typedef bool (*BoolCallback)(void* /* user data */);
5774
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
5875
typedef uint32_t (*UIntCallback)(void* /* user data */);
@@ -61,6 +78,11 @@ typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,
6178
size_t /* row bytes */,
6279
size_t /* height */);
6380
typedef void* (*ProcResolver)(void* /* user data */, const char* /* name */);
81+
typedef bool (*TextureFrameCallback)(void* /* user data */,
82+
int64_t /* texture identifier */,
83+
size_t /* width */,
84+
size_t /* height */,
85+
FlutterOpenGLTexture* /* texture out */);
6486

6587
typedef struct {
6688
// The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
@@ -79,6 +101,11 @@ typedef struct {
79101
// operations. This callback is optional.
80102
TransformationCallback surface_transformation;
81103
ProcResolver gl_proc_resolver;
104+
// When the embedder specifies that a texture has a frame available, the
105+
// engine will call this method (on an internal engine managed thread) so that
106+
// external texture details can be suppplied to the engine for subsequent
107+
// composition.
108+
TextureFrameCallback gl_external_texture_frame_callback;
82109
} FlutterOpenGLRendererConfig;
83110

84111
typedef struct {
@@ -220,6 +247,27 @@ FlutterResult FlutterEngineSendPlatformMessageResponse(
220247
FLUTTER_EXPORT
221248
FlutterResult __FlutterEngineFlushPendingTasksNow();
222249

250+
// Register an external texture with a unique (per engine) identifier. Only
251+
// rendering backends that support external textures accept external texture
252+
// registrations. After the external texture is registered, the application can
253+
// mark that a frame is available by calling
254+
// |FlutterEngineMarkExternalTextureFrameAvailable|.
255+
FLUTTER_EXPORT
256+
FlutterResult FlutterEngineRegisterExternalTexture(FlutterEngine engine,
257+
int64_t texture_identifier);
258+
259+
// Unregister a previous texture registration.
260+
FLUTTER_EXPORT
261+
FlutterResult FlutterEngineUnregisterExternalTexture(
262+
FlutterEngine engine,
263+
int64_t texture_identifier);
264+
265+
// Mark that a new texture frame is available for a given texture identifier.
266+
FLUTTER_EXPORT
267+
FlutterResult FlutterEngineMarkExternalTextureFrameAvailable(
268+
FlutterEngine engine,
269+
int64_t texture_identifier);
270+
223271
#if defined(__cplusplus)
224272
} // extern "C"
225273
#endif

shell/platform/embedder/embedder_engine.cc

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ EmbedderEngine::EmbedderEngine(
1313
blink::TaskRunners task_runners,
1414
blink::Settings settings,
1515
Shell::CreateCallback<PlatformView> on_create_platform_view,
16-
Shell::CreateCallback<Rasterizer> on_create_rasterizer)
16+
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
17+
EmbedderExternalTextureGL::ExternalTextureCallback
18+
external_texture_callback)
1719
: thread_host_(std::move(thread_host)),
1820
shell_(Shell::Create(std::move(task_runners),
1921
std::move(settings),
2022
on_create_platform_view,
21-
on_create_rasterizer)) {
23+
on_create_rasterizer)),
24+
external_texture_callback_(external_texture_callback) {
2225
is_valid_ = shell_ != nullptr;
2326
}
2427

@@ -112,4 +115,30 @@ bool EmbedderEngine::SendPlatformMessage(
112115
return true;
113116
}
114117

118+
bool EmbedderEngine::RegisterTexture(int64_t texture) {
119+
if (!IsValid() || !external_texture_callback_) {
120+
return false;
121+
}
122+
shell_->GetPlatformView()->RegisterTexture(
123+
std::make_unique<EmbedderExternalTextureGL>(texture,
124+
external_texture_callback_));
125+
return true;
126+
}
127+
128+
bool EmbedderEngine::UnregisterTexture(int64_t texture) {
129+
if (!IsValid() || !external_texture_callback_) {
130+
return false;
131+
}
132+
shell_->GetPlatformView()->UnregisterTexture(texture);
133+
return true;
134+
}
135+
136+
bool EmbedderEngine::MarkTextureFrameAvailable(int64_t texture) {
137+
if (!IsValid() || !external_texture_callback_) {
138+
return false;
139+
}
140+
shell_->GetPlatformView()->MarkTextureFrameAvailable(texture);
141+
return true;
142+
}
143+
115144
} // namespace shell

shell/platform/embedder/embedder_engine.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "flutter/shell/common/shell.h"
1212
#include "flutter/shell/common/thread_host.h"
1313
#include "flutter/shell/platform/embedder/embedder.h"
14+
#include "flutter/shell/platform/embedder/embedder_external_texture_gl.h"
1415

1516
namespace shell {
1617

@@ -22,7 +23,9 @@ class EmbedderEngine {
2223
blink::TaskRunners task_runners,
2324
blink::Settings settings,
2425
Shell::CreateCallback<PlatformView> on_create_platform_view,
25-
Shell::CreateCallback<Rasterizer> on_create_rasterizer);
26+
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
27+
EmbedderExternalTextureGL::ExternalTextureCallback
28+
external_texture_callback);
2629

2730
~EmbedderEngine();
2831

@@ -41,9 +44,17 @@ class EmbedderEngine {
4144

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

47+
bool RegisterTexture(int64_t texture);
48+
49+
bool UnregisterTexture(int64_t texture);
50+
51+
bool MarkTextureFrameAvailable(int64_t texture);
52+
4453
private:
4554
const ThreadHost thread_host_;
4655
std::unique_ptr<Shell> shell_;
56+
const EmbedderExternalTextureGL::ExternalTextureCallback
57+
external_texture_callback_;
4758
bool is_valid_ = false;
4859

4960
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderEngine);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2018 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/platform/embedder/embedder_external_texture_gl.h"
6+
7+
#include "flutter/fml/logging.h"
8+
9+
namespace shell {
10+
11+
EmbedderExternalTextureGL::EmbedderExternalTextureGL(
12+
int64_t texture_identifier,
13+
ExternalTextureCallback callback)
14+
: Texture(texture_identifier), external_texture_callback_(callback) {
15+
FML_DCHECK(external_texture_callback_);
16+
}
17+
18+
EmbedderExternalTextureGL::~EmbedderExternalTextureGL() = default;
19+
20+
// |flow::Texture|
21+
void EmbedderExternalTextureGL::Paint(SkCanvas& canvas,
22+
const SkRect& bounds,
23+
bool freeze) {
24+
if (auto image = external_texture_callback_(
25+
Id(), //
26+
canvas.getGrContext(), //
27+
SkISize::Make(bounds.width(), bounds.height()) //
28+
)) {
29+
last_image_ = image;
30+
}
31+
32+
if (last_image_) {
33+
canvas.drawImage(last_image_, bounds.x(), bounds.y());
34+
}
35+
}
36+
37+
// |flow::Texture|
38+
void EmbedderExternalTextureGL::OnGrContextCreated() {}
39+
40+
// |flow::Texture|
41+
void EmbedderExternalTextureGL::OnGrContextDestroyed() {}
42+
43+
// |flow::Texture|
44+
void EmbedderExternalTextureGL::MarkNewFrameAvailable() {}
45+
46+
} // namespace shell
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2018 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_
6+
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_
7+
8+
#include "flutter/flow/texture.h"
9+
#include "flutter/fml/macros.h"
10+
#include "third_party/skia/include/core/SkImage.h"
11+
#include "third_party/skia/include/core/SkSize.h"
12+
13+
namespace shell {
14+
15+
class EmbedderExternalTextureGL : public flow::Texture {
16+
public:
17+
using ExternalTextureCallback = std::function<
18+
sk_sp<SkImage>(int64_t texture_identifier, GrContext*, const SkISize&)>;
19+
20+
EmbedderExternalTextureGL(int64_t texture_identifier,
21+
ExternalTextureCallback callback);
22+
23+
~EmbedderExternalTextureGL();
24+
25+
private:
26+
ExternalTextureCallback external_texture_callback_;
27+
sk_sp<SkImage> last_image_;
28+
29+
// |flow::Texture|
30+
void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze) override;
31+
32+
// |flow::Texture|
33+
void OnGrContextCreated() override;
34+
35+
// |flow::Texture|
36+
void OnGrContextDestroyed() override;
37+
38+
// |flow::Texture|
39+
void MarkNewFrameAvailable() override;
40+
41+
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureGL);
42+
};
43+
44+
} // namespace shell
45+
46+
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_

0 commit comments

Comments
 (0)