VIGS/qt5: support scaling 97/25097/2
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Tue, 29 Jul 2014 12:13:34 +0000 (16:13 +0400)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 30 Jul 2014 05:10:09 +0000 (22:10 -0700)
Scaling is now supported using bicubic
interpolation in fragment shader

Change-Id: I4312e2c573859560d763683ef57c458223f8eec2
Signed-off-by: Stanislav Vorobiov <s.vorobiov@samsung.com>
hw/vigs/vigs_gl_backend.c
hw/vigs/vigs_gl_backend.h
hw/vigs/vigs_gl_backend_cgl.c
hw/vigs/vigs_gl_backend_glx.c
hw/vigs/vigs_gl_backend_wgl.c
tizen/src/ui/displaywidget.cpp

index f8c467de3e45f72ec3d6dc9e522e64f4c334f9b5..eda75cd316512746e779ce052ca715b474d692b9 100644 (file)
@@ -36,6 +36,9 @@
 #include "vigs_ref.h"
 #include "winsys_gl.h"
 
+extern uint32_t qt5_window_width;
+extern uint32_t qt5_window_height;
+
 struct vigs_gl_surface;
 
 struct vigs_winsys_gl_surface
@@ -187,6 +190,113 @@ static const char *g_fs_color_source_gl3 =
     "    FragColor = color;\n"
     "}\n";
 
