4 #include <wayland-server.h>
5 #include <tizen-surface-server-protocol.h>
6 #include <wtz-blender-server-protocol.h>
8 #include <libds/util/addon.h>
9 #include <libds/types/ds_surface.h>
12 #include "libds-tizen/blender.h"
14 #define TIZEN_BLENDER_VERSION 1
16 struct ds_tizen_blender
18 struct wl_global *global;
20 struct wl_list clients;
22 struct wl_listener destroy;
25 struct wl_signal destroy;
26 struct wl_signal new_blend;
30 struct ds_tizen_blender_client
32 struct wl_list link; //clients
34 struct ds_tizen_blender *blender;
36 struct wl_resource *resource;
37 struct wl_client *wl_client;
40 struct wl_signal destroy;
46 struct wl_resource *resource;
47 struct wl_client *wl_client;
49 struct ds_tizen_blend_state current, pending;
51 struct ds_surface *surface;
52 struct ds_addon surface_addon;
55 struct wl_listener surface_commit;
59 struct wl_signal commit;
60 struct wl_signal destroy;
65 blender_handle_display_destroy(struct wl_listener *listener, void *data);
67 blender_bind(struct wl_client *wl_client, void *data, uint32_t version,
70 WL_EXPORT struct ds_tizen_blender *
71 ds_tizen_blender_create(struct wl_display *display)
73 struct ds_tizen_blender *blender;
75 blender = calloc(1, sizeof *blender);
77 ds_err("calloc() failed.");
81 blender->global = wl_global_create(display, &wtz_blender_interface,
82 TIZEN_BLENDER_VERSION, blender, blender_bind);
83 if (!blender->global) {
84 ds_err("wl_global_create() failed. tizen_surface_shm_interface");
89 wl_list_init(&blender->clients);
91 blender->destroy.notify = blender_handle_display_destroy;
92 wl_display_add_destroy_listener(display, &blender->destroy);
94 wl_signal_init(&blender->events.destroy);
95 wl_signal_init(&blender->events.new_blend);
97 ds_inf("Global created: tizen_blender(%p)", blender);
103 ds_tizen_blender_add_destroy_listener(struct ds_tizen_blender *blender,
104 struct wl_listener *listener)
106 wl_signal_add(&blender->events.destroy, listener);
110 ds_tizen_blender_add_new_blend_listener(struct ds_tizen_blender *blender,
111 struct wl_listener *listener)
113 wl_signal_add(&blender->events.new_blend, listener);
117 ds_tizen_blend_add_destroy_listener(struct ds_tizen_blend *blend,
118 struct wl_listener *listener)
120 wl_signal_add(&blend->events.destroy, listener);
124 ds_tizen_blend_add_commit_listener(struct ds_tizen_blend *blend,
125 struct wl_listener *listener)
127 wl_signal_add(&blend->events.commit, listener);
130 WL_EXPORT struct ds_surface *
131 ds_tizen_blend_get_surface(struct ds_tizen_blend *blend)
133 return blend->surface;
136 WL_EXPORT struct ds_tizen_blend_state *
137 ds_tizen_blend_get_state(struct ds_tizen_blend *blend)
139 return &blend->current;
143 blender_handle_display_destroy(struct wl_listener *listener, void *data)
145 struct ds_tizen_blender *blender;
147 blender = wl_container_of(listener, blender, destroy);
149 ds_inf("Global destroy: blender(%p)", blender);
151 wl_signal_emit_mutable(&blender->events.destroy, blender);
152 wl_list_remove(&blender->destroy.link);
153 wl_global_destroy(blender->global);
158 blend_handle_destroy(struct wl_client *client, struct wl_resource *resource)
160 wl_resource_destroy(resource);
164 blend_handle_set_alpha(struct wl_client *client, struct wl_resource *resource,
167 struct ds_tizen_blend *blend;
169 blend = wl_resource_get_user_data(resource);
171 blend->pending.alpha = alpha;
172 blend->pending.committed |= DS_TIZEN_BLEND_STATE_ALPHA;
176 blend_handle_set_equation(struct wl_client *client, struct wl_resource *resource,
179 struct ds_tizen_blend *blend;
181 blend = wl_resource_get_user_data(resource);
183 blend->pending.equation = equation;
184 blend->pending.committed |= DS_TIZEN_BLEND_STATE_EQUATION;
187 static const struct wtz_blend_interface blend_impl = {
188 blend_handle_destroy,
189 blend_handle_set_alpha,
190 blend_handle_set_equation,
194 blend_destroy(struct ds_tizen_blend *blend)
196 ds_inf("blend_destroy (blend:%p)", blend);
198 wl_signal_emit_mutable(&blend->events.destroy, blend);
200 if (blend->listener.surface_commit.notify)
201 wl_list_remove(&blend->listener.surface_commit.link);
204 ds_addon_finish(&blend->surface_addon);
210 blend_handle_resource_destroy(struct wl_resource *resource)
212 struct ds_tizen_blend *blend;
214 blend = wl_resource_get_user_data(resource);
216 ds_inf("blend_handle_resource_destroy (blend:%p)", blend);
218 if (blend->surface) {
219 blend->resource = NULL;
223 blend_destroy(blend);
227 blend_handle_surface_commit(struct wl_listener *listener, void *data)
229 struct ds_tizen_blend *blend;
231 blend = wl_container_of(listener, blend, listener.surface_commit);
233 if (!blend->resource) {
234 blend_destroy(blend);
238 if (blend->pending.committed == DS_TIZEN_BLEND_STATE_NONE) {
239 blend->current.committed = DS_TIZEN_BLEND_STATE_NONE;
243 if (blend->pending.committed & DS_TIZEN_BLEND_STATE_ALPHA)
244 blend->current.alpha = blend->pending.alpha;
246 if (blend->pending.committed & DS_TIZEN_BLEND_STATE_EQUATION)
247 blend->current.equation = blend->pending.equation;
249 blend->current.committed = blend->pending.committed;
250 blend->pending.committed = DS_TIZEN_BLEND_STATE_NONE;
252 wl_signal_emit_mutable(&blend->events.commit, blend);
256 blend_handle_surface_destroy(struct ds_addon *addon)
258 struct ds_tizen_blend *blend;
260 blend = wl_container_of(addon, blend, surface_addon);
262 if (blend->listener.surface_commit.notify) {
263 wl_list_remove(&blend->listener.surface_commit.link);
264 blend->listener.surface_commit.notify = NULL;
267 ds_addon_finish(&blend->surface_addon);
268 blend->surface = NULL;
270 if (!blend->resource)
271 blend_destroy(blend);
274 static struct ds_addon_interface blend_addon_impl = {
275 .name = "ds_tizen_blend",
276 .destroy = blend_handle_surface_destroy,
279 static struct ds_tizen_blend *
280 blend_client_get_from_surface(struct ds_tizen_blender_client *client, struct ds_surface *surface)
282 struct ds_addon *addon;
283 struct ds_tizen_blend *blend;
285 addon = ds_addon_find(&surface->addons, client, &blend_addon_impl);
286 if (!addon) return NULL;
288 blend = wl_container_of(addon, blend, surface_addon);
294 blender_handle_get_blend(struct wl_client *wl_client,
295 struct wl_resource *resource,
296 uint32_t id, struct wl_resource *surface_resource)
298 struct ds_tizen_blender_client *client;
299 struct ds_surface *surface;
300 struct ds_tizen_blend *blend;
302 ds_inf("tizen_blender: get_blend");
304 client = wl_resource_get_user_data(resource);
306 surface = ds_surface_from_resource(surface_resource);
308 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
309 "invalid wl_surface resource:%u",
310 (unsigned int)wl_resource_get_id(surface_resource));
314 blend = blend_client_get_from_surface(client, surface);
316 wl_resource_post_error(resource, WTZ_BLENDER_ERROR_BLEND_EXISTS,
317 "blend object already exists");
321 blend = calloc(1, sizeof *blend);
323 ds_err("calloc() failed. tizen_blend");
324 wl_client_post_no_memory(wl_client);
328 blend->resource = wl_resource_create(wl_client, &wtz_blend_interface,
329 wl_resource_get_version(resource), id);
330 if (blend->resource == NULL) {
331 ds_err("tizen_blend : wl_resource_create() failed.");
333 wl_client_post_no_memory(wl_client);
337 wl_resource_set_implementation(blend->resource, &blend_impl, blend,
338 blend_handle_resource_destroy);
340 ds_addon_init(&blend->surface_addon, &surface->addons, client, &blend_addon_impl);
342 blend->listener.surface_commit.notify = blend_handle_surface_commit;
343 ds_surface_add_commit_listener(surface, &blend->listener.surface_commit);
345 blend->surface = surface;
347 wl_signal_init(&blend->events.destroy);
348 wl_signal_init(&blend->events.commit);
350 wl_signal_emit_mutable(&client->blender->events.new_blend, blend);
354 blender_handle_destroy(struct wl_client *wl_client,
355 struct wl_resource *resource)
357 wl_resource_destroy(resource);
360 static const struct wtz_blender_interface blender_impl =
362 blender_handle_destroy,
363 blender_handle_get_blend,
367 blender_client_handle_destroy(struct wl_resource *resource)
369 struct ds_tizen_blender_client *client;
371 client = wl_resource_get_user_data(resource);
373 ds_inf("blender_client_handle_destroy (client:%p)", client);
375 wl_list_remove(&client->link);
380 blender_bind(struct wl_client *wl_client, void *data, uint32_t version,
383 struct ds_tizen_blender *blender = data;
384 struct ds_tizen_blender_client *client;
386 client = calloc(1, sizeof *client);
387 if (client == NULL) {
388 ds_err("calloc() failed. tizen_blender");
389 wl_client_post_no_memory(wl_client);
393 ds_inf("tizen_blender_client binds. (client:%p)", client);
395 client->blender = blender;
396 client->wl_client = wl_client;
398 client->resource = wl_resource_create(wl_client, &wtz_blender_interface,
399 MIN(version, TIZEN_BLENDER_VERSION), id);
400 if (client->resource == NULL) {
401 ds_err("tizen_blender : wl_resource_create() failed.");
403 wl_client_post_no_memory(wl_client);
407 wl_resource_set_implementation(client->resource, &blender_impl, client,
408 blender_client_handle_destroy);
410 wl_signal_init(&client->events.destroy);
412 wl_list_insert(&blender->clients, &client->link);