diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index ef390e5d0649e..ded0c1e7dc2e2 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -6,6 +6,7 @@ import("//build/fuchsia/sdk.gni") import("//flutter/common/config.gni") import("//flutter/shell/gpu/gpu.gni") import("//flutter/testing/testing.gni") +import("//flutter/shell/platform/tizen/config.gni") # Template to generate a dart embedder resource.cc file. # Required invoker inputs: @@ -118,6 +119,10 @@ source_set("common") { "//third_party/dart/runtime:dart_api", "//third_party/skia", ] + + if (build_tizen_shell) { + defines = [ "FLUTTER_TIZEN_SHELL" ] + } } template("shell_host_executable") { diff --git a/shell/common/animator.cc b/shell/common/animator.cc index cacac38c12063..63c4d39891f33 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -31,7 +31,11 @@ Animator::Animator(Delegate& delegate, dart_frame_deadline_(0), #if SHELL_ENABLE_METAL layer_tree_pipeline_(fml::MakeRefCounted(2)), -#else // SHELL_ENABLE_METAL +#elif FLUTTER_TIZEN_SHELL + // FIXME + // This is a workaround to avoid flickering that occurs in evas gl direct mode. + layer_tree_pipeline_(fml::MakeRefCounted(1)), +#else // SHELL_ENABLE_METAL // TODO(dnfield): We should remove this logic and set the pipeline depth // back to 2 in this case. See // https://github.com/flutter/engine/pull/9132 for discussion. diff --git a/shell/platform/tizen/BUILD.gn b/shell/platform/tizen/BUILD.gn index 5cdac760a2ac3..dd6a40affe928 100644 --- a/shell/platform/tizen/BUILD.gn +++ b/shell/platform/tizen/BUILD.gn @@ -52,7 +52,6 @@ source_set("flutter_tizen") { "tizen_event_loop.cc", "tizen_log.cc", "tizen_renderer.cc", - "tizen_vsync_waiter.cc", "touch_event_handler.cc", ] @@ -87,7 +86,16 @@ source_set("flutter_tizen") { "$custom_sysroot/usr/include/eo-1", "$custom_sysroot/usr/include/evas-1", "$custom_sysroot/usr/include/system", - "$custom_sysroot/usr/include/wayland-extension" + "$custom_sysroot/usr/include/wayland-extension", + "$custom_sysroot/usr/include/elementary-1", + "$custom_sysroot/usr/include/eet-1", + "$custom_sysroot/usr/include/ecore-file-1", + "$custom_sysroot/usr/include/ecore-con-1", + "$custom_sysroot/usr/include/edje-1", + "$custom_sysroot/usr/include/efreet-1", + "$custom_sysroot/usr/include/ethumb-1", + "$custom_sysroot/usr/include/ethumb-client-1", + "$custom_sysroot/usr/include/efl-1/interfaces", ] lib_dirs = [ root_out_dir, "$custom_sysroot/usr/lib" ] @@ -119,9 +127,13 @@ source_set("flutter_tizen") { if (tizen_sdk_4) { sources += [ "tizen_renderer_ecore_wl.cc" ] libs += [ "ecore_wayland", "wayland-egl" ] - defines = [ "FLUTTER_TIZEN_4" ] + defines = [ "FLUTTER_TIZEN_EVASGL" ] } else { - sources += [ "tizen_renderer_ecore_wl2.cc" ] - libs += [ "ecore_wl2" ] + # sources += [ "tizen_renderer_ecore_wl2.cc" ] + # libs += [ "ecore_wl2" ] +#evasgl + sources += [ "tizen_renderer_evas_gl.cc" ] + libs += [ "elementary","ecore_evas" ] + defines = [ "FLUTTER_TIZEN_EVASGL" ] } } diff --git a/shell/platform/tizen/channels/text_input_channel.cc b/shell/platform/tizen/channels/text_input_channel.cc index 6aa7bf1f53f4b..57615e28f2889 100644 --- a/shell/platform/tizen/channels/text_input_channel.cc +++ b/shell/platform/tizen/channels/text_input_channel.cc @@ -183,61 +183,6 @@ Ecore_IMF_Keyboard_Locks EcoreInputModifierToEcoreIMFLock( return static_cast(lock); } -Ecore_IMF_Device_Class EoreDeviceClassToEcoreIMFDeviceClass( - Ecore_Device_Class ecoreDeviceClass) { - switch (ecoreDeviceClass) { - case ECORE_DEVICE_CLASS_SEAT: - return ECORE_IMF_DEVICE_CLASS_SEAT; - case ECORE_DEVICE_CLASS_KEYBOARD: - return ECORE_IMF_DEVICE_CLASS_KEYBOARD; - case ECORE_DEVICE_CLASS_MOUSE: - return ECORE_IMF_DEVICE_CLASS_MOUSE; - case ECORE_DEVICE_CLASS_TOUCH: - return ECORE_IMF_DEVICE_CLASS_TOUCH; - case ECORE_DEVICE_CLASS_PEN: - return ECORE_IMF_DEVICE_CLASS_PEN; - case ECORE_DEVICE_CLASS_POINTER: - return ECORE_IMF_DEVICE_CLASS_POINTER; - case ECORE_DEVICE_CLASS_GAMEPAD: - return ECORE_IMF_DEVICE_CLASS_GAMEPAD; - case ECORE_DEVICE_CLASS_NONE: - default: - return ECORE_IMF_DEVICE_CLASS_NONE; - } -} - -Ecore_IMF_Device_Subclass EoreDeviceSubClassToEcoreIMFDeviceSubClass( - Ecore_Device_Subclass ecoreDeviceSubclass) { - switch (ecoreDeviceSubclass) { - case ECORE_DEVICE_SUBCLASS_FINGER: - return ECORE_IMF_DEVICE_SUBCLASS_FINGER; - case ECORE_DEVICE_SUBCLASS_FINGERNAIL: - return ECORE_IMF_DEVICE_SUBCLASS_FINGERNAIL; - case ECORE_DEVICE_SUBCLASS_KNUCKLE: - return ECORE_IMF_DEVICE_SUBCLASS_KNUCKLE; - case ECORE_DEVICE_SUBCLASS_PALM: - return ECORE_IMF_DEVICE_SUBCLASS_PALM; - case ECORE_DEVICE_SUBCLASS_HAND_SIZE: - return ECORE_IMF_DEVICE_SUBCLASS_HAND_SIZE; - case ECORE_DEVICE_SUBCLASS_HAND_FLAT: - return ECORE_IMF_DEVICE_SUBCLASS_HAND_FLAT; - case ECORE_DEVICE_SUBCLASS_PEN_TIP: - return ECORE_IMF_DEVICE_SUBCLASS_PEN_TIP; - case ECORE_DEVICE_SUBCLASS_TRACKPAD: - return ECORE_IMF_DEVICE_SUBCLASS_TRACKPAD; - case ECORE_DEVICE_SUBCLASS_TRACKPOINT: - return ECORE_IMF_DEVICE_SUBCLASS_TRACKPOINT; - case ECORE_DEVICE_SUBCLASS_TRACKBALL: - return ECORE_IMF_DEVICE_SUBCLASS_TRACKBALL; - case ECORE_DEVICE_SUBCLASS_REMOCON: - case ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD: - // FT_LOGW("There is no corresponding type"); - case ECORE_DEVICE_SUBCLASS_NONE: - default: - return ECORE_IMF_DEVICE_SUBCLASS_NONE; - } -} - TextInputChannel::TextInputChannel(flutter::BinaryMessenger* messenger, TizenEmbedderEngine* engine) : channel_(std::make_unique>( @@ -397,8 +342,8 @@ void TextInputChannel::SendStateUpdate(const flutter::TextInputModel& model) { bool TextInputChannel::FilterEvent(Ecore_Event_Key* keyDownEvent) { bool handled = false; - const char* device = ecore_device_name_get(keyDownEvent->dev); - + bool isIME = ecore_imf_context_keyboard_mode_get(imf_context_) == + ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE; Ecore_IMF_Event_Key_Down ecoreKeyDownEvent; ecoreKeyDownEvent.keyname = keyDownEvent->keyname; ecoreKeyDownEvent.key = keyDownEvent->key; @@ -409,17 +354,15 @@ bool TextInputChannel::FilterEvent(Ecore_Event_Key* keyDownEvent) { EcoreInputModifierToEcoreIMFModifier(keyDownEvent->modifiers); ecoreKeyDownEvent.locks = EcoreInputModifierToEcoreIMFLock(keyDownEvent->modifiers); - ecoreKeyDownEvent.dev_name = device; - ecoreKeyDownEvent.dev_class = EoreDeviceClassToEcoreIMFDeviceClass( - ecore_device_class_get(keyDownEvent->dev)); - ecoreKeyDownEvent.dev_subclass = EoreDeviceSubClassToEcoreIMFDeviceSubClass( - ecore_device_subclass_get(keyDownEvent->dev)); + if (isIME) { + ecoreKeyDownEvent.dev_name = "ime"; + } else { + ecoreKeyDownEvent.dev_name = ""; + } #ifndef FLUTTER_TIZEN_4 ecoreKeyDownEvent.keycode = keyDownEvent->keycode; #endif - bool isIME = strcmp(device, "ime") == 0; - if (isIME && strcmp(keyDownEvent->key, "Select") == 0) { if (engine_->device_profile == DeviceProfile::kWearable) { // FIXME: for wearable diff --git a/shell/platform/tizen/external_texture_gl.cc b/shell/platform/tizen/external_texture_gl.cc index d7078978f5685..cb8133f67b399 100644 --- a/shell/platform/tizen/external_texture_gl.cc +++ b/shell/platform/tizen/external_texture_gl.cc @@ -4,11 +4,20 @@ #include "external_texture_gl.h" +#ifndef FLUTTER_TIZEN_EVASGL #include #include #include #include #include +#else +#undef EFL_BETA_API_SUPPORT +#include +#include +#include +extern Evas_GL* g_evas_gl; +EVAS_GL_GLOBAL_GLES3_DECLARE(); +#endif #include #include @@ -29,7 +38,11 @@ ExternalTextureGL::ExternalTextureGL() ExternalTextureGL::~ExternalTextureGL() { mutex_.lock(); if (state_->gl_texture != 0) { +#ifndef FLUTTER_TIZEN_EVASGL glDeleteTextures(1, &state_->gl_texture); +#else + glDeleteTextures(1, &state_->gl_texture); +#endif } state_.release(); DestructionTbmSurface(); @@ -48,13 +61,14 @@ bool ExternalTextureGL::OnFrameAvailable(tbm_surface_h tbm_surface) { mutex_.unlock(); return false; } - if (!tbm_surface_internal_is_valid(tbm_surface)) { + + tbm_surface_info_s info; + if (tbm_surface_get_info(tbm_surface, &info) != TBM_SURFACE_ERROR_NONE) { FT_LOGD("tbm_surface not valid, pass"); mutex_.unlock(); return false; } texture_tbm_surface_ = tbm_surface; - tbm_surface_internal_ref(texture_tbm_surface_); mutex_.unlock(); return true; } @@ -67,22 +81,26 @@ bool ExternalTextureGL::PopulateTextureWithIdentifier( mutex_.unlock(); return false; } - if (!tbm_surface_internal_is_valid(texture_tbm_surface_)) { + tbm_surface_info_s info; + if (tbm_surface_get_info(texture_tbm_surface_, &info) != + TBM_SURFACE_ERROR_NONE) { FT_LOGD("tbm_surface not valid"); DestructionTbmSurface(); mutex_.unlock(); return false; } +#ifndef FLUTTER_TIZEN_EVASGL PFNEGLCREATEIMAGEKHRPROC n_eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); const EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE}; - EGLImageKHR eglSrcImage = n_eglCreateImageKHR( + EGLImageKHR egl_src_image = n_eglCreateImageKHR( eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_SURFACE_TIZEN, (EGLClientBuffer)texture_tbm_surface_, attrs); - if (!eglSrcImage) { - FT_LOGE("eglSrcImage create fail!!, errorcode == %d", eglGetError()); + + if (!egl_src_image) { + FT_LOGE("egl_src_image create fail!!, errorcode == %d", eglGetError()); mutex_.unlock(); return false; } @@ -103,12 +121,43 @@ bool ExternalTextureGL::PopulateTextureWithIdentifier( PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress( "glEGLImageTargetTexture2DOES"); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglSrcImage); - if (eglSrcImage) { + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_src_image); + if (egl_src_image) { PFNEGLDESTROYIMAGEKHRPROC n_eglDestoryImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); - n_eglDestoryImageKHR(eglGetCurrentDisplay(), eglSrcImage); + n_eglDestoryImageKHR(eglGetCurrentDisplay(), egl_src_image); + } +#else + int eglImgAttr[] = {EVAS_GL_IMAGE_PRESERVED, GL_TRUE, 0}; + EvasGLImage egl_src_image = evasglCreateImageForContext( + g_evas_gl, evas_gl_current_context_get(g_evas_gl), + EVAS_GL_NATIVE_SURFACE_TIZEN, (void*)(intptr_t)texture_tbm_surface_, + eglImgAttr); + if (!egl_src_image) { + // FT_LOGE("egl_src_image create fail!!, errorcode == %d", eglGetError()); + mutex_.unlock(); + return false; + } + if (state_->gl_texture == 0) { + glGenTextures(1, &state_->gl_texture); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, state_->gl_texture); + // set the texture wrapping parameters + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_BORDER); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, state_->gl_texture); } + glEvasGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_src_image); + if (egl_src_image) { + evasglDestroyImage(egl_src_image); + } + +#endif opengl_texture->target = GL_TEXTURE_EXTERNAL_OES; opengl_texture->name = state_->gl_texture; opengl_texture->format = GL_RGBA8; @@ -131,7 +180,7 @@ void ExternalTextureGL::DestructionTbmSurface() { FT_LOGE("tbm_surface_h is NULL"); return; } - tbm_surface_internal_unref(texture_tbm_surface_); + tbm_surface_destroy(texture_tbm_surface_); texture_tbm_surface_ = NULL; } diff --git a/shell/platform/tizen/tizen_embedder_engine.cc b/shell/platform/tizen/tizen_embedder_engine.cc index 5ce8651fa2c3c..4a848bd4a66a3 100644 --- a/shell/platform/tizen/tizen_embedder_engine.cc +++ b/shell/platform/tizen/tizen_embedder_engine.cc @@ -15,6 +15,7 @@ // Unique number associated with platform tasks. static constexpr size_t kPlatformTaskRunnerIdentifier = 1; +static constexpr size_t kRederTaskRunnerIdentifier = 2; static DeviceProfile GetDeviceProfile() { char* feature_profile; @@ -44,6 +45,15 @@ static double GetDeviceDpi() { TizenEmbedderEngine::TizenEmbedderEngine( const FlutterWindowProperties& window_properties) : device_profile(GetDeviceProfile()), device_dpi(GetDeviceDpi()) { +#ifdef FLUTTER_TIZEN_EVASGL + tizen_renderer = std::make_unique( + *this, window_properties.x, window_properties.y, window_properties.width, + window_properties.height); + // clear once to remove noise + tizen_renderer->OnMakeCurrent(); + tizen_renderer->ClearColor(0, 0, 0, 0); + tizen_renderer->OnPresent(); +#else #ifdef FLUTTER_TIZEN_4 tizen_renderer = std::make_unique( *this, window_properties.x, window_properties.y, window_properties.width, @@ -53,11 +63,11 @@ TizenEmbedderEngine::TizenEmbedderEngine( *this, window_properties.x, window_properties.y, window_properties.width, window_properties.height); #endif - +#endif // Run flutter task on Tizen main loop. // Tizen engine has four threads (GPU thread, UI thread, IO thread, platform // thread). UI threads need to send flutter task to platform thread. - event_loop_ = std::make_unique( + event_loop_ = std::make_unique( std::this_thread::get_id(), // main thread [this](const auto* task) { if (FlutterEngineRunTask(this->flutter_engine, task) != kSuccess) { @@ -65,12 +75,21 @@ TizenEmbedderEngine::TizenEmbedderEngine( } }); + render_loop_ = std::make_unique( + std::this_thread::get_id(), // main thread + [this](const auto* task) { + if (FlutterEngineRunTask(this->flutter_engine, task) != kSuccess) { + FT_LOGE("Could not post an engine task."); + } + }, + tizen_renderer.get()); + messenger = std::make_unique(); messenger->engine = this; message_dispatcher = std::make_unique(messenger.get()); - tizen_vsync_waiter_ = std::make_unique(this); + // tizen_vsync_waiter_ = std::make_unique(this); } TizenEmbedderEngine::~TizenEmbedderEngine() { @@ -133,9 +152,23 @@ bool TizenEmbedderEngine::RunEngine( }; platform_task_runner.identifier = kPlatformTaskRunnerIdentifier; + FlutterTaskRunnerDescription render_task_runner = {}; + render_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription); + render_task_runner.user_data = render_loop_.get(); + render_task_runner.runs_task_on_current_thread_callback = + [](void* data) -> bool { + return static_cast(data)->RunsTasksOnCurrentThread(); + }; + render_task_runner.post_task_callback = + [](FlutterTask task, uint64_t target_time_nanos, void* data) -> void { + static_cast(data)->PostTask(task, target_time_nanos); + }; + render_task_runner.identifier = kRederTaskRunnerIdentifier; + FlutterCustomTaskRunners custom_task_runners = {}; custom_task_runners.struct_size = sizeof(FlutterCustomTaskRunners); custom_task_runners.platform_task_runner = &platform_task_runner; + custom_task_runners.render_task_runner = &render_task_runner; FlutterRendererConfig config = {}; config.type = kOpenGL; @@ -157,7 +190,7 @@ bool TizenEmbedderEngine::RunEngine( args.command_line_argv = &argv[0]; args.platform_message_callback = OnFlutterPlatformMessage; args.custom_task_runners = &custom_task_runners; - args.vsync_callback = OnVsyncCallback; + // args.vsync_callback = OnVsyncCallback; if (FlutterEngineRunsAOTCompiledDartCode()) { aot_data_ = LoadAotData(engine_properties.aot_library_path); @@ -345,11 +378,11 @@ void TizenEmbedderEngine::OnFlutterPlatformMessage( tizen_embedder_engine->message_dispatcher->HandleMessage(message); } -void TizenEmbedderEngine::OnVsyncCallback(void* user_data, intptr_t baton) { - TizenEmbedderEngine* tizen_embedder_engine = - reinterpret_cast(user_data); - tizen_embedder_engine->tizen_vsync_waiter_->AsyncWaitForVsync(baton); -} +// void TizenEmbedderEngine::OnVsyncCallback(void* user_data, intptr_t baton) { +// TizenEmbedderEngine* tizen_embedder_engine = +// reinterpret_cast(user_data); +// tizen_embedder_engine->tizen_vsync_waiter_->AsyncWaitForVsync(baton); +// } // Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage. FlutterDesktopMessage TizenEmbedderEngine::ConvertToDesktopMessage( diff --git a/shell/platform/tizen/tizen_embedder_engine.h b/shell/platform/tizen/tizen_embedder_engine.h index 316c99e8aa911..158359c6a7fe1 100644 --- a/shell/platform/tizen/tizen_embedder_engine.h +++ b/shell/platform/tizen/tizen_embedder_engine.h @@ -24,11 +24,15 @@ #include "flutter/shell/platform/tizen/public/flutter_tizen_texture_registrar.h" #include "flutter/shell/platform/tizen/tizen_event_loop.h" #include "flutter/shell/platform/tizen/tizen_renderer.h" +#ifndef FLUTTER_TIZEN_EVASGL #ifdef FLUTTER_TIZEN_4 #include "flutter/shell/platform/tizen/tizen_renderer_ecore_wl.h" #else #include "flutter/shell/platform/tizen/tizen_renderer_ecore_wl2.h" #endif +#else +#include "flutter/shell/platform/tizen/tizen_renderer_evas_gl.h" +#endif #include "flutter/shell/platform/tizen/tizen_vsync_waiter.h" #include "flutter/shell/platform/tizen/touch_event_handler.h" @@ -150,8 +154,8 @@ class TizenEmbedderEngine : public TizenRenderer::Delegate { std::unique_ptr internal_plugin_registrar_; // The event loop for the main thread that allows for delayed task execution. - std::unique_ptr event_loop_; - + std::unique_ptr event_loop_; + std::unique_ptr render_loop_; // The vsync waiter for the embedder. std::unique_ptr tizen_vsync_waiter_; diff --git a/shell/platform/tizen/tizen_event_loop.cc b/shell/platform/tizen/tizen_event_loop.cc index 876818f05815d..13b7bbcff4908 100644 --- a/shell/platform/tizen/tizen_event_loop.cc +++ b/shell/platform/tizen/tizen_event_loop.cc @@ -8,6 +8,9 @@ #include #include +#include "flutter/shell/platform/tizen/tizen_log.h" +#include "flutter/shell/platform/tizen/tizen_renderer.h" + TizenEventLoop::TizenEventLoop(std::thread::id main_thread_id, TaskExpiredCallback on_task_expired) : main_thread_id_(main_thread_id), @@ -27,22 +30,21 @@ bool TizenEventLoop::RunsTasksOnCurrentThread() const { void TizenEventLoop::ExcuteTaskEvents(std::chrono::nanoseconds max_wait) { const auto now = TaskTimePoint::clock::now(); - std::vector expired_tasks; { - std::lock_guard lock(task_queue_mutex_); + std::lock_guard lock1(task_queue_mutex_); + std::lock_guard lock2(expired_tasks_mutex_); while (!task_queue_.empty()) { const auto& top = task_queue_.top(); if (top.fire_time > now) { break; } - expired_tasks.push_back(task_queue_.top().task); + + expired_tasks_.push_back(task_queue_.top().task); task_queue_.pop(); } } - for (const auto& task : expired_tasks) { - on_task_expired_(&task); - } + OnTaskExpired(); } TizenEventLoop::TaskTimePoint TizenEventLoop::TimePointFromFlutterTime( @@ -55,9 +57,8 @@ TizenEventLoop::TaskTimePoint TizenEventLoop::TimePointFromFlutterTime( void TizenEventLoop::PostTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos) { - static std::atomic sGlobalTaskOrder(0); Task task; - task.order = ++sGlobalTaskOrder; + task.order = ++task_order_; task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos); task.task = flutter_task; if (ecore_pipe_) { @@ -87,6 +88,60 @@ void TizenEventLoop::ExcuteTaskEvents(void* data, void* buffer, } ecore_timer_add(flutter_duration, TaskTimerCallback, tizenEventLoop); } else { - tizenEventLoop->on_task_expired_(&(p_task->task)); + { + std::lock_guard lock(tizenEventLoop->expired_tasks_mutex_); + tizenEventLoop->expired_tasks_.push_back(p_task->task); + } + tizenEventLoop->OnTaskExpired(); + } +} + +TizenPlatformEventLoop::TizenPlatformEventLoop( + std::thread::id main_thread_id, TaskExpiredCallback on_task_expired) + : TizenEventLoop(main_thread_id, on_task_expired) {} + +TizenPlatformEventLoop::~TizenPlatformEventLoop() {} + +void TizenPlatformEventLoop::OnTaskExpired() { + for (const auto& task : expired_tasks_) { + on_task_expired_(&task); + } + expired_tasks_.clear(); +} + +TizenRenderEventLoop::TizenRenderEventLoop(std::thread::id main_thread_id, + TaskExpiredCallback on_task_expired, + TizenRenderer* tizen_renderer) + : TizenEventLoop(main_thread_id, on_task_expired), + tizen_renderer_(tizen_renderer) { + evas_object_image_pixels_get_callback_set( + (Evas_Object*)tizen_renderer_->GetImageHandle(), + [](void* data, Evas_Object* o) { // Render call back + TizenRenderEventLoop* self = (TizenRenderEventLoop*)data; + { + std::lock_guard lock(self->expired_tasks_mutex_); + for (const auto& task : self->expired_tasks_) { + self->on_task_expired_(&task); + } + self->expired_tasks_.clear(); + } + self->has_pending_renderer_callback_ = false; + }, + this); +} + +TizenRenderEventLoop::~TizenRenderEventLoop() {} + +void TizenRenderEventLoop::OnTaskExpired() { + size_t expired_tasks_count = 0; + std::lock_guard lock(expired_tasks_mutex_); + expired_tasks_count = expired_tasks_.size(); + if (has_pending_renderer_callback_ == false && expired_tasks_count) { + evas_object_image_pixels_dirty_set( + (Evas_Object*)tizen_renderer_->GetImageHandle(), EINA_TRUE); + has_pending_renderer_callback_ = true; + } else { + // Do nothing + FT_LOGD("Ignore set dirty"); } } diff --git a/shell/platform/tizen/tizen_event_loop.h b/shell/platform/tizen/tizen_event_loop.h index 56b41fae27e34..a3a81037186cb 100644 --- a/shell/platform/tizen/tizen_event_loop.h +++ b/shell/platform/tizen/tizen_event_loop.h @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -18,12 +19,14 @@ #include "flutter/shell/platform/embedder/embedder.h" +class TizenRenderer; + class TizenEventLoop { public: using TaskExpiredCallback = std::function; TizenEventLoop(std::thread::id main_thread_id, TaskExpiredCallback on_task_expired); - ~TizenEventLoop(); + virtual ~TizenEventLoop(); bool RunsTasksOnCurrentThread() const; void ExcuteTaskEvents( @@ -32,7 +35,9 @@ class TizenEventLoop { // Post a Flutter engine tasks to the event loop for delayed execution. void PostTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos); - private: + virtual void OnTaskExpired() = 0; + + protected: using TaskTimePoint = std::chrono::steady_clock::time_point; struct Task { uint64_t order; @@ -53,6 +58,11 @@ class TizenEventLoop { std::mutex task_queue_mutex_; std::priority_queue, Task::Comparer> task_queue_; std::condition_variable task_queue_cv_; + std::vector expired_tasks_; + std::mutex expired_tasks_mutex_; + std::atomic task_order_{0}; + + private: Ecore_Pipe* ecore_pipe_; TizenEventLoop(const TizenEventLoop&) = delete; @@ -66,4 +76,25 @@ class TizenEventLoop { uint64_t flutter_target_time_nanos); }; +class TizenPlatformEventLoop : public TizenEventLoop { + public: + TizenPlatformEventLoop(std::thread::id main_thread_id, + TaskExpiredCallback on_task_expired); + virtual ~TizenPlatformEventLoop(); + virtual void OnTaskExpired() override; +}; + +class TizenRenderEventLoop : public TizenEventLoop { + public: + TizenRenderEventLoop(std::thread::id main_thread_id, + TaskExpiredCallback on_task_expired, + TizenRenderer* tizen_renderer); + virtual ~TizenRenderEventLoop(); + virtual void OnTaskExpired() override; + + private: + TizenRenderer* tizen_renderer_; + std::atomic_bool has_pending_renderer_callback_{false}; +}; + #endif // TIZEN_EVENT_LOOP_H_ diff --git a/shell/platform/tizen/tizen_renderer.cc b/shell/platform/tizen/tizen_renderer.cc index 1354a7648b119..8232a8d805325 100644 --- a/shell/platform/tizen/tizen_renderer.cc +++ b/shell/platform/tizen/tizen_renderer.cc @@ -4,8 +4,14 @@ #include "tizen_renderer.h" +#ifndef FLUTTER_TIZEN_EVASGL #include #include +#else +#include +Evas_GL* g_evas_gl = nullptr; +EVAS_GL_GLOBAL_GLES3_DEFINE(); +#endif #include "flutter/shell/platform/tizen/tizen_log.h" @@ -14,6 +20,8 @@ TizenRenderer::TizenRenderer(TizenRenderer::Delegate& delegate) TizenRenderer::~TizenRenderer() = default; +#ifndef FLUTTER_TIZEN_EVASGL + bool TizenRenderer::OnMakeCurrent() { if (!IsValid()) { FT_LOGE("Invalid TizenRenderer"); @@ -458,3 +466,605 @@ void TizenRenderer::DestoryEglSurface() { egl_display_ = EGL_NO_DISPLAY; } } +#else + +void TizenRenderer::ClearColor(float r, float g, float b, float a) { + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT); +} + +bool TizenRenderer::OnMakeCurrent() { + if (!IsValid()) { + FT_LOGE("Invalid TizenRenderer"); + return false; + } + if (evas_gl_make_current(evas_gl_, gl_surface_, gl_context_) != EINA_TRUE) { + return false; + } + + return true; +} + +bool TizenRenderer::OnClearCurrent() { + if (!IsValid()) { + FT_LOGE("Invalid TizenRenderer"); + return false; + } + if (evas_gl_make_current(evas_gl_, NULL, NULL) != EINA_TRUE) { + return false; + } + return true; +} + +bool TizenRenderer::OnMakeResourceCurrent() { + if (!IsValid()) { + FT_LOGE("Invalid TizenRenderer"); + return false; + } + if (evas_gl_make_current(evas_gl_, gl_resource_surface_, + gl_resource_context_) != EINA_TRUE) { + return false; + } + return true; +} + +bool TizenRenderer::OnPresent() { + if (!is_valid_) { + FT_LOGE("Invalid TizenRenderer"); + return false; + } + if (received_rotation) { + SendRotationChangeDone(); + received_rotation = false; + } + + return true; +} + +uint32_t TizenRenderer::OnGetFBO() { + if (!is_valid_) { + FT_LOGE("Invalid TizenRenderer"); + return 999; + } + FT_LOGD("OnGetFBO"); + return 0; +} + +#define GL_FUNC(FunctionName) \ + else if (strcmp(name, #FunctionName) == 0) { \ + return reinterpret_cast(FunctionName); \ + } +void* TizenRenderer::OnProcResolver(const char* name) { + auto address = evas_gl_proc_address_get(evas_gl_, name); + if (address != nullptr) { + return reinterpret_cast(address); + } + GL_FUNC(glActiveTexture) + GL_FUNC(glAttachShader) + GL_FUNC(glBindAttribLocation) + GL_FUNC(glBindBuffer) + GL_FUNC(glBindFramebuffer) + GL_FUNC(glBindRenderbuffer) + GL_FUNC(glBindTexture) + GL_FUNC(glBlendColor) + GL_FUNC(glBlendEquation) + GL_FUNC(glBlendEquationSeparate) + GL_FUNC(glBlendFunc) + GL_FUNC(glBlendFuncSeparate) + GL_FUNC(glBufferData) + GL_FUNC(glBufferSubData) + GL_FUNC(glCheckFramebufferStatus) + GL_FUNC(glClear) + GL_FUNC(glClearColor) + GL_FUNC(glClearDepthf) + GL_FUNC(glClearStencil) + GL_FUNC(glColorMask) + GL_FUNC(glCompileShader) + GL_FUNC(glCompressedTexImage2D) + GL_FUNC(glCompressedTexSubImage2D) + GL_FUNC(glCopyTexImage2D) + GL_FUNC(glCopyTexSubImage2D) + GL_FUNC(glCreateProgram) + GL_FUNC(glCreateShader) + GL_FUNC(glCullFace) + GL_FUNC(glDeleteBuffers) + GL_FUNC(glDeleteFramebuffers) + GL_FUNC(glDeleteProgram) + GL_FUNC(glDeleteRenderbuffers) + GL_FUNC(glDeleteShader) + GL_FUNC(glDeleteTextures) + GL_FUNC(glDepthFunc) + GL_FUNC(glDepthMask) + GL_FUNC(glDepthRangef) + GL_FUNC(glDetachShader) + GL_FUNC(glDisable) + GL_FUNC(glDisableVertexAttribArray) + GL_FUNC(glDrawArrays) + GL_FUNC(glDrawElements) + GL_FUNC(glEnable) + GL_FUNC(glEnableVertexAttribArray) + GL_FUNC(glFinish) + GL_FUNC(glFlush) + GL_FUNC(glFramebufferRenderbuffer) + GL_FUNC(glFramebufferTexture2D) + GL_FUNC(glFrontFace) + GL_FUNC(glGenBuffers) + GL_FUNC(glGenerateMipmap) + GL_FUNC(glGenFramebuffers) + GL_FUNC(glGenRenderbuffers) + GL_FUNC(glGenTextures) + GL_FUNC(glGetActiveAttrib) + GL_FUNC(glGetActiveUniform) + GL_FUNC(glGetAttachedShaders) + GL_FUNC(glGetAttribLocation) + GL_FUNC(glGetBooleanv) + GL_FUNC(glGetBufferParameteriv) + GL_FUNC(glGetError) + GL_FUNC(glGetFloatv) + GL_FUNC(glGetFramebufferAttachmentParameteriv) + GL_FUNC(glGetIntegerv) + GL_FUNC(glGetProgramiv) + GL_FUNC(glGetProgramInfoLog) + GL_FUNC(glGetRenderbufferParameteriv) + GL_FUNC(glGetShaderiv) + GL_FUNC(glGetShaderInfoLog) + GL_FUNC(glGetShaderPrecisionFormat) + GL_FUNC(glGetShaderSource) + GL_FUNC(glGetString) + GL_FUNC(glGetTexParameterfv) + GL_FUNC(glGetTexParameteriv) + GL_FUNC(glGetUniformfv) + GL_FUNC(glGetUniformiv) + GL_FUNC(glGetUniformLocation) + GL_FUNC(glGetVertexAttribfv) + GL_FUNC(glGetVertexAttribiv) + GL_FUNC(glGetVertexAttribPointerv) + GL_FUNC(glHint) + GL_FUNC(glIsBuffer) + GL_FUNC(glIsEnabled) + GL_FUNC(glIsFramebuffer) + GL_FUNC(glIsProgram) + GL_FUNC(glIsRenderbuffer) + GL_FUNC(glIsShader) + GL_FUNC(glIsTexture) + GL_FUNC(glLineWidth) + GL_FUNC(glLinkProgram) + GL_FUNC(glPixelStorei) + GL_FUNC(glPolygonOffset) + GL_FUNC(glReadPixels) + GL_FUNC(glReleaseShaderCompiler) + GL_FUNC(glRenderbufferStorage) + GL_FUNC(glSampleCoverage) + GL_FUNC(glScissor) + GL_FUNC(glShaderBinary) + GL_FUNC(glShaderSource) + GL_FUNC(glStencilFunc) + GL_FUNC(glStencilFuncSeparate) + GL_FUNC(glStencilMask) + GL_FUNC(glStencilMaskSeparate) + GL_FUNC(glStencilOp) + GL_FUNC(glStencilOpSeparate) + GL_FUNC(glTexImage2D) + GL_FUNC(glTexParameterf) + GL_FUNC(glTexParameterfv) + GL_FUNC(glTexParameteri) + GL_FUNC(glTexParameteriv) + GL_FUNC(glTexSubImage2D) + GL_FUNC(glUniform1f) + GL_FUNC(glUniform1fv) + GL_FUNC(glUniform1i) + GL_FUNC(glUniform1iv) + GL_FUNC(glUniform2f) + GL_FUNC(glUniform2fv) + GL_FUNC(glUniform2i) + GL_FUNC(glUniform2iv) + GL_FUNC(glUniform3f) + GL_FUNC(glUniform3fv) + GL_FUNC(glUniform3i) + GL_FUNC(glUniform3iv) + GL_FUNC(glUniform4f) + GL_FUNC(glUniform4fv) + GL_FUNC(glUniform4i) + GL_FUNC(glUniform4iv) + GL_FUNC(glUniformMatrix2fv) + GL_FUNC(glUniformMatrix3fv) + GL_FUNC(glUniformMatrix4fv) + GL_FUNC(glUseProgram) + GL_FUNC(glValidateProgram) + GL_FUNC(glVertexAttrib1f) + GL_FUNC(glVertexAttrib1fv) + GL_FUNC(glVertexAttrib2f) + GL_FUNC(glVertexAttrib2fv) + GL_FUNC(glVertexAttrib3f) + GL_FUNC(glVertexAttrib3fv) + GL_FUNC(glVertexAttrib4f) + GL_FUNC(glVertexAttrib4fv) + GL_FUNC(glVertexAttribPointer) + GL_FUNC(glViewport) + GL_FUNC(glGetProgramBinaryOES) + GL_FUNC(glProgramBinaryOES) + GL_FUNC(glMapBufferOES) + GL_FUNC(glUnmapBufferOES) + GL_FUNC(glGetBufferPointervOES) + GL_FUNC(glTexImage3DOES) + GL_FUNC(glTexSubImage3DOES) + GL_FUNC(glCopyTexSubImage3DOES) + GL_FUNC(glCompressedTexImage3DOES) + GL_FUNC(glCompressedTexSubImage3DOES) + GL_FUNC(glFramebufferTexture3DOES) + GL_FUNC(glBindVertexArrayOES) + GL_FUNC(glDeleteVertexArraysOES) + GL_FUNC(glGenVertexArraysOES) + GL_FUNC(glIsVertexArrayOES) + GL_FUNC(glGetPerfMonitorGroupsAMD) + GL_FUNC(glGetPerfMonitorCountersAMD) + GL_FUNC(glGetPerfMonitorGroupStringAMD) + GL_FUNC(glGetPerfMonitorCounterStringAMD) + GL_FUNC(glGetPerfMonitorCounterInfoAMD) + GL_FUNC(glGenPerfMonitorsAMD) + GL_FUNC(glDeletePerfMonitorsAMD) + GL_FUNC(glSelectPerfMonitorCountersAMD) + GL_FUNC(glBeginPerfMonitorAMD) + GL_FUNC(glEndPerfMonitorAMD) + GL_FUNC(glGetPerfMonitorCounterDataAMD) + GL_FUNC(glCopyTextureLevelsAPPLE) + GL_FUNC(glRenderbufferStorageMultisampleAPPLE) + GL_FUNC(glResolveMultisampleFramebufferAPPLE) + GL_FUNC(glFenceSyncAPPLE) + GL_FUNC(glIsSyncAPPLE) + GL_FUNC(glDeleteSyncAPPLE) + GL_FUNC(glClientWaitSyncAPPLE) + GL_FUNC(glWaitSyncAPPLE) + GL_FUNC(glGetInteger64vAPPLE) + GL_FUNC(glGetSyncivAPPLE) + GL_FUNC(glDiscardFramebufferEXT) + GL_FUNC(glMapBufferRangeEXT) + GL_FUNC(glFlushMappedBufferRangeEXT) + GL_FUNC(glMultiDrawArraysEXT) + GL_FUNC(glMultiDrawElementsEXT) + GL_FUNC(glRenderbufferStorageMultisampleEXT) + GL_FUNC(glFramebufferTexture2DMultisampleEXT) + GL_FUNC(glGetGraphicsResetStatusEXT) + GL_FUNC(glReadnPixelsEXT) + GL_FUNC(glGetnUniformfvEXT) + GL_FUNC(glGetnUniformivEXT) + GL_FUNC(glTexStorage1DEXT) + GL_FUNC(glTexStorage2DEXT) + GL_FUNC(glTexStorage3DEXT) + GL_FUNC(glTextureStorage1DEXT) + GL_FUNC(glTextureStorage2DEXT) + GL_FUNC(glTextureStorage3DEXT) + GL_FUNC(glRenderbufferStorageMultisampleIMG) + GL_FUNC(glFramebufferTexture2DMultisampleIMG) + GL_FUNC(glDeleteFencesNV) + GL_FUNC(glGenFencesNV) + GL_FUNC(glIsFenceNV) + GL_FUNC(glTestFenceNV) + GL_FUNC(glGetFenceivNV) + GL_FUNC(glFinishFenceNV) + GL_FUNC(glSetFenceNV) + GL_FUNC(glGetDriverControlsQCOM) + GL_FUNC(glGetDriverControlStringQCOM) + GL_FUNC(glEnableDriverControlQCOM) + GL_FUNC(glDisableDriverControlQCOM) + GL_FUNC(glExtGetTexturesQCOM) + GL_FUNC(glExtGetBuffersQCOM) + GL_FUNC(glExtGetRenderbuffersQCOM) + GL_FUNC(glExtGetFramebuffersQCOM) + GL_FUNC(glExtGetTexLevelParameterivQCOM) + GL_FUNC(glExtTexObjectStateOverrideiQCOM) + GL_FUNC(glExtGetTexSubImageQCOM) + GL_FUNC(glExtGetBufferPointervQCOM) + GL_FUNC(glExtGetShadersQCOM) + GL_FUNC(glExtGetProgramsQCOM) + GL_FUNC(glExtIsProgramBinaryQCOM) + GL_FUNC(glExtGetProgramBinarySourceQCOM) + GL_FUNC(glStartTilingQCOM) + GL_FUNC(glEndTilingQCOM) + GL_FUNC(glEvasGLImageTargetTexture2DOES) + GL_FUNC(glEvasGLImageTargetRenderbufferStorageOES) + GL_FUNC(glBeginQuery) + GL_FUNC(glBeginTransformFeedback) + GL_FUNC(glBindBufferBase) + GL_FUNC(glBindBufferRange) + GL_FUNC(glBindSampler) + GL_FUNC(glBindTransformFeedback) + GL_FUNC(glBindVertexArray) + GL_FUNC(glBlitFramebuffer) + GL_FUNC(glClearBufferfi) + GL_FUNC(glClearBufferfv) + GL_FUNC(glClearBufferiv) + GL_FUNC(glClearBufferuiv) + GL_FUNC(glClientWaitSync) + GL_FUNC(glCompressedTexImage3D) + GL_FUNC(glCompressedTexSubImage3D) + GL_FUNC(glCopyBufferSubData) + GL_FUNC(glCopyTexSubImage3D) + GL_FUNC(glDeleteQueries) + GL_FUNC(glDeleteSamplers) + GL_FUNC(glDeleteSync) + GL_FUNC(glDeleteTransformFeedbacks) + GL_FUNC(glDeleteVertexArrays) + GL_FUNC(glDrawArraysInstanced) + GL_FUNC(glDrawBuffers) + GL_FUNC(glDrawElementsInstanced) + GL_FUNC(glDrawRangeElements) + GL_FUNC(glEndQuery) + GL_FUNC(glEndTransformFeedback) + GL_FUNC(glFenceSync) + GL_FUNC(glFlushMappedBufferRange) + GL_FUNC(glFramebufferTextureLayer) + GL_FUNC(glGenQueries) + GL_FUNC(glGenSamplers) + GL_FUNC(glGenTransformFeedbacks) + GL_FUNC(glGenVertexArrays) + GL_FUNC(glGetActiveUniformBlockiv) + GL_FUNC(glGetActiveUniformBlockName) + GL_FUNC(glGetActiveUniformsiv) + GL_FUNC(glGetBufferParameteri64v) + GL_FUNC(glGetBufferPointerv) + GL_FUNC(glGetFragDataLocation) + GL_FUNC(glGetInteger64i_v) + GL_FUNC(glGetInteger64v) + GL_FUNC(glGetIntegeri_v) + GL_FUNC(glGetInternalformativ) + GL_FUNC(glGetProgramBinary) + GL_FUNC(glGetQueryiv) + GL_FUNC(glGetQueryObjectuiv) + GL_FUNC(glGetSamplerParameterfv) + GL_FUNC(glGetSamplerParameteriv) + GL_FUNC(glGetStringi) + GL_FUNC(glGetSynciv) + GL_FUNC(glGetTransformFeedbackVarying) + GL_FUNC(glGetUniformBlockIndex) + GL_FUNC(glGetUniformIndices) + GL_FUNC(glGetUniformuiv) + GL_FUNC(glGetVertexAttribIiv) + GL_FUNC(glGetVertexAttribIuiv) + GL_FUNC(glInvalidateFramebuffer) + GL_FUNC(glInvalidateSubFramebuffer) + GL_FUNC(glIsQuery) + GL_FUNC(glIsSampler) + GL_FUNC(glIsSync) + GL_FUNC(glIsTransformFeedback) + GL_FUNC(glIsVertexArray) + GL_FUNC(glMapBufferRange) + GL_FUNC(glPauseTransformFeedback) + GL_FUNC(glProgramBinary) + GL_FUNC(glProgramParameteri) + GL_FUNC(glReadBuffer) + GL_FUNC(glRenderbufferStorageMultisample) + GL_FUNC(glResumeTransformFeedback) + GL_FUNC(glSamplerParameterf) + GL_FUNC(glSamplerParameterfv) + GL_FUNC(glSamplerParameteri) + GL_FUNC(glSamplerParameteriv) + GL_FUNC(glTexImage3D) + GL_FUNC(glTexStorage2D) + GL_FUNC(glTexStorage3D) + GL_FUNC(glTexSubImage3D) + GL_FUNC(glTransformFeedbackVaryings) + GL_FUNC(glUniform1ui) + GL_FUNC(glUniform1uiv) + GL_FUNC(glUniform2ui) + GL_FUNC(glUniform2uiv) + GL_FUNC(glUniform3ui) + GL_FUNC(glUniform3uiv) + GL_FUNC(glUniform4ui) + GL_FUNC(glUniform4uiv) + GL_FUNC(glUniformBlockBinding) + GL_FUNC(glUniformMatrix2x3fv) + GL_FUNC(glUniformMatrix3x2fv) + GL_FUNC(glUniformMatrix2x4fv) + GL_FUNC(glUniformMatrix4x2fv) + GL_FUNC(glUniformMatrix3x4fv) + GL_FUNC(glUniformMatrix4x3fv) + GL_FUNC(glUnmapBuffer) + GL_FUNC(glVertexAttribDivisor) + GL_FUNC(glVertexAttribI4i) + GL_FUNC(glVertexAttribI4iv) + GL_FUNC(glVertexAttribI4ui) + GL_FUNC(glVertexAttribI4uiv) + GL_FUNC(glVertexAttribIPointer) + GL_FUNC(glWaitSync) + GL_FUNC(glDispatchCompute) + GL_FUNC(glDispatchComputeIndirect) + GL_FUNC(glDrawArraysIndirect) + GL_FUNC(glDrawElementsIndirect) + GL_FUNC(glFramebufferParameteri) + GL_FUNC(glGetFramebufferParameteriv) + GL_FUNC(glGetProgramInterfaceiv) + GL_FUNC(glGetProgramResourceIndex) + GL_FUNC(glGetProgramResourceName) + GL_FUNC(glGetProgramResourceiv) + GL_FUNC(glGetProgramResourceLocation) + GL_FUNC(glUseProgramStages) + GL_FUNC(glActiveShaderProgram) + GL_FUNC(glCreateShaderProgramv) + GL_FUNC(glBindProgramPipeline) + GL_FUNC(glDeleteProgramPipelines) + GL_FUNC(glGenProgramPipelines) + GL_FUNC(glIsProgramPipeline) + GL_FUNC(glGetProgramPipelineiv) + GL_FUNC(glProgramUniform1i) + GL_FUNC(glProgramUniform2i) + GL_FUNC(glProgramUniform3i) + GL_FUNC(glProgramUniform4i) + GL_FUNC(glProgramUniform1ui) + GL_FUNC(glProgramUniform2ui) + GL_FUNC(glProgramUniform3ui) + GL_FUNC(glProgramUniform4ui) + GL_FUNC(glProgramUniform1f) + GL_FUNC(glProgramUniform2f) + GL_FUNC(glProgramUniform3f) + GL_FUNC(glProgramUniform4f) + GL_FUNC(glProgramUniform1iv) + GL_FUNC(glProgramUniform2iv) + GL_FUNC(glProgramUniform3iv) + GL_FUNC(glProgramUniform4iv) + GL_FUNC(glProgramUniform1uiv) + GL_FUNC(glProgramUniform2uiv) + GL_FUNC(glProgramUniform3uiv) + GL_FUNC(glProgramUniform4uiv) + GL_FUNC(glProgramUniform1fv) + GL_FUNC(glProgramUniform2fv) + GL_FUNC(glProgramUniform3fv) + GL_FUNC(glProgramUniform4fv) + GL_FUNC(glProgramUniformMatrix2fv) + GL_FUNC(glProgramUniformMatrix3fv) + GL_FUNC(glProgramUniformMatrix4fv) + GL_FUNC(glProgramUniformMatrix2x3fv) + GL_FUNC(glProgramUniformMatrix3x2fv) + GL_FUNC(glProgramUniformMatrix2x4fv) + GL_FUNC(glProgramUniformMatrix4x2fv) + GL_FUNC(glProgramUniformMatrix3x4fv) + GL_FUNC(glProgramUniformMatrix4x3fv) + GL_FUNC(glValidateProgramPipeline) + GL_FUNC(glGetProgramPipelineInfoLog) + GL_FUNC(glBindImageTexture) + GL_FUNC(glGetBooleani_v) + GL_FUNC(glMemoryBarrier) + GL_FUNC(glMemoryBarrierByRegion) + GL_FUNC(glTexStorage2DMultisample) + GL_FUNC(glGetMultisamplefv) + GL_FUNC(glSampleMaski) + GL_FUNC(glGetTexLevelParameteriv) + GL_FUNC(glGetTexLevelParameterfv) + GL_FUNC(glBindVertexBuffer) + GL_FUNC(glVertexAttribFormat) + GL_FUNC(glVertexAttribIFormat) + GL_FUNC(glVertexAttribBinding) + GL_FUNC(glVertexBindingDivisor) + GL_FUNC(glBlendBarrier) + GL_FUNC(glCopyImageSubData) + GL_FUNC(glDebugMessageControl) + GL_FUNC(glDebugMessageInsert) + GL_FUNC(glDebugMessageCallback) + GL_FUNC(glGetDebugMessageLog) + GL_FUNC(glPushDebugGroup) + GL_FUNC(glPopDebugGroup) + GL_FUNC(glObjectLabel) + GL_FUNC(glGetObjectLabel) + GL_FUNC(glObjectPtrLabel) + GL_FUNC(glGetObjectPtrLabel) + GL_FUNC(glGetPointerv) + GL_FUNC(glEnablei) + GL_FUNC(glDisablei) + GL_FUNC(glBlendEquationi) + GL_FUNC(glBlendEquationSeparatei) + GL_FUNC(glBlendFunci) + GL_FUNC(glBlendFuncSeparatei) + GL_FUNC(glColorMaski) + GL_FUNC(glIsEnabledi) + GL_FUNC(glDrawElementsBaseVertex) + GL_FUNC(glDrawRangeElementsBaseVertex) + GL_FUNC(glDrawElementsInstancedBaseVertex) + GL_FUNC(glFramebufferTexture) + GL_FUNC(glPrimitiveBoundingBox) + GL_FUNC(glGetGraphicsResetStatus) + GL_FUNC(glReadnPixels) + GL_FUNC(glGetnUniformfv) + GL_FUNC(glGetnUniformiv) + GL_FUNC(glGetnUniformuiv) + GL_FUNC(glMinSampleShading) + GL_FUNC(glPatchParameteri) + GL_FUNC(glTexParameterIiv) + GL_FUNC(glTexParameterIuiv) + GL_FUNC(glGetTexParameterIiv) + GL_FUNC(glGetTexParameterIuiv) + GL_FUNC(glSamplerParameterIiv) + GL_FUNC(glSamplerParameterIuiv) + GL_FUNC(glGetSamplerParameterIiv) + GL_FUNC(glGetSamplerParameterIuiv) + GL_FUNC(glTexBuffer) + GL_FUNC(glTexBufferRange) + GL_FUNC(glTexStorage3DMultisample) + FT_LOGD("Could not resolve: %s", name); + return nullptr; +} +#undef GL_FUNC + +bool TizenRenderer::InitializeRenderer(int32_t x, int32_t y, int32_t w, + int32_t h) { + if (!SetupEvasGL(x, y, w, h)) { + FT_LOGE("SetupEvasGL fail"); + return false; + } + Show(); + is_valid_ = true; + return true; +} + +bool TizenRenderer::IsValid() { return is_valid_; } + +void TizenRenderer::flush() { glFlush(); } + +bool TizenRenderer::SetupEvasGL(int32_t x, int32_t y, int32_t w, int32_t h) { + evas_gl_ = evas_gl_new( + evas_object_evas_get((Evas_Object*)SetupEvasWindow(x, y, w, h))); + + if (!evas_gl_) { + FT_LOGE("SetupEvasWindow fail"); + return false; + } + + g_evas_gl = evas_gl_; + gl_config_ = evas_gl_config_new(); + gl_config_->color_format = EVAS_GL_RGBA_8888; + gl_config_->depth_bits = EVAS_GL_DEPTH_NONE; + gl_config_->stencil_bits = EVAS_GL_STENCIL_NONE; +#define EVAS_GL_OPTIONS_DIRECT_MEMORY_OPTIMIZE (1 << 12) +#define EVAS_GL_OPTIONS_DIRECT_OVERRIDE (1 << 13) + gl_config_->options_bits = (Evas_GL_Options_Bits)( + EVAS_GL_OPTIONS_DIRECT | EVAS_GL_OPTIONS_DIRECT_MEMORY_OPTIMIZE | + EVAS_GL_OPTIONS_DIRECT_OVERRIDE | EVAS_GL_OPTIONS_CLIENT_SIDE_ROTATION); + + gl_context_ = + evas_gl_context_version_create(evas_gl_, NULL, EVAS_GL_GLES_3_X); + gl_resource_context_ = + evas_gl_context_version_create(evas_gl_, gl_context_, EVAS_GL_GLES_3_X); + + if (gl_context_ == nullptr) { + FT_LOGW( + "Failed to create evas gl context with EVAS_GL_GLES_3_X, try to use " + "EVAS_GL_GLES_2_X,"); + gl_context_ = + evas_gl_context_version_create(evas_gl_, NULL, EVAS_GL_GLES_2_X); + gl_resource_context_ = + evas_gl_context_version_create(evas_gl_, gl_context_, EVAS_GL_GLES_2_X); + } + if (gl_context_ == nullptr) { + FT_LOGE("Failed to create evas gl context!"); + FT_RELEASE_ASSERT_NOT_REACHED(); + } + + EVAS_GL_GLOBAL_GLES3_USE(g_evas_gl, gl_context_); + gl_surface_ = evas_gl_surface_create(evas_gl_, gl_config_, w, h); + + gl_resource_surface_ = + evas_gl_pbuffer_surface_create(evas_gl_, gl_config_, w, h, NULL); + + Evas_Native_Surface ns; + evas_gl_native_surface_get(evas_gl_, gl_surface_, &ns); + evas_object_image_native_surface_set((Evas_Object*)GetImageHandle(), &ns); + + return true; +} + +void TizenRenderer::DestoryRenderer() { + DestoryEvasGL(); + DestoryEvasWindow(); +} + +void TizenRenderer::DestoryEvasGL() { + evas_gl_surface_destroy(evas_gl_, gl_surface_); + evas_gl_surface_destroy(evas_gl_, gl_resource_surface_); + + evas_gl_context_destroy(evas_gl_, gl_context_); + evas_gl_context_destroy(evas_gl_, gl_resource_context_); + + evas_gl_config_free(gl_config_); + evas_gl_free(evas_gl_); +} + +#endif diff --git a/shell/platform/tizen/tizen_renderer.h b/shell/platform/tizen/tizen_renderer.h index d4cddfe4a2b4d..c6f43e4923575 100644 --- a/shell/platform/tizen/tizen_renderer.h +++ b/shell/platform/tizen/tizen_renderer.h @@ -5,7 +5,13 @@ #ifndef EMBEDDER_TIZEN_RENDERER_H #define EMBEDDER_TIZEN_RENDERER_H +#ifdef FLUTTER_TIZEN_EVASGL +#undef EFL_BETA_API_SUPPORT +#include +#include +#else #include +#endif class TizenRenderer { public: @@ -20,12 +26,17 @@ class TizenRenderer { TizenRenderer(TizenRenderer::Delegate& deleget); virtual ~TizenRenderer(); + +#ifdef FLUTTER_TIZEN_EVASGL + void ClearColor(float r, float g, float b, float a); +#endif bool OnMakeCurrent(); bool OnClearCurrent(); bool OnMakeResourceCurrent(); bool OnPresent(); uint32_t OnGetFBO(); void* OnProcResolver(const char* name); + void flush(); virtual TizenWindowGeometry GetGeometry() = 0; bool IsValid(); virtual void Show() = 0; @@ -38,30 +49,55 @@ class TizenRenderer { bool received_rotation{false}; TizenRenderer::Delegate& delegate_; bool InitializeRenderer(int32_t x, int32_t y, int32_t w, int32_t h); +#ifndef FLUTTER_TIZEN_EVASGL virtual bool SetupDisplay() = 0; virtual bool SetupEcoreWlWindow(int32_t x, int32_t y, int32_t w, int32_t h) = 0; virtual bool SetupEglWindow(int32_t w, int32_t h) = 0; - bool SetupEglSurface(); virtual EGLDisplay GetEGLDisplay() = 0; virtual EGLNativeWindowType GetEGLNativeWindowType() = 0; - void DestoryRenderer(); - void DestoryEglSurface(); virtual void DestoryEglWindow() = 0; virtual void DestoryEcoreWlWindow() = 0; virtual void ShutdownDisplay() = 0; + + void DestoryEglSurface(); + bool SetupEglSurface(); +#else + virtual void* SetupEvasWindow(int32_t x, int32_t y, int32_t w, int32_t h) = 0; + virtual void DestoryEvasWindow() = 0; + + public: + virtual void* GetImageHandle() = 0; + + protected: + bool SetupEvasGL(int32_t x, int32_t y, int32_t w, int32_t h); + void DestoryEvasGL(); +#endif + void DestoryRenderer(); virtual void SendRotationChangeDone() = 0; private: bool is_valid_ = false; +#ifdef FLUTTER_TIZEN_EVASGL + Evas_GL_Config* gl_config_; + Evas_GL* evas_gl_{nullptr}; + + Evas_GL_Context* gl_context_; + Evas_GL_Context* gl_resource_context_; + + Evas_GL_Surface* gl_surface_{nullptr}; + Evas_GL_Surface* gl_resource_surface_{nullptr}; + + bool ChooseEGLConfiguration(); + void PrintEGLError(); +#else EGLConfig egl_config_; EGLDisplay egl_display_ = EGL_NO_DISPLAY; EGLContext egl_context_ = EGL_NO_CONTEXT; EGLSurface egl_surface_ = EGL_NO_SURFACE; EGLContext egl_resource_context_ = EGL_NO_CONTEXT; EGLSurface egl_resource_surface_ = EGL_NO_SURFACE; - bool ChooseEGLConfiguration(); - void PrintEGLError(); +#endif }; #endif // EMBEDDER_TIZEN_RENDERER_H diff --git a/shell/platform/tizen/tizen_renderer_evas_gl.cc b/shell/platform/tizen/tizen_renderer_evas_gl.cc new file mode 100644 index 0000000000000..902eb600ec91d --- /dev/null +++ b/shell/platform/tizen/tizen_renderer_evas_gl.cc @@ -0,0 +1,102 @@ +// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "tizen_renderer_evas_gl.h" + +#include "flutter/shell/platform/tizen/tizen_log.h" + +TizenRendererEvasGL::TizenRendererEvasGL(TizenRenderer::Delegate& delegate, + int32_t x, int32_t y, int32_t w, + int32_t h) + : TizenRenderer(delegate) { + InitializeRenderer(x, y, w, h); +} + +TizenRendererEvasGL::~TizenRendererEvasGL() { DestoryRenderer(); } + +void* TizenRendererEvasGL::SetupEvasWindow(int32_t x, int32_t y, int32_t w, + int32_t h) { + if (w == 0 || h == 0) { + FT_LOGE("Failed to create because of the wrong size"); + return nullptr; + } + elm_config_accel_preference_set("hw:opengl"); + + evas_window_ = elm_win_add(NULL, NULL, ELM_WIN_BASIC); + elm_win_alpha_set(evas_window_, EINA_FALSE); + elm_win_aux_hint_add(evas_window_, "wm.policy.win.user.geometry", "1"); + evas_object_move(evas_window_, x, y); + evas_object_resize(evas_window_, w, h); + evas_object_raise(evas_window_); + + Evas_Object* bg = elm_bg_add(evas_window_); + evas_object_color_set(bg, 0x00, 0x00, 0x00, 0x00); + + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(evas_window_, bg); + + graphics_adapter_ = + evas_object_image_filled_add(evas_object_evas_get(evas_window_)); + evas_object_resize(graphics_adapter_, w, h); + evas_object_move(graphics_adapter_, x, y); + evas_object_image_size_set(graphics_adapter_, w, h); + evas_object_image_alpha_set(graphics_adapter_, EINA_TRUE); + elm_win_resize_object_add(evas_window_, graphics_adapter_); + + int rotations[4] = {0, 90, 180, 270}; + elm_win_wm_rotation_available_rotations_set(evas_window_, + (const int*)(&rotations), 4); + evas_object_smart_callback_add(evas_window_, "rotation,changed", + RotationEventCb, this); + return (void*)evas_window_; +} + +void TizenRendererEvasGL::RotationEventCb(void* data, Evas_Object* obj, + void* event_info) { + auto* self = reinterpret_cast(data); + // TODO : Use current window rotation degree + FT_UNIMPLEMENTED(); + self->delegate_.OnRotationChange(0); +} + +void TizenRendererEvasGL::Show() { + evas_object_show((Evas_Object*)GetImageHandle()); + evas_object_show(evas_window_); +} + +void TizenRendererEvasGL::SetRotate(int angle) { + elm_win_rotation_set(evas_window_, angle); + received_rotation = true; +} + +void* TizenRendererEvasGL::GetImageHandle() { return (void*)graphics_adapter_; } + +void TizenRendererEvasGL::ResizeWithRotation(int32_t x, int32_t y, + int32_t width, int32_t height, + int32_t angle) { + evas_object_move(evas_window_, x, y); + evas_object_resize(evas_window_, width, height); + SetRotate(angle); +} + +void TizenRendererEvasGL::SendRotationChangeDone() { + elm_win_wm_rotation_manual_rotation_done(evas_window_); +} + +void TizenRendererEvasGL::DestoryEvasWindow() { + evas_object_del(evas_window_); + evas_object_del(graphics_adapter_); +} + +TizenRenderer::TizenWindowGeometry TizenRendererEvasGL::GetGeometry() { + TizenWindowGeometry result; + evas_object_geometry_get(evas_window_, &result.x, &result.y, &result.w, + &result.h); + return result; +} + +int TizenRendererEvasGL::GetEcoreWindowId() { + return (int)ecore_evas_window_get( + ecore_evas_ecore_evas_get(evas_object_evas_get(graphics_adapter_))); +} diff --git a/shell/platform/tizen/tizen_renderer_evas_gl.h b/shell/platform/tizen/tizen_renderer_evas_gl.h new file mode 100644 index 0000000000000..a47347375430f --- /dev/null +++ b/shell/platform/tizen/tizen_renderer_evas_gl.h @@ -0,0 +1,38 @@ +// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EMBEDDER_TIZEN_RENDERER_EVAS_GL_H +#define EMBEDDER_TIZEN_RENDERER_EVAS_GL_H + +#include +#include + +#include "tizen_renderer.h" + +class TizenRendererEvasGL : public TizenRenderer { + public: + TizenRendererEvasGL(TizenRenderer::Delegate& delegate, int32_t x, int32_t y, + int32_t w, int32_t h); + ~TizenRendererEvasGL(); + TizenWindowGeometry GetGeometry() override; + int GetEcoreWindowId() override; + void ResizeWithRotation(int32_t x, int32_t y, int32_t width, int32_t height, + int32_t angle) override; + void Show() override; + void SetRotate(int angle) override; + + void* GetImageHandle() override; + + protected: + virtual void* SetupEvasWindow(int32_t x, int32_t y, int32_t w, + int32_t h) override; + virtual void DestoryEvasWindow() override; + void SendRotationChangeDone() override; + + private: + Evas_Object* evas_window_{nullptr}; + Evas_Object* graphics_adapter_{nullptr}; + static void RotationEventCb(void* data, Evas_Object* obj, void* event_info); +}; +#endif // EMBEDDER_TIZEN_RENDERER_ECORE_WL2_H