virtual_func_display.display_get_outputs = virtual_display_get_outputs;
virtual_func_display.display_get_fd = virtual_display_get_fd;
virtual_func_display.display_handle_events = virtual_display_handle_events;
+ virtual_func_display.display_output_create = virtual_display_output_create;
+ virtual_func_display.display_output_destroy = virtual_display_output_destroy;
memset(&virtual_func_output, 0, sizeof(virtual_func_output));
virtual_func_output.output_get_capability = virtual_output_get_capability;
ret = TDM_ERROR_OPERATION_FAILED;
goto failed;
}
-
+#if 0
ret = tdm_virtual_display_create_output_list(virtual_data);
if (ret != TDM_ERROR_NONE)
goto failed;
ret = tdm_virtual_display_create_layer_list(virtual_data);
if (ret != TDM_ERROR_NONE)
goto failed;
-
+#endif
if (error)
*error = TDM_ERROR_NONE;
#include <tdm_helper.h>
/* virtual backend functions (display) */
-tdm_error virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps);
-tdm_output** virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error);
-tdm_error virtual_display_get_fd(tdm_backend_data *bdata, int *fd);
-tdm_error virtual_display_handle_events(tdm_backend_data *bdata);
+tdm_error virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps);
+tdm_output **virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error);
+tdm_error virtual_display_get_fd(tdm_backend_data *bdata, int *fd);
+tdm_error virtual_display_handle_events(tdm_backend_data *bdata);
+tdm_output *virtual_display_output_create(tdm_backend_data *bdata, const char* name, tdm_error *error);
+tdm_error virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output);
-tdm_error virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps);
-tdm_layer** virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error);
-tdm_error virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data);
-tdm_error virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func);
-tdm_error virtual_output_commit(tdm_output *output, int sync, void *user_data);
-tdm_error virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func);
-tdm_error virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode);
-tdm_error virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode);
+tdm_error virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps);
+tdm_layer **virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error);
+tdm_error virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data);
+tdm_error virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func);
+tdm_error virtual_output_commit(tdm_output *output, int sync, void *user_data);
+tdm_error virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func);
+tdm_error virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode);
+tdm_error virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode);
-tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
-tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info);
-tdm_error virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info);
-tdm_error virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
-tdm_error virtual_layer_unset_buffer(tdm_layer *layer);
+tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
+tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info);
+tdm_error virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info);
+tdm_error virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
+tdm_error virtual_layer_unset_buffer(tdm_layer *layer);
#define RETURN_VAL_IF_FAIL(cond, val) {\
- if (!(cond)) {\
- TDM_ERR("'%s' failed", #cond);\
- return val;\
- }\
+ if (!(cond)) {\
+ TDM_ERR("'%s' failed", #cond);\
+ return val;\
+ }\
}
#define GOTO_IF_FAIL(cond, val) {\
- if (!(cond)) {\
- TDM_ERR("'%s' failed", #cond);\
- goto val;\
- }\
+ if (!(cond)) {\
+ TDM_ERR("'%s' failed", #cond);\
+ goto val;\
+ }\
}
typedef struct _tdm_virtual_data
{
- tdm_display *dpy;
+ tdm_display *dpy;
- int pipe[2];
+ int pipe[2];
- struct list_head output_list;
- struct list_head buffer_list;
+ struct list_head output_list;
+ struct list_head buffer_list;
} tdm_virtual_data;
-tdm_error tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data);
void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data);
-tdm_error tdm_virtual_display_create_layer_list(tdm_virtual_data *virtual_data);
#endif /* _TDM_VIRTUAL_H_ */
uint32_t pipe;
tdm_output_mode *output_mode;
+ int mode_count;
tdm_output_type connector_type;
struct list_head layer_list;
tdm_virtual_layer_data *primary_layer;
tdm_event_loop_source *timer;
unsigned int timer_waiting;
struct list_head timer_event_list;
+
+ unsigned int mmwidth;
+ unsigned int mmheight;
+
+ char name[TDM_NAME_LEN]; /**< The output name */
};
struct _tdm_virtual_layer_data {
output_data->virtual_data = virtual_data;
output_data->pipe = 0;
output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
- output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
+ output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
output_data->output_mode = calloc(1, sizeof(tdm_output_mode));
if (!output_data->output_mode) {
return TDM_ERROR_NONE;
}
+tdm_output *
+virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error)
+{
+ tdm_virtual_data *virtual_data = bdata;
+ tdm_virtual_output_data *output_data = NULL;
+ tdm_virtual_layer_data *layer_data = NULL;
+ tdm_error ret;
+
+ if (!virtual_data || !name) {
+ TDM_ERR("invalid parameter");
+ *error = TDM_ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ output_data = calloc(1, sizeof(tdm_virtual_output_data));
+ if (!output_data) {
+ TDM_ERR("alloc failed");
+ *error = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ LIST_INITHEAD(&output_data->layer_list);
+
+ output_data->virtual_data = virtual_data;
+ output_data->pipe = 0;
+ output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
+ output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+
+ if (name)
+ snprintf(output_data->name, TDM_NAME_LEN, "%s", name);
+ else
+ snprintf(output_data->name, TDM_NAME_LEN, "unknown");
+#if 0
+ output_data->output_mode = calloc(1, sizeof(tdm_output_mode));
+ if (!output_data->output_mode) {
+ TDM_ERR("alloc failed");
+ ret = TDM_ERROR_OUT_OF_MEMORY;
+ goto create_fail;
+ }
+
+ snprintf(output_data->output_mode->name, TDM_NAME_LEN, "640x480");
+ output_data->output_mode->vrefresh = 30;
+ output_data->output_mode->clock = 25200;
+ output_data->output_mode->hdisplay = 640;
+ output_data->output_mode->hsync_start = 656;
+ output_data->output_mode->hsync_end = 752;
+ output_data->output_mode->htotal = 800;
+ output_data->output_mode->hskew = 0;
+ output_data->output_mode->vdisplay = 480;
+ output_data->output_mode->vsync_start = 490;
+ output_data->output_mode->vsync_end = 492;
+ output_data->output_mode->vtotal = 525;
+ output_data->output_mode->vscan = 0;
+ output_data->output_mode->flags = 0;
+ output_data->output_mode->type = 0;
+
+ output_data->mode_count = 1;
+#endif
+ output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
+ _tdm_virtual_display_cb_timeout,
+ output_data,
+ &ret);
+ if (!output_data->timer) goto create_fail;
+
+ LIST_INITHEAD(&output_data->timer_event_list);
+
+ /* The TDM virtual backend output support only one layer. */
+ layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
+ if (!layer_data) {
+ TDM_ERR("alloc failed");
+ ret = TDM_ERROR_OUT_OF_MEMORY;
+ goto create_fail;
+ }
+
+ layer_data->virtual_data = virtual_data;
+ layer_data->output_data = output_data;
+ layer_data->zpos = 0;
+
+ layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
+ output_data->primary_layer = layer_data;
+
+ LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
+
+ ret = tdm_backend_register_output(virtual_data->dpy, output_data);
+ GOTO_IF_FAIL(ret == TDM_ERROR_NONE, create_fail);
+
+ *error = TDM_ERROR_NONE;
+
+ return output_data;
+
+create_fail:
+ if (layer_data) free(layer_data);
+ if (output_data->output_mode) free(output_data->output_mode);
+ free(output_data);
+
+ *error = ret;
+
+ return NULL;
+}
+
+tdm_error
+virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output)
+{
+ tdm_virtual_data *virtual_data = bdata;
+ tdm_virtual_output_data *o, *output_data = output;
+ int find = 0;
+
+ RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+ LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
+ if (o == output_data) {
+ find = 1;
+ break;
+ }
+ }
+
+ if (find)
+ tdm_backend_unregister_output(virtual_data->dpy, output);
+ else
+ return TDM_ERROR_INVALID_PARAMETER;
+
+ return TDM_ERROR_NONE;
+}
+
tdm_error
virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
{
snprintf(caps->maker, TDM_NAME_LEN, "virtual");
snprintf(caps->model, TDM_NAME_LEN, "virtual");
- snprintf(caps->name, TDM_NAME_LEN, "virtual");
+ snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name);
caps->status = output_data->status;
caps->type = output_data->connector_type;
caps->type_id = 0;
- caps->mode_count = 1;
- caps->modes = calloc(1, sizeof(tdm_output_mode));
- if (!caps->modes) {
- ret = TDM_ERROR_OUT_OF_MEMORY;
- TDM_ERR("alloc failed\n");
- goto failed_get;
- }
+ caps->mode_count = output_data->mode_count;
+ if (output_data->mode_count != 0) {
+ caps->modes = calloc(output_data->mode_count, sizeof(tdm_output_mode));
+ if (!caps->modes) {
+ ret = TDM_ERROR_OUT_OF_MEMORY;
+ TDM_ERR("alloc failed\n");
+ goto failed_get;
+ }
- *caps->modes = *output_data->output_mode;
+ *caps->modes = *output_data->output_mode;
+ }
- caps->mmWidth = 640;
- caps->mmHeight = 480;
+ caps->mmWidth = output_data->mmwidth;
+ caps->mmHeight =output_data->mmheight;
caps->subpixel = 1;
caps->min_w = -1;
TDM_UT_PIPE_MSG_TERMINATE_SERVER,
};
+#define TDM_UT_WAIT(fmt, ...) \
+ do { \
+ char ch; \
+ do { \
+ printf(fmt" [n]):next ", ##__VA_ARGS__); \
+ ch = tc_tdm_getchar(); \
+ } while(ch != 'n'); \
+ } while (0)
+
static int _tc_tdm_pipe_read_msg(int fd);
static bool _tc_tdm_pipe_write_msg(int fd, int reply_fd, int msg);
static pid_t _tc_tdm_client_server_fork(int *pipe_to_parent, int *pipe_to_child);
return true;
}
+char
+tc_tdm_getchar(void)
+{
+ int c = getchar();
+ int ch = c;
+
+ if (ch == '\n' || ch == '\r')
+ ch = 'y';
+ else if (ch < 'a')
+ ch += ('a' - 'A');
+
+ while (c != '\n' && c != EOF)
+ c = getchar();
+
+ return ch;
+}
+
static int
_tc_tdm_pipe_read_msg(int fd)
{
TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
TDM_UT_RETURN_FALSE_IF_FAIL(client != NULL);
+
voutput = tdm_client_create_voutput(client, name, &ret);
TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
TDM_UT_RETURN_FALSE_IF_FAIL(voutput != NULL);
+
+// TDM_UT_WAIT("check & press");
+
return true;
}
*/
tdm_pp *(*display_create_pp)(tdm_backend_data *bdata, tdm_error *error);
- void (*reserved1)(void);
- void (*reserved2)(void);
+ /* virtual */
+ tdm_output *(*display_output_create)(tdm_backend_data *bdata, const char *name, tdm_error *error);
+ tdm_error (*display_output_destroy)(tdm_backend_data *bdata, tdm_output *output);
+
void (*reserved3)(void);
void (*reserved4)(void);
void (*reserved5)(void);
return NULL;
}
+INTERN tdm_output *
+tdm_display_create_output(tdm_display *dpy, const char *name, tdm_error *error)
+{
+ tdm_private_module *private_module = NULL;
+ tdm_private_module *current_module = NULL;
+ tdm_func_display *func_display = NULL;
+ tdm_output *output = NULL;
+
+ DISPLAY_FUNC_ENTRY_ERROR();
+
+ TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL);
+ private_display = (tdm_private_display*)dpy;
+
+ private_module = private_display->virtual_module;
+ TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_module != NULL, TDM_ERROR_BAD_MODULE, NULL);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ func_display = &private_module->func_display;
+ current_module = private_display->current_module;
+ private_display->current_module = private_module;
+ output = func_display->display_output_create(private_module->bdata, name, &ret);
+ private_display->current_module = current_module;
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, ret, NULL);
+
+ return output;
+}
+
+INTERN tdm_error
+tdm_display_destroy_output(tdm_display *dpy, tdm_output *output)
+{
+ tdm_private_module *private_module = NULL;
+ tdm_private_module *current_module = NULL;
+ tdm_func_display *func_display = NULL;
+
+ DISPLAY_FUNC_ENTRY();
+
+ TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ private_display = (tdm_private_display*)dpy;
+
+ private_module = private_display->virtual_module;
+ TDM_RETURN_VAL_IF_FAIL(private_module != NULL, TDM_ERROR_BAD_MODULE);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ func_display = &private_module->func_display;
+ current_module = private_display->current_module;
+ private_display->current_module = private_module;
+ ret = func_display->display_output_destroy(private_module->bdata, output);
+ private_display->current_module = current_module;
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}
+
EXTERN tdm_error
tdm_display_get_fd(tdm_display *dpy, int *fd)
{
void
tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len);
+tdm_output *
+tdm_display_create_output(tdm_display *dpy, const char *name, tdm_error *error);
+tdm_error
+tdm_display_destroy_output(tdm_display *dpy, tdm_output *output);
+
#ifdef __cplusplus
}
#endif
struct _tdm_private_server {
tdm_private_loop *private_loop;
struct list_head output_list;
+ struct list_head voutput_list;
struct list_head wait_list;
};
unsigned int watch_output_changes;
} tdm_server_output_info;
+typedef struct _tdm_server_voutput_info {
+ struct list_head link;
+ tdm_private_server *private_server;
+ struct wl_resource *resource;
+ tdm_output *output;
+ struct list_head output_list;
+} tdm_server_voutput_info;
+
typedef struct _tdm_server_vblank_info {
struct list_head link;
tdm_server_output_info *output_info;
free(output_info);
}
+#if 0
+static void
+destroy_voutput_callback(struct wl_resource *resource)
+{
+ tdm_server_voutput_info *voutput_info = wl_resource_get_user_data(resource);
+
+ TDM_RETURN_IF_FAIL(voutput_info != NULL);
+
+ LIST_DEL(&voutput_info->link);
+ free(voutput_info);
+}
+#endif
static void
_tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resource,
const char *name, uint32_t id)
_tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resource *resource, const char *name, uint32_t id)
{
struct wl_resource *voutput_resource = NULL;
+ tdm_private_server *private_server = wl_resource_get_user_data(resource);
+ tdm_server_voutput_info *voutput_info;
+ tdm_output *output;
+ tdm_error ret;
+
+ output = tdm_display_find_output(private_server->private_loop->dpy, name, NULL);
+ if (output) {
+ TDM_ERR("There is '%s' output, cannot create.", name);
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "There is '%s' output", name);
+ return;
+ }
+
+ output = tdm_display_create_output(private_server->private_loop->dpy, name, &ret);
+ if (!output) {
+ TDM_ERR("output creation fail(%s)(%d).", name, ret);
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_NO_MEMORY,
+ "%s output creation fail", name);
+ return;
+ }
voutput_resource =
wl_resource_create(client, &wl_tdm_voutput_interface,
/* LCOV_EXCL_STOP */
}
+ voutput_info = calloc(1, sizeof * voutput_info);
+ if (!voutput_info) {
+ /* LCOV_EXCL_START */
+
+ wl_resource_post_no_memory(resource);
+ wl_resource_destroy(voutput_resource);
+ TDM_ERR("alloc failed");
+ return;
+
+ /* LCOV_EXCL_STOP */
+ }
+
+ LIST_ADDTAIL(&voutput_info->link, &private_server->voutput_list);
+ voutput_info->private_server = private_server;
+ voutput_info->resource = voutput_resource;
+ voutput_info->output = output;
+ LIST_INITHEAD(&voutput_info->output_list);
+#if 0
+ wl_resource_set_implementation(voutput_resource, &tdm_voutput_implementation,
+ voutput_info, destroy_voutput_callback);
+#endif
wl_tdm_voutput_send_ack_message(voutput_resource, WL_TDM_VOUTPUT_MESSAGE_ADDED);
}
}
LIST_INITHEAD(&private_server->output_list);
+ LIST_INITHEAD(&private_server->voutput_list);
LIST_INITHEAD(&private_server->wait_list);
if (!wl_global_create(private_loop->wl_display, &wl_tdm_interface, 1,
tdm_server_deinit(tdm_private_loop *private_loop)
{
tdm_server_output_info *o = NULL, *oo = NULL;
+// tdm_server_voutput_info *vo = NULL, *voo = NULL;
tdm_server_wait_info *w = NULL, *ww = NULL;
tdm_server_client_info *c = NULL, *cc = NULL;
tdm_private_server *private_server;
LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_server->output_list, link) {
wl_resource_destroy(o->resource);
}
-
+#if 0
+ LIST_FOR_EACH_ENTRY_SAFE(vo, voo, &private_server->voutput_list, link) {
+ wl_resource_destroy(vo->resource);
+ }
+#endif
LIST_FOR_EACH_ENTRY_SAFE(c, cc, &client_list, link) {
wl_resource_destroy(c->resource);
}