Skip to content

Commit c8f7c2b

Browse files
bbrto21swift-kim
authored andcommitted
Fix a crash in ExternalTextureGL (#81)
* Fix a crash in ExternalTextureGL * Abandon ownership of tbm surface in PopulateTextureWithIdentifier * Include the texture id in the log * Lock the mutex in the external texture related API * Use find instead of operator[] that can cause unintended insertion
1 parent f9ece97 commit c8f7c2b

File tree

5 files changed

+79
-65
lines changed

5 files changed

+79
-65
lines changed

shell/platform/tizen/external_texture_gl.cc

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -30,69 +30,90 @@ struct ExternalTextureGLState {
3030

3131
static std::atomic_long nextTextureId = {1};
3232

33+
static void MarkTbmSurfaceToUse(void* surface) {
34+
#ifndef WEARABLE_PROFILE
35+
FT_ASSERT(surface);
36+
tbm_surface_h tbm_surface = (tbm_surface_h)surface;
37+
tbm_surface_internal_ref(tbm_surface);
38+
#endif
39+
}
40+
41+
static void UnmarkTbmSurfaceToUse(void* surface) {
42+
FT_ASSERT(surface);
43+
tbm_surface_h tbm_surface = (tbm_surface_h)surface;
44+
#ifndef WEARABLE_PROFILE
45+
tbm_surface_internal_unref(tbm_surface);
46+
#else
47+
tbm_surface_destroy(tbm_surface);
48+
#endif
49+
}
50+
3351
ExternalTextureGL::ExternalTextureGL()
3452
: state_(std::make_unique<ExternalTextureGLState>()),
35-
texture_tbm_surface_(NULL),
53+
available_tbm_surface_(nullptr),
3654
texture_id_(nextTextureId++) {}
3755

3856
ExternalTextureGL::~ExternalTextureGL() {
39-
mutex_.lock();
4057
if (state_->gl_texture != 0) {
4158
glDeleteTextures(1, &state_->gl_texture);
4259
}
60+
61+
// If there is a available_tbm_surface_ that is not populated, remove it
62+
if (available_tbm_surface_) {
63+
UnmarkTbmSurfaceToUse(available_tbm_surface_);
64+
}
65+
4366
state_.release();
44-
DestructionTbmSurface();
45-
mutex_.unlock();
4667
}
4768

4869
bool ExternalTextureGL::OnFrameAvailable(tbm_surface_h tbm_surface) {
49-
mutex_.lock();
5070
if (!tbm_surface) {
51-
FT_LOGE("tbm_surface is null");
52-
mutex_.unlock();
71+
FT_LOGE("[texture id:%ld] tbm_surface is null", texture_id_);
5372
return false;
5473
}
55-
if (texture_tbm_surface_) {
56-
FT_LOGD("texture_tbm_surface_ does not destruction, discard");
57-
mutex_.unlock();
74+
75+
if (available_tbm_surface_) {
76+
FT_LOGD(
77+
"[texture id:%ld] Discard! an available tbm surface that has not yet "
78+
"been used exists",
79+
texture_id_);
5880
return false;
5981
}
82+
6083
tbm_surface_info_s info;
6184
if (tbm_surface_get_info(tbm_surface, &info) != TBM_SURFACE_ERROR_NONE) {
62-
FT_LOGD("tbm_surface not valid, pass");
63-
mutex_.unlock();
85+
FT_LOGD("[texture id:%ld] tbm_surface not valid, pass", texture_id_);
6486
return false;
6587
}
66-
texture_tbm_surface_ = tbm_surface;
67-
mutex_.unlock();
88+
89+
available_tbm_surface_ = tbm_surface;
90+
MarkTbmSurfaceToUse(available_tbm_surface_);
91+
6892
return true;
6993
}
7094

7195
bool ExternalTextureGL::PopulateTextureWithIdentifier(
7296
size_t width, size_t height, FlutterOpenGLTexture* opengl_texture) {
73-
mutex_.lock();
74-
if (!texture_tbm_surface_) {
75-
FT_LOGD("texture_tbm_surface_ is NULL");
76-
mutex_.unlock();
97+
if (!available_tbm_surface_) {
98+
FT_LOGD("[texture id:%ld] available_tbm_surface_ is null", texture_id_);
7799
return false;
78100
}
79101
tbm_surface_info_s info;
80-
if (tbm_surface_get_info(texture_tbm_surface_, &info) !=
102+
if (tbm_surface_get_info(available_tbm_surface_, &info) !=
81103
TBM_SURFACE_ERROR_NONE) {
82-
FT_LOGD("tbm_surface not valid");
83-
DestructionTbmSurface();
84-
mutex_.unlock();
104+
FT_LOGD("[texture id:%ld] tbm_surface is invalid", texture_id_);
105+
UnmarkTbmSurfaceToUse(available_tbm_surface_);
106+
available_tbm_surface_ = nullptr;
85107
return false;
86108
}
87109

88110
#ifdef TIZEN_RENDERER_EVAS_GL
89111
int attribs[] = {EVAS_GL_IMAGE_PRESERVED, GL_TRUE, 0};
90112
EvasGLImage egl_src_image = evasglCreateImageForContext(
91113
g_evas_gl, evas_gl_current_context_get(g_evas_gl),
92-
EVAS_GL_NATIVE_SURFACE_TIZEN, (void*)(intptr_t)texture_tbm_surface_,
114+
EVAS_GL_NATIVE_SURFACE_TIZEN, (void*)(intptr_t)available_tbm_surface_,
93115
attribs);
94116
if (!egl_src_image) {
95-
mutex_.unlock();
96117
return false;
97118
}
98119
if (state_->gl_texture == 0) {
@@ -120,10 +141,11 @@ bool ExternalTextureGL::PopulateTextureWithIdentifier(
120141
EGL_NONE};
121142
EGLImageKHR egl_src_image = n_eglCreateImageKHR(
122143
eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_SURFACE_TIZEN,
123-
(EGLClientBuffer)texture_tbm_surface_, attribs);
144+
(EGLClientBuffer)available_tbm_surface_, attribs);
145+
124146
if (!egl_src_image) {
125-
FT_LOGE("egl_src_image create fail!!, errorcode == %d", eglGetError());
126-
mutex_.unlock();
147+
FT_LOGE("[texture id:%ld] egl_src_image create fail!!, errorcode == %d",
148+
texture_id_, eglGetError());
127149
return false;
128150
}
129151
if (state_->gl_texture == 0) {
@@ -154,31 +176,13 @@ bool ExternalTextureGL::PopulateTextureWithIdentifier(
154176
opengl_texture->target = GL_TEXTURE_EXTERNAL_OES;
155177
opengl_texture->name = state_->gl_texture;
156178
opengl_texture->format = GL_RGBA8;
157-
opengl_texture->destruction_callback = (VoidCallback)DestructionCallback;
158-
opengl_texture->user_data = static_cast<void*>(this);
179+
opengl_texture->destruction_callback = (VoidCallback)UnmarkTbmSurfaceToUse;
180+
181+
// Abandon ownership of tbm_surface
182+
opengl_texture->user_data = available_tbm_surface_;
183+
available_tbm_surface_ = nullptr;
184+
159185
opengl_texture->width = width;
160186
opengl_texture->height = height;
161-
mutex_.unlock();
162187
return true;
163188
}
164-
165-
void ExternalTextureGL::DestructionTbmSurfaceWithLock() {
166-
mutex_.lock();
167-
DestructionTbmSurface();
168-
mutex_.unlock();
169-
}
170-
171-
void ExternalTextureGL::DestructionTbmSurface() {
172-
if (!texture_tbm_surface_) {
173-
FT_LOGE("tbm_surface_h is NULL");
174-
return;
175-
}
176-
tbm_surface_destroy(texture_tbm_surface_);
177-
texture_tbm_surface_ = NULL;
178-
}
179-
180-
void ExternalTextureGL::DestructionCallback(void* user_data) {
181-
ExternalTextureGL* externalTextureGL =
182-
reinterpret_cast<ExternalTextureGL*>(user_data);
183-
externalTextureGL->DestructionTbmSurfaceWithLock();
184-
}

shell/platform/tizen/external_texture_gl.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,12 @@ class ExternalTextureGL {
4141
bool PopulateTextureWithIdentifier(size_t width, size_t height,
4242
FlutterOpenGLTexture* opengl_texture);
4343
bool OnFrameAvailable(tbm_surface_h tbm_surface);
44-
void DestructionTbmSurface();
45-
void DestructionTbmSurfaceWithLock();
4644

4745
private:
4846
std::unique_ptr<ExternalTextureGLState> state_;
4947
std::mutex mutex_;
50-
tbm_surface_h texture_tbm_surface_;
51-
static void DestructionCallback(void* user_data);
52-
const long texture_id_;
48+
tbm_surface_h available_tbm_surface_{nullptr};
49+
const long texture_id_{0};
5350
};
5451

5552
#endif // FLUTTER_SHELL_PLATFORM_TIZEN_EXTERNAL_TEXTURE_GL_H_

shell/platform/tizen/flutter_tizen.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ void FlutterNotifyLowMemoryWarning(FlutterWindowControllerRef controller) {
181181
int64_t FlutterRegisterExternalTexture(
182182
FlutterTextureRegistrarRef texture_registrar) {
183183
FT_LOGD("FlutterDesktopRegisterExternalTexture");
184+
std::lock_guard<std::mutex> lock(texture_registrar->mutex);
184185
auto texture_gl = std::make_unique<ExternalTextureGL>();
185186
int64_t texture_id = texture_gl->TextureId();
186187
texture_registrar->textures[texture_id] = std::move(texture_gl);
@@ -193,28 +194,32 @@ int64_t FlutterRegisterExternalTexture(
193194

194195
bool FlutterUnregisterExternalTexture(
195196
FlutterTextureRegistrarRef texture_registrar, int64_t texture_id) {
197+
std::lock_guard<std::mutex> lock(texture_registrar->mutex);
196198
auto it = texture_registrar->textures.find(texture_id);
197199
if (it != texture_registrar->textures.end())
198200
texture_registrar->textures.erase(it);
199-
return (FlutterEngineUnregisterExternalTexture(
200-
texture_registrar->flutter_engine, texture_id) == kSuccess);
201+
bool ret = FlutterEngineUnregisterExternalTexture(
202+
texture_registrar->flutter_engine, texture_id) == kSuccess;
203+
return ret;
201204
}
202205

203206
bool FlutterMarkExternalTextureFrameAvailable(
204207
FlutterTextureRegistrarRef texture_registrar, int64_t texture_id,
205208
void* tbm_surface) {
209+
std::lock_guard<std::mutex> lock(texture_registrar->mutex);
206210
auto it = texture_registrar->textures.find(texture_id);
207211
if (it == texture_registrar->textures.end()) {
208212
FT_LOGE("can't find texture texture_id = %" PRId64, texture_id);
209213
return false;
210214
}
211215
if (!texture_registrar->textures[texture_id]->OnFrameAvailable(
212216
(tbm_surface_h)tbm_surface)) {
213-
FT_LOGE("OnFrameAvailable fail texture_id = %" PRId64, texture_id);
217+
// If a texture that has not been used already exists, it can fail
214218
return false;
215219
}
216-
return (FlutterEngineMarkExternalTextureFrameAvailable(
217-
texture_registrar->flutter_engine, texture_id) == kSuccess);
220+
bool ret = FlutterEngineMarkExternalTextureFrameAvailable(
221+
texture_registrar->flutter_engine, texture_id) == kSuccess;
222+
return ret;
218223
}
219224

220225
void FlutterRegisterViewFactory(

shell/platform/tizen/tizen_embedder_engine.cc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ bool TizenEmbedderEngine::RunEngine(
231231

232232
if (HasTizenRenderer()) {
233233
std::unique_ptr<FlutterTextureRegistrar> textures =
234-
std::make_unique<FlutterTextureRegistrar>();
234+
std::make_unique<FlutterTextureRegistrar>();
235235
textures->flutter_engine = flutter_engine;
236236
plugin_registrar_->texture_registrar = std::move(textures);
237237

@@ -285,9 +285,16 @@ bool TizenEmbedderEngine::OnAcquireExternalTexture(
285285
FlutterOpenGLTexture* texture) {
286286
TizenEmbedderEngine* tizen_embedder_engine =
287287
reinterpret_cast<TizenEmbedderEngine*>(user_data);
288-
return tizen_embedder_engine->plugin_registrar_->texture_registrar
289-
->textures[texture_id]
290-
->PopulateTextureWithIdentifier(width, height, texture);
288+
std::lock_guard<std::mutex> lock(
289+
tizen_embedder_engine->plugin_registrar_->texture_registrar->mutex);
290+
auto it = tizen_embedder_engine->plugin_registrar_->texture_registrar
291+
->textures.find(texture_id);
292+
int ret = false;
293+
if (it != tizen_embedder_engine->plugin_registrar_->texture_registrar
294+
->textures.end()) {
295+
ret = it->second->PopulateTextureWithIdentifier(width, height, texture);
296+
}
297+
return ret;
291298
}
292299

293300
void TizenEmbedderEngine::SendWindowMetrics(int32_t width, int32_t height,

shell/platform/tizen/tizen_embedder_engine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct FlutterTextureRegistrar {
6060

6161
// The texture registrar managing external texture adapters.
6262
std::map<int64_t, std::unique_ptr<ExternalTextureGL>> textures;
63+
std::mutex mutex;
6364
};
6465

6566
using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AOTDataDeleter>;

0 commit comments

Comments
 (0)