fix some syntax errors
[platform/core/uifw/libtdm.git] / src / tdm_helper.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
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>
13  *
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:
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
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.
33  *
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <png.h>
41 #include <string.h>
42 #include <tbm_surface.h>
43 #include <tbm_surface_internal.h>
44 #include <string.h>
45 #include <time.h>
46 #include <pixman.h>
47
48 #include "tdm.h"
49 #include "tdm_private.h"
50 #include "tdm_helper.h"
51
52 #define PNG_DEPTH 8
53
54 static const char *dump_prefix[2] = {"png", "yuv"};
55
56 int tdm_dump_enable;
57
58 INTERN unsigned long
59 tdm_helper_get_time_in_millis(void)
60 {
61         struct timespec tp;
62
63         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
64                 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
65
66         return 0;
67 }
68
69 INTERN unsigned long
70 tdm_helper_get_time_in_micros(void)
71 {
72         struct timespec tp;
73
74         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
75                 return (tp.tv_sec * 1000000) + (tp.tv_nsec / 1000L);
76
77         return 0;
78 }
79
80 static void
81 _tdm_helper_dump_raw(const char *file, void *data1, int size1, void *data2,
82                                          int size2, void *data3, int size3)
83 {
84         unsigned int *blocks;
85         FILE *fp = fopen(file, "w+");
86         TDM_RETURN_IF_FAIL(fp != NULL);
87
88         blocks = (unsigned int *)data1;
89         fwrite(blocks, 1, size1, fp);
90
91         if (size2 > 0) {
92                 blocks = (unsigned int *)data2;
93                 fwrite(blocks, 1, size2, fp);
94         }
95
96         if (size3 > 0) {
97                 blocks = (unsigned int *)data3;
98                 fwrite(blocks, 1, size3, fp);
99         }
100
101         fclose(fp);
102 }
103
104 static void
105 _tdm_helper_dump_png(const char *file, const void *data, int width,
106                                          int height)
107 {
108         FILE *fp = fopen(file, "wb");
109         TDM_RETURN_IF_FAIL(fp != NULL);
110
111         png_structp pPngStruct =
112                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
113         if (!pPngStruct) {
114                 fclose(fp);
115                 return;
116         }
117
118         png_infop pPngInfo = png_create_info_struct(pPngStruct);
119         if (!pPngInfo) {
120                 png_destroy_write_struct(&pPngStruct, NULL);
121                 fclose(fp);
122                 return;
123         }
124
125         png_init_io(pPngStruct, fp);
126         png_set_IHDR(pPngStruct,
127                                  pPngInfo,
128                                  width,
129                                  height,
130                                  PNG_DEPTH,
131                                  PNG_COLOR_TYPE_RGBA,
132                                  PNG_INTERLACE_NONE,
133                                  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
134
135         png_set_bgr(pPngStruct);
136         png_write_info(pPngStruct, pPngInfo);
137
138         const int pixel_size = 4;       // RGBA
139         png_bytep *row_pointers =
140                 png_malloc(pPngStruct, height * sizeof(png_byte *));
141
142         unsigned int *blocks = (unsigned int *)data;
143         int y = 0;
144         int x = 0;
145
146         for (; y < height; ++y) {
147                 png_bytep row =
148                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
149                 row_pointers[y] = (png_bytep)row;
150                 for (x = 0; x < width; ++x) {
151                         unsigned int curBlock = blocks[y * width + x];
152                         row[x * pixel_size] = (curBlock & 0xFF);
153                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
154                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
155                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
156                 }
157         }
158
159         png_write_image(pPngStruct, row_pointers);
160         png_write_end(pPngStruct, pPngInfo);
161
162         for (y = 0; y < height; y++)
163                 png_free(pPngStruct, row_pointers[y]);
164         png_free(pPngStruct, row_pointers);
165
166         png_destroy_write_struct(&pPngStruct, &pPngInfo);
167
168         fclose(fp);
169 }
170
171 EXTERN void
172 tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file)
173 {
174         tbm_surface_info_s info;
175         int len, ret;
176         const char *prefix;
177
178         TDM_RETURN_IF_FAIL(buffer != NULL);
179         TDM_RETURN_IF_FAIL(file != NULL);
180
181         ret = tbm_surface_map(buffer, TBM_OPTION_READ, &info);
182         TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
183
184         len = strnlen(file, 1024);
185         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
186                 prefix = dump_prefix[0];
187         else
188                 prefix = dump_prefix[1];
189
190         if (strncmp(file + (len - 3), prefix, 3)) {
191                 TDM_ERR("can't dump to '%s' file", file + (len - 3));
192                 tbm_surface_unmap(buffer);
193                 return;
194         }
195
196         switch (info.format) {
197         case TBM_FORMAT_ARGB8888:
198         case TBM_FORMAT_XRGB8888:
199                 _tdm_helper_dump_png(file, info.planes[0].ptr,
200                                                          info.planes[0].stride >> 2, info.height);
201                 break;
202         case TBM_FORMAT_YVU420:
203         case TBM_FORMAT_YUV420:
204                 _tdm_helper_dump_raw(file,
205                                                          info.planes[0].ptr,
206                                                          info.planes[0].stride * info.height,
207                                                          info.planes[1].ptr,
208                                                          info.planes[1].stride * (info.height >> 1),
209                                                          info.planes[2].ptr,
210                                                          info.planes[2].stride * (info.height >> 1));
211                 break;
212         case TBM_FORMAT_NV12:
213         case TBM_FORMAT_NV21:
214                 _tdm_helper_dump_raw(file,
215                                                          info.planes[0].ptr,
216                                                          info.planes[0].stride * info.height,
217                                                          info.planes[1].ptr,
218                                                          info.planes[1].stride * (info.height >> 1), NULL,
219                                                          0);
220                 break;
221         case TBM_FORMAT_YUYV:
222         case TBM_FORMAT_UYVY:
223                 _tdm_helper_dump_raw(file,
224                                                          info.planes[0].ptr,
225                                                          info.planes[0].stride * info.height, NULL, 0,
226                                                          NULL, 0);
227                 break;
228         default:
229                 TDM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
230                 tbm_surface_unmap(buffer);
231                 return;
232         }
233
234         tbm_surface_unmap(buffer);
235
236         TDM_INFO("dump %s", file);
237 }
238
239 EXTERN int
240 tdm_helper_get_fd(const char *env)
241 {
242         const char *value;
243         int fd, newfd, flags, ret;
244
245         value = (const char*)getenv(env);
246         if (!value)
247                 return -1;
248
249         ret = sscanf(value, "%d", &fd);
250         if (ret < 0) {
251                 TDM_ERR("sscanf failed: %m");
252                 return -1;
253         }
254
255         flags = fcntl(fd, F_GETFD);
256         if (flags == -1) {
257                 TDM_ERR("fcntl failed: %m");
258                 return -1;
259         }
260
261         newfd = dup(fd);
262         if (newfd < 0) {
263                 TDM_ERR("dup failed: %m");
264                 return -1;
265         }
266
267         TDM_INFO("%s: fd(%d) newfd(%d)", env, fd, newfd);
268
269         fcntl(newfd, F_SETFD, flags | FD_CLOEXEC);
270
271         return newfd;
272 }
273
274 EXTERN void
275 tdm_helper_set_fd(const char *env, int fd)
276 {
277         char buf[32];
278         int ret;
279
280         snprintf(buf, sizeof(buf), "%d", fd);
281
282         ret = setenv(env, (const char*)buf, 1);
283         if (ret) {
284                 TDM_ERR("setenv failed: %m");
285                 return;
286         }
287
288         if (fd >= 0)
289                 TDM_INFO("%s: fd(%d)", env, fd);
290 }
291
292 EXTERN void
293 tdm_helper_dump_start(char *dumppath, int *count)
294 {
295         if (dumppath == NULL || count == NULL) {
296                 TDM_DBG("tdm_helper_dump dumppath or count is null.");
297                 return;
298         }
299
300         tdm_dump_enable = 1;
301
302         TDM_DBG("tdm_helper_dump start.(path : %s)", dumppath);
303 }
304
305 EXTERN void
306 tdm_helper_dump_stop(void)
307 {
308         tdm_dump_enable = 0;
309
310         TDM_DBG("tdm_helper_dump stop.");
311 }
312
313 static pixman_format_code_t
314 _tdm_helper_pixman_format_get(tbm_format format)
315 {
316         switch (format) {
317         case TBM_FORMAT_ARGB8888:
318                 return PIXMAN_a8r8g8b8;
319         case TBM_FORMAT_XRGB8888:
320                 return PIXMAN_x8r8g8b8;
321         default:
322                 return 0;
323         }
324
325         return 0;
326 }
327
328 static tdm_error
329 _tdm_helper_buffer_convert(tbm_surface_h srcbuf, tbm_surface_h dstbuf,
330                                                    int dx, int dy, int dw, int dh, int count)
331 {
332         pixman_image_t *src_img = NULL, *dst_img = NULL;
333         pixman_format_code_t src_format, dst_format;
334         pixman_transform_t t;
335         struct pixman_f_transform ft;
336         pixman_op_t op;
337         tbm_surface_info_s src_info = {0, };
338         tbm_surface_info_s dst_info = {0, };
339         int stride, width;
340         double scale_x, scale_y;
341
342         TDM_RETURN_VAL_IF_FAIL(srcbuf != NULL, TDM_ERROR_INVALID_PARAMETER);
343         TDM_RETURN_VAL_IF_FAIL(dstbuf != NULL, TDM_ERROR_INVALID_PARAMETER);
344
345         if (tbm_surface_map(srcbuf, TBM_SURF_OPTION_READ, &src_info)
346                         != TBM_SURFACE_ERROR_NONE) {
347                 TDM_ERR("cannot mmap srcbuf\n");
348                 return TDM_ERROR_OPERATION_FAILED;
349         }
350
351         if (tbm_surface_map(dstbuf, TBM_SURF_OPTION_WRITE, &dst_info)
352                         != TBM_SURFACE_ERROR_NONE) {
353                 TDM_ERR("cannot mmap dstbuf\n");
354                 tbm_surface_unmap(srcbuf);
355                 return TDM_ERROR_OPERATION_FAILED;
356         }
357         TDM_GOTO_IF_FAIL(src_info.num_planes == 1, cant_convert);
358         TDM_GOTO_IF_FAIL(dst_info.num_planes == 1, cant_convert);
359
360         /* src */
361         src_format = _tdm_helper_pixman_format_get(src_info.format);
362         TDM_GOTO_IF_FAIL(src_format > 0, cant_convert);
363
364         width = src_info.planes[0].stride / 4;
365         stride = src_info.planes[0].stride;
366         src_img = pixman_image_create_bits(src_format, width, src_info.height,
367                                                                            (uint32_t*)src_info.planes[0].ptr, stride);
368         TDM_GOTO_IF_FAIL(src_img != NULL, cant_convert);
369
370         /* dst */
371         dst_format = _tdm_helper_pixman_format_get(dst_info.format);
372         TDM_GOTO_IF_FAIL(dst_format > 0, cant_convert);
373
374         width = dst_info.planes[0].stride / 4;
375         stride = dst_info.planes[0].stride;
376         dst_img = pixman_image_create_bits(dst_format, width, dst_info.height,
377                                                                            (uint32_t*)dst_info.planes[0].ptr, stride);
378         TDM_GOTO_IF_FAIL(dst_img != NULL, cant_convert);
379
380         pixman_f_transform_init_identity(&ft);
381
382         scale_x = (double)src_info.width / dw;
383         scale_y = (double)src_info.height / dh;
384
385         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
386         pixman_f_transform_translate(&ft, NULL, 0, 0);
387         pixman_transform_from_pixman_f_transform(&t, &ft);
388         pixman_image_set_transform(src_img, &t);
389
390         if (count == 0)
391                 op = PIXMAN_OP_SRC;
392         else
393                 op = PIXMAN_OP_OVER;
394
395         pixman_image_composite(op, src_img, NULL, dst_img,
396                                                    0, 0, 0, 0, dx, dy, dw, dh);
397
398         if (src_img)
399                 pixman_image_unref(src_img);
400         if (dst_img)
401                 pixman_image_unref(dst_img);
402
403         tbm_surface_unmap(srcbuf);
404         tbm_surface_unmap(dstbuf);
405
406         return TDM_ERROR_NONE;
407
408 cant_convert:
409         if (src_img)
410                 pixman_image_unref(src_img);
411
412         tbm_surface_unmap(srcbuf);
413         tbm_surface_unmap(dstbuf);
414
415         return TDM_ERROR_OPERATION_FAILED;
416 }
417
418 EXTERN tdm_error
419 tdm_helper_capture_output(tdm_output *output, tbm_surface_h dst_buffer,
420                                                   int x, int y, int w, int h,
421                                                   tdm_helper_capture_handler func, void *data)
422 {
423         tbm_surface_h surface;
424         tdm_error err;
425         int i, count, first = 0;
426
427         TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
428         TDM_RETURN_VAL_IF_FAIL(dst_buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
429         TDM_RETURN_VAL_IF_FAIL(x >= 0, TDM_ERROR_INVALID_PARAMETER);
430         TDM_RETURN_VAL_IF_FAIL(y >= 0, TDM_ERROR_INVALID_PARAMETER);
431         TDM_RETURN_VAL_IF_FAIL(w >= 0, TDM_ERROR_INVALID_PARAMETER);
432         TDM_RETURN_VAL_IF_FAIL(h >= 0, TDM_ERROR_INVALID_PARAMETER);
433         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
434         TDM_RETURN_VAL_IF_FAIL(data != NULL, TDM_ERROR_INVALID_PARAMETER);
435
436         err = tdm_output_get_layer_count(output, &count);
437         if (err != TDM_ERROR_NONE) {
438                 TDM_ERR("tdm_output_get_layer_count fail(%d)\n", err);
439                 return TDM_ERROR_OPERATION_FAILED;
440         }
441         if (count <= 0) {
442                 TDM_ERR("tdm_output_get_layer_count err(%d, %d)\n", err, count);
443                 return TDM_ERROR_BAD_MODULE;
444         }
445
446         for (i = count - 1; i >= 0; i--) {
447                 tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
448
449                 surface = tdm_layer_get_displaying_buffer(layer, &err);
450                 if (err != TDM_ERROR_NONE)
451                         continue;
452
453                 err = _tdm_helper_buffer_convert(surface, dst_buffer, x, y, w, h, first++);
454                 if (err != TDM_ERROR_NONE)
455                         TDM_DBG("convert fail %d-layer buffer\n", i);
456                 else
457                         TDM_DBG("convert success %d-layer buffer\n", i);
458         }
459
460         func(dst_buffer, data);
461
462         return TDM_ERROR_NONE;
463 }
464