+static const char *g_fs_scale_source_gl2 =
+"#version 120\n\
+\n\
+uniform sampler2D tex;\n\
+uniform vec2 texSize;\n\
+varying vec2 v_texCoord;\n\
+vec4 cubic(float x)\n\
+{\n\
+    float x2 = x * x;\n\
+    float x3 = x2 * x;\n\
+    vec4 w;\n\
+    w.x = -x3 + 3*x2 - 3*x + 1;\n\
+    w.y = 3*x3 - 6*x2 + 4;\n\
+    w.z = -3*x3 + 3*x2 + 3*x + 1;\n\
+    w.w = x3;\n\
+    return w / 6.f;\n\
+}\n\
+void main()\n\
+{\n\
+    vec2 texscale = vec2(1.0 / texSize.x, 1.0 / texSize.y);\n\
+    vec2 texcoord = vec2(v_texCoord.x * texSize.x, v_texCoord.y * texSize.y);\n\
+    float fx = fract(texcoord.x);\n\
+    float fy = fract(texcoord.y);\n\
+    texcoord.x -= fx;\n\
+    texcoord.y -= fy;\n\
+\n\
+    vec4 xcubic = cubic(fx);\n\
+    vec4 ycubic = cubic(fy);\n\
+\n\
+    vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y -\n\
+0.5, texcoord.y + 1.5);\n\
+    vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x +\n\
+ycubic.y, ycubic.z + ycubic.w);\n\
+    vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) /\n\
+s;\n\
+\n\
+    vec4 sample0 = texture2D(tex, vec2(offset.x, offset.z) *\n\
+texscale);\n\
+    vec4 sample1 = texture2D(tex, vec2(offset.y, offset.z) *\n\
+texscale);\n\
+    vec4 sample2 = texture2D(tex, vec2(offset.x, offset.w) *\n\
+texscale);\n\
+    vec4 sample3 = texture2D(tex, vec2(offset.y, offset.w) *\n\
+texscale);\n\
+\n\
+    float sx = s.x / (s.x + s.y);\n\
+    float sy = s.z / (s.z + s.w);\n\
+\n\
+    gl_FragColor = mix(\n\
+        mix(sample3, sample2, sx),\n\
+        mix(sample1, sample0, sx), sy);\n\
+}";
+
+static const char *g_fs_scale_source_gl3 =
+"#version 140\n\
+\n\
+uniform sampler2D tex;\n\
+uniform vec2 texSize;\n\
+in vec2 v_texCoord;\n\
+out vec4 FragColor;\n\
+vec4 cubic(float x)\n\
+{\n\
+    float x2 = x * x;\n\
+    float x3 = x2 * x;\n\
+    vec4 w;\n\
+    w.x = -x3 + 3*x2 - 3*x + 1;\n\
+    w.y = 3*x3 - 6*x2 + 4;\n\
+    w.z = -3*x3 + 3*x2 + 3*x + 1;\n\
+    w.w = x3;\n\
+    return w / 6.f;\n\
+}\n\
+void main()\n\
+{\n\
+    vec2 texscale = vec2(1.0 / texSize.x, 1.0 / texSize.y);\n\
+    vec2 texcoord = vec2(v_texCoord.x * texSize.x, v_texCoord.y * texSize.y);\n\
+    float fx = fract(texcoord.x);\n\
+    float fy = fract(texcoord.y);\n\
+    texcoord.x -= fx;\n\
+    texcoord.y -= fy;\n\
+\n\
+    vec4 xcubic = cubic(fx);\n\
+    vec4 ycubic = cubic(fy);\n\
+\n\
+    vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y -\n\
+0.5, texcoord.y + 1.5);\n\
+    vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x +\n\
+ycubic.y, ycubic.z + ycubic.w);\n\
+    vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) /\n\
+s;\n\
+\n\
+    vec4 sample0 = texture2D(tex, vec2(offset.x, offset.z) *\n\
+texscale);\n\
+    vec4 sample1 = texture2D(tex, vec2(offset.y, offset.z) *\n\
+texscale);\n\
+    vec4 sample2 = texture2D(tex, vec2(offset.x, offset.w) *\n\
+texscale);\n\
+    vec4 sample3 = texture2D(tex, vec2(offset.y, offset.w) *\n\
+texscale);\n\
+\n\
+    float sx = s.x / (s.x + s.y);\n\
+    float sy = s.z / (s.z + s.w);\n\
+\n\
+    FragColor = mix(\n\
+        mix(sample3, sample2, sx),\n\
+        mix(sample1, sample0, sx), sy);\n\
+}";
+
 static GLuint vigs_gl_backend_alloc_tmp_texture(void *user_data,
                                                 uint32_t width,
                                                 uint32_t height,
@@ -226,6 +336,8 @@ static GLuint vigs_gl_backend_alloc_tmp_texture(void *user_data,
      */
     backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
     backend->TexImage2D(GL_TEXTURE_2D, 0, tex_internalformat,
                         width, height, 0,
@@ -483,6 +595,54 @@ static void vigs_gl_draw_dpy_tex_prog(struct vigs_gl_backend *backend,
     backend->DisableVertexAttribArray(backend->dpy_tex_prog_vertCoord_loc);
 }
 
+static void vigs_gl_draw_dpy_scale_prog(struct vigs_gl_backend *backend,
+                                        uint32_t count)
+{
+    uint32_t size = count * 16;
+    void *ptr;
+
+    if (size > backend->dpy_vbo_size) {
+        backend->dpy_vbo_size = size;
+        backend->BufferData(GL_ARRAY_BUFFER,
+                            size,
+                            0,
+                            GL_STREAM_DRAW);
+    }
+
+    if (backend->MapBufferRange) {
+        ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size,
+                                      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+
+        if (ptr) {
+            memcpy(ptr, vigs_vector_data(&backend->dpy_v1), size / 2);
+            memcpy(ptr + (size / 2), vigs_vector_data(&backend->dpy_v2), size / 2);
+
+            backend->UnmapBuffer(GL_ARRAY_BUFFER);
+        } else {
+            VIGS_LOG_ERROR("glMapBufferRange failed");
+        }
+    } else {
+        backend->Finish();
+        backend->BufferSubData(GL_ARRAY_BUFFER, 0,
+                               (size / 2), vigs_vector_data(&backend->dpy_v1));
+        backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2),
+                               (size / 2), vigs_vector_data(&backend->dpy_v2));
+    }
+
+    backend->EnableVertexAttribArray(backend->dpy_scale_prog_vertCoord_loc);
+    backend->EnableVertexAttribArray(backend->dpy_scale_prog_texCoord_loc);
+
+    backend->VertexAttribPointer(backend->dpy_scale_prog_vertCoord_loc,
+                                 2, GL_FLOAT, GL_FALSE, 0, NULL);
+    backend->VertexAttribPointer(backend->dpy_scale_prog_texCoord_loc,
+                                 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2));
+
+    backend->DrawArrays(GL_TRIANGLES, 0, count);
+
+    backend->DisableVertexAttribArray(backend->dpy_scale_prog_texCoord_loc);
+    backend->DisableVertexAttribArray(backend->dpy_scale_prog_vertCoord_loc);
+}
+
 static void vigs_gl_create_ortho(GLfloat left, GLfloat right,
                                  GLfloat bottom, GLfloat top,
                                  GLfloat nearf, GLfloat farf,
@@ -543,6 +703,8 @@ static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface
      */
     ws_sfc->backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     ws_sfc->backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    ws_sfc->backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    ws_sfc->backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
     ws_sfc->backend->TexImage2D(GL_TEXTURE_2D, 0, ws_sfc->tex_internalformat,
                                 ws_sfc->base.base.width, ws_sfc->base.base.height, 0,
@@ -1236,6 +1398,7 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface,
     GLfloat *vert_coords;
     GLfloat *tex_coords;
     const struct vigs_plane *sorted_planes[VIGS_MAX_PLANES];
+    bool scale;
 
     VIGS_LOG_TRACE("enter");
 
@@ -1276,17 +1439,29 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface,
         }
     }
 
