vblank: add set_vblank_fps functionality for the given PID 02/113502/2
authorBoram Park <boram1288.park@samsung.com>
Wed, 8 Feb 2017 03:39:16 +0000 (12:39 +0900)
committerBoram Park <boram1288.park@samsung.com>
Thu, 9 Feb 2017 04:45:18 +0000 (13:45 +0900)
Change-Id: I28a8b5ca1e585f68817da6f887aed13f188b64f0

client/tdm_client.c
client/tdm_client.h
include/tdm.h
include/tdm_common.h
protocol/tdm.xml
src/tdm_monitor_server.c
src/tdm_private.h
src/tdm_server.c
src/tdm_vblank.c
tools/tdm_test_client.c

index c9b312c..bdab4c0 100644 (file)
@@ -86,6 +86,7 @@ struct _tdm_private_client_vblank {
        struct wl_tdm_vblank *vblank;
        struct list_head wait_list;
 
+       char name[TDM_NAME_LEN];
        unsigned int sync;
        unsigned int fps;
        int offset;
@@ -425,6 +426,25 @@ tdm_client_wait_vblank(tdm_client *client, char *name,
        return tdm_client_vblank_wait(private_client->temp_vblank, interval, _tdm_client_vblank_handler_temp, vblank_temp);
 }
 
+tdm_error
+tdm_client_set_client_vblank_fps(tdm_client *client, pid_t pid, const char *name, unsigned int fps)
+{
+       tdm_private_client *private_client = (tdm_private_client*)client;
+
+       TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(pid > 0, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(fps > 0, TDM_ERROR_INVALID_PARAMETER);
+
+       if (!name)
+               name = TDM_VBLANK_DEFAULT_NAME;
+
+       wl_tdm_set_client_vblank_fps(private_client->tdm, pid, name, fps);
+
+       wl_display_flush(private_client->display);
+
+       return TDM_ERROR_NONE;
+}
+
 tdm_client_output*
 tdm_client_get_output(tdm_client *client, char *name, tdm_error *error)
 {
@@ -647,6 +667,26 @@ tdm_client_vblank_destroy(tdm_client_vblank *vblank)
 }
 
 tdm_error
+tdm_client_vblank_set_name(tdm_client_vblank *vblank, const char *name)
+{
+       tdm_private_client_vblank *private_vblank;
+
+       TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       private_vblank = vblank;
+
+       if (!name)
+               name = TDM_VBLANK_DEFAULT_NAME;
+
+       strncpy(private_vblank->name, name, TDM_NAME_LEN - 1);
+       private_vblank->name[TDM_NAME_LEN - 1] = '\0';
+
+       wl_tdm_vblank_set_name(private_vblank->vblank, private_vblank->name);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
 tdm_client_vblank_set_sync(tdm_client_vblank *vblank, unsigned int sync)
 {
        tdm_private_client_vblank *private_vblank;
index e7df780..5cb1cce 100644 (file)
@@ -138,6 +138,17 @@ tdm_client_wait_vblank(tdm_client *client, char *name,
                                           tdm_client_vblank_handler2 func, void *user_data);
 
 /**
+ * @brief Set the client vblank fps for the given PID and name.
+ * @param[in] client A TDM client object
+ * @param[in] pid The process ID
+ * @param[in] name The client vblank name
+ * @param[in] fps The client vblank fps
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_client_set_client_vblank_fps(tdm_client *client, pid_t pid, const char *name, unsigned int fps);
+
+/**
  * @brief Get the client output object which has the given name.
  * @details
  * The client output name can be @b 'primary' or @b 'default' to get the main output.
@@ -241,6 +252,15 @@ void
 tdm_client_vblank_destroy(tdm_client_vblank *vblank);
 
 /**
+ * @brief Set the name to the client vblank object
+ * @param[in] vblank The client vblank object
+ * @param[in] name The client vblank name
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_client_vblank_set_name(tdm_client_vblank *vblank, const char *name);
+
+/**
  * @brief Set the sync value to the client vblank object
  * @details
  * If sync == 1, the user client vblank handler of #tdm_client_vblank_wait
index 3a066c1..ebb8f4f 100644 (file)
@@ -903,6 +903,26 @@ void
 tdm_vblank_destroy(tdm_vblank *vblank);
 
 /**
+ * @brief Set the name to a vblank object
+ * @details The default name is "unknown"
+ * @param[in] vblank A vblank object
+ * @param[in] name vblank name
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_vblank_set_name(tdm_vblank *vblank, const char *name);
+
+/**
+ * @brief Get the name for a vblank object
+ * @details The default name is "unknown"
+ * @param[in] vblank A vblank object
+ * @param[out] name vblank name
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_vblank_get_name(tdm_vblank *vblank, const char **name);
+
+/**
  * @brief Set the fps to a vblank object
  * @details Default is the @b vertical @b refresh @b rate of the given output.
  * @param[in] vblank A vblank object
@@ -913,6 +933,15 @@ tdm_error
 tdm_vblank_set_fps(tdm_vblank *vblank, unsigned int fps);
 
 /**
+ * @brief Get the fps for a vblank object
+ * @param[in] vblank A vblank object
+ * @param[out] fps over 0
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_vblank_get_fps(tdm_vblank *vblank, unsigned int *fps);
+
+/**
  * @brief Set the offset(milli-second) to a vblank object
  * @details Default is @b 0.
  * @param[in] vblank A vblank object
@@ -923,6 +952,15 @@ tdm_error
 tdm_vblank_set_offset(tdm_vblank *vblank, int offset);
 
 /**
+ * @brief Get the offset(milli-second) for a vblank object
+ * @param[in] vblank A vblank object
+ * @param[out] offset the offset(milli-second)
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_vblank_get_offset(tdm_vblank *vblank, int *offset);
+
+/**
  * @brief Enable/Disable the fake vblank to a vblank object
  * @details
  * If enable_fake == 0, #tdm_vblank_wait will return TDM_ERROR_DPMS_OFF
@@ -938,10 +976,11 @@ tdm_vblank_set_enable_fake(tdm_vblank *vblank, unsigned int enable_fake);
 /**
  * @brief Get the fake vblank
  * @param[in] vblank A vblank object
- * @return 1 if enable. Otherwise, 0.
+ * @param[out] enable_fake 1:enable, 0:disable
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
  */
-unsigned int
-tdm_vblank_get_enable_fake(tdm_vblank *vblank);
+tdm_error
+tdm_vblank_get_enable_fake(tdm_vblank *vblank, unsigned int *enable_fake);
 
 /**
  * @brief Wait for a vblank
index 3b9f5fa..dc33494 100644 (file)
@@ -44,6 +44,7 @@ extern "C" {
 
 #define TDM_NAME_LEN        64
 #define TDM_PATH_LEN        1024
+#define TDM_VBLANK_DEFAULT_NAME   "Unknown"
 
 /**
  * @file tdm_common.h
index 3f98fd1..0a157e0 100644 (file)
             <arg name="message" type="string"/>
         </event>
 
+        <request name="debug">
+            <arg name="options" type="string" summary="debug options"/>
+        </request>
+
         <request name="create_output">
             <arg name="name" type="string" summary="output's name. 'primary' or 'default' can be used for default."/>
             <arg name="id" type="new_id" interface="wl_tdm_output"/>
         </request>
 
-        <request name="debug">
-            <arg name="options" type="string" summary="debug options"/>
+        <request name="set_client_vblank_fps">
+            <arg name="pid" type="uint"/>
+            <arg name="name" type="string"/>
+            <arg name="fps" type="uint"/>
         </request>
 
     </interface>
             <arg name="error" type="uint" summary="error status enumeration"/>
         </event>
 
+        <event name="fps_changed" />
+
         <request name="destroy" type="destructor"/>
 
+        <request name="set_name">
+            <arg name="name" type="string"/>
+        </request>
+
         <request name="set_fps">
             <arg name="fps" type="uint"/>
         </request>
index 0d18743..1916e4a 100644 (file)
@@ -241,6 +241,56 @@ _tdm_monitor_server_fps(unsigned int pid, char *cwd, int argc, char *argv[], cha
 }
 
 static void
+_tdm_monitor_server_vblank_list(unsigned int pid, char *cwd, int argc, char *argv[],
+                                                               char *reply, int *len, tdm_display *dpy)
+{
+       tdm_server_get_vblank_list_information(dpy, reply, len);
+}
+
+static void
+_tdm_monitor_server_vblank_fps(unsigned int pid, char *cwd, int argc, char *argv[],
+                                                          char *reply, int *len, tdm_display *dpy)
+{
+       unsigned int target_pid, fps;
+       char *arg;
+       char *end;
+       char name[TDM_NAME_LEN];
+       tdm_error ret;
+
+       if (argc < 3) {
+               _tdm_monitor_server_usage(argv[0], reply, len);
+               return;
+       }
+
+       arg = argv[2];
+       target_pid = strtol(arg, &end, 10);
+
+       if (*end == ',') {
+               arg = end + 1;
+               end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
+       } else {
+               strncpy(name, TDM_VBLANK_DEFAULT_NAME, TDM_NAME_LEN - 1);
+               name[TDM_NAME_LEN - 1] = '\0';
+       }
+
+       if (*end != '@') {
+               TDM_SNPRINTF(reply, len, "failed: no fps value\n");
+               return;
+       }
+
+       arg = end + 1;
+       fps = strtol(arg, &end, 10);
+
+       ret = tdm_server_set_client_vblank_fps(target_pid, name, fps);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_SNPRINTF(reply, len, "can't set '%u' fps to '%s' client vblank(PID:%u)\n", fps, name, target_pid);
+               return;
+       }
+
+       TDM_SNPRINTF(reply, len, "success: '%u' fps for '%s' client vblank(PID:%u)\n", fps, name, target_pid);
+}
+
+static void
 _tdm_monitor_server_prop(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy)
 {
        tdm_output *output;
@@ -446,6 +496,18 @@ static struct {
                "0 or 1"
        },
        {
+               "vblank_list", _tdm_monitor_server_vblank_list,
+               "print the client vblank list",
+               NULL,
+               NULL
+       },
+       {
+               "vblank_fps", _tdm_monitor_server_vblank_fps,
+               "set the client vblank fps for the given process ID and client vblank name",
+               "<pid>[,<vblank_name>]@<fps>",
+               NULL
+       },
+       {
                "prop", _tdm_monitor_server_prop,
                "set the property of a output or a layer",
                "<output_idx>[,<layer_idx>]:<prop_name>,<value>",
index cd7405d..c7a08d8 100644 (file)
@@ -554,6 +554,10 @@ tdm_error
 tdm_server_init(tdm_private_loop *private_loop);
 void
 tdm_server_deinit(tdm_private_loop *private_loop);
+tdm_error
+tdm_server_set_client_vblank_fps(unsigned int pid, const char *name, unsigned int fps);
+void
+tdm_server_get_vblank_list_information(tdm_display *dpy, char *reply, int *len);
 
 char *
 tdm_helper_dump_make_directory(const char *path, char *reply, int *len);
index 914b1da..bb2a7c3 100644 (file)
@@ -67,6 +67,8 @@ typedef struct _tdm_server_output_info {
 
 typedef struct _tdm_server_vblank_info {
        struct list_head link;
+       struct list_head valid_link;
+
        tdm_server_output_info *output_info;
        struct wl_resource *resource;
 
@@ -81,6 +83,7 @@ typedef struct _tdm_server_wait_info {
 } tdm_server_wait_info;
 
 static tdm_private_server *keep_private_server;
+static struct list_head valid_vblank_list;
 
 static void destroy_wait(tdm_server_wait_info *wait_info);
 
@@ -202,6 +205,8 @@ destroy_vblank_callback(struct wl_resource *resource)
        }
 
        LIST_DEL(&vblank_info->link);
+       LIST_DEL(&vblank_info->valid_link);
+
        free(vblank_info);
 }
 
@@ -212,6 +217,14 @@ _tdm_server_vblank_cb_destroy(struct wl_client *client, struct wl_resource *reso
 }
 
 static void
+_tdm_server_vblank_cb_set_name(struct wl_client *client, struct wl_resource *resource, const char *name)
+{
+       tdm_server_vblank_info *vblank_info = wl_resource_get_user_data(resource);
+
+       tdm_vblank_set_name(vblank_info->vblank, name);
+}
+
+static void
 _tdm_server_vblank_cb_set_fps(struct wl_client *client, struct wl_resource *resource, uint32_t fps)
 {
        tdm_server_vblank_info *vblank_info = wl_resource_get_user_data(resource);
@@ -243,6 +256,7 @@ _tdm_server_vblank_cb_wait_vblank(struct wl_client *client, struct wl_resource *
        tdm_server_output_info *output_info = vblank_info->output_info;
        tdm_private_server *private_server = output_info->private_server;
        tdm_server_wait_info *wait_info;
+       unsigned int enable_fake = 0;
        tdm_error ret;
 
        TDM_TRACE_COUNT(ServerWaitVBlank, req_id);
@@ -263,7 +277,8 @@ _tdm_server_vblank_cb_wait_vblank(struct wl_client *client, struct wl_resource *
 
        ret = tdm_vblank_wait(vblank_info->vblank, req_sec, req_usec, interval, _tdm_server_cb_vblank, wait_info);
 
-       if (!tdm_vblank_get_enable_fake(vblank_info->vblank) && ret == TDM_ERROR_DPMS_OFF)
+       tdm_vblank_get_enable_fake(vblank_info->vblank, &enable_fake);
+       if (!enable_fake && ret == TDM_ERROR_DPMS_OFF)
                goto wait_failed;
 
        TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
@@ -283,6 +298,7 @@ _tdm_server_vblank_cb_wait_vblank_seq(struct wl_client *client, struct wl_resour
        tdm_server_output_info *output_info = vblank_info->output_info;
        tdm_private_server *private_server = output_info->private_server;
        tdm_server_wait_info *wait_info;
+       unsigned int enable_fake = 0;
        tdm_error ret;
 
        TDM_TRACE_COUNT(ServerWaitVBlank, req_id);
@@ -303,7 +319,8 @@ _tdm_server_vblank_cb_wait_vblank_seq(struct wl_client *client, struct wl_resour
 
        ret = tdm_vblank_wait_seq(vblank_info->vblank, req_sec, req_usec, sequence, _tdm_server_cb_vblank, wait_info);
 
-       if (!tdm_vblank_get_enable_fake(vblank_info->vblank) && ret == TDM_ERROR_DPMS_OFF)
+       tdm_vblank_get_enable_fake(vblank_info->vblank, &enable_fake);
+       if (!enable_fake && ret == TDM_ERROR_DPMS_OFF)
                goto wait_failed;
 
        TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
@@ -317,6 +334,7 @@ wait_failed:
 
 static const struct wl_tdm_vblank_interface tdm_vblank_implementation = {
        _tdm_server_vblank_cb_destroy,
+       _tdm_server_vblank_cb_set_name,
        _tdm_server_vblank_cb_set_fps,
        _tdm_server_vblank_cb_set_offset,
        _tdm_server_vblank_cb_set_enable_fake,
@@ -367,6 +385,8 @@ _tdm_server_output_cb_create_vblank(struct wl_client *client, struct wl_resource
        }
 
        LIST_ADDTAIL(&vblank_info->link, &output_info->vblank_list);
+       LIST_ADDTAIL(&vblank_info->valid_link, &valid_vblank_list);
+
        vblank_info->output_info = output_info;
        vblank_info->resource = vblank_resource;
        vblank_info->vblank = vblank;
@@ -486,9 +506,20 @@ _tdm_server_cb_debug(struct wl_client *client, struct wl_resource *resource, con
        wl_tdm_send_debug_done(resource, message);
 }
 
+static void
+_tdm_server_cb_set_client_vblank_fps(struct wl_client *client, struct wl_resource *resource,
+                                                                        unsigned int pid, const char *name, unsigned int fps)
+{
+       tdm_error ret = tdm_server_set_client_vblank_fps(pid, name, fps);
+       TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       TDM_INFO("'%s' vblank fps(PID: '%u'): %u", name, pid, fps);
+}
+
 static const struct wl_tdm_interface tdm_implementation = {
-       _tdm_server_cb_create_output,
        _tdm_server_cb_debug,
+       _tdm_server_cb_create_output,
+       _tdm_server_cb_set_client_vblank_fps,
 };
 
 static void
@@ -538,6 +569,8 @@ tdm_server_init(tdm_private_loop *private_loop)
                return TDM_ERROR_OUT_OF_MEMORY;
        }
 
+       LIST_INITHEAD(&valid_vblank_list);
+
        private_server->private_loop = private_loop;
        private_loop->private_server = private_server;
        keep_private_server = private_server;
@@ -569,3 +602,98 @@ tdm_server_deinit(tdm_private_loop *private_loop)
        private_loop->private_server = NULL;
        keep_private_server = NULL;
 }
+
+INTERN tdm_error
+tdm_server_set_client_vblank_fps(unsigned int pid, const char *name, unsigned int fps)
+{
+       tdm_server_vblank_info *v;
+
+       TDM_RETURN_VAL_IF_FAIL(pid > 0, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(fps > 0, TDM_ERROR_INVALID_PARAMETER);
+
+       LIST_FOR_EACH_ENTRY(v, &valid_vblank_list, valid_link) {
+               struct wl_client *client = wl_resource_get_client(v->resource);
+               pid_t client_pid = 0;
+               const char *vblank_name = NULL;
+
+               if (!client)
+                       continue;
+
+               wl_client_get_credentials(client, &client_pid, NULL, NULL);
+
+               if (client_pid != pid)
+                       continue;
+
+               if (name && strncmp(name, TDM_VBLANK_DEFAULT_NAME, TDM_NAME_LEN)) {
+                       tdm_vblank_get_name(v->vblank, &vblank_name);
+                       if (strncmp(vblank_name, name, TDM_NAME_LEN))
+                               continue;
+               }
+
+               tdm_vblank_set_fps(v->vblank, fps);
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+static void
+_tdm_server_get_process_name(pid_t pid, char *name, unsigned int size)
+{
+       char proc[TDM_NAME_LEN], pname[TDM_NAME_LEN];
+       FILE *h;
+       size_t len;
+
+       snprintf(proc, TDM_NAME_LEN, "/proc/%d/cmdline", pid);
+       h = fopen(proc, "r");
+       if (!h)
+               return;
+
+       len = fread(pname, sizeof(char), TDM_NAME_LEN, h);
+       if (len == 0) {
+               char *p = strncpy(pname, "NO NAME", sizeof(pname) - 1);
+               len = p - pname;
+       }
+       pname[len - 1] = '\0';
+
+       strncpy(name, pname, size - 1);
+       name[size - 1] = '\0';
+
+       fclose(h);
+}
+
+INTERN void
+tdm_server_get_vblank_list_information(tdm_display *dpy, char *reply, int *len)
+{
+       tdm_server_vblank_info *v;
+
+       TDM_SNPRINTF(reply, len, "[Client Vblank List]\n");
+       TDM_SNPRINTF(reply, len, "---------------------------------------------------------------\n");
+       TDM_SNPRINTF(reply, len, "name         fps offset fake process\n");
+       TDM_SNPRINTF(reply, len, "---------------------------------------------------------------\n");
+
+       LIST_FOR_EACH_ENTRY(v, &valid_vblank_list, valid_link) {
+               struct wl_client *client = wl_resource_get_client(v->resource);
+               const char *vbl_name = NULL;
+               char proc_name[TDM_NAME_LEN];
+               unsigned int fps = 0, fake = 0;
+               int offset = 0;
+               pid_t pid = 0;
+
+               tdm_vblank_get_name(v->vblank, &vbl_name);
+               tdm_vblank_get_fps(v->vblank, &fps);
+               tdm_vblank_get_offset(v->vblank, &offset);
+               tdm_vblank_get_enable_fake(v->vblank, &fake);
+
+               snprintf(proc_name, TDM_NAME_LEN, "Unknown");
+               if (client) {
+                       wl_client_get_credentials(client, &pid, NULL, NULL);
+                       _tdm_server_get_process_name(pid, proc_name, TDM_NAME_LEN);
+               }
+
+               TDM_SNPRINTF(reply, len, "%-12s %u  %d      %u    %s (pid: %u)\n",
+                                        vbl_name, fps, offset, fake, proc_name, pid);
+       }
+
+       TDM_SNPRINTF(reply, len, "\n");
+}
+
index 0e3c1aa..b9ce1ab 100644 (file)
@@ -91,6 +91,7 @@ typedef struct _tdm_private_vblank {
        unsigned int vrefresh;
 
        unsigned int check_HW_or_SW;
+       char name[TDM_NAME_LEN];
        unsigned int fps;
        int offset;
        unsigned int enable_fake;
@@ -378,6 +379,9 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error)
        private_vblank->check_HW_or_SW = 1;
        private_vblank->fps = mode->vrefresh;
 
+       strncpy(private_vblank->name, TDM_VBLANK_DEFAULT_NAME, TDM_NAME_LEN - 1);
+       private_vblank->name[TDM_NAME_LEN - 1] = '\0';
+
        LIST_INITHEAD(&private_vblank->HW_wait_list);
        LIST_INITHEAD(&private_vblank->SW_wait_list);
 
@@ -425,6 +429,38 @@ tdm_vblank_destroy(tdm_vblank *vblank)
 }
 
 EXTERN tdm_error
+tdm_vblank_set_name(tdm_vblank *vblank, const char *name)
+{
+       tdm_private_vblank *private_vblank = vblank;
+
+       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       if (!name)
+               name = TDM_VBLANK_DEFAULT_NAME;
+
+       strncpy(private_vblank->name, name, TDM_NAME_LEN - 1);
+       private_vblank->name[TDM_NAME_LEN - 1] = '\0';
+
+       if (tdm_debug_module & TDM_DEBUG_VBLANK)
+               VIN("name(%s)", name);
+
+       return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
+tdm_vblank_get_name(tdm_vblank *vblank, const char **name)
+{
+       tdm_private_vblank *private_vblank = vblank;
+
+       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(name != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *name = (const char*)private_vblank->name;
+
+       return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
 tdm_vblank_set_fps(tdm_vblank *vblank, unsigned int fps)
 {
        tdm_private_vblank *private_vblank = vblank;
@@ -445,6 +481,19 @@ tdm_vblank_set_fps(tdm_vblank *vblank, unsigned int fps)
 }
 
 EXTERN tdm_error
+tdm_vblank_get_fps(tdm_vblank *vblank, unsigned int *fps)
+{
+       tdm_private_vblank *private_vblank = vblank;
+
+       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(fps != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *fps = private_vblank->fps;
+
+       return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
 tdm_vblank_set_offset(tdm_vblank *vblank, int offset)
 {
        tdm_private_vblank *private_vblank = vblank;
@@ -464,6 +513,19 @@ tdm_vblank_set_offset(tdm_vblank *vblank, int offset)
 }
 
 EXTERN tdm_error
+tdm_vblank_get_offset(tdm_vblank *vblank, int *offset)
+{
+       tdm_private_vblank *private_vblank = vblank;
+
+       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(offset != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *offset = private_vblank->offset;
+
+       return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
 tdm_vblank_set_enable_fake(tdm_vblank *vblank, unsigned int enable_fake)
 {
        tdm_private_vblank *private_vblank = vblank;
@@ -481,14 +543,17 @@ tdm_vblank_set_enable_fake(tdm_vblank *vblank, unsigned int enable_fake)
        return TDM_ERROR_NONE;
 }
 
-EXTERN unsigned int
-tdm_vblank_get_enable_fake(tdm_vblank *vblank)
+EXTERN tdm_error
+tdm_vblank_get_enable_fake(tdm_vblank *vblank, unsigned int *enable_fake)
 {
        tdm_private_vblank *private_vblank = vblank;
 
-       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, 0);
+       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(enable_fake != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *enable_fake = private_vblank->enable_fake;
 
-       return private_vblank->enable_fake;
+       return TDM_ERROR_NONE;
 }
 
 static tdm_error
index fb371f5..1ec8f93 100644 (file)
 #include "tdm_macro.h"
 
 typedef struct _tdm_test_client_arg {
-       char output_name[512];
+       char *output_name;
        int fps;
        int sync;
        int interval;
        int offset;
        int enable_fake;
+       int pid;
+       char *vblank_name;
 } tdm_test_client_arg;
 
 typedef struct _tdm_test_client {
@@ -58,6 +60,7 @@ typedef struct _tdm_test_client {
 
        int do_query;
        int do_vblank;
+       int do_set_fps;
        int waiting;
 
        tdm_client *client;
@@ -90,7 +93,8 @@ static struct typestrings typestrs[] = {
 
 static struct optstrings optstrs[] = {
        {OPT_QRY, "qo", "output objects info", "<output_name>", "primary"},
-       {OPT_TST, "v", "vblank test", "<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake]", "primary,0@60~1+0*1"},
+       {OPT_TST, "v", "vblank test", "<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake][^vblank_name]", "primary,0@60~1+0*1^test"},
+       {OPT_TST, "f", "fps setting test", "<pid>[,<vblank_name>]@<fps>", "<pid>@60"},
 };
 
 static void
@@ -126,7 +130,9 @@ usage(char *app_name)
 static void
 parse_arg_qo(tdm_test_client *data, char *arg)
 {
-       strtostr(data->args.output_name, 512, arg, TDM_DELIM);
+       char name[TDM_NAME_LEN];
+       strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
+       data->args.output_name = strndup(name, TDM_NAME_LEN);
 }
 
 //"<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake]"
@@ -134,8 +140,10 @@ static void
 parse_arg_v(tdm_test_client *data, char *arg)
 {
        char *end = arg;
+       char name[TDM_NAME_LEN];
 
-       end = strtostr(data->args.output_name, 512, arg, TDM_DELIM);
+       end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
+       data->args.output_name = strndup(name, TDM_NAME_LEN);
 
        if (*end == ',') {
                arg = end + 1;
@@ -161,6 +169,37 @@ parse_arg_v(tdm_test_client *data, char *arg)
                arg = end + 1;
                data->args.enable_fake = strtol(arg, &end, 10);
        }
+
+       if (*end == '^') {
+               char name[TDM_NAME_LEN];
+               arg = end + 1;
+               end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
+               data->args.vblank_name = strndup(name, TDM_NAME_LEN);
+       }
+}
+
+//"<pid>@<fps>"
+static void
+parse_arg_f(tdm_test_client *data, char *arg)
+{
+       char *end = arg;
+
+       data->args.pid = strtol(arg, &end, 10);
+
+       if (*end == ',') {
+               char name[TDM_NAME_LEN];
+               arg = end + 1;
+               end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
+               data->args.vblank_name = strndup(name, TDM_NAME_LEN);
+       }
+
+       if (*end != '@') {
+               printf("failed: no fps value\n");
+               exit(0);
+       }
+
+       arg = end + 1;
+       data->args.fps = strtol(arg, &end, 10);
 }
 
 static void
@@ -183,6 +222,9 @@ parse_args(tdm_test_client *data, int argc, char *argv[])
                } else if (!strncmp(argv[i] + 1, "v", 1)) {
                        data->do_vblank = 1;
                        parse_arg_v(data, argv[++i]);
+               } else if (!strncmp(argv[i] + 1, "f", 1)) {
+                       data->do_set_fps = 1;
+                       parse_arg_f(data, argv[++i]);
                } else {
                        usage(argv[0]);
                        exit(0);
@@ -293,6 +335,7 @@ do_vblank(tdm_test_client *data)
                return;
        }
 
+       tdm_client_vblank_set_name(vblank, data->args.vblank_name);
        tdm_client_vblank_set_enable_fake(vblank, data->args.enable_fake);
        tdm_client_vblank_set_sync(vblank, data->args.sync);
        if (data->args.fps > 0)
@@ -350,6 +393,18 @@ done:
                tdm_client_vblank_destroy(vblank);
 }
 
+static void
+do_set_fps(tdm_test_client *data)
+{
+       tdm_error error;
+
+       error = tdm_client_set_client_vblank_fps(data->client, data->args.pid, data->args.vblank_name, data->args.fps);
+       if (error != TDM_ERROR_NONE) {
+               printf("tdm_client_set_client_vblank_fps failed\n");
+               return;
+       }
+}
+
 static tdm_test_client ttc_data;
 
 int
@@ -371,9 +426,9 @@ main(int argc, char *argv[])
 
        parse_args(data, argc, argv);
 
-       printf("sync(%d) fps(%d) interval(%d) offset(%d) enable_fake(%d)\n",
+       printf("sync(%d) fps(%d) interval(%d) offset(%d) enable_fake(%d) pid(%d)\n",
                   data->args.sync, data->args.fps, data->args.interval,
-                  data->args.offset, data->args.enable_fake);
+                  data->args.offset, data->args.enable_fake, data->args.pid);
 
        data->client = tdm_client_create(&error);
        if (error != TDM_ERROR_NONE) {
@@ -385,8 +440,14 @@ main(int argc, char *argv[])
                do_query(data);
        if (data->do_vblank)
                do_vblank(data);
+       if (data->do_set_fps)
+               do_set_fps(data);
 
 done:
+       if (data->args.output_name)
+               free(data->args.output_name);
+       if (data->args.vblank_name)
+               free(data->args.vblank_name);
        if (data->client)
                tdm_client_destroy(data->client);