VIGS: add draw_pixels_scaled to winsys interface
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Fri, 21 Aug 2015 10:21:44 +0000 (13:21 +0300)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 26 Aug 2015 01:25:43 +0000 (10:25 +0900)
Needed to render images with custom dimensions scaled to
a surface width and height.

Change-Id: I69b34fe60e3075cfcd66202217a1416eb17c3a8f
Signed-off-by: Vasiliy Ulyanov <v.ulyanov@samsung.com>
hw/vigs/vigs_gl_backend.c
hw/vigs/vigs_surface.h
hw/vigs/vigs_sw_backend.c
hw/vigs/winsys.h

index ab14baa..7fcd2c0 100644 (file)
@@ -1138,6 +1138,37 @@ static void vigs_winsys_gl_surface_draw_pixels(struct winsys_surface *sfc,
     }
 }
 
+static void vigs_winsys_gl_surface_draw_pixels_scaled(struct winsys_surface *sfc,
+                                                      uint8_t *pixels,
+                                                      uint32_t width,
+                                                      uint32_t height)
+{
+    struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
+    bool has_current = vigs_sfc->backend->has_current(vigs_sfc->backend);
+    if (!vigs_sfc->parent) {
+        return;
+    }
+
+    if (has_current ||
+        vigs_sfc->backend->make_current(vigs_sfc->backend, true)) {
+
+        vigs_sfc->parent->base.draw_pixels_scaled(&vigs_sfc->parent->base,
+                                                  pixels,
+                                                  width,
+                                                  height);
+
+        vigs_sfc->parent->base.is_dirty = true;
+
+        vigs_sfc->backend->Finish();
+
+        if (!has_current) {
+            vigs_sfc->backend->make_current(vigs_sfc->backend, false);
+        }
+    } else {
+        VIGS_LOG_CRITICAL("make_current failed");
+    }
+}
+
 static GLuint vigs_winsys_gl_surface_get_texture(struct winsys_gl_surface *sfc)
 {
     struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
@@ -1198,6 +1229,7 @@ static struct vigs_winsys_gl_surface
     ws_sfc->base.base.release = &vigs_winsys_gl_surface_release;
     ws_sfc->base.base.set_dirty = &vigs_winsys_gl_surface_set_dirty;
     ws_sfc->base.base.draw_pixels = &vigs_winsys_gl_surface_draw_pixels;
+    ws_sfc->base.base.draw_pixels_scaled = &vigs_winsys_gl_surface_draw_pixels_scaled;
     ws_sfc->base.get_texture = &vigs_winsys_gl_surface_get_texture;
     ws_sfc->tex_internalformat = tex_internalformat;
     ws_sfc->tex_format = tex_format;
@@ -1396,6 +1428,96 @@ out:
     gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
+static void vigs_gl_surface_draw_pixels_scaled(struct vigs_surface *sfc,
+                                               uint8_t *pixels,
+                                               uint32_t width,
+                                               uint32_t height)
+{
+    struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
+    struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
+    struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
+    GLfloat sfc_w, sfc_h;
+    GLfloat *vert_coords;
+    GLfloat *tex_coords;
+
+    sfc_w = ws_sfc->base.base.width;
+    sfc_h = ws_sfc->base.base.height;
+
+    if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
+        goto out;
+    }
+
+    if (!vigs_gl_surface_create_tmp_texture(gl_sfc)) {
+        goto out;
+    }
+
+    if (!vigs_gl_surface_setup_framebuffer(gl_sfc,
+                                           gl_backend->tex_prog_id,
+                                           gl_backend->tex_prog_proj_loc)) {
+        goto out;
+    }
+
+    gl_backend->BindTexture(GL_TEXTURE_2D, gl_sfc->tmp_tex);
+
+    gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    gl_backend->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    gl_backend->PixelStorei(GL_UNPACK_ROW_LENGTH, width);
+    gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+    gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+
+    if (width > sfc_w || height > sfc_h) {
+        gl_backend->TexImage2D(GL_TEXTURE_2D, 0, ws_sfc->tex_internalformat,
+                               width, height, 0,
+                               ws_sfc->tex_format,
+                               ws_sfc->tex_type,
+                               pixels);
+    } else {
+        gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+                                  width, height,
+                                  ws_sfc->tex_format,
+                                  ws_sfc->tex_type,
+                                  pixels);
+    }
+
+    vigs_vector_resize(&gl_backend->v1, 0);
+    vigs_vector_resize(&gl_backend->v2, 0);
+
+    gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                     GL_TEXTURE_2D, ws_sfc->tex, 0);
+
+    vert_coords = vigs_vector_append(&gl_backend->v1,
+                                     (12 * sizeof(GLfloat)));
+    tex_coords = vigs_vector_append(&gl_backend->v2,
+                                    (12 * sizeof(GLfloat)));
+
+    vert_coords[6] = vert_coords[0] = 0;
+    vert_coords[7] = vert_coords[1] = sfc_h;
+    vert_coords[2] = sfc_w;
+    vert_coords[3] = sfc_h;
+    vert_coords[8] = vert_coords[4] = sfc_w;
+    vert_coords[9] = vert_coords[5] = 0;
+    vert_coords[10] = 0;
+    vert_coords[11] = 0;
+
+    tex_coords[6] = tex_coords[0] = 0;
+    tex_coords[7] = tex_coords[1] = 0;
+    tex_coords[2] = (GLfloat)width / sfc_w;
+    tex_coords[3] = 0;
+    tex_coords[8] = tex_coords[4] = (GLfloat)width / sfc_w;
+    tex_coords[9] = tex_coords[5] = (GLfloat)height / sfc_h;
+    tex_coords[10] = 0;
+    tex_coords[11] = (GLfloat)height / sfc_h;
+
+    vigs_gl_draw_tex_prog(gl_backend, 6);
+
+out:
+    gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
 static void vigs_gl_surface_copy(struct vigs_surface *dst,
                                  struct vigs_surface *src,
                                  const struct vigsp_copy *entries,
@@ -1793,6 +1915,7 @@ static struct vigs_surface *vigs_gl_backend_create_surface(struct vigs_backend *
 
     gl_sfc->base.read_pixels = &vigs_gl_surface_read_pixels;
     gl_sfc->base.draw_pixels = &vigs_gl_surface_draw_pixels;
+    gl_sfc->base.draw_pixels_scaled = &vigs_gl_surface_draw_pixels_scaled;
     gl_sfc->base.copy = &vigs_gl_surface_copy;
     gl_sfc->base.solid_fill = &vigs_gl_surface_solid_fill;
     gl_sfc->base.ga_copy = &vigs_gl_surface_ga_copy;
index a508d06..707f952 100644 (file)
@@ -60,6 +60,11 @@ struct vigs_surface
                         const struct vigsp_rect */*entries*/,
                         uint32_t /*num_entries*/);
 
+    void (*draw_pixels_scaled)(struct vigs_surface */*sfc*/,
+                               uint8_t */*pixels*/,
+                               uint32_t /*width*/,
+                               uint32_t /*height*/);
+
     void (*copy)(struct vigs_surface */*dst*/,
                  struct vigs_surface */*src*/,
                  const struct vigsp_copy */*entries*/,
index 2261ebc..a41e983 100644 (file)
@@ -112,6 +112,25 @@ static void vigs_winsys_sw_surface_draw_pixels(struct winsys_surface *sfc,
     vigs_sfc->parent->base.is_dirty = true;
 }
 
+static void vigs_winsys_sw_surface_draw_pixels_scaled(struct winsys_surface *sfc,
+                                                      uint8_t *pixels,
+                                                      uint32_t width,
+                                                      uint32_t height)
+{
+    struct vigs_winsys_sw_surface *vigs_sfc = (struct vigs_winsys_sw_surface*)sfc;
+
+    if (!vigs_sfc->parent) {
+        return;
+    }
+
+    vigs_sfc->parent->base.draw_pixels_scaled(&vigs_sfc->parent->base,
+                                              pixels,
+                                              width,
+                                              height);
+
+    vigs_sfc->parent->base.is_dirty = true;
+}
+
 static void vigs_winsys_sw_surface_destroy(struct vigs_ref *ref)
 {
     struct vigs_winsys_sw_surface *vigs_sfc =
@@ -137,6 +156,7 @@ static struct vigs_winsys_sw_surface
     ws_sfc->base.release = &vigs_winsys_sw_surface_release;
     ws_sfc->base.set_dirty = &vigs_winsys_sw_surface_set_dirty;
     ws_sfc->base.draw_pixels = &vigs_winsys_sw_surface_draw_pixels;
+    ws_sfc->base.draw_pixels_scaled = &vigs_winsys_sw_surface_draw_pixels_scaled;
     ws_sfc->parent = parent;
 
     vigs_ref_init(&ws_sfc->ref, &vigs_winsys_sw_surface_destroy);
@@ -208,6 +228,14 @@ static void vigs_sw_surface_draw_pixels(struct vigs_surface *sfc,
     }
 }
 
+static void vigs_sw_surface_draw_pixels_scaled(struct vigs_surface *sfc,
+                                               uint8_t *pixels,
+                                               uint32_t width,
+                                               uint32_t height)
+{
+    /* TODO: implement */
+}
+
 static void vigs_sw_surface_copy(struct vigs_surface *dst,
                                  struct vigs_surface *src,
                                  const struct vigsp_copy *entries,
@@ -369,6 +397,7 @@ static struct vigs_surface *vigs_sw_backend_create_surface(struct vigs_backend *
 
     sw_sfc->base.read_pixels = &vigs_sw_surface_read_pixels;
     sw_sfc->base.draw_pixels = &vigs_sw_surface_draw_pixels;
+    sw_sfc->base.draw_pixels_scaled = &vigs_sw_surface_draw_pixels_scaled;
     sw_sfc->base.copy = &vigs_sw_surface_copy;
     sw_sfc->base.solid_fill = &vigs_sw_surface_solid_fill;
     sw_sfc->base.ga_copy = &vigs_sw_surface_ga_copy;
index c480e07..7f365bc 100644 (file)
@@ -16,6 +16,11 @@ struct winsys_surface
     void (*set_dirty)(struct winsys_surface */*sfc*/);
 
     void (*draw_pixels)(struct winsys_surface */*sfc*/, uint8_t */*pixels*/);
+
+    void (*draw_pixels_scaled)(struct winsys_surface */*sfc*/,
+                               uint8_t */*pixels*/,
+                               uint32_t /*width*/,
+                               uint32_t /*height*/);
 };
 
 struct winsys_info