-    /*
-     * TODO: scale.
-     */
+    scale = (qt5_window_width != ws_root_sfc->base.base.width) ||
+            (qt5_window_height != ws_root_sfc->base.base.height);
 
     gl_backend->Viewport(0, 0,
-                         gl_root_sfc->base.ws_sfc->width / 2,
-                         gl_root_sfc->base.ws_sfc->height / 2);
+                         qt5_window_width,
+                         qt5_window_height);
+
+    if (scale) {
+        float texSize[2];
 
-    gl_backend->UseProgram(gl_backend->dpy_tex_prog_id);
-    gl_backend->UniformMatrix4fv(gl_backend->dpy_tex_prog_proj_loc, 1, GL_FALSE,
-                                 gl_root_sfc->ortho);
+        gl_backend->UseProgram(gl_backend->dpy_scale_prog_id);
+        gl_backend->UniformMatrix4fv(gl_backend->dpy_scale_prog_proj_loc, 1, GL_FALSE,
+                                     gl_root_sfc->ortho);
+
+        texSize[0] = ws_root_sfc->base.base.width;
+        texSize[1] = ws_root_sfc->base.base.height;
+
+        gl_backend->Uniform2fv(gl_backend->dpy_scale_prog_texSize_loc, 1, texSize);
+    } else {
+        gl_backend->UseProgram(gl_backend->dpy_tex_prog_id);
+        gl_backend->UniformMatrix4fv(gl_backend->dpy_tex_prog_proj_loc, 1, GL_FALSE,
+                                     gl_root_sfc->ortho);
+    }
 
     gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
 
@@ -1346,7 +1521,11 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface,
         tex_coords[11] = 0;
     }
 
