Skip to content

Commit 3ae82b3

Browse files
authored
[Tizen] Re-implemented render external texture gl for impeller to avoid change FlutterOpenGLTexture and use deprecated api (#23)
We have supported render external texture gl for Impeller flutter-tizen/engine#368 But this PR has two issues: 1. It modify FlutterOpenGLTexture, it added additional variables, not a good design. ```C++ /// The pixel data buffer. const uint8_t* buffer; /// The size of pixel buffer. size_t buffer_size; /// Callback invoked that the gpu surface texture start binding. BoolCallback bind_callback; /// The type of the texture. FlutterGLImpellerTextureType impeller_texture_type; ``` 2. It uses Deprecated API ```C++ // Deprecated: use BlitPass::AddCopy instead. [[nodiscard]] bool SetContents(const uint8_t* contents, size_t length, size_t slice = 0, bool is_opaque = false); ``` So I tried to revert offical PR to render external gl for impeller flutter/engine#56277 But this PR doesn't work on Tizen platform, I think This PR may not have been verified. To avoid change FlutterOpenGLTexture and use deprecated api, so I re-implemented render external texture gl for impeller based on this offical PR. Fix flutter-tizen/embedder#131
1 parent 5841d41 commit 3ae82b3

3 files changed

Lines changed: 199 additions & 89 deletions

File tree

engine/src/flutter/shell/platform/embedder/embedder.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,6 @@ typedef struct {
405405
} FlutterTransformation;
406406

407407
typedef void (*VoidCallback)(void* /* user data */);
408-
typedef bool (*BoolCallback)(void* /* user data */);
409408

410409
typedef enum {
411410
/// Specifies an OpenGL texture target type. Textures are specified using
@@ -513,13 +512,6 @@ typedef struct {
513512
uint32_t name;
514513
/// The texture format (example GL_RGBA8).
515514
uint32_t format;
516-
/// The pixel data buffer.
517-
const uint8_t* buffer;
518-
/// The size of pixel buffer.
519-
size_t buffer_size;
520-
/// Callback invoked that the gpu surface texture start binding.
521-
BoolCallback bind_callback;
522-
523515
/// User data to be returned on the invocation of the destruction callback.
524516
void* user_data;
525517
/// Callback invoked (on an engine managed thread) that asks the embedder to
@@ -613,6 +605,7 @@ typedef struct {
613605
uint32_t format;
614606
} FlutterOpenGLSurface;
615607

608+
typedef bool (*BoolCallback)(void* /* user data */);
616609
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
617610
typedef uint32_t (*UIntCallback)(void* /* user data */);
618611
typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,

engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc

Lines changed: 155 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,88 @@
2727

2828
namespace flutter {
2929

30+
std::optional<TextureLRU::Data> TextureLRU::FindTexture(
31+
std::optional<GLuint> key) {
32+
if (!key.has_value()) {
33+
return std::nullopt;
34+
}
35+
auto key_value = key.value();
36+
for (size_t i = 0u; i < kTextureMaxSize; i++) {
37+
if (textures_[i].key == key_value) {
38+
UpdateTexture(Data{.key = key_value,
39+
.texture = textures_[i].texture,
40+
.width = textures_[i].width,
41+
.height = textures_[i].height});
42+
return std::make_optional(textures_[i]);
43+
}
44+
}
45+
return std::nullopt;
46+
}
47+
48+
void TextureLRU::UpdateTexture(Data data) {
49+
if (textures_[0].key == data.key) {
50+
textures_[0] = data;
51+
return;
52+
}
53+
size_t i = 1u;
54+
for (; i < kTextureMaxSize; i++) {
55+
if (textures_[i].key == data.key) {
56+
break;
57+
}
58+
}
59+
60+
if (i == kTextureMaxSize) {
61+
return;
62+
}
63+
64+
for (auto j = i; j > 0; j--) {
65+
textures_[j] = textures_[j - 1];
66+
}
67+
textures_[0] = data;
68+
}
69+
70+
GLuint TextureLRU::AddTexture(Data data) {
71+
GLuint lru_key = textures_[kTextureMaxSize - 1].key;
72+
bool updated_image = false;
73+
for (size_t i = 0u; i < kTextureMaxSize; i++) {
74+
if (textures_[i].key == lru_key) {
75+
updated_image = true;
76+
textures_[i] = data;
77+
break;
78+
}
79+
}
80+
if (!updated_image) {
81+
textures_[0] = data;
82+
}
83+
UpdateTexture(data);
84+
return lru_key;
85+
}
86+
87+
void TextureLRU::Clear() {
88+
for (size_t i = 0u; i < kTextureMaxSize; i++) {
89+
textures_[i] = Data{.key = 0u, .texture = nullptr};
90+
}
91+
}
92+
93+
void TextureLRU::RemoveTexture(GLuint key) {
94+
size_t i = 0u;
95+
for (; i < kTextureMaxSize; i++) {
96+
if (textures_[i].key == key) {
97+
break;
98+
}
99+
}
100+
101+
if (i == kTextureMaxSize) {
102+
return;
103+
}
104+
105+
for (; i < kTextureMaxSize - 1; i++) {
106+
textures_[i] = textures_[i + 1];
107+
}
108+
109+
textures_[kTextureMaxSize - 1] = Data{.key = 0u, .texture = nullptr};
110+
}
111+
30112
EmbedderExternalTextureGL::EmbedderExternalTextureGL(
31113
int64_t texture_identifier,
32114
const ExternalTextureCallback& callback)
@@ -129,46 +211,27 @@ sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureSkia(
129211
return DlImage::Make(std::move(image));
130212
}
131213

132-
sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureImpeller(
133-
int64_t texture_id,
134-
impeller::AiksContext* aiks_context,
135-
const SkISize& size) {
136-
std::unique_ptr<FlutterOpenGLTexture> texture =
137-
external_texture_callback_(texture_id, size.width(), size.height());
138-
139-
if (!texture) {
140-
return nullptr;
141-
}
142-
143-
if (texture->bind_callback != nullptr) {
144-
return ResolveTextureImpellerSurface(aiks_context, std::move(texture));
145-
} else {
146-
return ResolveTextureImpellerPixelbuffer(aiks_context, std::move(texture));
147-
}
148-
}
149-
150-
sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureImpellerPixelbuffer(
214+
std::shared_ptr<impeller::TextureGLES>
215+
EmbedderExternalTextureGL::CreateTextureGLES(
151216
impeller::AiksContext* aiks_context,
152-
std::unique_ptr<FlutterOpenGLTexture> texture) {
217+
FlutterOpenGLTexture* texture) {
153218
impeller::TextureDescriptor desc;
154219
desc.size = impeller::ISize(texture->width, texture->height);
155-
desc.type = impeller::TextureType::kTexture2D;
156220
desc.storage_mode = impeller::StorageMode::kDevicePrivate;
157221
desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
222+
if (texture->target == GL_TEXTURE_EXTERNAL_OES) {
223+
desc.type = impeller::TextureType::kTextureExternalOES;
224+
} else {
225+
desc.type = impeller::TextureType::kTexture2D;
226+
}
158227
impeller::ContextGLES& context =
159228
impeller::ContextGLES::Cast(*aiks_context->GetContext());
160-
std::shared_ptr<impeller::TextureGLES> image =
161-
std::make_shared<impeller::TextureGLES>(context.GetReactor(), desc);
229+
impeller::HandleGLES handle = context.GetReactor()->CreateHandle(
230+
impeller::HandleType::kTexture, texture->name);
162231

163-
image->MarkContentsInitialized();
164-
if (!image->SetContents(texture->buffer, texture->buffer_size)) {
165-
if (texture->destruction_callback) {
166-
texture->destruction_callback(texture->user_data);
167-
}
168-
return nullptr;
169-
}
170-
171-
if (!image) {
232+
auto gles_texture =
233+
impeller::TextureGLES::WrapTexture(context.GetReactor(), desc, handle);
234+
if (!gles_texture) {
172235
// In case Skia rejects the image, call the release proc so that
173236
// embedders can perform collection of intermediates.
174237
if (texture->destruction_callback) {
@@ -178,58 +241,74 @@ sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureImpellerPixelbuffer(
178241
return nullptr;
179242
}
180243

181-
if (texture->destruction_callback) {
182-
texture->destruction_callback(texture->user_data);
183-
}
244+
gles_texture->SetCoordinateSystem(
245+
impeller::TextureCoordinateSystem::kUploadFromHost);
184246

185-
return impeller::DlImageImpeller::Make(image);
247+
if (texture->destruction_callback &&
248+
!context.GetReactor()->RegisterCleanupCallback(
249+
handle,
250+
[callback = texture->destruction_callback,
251+
user_data = texture->user_data]() { callback(user_data); })) {
252+
FML_LOG(ERROR) << "Could not register destruction callback";
253+
return nullptr;
254+
}
255+
return gles_texture;
186256
}
187257

188-
sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureImpellerSurface(
258+
sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureImpeller(
259+
int64_t texture_id,
189260
impeller::AiksContext* aiks_context,
190-
std::unique_ptr<FlutterOpenGLTexture> texture) {
191-
impeller::TextureDescriptor desc;
192-
desc.size = impeller::ISize(texture->width, texture->height);
193-
desc.storage_mode = impeller::StorageMode::kDevicePrivate;
194-
desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
195-
desc.type = impeller::TextureType::kTextureExternalOES;
196-
impeller::ContextGLES& context =
197-
impeller::ContextGLES::Cast(*aiks_context->GetContext());
198-
std::shared_ptr<impeller::TextureGLES> image =
199-
std::make_shared<impeller::TextureGLES>(context.GetReactor(), desc);
200-
image->MarkContentsInitialized();
201-
image->SetCoordinateSystem(
202-
impeller::TextureCoordinateSystem::kUploadFromHost);
203-
if (!image->Bind()) {
204-
if (texture->destruction_callback) {
205-
texture->destruction_callback(texture->user_data);
206-
}
207-
FML_LOG(ERROR) << "Could not bind texture";
208-
return nullptr;
209-
}
261+
const SkISize& size) {
262+
std::unique_ptr<FlutterOpenGLTexture> texture =
263+
external_texture_callback_(texture_id, size.width(), size.height());
210264

211-
if (!image) {
212-
// In case Skia rejects the image, call the release proc so that
213-
// embedders can perform collection of intermediates.
214-
if (texture->destruction_callback) {
215-
texture->destruction_callback(texture->user_data);
216-
}
217-
FML_LOG(ERROR) << "Could not create external texture";
265+
if (!texture) {
218266
return nullptr;
219267
}
220268

221-
if (!texture->bind_callback(texture->user_data)) {
222-
if (texture->destruction_callback) {
223-
texture->destruction_callback(texture->user_data);
224-
}
225-
return nullptr;
226-
}
269+
std::optional<TextureLRU::Data> texture_data =
270+
texture_lru_.FindTexture(texture->name);
271+
272+
bool size_change = false;
227273

228-
if (texture->destruction_callback) {
229-
texture->destruction_callback(texture->user_data);
274+
if (texture_data.has_value() &&
275+
(texture_data.value().width != texture->width ||
276+
texture_data.value().height != texture->height)) {
277+
size_change = true;
230278
}
231279

232-
return impeller::DlImageImpeller::Make(image);
280+
if (texture_data.has_value() && !size_change) {
281+
return impeller::DlImageImpeller::Make(texture_data.value().texture);
282+
} else if (texture_data.has_value() && size_change) {
283+
std::shared_ptr<impeller::TextureGLES> old_gles_texture =
284+
texture_data.value().texture;
285+
old_gles_texture->Leak();
286+
std::shared_ptr<impeller::TextureGLES> new_gles_texture =
287+
CreateTextureGLES(aiks_context, texture.get());
288+
if (new_gles_texture) {
289+
texture_lru_.UpdateTexture(TextureLRU::Data{.key = texture->name,
290+
.texture = new_gles_texture,
291+
.width = texture->width,
292+
.height = texture->height});
293+
294+
return impeller::DlImageImpeller::Make(new_gles_texture);
295+
} else {
296+
texture_lru_.RemoveTexture(texture->name);
297+
return nullptr;
298+
}
299+
} else {
300+
std::shared_ptr<impeller::TextureGLES> new_gles_texture =
301+
CreateTextureGLES(aiks_context, texture.get());
302+
if (new_gles_texture) {
303+
texture_lru_.AddTexture(TextureLRU::Data{.key = texture->name,
304+
.texture = new_gles_texture,
305+
.width = texture->width,
306+
.height = texture->height});
307+
return impeller::DlImageImpeller::Make(new_gles_texture);
308+
} else {
309+
return nullptr;
310+
}
311+
}
233312
}
234313

235314
// |flutter::Texture|
@@ -244,6 +323,8 @@ void EmbedderExternalTextureGL::MarkNewFrameAvailable() {
244323
}
245324

246325
// |flutter::Texture|
247-
void EmbedderExternalTextureGL::OnTextureUnregistered() {}
326+
void EmbedderExternalTextureGL::OnTextureUnregistered() {
327+
texture_lru_.Clear();
328+
}
248329

249330
} // namespace flutter

engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.h

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,52 @@
55
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_
66
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_H_
77

8+
#include <list>
9+
#include <memory>
10+
#include <unordered_map>
811
#include "flutter/common/graphics/texture.h"
912
#include "flutter/fml/macros.h"
1013
#include "flutter/shell/platform/embedder/embedder.h"
14+
#include "impeller/renderer/backend/gles/texture_gles.h"
1115
#include "third_party/skia/include/core/SkSize.h"
1216

1317
namespace flutter {
18+
static constexpr size_t kTextureMaxSize = 6u;
19+
20+
class TextureLRU {
21+
public:
22+
struct Data {
23+
GLuint key = 0u;
24+
std::shared_ptr<impeller::TextureGLES> texture;
25+
size_t width = 0;
26+
size_t height = 0;
27+
};
28+
29+
TextureLRU() = default;
30+
31+
~TextureLRU() = default;
32+
33+
/// @brief Retrieve the Texture associated with the given [key], or nullptr.
34+
std::optional<Data> FindTexture(std::optional<GLuint> key);
35+
36+
/// @brief Add a new texture to the cache with a key, returning the key of the
37+
/// LRU entry that was removed.
38+
///
39+
/// The value may be `0`, in which case nothing was removed.
40+
GLuint AddTexture(Data data);
41+
42+
/// @brief Remove all entires from the image cache.
43+
void Clear();
44+
45+
/// @brief Remove a texture from the cache by key.
46+
void RemoveTexture(GLuint key);
47+
48+
/// @brief Marks [key] as the most recently used.
49+
void UpdateTexture(Data data);
50+
51+
private:
52+
std::array<Data, kTextureMaxSize> textures_;
53+
};
1454

1555
class EmbedderExternalTextureGL : public flutter::Texture {
1656
public:
@@ -25,7 +65,7 @@ class EmbedderExternalTextureGL : public flutter::Texture {
2565
private:
2666
const ExternalTextureCallback& external_texture_callback_;
2767
sk_sp<DlImage> last_image_;
28-
68+
TextureLRU texture_lru_ = TextureLRU();
2969
sk_sp<DlImage> ResolveTexture(int64_t texture_id,
3070
GrDirectContext* context,
3171
impeller::AiksContext* aiks_context,
@@ -39,13 +79,9 @@ class EmbedderExternalTextureGL : public flutter::Texture {
3979
impeller::AiksContext* aiks_context,
4080
const SkISize& size);
4181

42-
sk_sp<DlImage> ResolveTextureImpellerPixelbuffer(
43-
impeller::AiksContext* aiks_context,
44-
std::unique_ptr<FlutterOpenGLTexture> texture);
45-
46-
sk_sp<DlImage> ResolveTextureImpellerSurface(
82+
std::shared_ptr<impeller::TextureGLES> CreateTextureGLES(
4783
impeller::AiksContext* aiks_context,
48-
std::unique_ptr<FlutterOpenGLTexture> texture);
84+
FlutterOpenGLTexture* texture);
4985

5086
// |flutter::Texture|
5187
void Paint(PaintContext& context,

0 commit comments

Comments
 (0)