change wl_signal_emit_mutable into wl_signal_emit
[platform/core/uifw/libds-tizen.git] / examples / tinyds-renderer.c
1 #include <assert.h>
2 #include <stdlib.h>
3
4 #include <libds/log.h>
5
6 #include "pixman-helper.h"
7 #include "pixman-tbm-helper.h"
8 #include "tinyds-renderer.h"
9
10 static void renderer_setup_thread(struct tinyds_renderer *renderer);
11 static void *renderer_thread_func(void *data);
12 static void texture_destroy(struct tinyds_texture *texture);
13
14 bool
15 init_renderer(struct tinyds_renderer *renderer)
16 {
17     renderer->damaged = false;
18
19     wl_list_init(&renderer->textures);
20
21     renderer_setup_thread(renderer);
22
23     return true;
24 }
25
26 void
27 fini_renderer(struct tinyds_renderer *renderer)
28 {
29     pthread_mutex_lock(&renderer->mutex);
30
31     renderer->destroying = true;
32     pthread_cond_signal(&renderer->cond);
33
34     pthread_mutex_unlock(&renderer->mutex);
35
36     pthread_join(renderer->worker_thread, NULL);
37
38     pthread_mutex_destroy(&renderer->mutex);
39     pthread_cond_destroy(&renderer->cond);
40 }
41
42 void
43 renderer_set_surface_queue(struct tinyds_renderer *renderer,
44         void *surface_queue)
45 {
46     pthread_mutex_lock(&renderer->mutex);
47
48     renderer->surface_queue = (tbm_surface_queue_h)surface_queue;
49
50     pthread_mutex_unlock(&renderer->mutex);
51 }
52
53 void
54 renderer_set_bg_color(struct tinyds_renderer *renderer,
55         uint8_t r, uint8_t g, uint8_t b)
56 {
57     pixman_color_t color;
58
59     pthread_mutex_lock(&renderer->mutex);
60
61     color_rgb888(&color, r, g, b);
62
63     renderer->bg_image = pixman_image_create_solid_fill(&color);
64     assert(renderer->bg_image);
65
66     renderer->damaged = true;
67
68     pthread_mutex_unlock(&renderer->mutex);
69 }
70
71 #ifdef USE_CURSOR
72 void
73 renderer_cursor_create(struct tinyds_renderer *renderer,
74         uint8_t r, uint8_t g, uint8_t b, uint32_t width, uint32_t height)
75 {
76     pixman_color_t color;
77
78     pthread_mutex_lock(&renderer->mutex);
79
80     color_rgb888(&color, r, g, b);
81
82     renderer->cursor_image = pixman_image_create_solid_fill(&color);
83     assert(renderer->cursor_image);
84
85     renderer->damaged = true;
86
87     renderer->cursor.w = width;
88     renderer->cursor.h = height;
89
90     pthread_mutex_unlock(&renderer->mutex);
91 }
92
93 void
94 renderer_cursor_destroy(struct tinyds_renderer *renderer)
95 {
96     pthread_mutex_lock(&renderer->mutex);
97
98     if (renderer->cursor_image)
99     {
100         pixman_image_unref(renderer->cursor_image);
101         renderer->cursor_image = NULL;
102     }
103
104     renderer->damaged = true;
105
106     pthread_mutex_unlock(&renderer->mutex);
107 }
108
109 void
110 renderer_cursor_update(struct tinyds_renderer *renderer,
111         uint32_t x, uint32_t y)
112 {
113     pthread_mutex_lock(&renderer->mutex);
114
115     renderer->cursor.x = x;
116     renderer->cursor.y = y;
117
118     pthread_mutex_unlock(&renderer->mutex);
119 }
120 #endif
121
122 void
123 renderer_add_texture(struct tinyds_renderer *renderer,
124         tbm_surface_h tbm_surface, int x, int y)
125 {
126     struct tinyds_texture *texture;
127
128     pthread_mutex_lock(&renderer->mutex);
129
130     texture = calloc(1, sizeof *texture);
131
132     texture->x = x;
133     texture->y = y;
134     texture->renderer = renderer;
135     texture->surface = tbm_surface;
136     texture->image = pixman_image_from_tbm_surface(tbm_surface,
137             DS_BUFFER_DATA_PTR_ACCESS_READ);
138
139     wl_list_insert(renderer->textures.prev, &texture->link);
140
141     ds_dbg("Add texture(%p)", texture);
142
143     pthread_mutex_unlock(&renderer->mutex);
144 }
145
146 void
147 renderer_draw(struct tinyds_renderer *renderer)
148 {
149     pthread_mutex_lock(&renderer->mutex);
150
151     renderer->damaged = true;
152     pthread_cond_signal(&renderer->cond);
153
154     pthread_mutex_unlock(&renderer->mutex);
155 }
156
157 static void
158 renderer_setup_thread(struct tinyds_renderer *renderer)
159 {
160     pthread_mutex_init(&renderer->mutex, NULL);
161     pthread_cond_init(&renderer->cond, NULL);
162     pthread_create(&renderer->worker_thread, NULL,
163             renderer_thread_func, renderer);
164 }
165
166 static void *
167 renderer_thread_func(void *data)
168 {
169     struct tinyds_renderer *renderer = data;
170     struct tinyds_texture *texture, *texture_tmp;
171     pixman_image_t *dst_image;
172     tbm_surface_h surface;
173     tbm_surface_queue_error_e err;
174
175     pthread_mutex_lock(&renderer->mutex);
176
177     while (!renderer->destroying) {
178         if (!renderer->damaged)
179             pthread_cond_wait(&renderer->cond, &renderer->mutex);
180
181         if (!renderer->damaged)
182             continue;
183
184         if (!tbm_surface_queue_can_dequeue(renderer->surface_queue, 0))
185             continue;
186
187         ds_dbg(">> BEGIN DRAW");
188
189         err = tbm_surface_queue_dequeue(renderer->surface_queue, &surface);
190         assert(err == TBM_SURFACE_QUEUE_ERROR_NONE);
191
192         dst_image = pixman_image_from_tbm_surface(surface,
193                 DS_BUFFER_DATA_PTR_ACCESS_WRITE);
194
195         if (renderer->bg_image) {
196             pixman_image_composite32(PIXMAN_OP_SRC,
197                     renderer->bg_image,
198                     NULL,
199                     dst_image,
200                     0, 0, 0, 0, 0, 0,
201                     pixman_image_get_width(dst_image),
202                     pixman_image_get_height(dst_image));
203         }
204
205 #ifdef USE_CURSOR
206         if (renderer->cursor_image) {
207             pixman_image_composite32(PIXMAN_OP_OVER,
208                     renderer->cursor_image,
209                     NULL,
210                     dst_image,
211                     0, 0, 0, 0,
212                     renderer->cursor.x, renderer->cursor.y,
213                     renderer->cursor.w, renderer->cursor.h);
214         }
215 #endif
216
217         wl_list_for_each_safe(texture, texture_tmp, &renderer->textures, link) {
218             ds_dbg("Draw texture(%p)", texture);
219             pixman_image_composite32(PIXMAN_OP_OVER,
220                     texture->image,
221                     NULL,
222                     dst_image,
223                     0, 0, 0, 0,
224                     texture->x, texture->y,
225                     pixman_image_get_width(texture->image),
226                     pixman_image_get_height(texture->image));
227             texture_destroy(texture);
228         }
229         pixman_image_unref(dst_image);
230
231         err = tbm_surface_queue_enqueue(renderer->surface_queue, surface);
232         assert(err == TBM_SURFACE_QUEUE_ERROR_NONE);
233
234         renderer->damaged = false;
235
236         ds_dbg("<< END DRAW");
237     }
238
239     pthread_mutex_unlock(&renderer->mutex);
240
241     return NULL;
242 }
243
244 static void
245 texture_destroy(struct tinyds_texture *texture)
246 {
247     pixman_image_unref(texture->image);
248     wl_list_remove(&texture->link);
249     free(texture);
250 }