summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuhiko Tanibata <NOBUHIKO_TANIBATA@denso.co.jp>2014-07-28 18:02:51 +0900
committerNobuhiko Tanibata <NOBUHIKO_TANIBATA@denso.co.jp>2014-09-01 15:55:42 +0900
commitbd02702c42070764c9b5b0b2c72de4fad1cc3c25 (patch)
treefd8370eb330432928df5c475ebada83a45d258fc
parent20d27a65e9cbcdbdf21f6d29bd2806fee7ddbf3a (diff)
downloadwayland-ivi-extension-bd02702c42070764c9b5b0b2c72de4fad1cc3c25.tar.gz
weston-ivi-shell: Add surface-screenshot function.
Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA@denso.co.jp>
-rwxr-xr-xweston-ivi-shell/src/ivi-controller.c263
-rw-r--r--weston-ivi-shell/src/ivi-layout-export.h18
2 files changed, 251 insertions, 30 deletions
diff --git a/weston-ivi-shell/src/ivi-controller.c b/weston-ivi-shell/src/ivi-controller.c
index eddcf08..231567c 100755
--- a/weston-ivi-shell/src/ivi-controller.c
+++ b/weston-ivi-shell/src/ivi-controller.c
@@ -27,10 +27,12 @@
#include <string.h>
#include <linux/input.h>
#include <cairo.h>
+#include <GLES2/gl2.h>
#include "weston/compositor.h"
#include "ivi-controller-server-protocol.h"
#include "ivi-layout-export.h"
+#include "bitmap.h"
struct ivishell;
struct ivilayer;
@@ -776,16 +778,243 @@ controller_surface_set_orientation(struct wl_client *client,
ivi_layout_surfaceSetOrientation(ivisurf->layout_surface, (uint32_t)orientation);
}
+static int
+shm_surface_screenshot(struct weston_surface *surface,
+ int32_t width,
+ int32_t height,
+ int32_t stride,
+ const char *filename)
+{
+ struct weston_buffer *weston_buffer = NULL;
+ struct wl_shm_buffer *shm_buffer = NULL;
+ cairo_surface_t *cairo_surf = NULL;
+ uint8_t *source_buffer = NULL;
+ uint8_t *dest_buffer = NULL;
+
+ weston_buffer = surface->buffer_ref.buffer;
+ if (weston_buffer == NULL) {
+ fprintf(stderr, "Failed to get weston buffer.\n");
+ return -1;
+ }
+
+ shm_buffer = wl_shm_buffer_get(weston_buffer->resource);
+ if (shm_buffer == NULL) {
+ return -1;
+ }
+
+ source_buffer = wl_shm_buffer_get_data(shm_buffer);
+ if (source_buffer == NULL) {
+ fprintf(stderr, "Failed to get data from shm buffer.\n");
+ return -1;
+ }
+
+ dest_buffer = malloc(stride * height);
+ if (dest_buffer == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ return -1;
+ }
+
+ memcpy(dest_buffer, source_buffer, stride * height);
+
+ cairo_surf = cairo_image_surface_create_for_data(
+ dest_buffer,
+ CAIRO_FORMAT_RGB24,
+ width,
+ height,
+ stride);
+
+ cairo_surface_write_to_png(cairo_surf, filename);
+ cairo_surface_destroy(cairo_surf);
+ free(dest_buffer);
+
+ return 0;
+}
+
+static void
+bind_framebuffer(GLuint *fbo_id, GLuint *tex_id, GLsizei width, GLsizei height)
+{
+ glGenTextures(1, tex_id);
+ glGenFramebuffers(1, fbo_id);
+ glBindTexture(GL_TEXTURE_2D, *tex_id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindFramebuffer(GL_FRAMEBUFFER, *fbo_id);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex_id, 0);
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+static void
+unbind_framebuffer(GLuint fbo_id, GLuint tex_id)
+{
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteTextures(1, &tex_id);
+ glDeleteFramebuffers(1, &fbo_id);
+}
+
+static void
+dump_surface(struct weston_output *output,
+ struct weston_compositor *compositor,
+ const char *filename,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height)
+{
+ struct weston_renderer *renderer = compositor->renderer;
+ pixman_region32_t region;
+ uint8_t *readpixs = NULL;
+ int32_t stride = width * (PIXMAN_FORMAT_BPP(compositor->read_format) / 8);
+ GLuint fbo_id, tex_id;
+
+ readpixs = malloc(stride * height);
+ if (readpixs == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ return;
+ }
+
+ pixman_region32_init_rect(&region, x, y, width, height);
+ bind_framebuffer(&fbo_id, &tex_id, output->current_mode->width, output->current_mode->height);
+ renderer->repaint_output(output, &region);
+ glFinish();
+
+ y = output->current_mode->height - (y + height);
+ int result = renderer->read_pixels(output,
+ compositor->read_format,
+ readpixs,
+ x,
+ y,
+ width,
+ height);
+ unbind_framebuffer(fbo_id, tex_id);
+
+ save_as_bitmap(filename, readpixs, stride * height, width, height, PIXMAN_FORMAT_BPP(compositor->read_format));
+ free(readpixs);
+}
+
+static void
+clear_viewlist_but_specified_surface(struct weston_compositor *compositor,
+ struct weston_surface *surface)
+{
+ struct weston_view *view = NULL;
+ wl_list_init(&compositor->view_list);
+
+ wl_list_for_each(view, &surface->views, surface_link) {
+ if (view == NULL) {
+ continue;
+ }
+
+ wl_list_insert(compositor->view_list.prev, &view->link);
+ }
+}
+
+static void
+get_gl_surface_rectangle(struct ivi_layout_SurfaceProperties *prop,
+ int32_t *x,
+ int32_t *y,
+ int32_t *width,
+ int32_t *height)
+{
+ if (prop == NULL) {
+ return;
+ }
+
+ if ((prop->destX == 0) &&
+ (prop->destY == 0) &&
+ (prop->destWidth == 0) &&
+ (prop->destHeight == 0)) {
+ *x = prop->sourceX;
+ *y = prop->sourceY;
+ *width = prop->sourceWidth;
+ *height = prop->sourceHeight;
+ }
+ else {
+ *x = prop->destX;
+ *y = prop->destY;
+ *width = prop->destWidth;
+ *height = prop->destHeight;
+ }
+}
+
+static int
+gl_surface_screenshot(struct ivisurface *ivisurf,
+ struct weston_surface *surface,
+ const char *filename)
+{
+ struct weston_compositor *compositor = surface->compositor;
+ struct link_layer *link_layer = NULL;
+ struct link_screen *link_scrn = NULL;
+ struct ivi_layout_SurfaceProperties prop = {};
+ int32_t x = 0;
+ int32_t y = 0;
+ int32_t width = 0;
+ int32_t height = 0;
+
+ wl_list_for_each(link_layer, &ivisurf->list_layer, link) {
+ if (link_layer == NULL) {
+ continue;
+ }
+
+ wl_list_for_each(link_scrn, &link_layer->layer->list_screen, link) {
+ if (link_scrn != NULL) {
+ break;
+ }
+ }
+ }
+
+ if (link_scrn == NULL) {
+ fprintf(stderr, "Failed to get iviscreen\n");
+ return -1;
+ }
+
+ if (ivi_layout_getPropertiesOfSurface(ivisurf->layout_surface, &prop) != 0) {
+ fprintf(stderr, "Failed to get surface properties.");
+ return -1;
+ }
+
+ get_gl_surface_rectangle(&prop, &x, &y, &width, &height);
+ clear_viewlist_but_specified_surface(compositor, surface);
+ dump_surface(link_scrn->screen->output,
+ compositor,
+ filename,
+ x,
+ y,
+ width,
+ height);
+
+ return 0;
+}
+
static void
controller_surface_screenshot(struct wl_client *client,
struct wl_resource *resource,
const char *filename)
{
- (void)client;
- (void)resource;
- (void)filename;
+ struct ivisurface *ivisurf = wl_resource_get_user_data(resource);
+ struct weston_surface *weston_surface = NULL;
+ int32_t width = 0;
+ int32_t height = 0;
+ int32_t stride = 0;
+
+ weston_surface = ivi_layout_surfaceGetWestonSurface(ivisurf->layout_surface);
+ if (weston_surface == NULL) {
+ fprintf(stderr, "Failed to get weston surface.\n");
+ return;
+ }
+
+ if (ivi_layout_surfaceGetSize(ivisurf->layout_surface, &width, &height, &stride) != 0) {
+ fprintf(stderr, "Failed to get surface size.\n");
+ return;
+ }
+
+ if (shm_surface_screenshot(weston_surface, width, height, stride, filename) != 0) {
+ if (gl_surface_screenshot(ivisurf, weston_surface, filename) != 0) {
+ fprintf(stderr, "Failed to capture surface.\n");
+ }
+ }
}
+
static void
controller_surface_send_stats(struct wl_client *client,
struct wl_resource *resource)
@@ -1078,9 +1307,6 @@ controller_screen_screenshot(struct wl_client *client,
int32_t height = 0;
int32_t stride = 0;
uint8_t *readpixs = NULL;
- uint8_t *writepixs = NULL;
- uint8_t *d = NULL;
- uint8_t *s = NULL;
output = ivi_layout_screenGetOutput(iviscrn->layout_screen);
--output->disable_planes;
@@ -1095,12 +1321,6 @@ controller_screen_screenshot(struct wl_client *client,
return;
}
- writepixs = malloc(stride * height);
- if (writepixs == NULL) {
- weston_log("fails to allocate memory\n");
- return;
- }
-
output->compositor->renderer->read_pixels(
output,
output->compositor->read_format,
@@ -1110,24 +1330,7 @@ controller_screen_screenshot(struct wl_client *client,
width,
height);
- s = readpixs;
- d = writepixs + stride * (height - 1);
-
- for (i = 0; i < height; ++i) {
- memcpy(d, s, stride);
- d -= stride;
- s += stride;
- }
-
- cairo_surf = cairo_image_surface_create_for_data(
- writepixs,
- CAIRO_FORMAT_ARGB32,
- width,
- height,
- stride);
- cairo_surface_write_to_png(cairo_surf, filename);
- cairo_surface_destroy(cairo_surf);
- free(writepixs);
+ save_as_bitmap(filename, readpixs, stride * height, width, height, PIXMAN_FORMAT_BPP(output->compositor->read_format));
free(readpixs);
}
diff --git a/weston-ivi-shell/src/ivi-layout-export.h b/weston-ivi-shell/src/ivi-layout-export.h
index 874911d..f0654f1 100644
--- a/weston-ivi-shell/src/ivi-layout-export.h
+++ b/weston-ivi-shell/src/ivi-layout-export.h
@@ -81,6 +81,10 @@ enum ivi_layout_transition_type{
IVI_LAYOUT_TRANSITION_MAX,
};
+typedef void(*shellWarningNotificationFunc)(uint32_t id_surface,
+ enum ivi_layout_warning_flag warn,
+ void *userdata);
+
typedef void(*layerPropertyNotificationFunc)(struct ivi_layout_layer *ivilayer,
struct ivi_layout_LayerProperties*,
enum ivi_layout_notification_mask mask,
@@ -110,6 +114,14 @@ typedef void(*ivi_controller_surface_content_callback)(struct ivi_layout_surface
int32_t content,
void *userdata);
+int32_t
+ivi_layout_addNotificationShellWarning(shellWarningNotificationFunc callback,
+ void *userdata);
+
+void
+ivi_layout_removeNotificationShellWarning(shellWarningNotificationFunc callback,
+ void *userdata);
+
/**
* \brief to be called by ivi-shell in order to set initail view of
* weston_surface.
@@ -896,6 +908,12 @@ ivi_layout_surfaceSetSourceRectangle(struct ivi_layout_surface *ivisurf,
struct weston_output *
ivi_layout_screenGetOutput(struct ivi_layout_screen *);
+struct weston_surface *
+ivi_layout_surfaceGetWestonSurface(struct ivi_layout_surface *ivisurf);
+
+int32_t
+ivi_layout_surfaceGetSize(struct ivi_layout_surface *ivisurf, int32_t *width, int32_t *height, int32_t *stride);
+
int32_t
ivi_layout_layerSetTransition(struct ivi_layout_layer *ivilayer,
enum ivi_layout_transition_type type,