From: Stanislav Vorobiov Date: Tue, 29 Jul 2014 12:13:34 +0000 (+0400) Subject: VIGS/qt5: support scaling X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ce49cfbaa583229d32c95bb393a544778b4c1471;p=sdk%2Femulator%2Fqemu.git VIGS/qt5: support scaling Scaling is now supported using bicubic interpolation in fragment shader Change-Id: I4312e2c573859560d763683ef57c458223f8eec2 Signed-off-by: Stanislav Vorobiov --- diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c index f8c467de3e..eda75cd316 100644 --- a/hw/vigs/vigs_gl_backend.c +++ b/hw/vigs/vigs_gl_backend.c @@ -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, diff --git a/hw/vigs/vigs_gl_backend.h b/hw/vigs/vigs_gl_backend.h index f3643be689..7f900f9e7a 100644 --- a/hw/vigs/vigs_gl_backend.h +++ b/hw/vigs/vigs_gl_backend.h @@ -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; diff --git a/hw/vigs/vigs_gl_backend_cgl.c b/hw/vigs/vigs_gl_backend_cgl.c index 081940970a..768146d2b2 100644 --- a/hw/vigs/vigs_gl_backend_cgl.c +++ b/hw/vigs/vigs_gl_backend_cgl.c @@ -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); diff --git a/hw/vigs/vigs_gl_backend_glx.c b/hw/vigs/vigs_gl_backend_glx.c index 294bdef2a8..64d8324ed4 100644 --- a/hw/vigs/vigs_gl_backend_glx.c +++ b/hw/vigs/vigs_gl_backend_glx.c @@ -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); diff --git a/hw/vigs/vigs_gl_backend_wgl.c b/hw/vigs/vigs_gl_backend_wgl.c index 7cb650e9bf..30eb634f4e 100644 --- a/hw/vigs/vigs_gl_backend_wgl.c +++ b/hw/vigs/vigs_gl_backend_wgl.c @@ -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); diff --git a/tizen/src/ui/displaywidget.cpp b/tizen/src/ui/displaywidget.cpp index 19150196ba..9d469c44fd 100644 --- a/tizen/src/ui/displaywidget.cpp +++ b/tizen/src/ui/displaywidget.cpp @@ -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)