730a03d7695c4f8bfc922b5b8ea21c863c06eacd
[platform/core/system/swap-probe.git] / helper / dacapture.c
1 /*
2  *  DA probe
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Anastasia Lyupa <a.lyupa@samsung.com>
12  *
13  * This library is free software; you can redistribute it and/or modify it under
14  * the terms of the GNU Lesser General Public License as published by the
15  * Free Software Foundation; either version 2.1 of the License, or (at your option)
16  * any later version.
17  *
18  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
19  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this library; if not, write to the Free Software Foundation, Inc., 51
25  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26  *
27  * Contributors:
28  * - S-Core Co., Ltd
29  * - Samsung RnD Institute Russia
30  *
31  */
32
33 #include <stdlib.h>             // for system
34 #include <sys/types.h>  // for stat
35 #include <sys/stat.h>   // fot stat
36 #include <unistd.h>             // fot stat
37 #include <sys/shm.h>    // for shmget, shmat
38
39 #include <X11/Xlib.h>
40 #include <X11/Xutil.h>
41 #include <X11/extensions/XShm.h>
42
43 #include <Ecore.h>
44 #include <Evas.h>
45 #include <Evas_Engine_Buffer.h>
46
47 #include "daprobe.h"
48 #include "dahelper.h"
49
50 #define SCREENSHOT_DIRECTORY    "/tmp/da"
51
52 #define MAX_HEIGHT      720
53 #define CAPTURE_TIMEOUT         2.0
54
55 typedef struct _screenshot_data
56 {
57         XImage*                 ximage;
58         Display*                dpy;
59         XShmSegmentInfo x_shm_info;
60 } screenshot_data;
61
62 /*
63 int convert_image(      void* srcbuf, void* dstbuf,
64                                         pixman_format_code_t src_format,
65                                         pixman_format_code_t dst_format,
66                                         int src_width, int src_height,
67                                         int dst_width, int dst_height,
68                                         int     rotate)
69 {
70         pixman_image_t *   src_img;
71         pixman_image_t *   dst_img;
72         pixman_transform_t transform;
73
74         int                src_stride, dst_stride;
75         int                src_bpp;
76         int                dst_bpp;
77         pixman_op_t        op;
78         int                rotate_step;
79         int                ret = False;
80
81         return_val_if_fail (srcbuf != NULL, False);
82         return_val_if_fail (dstbuf != NULL, False);
83         return_val_if_fail (rotate <= 360 && rotate >= -360, False);
84
85         op = PIXMAN_OP_SRC;
86
87         src_bpp = PIXMAN_FORMAT_BPP (src_format) / 8;
88         return_val_if_fail (src_bpp > 0, False);
89
90         dst_bpp = PIXMAN_FORMAT_BPP (dst_format) / 8;
91         return_val_if_fail (dst_bpp > 0, False);
92
93         rotate_step = (rotate + 360) / 90 % 4;
94
95         src_stride = src_width * src_bpp;
96         dst_stride = dst_width * dst_bpp;
97
98         src_img = pixman_image_create_bits (src_format, src_width, src_height, srcbuf, src_stride);
99         dst_img = pixman_image_create_bits (dst_format, dst_width, dst_height, dstbuf, dst_stride);
100
101         goto_if_fail (src_img != NULL, CANT_CONVERT);
102         goto_if_fail (dst_img != NULL, CANT_CONVERT);
103
104         pixman_transform_init_identity (&transform);
105
106         if (rotate_step > 0)
107         {
108                 int c, s, tx = 0, ty = 0;
109                 switch (rotate_step)
110                 {
111                 case 1:
112                         // 270 degrees
113                         c = 0;
114                         s = -pixman_fixed_1;
115                         ty = pixman_int_to_fixed (dst_width);
116                         break;
117                 case 2:
118                         // 180 degrees
119                         c = -pixman_fixed_1;
120                         s = 0;
121                         tx = pixman_int_to_fixed (dst_width);
122                         ty = pixman_int_to_fixed (dst_height);
123                         break;
124                 case 3:
125                         // 90 degrees
126                         c = 0;
127                         s = pixman_fixed_1;
128                         tx = pixman_int_to_fixed (dst_height);
129                         break;
130                 default:
131                         // 0 degrees
132                         c = 0;
133                         s = 0;
134                         break;
135                 }
136                 pixman_transform_rotate (&transform, NULL, c, s);
137                 pixman_transform_translate (&transform, NULL, tx, ty);
138         }
139
140         pixman_image_set_transform (src_img, &transform);
141
142         pixman_image_composite (op, src_img, NULL, dst_img,
143                                 0, 0, 0, 0, 0, 0, dst_width, dst_height);
144
145         ret = True;
146
147 CANT_CONVERT:
148         if (src_img)
149                 pixman_image_unref (src_img);
150         if (dst_img)
151                 pixman_image_unref (dst_img);
152
153         return ret;
154 }
155 */
156
157 static char* captureScreenShotX(int* pwidth, int* pheight, screenshot_data* sdata)
158 {
159         Window                  root;
160 //      Atom                    atom_rotation;
161
162         sdata->dpy = XOpenDisplay(NULL);
163         if(unlikely(sdata->dpy == NULL))
164         {
165                 // XOpenDisplay failed!
166                 return NULL;
167         }
168
169         *pwidth = DisplayWidth(sdata->dpy, DefaultScreen(sdata->dpy));
170         *pheight = DisplayHeight(sdata->dpy, DefaultScreen(sdata->dpy));
171
172         root = RootWindow(sdata->dpy, DefaultScreen(sdata->dpy));
173
174         sdata->ximage = XShmCreateImage(sdata->dpy, DefaultVisualOfScreen (DefaultScreenOfDisplay (sdata->dpy)), 24,
175                                         ZPixmap, NULL, &sdata->x_shm_info, (unsigned int)*pwidth, (unsigned int)*pheight);
176
177         if(sdata->ximage != NULL)
178         {
179                 sdata->x_shm_info.shmid = shmget(IPC_PRIVATE, sdata->ximage->bytes_per_line * sdata->ximage->height, IPC_CREAT | 0777);
180                 sdata->x_shm_info.shmaddr = sdata->ximage->data = shmat(sdata->x_shm_info.shmid, 0, 0);
181                 sdata->x_shm_info.readOnly = False;
182
183                 if(XShmAttach(sdata->dpy, &sdata->x_shm_info))
184                 {
185                         if(XShmGetImage(sdata->dpy, root, sdata->ximage, 0, 0, AllPlanes))
186                         {
187                                 XSync (sdata->dpy, False);
188                                 return sdata->ximage->data;
189                         }
190                         else
191                         {
192                                 ; // XShmGetImage failed !
193                         }
194
195                         XShmDetach (sdata->dpy, &sdata->x_shm_info);
196                 }
197                 else
198                 {
199                         ; // XShmAttach failed !
200                 }
201
202                 shmdt (sdata->x_shm_info.shmaddr);
203                 shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL);
204                 XDestroyImage(sdata->ximage);
205                 sdata->ximage = NULL;
206         }
207         else
208         {
209                 ; // XShmCreateImage failed!
210         }
211
212         return NULL;
213 }
214
215 static void releaseScreenShotX(screenshot_data* sdata)
216 {
217         if(sdata->ximage)
218         {
219                 XShmDetach (sdata->dpy, &sdata->x_shm_info);
220                 shmdt (sdata->x_shm_info.shmaddr);
221                 shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL);
222                 XDestroyImage(sdata->ximage);
223         }
224         else { }
225
226         if(sdata->dpy)
227         {
228                 XCloseDisplay(sdata->dpy);
229         }
230 }
231
232 static Evas* create_canvas(int width, int height)
233 {
234         Evas* canvas;
235         Evas_Engine_Info_Buffer* einfo;
236         int method;
237         void* pixels;
238
239         method = evas_render_method_lookup("buffer");
240         if(unlikely(method <= 0))
241         {
242                 // ERROR: evas was not compiled with 'buffer' engine!
243                 return NULL;
244         }
245
246         canvas = evas_new();
247         if(unlikely(canvas == NULL))
248         {
249                 // ERROR: could not instantiate new evas canvas.
250                 return NULL;
251         }
252
253         evas_output_method_set(canvas, method);
254         evas_output_size_set(canvas, width, height);
255         evas_output_viewport_set(canvas, 0, 0, width, height);
256
257         einfo = (Evas_Engine_Info_Buffer*)evas_engine_info_get(canvas);
258         if(unlikely(einfo == NULL))
259         {
260                 // ERROR: could not get evas engine info!
261                 evas_free(canvas);
262                 return NULL;
263         }
264
265         // ARGB32 is sizeof(int), that is 4 bytes, per pixel
266         pixels = malloc(width * height * sizeof(int));
267         if(unlikely(pixels == NULL))
268         {
269                 // ERROR: could not allocate canvas pixels!
270                 evas_free(canvas);
271                 return NULL;
272         }
273
274         einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
275         einfo->info.dest_buffer = pixels;
276         einfo->info.dest_buffer_row_bytes = width * sizeof(int);
277         einfo->info.use_color_key = 0;
278         einfo->info.alpha_threshold = 0;
279         einfo->info.func.new_update_region = NULL;
280         einfo->info.func.free_update_region = NULL;
281         evas_engine_info_set(canvas, (Evas_Engine_Info*)einfo);
282
283         return canvas;
284 }
285
286 static void destroy_canvas(Evas* canvas)
287 {
288         Evas_Engine_Info_Buffer* einfo;
289
290         einfo = (Evas_Engine_Info_Buffer*)evas_engine_info_get(canvas);
291         if(unlikely(einfo == NULL))
292         {
293                 ; // ERROR: could not get evas engine info!
294         }
295         else
296         {
297                 free(einfo->info.dest_buffer);
298         }
299         evas_free(canvas);
300 }
301
302 int captureScreen()
303 {
304         char dstpath[32];
305         char* scrimage;
306         int width, height;
307         Evas* ev = NULL;
308         Evas_Object* img;
309         screenshot_data sdata;
310         probeInfo_t     probeInfo;
311         int ret = 0;
312
313         probeBlockStart();
314
315         setProbePoint(&probeInfo);
316         sdata.ximage = NULL;
317         scrimage = captureScreenShotX(&width, &height, &sdata);
318         if(scrimage != NULL)
319         {
320                 ev = create_canvas(width, height);
321                 if(likely(ev != NULL))
322                 {
323                         sprintf(dstpath, SCREENSHOT_DIRECTORY "/%d.png", probeInfo.eventIndex);
324
325                         // make image buffer
326                         if((img = evas_object_image_add(ev)) != NULL)
327                         {
328                                 //image buffer set
329                                 evas_object_image_data_set(img, NULL);
330                                 evas_object_image_size_set(img, width, height);
331                                 evas_object_image_data_set(img, scrimage);
332
333                                 // resize image
334                                 if(height > MAX_HEIGHT)
335                                 {
336                                         width = width * MAX_HEIGHT / height;
337                                         height = MAX_HEIGHT;
338                                         evas_object_resize(img, width, height);
339                                         evas_object_image_fill_set(img, 0, 0, width, height);
340                                 }
341                                 evas_object_image_data_update_add(img, 0, 0, width, height);
342
343                                 //save file
344                                 if(evas_object_image_save(img, dstpath, NULL, "compress=5") != 0)
345                                 {
346                                         // nothing
347                                 }
348                                 else
349                                 {
350                                         // captureScreen : evas_object_image_save failed
351                                         ret = -1;
352                                 }
353                         }
354                         else
355                         {
356                                 // captureScreen : evas_object_image_add failed
357                                 ret = -1;
358                         }
359                 }
360                 else
361                 {
362                         // captureScreen : create canvas failed
363                         ret = -1;
364                 }
365         }
366         else
367         {
368                 // captureScreen : captureScreenShotX failed
369                 ret = -1;
370         }
371
372         // release resources
373         releaseScreenShotX(&sdata);
374         if(ev)
375                 destroy_canvas(ev);
376
377         probeBlockEnd();
378
379         return ret;
380 }
381
382 int initialize_screencapture()
383 {
384         // remove all previous screenshot in dir
385 //      remove_indir(SCREENSHOT_DIRECTORY);
386
387         // make screenshot directory
388 //      mkdir(SCREENSHOT_DIRECTORY, 0777);
389
390         return 0;
391 }
392
393 int finalize_screencapture()
394 {
395         return 0;
396 }
397
398 // =======================================================================
399 // screen shot manipulation functions
400 // =======================================================================
401
402 static Eina_Bool _captureTimer(void* data)
403 {
404         probeBlockStart();
405         SCREENSHOT_DONE();
406         probeBlockEnd();
407
408         return ECORE_CALLBACK_CANCEL;
409 }
410
411 int activateCaptureTimer()
412 {
413         ecore_timer_add(CAPTURE_TIMEOUT, _captureTimer, NULL);
414         return 0;
415 }
416
417 void _cb_render_post(void* data, Evas* e, void* eventinfo)
418 {
419         probeBlockStart();
420         SCREENSHOT_DONE();
421         probeBlockEnd();
422 }
423