#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
" 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,
*/
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,
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,
*/
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,
GLfloat *vert_coords;
GLfloat *tex_coords;
const struct vigs_plane *sorted_planes[VIGS_MAX_PLANES];
+ bool scale;
VIGS_LOG_TRACE("enter");
}
}
- /*
- * 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);
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...
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;
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);
{
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,