#include "tdm_log.h"
#include "tdm_macro.h"
#include "tdm_list.h"
+#include "tdm.h"
+#include "tdm_private.h"
#include "tdm-client-protocol.h"
-int tdm_debug;
-
typedef struct _tdm_private_client_vblank tdm_private_client_vblank;
typedef struct _tdm_private_client {
struct wl_tdm_vblank *vblank;
struct list_head wait_list;
+ char name[TDM_NAME_LEN];
unsigned int sync;
unsigned int fps;
int offset;
TDM_RETURN_IF_FAIL(private_vblank != NULL);
+ TDM_TRACE_COUNT(ClientDoneVBlank, req_id);
+
LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->wait_list, link) {
if (w->req_id != req_id)
continue;
{
tdm_private_client *private_client = data;
- if (strcmp(interface, "wl_tdm") == 0) {
+ if (strncmp(interface, "wl_tdm", 6) == 0) {
private_client->tdm =
wl_registry_bind(registry, name, &wl_tdm_interface, version);
TDM_RETURN_IF_FAIL(private_client->tdm != NULL);
tdm_client_create(tdm_error *error)
{
tdm_private_client *private_client;
- const char *debug;
-
- debug = getenv("TDM_DEBUG");
- if (debug && (strstr(debug, "1")))
- tdm_debug = 1;
private_client = calloc(1, sizeof *private_client);
if (!private_client) {
h = calloc(1, sizeof *h);
TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY);
+ if (LIST_IS_EMPTY(&private_output->change_handler_list))
+ wl_tdm_output_watch_output_changes(private_output->output, 1);
+
h->private_output = private_output;
h->func = func;
h->user_data = user_data;
LIST_DEL(&h->link);
free(h);
+
+ if (LIST_IS_EMPTY(&private_output->change_handler_list))
+ wl_tdm_output_watch_output_changes(private_output->output, 0);
+
return;
}
}
}
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;
TDM_RETURN_VAL_IF_FAIL(fps > 0, TDM_ERROR_INVALID_PARAMETER);
private_vblank = vblank;
- TDM_RETURN_VAL_IF_FAIL(private_vblank->started == 0, TDM_ERROR_BAD_REQUEST);
if (private_vblank->fps == fps)
return TDM_ERROR_NONE;
wl_tdm_vblank_wait_vblank(private_vblank->vblank, interval, w->req_id, w->req_sec, w->req_usec);
+ TDM_TRACE_COUNT(ClientWaitVBlank, w->req_id);
+
+ if (!private_vblank->sync) {
+ wl_display_flush(private_client->display);
+ return TDM_ERROR_NONE;
+ }
+
+ while (ret != -1 && !w->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 / 1000))
+ - (w->req_sec * 1000000 + w->req_usec));
+
+ LIST_DEL(&w->link);
+ free(w);
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence,
+ tdm_client_vblank_handler func, void *user_data)
+{
+ tdm_private_client *private_client;
+ tdm_private_client_output *private_output;
+ tdm_private_client_vblank *private_vblank;
+ tdm_client_wait_info *w;
+ struct timespec tp;
+ int ret = 0;
+
+ TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ private_vblank = vblank;
+ private_output = private_vblank->private_output;
+ private_client = private_output->private_client;
+
+ if (!private_vblank->started)
+ private_vblank->started = 1;
+
+ if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
+ TDM_INFO("dpms off");
+ return TDM_ERROR_DPMS_OFF;
+ }
+
+ w = calloc(1, sizeof *w);
+ if (!w) {
+ TDM_ERR("alloc failed");
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ w->private_vblank = private_vblank;
+ w->func = func;
+ w->user_data = user_data;
+
+ LIST_ADDTAIL(&w->link, &private_vblank->wait_list);
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ w->req_id = ++private_output->req_id;
+ w->req_sec = (unsigned int)tp.tv_sec;
+ w->req_usec = (unsigned int)(tp.tv_nsec / 1000);
+ w->need_free = (private_vblank->sync) ? 0 : 1;
+
+ wl_tdm_vblank_wait_vblank_seq(private_vblank->vblank, sequence, w->req_id, w->req_sec, w->req_usec);
+
+ TDM_TRACE_COUNT(ClientWaitVBlank, w->req_id);
+
if (!private_vblank->sync) {
wl_display_flush(private_client->display);
return TDM_ERROR_NONE;