From 3395560d91a4ad4415641db824a6edb3aa66603b Mon Sep 17 00:00:00 2001 From: Kitae Kim Date: Mon, 28 Jul 2014 11:40:46 +0900 Subject: [PATCH] tethering: add a function to get framebuffer in maru_sdl. When request_screenshot function is called by tethering module it makes qemu update display. So, this function has to be implemented to extract framebuffer because of unnecessary display update. Change-Id: I642119a430261f0176be47445b3b6fe5630920cc Signed-off-by: Kitae Kim --- tizen/src/display/maru_sdl.c | 28 ++++++++++++- tizen/src/display/maru_sdl.h | 2 + tizen/src/display/maru_shm.c | 6 +++ tizen/src/display/maru_shm.h | 1 + tizen/src/tethering/encode_fb.c | 92 +++++++++++++++++++++++++++-------------- tizen/src/tethering/encode_fb.h | 2 - tizen/src/tethering/touch.c | 54 +++++++++++++----------- tizen/src/tethering/touch.h | 8 +++- 8 files changed, 133 insertions(+), 60 deletions(-) diff --git a/tizen/src/display/maru_sdl.c b/tizen/src/display/maru_sdl.c index cdc099d..04bf1a7 100644 --- a/tizen/src/display/maru_sdl.c +++ b/tizen/src/display/maru_sdl.c @@ -39,6 +39,8 @@ #include "hw/pci/maru_brightness.h" #include "debug_ch.h" +#include "tethering/touch.h" + #include #ifndef CONFIG_WIN32 #include @@ -87,7 +89,6 @@ static bool sdl_thread_exit; static void qemu_update(void); - static void qemu_ds_sdl_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { @@ -101,6 +102,8 @@ static void qemu_ds_sdl_update(DisplayChangeListener *dcl, #else qemu_update(); #endif + + set_display_dirty(true); } static void qemu_ds_sdl_switch(DisplayChangeListener *dcl, @@ -612,3 +615,26 @@ void maru_sdl_invalidate(bool on) { sdl_invalidate = on; } + +bool maru_extract_framebuffer(void *buffer) +{ + uint32_t buffer_size = 0; + + if (!buffer) { + ERR("given buffer is null\n"); + return false; + } + + if (!surface_qemu) { + ERR("surface_qemu is null\n"); + return false; + } + + maru_do_pixman_dpy_surface(dpy_surface->image); + + buffer_size = surface_stride(dpy_surface) * surface_height(dpy_surface); + INFO("extract framebuffer %d\n", buffer_size); + + memcpy(buffer, surface_data(dpy_surface), buffer_size); + return true; +} diff --git a/tizen/src/display/maru_sdl.h b/tizen/src/display/maru_sdl.h index 87e4ec8..5345c78 100644 --- a/tizen/src/display/maru_sdl.h +++ b/tizen/src/display/maru_sdl.h @@ -46,4 +46,6 @@ void maru_sdl_invalidate(bool on); void maru_sdl_interpolation(bool on); void maru_sdl_quit(void); +bool maru_extract_framebuffer(void *buffer); + #endif /* MARU_SDL_H_ */ diff --git a/tizen/src/display/maru_shm.c b/tizen/src/display/maru_shm.c index 77a9cba..cb0f6dc 100644 --- a/tizen/src/display/maru_shm.c +++ b/tizen/src/display/maru_shm.c @@ -287,3 +287,9 @@ void maru_shm_resize(void) { shm_skip_update = 0; } + +bool maru_extract_framebuffer(void* buffer) +{ + INFO("not support on Mac OS X\n"); + return false; +} diff --git a/tizen/src/display/maru_shm.h b/tizen/src/display/maru_shm.h index d24b1b6..7beebee 100644 --- a/tizen/src/display/maru_shm.h +++ b/tizen/src/display/maru_shm.h @@ -40,5 +40,6 @@ void maru_shm_init(uint64 swt_handle, bool blank_guide); void maru_shm_resize(void); void maru_shm_quit(void); +bool maru_extract_framebuffer(void *buffer); #endif /* MARU_SHM_H_ */ diff --git a/tizen/src/tethering/encode_fb.c b/tizen/src/tethering/encode_fb.c index 9ecc50a..8f4f717 100644 --- a/tizen/src/tethering/encode_fb.c +++ b/tizen/src/tethering/encode_fb.c @@ -5,6 +5,7 @@ * * Contact: * Kitae Kim + * SangHo Park * YeongKyoon Lee * * This program is free software; you can redistribute it and/or @@ -28,15 +29,28 @@ */ #include -#ifdef CONFIG_WEBP -#include -#include -#endif #include "emulator_common.h" #include "emul_state.h" + +#ifdef CONFIG_SDL +#include "display/maru_sdl.h" +#endif +#ifdef CONFIG_USE_SHM +#include "display/maru_shm.h" +#endif + #include "skin/maruskin_operation.h" #include "encode_fb.h" + +#if defined(CONFIG_LINUX) && defined(ENCODE_DEBUG) +#include +#endif +#ifdef CONFIG_WEBP +#include +#include +#endif + #include "util/new_debug_ch.h" DECLARE_DEBUG_CHANNEL(app_tethering); @@ -110,19 +124,13 @@ static void *encode_png(void) */ int bit_depth = 8; struct encode_mem *container = NULL; + uint8_t *surface = NULL; + uint32_t surface_size = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytepp row_pointers = NULL; - Framebuffer *surface = NULL; - - surface = request_screenshot(); - if (!surface) { - LOG_SEVERE("failed to get framebuffer\n"); - return NULL; - } - width = get_emul_resolution_width(); height = get_emul_resolution_height(); @@ -130,11 +138,24 @@ static void *encode_png(void) LOG_TRACE("width %d, height %d, stride %d, raw image %d\n", width, height, image_stride, (image_stride * height)); + surface_size = width * height * 4; + + surface = g_malloc0(surface_size); + if (!surface) { + LOG_SEVERE("failed to allocate framebuffer\n"); + return NULL; + } + + if (!maru_extract_framebuffer(surface)) { + LOG_SEVERE("failed to extract framebuffer\n"); + g_free(surface); + return NULL; + } + LOG_TRACE("png_create_write_struct\n"); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { LOG_SEVERE("png_create_write_struct failure\n"); - g_free(surface->data); g_free(surface); return NULL; } @@ -143,7 +164,6 @@ static void *encode_png(void) info_ptr = png_create_info_struct(png_ptr); if (!png_ptr) { LOG_SEVERE("png_create_info_struct failure\n"); - g_free(surface->data); g_free(surface); png_destroy_write_struct(&png_ptr, &info_ptr); return NULL; @@ -152,7 +172,6 @@ static void *encode_png(void) LOG_TRACE("try png_jmpbuf\n"); if (setjmp(png_jmpbuf(png_ptr))) { LOG_SEVERE("png_jmpbuf failure\n"); - g_free(surface->data); g_free(surface); png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_info_struct(png_ptr, &info_ptr); @@ -163,7 +182,6 @@ static void *encode_png(void) container = g_malloc(sizeof(struct encode_mem)); if (!container) { LOG_SEVERE("failed to allocate encode_mem\n"); - g_free(surface->data); g_free(surface); png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_info_struct(png_ptr, &info_ptr); @@ -190,7 +208,6 @@ static void *encode_png(void) row_pointers = png_malloc(png_ptr, sizeof(png_bytep) * height); if (row_pointers == NULL) { LOG_SEVERE("failed to allocate png memory\n"); - g_free(surface->data); g_free(surface); png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_info_struct(png_ptr, &info_ptr); @@ -198,7 +215,7 @@ static void *encode_png(void) } for (row_index = 0; row_index < height; row_index++) { - row_pointers[row_index] = surface->data + (row_index * image_stride); + row_pointers[row_index] = surface + (row_index * image_stride); } LOG_TRACE("png_write_image\n"); @@ -207,7 +224,6 @@ static void *encode_png(void) LOG_TRACE("png_write_end\n"); png_write_end(png_ptr, info_ptr); - g_free(surface->data); g_free(surface); LOG_TRACE("png image size %d\n", container->length); @@ -221,11 +237,11 @@ static void *encode_png(void) static void *encode_webp(void) { int width = 0, height = 0, image_stride = 0; - // float quality = 0; size_t ret = 0; struct encode_mem *container = NULL; - Framebuffer *surface = NULL; + uint8_t *surface = NULL; + uint32_t surface_size = 0; container = g_malloc(sizeof(struct encode_mem)); if (!container) { @@ -236,13 +252,6 @@ static void *encode_webp(void) container->buffer = NULL; container->length = 0; - surface = request_screenshot(); - if (!surface) { - LOG_SEVERE("failed to get framebuffer\n"); - g_free(container); - return NULL; - } - width = get_emul_resolution_width(); height = get_emul_resolution_height(); @@ -250,13 +259,36 @@ static void *encode_webp(void) LOG_TRACE("width %d, height %d, stride %d, raw image %d\n", width, height, image_stride, (image_stride * height)); - ret = WebPEncodeLosslessBGRA((const uint8_t *)surface->data, width, + surface_size = width * height * 4; + + surface = g_malloc0(surface_size); + if (!surface) { + LOG_SEVERE("failed to allocate framebuffer\n"); + return NULL; + } + + if (!maru_extract_framebuffer(surface)) { + LOG_SEVERE("failed to extract framebuffer\n"); + g_free(surface); + return NULL; + } + + container = g_malloc(sizeof(struct encode_mem)); + if (!container) { + LOG_SEVERE("failed to allocate encode_mem\n"); + g_free(surface); + return NULL; + } + + container->buffer = NULL; + container->length = 0; + + ret = WebPEncodeLosslessBGRA((const uint8_t *)surface, width, height, image_stride, &container->buffer); LOG_TRACE("lossless encode framebuffer via webp. result %zu\n", ret); container->length = (int)ret; - g_free(surface->data); g_free(surface); return container; diff --git a/tizen/src/tethering/encode_fb.h b/tizen/src/tethering/encode_fb.h index 235f782..330fc3a 100644 --- a/tizen/src/tethering/encode_fb.h +++ b/tizen/src/tethering/encode_fb.h @@ -28,8 +28,6 @@ * */ -#include - struct encode_mem { uint8_t *buffer; uint32_t length; diff --git a/tizen/src/tethering/touch.c b/tizen/src/tethering/touch.c index f4b9308..625cbbf 100644 --- a/tizen/src/tethering/touch.c +++ b/tizen/src/tethering/touch.c @@ -32,6 +32,7 @@ #include "emul_state.h" #include "common.h" #include "touch.h" +#include "encode_fb.h" #include "genmsg/tethering.pb-c.h" #include "ecs/ecs_tethering.h" #include "util/new_debug_ch.h" @@ -49,18 +50,8 @@ typedef struct touch_state { // static bool is_touch_event; static int touch_device_status; -#ifndef DISPLAY_FEATURE -#include "encode_fb.h" - -enum { - ENCODE_WEBP = 0, - ENCODE_PNG, -}; - // static void set_touch_event_status(bool status); static bool send_display_image_data(void); -#endif - #if 0 touch_state *init_touch_state(void) @@ -254,6 +245,14 @@ static void set_hwkey_data(Tethering__HWKeyMsg *msg) } #endif +static bool is_display_dirty = false; + +void set_display_dirty(bool dirty) +{ + LOG_TRACE("qemu display update: %d\n", is_display_dirty); + is_display_dirty = dirty; +} + // bool msgproc_tethering_touch_msg(Tethering__TouchMsg *msg) bool msgproc_tethering_touch_msg(void *message) { @@ -287,7 +286,10 @@ bool msgproc_tethering_touch_msg(void *message) break; case TETHERING__TOUCH_MSG__TYPE__DISPLAY_MSG: - send_display_image_data(); + if (is_display_dirty) { + send_display_image_data(); + is_display_dirty = false; + } break; #if 0 @@ -315,6 +317,19 @@ void set_tethering_touch_status(int status) send_tethering_touch_status_ecp(); } +static void dump_display_image_data(struct encode_mem *image) +{ +#ifdef IMAGE_DUMP + FILE *fp = NULL; + + fp = fopen("display_image_dump.png", "wb"); + if (fp != NULL) { + fwrite(image->buffer, 1, image->length, fp); + fclose(fp); + } +#endif +} + static bool send_display_image_data(void) { bool ret = false; @@ -325,33 +340,22 @@ static bool send_display_image_data(void) LOG_TRACE("enter: %s\n", __func__); - image = (struct encode_mem *)encode_framebuffer(ENCODE_WEBP); + image = (struct encode_mem *)encode_framebuffer(ENCODE_PNG); if (!image) { LOG_SEVERE("failed to encode framebuffer\n"); return false; } + dump_display_image_data(image); + LOG_TRACE("image data size %d\n", image->length); display.has_imagedata = true; display.imagedata.len = image->length; display.imagedata.data = image->buffer; -#ifdef IMAGE_DUMP - { - FILE *fp = NULL; - - fp = fopen("test2.png", "wb"); - if (fp != NULL) { - fwrite(image->buffer, 1, image->length, fp); - fclose(fp); - } - } -#endif - touch.type = TETHERING__TOUCH_MSG__TYPE__DISPLAY_MSG; touch.display = &display; - // ret = build_display_msg(&display); ret = build_touch_msg(&touch); LOG_TRACE("send display message: %d\n", ret); diff --git a/tizen/src/tethering/touch.h b/tizen/src/tethering/touch.h index 3fbd6c9..251a68b 100644 --- a/tizen/src/tethering/touch.h +++ b/tizen/src/tethering/touch.h @@ -28,11 +28,15 @@ * */ -// #include "genmsg/tethering.pb-c.h" +enum { + ENCODE_WEBP = 0, + ENCODE_PNG, +}; -// bool msgproc_tethering_touch_msg(Tethering__TouchMsg *msg); bool msgproc_tethering_touch_msg(void *message); int get_tethering_touch_status(void); void set_tethering_touch_status(int status); + +void set_display_dirty(bool dirty); -- 2.7.4