-    vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
+    if (scale) {
+        vigs_gl_draw_dpy_scale_prog(gl_backend, 6);
+    } else {
+        vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
+    }
 
     /*
      * Sort planes, only 2 of them now, don't bother...
@@ -1402,7 +1581,18 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface,
 
         gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
 
-        vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
+        if (scale) {
+            float texSize[2];
+
+            texSize[0] = src_w;
+            texSize[1] = src_h;
+
+            gl_backend->Uniform2fv(gl_backend->dpy_scale_prog_texSize_loc, 1, texSize);
+
+            vigs_gl_draw_dpy_scale_prog(gl_backend, 6);
+        } else {
+            vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
+        }
     }
 
     return false;
@@ -1547,6 +1737,35 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend)
     gl_backend->dpy_tex_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_tex_prog_id, "vertCoord");
     gl_backend->dpy_tex_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_tex_prog_id, "texCoord");
 
+    gl_backend->dpy_scale_prog_vs_id = vigs_gl_create_shader(gl_backend,
+        (gl_backend->is_gl_2 ? g_vs_tex_source_gl2 : g_vs_tex_source_gl3),
+        GL_VERTEX_SHADER);
+
+    if (!gl_backend->dpy_scale_prog_vs_id) {
+        goto fail;
+    }
+
+    gl_backend->dpy_scale_prog_fs_id = vigs_gl_create_shader(gl_backend,
+        (gl_backend->is_gl_2 ? g_fs_scale_source_gl2 : g_fs_scale_source_gl3),
+        GL_FRAGMENT_SHADER);
+
+    if (!gl_backend->dpy_scale_prog_fs_id) {
+        goto fail;
+    }
+
+    gl_backend->dpy_scale_prog_id = vigs_gl_create_program(gl_backend,
+                                                           gl_backend->dpy_scale_prog_vs_id,
+                                                           gl_backend->dpy_scale_prog_fs_id);
+
+    if (!gl_backend->dpy_scale_prog_id) {
+        goto fail;
+    }
+
+    gl_backend->dpy_scale_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->dpy_scale_prog_id, "proj");
+    gl_backend->dpy_scale_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_scale_prog_id, "vertCoord");
+    gl_backend->dpy_scale_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_scale_prog_id, "texCoord");
+    gl_backend->dpy_scale_prog_texSize_loc = gl_backend->GetUniformLocation(gl_backend->dpy_scale_prog_id, "texSize");
+
     gl_backend->Disable(GL_DEPTH_TEST);
     gl_backend->Disable(GL_BLEND);
 
@@ -1574,6 +1793,13 @@ void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend)
 {
     if (gl_backend->make_current(gl_backend, true)) {
         gl_backend->DeleteBuffers(1, &gl_backend->dpy_vbo);
+        gl_backend->DetachShader(gl_backend->dpy_scale_prog_id,
+                                 gl_backend->dpy_scale_prog_vs_id);
+        gl_backend->DetachShader(gl_backend->dpy_scale_prog_id,
+                                 gl_backend->dpy_scale_prog_fs_id);
+        gl_backend->DeleteShader(gl_backend->dpy_scale_prog_vs_id);
+        gl_backend->DeleteShader(gl_backend->dpy_scale_prog_fs_id);
+        gl_backend->DeleteProgram(gl_backend->dpy_scale_prog_id);
         gl_backend->DetachShader(gl_backend->dpy_tex_prog_id,
                                  gl_backend->dpy_tex_prog_vs_id);
         gl_backend->DetachShader(gl_backend->dpy_tex_prog_id,
index f3643be68925bda1ea5f1811022554fa70d042ac..7f900f9e7a419928087ab21aada608df3ed6423e 100644 (file)
@@ -116,6 +116,7 @@ struct vigs_gl_backend
     void (GLAPIENTRY* VertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
     void (GLAPIENTRY* Uniform4fv)(GLint location, GLsizei count, const GLfloat* value);
     void (GLAPIENTRY* UniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+    void (GLAPIENTRY* Uniform2fv)(GLint location, GLsizei count, const GLfloat* value);
 
     /*
      * @}
@@ -198,6 +199,14 @@ struct vigs_gl_backend
     GLint dpy_tex_prog_vertCoord_loc;
     GLint dpy_tex_prog_texCoord_loc;
 
+    GLuint dpy_scale_prog_vs_id;
+    GLuint dpy_scale_prog_fs_id;
+    GLuint dpy_scale_prog_id;
+    GLint dpy_scale_prog_proj_loc;
+    GLint dpy_scale_prog_vertCoord_loc;
+    GLint dpy_scale_prog_texCoord_loc;
+    GLint dpy_scale_prog_texSize_loc;
+
     GLuint dpy_vbo;
     uint32_t dpy_vbo_size;
 
index 081940970a817f7d1bc614b14c7bf4105f68c6df..768146d2b2099123c2ff1b6c0ae7bb112b55411c 100644 (file)
@@ -320,6 +320,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer);
     VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
     VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);
+    VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv);
 
     VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);
 
index 294bdef2a85a747b8f815d7381af3fdf100ee388..64d8324ed4ad0d02e6e91475d10ad8e733942cca 100644 (file)
@@ -404,6 +404,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer);
     VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
     VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);
+    VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv);
 
     VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);
 
index 7cb650e9bf6abfb1007d7e05e322f31b624cd0ad..30eb634f4e47f08d44da446485fe73127d2713c5 100644 (file)
@@ -610,6 +610,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer);
     VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
     VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);
+    VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv);
 
     VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);
 
index 19150196ba1796e8bc1db9324db84227d25f815a..9d469c44fd64501003ef4ca7a02e288fd86d7661 100644 (file)
@@ -8,6 +8,9 @@ void do_mouse_event(int button_type, int event_type,
     int origin_x, int origin_y, int x, int y, int z);
 }
 
+uint32_t qt5_window_width = 0;
+uint32_t qt5_window_height = 0;
+
 DisplayWidget::DisplayWidget(QSize resolution, QGLContext *context, QWidget *parent) :
     QGLWidget(context, parent)
 {
@@ -77,6 +80,9 @@ void DisplayWidget::resizeEvent(QResizeEvent *event)
                 layout->displayRegion.y() * sy,
                 layout->displayRegion.width() * sx,
                 layout->displayRegion.height() * sy);
+
+    qt5_window_width = width();
+    qt5_window_height = height();
 }
 
 void DisplayWidget::mousePressEvent(QMouseEvent *event)