unsigned int req_sec;
unsigned int req_usec;
void *user_data;
+ int need_free;
} tdm_client_vblank_info;
static void
vblank_info->func(sequence, tv_sec, tv_usec, vblank_info->user_data);
}
- LIST_DEL(&vblank_info->link);
- free(vblank_info);
+ if (vblank_info->need_free) {
+ LIST_DEL(&vblank_info->link);
+ free(vblank_info);
+ } else {
+ vblank_info->need_free = 1;
+ }
}
static const struct wl_tdm_vblank_listener tdm_client_vblank_listener = {
tdm_private_client *private_client = (tdm_private_client*)client;
tdm_client_vblank_info *vblank_info;
struct timespec tp;
+ int ret = 0;
TDM_RETURN_VAL_IF_FAIL(name != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
TDM_RETURN_VAL_IF_FAIL(interval > 0, TDM_CLIENT_ERROR_INVALID_PARAMETER);
vblank_info->req_sec = (unsigned int)tp.tv_sec;
vblank_info->req_usec = (unsigned int)(tp.tv_nsec/1000L);
+ vblank_info->need_free = (sync) ? 0 : 1;
vblank_info->vblank =
wl_tdm_wait_vblank(private_client->tdm, name, sw_timer, interval,
vblank_info->user_data = user_data;
LIST_ADDTAIL(&vblank_info->link, &private_client->vblank_list);
- if (sync)
- wl_display_roundtrip(private_client->display);
- else
+ if (!sync) {
wl_display_flush(private_client->display);
+ return TDM_CLIENT_ERROR_NONE;
+ }
+
+ while (ret != -1 && !vblank_info->need_free)
+ ret = wl_display_dispatch(private_client->display);
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ TDM_DBG("block during %d us",
+ ((unsigned int)(tp.tv_sec * 1000000) + (unsigned int)(tp.tv_nsec/1000L))
+ - (vblank_info->req_sec * 1000000 + vblank_info->req_usec));
+
+ LIST_DEL(&vblank_info->link);
+ free(vblank_info);
return TDM_CLIENT_ERROR_NONE;
}
TDM_CLIENT_ERROR_INVALID_PARAMETER = -2, /**< wrong input parameter */
TDM_CLIENT_ERROR_PERMISSION_DENIED = -3, /**< access denied */
TDM_CLIENT_ERROR_OUT_OF_MEMORY = -4, /**< no free memory */
+ TDM_CLIENT_ERROR_DPMS_OFF = -5, /**< dpms off */
} tdm_client_error;
/**
/**
* @brief Wait for VBLANK
* @details After interval vblanks, a client vblank handler will be called.
- * If 'sw_timer' param is 1, TDM will use the SW timer and call a client vblank
- * handler when DPMS off.
+ * If 'sw_timer' param is 1 in case of DPMS off, TDM will use the SW timer and
+ * call a client vblank handler. Otherwise, this function will return error.
* @param[in] client A TDM client object
* @param[in] name The name of a TDM output
* @param[in] sw_timer 0: not using SW timer, 1: using SW timer
<enum name="error">
<entry name="invalid_name" value="0"/>
<entry name="operation_failed" value="1"/>
+ <entry name="dpms_off" value="2"/>
</enum>
<request name="wait_vblank">
INTERN type_name_fn(status)
+INTERN const char*
+tdm_get_dpms_str(tdm_output_dpms dpms_value)
+{
+ return dpms_str(dpms_value);
+}
+
EXTERN tdm_error
tdm_display_get_capabilities(tdm_display *dpy,
tdm_display_capability *capabilities)
struct list_head link;
} tdm_buffer_info;
+const char*
+tdm_get_dpms_str(tdm_output_dpms dpms_value);
+
tdm_private_output *
tdm_display_find_output_stamp(tdm_private_display *private_display,
unsigned long stamp);
tdm_server_vblank_info *vblank_info;
struct wl_resource *vblank_resource;
tdm_output *found = NULL;
+ tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_ON;
int count = 0, i;
tdm_error ret;
TDM_DBG("The tdm client requests vblank");
+ if (tdm_debug_server) {
+ unsigned long curr = tdm_helper_get_time_in_micros();
+ unsigned long reqtime = (req_sec * 1000000) + req_usec;
+ if (curr - reqtime > 1000) /* 1ms */
+ TDM_WRN("delay(req): %d us", (int)(curr - reqtime));
+ }
+
tdm_display_get_output_count(private_loop->dpy, &count);
for (i = 0; i < count; i++) {
return;
}
- /* TODO: need to implement things related with sw_timer */
+ tdm_output_get_dpms(found, &dpms_value);
- vblank_resource =
- wl_resource_create(client, &wl_tdm_vblank_interface,
- wl_resource_get_version(resource), id);
- if (!vblank_resource) {
- wl_resource_post_no_memory(resource);
- TDM_ERR("wl_resource_create failed");
+ if (dpms_value != TDM_OUTPUT_DPMS_ON && !sw_timer) {
+ wl_resource_post_error(resource, WL_TDM_ERROR_DPMS_OFF,
+ "dpms '%s'", tdm_get_dpms_str(dpms_value));
+ TDM_ERR("dpms '%s'", tdm_get_dpms_str(dpms_value));
return;
}
vblank_info = calloc(1, sizeof *vblank_info);
if (!vblank_info) {
- wl_resource_destroy(vblank_resource);
wl_resource_post_no_memory(resource);
TDM_ERR("alloc failed");
return;
TDM_DBG("wl_tdm_vblank@%d output(%s) interval(%d)", id, name, interval);
- ret = tdm_output_wait_vblank(found, interval, 0,
- _tdm_server_cb_output_vblank, vblank_info);
- if (ret != TDM_ERROR_NONE) {
- wl_resource_destroy(vblank_resource);
- free(vblank_info);
- wl_resource_post_error(resource, WL_TDM_ERROR_OPERATION_FAILED,
- "couldn't wait vblank for %s", name);
- TDM_ERR("couldn't wait vblank for %s", name);
- return;
+ vblank_resource =
+ wl_resource_create(client, &wl_tdm_vblank_interface,
+ wl_resource_get_version(resource), id);
+ if (!vblank_resource) {
+ wl_resource_post_no_memory(resource);
+ TDM_ERR("wl_resource_create failed");
+ goto free_info;
}
- if (tdm_debug_server) {
- unsigned long curr = tdm_helper_get_time_in_micros();
- unsigned long reqtime = (req_sec * 1000000) + req_usec;
- if (curr - reqtime > 1000) /* 1ms */
- TDM_WRN("delay(req): %d us", (int)(curr - reqtime));
+ if (dpms_value == TDM_OUTPUT_DPMS_ON) {
+ ret = tdm_output_wait_vblank(found, interval, 0,
+ _tdm_server_cb_output_vblank, vblank_info);
+ if (ret != TDM_ERROR_NONE) {
+ wl_resource_post_error(resource, WL_TDM_ERROR_OPERATION_FAILED,
+ "couldn't wait vblank for %s", name);
+ TDM_ERR("couldn't wait vblank for %s", name);
+ goto destroy_resource;
+ }
+ } else if (sw_timer) {
+ /* TODO: need to implement things related with sw_timer */
+ if (ret != TDM_ERROR_NONE) {
+ wl_resource_post_error(resource, WL_TDM_ERROR_OPERATION_FAILED,
+ "not implemented yet");
+ TDM_ERR("not implemented yet");
+ goto destroy_resource;
+ }
+ } else {
+ wl_resource_post_error(resource, WL_TDM_ERROR_OPERATION_FAILED,
+ "bad implementation");
+ TDM_NEVER_GET_HERE();
+ goto destroy_resource;
}
vblank_info->resource = vblank_resource;
destroy_vblank_callback);
LIST_ADDTAIL(&vblank_info->link, &private_server->vblank_list);
+ return;
+destroy_resource:
+ wl_resource_destroy(vblank_resource);
+free_info:
+ free(vblank_info);
}
static const struct wl_tdm_interface tdm_implementation = {
tdm_client_error error;
int fd = -1;
struct pollfd fds;
+ int sync;
+
+ if (argc < 2) {
+ printf("Usage: %s\n", argv[0]);
+ printf("\t%s 0 : non-sync\n", argv[0]);
+ printf("\t%s 1 : sync\n", argv[0]);
+ exit(1);
+ }
+
+ sync = atoi(argv[1]);
client = tdm_client_create(&error);
if (error != TDM_CLIENT_ERROR_NONE) {
while (1) {
int ret;
- error = tdm_client_wait_vblank(client, "unknown-0", 1, 1, 0,
+ error = tdm_client_wait_vblank(client, "unknown-0", 1, 1, sync,
_client_vblank_handler, NULL);
if (error != TDM_CLIENT_ERROR_NONE) {
printf("tdm_client_wait_vblank failed\n");
goto done;
}
- ret = poll(&fds, 1, -1);
- if (ret < 0) {
- if (errno == EBUSY) /* normal case */
- continue;
- else {
- printf("poll failed: %m\n");
- goto done;
+ if (!sync) {
+ ret = poll(&fds, 1, -1);
+ if (ret < 0) {
+ if (errno == EBUSY) /* normal case */
+ continue;
+ else {
+ printf("poll failed: %m\n");
+ goto done;
+ }
}
- }
- error = tdm_client_handle_events(client);
- if (error != TDM_CLIENT_ERROR_NONE)
- printf("tdm_client_handle_events failed\n");
+ error = tdm_client_handle_events(client);
+ if (error != TDM_CLIENT_ERROR_NONE)
+ printf("tdm_client_handle_events failed\n");
+ }
}
done: