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

Commit a812604

Browse files
committed
Wire up support for external OpenGL textures for the embedder.
1 parent b972f75 commit a812604

7 files changed

+283
-8
lines changed

shell/platform/embedder/BUILD.gn

+3
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

+97-5
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,65 @@ FlutterResult FlutterEngineRun(size_t version,
356356
return std::make_unique<shell::Rasterizer>(shell.GetTaskRunners());
357357
};
358358

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

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

shell/platform/embedder/embedder.h

+48
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

+31-2
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

+12-1
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);
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
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)