2 * PASS (Power Aware System Service) - Display Resource Driver
4 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 * @file resource-display.c
28 #include <util/common.h>
29 #include <util/devices.h>
31 #include <util/gdbus-util.h>
32 #include <util/thread.h>
34 #include <libsyscommon/resource-manager.h>
35 #include <libsyscommon/resource-type.h>
36 #include <libsyscommon/resource-device.h>
38 #include <resource-monitor/resource-monitor.h>
40 #define DBUS_ENLIGHTENMENT_NAME "org.enlightenment.wm"
41 #define DBUS_ENLIGHTENMENT_PATH "/org/enlightenment/wm"
42 #define DBUS_ENLIGHTENMENT_INTERFACE "org.enlightenment.wm.info"
43 #define DBUS_ENLIGHTENMENT_FPS_FUNC "get_fps_info"
45 #define DISPLAY_SAMPLE_RATE_MSEC 1000
47 struct display_context {
52 struct display_fps_data {
60 struct display_fps_monitor {
64 struct thread *thread;
68 static struct display_fps_monitor g_fps_monitor;
70 static int display_read_fps(int resource_index)
73 GDBusConnection *conn;
74 GDBusMessage *msg, *reply;
75 GVariant *result, *value;
77 struct display_fps_data fps_data;
79 /* Connect dbus interface and receive message */
80 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
86 msg = g_dbus_message_new_method_call(DBUS_ENLIGHTENMENT_NAME,
87 DBUS_ENLIGHTENMENT_PATH,
88 DBUS_ENLIGHTENMENT_INTERFACE,
89 DBUS_ENLIGHTENMENT_FPS_FUNC);
95 reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
96 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
97 G_MAXINT, NULL, NULL, &err);
104 if (g_dbus_message_get_message_type(reply) == G_DBUS_MESSAGE_TYPE_ERROR) {
109 /* Parse the received data */
110 result = g_variant_get_child_value(g_dbus_message_get_body(reply), 0);
111 if (g_variant_n_children(result) == 0) {
116 /* Get the fps information according to the index of resource_device */
117 value = g_variant_get_child_value(result, resource_index);
118 g_variant_get(value, "(usiud)",
119 &fps_data.type, fps_data.output, &fps_data.zpos,
120 &fps_data.window, &fps_data.fps);
123 __atomic_store((&g_fps_monitor.last_fps[resource_index]),
124 &fps_data.fps, __ATOMIC_RELEASE);
127 g_object_unref(reply);
131 g_dbus_connection_flush(conn, NULL, NULL, NULL);
136 static int display_get_fps(struct syscommon_resman_resource *res,
137 const struct syscommon_resman_resource_attribute *attr,
140 struct display_context *ctx;
141 double *fps = (double *)data;
143 if (!res || !attr || !data)
146 ctx = syscommon_resman_get_resource_privdata(res);
150 if (!ctx->device_name) {
151 _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n",
152 syscommon_resman_get_resource_name(res));
156 __atomic_load(&g_fps_monitor.last_fps[ctx->index], fps, __ATOMIC_ACQUIRE);
161 static int display_get_name(struct syscommon_resman_resource *res,
162 const struct syscommon_resman_resource_attribute *attr,
165 struct display_context *ctx;
166 char *buf = (char *)data;
168 if (!res || !attr || !data)
171 ctx = syscommon_resman_get_resource_privdata(res);
175 if (!ctx->device_name) {
176 _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n",
177 syscommon_resman_get_resource_name(res));
181 strncpy(buf, ctx->device_name, BUFF_MAX);
186 static const struct syscommon_resman_resource_attribute display_attrs[] = {
188 .name = "DISPLAY_ATTR_FPS",
189 .id = DISPLAY_ATTR_FPS,
190 .type = SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE,
191 .flag = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
193 .get = display_get_fps,
196 .name = "DISPLAY_ATTR_NAME",
197 .id = DISPLAY_ATTR_NAME,
198 .type = SYSCOMMON_RESMAN_DATA_TYPE_STRING,
199 .flag = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
201 .get = display_get_name,
206 static int display_setup_device_id(struct syscommon_resman_resource *res,
207 const struct syscommon_resman_resource_control *ctrl,
210 struct display_context *ctx;
211 const struct syscommon_resman_resource_device *device;
212 int resource_index = (int)(intptr_t)data;
217 ctx = syscommon_resman_get_resource_privdata(res);
221 device = syscommon_resman_find_resource_device(syscommon_resman_get_resource_type(res), resource_index);
223 _E("Not available resource: type: %s, index: %d\n",
224 syscommon_resman_get_resource_name(res), resource_index);
228 if (ctx->device_name)
229 free(ctx->device_name);
231 ctx->device_name = g_strdup(device->name);
232 ctx->index = resource_index;
237 static const struct syscommon_resman_resource_control display_ctrls[] = {
239 .name = "DISPLAY_CTRL_DEVICE_ID",
240 .id = DISPLAY_CTRL_DEVICE_ID,
242 .set = display_setup_device_id,
247 static int display_monitor_func(void *data, void **result)
251 for (i = 0; i < g_fps_monitor.resource_count; i++)
254 return THREAD_RETURN_CONTINUE;
257 static int display_create(struct syscommon_resman_resource *res)
260 struct display_context *ctx;
262 ctx = calloc(1, sizeof(struct display_context));
268 syscommon_resman_set_resource_privdata(res, ctx);
270 g_mutex_lock(&g_fps_monitor.display_lock);
271 if (g_fps_monitor.holder++ == 0)
272 resume_thread(g_fps_monitor.thread);
273 g_mutex_unlock(&g_fps_monitor.display_lock);
278 static void display_delete(struct syscommon_resman_resource *res)
280 struct display_context *ctx;
285 ctx = syscommon_resman_get_resource_privdata(res);
289 if (ctx->device_name)
290 free(ctx->device_name);
293 syscommon_resman_set_resource_privdata(res, NULL);
295 g_mutex_lock(&g_fps_monitor.display_lock);
296 if (--g_fps_monitor.holder == 0)
297 suspend_thread(g_fps_monitor.thread);
298 g_mutex_unlock(&g_fps_monitor.display_lock);
301 static int display_init(void)
305 g_fps_monitor.resource_count = syscommon_resman_get_resource_device_count(RESOURCE_TYPE_DISPLAY);
306 if (g_fps_monitor.resource_count < 0)
307 return g_fps_monitor.resource_count;
309 g_fps_monitor.last_fps = calloc(g_fps_monitor.resource_count, sizeof(double));
310 if (!g_fps_monitor.last_fps)
313 ret = create_timer_thread(&g_fps_monitor.thread, DISPLAY_SAMPLE_RATE_MSEC,
314 display_monitor_func, NULL);
319 static void display_exit(void)
321 if (g_fps_monitor.thread) {
322 destroy_thread(g_fps_monitor.thread);
323 g_fps_monitor.thread = NULL;
326 if (g_fps_monitor.last_fps) {
327 free(g_fps_monitor.last_fps);
328 g_fps_monitor.last_fps = NULL;
331 g_fps_monitor.resource_count = 0;
334 static const struct syscommon_resman_resource_driver display_resource_driver = {
336 .type = RESOURCE_TYPE_DISPLAY,
337 .attrs = display_attrs,
338 .num_attrs = ARRAY_SIZE(display_attrs),
339 .ctrls = display_ctrls,
340 .num_ctrls = ARRAY_SIZE(display_ctrls),
342 .create = display_create,
343 .delete = display_delete,
344 .init = display_init,
345 .exit = display_exit,
348 SYSCOMMON_RESMAN_RESOURCE_DRIVER_REGISTER(&display_resource_driver)