*/
#include <glib.h>
+#include <unistd.h>
#include <hal/hal-power.h>
#include <util/log.h>
#include <util/resource.h>
#include <util/gdbus-util.h>
+#include <util/thread.h>
#include <resource-monitor/resource-monitor.h>
#define DBUS_ENLIGHTENMENT_INTERFACE "org.enlightenment.wm.info"
#define DBUS_ENLIGHTENMENT_FPS_FUNC "get_fps_info"
+#define DISPLAY_SAMPLE_RATE_MSEC 1000
+
struct display_context {
char *device_name;
int index;
double fps;
};
-static int display_get_fps(struct resource *res,
- const struct resource_attribute *attr,
- void *data)
+struct display_fps_monitor {
+ int holder;
+ int resource_count;
+ double *last_fps;
+ struct thread *thread;
+ GMutex display_lock;
+};
+
+static struct display_fps_monitor g_fps_monitor;
+
+static int display_read_fps(int resource_index)
{
- struct display_context *ctx;
+ int ret = 0;
GDBusConnection *conn;
GDBusMessage *msg, *reply;
GVariant *result, *value;
GError *err = NULL;
struct display_fps_data fps_data;
- double *fps = (double *)data;
- int ret = 0;
-
- if (!res || !attr || !data)
- return -EINVAL;
-
- ctx = get_resource_privdata(res);
- if (!ctx)
- return -EINVAL;
-
- if (!ctx->device_name) {
- _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n",
- get_resource_name(res));
- return -EINVAL;
- }
/* Connect dbus interface and receive message */
conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
}
/* Get the fps information according to the index of resource_device */
- value = g_variant_get_child_value(result, ctx->index);
+ value = g_variant_get_child_value(result, resource_index);
g_variant_get(value, "(usiud)",
&fps_data.type, fps_data.output, &fps_data.zpos,
&fps_data.window, &fps_data.fps);
out:
- *fps = fps_data.fps;
+ __atomic_store((&g_fps_monitor.last_fps[resource_index]),
+ &fps_data.fps, __ATOMIC_RELEASE);
err_reply:
g_object_unref(reply);
return ret;
}
+static int display_get_fps(struct resource *res,
+ const struct resource_attribute *attr,
+ void *data)
+{
+ struct display_context *ctx;
+ double *fps = (double *)data;
+
+ if (!res || !attr || !data)
+ return -EINVAL;
+
+ ctx = get_resource_privdata(res);
+ if (!ctx)
+ return -EINVAL;
+
+ if (!ctx->device_name) {
+ _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n",
+ get_resource_name(res));
+ return -EINVAL;
+ }
+
+ __atomic_load(&g_fps_monitor.last_fps[ctx->index], fps, __ATOMIC_ACQUIRE);
+
+ return 0;
+}
+
static int display_get_name(struct resource *res,
const struct resource_attribute *attr,
void *data)
},
};
+static int display_monitor_func(void *data, void **result)
+{
+ int i;
+
+ for (i = 0; i < g_fps_monitor.resource_count; i++)
+ display_read_fps(i);
+
+ return THREAD_RETURN_CONTINUE;
+}
+
+static int init_display_monitor_thread(struct resource *res)
+{
+ int ret;
+
+ g_fps_monitor.resource_count = get_resource_device_count(get_resource_type(res));
+ g_fps_monitor.last_fps = calloc(g_fps_monitor.resource_count, sizeof(double));
+ if (!g_fps_monitor.last_fps)
+ return -ENOMEM;
+
+ ret = create_timer_thread(&g_fps_monitor.thread, DISPLAY_SAMPLE_RATE_MSEC,
+ display_monitor_func, NULL);
+
+ return ret;
+}
+
+static void __DESTRUCTOR__ exit_display_monitor_thread(void)
+{
+ if (g_fps_monitor.thread != NULL) {
+ destroy_thread(g_fps_monitor.thread);
+ g_fps_monitor.thread = NULL;
+ }
+
+ if (g_fps_monitor.last_fps) {
+ free(g_fps_monitor.last_fps);
+ g_fps_monitor.last_fps = NULL;
+ }
+
+ g_fps_monitor.resource_count = 0;
+}
+
static int display_init(struct resource *res)
{
+ int ret = 0;
struct display_context *ctx;
ctx = calloc(1, sizeof(struct display_context));
set_resource_privdata(res, ctx);
- return 0;
+ g_mutex_lock(&g_fps_monitor.display_lock);
+ if (g_fps_monitor.holder++ == 0) {
+ if (!g_fps_monitor.thread)
+ ret = init_display_monitor_thread(res);
+ else
+ resume_thread(g_fps_monitor.thread);
+ }
+ g_mutex_unlock(&g_fps_monitor.display_lock);
+
+ return ret;
}
static void display_exit(struct resource *res)
free(ctx);
set_resource_privdata(res, NULL);
+
+ g_mutex_lock(&g_fps_monitor.display_lock);
+ if (--g_fps_monitor.holder == 0 && g_fps_monitor.thread != NULL)
+ suspend_thread(g_fps_monitor.thread);
+ g_mutex_unlock(&g_fps_monitor.display_lock);
}
static const struct resource_driver display_resource_driver = {