keyrouter: Fix wrong return value
[platform/core/uifw/libds-tizen.git] / src / libds / buffer.c
1 #include <assert.h>
2 #include <stdlib.h>
3
4 #include "libds/log.h"
5 #include "libds/interfaces/buffer.h"
6
7 #include "buffer.h"
8 #include "client_buffer.h"
9
10 static struct wl_array buffer_resource_interfaces = {0};
11
12 static void buffer_consider_destroy(struct ds_buffer *buffer);
13 static bool ds_resource_is_buffer(struct wl_resource *resource);
14 static const struct ds_buffer_resource_interface *
15 get_buffer_resource_iface(struct wl_resource *resource);
16
17 WL_EXPORT void
18 ds_buffer_init(struct ds_buffer *buffer,
19         const struct ds_buffer_interface *iface, int width, int height)
20 {
21     buffer->iface = iface;
22     buffer->width = width;
23     buffer->height = height;
24
25     wl_signal_init(&buffer->events.destroy);
26     wl_signal_init(&buffer->events.release);
27 }
28
29 WL_EXPORT struct ds_buffer *
30 ds_buffer_from_resource(struct wl_resource *resource)
31 {
32     struct ds_buffer *buffer;
33     const struct ds_buffer_resource_interface *iface;
34
35     assert(resource && ds_resource_is_buffer(resource));
36
37     if (wl_shm_buffer_get(resource) != NULL) {
38         struct ds_shm_client_buffer *shm_client_buffer =
39             ds_shm_client_buffer_get_or_create(resource);
40         if (!shm_client_buffer) {
41             ds_err("Failed to create shm client buffer");
42             return NULL;
43         }
44
45         buffer = ds_buffer_lock(&shm_client_buffer->base);
46     }
47     else {
48         iface = get_buffer_resource_iface(resource);
49         if (!iface) {
50             ds_err("Unknown buffer type");
51             return NULL;
52         }
53
54         buffer = iface->from_resource(resource);
55         if (!buffer) {
56             ds_err("Failed to create %s buffer", iface->name);
57             return NULL;
58         }
59
60         buffer = ds_buffer_lock(buffer);
61     }
62
63     return buffer;
64 }
65
66 WL_EXPORT void
67 ds_buffer_drop(struct ds_buffer *buffer)
68 {
69     assert(!buffer->dropped);
70     buffer->dropped = true;
71     ds_dbg("Buffer(%p) dropped: n_locks(%zu)", buffer, buffer->n_locks);
72     buffer_consider_destroy(buffer);
73 }
74
75 WL_EXPORT struct ds_buffer *
76 ds_buffer_lock(struct ds_buffer *buffer)
77 {
78     buffer->n_locks++;
79     ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
80     return buffer;
81 }
82
83 WL_EXPORT void
84 ds_buffer_unlock(struct ds_buffer *buffer)
85 {
86     assert(buffer->n_locks > 0);
87     buffer->n_locks--;
88     ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
89
90     if (buffer->n_locks == 0)
91         wl_signal_emit(&buffer->events.release, NULL);
92
93     buffer_consider_destroy(buffer);
94 }
95
96 WL_EXPORT bool
97 ds_buffer_begin_data_ptr_access(struct ds_buffer *buffer, uint32_t flags,
98         void **data, uint32_t *format, size_t *stride)
99 {
100     assert(!buffer->accessing_data_ptr);
101     if (!buffer->iface->begin_data_ptr_access)
102         return false;
103     if (!buffer->iface->begin_data_ptr_access(buffer,
104                 flags, data, format, stride))
105         return false;
106     buffer->accessing_data_ptr = true;
107     return true;
108 }
109
110 WL_EXPORT void
111 ds_buffer_end_data_ptr_access(struct ds_buffer *buffer)
112 {
113     assert(buffer->accessing_data_ptr);
114     buffer->iface->end_data_ptr_access(buffer);
115     buffer->accessing_data_ptr = false;
116 }
117
118 WL_EXPORT void
119 ds_buffer_add_destroy_listener(struct ds_buffer *buffer,
120         struct wl_listener *listener)
121 {
122     wl_signal_add(&buffer->events.destroy, listener);
123 }
124
125 void
126 ds_buffer_add_release_listener(struct ds_buffer *buffer,
127         struct wl_listener *listener)
128 {
129     wl_signal_add(&buffer->events.release, listener);
130 }
131
132 WL_EXPORT bool
133 ds_buffer_get_shm(struct ds_buffer *buffer, struct ds_shm_attributes *attribs)
134 {
135     if (!buffer->iface->get_shm)
136         return false;
137
138     return buffer->iface->get_shm(buffer, attribs);
139 }
140
141 WL_EXPORT void
142 ds_buffer_get_size(struct ds_buffer *buffer, int *out_width, int *out_height)
143 {
144     if (out_width)
145         *out_width = buffer->width;
146     if (out_height)
147         *out_height = buffer->height;
148 }
149
150 WL_EXPORT void
151 ds_buffer_register_resource_interface(
152         const struct ds_buffer_resource_interface *iface)
153 {
154     const struct ds_buffer_resource_interface **iface_ptr;
155
156     assert(iface);
157     assert(iface->is_instance);
158     assert(iface->from_resource);
159
160     wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
161         if (*iface_ptr == iface) {
162             ds_dbg("ds_buffer_resource_interface %s has already "
163                     "been registered", iface->name);
164             return;
165         }
166     }
167
168     iface_ptr = wl_array_add(&buffer_resource_interfaces, sizeof(iface));
169     *iface_ptr = iface;
170 }
171
172 static void
173 buffer_consider_destroy(struct ds_buffer *buffer)
174 {
175     if (!buffer->dropped || buffer->n_locks > 0)
176         return;
177
178     assert(!buffer->accessing_data_ptr);
179
180     wl_signal_emit(&buffer->events.destroy, NULL);
181     buffer->iface->destroy(buffer);
182 }
183
184 static bool
185 ds_resource_is_buffer(struct wl_resource *resource)
186 {
187     return strcmp(wl_resource_get_class(resource),
188             wl_buffer_interface.name) == 0;
189 }
190
191 static const struct ds_buffer_resource_interface *
192 get_buffer_resource_iface(struct wl_resource *resource)
193 {
194     struct ds_buffer_resource_interface **iface_ptr;
195
196     wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
197         if ((*iface_ptr)->is_instance(resource)) {
198             return *iface_ptr;
199         }
200     }
201
202     return NULL;
203 }