support client API for wait_vblank
[platform/core/uifw/libtdm.git] / src / tdm_helper.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <png.h>
6 #include <string.h>
7 #include <tbm_surface.h>
8 #include <tbm_surface_internal.h>
9 #include <string.h>
10 #include <time.h>
11
12 #include "tdm.h"
13 #include "tdm_private.h"
14
15 #define PNG_DEPTH 8
16
17 static const char *dump_prefix[2] = {"png", "yuv"};
18
19 INTERN int
20 tdm_helper_unlock_in_cb(tdm_private_display *private_display)
21 {
22         int ret = pthread_mutex_trylock(&private_display->lock);
23         int need_lock = 0;
24
25         if (ret == 0)
26                 _pthread_mutex_unlock(&private_display->lock);
27         else  if (ret == EBUSY) {
28                 _pthread_mutex_unlock(&private_display->lock);
29                 need_lock = 1;
30         }
31
32         return need_lock;
33 }
34
35 INTERN void
36 tdm_helper_lock_in_cb(tdm_private_display *private_display, int need_lock)
37 {
38         if (!need_lock)
39                 return;
40
41         _pthread_mutex_lock(&private_display->lock);
42 }
43
44 INTERN unsigned long
45 tdm_helper_get_time_in_millis(void)
46 {
47         struct timespec tp;
48
49         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
50                 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
51
52         return 0;
53 }
54
55 static void
56 _tdm_helper_dump_raw(const char *file, void *data1, int size1, void *data2,
57                      int size2, void *data3, int size3)
58 {
59         unsigned int *blocks;
60         FILE *fp = fopen(file, "w+");
61         TDM_RETURN_IF_FAIL(fp != NULL);
62
63         blocks = (unsigned int *)data1;
64         fwrite(blocks, 1, size1, fp);
65
66         if (size2 > 0) {
67                 blocks = (unsigned int *)data2;
68                 fwrite(blocks, 1, size2, fp);
69         }
70
71         if (size3 > 0) {
72                 blocks = (unsigned int *)data3;
73                 fwrite(blocks, 1, size3, fp);
74         }
75
76         fclose(fp);
77 }
78
79 static void
80 _tdm_helper_dump_png(const char *file, const void *data, int width,
81                      int height)
82 {
83         FILE *fp = fopen(file, "wb");
84         TDM_RETURN_IF_FAIL(fp != NULL);
85
86         png_structp pPngStruct =
87                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
88         if (!pPngStruct) {
89                 fclose(fp);
90                 return;
91         }
92
93         png_infop pPngInfo = png_create_info_struct(pPngStruct);
94         if (!pPngInfo) {
95                 png_destroy_write_struct(&pPngStruct, NULL);
96                 fclose(fp);
97                 return;
98         }
99
100         png_init_io(pPngStruct, fp);
101         png_set_IHDR(pPngStruct,
102                      pPngInfo,
103                      width,
104                      height,
105                      PNG_DEPTH,
106                      PNG_COLOR_TYPE_RGBA,
107                      PNG_INTERLACE_NONE,
108                      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
109
110         png_set_bgr(pPngStruct);
111         png_write_info(pPngStruct, pPngInfo);
112
113         const int pixel_size = 4;       // RGBA
114         png_bytep *row_pointers =
115                 png_malloc(pPngStruct, height * sizeof(png_byte *));
116
117         unsigned int *blocks = (unsigned int *)data;
118         int y = 0;
119         int x = 0;
120
121         for (; y < height; ++y) {
122                 png_bytep row =
123                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
124                 row_pointers[y] = (png_bytep)row;
125                 for (x = 0; x < width; ++x) {
126                         unsigned int curBlock = blocks[y * width + x];
127                         row[x * pixel_size] = (curBlock & 0xFF);
128                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
129                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
130                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
131                 }
132         }
133
134         png_write_image(pPngStruct, row_pointers);
135         png_write_end(pPngStruct, pPngInfo);
136
137         for (y = 0; y < height; y++)
138                 png_free(pPngStruct, row_pointers[y]);
139         png_free(pPngStruct, row_pointers);
140
141         png_destroy_write_struct(&pPngStruct, &pPngInfo);
142
143         fclose(fp);
144 }
145
146 EXTERN void
147 tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file)
148 {
149         tbm_surface_info_s info;
150         int len, ret;
151         const char *prefix;
152
153         TDM_RETURN_IF_FAIL(buffer != NULL);
154         TDM_RETURN_IF_FAIL(file != NULL);
155
156         ret = tbm_surface_map(buffer, TBM_DEVICE_CPU, &info);
157         TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
158
159         len = strnlen(file, 1024);
160         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
161                 prefix = dump_prefix[0];
162         else
163                 prefix = dump_prefix[1];
164
165         if (strncmp(file + (len - 3), prefix, 3)) {
166                 TDM_ERR("can't dump to '%s' file", file + (len - 3));
167                 tbm_surface_unmap(buffer);
168                 return;
169         }
170
171         switch (info.format) {
172         case TBM_FORMAT_ARGB8888:
173         case TBM_FORMAT_XRGB8888:
174                 _tdm_helper_dump_png(file, info.planes[0].ptr,
175                                      info.planes[0].stride >> 2, info.height);
176                 break;
177         case TBM_FORMAT_YVU420:
178         case TBM_FORMAT_YUV420:
179                 _tdm_helper_dump_raw(file,
180                                      info.planes[0].ptr,
181                                      info.planes[0].stride * info.height,
182                                      info.planes[1].ptr,
183                                      info.planes[1].stride * (info.height >> 1),
184                                      info.planes[2].ptr,
185                                      info.planes[2].stride * (info.height >> 1));
186                 break;
187         case TBM_FORMAT_NV12:
188         case TBM_FORMAT_NV21:
189                 _tdm_helper_dump_raw(file,
190                                      info.planes[0].ptr,
191                                      info.planes[0].stride * info.height,
192                                      info.planes[1].ptr,
193                                      info.planes[1].stride * (info.height >> 1), NULL,
194                                      0);
195                 break;
196         case TBM_FORMAT_YUYV:
197         case TBM_FORMAT_UYVY:
198                 _tdm_helper_dump_raw(file,
199                                      info.planes[0].ptr,
200                                      info.planes[0].stride * info.height, NULL, 0,
201                                      NULL, 0);
202                 break;
203         default:
204                 TDM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR (info.format));
205                 tbm_surface_unmap(buffer);
206                 return;
207         }
208
209         tbm_surface_unmap(buffer);
210
211         TDM_INFO("dump %s", file);
212 }
213
214 EXTERN int
215 tdm_helper_get_fd(const char *env)
216 {
217         const char *value;
218         int fd, newfd, flags, ret;
219
220         value = (const char*)getenv(env);
221         if (!value)
222                 return -1;
223
224         ret = sscanf(value, "%d", &fd);
225         if (ret < 0) {
226                 TDM_ERR("sscanf failed: %m");
227                 return -1;
228         }
229
230         flags = fcntl(fd, F_GETFD);
231         if (flags == -1) {
232                 TDM_ERR("fcntl failed: %m");
233                 return -1;
234         }
235
236         newfd = dup(fd);
237         if (newfd < 0) {
238                 TDM_ERR("dup failed: %m");
239                 return -1;
240         }
241
242         TDM_INFO("%s: fd(%d) newfd(%d)", env, fd, newfd);
243
244         fcntl(newfd, F_SETFD, flags | FD_CLOEXEC);
245
246         return newfd;
247 }
248
249 EXTERN void
250 tdm_helper_set_fd(const char *env, int fd)
251 {
252         char buf[32];
253         int ret;
254
255         snprintf(buf, sizeof(buf), "%d", fd);
256
257         ret = setenv(env, (const char*)buf, 1);
258         if (ret) {
259                 TDM_ERR("setenv failed: %m");
260                 return;
261         }
262
263         if (fd >= 0)
264                 TDM_INFO("%s: fd(%d)", env, fd);
265 }