Introduce E_Surface_Fps_Tracker 94/320494/1
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 6 Feb 2025 03:06:26 +0000 (12:06 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Tue, 4 Mar 2025 08:08:34 +0000 (17:08 +0900)
E_Surface_Fps_Tracker is responsible for tracking fps of surface
whenever a client commits a new buffer to the surface.

The purpose of the patch is to separate the implementation about fps
tracking out from e_client. Therefore, it will make e_client_fps APIs
deprecated in the next comming patch.

Change-Id: Iaad54325fc206ba6de609e6ff5b66df73acf0659

src/bin/Makefile.mk
src/bin/debug/e_info_server.c
src/bin/server/e_surface_fps_tracker.c [new file with mode: 0644]
src/bin/server/e_surface_fps_tracker_intern.h [new file with mode: 0644]

index bc306b30414f49c3d661c0c5febcdec46b541b70..7782e71e61baa422278b40a625c38ca997ce7674 100644 (file)
@@ -204,6 +204,7 @@ src/bin/server/e_tizen_indicator.c \
 src/bin/server/e_tizen_clipboard.c \
 src/bin/server/e_surface_view.c \
 src/bin/server/e_seat.c \
+src/bin/server/e_surface_fps_tracker.c \
 src/bin/windowmgr/services/e_service_gesture.c \
 src/bin/windowmgr/services/e_service_lockscreen.c \
 src/bin/windowmgr/services/e_service_quickpanel.c \
index 77b53b7deadded74421fcbf07e7f6ae5ac8c7c63..4f2de898d82649e32cfe2e866e37b2d18f356f47 100644 (file)
@@ -47,6 +47,8 @@
 #include "e_view_client_intern.h"
 #include "e_blur_intern.h"
 #include "e_blur_video_capture_intern.h"
+#include "e_compositor_intern.h"
+#include "e_surface_fps_tracker_intern.h"
 
 #include <tbm_bufmgr.h>
 #include <tbm_debug.h>
@@ -4614,35 +4616,15 @@ e_info_server_cb_exsync_trace_message(const Eldbus_Service_Interface *iface EINA
    return reply;
 }
 
-static E_Client *
-_e_info_server_find_client_by_win_id(uint64_t win_id)
-{
-   Ecore_Window win;
-   Evas_Object *o;
-   E_Client *ec;
-
-   for (o = evas_object_top_get(e_comp_evas_get()); o; o = evas_object_below_get(o))
-     {
-        ec = evas_object_data_get(o, "E_Client");
-        if (!ec) continue;
-
-        win = e_client_util_win_get(ec);
-        if (win == win_id)
-          return ec;
-     }
-
-   return NULL;
-}
-
 static void
-_msg_client_fps_append(Eldbus_Message_Iter *iter, E_Client *ec)
+_msg_client_fps_append(Eldbus_Message_Iter *iter, E_Surface_Fps_Tracker *tracker, struct wl_resource *surface_resource)
 {
    Eldbus_Message_Iter *array_of_fps, *struct_of_fps;
    double fps = 0.0;
 
    eldbus_message_iter_arguments_append(iter, "a("VALUE_TYPE_FOR_FPS")", &array_of_fps);
 
-   if (e_client_fps_get(ec, &fps))
+   if (e_surface_fps_tracker_fps_get(tracker, &fps))
      {
         eldbus_message_iter_arguments_append(array_of_fps, "("VALUE_TYPE_FOR_FPS")", &struct_of_fps);
         eldbus_message_iter_arguments_append(struct_of_fps,
@@ -4650,7 +4632,7 @@ _msg_client_fps_append(Eldbus_Message_Iter *iter, E_Client *ec)
                                             E_INFO_FPS_TYPE_CLIENT_WIN,
                                             "none",
                                             -999,
-                                            e_client_util_win_get(ec),
+                                            surface_resource,
                                             fps);
         eldbus_message_iter_container_close(array_of_fps, struct_of_fps);
      }
@@ -4729,9 +4711,10 @@ static Eldbus_Message *
 _e_info_server_cb_fps_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
 {
    const char *win_str;
-   uint64_t win_id = 0;
-   unsigned long tmp;
-   E_Client *ec;
+   struct wl_resource *surface_resource;
+   unsigned long surface_resource_ptr;
+   E_Surface *surface;
+   E_Surface_Fps_Tracker *tracker;
    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
 
    if (!eldbus_message_arguments_get(msg, "s", &win_str))
@@ -4742,16 +4725,16 @@ _e_info_server_cb_fps_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED
 
    if (e_util_strcmp(win_str, "none"))
      {
-        if (!e_util_string_to_ulong(win_str, &tmp, 16))
+        if (!e_util_string_to_ulong(win_str, &surface_resource_ptr, 16))
           return reply;
 
-        win_id = (uint64_t)tmp;
-
-        ec = _e_info_server_find_client_by_win_id(win_id);
-        if (!ec) return reply;
-
-        e_client_fps_enable(ec, EINA_TRUE);
-        _msg_client_fps_append(eldbus_message_iter_get(reply), ec);
+        surface_resource = (struct wl_resource *)surface_resource_ptr;
+        surface = e_compositor_surface_find_by_resource(surface_resource);
+        if (surface)
+          {
+             tracker = e_surface_fps_tracker_get_or_create(surface);
+             _msg_client_fps_append(eldbus_message_iter_get(reply), tracker, surface_resource);
+          }
      }
    else
      {
diff --git a/src/bin/server/e_surface_fps_tracker.c b/src/bin/server/e_surface_fps_tracker.c
new file mode 100644 (file)
index 0000000..513aa42
--- /dev/null
@@ -0,0 +1,127 @@
+#include "e_surface_fps_tracker_intern.h"
+#include "e_compositor_private.h"
+
+#include <stdlib.h>
+#include <wayland-util.h>
+
+struct _E_Surface_Fps_Tracker
+{
+   double               fps;
+   double               old_fps;
+   double               frametime;
+   double               time;
+   double               lapse;
+   int                  cframes;
+   int                  flapse;
+
+   struct wl_listener surface_destroy;
+   struct wl_listener commit;
+};
+
+static void
+_tracker_cb_surface_destroy(struct wl_listener *listener, void *data)
+{
+   E_Surface_Fps_Tracker *tracker = wl_container_of(listener, tracker, surface_destroy);
+
+   wl_list_remove(&tracker->surface_destroy.link);
+   wl_list_remove(&tracker->commit.link);
+   free(tracker);
+}
+
+static E_Surface_Fps_Tracker *
+_tracker_try_from_surface(E_Surface *surface)
+{
+   E_Surface_Fps_Tracker *tracker;
+   struct wl_listener *listener;
+
+   listener = e_surface_destroy_listener_get(surface, _tracker_cb_surface_destroy);
+   if (!listener)
+     return NULL;
+
+   return wl_container_of(listener, tracker, surface_destroy);
+}
+
+static void
+_tracker_fps_update(E_Surface_Fps_Tracker *tracker)
+{
+   double dt;
+   double tim;
+
+   tim = ecore_time_get();
+
+   dt = tim - tracker->frametime;
+
+   tracker->frametime = tim;
+   tracker->time += dt;
+   tracker->cframes++;
+
+   if (tracker->lapse == 0.0)
+     {
+        tracker->lapse = tim;
+        tracker->flapse = tracker->cframes;
+     }
+   else if ((tim - tracker->lapse) >= 0.5)
+     {
+        tracker->fps = (tracker->cframes - tracker->flapse) /
+           (tim - tracker->lapse);
+        tracker->lapse = tim;
+        tracker->flapse = tracker->cframes;
+        tracker->time = 0.0;
+     }
+}
+
+static void
+_tracker_cb_commit(struct wl_listener *listener, void *data)
+{
+   E_Surface_Fps_Tracker *tracker = wl_container_of(listener, tracker, commit);
+   E_Surface_Event_Commit *event = data;
+
+   if (event->committed & E_SURFACE_STATE_BUFFER)
+     _tracker_fps_update(tracker);
+}
+
+static E_Surface_Fps_Tracker *
+_tracker_create(E_Surface *surface)
+{
+   E_Surface_Fps_Tracker *tracker;
+
+   tracker = calloc(1, sizeof(*tracker));
+   if (!tracker)
+     return NULL;
+
+   tracker->surface_destroy.notify = _tracker_cb_surface_destroy;
+   e_surface_destroy_listener_add(surface, &tracker->surface_destroy);
+
+   tracker->commit.notify = _tracker_cb_commit;
+   e_surface_commit_listener_add(surface, &tracker->commit);
+
+   return tracker;
+}
+
+EINTERN E_Surface_Fps_Tracker *
+e_surface_fps_tracker_get_or_create(E_Surface *surface)
+{
+   E_Surface_Fps_Tracker *tracker;
+
+   tracker = _tracker_try_from_surface(surface);
+   if (tracker)
+     return tracker;
+
+   return _tracker_create(surface);
+}
+
+EINTERN Eina_Bool
+e_surface_fps_tracker_fps_get(E_Surface_Fps_Tracker *tracker, double *fps)
+{
+   if (tracker->old_fps == tracker->fps)
+     return EINA_FALSE;
+
+   if (tracker->fps > 0.0)
+     {
+        *fps = tracker->fps;
+        tracker->old_fps = tracker->fps;
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
diff --git a/src/bin/server/e_surface_fps_tracker_intern.h b/src/bin/server/e_surface_fps_tracker_intern.h
new file mode 100644 (file)
index 0000000..2bfaf0f
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef E_SURFACE_FPS_TRACKER_INTERN_H
+#define E_SURFACE_FPS_TRACKER_INTERN_H
+
+#include <wayland-server.h>
+#include <Eina.h>
+
+#include "e_compositor_intern.h"
+
+typedef struct _E_Surface_Fps_Tracker E_Surface_Fps_Tracker;
+
+/**
+ * Creates or retrieves an existing E_Surface_Fps_Tracker instance associated
+ * with the given surface.
+ */
+E_Surface_Fps_Tracker *e_surface_fps_tracker_get_or_create(E_Surface *surface);
+
+/**
+ * Gets the most recently calculated FPS value.
+ *
+ * The FPS value is calculated based on the time an associated surface submits
+ * new buffer and commits it.
+ */
+Eina_Bool e_surface_fps_tracker_fps_get(E_Surface_Fps_Tracker *tracker, double *fps);
+
+#endif