1 /**************************************************************************
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8 JinYoung Jeon <jy0.jeon@samsung.com>,
9 Taeheon Kim <th908.kim@samsung.com>,
10 YoungJun Cho <yj44.cho@samsung.com>,
11 SooChan Lim <sc1.lim@samsung.com>,
12 Boram Park <sc1.lim@samsung.com>
14 Permission is hereby granted, free of charge, to any person obtaining a
15 copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sub license, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 **************************************************************************/
41 #include "tdm_private.h"
43 #include "tdm-server-protocol.h"
46 * - tdm server doesn't care about thread things.
47 * - DO NOT use the TDM internal functions here.
50 struct _tdm_private_server {
51 struct list_head vblank_list;
54 typedef struct _tdm_server_vblank_info {
55 struct list_head link;
56 struct wl_resource *resource;
57 tdm_private_server *private_server;
58 } tdm_server_vblank_info;
60 static tdm_private_server *keep_private_server;
63 _tdm_server_cb_output_vblank(tdm_output *output, unsigned int sequence,
64 unsigned int tv_sec, unsigned int tv_usec,
67 tdm_server_vblank_info *vblank_info = (tdm_server_vblank_info*)user_data;
68 tdm_server_vblank_info *found;
70 if (!keep_private_server)
73 LIST_FIND_ITEM(vblank_info, &keep_private_server->vblank_list,
74 tdm_server_vblank_info, link, found);
76 TDM_DBG("vblank_info(%p) is destroyed", vblank_info);
80 TDM_DBG("wl_tdm_vblank@%d done", wl_resource_get_id(vblank_info->resource));
82 wl_tdm_vblank_send_done(vblank_info->resource, sequence, tv_sec, tv_usec);
83 wl_resource_destroy(vblank_info->resource);
87 destroy_vblank_callback(struct wl_resource *resource)
89 tdm_server_vblank_info *vblank_info = wl_resource_get_user_data(resource);
90 LIST_DEL(&vblank_info->link);
95 _tdm_server_cb_wait_vblank(struct wl_client *client,
96 struct wl_resource *resource,
97 uint32_t id, const char *name, int32_t interval)
99 tdm_private_loop *private_loop = wl_resource_get_user_data(resource);
100 tdm_private_server *private_server = private_loop->private_server;
101 tdm_server_vblank_info *vblank_info;
102 struct wl_resource *vblank_resource;
103 tdm_output *found = NULL;
107 TDM_DBG("The tdm client requests vblank");
109 tdm_display_get_output_count(private_loop->dpy, &count);
111 for (i = 0; i < count; i++) {
112 tdm_output *output= tdm_display_get_output(private_loop->dpy, i, NULL);
113 tdm_output_conn_status status;
114 const char *model = NULL;
116 ret = tdm_output_get_conn_status(output, &status);
117 if (ret || status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
120 ret = tdm_output_get_model_info(output, NULL, &model, NULL);
124 if (strncmp(model, name, TDM_NAME_LEN))
132 wl_resource_post_error(resource, WL_TDM_ERROR_INVALID_NAME,
133 "There is no '%s' output", name);
134 TDM_ERR("There is no '%s' output", name);
139 wl_resource_create(client, &wl_tdm_vblank_interface,
140 wl_resource_get_version(resource), id);
141 if (!vblank_resource) {
142 wl_resource_post_no_memory(resource);
143 TDM_ERR("wl_resource_create failed");
147 vblank_info = calloc(1, sizeof *vblank_info);
149 wl_resource_destroy(vblank_resource);
150 wl_resource_post_no_memory(resource);
151 TDM_ERR("alloc failed");
155 TDM_DBG("wl_tdm_vblank@%d output(%s) interval(%d)", id, name, interval);
157 ret = tdm_output_wait_vblank(found, interval, 0,
158 _tdm_server_cb_output_vblank, vblank_info);
159 if (ret != TDM_ERROR_NONE) {
160 wl_resource_destroy(vblank_resource);
162 wl_resource_post_error(resource, WL_TDM_ERROR_OPERATION_FAILED,
163 "couldn't wait vblank for %s", name);
164 TDM_ERR("couldn't wait vblank for %s", name);
168 vblank_info->resource = vblank_resource;
169 vblank_info->private_server = private_server;
171 wl_resource_set_implementation(vblank_resource, NULL, vblank_info,
172 destroy_vblank_callback);
174 LIST_ADDTAIL(&vblank_info->link, &private_server->vblank_list);
177 static const struct wl_tdm_interface tdm_implementation = {
178 _tdm_server_cb_wait_vblank,
182 _tdm_server_bind(struct wl_client *client, void *data,
183 uint32_t version, uint32_t id)
185 struct wl_resource *resource;
187 resource = wl_resource_create(client, &wl_tdm_interface, version, id);
189 wl_client_post_no_memory(client);
193 TDM_DBG("tdm server binding");
195 wl_resource_set_implementation(resource, &tdm_implementation, data, NULL);
199 tdm_server_init(tdm_private_loop *private_loop)
201 tdm_private_server *private_server;
203 if (private_loop->private_server)
204 return TDM_ERROR_NONE;
206 TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_OPERATION_FAILED);
207 TDM_RETURN_VAL_IF_FAIL(private_loop->wl_display, TDM_ERROR_OPERATION_FAILED);
209 if(wl_display_add_socket(private_loop->wl_display, "tdm-socket")) {
210 TDM_ERR("createing a tdm-socket failed");
211 return TDM_ERROR_OPERATION_FAILED;
214 private_server = calloc(1, sizeof *private_server);
215 if (!private_server) {
216 TDM_ERR("alloc failed");
217 return TDM_ERROR_OUT_OF_MEMORY;
220 LIST_INITHEAD(&private_server->vblank_list);
222 if (!wl_global_create(private_loop->wl_display, &wl_tdm_interface, 1,
223 private_loop, _tdm_server_bind)) {
224 TDM_ERR("creating a global resource failed");
225 free(private_server);
226 return TDM_ERROR_OUT_OF_MEMORY;
229 private_loop->private_server = private_server;
230 keep_private_server = private_server;
232 return TDM_ERROR_NONE;
236 tdm_server_deinit(tdm_private_loop *private_loop)
238 tdm_server_vblank_info *v = NULL, *vv = NULL;
239 tdm_private_server *private_server;
241 if (!private_loop->private_server)
244 private_server = private_loop->private_server;
246 LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_server->vblank_list, link) {
247 wl_resource_destroy(v->resource);
250 free(private_server);
251 private_loop->private_server = NULL;
252 keep_private_server = NULL;