add tdm_helper_capture_output API 80/72480/2
authorJunkyeong Kim <jk0430.kim@samsung.com>
Wed, 1 Jun 2016 07:20:27 +0000 (16:20 +0900)
committerBoram Park <boram1288.park@samsung.com>
Thu, 9 Jun 2016 05:56:50 +0000 (22:56 -0700)
It makes composite image with output's all layers showing buffer.
After composing, call tdm_helper_capture_handler function.

Change-Id: I1ea7b939d77aeaf4f6d2c5347a3443ddac2b6d1d
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
configure.ac
include/tdm_helper.h
packaging/libtdm.spec
src/tdm_helper.c

index fa99a81a3a5b7dc87a66cbeec6d1e80742133e93..ff06dd9660b33c24d395eaf0487ec2d5f09ccde5 100644 (file)
@@ -37,7 +37,7 @@ fi
 
 PKG_CHECK_MODULES(WAYLAND_SCANNER, wayland-scanner >= 1.7.0)
 
-PKG_CHECK_MODULES(TDM, dlog libtbm pthread-stubs libpng wayland-server)
+PKG_CHECK_MODULES(TDM, dlog libtbm pthread-stubs libpng pixman-1 wayland-server)
 
 PKG_CHECK_MODULES(TTRACE,
                [ttrace],
index 0bde0b9431dffba950fdbe4fb015bf6d684ab9fc..e98ad9f43af17eb2de0a515195cd579f3dd6adf0 100644 (file)
@@ -118,6 +118,32 @@ tdm_helper_dump_start(char *dumppath, int *count);
 void
 tdm_helper_dump_stop(void);
 
+/**
+ * @brief The tdm helper capture handler
+ * @details
+ * This handler will be called when composit image produced.
+ * @see #tdm_helper_capture_output() function
+ */
+typedef void (*tdm_helper_capture_handler)(tbm_surface_h buffer, void *user_data);
+
+/**
+ * @brief Make an output's image surface.
+ * @details Composit specific output's all layer's buffer to dst_buffer surface.
+ * After composing, tdm_helper_capture_handler func will be called.
+ * @param[in] output A output object
+ * @param[in] dst_buffer A surface composite image saved
+ * @param[in] x A horizontal position of composite image on dst_buffer
+ * @param[in] y A vertical position of composite image on dst_buffer
+ * @param[in] w A composite image width
+ * @param[in] h A composite image height
+ * @param[in] func A composing done handler
+ * @param[in] user_data The user data
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_helper_capture_output(tdm_output *output, tbm_surface_h dst_buffer,
+                                                 int x, int y, int w, int h,
+                                                 tdm_helper_capture_handler func, void *data);
 #ifdef __cplusplus
 }
 #endif
index 881db02c89c37e991d49e7e106e91e26dc03b52c..077db23aa3e8578ccb66f104efe8d712430f36e3 100644 (file)
@@ -11,6 +11,7 @@ BuildRequires:  pkgconfig(libtbm)
 BuildRequires:  pkgconfig(libpng)
 BuildRequires:  pkgconfig(ttrace)
 BuildRequires:  pkgconfig(wayland-server)
+BuildRequires:  pkgconfig(pixman-1)
 
 %description
 Common user library of Tizen Display Manager : libtdm front-end library
index a57a7321e5251c9403547c83a742c6b365e107d1..354e2e8022c232ce492303a23c009110d4d99343 100644 (file)
 #include <tbm_surface_internal.h>
 #include <string.h>
 #include <time.h>
+#include <pixman.h>
 
 #include "tdm.h"
 #include "tdm_private.h"
+#include "tdm_helper.h"
 
 #define PNG_DEPTH 8
 
@@ -308,3 +310,157 @@ tdm_helper_dump_stop(void)
        TDM_DBG("tdm_helper_dump stop.");
 }
 
+static pixman_format_code_t
+_tdm_helper_pixman_format_get(tbm_format format)
+{
+       switch (format) {
+       case TBM_FORMAT_ARGB8888:
+               return PIXMAN_a8r8g8b8;
+       case TBM_FORMAT_XRGB8888:
+               return PIXMAN_x8r8g8b8;
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+static tdm_error
+_tdm_helper_buffer_convert(tbm_surface_h srcbuf, tbm_surface_h dstbuf,
+                                                  int dx, int dy, int dw, int dh, int count)
+{
+       pixman_image_t *src_img = NULL, *dst_img = NULL;
+       pixman_format_code_t src_format, dst_format;
+       pixman_transform_t t;
+       struct pixman_f_transform ft;
+       pixman_op_t op;
+       tbm_surface_info_s src_info = {0, };
+       tbm_surface_info_s dst_info = {0, };
+       int stride, width;
+       double scale_x, scale_y;
+
+       TDM_RETURN_VAL_IF_FAIL(srcbuf != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(dstbuf != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       if (tbm_surface_map(srcbuf, TBM_SURF_OPTION_READ, &src_info)
+                       != TBM_SURFACE_ERROR_NONE) {
+               TDM_ERR("cannot mmap srcbuf\n");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       if (tbm_surface_map(dstbuf, TBM_SURF_OPTION_WRITE, &dst_info)
+                       != TBM_SURFACE_ERROR_NONE) {
+               TDM_ERR("cannot mmap dstbuf\n");
+               tbm_surface_unmap(srcbuf);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+       TDM_GOTO_IF_FAIL(src_info.num_planes == 1, cant_convert);
+       TDM_GOTO_IF_FAIL(dst_info.num_planes == 1, cant_convert);
+
+       /* src */
+       src_format = _tdm_helper_pixman_format_get(src_info.format);
+       TDM_GOTO_IF_FAIL(src_format > 0, cant_convert);
+
+       width = src_info.planes[0].stride / 4;
+       stride = src_info.planes[0].stride;
+       src_img = pixman_image_create_bits(src_format, width, src_info.height,
+                                                                          (uint32_t*)src_info.planes[0].ptr, stride);
+       TDM_GOTO_IF_FAIL(src_img != NULL, cant_convert);
+
+       /* dst */
+       dst_format = _tdm_helper_pixman_format_get(dst_info.format);
+       TDM_GOTO_IF_FAIL(dst_format > 0, cant_convert);
+
+       width = dst_info.planes[0].stride / 4;
+       stride = dst_info.planes[0].stride;
+       dst_img = pixman_image_create_bits(dst_format, width, dst_info.height,
+                                                                          (uint32_t*)dst_info.planes[0].ptr, stride);
+       TDM_GOTO_IF_FAIL(dst_img != NULL, cant_convert);
+
+       pixman_f_transform_init_identity(&ft);
+
+       scale_x = (double)src_info.width / dw;
+       scale_y = (double)src_info.height / dh;
+
+       pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
+       pixman_f_transform_translate(&ft, NULL, 0, 0);
+       pixman_transform_from_pixman_f_transform(&t, &ft);
+       pixman_image_set_transform(src_img, &t);
+
+       if (count == 0)
+               op = PIXMAN_OP_SRC;
+       else
+               op = PIXMAN_OP_OVER;
+
+       pixman_image_composite(op, src_img, NULL, dst_img,
+                                                  0, 0, 0, 0, dx, dy, dw, dh);
+
+       if (src_img)
+               pixman_image_unref(src_img);
+       if (dst_img)
+               pixman_image_unref(dst_img);
+
+       tbm_surface_unmap(srcbuf);
+       tbm_surface_unmap(dstbuf);
+
+       return TDM_ERROR_NONE;
+
+cant_convert:
+       if (src_img)
+               pixman_image_unref(src_img);
+       if (dst_img)
+               pixman_image_unref(dst_img);
+
+       tbm_surface_unmap(srcbuf);
+       tbm_surface_unmap(dstbuf);
+
+       return TDM_ERROR_OPERATION_FAILED;
+}
+
+EXTERN tdm_error
+tdm_helper_capture_output(tdm_output *output, tbm_surface_h dst_buffer,
+                                                 int x, int y, int w, int h,
+                                                 tdm_helper_capture_handler func, void *data)
+{
+       tbm_surface_h surface;
+       tdm_error err;
+       int i, count, first = 0;
+
+       TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(dst_buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(x >= 0, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(y >= 0, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(w >= 0, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(h >= 0, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       err = tdm_output_get_layer_count(output, &count);
+       if (err != TDM_ERROR_NONE) {
+               TDM_ERR("tdm_output_get_layer_count fail(%d)\n", err);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+       if (count <= 0) {
+               TDM_ERR("tdm_output_get_layer_count err(%d, %d)\n", err, count);
+               return TDM_ERROR_BAD_MODULE;
+       }
+
+       for (i = count - 1; i >= 0; i--) {
+               tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+
+               surface = tdm_layer_get_displaying_buffer(layer, &err);
+               if (err != TDM_ERROR_NONE)
+                       continue;
+
+               err = _tdm_helper_buffer_convert(surface, dst_buffer, x, y, w, h, first++);
+               if (err != TDM_ERROR_NONE)
+                       TDM_DBG("convert fail %d-layer buffer\n", i);
+               else
+                       TDM_DBG("convert success %d-layer buffer\n", i);
+       }
+
+       func(dst_buffer, data);
+
+       return TDM_ERROR_NONE;
+}
+