#include "vigs_ref.h"
#include "vigs_qt5.h"
#include "winsys_gl.h"
-#include "hw/pci/maru_brightness.h"
#include <math.h>
-extern uint32_t qt5_window_width;
-extern uint32_t qt5_window_height;
-extern int qt5_window_angle;
-
-/* multitouch data */
-extern float *qt5_mt_points;
-extern int qt5_mt_count;
-extern const void *qt5_mt_pixels;
-extern int qt5_mt_width;
-extern int qt5_mt_height;
-
struct vigs_gl_surface;
struct vigs_winsys_gl_surface
" FragColor = color;\n"
"}\n";
-static const char *g_fs_dpy_source_gl2 =
- "#version 120\n\n"
- "uniform sampler2D tex;\n"
- "uniform float brightness;\n"
- "varying vec2 v_texCoord;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = texture2D(tex, v_texCoord) * brightness;\n"
- "}\n";
-
-static const char *g_fs_dpy_source_gl3 =
- "#version 140\n\n"
- "uniform sampler2D tex;\n"
- "uniform float brightness;\n"
- "in vec2 v_texCoord;\n"
- "out vec4 FragColor;\n"
- "void main()\n"
- "{\n"
- " FragColor = texture(tex, v_texCoord) * brightness;\n"
- "}\n";
-
-static const char *g_fs_scale_source_gl2 =
-"#version 120\n\
-\n\
-uniform sampler2D tex;\n\
-uniform float brightness;\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) * brightness;\n\
-}";
-
-static const char *g_fs_scale_source_gl3 =
-"#version 140\n\
-\n\
-uniform sampler2D tex;\n\
-uniform float brightness;\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 = texture(tex, vec2(offset.x, offset.z) *\n\
-texscale);\n\
- vec4 sample1 = texture(tex, vec2(offset.y, offset.z) *\n\
-texscale);\n\
- vec4 sample2 = texture(tex, vec2(offset.x, offset.w) *\n\
-texscale);\n\
- vec4 sample3 = texture(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) * brightness;\n\
-}";
-
static const char *g_vs_nv21_source_gl2 =
"#version 120\n\n"
"attribute vec4 vertCoord;\n"
backend->DisableVertexAttribArray(backend->color_prog_vertCoord_loc);
}
-static void vigs_gl_draw_dpy_tex_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_tex_prog_vertCoord_loc);
- backend->EnableVertexAttribArray(backend->dpy_tex_prog_texCoord_loc);
-
- backend->VertexAttribPointer(backend->dpy_tex_prog_vertCoord_loc,
- 2, GL_FLOAT, GL_FALSE, 0, NULL);
- backend->VertexAttribPointer(backend->dpy_tex_prog_texCoord_loc,
- 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2));
-
- backend->DrawArrays(GL_TRIANGLES, 0, count);
-
- backend->DisableVertexAttribArray(backend->dpy_tex_prog_texCoord_loc);
- 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_draw_nv21_prog(struct vigs_gl_backend *backend,
uint32_t count)
{
ortho[15] = 1.0f;
}
-static void vigs_gl_rotate_ortho(const GLfloat ortho[16],
- GLfloat angle,
- GLfloat res[16])
-{
- GLfloat rot[4][4] = {
- { cos(angle), sin(angle), 0, 0 },
- { -sin(angle), cos(angle), 0, 0 },
- { 0, 0, 1, 0 },
- { 0, 0, 0, 1 }
- };
- int i, j, k;
-
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 4; ++j) {
- res[i * 4 + j] = 0.0f;
- for (k = 0; k < 4; ++k) {
- res[i * 4 + j] += ortho[i * 4 + k] * rot[k][j];
- }
- }
- }
-}
-
static void vigs_gl_translate_color(vigsp_color color,
vigsp_surface_format format,
GLfloat res[4])
}
static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend,
- uint32_t width, uint32_t height,
- GLfloat ortho[16])
+ uint32_t width, uint32_t height)
{
GLuint cur_tex = 0;
gl_backend->BindTexture(GL_TEXTURE_2D, cur_tex);
- memcpy(gl_backend->dpy_tex_ortho,
- ortho,
- sizeof(gl_backend->dpy_tex_ortho));
gl_backend->dpy_tex_width = width;
gl_backend->dpy_tex_height = height;
if (!vigs_gl_update_dpy_texture(gl_backend,
surface->ws_sfc->width,
- surface->ws_sfc->height,
- gl_root_sfc->ortho)) {
+ surface->ws_sfc->height)) {
goto out;
}
VIGS_LOG_TRACE("enter");
if (vigs_qt5_onscreen_enabled()) {
- GLfloat *vert_coords;
- GLfloat *tex_coords;
- bool scale;
- GLfloat rotated_ortho[16];
- GLfloat *ortho;
- float brightness = (float)(255 - brightness_tbl[brightness_level]) / 255.0f;
- int i, mt_count = qt5_mt_count;
-
- if (display_off) {
- brightness = 0.0f;
- }
-
- if (!gl_backend->is_gl_2 && !gl_backend->dpy_vao) {
- gl_backend->GenVertexArrays(1, &gl_backend->dpy_vao);
+ vigs_qt5_dpy_render_texture(gl_backend->dpy_tex);
+ return true;
+ }
- if (!gl_backend->dpy_vao) {
- VIGS_LOG_CRITICAL("cannot create VAO");
+ if (gl_backend->read_pixels_make_current(gl_backend, true)) {
+ if (!gl_backend->dpy_fb) {
+ gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb);
+ if (!gl_backend->dpy_fb) {
+ VIGS_LOG_CRITICAL("cannot create FB");
exit(1);
}
- gl_backend->BindVertexArray(gl_backend->dpy_vao);
- }
-
- gl_backend->BindBuffer(GL_ARRAY_BUFFER, gl_backend->dpy_vbo);
- gl_backend->Disable(GL_DEPTH_TEST);
- gl_backend->Disable(GL_BLEND);
-
- if (qt5_window_angle == 0) {
- ortho = gl_backend->dpy_tex_ortho;
- } else {
- vigs_gl_rotate_ortho(gl_backend->dpy_tex_ortho,
- (float)(360.0f - qt5_window_angle) * M_PI / 180.0f,
- rotated_ortho);
- ortho = rotated_ortho;
- }
-
- scale = (qt5_window_width != gl_backend->dpy_tex_width) ||
- (qt5_window_height != gl_backend->dpy_tex_height);
-
- gl_backend->Viewport(0, 0,
- qt5_window_width,
- qt5_window_height);
-
- if (scale) {
- float texSize[2];
-
- gl_backend->UseProgram(gl_backend->dpy_scale_prog_id);
- gl_backend->UniformMatrix4fv(gl_backend->dpy_scale_prog_proj_loc, 1, GL_FALSE,
- ortho);
-
- texSize[0] = gl_backend->dpy_tex_width;
- texSize[1] = gl_backend->dpy_tex_height;
-
- gl_backend->Uniform2fv(gl_backend->dpy_scale_prog_texSize_loc, 1, texSize);
- gl_backend->Uniform1f(gl_backend->dpy_scale_prog_brightness_loc, brightness);
- } else {
- gl_backend->UseProgram(gl_backend->dpy_tex_prog_id);
- gl_backend->UniformMatrix4fv(gl_backend->dpy_tex_prog_proj_loc, 1, GL_FALSE,
- ortho);
- gl_backend->Uniform1f(gl_backend->dpy_tex_prog_brightness_loc, brightness);
- }
-
- gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->dpy_tex);
-
- vigs_vector_resize(&gl_backend->dpy_v1, 0);
- vigs_vector_resize(&gl_backend->dpy_v2, 0);
-
- vert_coords = vigs_vector_append(&gl_backend->dpy_v1,
- (12 * sizeof(GLfloat)));
- tex_coords = vigs_vector_append(&gl_backend->dpy_v2,
- (12 * sizeof(GLfloat)));
-
- vert_coords[6] = vert_coords[0] = 0;
- vert_coords[7] = vert_coords[1] = gl_backend->dpy_tex_height;
- vert_coords[2] = gl_backend->dpy_tex_width;
- vert_coords[3] = gl_backend->dpy_tex_height;
- vert_coords[8] = vert_coords[4] = gl_backend->dpy_tex_width;
- 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] = 1;
- tex_coords[3] = 0;
- tex_coords[8] = tex_coords[4] = 1;
- tex_coords[9] = tex_coords[5] = 1;
- tex_coords[10] = 0;
- tex_coords[11] = 1;
-
- if (scale) {
- vigs_gl_draw_dpy_scale_prog(gl_backend, 6);
- } else {
- vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
- }
-
- if (!gl_backend->mt_tex) {
- GLuint mt_tex = 0;
-
- if (!qt5_mt_pixels || qt5_mt_width == 0 || qt5_mt_height == 0) {
- /* multitouch not initialized */
- goto out;
- }
-
- gl_backend->GenTextures(1, &mt_tex);
-
- if (!mt_tex) {
- VIGS_LOG_WARN("MT: GenTextures failed");
- goto out;
- }
-
- gl_backend->BindTexture(GL_TEXTURE_2D, mt_tex);
-
- gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- 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->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
- qt5_mt_width, qt5_mt_height, 0,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
- qt5_mt_pixels);
-
- gl_backend->mt_tex = mt_tex;
- gl_backend->mt_tex_width = qt5_mt_width;
- gl_backend->mt_tex_height = qt5_mt_height;
- } else {
- gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->mt_tex);
+ gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb);
}
- vigs_vector_resize(&gl_backend->dpy_v1, 0);
- vigs_vector_resize(&gl_backend->dpy_v2, 0);
-
- for (i = 0; i < mt_count; i++) {
- GLfloat w = (GLfloat)gl_backend->mt_tex_width;
- GLfloat h = (GLfloat)gl_backend->mt_tex_height;
- GLfloat x = qt5_mt_points[2 * i + 0] - w / 2;
- GLfloat y = qt5_window_height - qt5_mt_points[2 * i + 1] - h / 2;
-
- vert_coords = vigs_vector_append(&gl_backend->dpy_v1,
- (12 * sizeof(GLfloat)));
- tex_coords = vigs_vector_append(&gl_backend->dpy_v2,
- (12 * sizeof(GLfloat)));
-
- vert_coords[6] = vert_coords[0] = x;
- vert_coords[7] = vert_coords[1] = y;
- vert_coords[2] = x + w;
- vert_coords[3] = y;
- vert_coords[8] = vert_coords[4] = x + w;
- vert_coords[9] = vert_coords[5] = y + h;
- vert_coords[10] = x;
- vert_coords[11] = y + h;
-
- tex_coords[6] = tex_coords[0] = 0;
- tex_coords[7] = tex_coords[1] = 1;
- tex_coords[2] = 1;
- tex_coords[3] = 1;
- tex_coords[8] = tex_coords[4] = 1;
- tex_coords[9] = tex_coords[5] = 0;
- tex_coords[10] = 0;
- tex_coords[11] = 0;
- }
-
- if (mt_count) {
- vigs_gl_create_ortho(0.0f, qt5_window_width,
- 0.0f, qt5_window_height,
- -1.0f, 1.0f,
- gl_backend->mt_tex_ortho);
-
- gl_backend->Enable(GL_BLEND);
- gl_backend->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- gl_backend->UseProgram(gl_backend->dpy_tex_prog_id);
- gl_backend->UniformMatrix4fv(gl_backend->dpy_tex_prog_proj_loc, 1, GL_FALSE,
- gl_backend->mt_tex_ortho);
- gl_backend->Uniform1f(gl_backend->dpy_tex_prog_brightness_loc, 1.0f);
-
- vigs_gl_draw_dpy_tex_prog(gl_backend, mt_count * 6);
+ gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, gl_backend->dpy_tex, 0);
- gl_backend->Disable(GL_BLEND);
- }
+ gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width,
+ gl_backend->dpy_tex_height,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ display_data);
-out:
- gl_backend->Finish();
+ gl_backend->read_pixels_make_current(gl_backend, false);
return true;
} else {
- if (gl_backend->read_pixels_make_current(gl_backend, true)) {
- if (!gl_backend->dpy_fb) {
- gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb);
-
- if (!gl_backend->dpy_fb) {
- VIGS_LOG_CRITICAL("cannot create FB");
- exit(1);
- }
-
- gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb);
- }
-
- gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, gl_backend->dpy_tex, 0);
-
- gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width,
- gl_backend->dpy_tex_height,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
- display_data);
-
- gl_backend->read_pixels_make_current(gl_backend, false);
-
- return true;
- } else {
- return false;
- }
+ return false;
}
}
gl_backend->yuv420_prog_vtex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtex");
gl_backend->GenBuffers(1, &gl_backend->vbo);
- gl_backend->GenBuffers(1, &gl_backend->dpy_vbo);
-
- if (!gl_backend->vbo || !gl_backend->dpy_vbo) {
+ if (!gl_backend->vbo) {
VIGS_LOG_CRITICAL("cannot create VBOs");
goto fail;
}
gl_backend->UseProgram(gl_backend->tex_prog_id);
gl_backend->cur_prog_id = gl_backend->tex_prog_id;
- gl_backend->dpy_tex_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_tex_prog_vs_id) {
- goto fail;
- }
-
- gl_backend->dpy_tex_prog_fs_id = vigs_gl_create_shader(gl_backend,
- (gl_backend->is_gl_2 ? g_fs_dpy_source_gl2 : g_fs_dpy_source_gl3),
- GL_FRAGMENT_SHADER);
-
- if (!gl_backend->dpy_tex_prog_fs_id) {
- goto fail;
- }
-
- gl_backend->dpy_tex_prog_id = vigs_gl_create_program(gl_backend,
- gl_backend->dpy_tex_prog_vs_id,
- gl_backend->dpy_tex_prog_fs_id);
-
- if (!gl_backend->dpy_tex_prog_id) {
- goto fail;
- }
-
- gl_backend->dpy_tex_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->dpy_tex_prog_id, "proj");
- 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_tex_prog_brightness_loc = gl_backend->GetUniformLocation(gl_backend->dpy_tex_prog_id, "brightness");
-
- 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->dpy_scale_prog_brightness_loc = gl_backend->GetUniformLocation(gl_backend->dpy_scale_prog_id, "brightness");
-
gl_backend->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl_backend->Disable(GL_DEPTH_TEST);
gl_backend->Disable(GL_BLEND);
vigs_vector_init(&gl_backend->v1, 0);
vigs_vector_init(&gl_backend->v2, 0);
- vigs_vector_init(&gl_backend->dpy_v1, 0);
- vigs_vector_init(&gl_backend->dpy_v2, 0);
return true;
void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend)
{
if (gl_backend->make_current(gl_backend, true)) {
- if (gl_backend->mt_tex) {
- gl_backend->DeleteTextures(1, &gl_backend->mt_tex);
- }
if (gl_backend->dpy_tex) {
gl_backend->DeleteTextures(1, &gl_backend->dpy_tex);
}
if (gl_backend->dpy_fb) {
gl_backend->DeleteFramebuffers(1, &gl_backend->dpy_fb);
}
- 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,
- gl_backend->dpy_tex_prog_fs_id);
- gl_backend->DeleteShader(gl_backend->dpy_tex_prog_vs_id);
- gl_backend->DeleteShader(gl_backend->dpy_tex_prog_fs_id);
- gl_backend->DeleteProgram(gl_backend->dpy_tex_prog_id);
gl_backend->DeleteBuffers(1, &gl_backend->vbo);
gl_backend->DetachShader(gl_backend->yuv420_prog_id,
gl_backend->yuv420_prog_vs_id);
gl_backend->make_current(gl_backend, false);
}
- vigs_vector_cleanup(&gl_backend->dpy_v2);
- vigs_vector_cleanup(&gl_backend->dpy_v1);
vigs_vector_cleanup(&gl_backend->v2);
vigs_vector_cleanup(&gl_backend->v1);
}
* Display thread related.
* @{
*/
-
- struct vigs_vector dpy_v1;
- struct vigs_vector dpy_v2;
-
- GLuint dpy_vao;
-
- GLuint dpy_tex_prog_vs_id;
- GLuint dpy_tex_prog_fs_id;
- GLuint dpy_tex_prog_id;
- GLint dpy_tex_prog_proj_loc;
- GLint dpy_tex_prog_vertCoord_loc;
- GLint dpy_tex_prog_texCoord_loc;
- GLint dpy_tex_prog_brightness_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;
- GLint dpy_scale_prog_brightness_loc;
-
- GLuint dpy_vbo;
- uint32_t dpy_vbo_size;
-
GLuint dpy_tex;
GLuint dpy_fb;
- GLfloat dpy_tex_ortho[16];
uint32_t dpy_tex_width;
uint32_t dpy_tex_height;
- GLuint mt_tex;
- GLfloat mt_tex_ortho[16];
- uint32_t mt_tex_width;
- uint32_t mt_tex_height;
-
/*
* @}
*/
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFAPBuffer,
+ kCGLPFAOpenGLProfile, kCGLOGLPVersion_Legacy,
0
};
CGLError error;
CGLPixelFormatObj pixel_format;
int n;
- CGLContextObj qt5_ctx = NULL;
+ CGLContextObj share_ctx = NULL;
gl_backend_cgl = g_malloc0(sizeof(*gl_backend_cgl));
}
if (vigs_qt5_onscreen_enabled()) {
- qt5_ctx = (CGLContextObj)vigs_qt5_gl_context_create(gl_backend_cgl->base.is_gl_2);
- if (!qt5_ctx) {
+ share_ctx = (CGLContextObj)vigs_qt5_gl_context_get();
+ if (!share_ctx) {
goto fail2;
}
}
if (!vigs_gl_backend_cgl_create_context(gl_backend_cgl,
pixel_format,
- qt5_ctx,
+ share_ctx,
&gl_backend_cgl->context)) {
goto fail3;
}
};
if (gl_backend_glx->glXQueryContext(gl_backend_glx->dpy,
- gl_backend_glx->ctx,
+ vigs_qt5_gl_context_get(),
GLX_FBCONFIG_ID,
&config_attribs[1]) != Success) {
VIGS_LOG_CRITICAL("Unable to get context's GLX config");
gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy,
gl_backend_glx->read_pixels_sfc);
}
- if (!vigs_qt5_onscreen_enabled() && gl_backend_glx->ctx) {
+ if (gl_backend_glx->ctx) {
gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy,
gl_backend_glx->ctx);
}
{
struct vigs_gl_backend_glx *gl_backend_glx;
GLXFBConfig config;
+ GLXContext share_ctx = NULL;
Display *x_display = display;
gl_backend_glx = g_malloc0(sizeof(*gl_backend_glx));
}
if (vigs_qt5_onscreen_enabled()) {
- gl_backend_glx->ctx =
- (GLXContext)vigs_qt5_gl_context_create(gl_backend_glx->base.is_gl_2);
-
- if (!gl_backend_glx->ctx) {
- goto fail2;
- }
-
- config = vigs_gl_backend_glx_get_config(gl_backend_glx);
-
- if (!config) {
- goto fail2;
- }
-
- if (!vigs_gl_backend_glx_create_surface(gl_backend_glx,
- config,
- &gl_backend_glx->read_pixels_sfc)) {
+ share_ctx = (GLXContext)vigs_qt5_gl_context_get();
+ if (!share_ctx) {
goto fail2;
}
+ }
- if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
- config,
- gl_backend_glx->ctx,
- &gl_backend_glx->read_pixels_ctx)) {
- goto fail2;
- }
- } else {
- config = vigs_gl_backend_glx_get_config(gl_backend_glx);
-
- if (!config) {
- goto fail2;
- }
+ config = vigs_gl_backend_glx_get_config(gl_backend_glx);
+ if (!config) {
+ goto fail2;
+ }
- if (!vigs_gl_backend_glx_create_surface(gl_backend_glx,
- config,
- &gl_backend_glx->read_pixels_sfc)) {
- goto fail2;
- }
+ if (!vigs_gl_backend_glx_create_surface(gl_backend_glx,
+ config,
+ &gl_backend_glx->read_pixels_sfc)) {
+ goto fail2;
+ }
- if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
- config,
- NULL,
- &gl_backend_glx->ctx)) {
- goto fail2;
- }
+ if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
+ config,
+ share_ctx,
+ &gl_backend_glx->ctx)) {
+ goto fail2;
+ }
- if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
- config,
- gl_backend_glx->ctx,
- &gl_backend_glx->read_pixels_ctx)) {
- goto fail2;
- }
+ if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
+ config,
+ gl_backend_glx->ctx,
+ &gl_backend_glx->read_pixels_ctx)) {
+ goto fail2;
}
if (!vigs_gl_backend_glx_create_surface(gl_backend_glx,
gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy,
gl_backend_glx->read_pixels_sfc);
}
- if (!vigs_qt5_onscreen_enabled() && gl_backend_glx->ctx) {
+ if (gl_backend_glx->ctx) {
gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy,
gl_backend_glx->ctx);
}
};
const char *ext_str = NULL;
struct vigs_gl_backend_wgl *gl_backend_wgl = NULL;
- HGLRC qt5_ctx = NULL;
+ HGLRC share_ctx = NULL;
vigs_win_class.cbSize = sizeof(WNDCLASSEXA);
vigs_win_class.style = 0;
tmp_win = NULL;
if (vigs_qt5_onscreen_enabled()) {
- qt5_ctx =
- (HGLRC)vigs_qt5_gl_context_create(gl_backend_wgl->base.is_gl_2);
- if (!qt5_ctx) {
+ share_ctx = (HGLRC)vigs_qt5_gl_context_get();
+ if (!share_ctx) {
goto fail;
}
}
}
if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl,
- qt5_ctx,
+ share_ctx,
&gl_backend_wgl->ctx)) {
goto fail;
}
#include "vigs_log.h"
#include "work_queue.h"
+struct vigs_display_work_item
+{
+ struct work_queue_item base;
+
+ struct vigs_server *server;
+};
+
+static void vigs_onscreen_server_display_work(struct work_queue_item *wq_item)
+{
+ struct vigs_display_work_item *item = (struct vigs_display_work_item*)wq_item;
+ struct vigs_server *server = item->server;
+
+ server->backend->display(server->backend, NULL);
+ vigs_server_finish_update_display(server, false);
+
+ g_free(item);
+}
+
static bool vigs_onscreen_server_begin_update(struct vigs_server *server,
bool is_capturing,
bool force)
goto out;
}
- onscreen_server->updated = false;
- onscreen_server->composited = false;
- onscreen_server->dirty = false;
-
out:
qemu_mutex_unlock(&onscreen_server->mutex);
{
struct vigs_onscreen_server *onscreen_server =
(struct vigs_onscreen_server*)server;
-
- qemu_mutex_lock(&onscreen_server->mutex);
-
- onscreen_server->updated = true;
- onscreen_server->composited = composited;
- onscreen_server->dirty = dirty;
-
- qemu_mutex_unlock(&onscreen_server->mutex);
-
- qemu_cond_signal(&onscreen_server->cond);
-}
-
-static bool vigs_onscreen_server_display(struct vigs_server *server,
- bool *displayed)
-{
- struct vigs_onscreen_server *onscreen_server =
- (struct vigs_onscreen_server*)server;
bool force = false;
qemu_mutex_lock(&onscreen_server->mutex);
- /*
- * Wait until rendering is finished.
- */
- while (!onscreen_server->updated) {
- qemu_cond_wait(&onscreen_server->cond, &onscreen_server->mutex);
- }
-
if (onscreen_server->invalidate_cnt > 0) {
--onscreen_server->invalidate_cnt;
force = true;
}
- onscreen_server->updated = false;
-
qemu_mutex_unlock(&onscreen_server->mutex);
- *displayed = true;
+ if (composited || force) {
+ struct vigs_display_work_item *item;
- if (onscreen_server->dirty) {
- /*
- * Software composition took place, finish ASAP and
- * process captured data.
- */
- vigs_server_finish_update_display(server, true);
- return vigs_server_process_captured(server, force);
- } else if (onscreen_server->composited) {
- /*
- * Hw composition took place, display the content.
- */
- server->backend->display(server->backend, NULL);
- } else if (force) {
- /*
- * Nothing happened, but if it's a forced display, then
- * we should try to display hw stuff first, if there isn't any
- * then display sw stuff.
- */
- if (!server->backend->display(server->backend, NULL)) {
- vigs_server_finish_update_display(server, false);
- return vigs_server_process_captured(server, force);
- }
+ item = g_malloc(sizeof(*item));
+
+ work_queue_item_init(&item->base, &vigs_onscreen_server_display_work);
+
+ item->server = server;
+
+ work_queue_add_item(onscreen_server->display_queue, &item->base);
} else {
- *displayed = false;
+ vigs_server_finish_update_display(server, false);
}
- vigs_server_finish_update_display(server, false);
+}
+static bool vigs_onscreen_server_display(struct vigs_server *server,
+ bool *displayed)
+{
+ *displayed = false;
return false;
}
struct vigs_onscreen_server *onscreen_server =
(struct vigs_onscreen_server*)server;
- qemu_cond_destroy(&onscreen_server->cond);
qemu_mutex_destroy(&onscreen_server->mutex);
vigs_server_cleanup(server);
}
qemu_mutex_init(&server->mutex);
- qemu_cond_init(&server->cond);
+
+ server->display_queue = render_queue;
server->base.begin_update = &vigs_onscreen_server_begin_update;
server->base.finish_update = &vigs_onscreen_server_finish_update;
struct vigs_server base;
QemuMutex mutex;
- QemuCond cond;
- bool updated;
- bool composited;
- bool dirty;
-
int invalidate_cnt;
+ struct work_queue *display_queue;
};
struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr,
*
*/
-#include "vigs_qt5.h"
-#include "config-host.h"
+#include <stdio.h>
#include <QGuiApplication>
#include <QOpenGLContext>
#include <qpa/qplatformnativeinterface.h>
-#include <stdio.h>
+#include "config-host.h"
+#include "vigs_qt5.h"
extern bool qt5IsOnscreen;
extern QApplication *qt5App;
extern QOpenGLContext *qt5GLContext;
-extern QSurfaceFormat qt5GLFormat;
extern void qt5_register_capture_request_listener(void *listener,
void (*handler)(void *));
extern void qt5_unregister_capture_request_listener(void *listener);
extern void qt5_process_captured(bool captured, void *pixels,
int width, int height);
+extern void qt5_update_texture(unsigned int tex_id);
bool vigs_qt5_onscreen_enabled(void)
{
- // TODO: on Darwin?
if (qt5App != NULL && qt5IsOnscreen) {
return true;
}
QGuiApplication::primaryScreen());
}
-void *vigs_qt5_gl_context_create(bool is_gl2)
+void *vigs_qt5_gl_context_get(void)
{
if (!qt5App) {
fprintf(stderr, "QT5 not enabled!\n");
}
if (qt5GLContext) {
- fprintf(stderr, "QT5 GL context already created!\n");
- return NULL;
- }
-
- qt5GLContext = new QOpenGLContext();
-
- QSurfaceFormat format;
-
- format.setRedBufferSize(8);
- format.setGreenBufferSize(8);
- format.setBlueBufferSize(8);
- format.setAlphaBufferSize(8);
- format.setDepthBufferSize(24);
- format.setStencilBufferSize(8);
-
- if (!is_gl2) {
- format.setMajorVersion(3);
-#ifdef CONFIG_DARWIN
- format.setMinorVersion(2);
- format.setProfile(QSurfaceFormat::CoreProfile);
-#else
- format.setMinorVersion(1);
-#endif
- }
-
- qt5GLContext->setScreen(QGuiApplication::primaryScreen());
- qt5GLContext->setFormat(format);
-
- if (!qt5GLContext->create()) {
- fprintf(stderr, "Cannot create QT5 GL context!\n");
-
- delete qt5GLContext;
- qt5GLContext = NULL;
-
- return NULL;
- }
-
- if (!is_gl2) {
- if ((qt5GLContext->format().majorVersion() < 3) ||
- ((qt5GLContext->format().majorVersion() == 3) &&
- (qt5GLContext->format().minorVersion() < 1))) {
- fprintf(stderr, "Cannot create QT5 3.1 GL context!\n");
-
- delete qt5GLContext;
- qt5GLContext = NULL;
-
- return NULL;
- }
- }
-
- QPlatformNativeInterface *native =
- QGuiApplication::platformNativeInterface();
+ QPlatformNativeInterface *native =
+ QGuiApplication::platformNativeInterface();
- void *ret = NULL;
+ void *ret = NULL;
#if defined(CONFIG_LINUX)
- ret = native->nativeResourceForContext(QByteArray("glxcontext"), qt5GLContext);
+ ret = native->nativeResourceForContext(QByteArray("glxcontext"),
+ qt5GLContext);
#elif defined(CONFIG_WIN32)
- ret = native->nativeResourceForContext(QByteArray("renderingContext"), qt5GLContext);
+ ret = native->nativeResourceForContext(QByteArray("renderingContext"),
+ qt5GLContext);
#elif defined(CONFIG_DARWIN)
- ret = native->nativeResourceForContext(QByteArray("cglContextObj"), qt5GLContext);
+ ret = native->nativeResourceForContext(QByteArray("cglContextObj"),
+ qt5GLContext);
#endif
-
- if (!ret) {
- fprintf(stderr, "Cannot get native QT5 GL context!\n");
-
- delete qt5GLContext;
- qt5GLContext = NULL;
+ if (!ret) {
+ fprintf(stderr, "Cannot get native QT5 GL context!\n");
+ }
+ return ret;
}
-
- qt5GLFormat = format;
-
- return ret;
+ return NULL;
}
void vigs_qt5_register_capture_request_listener(void *listener,
{
qt5_process_captured(captured, pixels, width, height);
}
+
+void vigs_qt5_dpy_render_texture(uint32_t tex_id)
+{
+ qt5_update_texture(tex_id);
+}
void *vigs_qt5_display(void);
-void *vigs_qt5_gl_context_create(bool is_gl2);
+void *vigs_qt5_gl_context_get(void);
void vigs_qt5_register_capture_request_listener(void *listener,
void (*handler)(void *));
void vigs_qt5_unregister_capture_request_listener(void *listener);
void vigs_qt5_process_captured(bool captured, void *pixels,
int width, int height);
-
+void vigs_qt5_dpy_render_texture(uint32_t tex_id);
#ifdef __cplusplus
};
#endif
#include "emulator_common.h"
#include "vigs_qt5.h"
-uint32_t qt5_window_width = 0;
-uint32_t qt5_window_height = 0;
-int qt5_window_angle = 0;
-
-/* mutlitouch data */
-float *qt5_mt_points = NULL;
-int qt5_mt_count = 0;
-const void *qt5_mt_pixels = NULL;
-int qt5_mt_width = 0;
-int qt5_mt_height = 0;
-
bool vigs_qt5_onscreen_enabled(void)
{
return false;
return NULL;
}
-void *vigs_qt5_gl_context_create(bool is_gl2)
+void *vigs_qt5_gl_context_get(void)
{
return NULL;
}
{
return;
}
+
+void vigs_qt5_dpy_render_texture(uint32_t tex_id)
+{
+ return;
+}
+
obj-$(CONFIG_QT) += displaybase.o
obj-$(CONFIG_QT) += displayglwidget.o moc_displayglwidget.o
obj-$(CONFIG_QT) += displayswwidget.o moc_displayswwidget.o
-obj-$(CONFIG_QT) += displayswapper.o moc_displayswapper.o
obj-$(CONFIG_QT) += movingwidget.o
obj-$(CONFIG_QT) += mainwindow.o moc_mainwindow.o
obj-$(CONFIG_QT) += skinbezelitem.o
moc $< -o $@
$(obj)/moc_displayswwidget.cpp: $(obj)/displayswwidget.h
moc $< -o $@
-$(obj)/moc_displayswapper.cpp: $(obj)/displayswapper.h
- moc $< -o $@
$(obj)/moc_mainwindow.cpp: $(obj)/mainwindow.h
moc $< -o $@
$(obj)/moc_skinkeyitem.cpp: $(obj)/skinkeyitem.h
this->menu = menu;
this->dockPos = dockPos;
- setStyleSheet("border-style: none");
+ setStyleSheet("background: transparent; border-style: none");
QGraphicsScene *conScene = new QGraphicsScene(this);
- conScene->setBackgroundBrush(Qt::black);
+ conScene->setBackgroundBrush(Qt::transparent);
conView = new DockingConView(this, conForm, conScene);
conView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
this->conForm = conForm;
this->menu = menu;
- setStyleSheet("border-style: none");
+ setStyleSheet("background: transparent; border-style: none");
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
setWindowTitle(conForm->getName());
QGraphicsScene *conScene = new QGraphicsScene(this);
- conScene->setBackgroundBrush(Qt::black);
+ conScene->setBackgroundBrush(Qt::transparent);
conView = new FloatingConView(this, conForm, conScene);
conView->resize(conForm->skinImg[LayoutForm::normal].size());
void req_set_sensor_accel_angle(int angle);
}
-uint32_t qt5_window_width = 0;
-uint32_t qt5_window_height = 0;
-int qt5_window_angle = 0;
-
DisplayBase::DisplayBase(DisplayType *displayForm, QSize resolution, qreal scaleFactor,
QWidget *w) : resolution(resolution), widget(w)
{
maskImage.height() * scaleFactor).mask());
}
+ widget->update();
offGuide->show();
}
{
qDebug() << "display switch angle:" << displayForm->getAngle();
- qt5_window_angle = rotateAngle = displayForm->getAngle();
+ rotateAngle = displayForm->getAngle();
rect = displayForm->getRect();
maskImage = displayForm->getMask();
req_set_sensor_accel_angle(rotateAngle); /* update sensor */
updateGeometry();
- update();
- widget->repaint();
+ invalidateDisplay();
+ widget->update();
}
void DisplayBase::scaleForm(qreal scaleFactor)
updateGeometry();
- update();
- widget->repaint();
+ invalidateDisplay();
+ widget->update();
}
-void DisplayBase::update()
+void DisplayBase::invalidateDisplay()
{
qt5_graphic_hw_invalidate();
}
return widget->mask();
}
-void DisplayBase::handlePaint(QPaintEvent *event)
+void DisplayBase::handlePaint()
{
/* do nothing */
}
-void DisplayBase::handleResize(QResizeEvent *event)
+void DisplayBase::handleResize()
{
- qDebug() << "resize display:" << event->size();
-
- qt5_window_width = widget->width();
- qt5_window_height = widget->height();
+ qDebug() << "resize display:" << widget->size();
qt5_graphic_hw_invalidate();
SdbHelper *sdbHelper;
void switchForm(DisplayType *displayForm);
void scaleForm(qreal scaleFactor);
- void update();
+ void invalidateDisplay();
void updateGeometry();
QWidget *getWidget();
const QRect &getGeometry();
DisplayBase(DisplayType *displayForm, QSize resolution, qreal scaleFactor, QWidget *w);
virtual ~DisplayBase();
- void handlePaint(QPaintEvent *event);
- void handleResize(QResizeEvent *event);
+ void handlePaint();
+ void handleResize();
void handleMousePress(QMouseEvent *event);
void handleMouseRelease(QMouseEvent *event);
* Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
* GiWoong Kim <giwoong.kim@samsung.com>
* SeokYeon Hwang <syeon.hwang@samsung.com>
- * Sangho Park <sangho.p@samsung.com>
* Stanislav Vorobiov
*
* This program is free software; you can redistribute it and/or
*
*/
+#include <QtOpenGL>
+#include <QOpenGLShaderProgram>
#include "displayglwidget.h"
+#include "input/multitouchtracker.h"
extern "C" {
-#include "emul_state.h"
+extern uint32_t brightness_level;
+extern bool display_off;
+extern uint8_t brightness_tbl[];
};
-DisplayGLWidget::DisplayGLWidget(QWidget *parent, QGLContext *context,
+// number of coordinates that two triangles to make a rectangle
+#define COORD_COUNT (6)
+// coordinate is the point of two float
+#define COORDS_SIZE (2 * 4 * COORD_COUNT)
+// vertex coords + texture coords
+#define FULL_COORDS_SIZE (2 * COORDS_SIZE)
+
+// cast an uint to void pointer
+#define TO_VOIDP(x) ((const void *)((uintptr_t)(x)))
+
+static const char *vs_tex_source_gl2 =
+ "#version 120\n\n"
+ "attribute vec4 vertCoord;\n"
+ "uniform mat4 proj;\n"
+ "attribute vec2 texCoord;\n"
+ "varying vec2 v_texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " v_texCoord = texCoord;\n"
+ " gl_Position = proj * vertCoord;\n"
+ "}\n";
+
+static const char *vs_tex_source_gl3 =
+ "#version 140\n\n"
+ "in vec4 vertCoord;\n"
+ "uniform mat4 proj;\n"
+ "in vec2 texCoord;\n"
+ "out vec2 v_texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " v_texCoord = texCoord;\n"
+ " gl_Position = proj * vertCoord;\n"
+ "}\n";
+
+static const char *fs_dpy_source_gl2 =
+ "#version 120\n\n"
+ "uniform sampler2D tex;\n"
+ "uniform float brightness;\n"
+ "varying vec2 v_texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = texture2D(tex, v_texCoord) * brightness;\n"
+ "}\n";
+
+static const char *fs_dpy_source_gl3 =
+ "#version 140\n\n"
+ "uniform sampler2D tex;\n"
+ "uniform float brightness;\n"
+ "in vec2 v_texCoord;\n"
+ "out vec4 FragColor;\n"
+ "void main()\n"
+ "{\n"
+ " FragColor = texture(tex, v_texCoord) * brightness;\n"
+ "}\n";
+
+
+static const char *fs_scale_source_gl2 =
+"#version 120\n\
+\n\
+uniform sampler2D tex;\n\
+uniform float brightness;\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) / 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) * brightness;\n\
+}";
+
+static const char *fs_scale_source_gl3 =
+"#version 140\n\
+\n\
+uniform sampler2D tex;\n\
+uniform float brightness;\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 = texture(tex, vec2(offset.x, offset.z) *\n\
+texscale);\n\
+ vec4 sample1 = texture(tex, vec2(offset.y, offset.z) *\n\
+texscale);\n\
+ vec4 sample2 = texture(tex, vec2(offset.x, offset.w) *\n\
+texscale);\n\
+ vec4 sample3 = texture(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) * brightness;\n\
+}";
+
+DisplayGLWidget::DisplayGLWidget(QWidget *parent,
DisplayType *displayForm, QSize resolution, qreal scaleFactor) :
- QGLWidget(context, parent), DisplayBase(displayForm, resolution, scaleFactor, this)
+ QOpenGLWidget(parent), DisplayBase(displayForm, resolution, scaleFactor, this),
+ mGuestResolution(resolution)
{
- setAutoBufferSwap(false);
+ this->maskQImage = displayForm->getMask().toImage();
+ this->maskTexture = 0;
+ this->needScale = false;
+ this->dpyTexture = 0;
+ this->mtTexture = 0;
+ this->texProgram = NULL;
+ this->scaleProgram = NULL;
+
/* to be enable to drop events */
setAcceptDrops(true);
}
+void DisplayGLWidget::changedTexture(unsigned int id)
+{
+ if (dpyTexture != id) {
+ dpyTexture = id;
+ }
+ this->update();
+}
+
+float DisplayGLWidget::getBrightness()
+{
+ if (display_off) {
+ return 0.0f;
+ }
+ return ((float)(255 - brightness_tbl[brightness_level]) / 255.0f);
+}
+
+// TODO: if possible, simply clean up rendeing & init code
+void DisplayGLWidget::drawQuad(GLuint textureID, bool isMask)
+{
+ QOpenGLShaderProgram *program = needScale ? scaleProgram : texProgram;
+
+ mFuncs->glBindTexture(GL_TEXTURE_2D, textureID);
+
+ program->bind();
+ program->enableAttributeArray("vertCoord");
+ program->enableAttributeArray("texCoord");
+ int vertCoordLoc = program->attributeLocation("vertCoord");
+ int texCoordLoc = program->attributeLocation("texCoord");
+ program->setUniformValue("proj", mOrtho);
+ if (needScale) {
+ GLfloat texSize[2];
+ texSize[0] = (GLfloat)mGuestResolution.width();
+ texSize[1] = (GLfloat)mGuestResolution.height();
+ program->setUniformValueArray("texSize", texSize, 1, 2);
+ }
+ program->setUniformValue("brightness", isMask ? 1.0f : getBrightness());
+
+ mVBO->bind();
+ mVBO->write(0, mVertCoords, COORDS_SIZE);
+ mVBO->write(COORDS_SIZE, mTexCoords, COORDS_SIZE);
+ mFuncs->glVertexAttribPointer(vertCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ mFuncs->glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0,
+ TO_VOIDP(COORDS_SIZE));
+ mVBO->release();
+
+ mFuncs->glDrawArrays(GL_TRIANGLES, 0, COORD_COUNT);
+
+ program->disableAttributeArray("texCoord");
+ program->disableAttributeArray("vertCoord");
+
+ program->release();
+}
+
+void DisplayGLWidget::drawMultiTouchPoints()
+{
+ MultiTouchTracker *mtTracker = getTouchScreenHelper()->getMtTracker();
+ QList<TouchPoint *> pointList = mtTracker->getTouchPointList();
+
+ if (pointList.isEmpty()) {
+ return;
+ }
+
+ mVBO->bind();
+ if (mVBO->size() < pointList.count() * (int)FULL_COORDS_SIZE) {
+ mVBO->allocate(pointList.count() * FULL_COORDS_SIZE);
+ }
+
+ for (int i = 0; i < pointList.count(); i++) {
+ TouchPoint *p = pointList.at(i);
+ GLfloat vertCoords[12];
+ GLfloat x = p->getHostPos().x() - 32 / 2;
+ GLfloat y = height() - p->getHostPos().y() - 32 / 2;
+
+ vertCoords[6] = vertCoords[0] = x;
+ vertCoords[7] = vertCoords[1] = y;
+ vertCoords[2] = x + 32;
+ vertCoords[3] = y;
+ vertCoords[8] = vertCoords[4] = x + 32;
+ vertCoords[9] = vertCoords[5] = y + 32;
+ vertCoords[10] = x;
+ vertCoords[11] = y + 32;
+
+ mVBO->write(i * COORDS_SIZE, vertCoords, COORDS_SIZE);
+ mVBO->write(pointList.count() * COORDS_SIZE + i * COORDS_SIZE,
+ mTexCoords, COORDS_SIZE);
+ }
+
+ mFuncs->glBlendFunc(GL_SRC_COLOR, GL_ONE);
+ mFuncs->glBindTexture(GL_TEXTURE_2D, mtTexture);
+
+ texProgram->bind();
+ texProgram->enableAttributeArray("vertCoord");
+ texProgram->enableAttributeArray("texCoord");
+ int vertCoordLoc = texProgram->attributeLocation("vertCoord");
+ int texCoordLoc = texProgram->attributeLocation("texCoord");
+
+ QMatrix4x4 mat;
+ mat.ortho(0.0f, (float)width(),
+ 0.0f, (float)height(),
+ -1.0f, 1.0f);
+ texProgram->setUniformValue("proj", mat);
+ texProgram->setUniformValue("brightness", 0.7f);
+
+ mFuncs->glVertexAttribPointer(vertCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ mFuncs->glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0,
+ TO_VOIDP(pointList.count() * COORDS_SIZE));
+ mVBO->release();
+
+ mFuncs->glDrawArrays(GL_TRIANGLES, 0, pointList.count() * COORD_COUNT);
+
+ texProgram->disableAttributeArray("texCoord");
+ texProgram->disableAttributeArray("vertCoord");
+
+ texProgram->release();
+}
+
+
/* override */
void DisplayGLWidget::initializeGL()
{
qDebug("initialize GL");
+
+ mFuncs = QOpenGLContext::currentContext()->functions();
+
+ QOpenGLShader *vShader = new QOpenGLShader(QOpenGLShader::Vertex, this);
+ QOpenGLShader *dpyFgShader = new QOpenGLShader(QOpenGLShader::Fragment, this);
+ QOpenGLShader *scaleFgShader = new QOpenGLShader(QOpenGLShader::Fragment, this);
+ if (format().majorVersion() > 2) {
+ vShader->compileSourceCode(vs_tex_source_gl3);
+ dpyFgShader->compileSourceCode(fs_dpy_source_gl3);
+ scaleFgShader->compileSourceCode(fs_scale_source_gl3);
+ } else {
+ vShader->compileSourceCode(vs_tex_source_gl2);
+ dpyFgShader->compileSourceCode(fs_dpy_source_gl2);
+ scaleFgShader->compileSourceCode(fs_scale_source_gl2);
+ }
+
+ texProgram = new QOpenGLShaderProgram(this);
+ texProgram->addShader(vShader);
+ texProgram->addShader(dpyFgShader);
+ scaleProgram = new QOpenGLShaderProgram(this);
+ scaleProgram->addShader(vShader);
+ scaleProgram->addShader(scaleFgShader);
+
+ texProgram->link();
+ scaleProgram->link();
+
+ mVAO = new QOpenGLVertexArrayObject;
+ if (mVAO->create()) {
+ mVAO->bind();
+ }
+ mVBO = new QOpenGLBuffer;
+ mVBO->setUsagePattern(QOpenGLBuffer::StreamDraw);
+ mVBO->create();
+ mVBO->bind();
+ mVBO->allocate(FULL_COORDS_SIZE);
+ mVBO->release();
+
+ mVertCoords[6] = mVertCoords[0] = 0;
+ mVertCoords[7] = mVertCoords[1] = mGuestResolution.height();
+ mVertCoords[2] = mGuestResolution.width();
+ mVertCoords[3] = mGuestResolution.height();
+ mVertCoords[8] = mVertCoords[4] = mGuestResolution.width();
+ mVertCoords[9] = mVertCoords[5] = 0;
+ mVertCoords[10] = 0;
+ mVertCoords[11] = 0;
+
+ mTexCoords[6] = mTexCoords[0] = 0;
+ mTexCoords[7] = mTexCoords[1] = 0;
+ mTexCoords[2] = 1;
+ mTexCoords[3] = 0;
+ mTexCoords[8] = mTexCoords[4] = 1;
+ mTexCoords[9] = mTexCoords[5] = 1;
+ mTexCoords[10] = 0;
+ mTexCoords[11] = 1;
+
+ GLuint curTexture = 0;
+ mFuncs->glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&curTexture);
+
+ const QImage img = getTouchScreenHelper()->getMtTracker()->getPointImage();
+ mFuncs->glGenTextures(1, &mtTexture);
+ mFuncs->glBindTexture(GL_TEXTURE_2D, mtTexture);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ mFuncs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ (const void *)img.constBits());
+ mFuncs->glBindTexture(GL_TEXTURE_2D, curTexture);
+
+ if (!maskQImage.isNull()) {
+ mFuncs->glGenTextures(1, &maskTexture);
+ mFuncs->glBindTexture(GL_TEXTURE_2D, maskTexture);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ mFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ mFuncs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
+ maskQImage.width(), maskQImage.height(),
+ 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ (const void *)maskQImage.constBits());
+ mFuncs->glBindTexture(GL_TEXTURE_2D, curTexture);
+ }
}
/* override */
-void DisplayGLWidget::dragEnterEvent(QDragEnterEvent *event)
+void DisplayGLWidget::paintGL()
{
- handleDragEnterEvent(event);
+ mFuncs->glDisable(GL_DEPTH_TEST);
+ mFuncs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ mFuncs->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ mFuncs->glEnable(GL_BLEND);
+
+ if (maskTexture) {
+ mFuncs->glBlendFuncSeparate(GL_ONE, GL_ZERO,
+ GL_SRC_ALPHA, GL_ZERO);
+ drawQuad(maskTexture, true);
+ }
+ mFuncs->glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ mOrtho.setToIdentity();
+ mOrtho.rotate((float)-rotateAngle, 0.0f, 0.0f, 1.0f);
+ mOrtho.ortho(0.0f, (float)mGuestResolution.width(),
+ 0.0f, (float)mGuestResolution.height(),
+ -1.0f, 1.0f);
+ needScale = (mGuestResolution.width() != width())
+ || (mGuestResolution.height() != height());
+
+ drawQuad(dpyTexture, false);
+ if (isTsEnabled) {
+ drawMultiTouchPoints();
+ }
+
+ mFuncs->glDisable(GL_BLEND);
+ mFuncs->glFinish();
}
/* override */
-void DisplayGLWidget::dropEvent(QDropEvent *event)
+void DisplayGLWidget::resizeGL(int w, int h)
{
- handleDropEvent(event);
+ qDebug("resizeGL");
+ handleResize();
+
+ // TODO: check changing of the guest resolution
+ // for 'Runtime Resolution Change'
}
/* override */
-void DisplayGLWidget::paintEvent(QPaintEvent *event)
+void DisplayGLWidget::dragEnterEvent(QDragEnterEvent *event)
{
- /*
- * We offload rendering to separate thread, this must be
- * a no-op, see: http://qt-project.org/doc/qt-5/QGLWidget.html:
- * "3. Using QPainter to draw into a QGLWidget in a thread"
- */
-
- handlePaint(event);
+ handleDragEnterEvent(event);
}
/* override */
-void DisplayGLWidget::resizeEvent(QResizeEvent *event)
+void DisplayGLWidget::dropEvent(QDropEvent *event)
{
- /*
- * We offload rendering to separate thread, this must be
- * a no-op, see: http://qt-project.org/doc/qt-5/QGLWidget.html:
- * "3. Using QPainter to draw into a QGLWidget in a thread"
- */
-
- handleResize(event);
+ handleDropEvent(event);
}
/* override */
}
}
+// TODO: To correct releasing resources
DisplayGLWidget::~DisplayGLWidget()
{
- /* do nothing */
+ makeCurrent();
+ if (mtTexture) {
+ mFuncs->glDeleteTextures(1, &mtTexture);
+ }
+ if (maskTexture) {
+ mFuncs->glDeleteTextures(1, &maskTexture);
+ }
+ mVAO->destroy();
+ mVBO->destroy();
+ texProgram->removeAllShaders();
+ scaleProgram->removeAllShaders();
+ delete mVAO;
+ delete mVBO;
+ delete texProgram;
+ delete scaleProgram;
+ doneCurrent();
}
* Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
* GiWoong Kim <giwoong.kim@samsung.com>
* SeokYeon Hwang <syeon.hwang@samsung.com>
- * Sangho Park <sangho.p@samsung.com>
* Stanislav Vorobiov
*
* This program is free software; you can redistribute it and/or
#ifndef DISPLAYGLWIDGET_H
#define DISPLAYGLWIDGET_H
-#include <QGLWidget>
#include "displaybase.h"
+#include <QOpenGLWidget>
+#include <QMatrix4x4>
-class DisplayGLWidget : public QGLWidget,
+class QOpenGLFunctions;
+class QOpenGLShaderProgram;
+class QOpenGLVertexArrayObject;
+class QOpenGLBuffer;
+
+class DisplayGLWidget : public QOpenGLWidget,
public DisplayBase
{
Q_OBJECT
public:
- DisplayGLWidget(QWidget *parent, QGLContext *context,
- DisplayType *displayForm, QSize resolution, qreal scaleFactor);
+ DisplayGLWidget(QWidget *parent,
+ DisplayType *displayForm,
+ QSize resolution, qreal scaleFactor);
~DisplayGLWidget();
+ void changedTexture(unsigned int texture);
+
protected:
void initializeGL();
-
- void paintEvent(QPaintEvent *event);
- void resizeEvent(QResizeEvent *event);
+ void paintGL();
+ void resizeGL(int w, int h);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
+
+private:
+ float getBrightness();
+ void drawQuad(GLuint texture, bool isMask);
+ void drawMultiTouchPoints();
+
+ QSize mGuestResolution;
+ QOpenGLFunctions *mFuncs;
+
+ bool needScale;
+ QImage maskQImage;
+ GLuint maskTexture;
+
+ GLuint dpyTexture;
+ GLuint mtTexture;
+ QMatrix4x4 mOrtho;
+ GLfloat mVertCoords[12];
+ GLfloat mTexCoords[12];
+
+ QOpenGLVertexArrayObject *mVAO;
+ QOpenGLBuffer *mVBO;
+ QOpenGLShaderProgram *texProgram;
+ QOpenGLShaderProgram *scaleProgram;
};
#endif // DISPLAYGLWIDGET_H
+++ /dev/null
-/*
- * Qt UI
- *
- * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * GiWoong Kim <giwoong.kim@samsung.com>
- * Sangho Park <sangho1206.park@samsung.com>
- * Stanislav Vorobiov
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#include "displayswapper.h"
-
-extern "C" {
-int qt5_graphic_hw_display(void);
-}
-
-DisplaySwapper::DisplaySwapper(QGLContext* context, QObject* parent) :
- QObject(parent), context(context), terminating(false)
-{
- /* do nothing */
-}
-
-void DisplaySwapper::display()
-{
- if (context) {
- while (!terminating) {
- context->makeCurrent();
- if (qt5_graphic_hw_display()) {
- context->swapBuffers();
- }
- context->doneCurrent();
- }
- } else {
- while (!terminating) {
- qt5_graphic_hw_display();
- }
- }
-
- qDebug("DisplaySwapper::display() terminated");
-
- emit displayFinished();
-}
+++ /dev/null
-/*
- * Qt UI
- *
- * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * GiWoong Kim <giwoong.kim@samsung.com>
- * Sangho Park <sangho1206.park@samsung.com>
- * Stanislav Vorobiov
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#ifndef DISPLAYSWAPPER_H
-#define DISPLAYSWAPPER_H
-
-#include <QWidget>
-#include <QGLContext>
-
-class DisplaySwapper : public QObject
-{
- Q_OBJECT
-
-public:
- DisplaySwapper(QGLContext* context, QObject* parent = 0);
-
- inline void setTerminating() { terminating = true; }
-
-public slots:
- void display();
-
-signals:
- void displayFinished();
-
-private:
- QGLContext *context;
- bool terminating;
-};
-
-#endif // DISPLAYSWAPPER_H
void DisplaySWWidget::paintEvent(QPaintEvent *event)
{
QLabel::paintEvent(event);
- handlePaint(event);
+ handlePaint();
if (isTsEnabled == true) {
/* draw multi-touch points */
void DisplaySWWidget::resizeEvent(QResizeEvent *event)
{
QLabel::resizeEvent(event);
- handleResize(event);
+ handleResize();
repaint();
}
#include "multitouchtracker.h"
#include "displaybase.h"
-float *qt5_mt_points = 0;
-int qt5_mt_count = 0;
-const void *qt5_mt_pixels = 0;
-int qt5_mt_width = 0;
-int qt5_mt_height = 0;
-
extern "C" {
bool virtio_touchscreen_ready(void);
void virtio_touchscreen_event(int x, int y, int z, int buttons_state);
this->hostPos = hostPos;
this->guestPos = guestPos;
- qt5_mt_points[2 * (this->id - 1) + 0] = hostPos.x();
- qt5_mt_points[2 * (this->id - 1) + 1] = hostPos.y();
qt5_graphic_hw_invalidate();
}
painter.setBrush(QBrush(QColor(128, 128, 128, 128)));
painter.setRenderHint(QPainter::Antialiasing, true);
painter.drawEllipse(1, 1, 30, 30);
-
- qt5_mt_points = new float[2 * maxTouchPoint]();
- qt5_mt_count = 0;
- qt5_mt_pixels = touchPointImage.constBits();
- qt5_mt_width = qt5_mt_height = 32;
}
int MultiTouchTracker::getPointRadius()
touchPointList.append(point);
qDebug() << "ID" << point->getID() << "point touching" << hostPos << guestPos;
- qt5_mt_points[2 * qt5_mt_count + 0] = hostPos.x();
- qt5_mt_points[2 * qt5_mt_count + 1] = hostPos.y();
- qt5_mt_count++;
qt5_graphic_hw_invalidate();
return touchPointList.count();
delete point;
}
touchPointList.removeLast();
-
- qt5_mt_count--;
}
diff = beforeCnt - touchPointList.count();
}
touchPointList.clear();
- qt5_mt_count = 0;
qt5_graphic_hw_invalidate();
}
qDebug("destroy multi-touch tracker");
finishTracking();
-
- delete[] qt5_mt_points;
- qt5_mt_points = 0;
- qt5_mt_count = 0;
- qt5_mt_pixels = 0;
- qt5_mt_width = qt5_mt_height = 0;
}
void qemu_system_graceful_shutdown_request(unsigned int sec);
}
-QOpenGLContext *qt5GLContext = NULL;
-QSurfaceFormat qt5GLFormat;
-
-MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) :
+MainWindow::MainWindow(UiInformation *uiInfo, bool useGL, QWidget *parent) :
QWidget(parent)
{
/* initialize */
this->display = NULL;
this->rotary = NULL;
- this->swapper = NULL;
- this->swapperThread = NULL;
this->screenWidget = NULL;
this->captureRequestHandler = NULL;
setWindowIcon(QIcon(":/icons/emulator_icon.ico"));
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowCloseButtonHint);
setMinimumSize(0, 0);
+ setAttribute(Qt::WA_TranslucentBackground, true);
/* scene */
mainScene = new QGraphicsScene(this);
- mainScene->setBackgroundBrush(Qt::black);
+ mainScene->setBackgroundBrush(Qt::transparent);
/* view */
mainView = new MainView(mainScene, this);
/* display */
updateDisplayTransform();
- display = createDisplay(uiInfo->getMainFormDpyType());
+ createDisplay(useGL);
/* set HW Key shortcut */
keyboardShortcut = new KeyboardShortcut(this);
SLOT(slotContextMenu(const QPoint&)));
}
-DisplayBase *MainWindow::createDisplay(DisplayType *displayForm)
+void MainWindow::createDisplay(bool useGL)
{
qDebug("create a display");
- DisplayBase *displayWidget = NULL;
-
- if (qt5GLContext) { /* on-screen rendering */
- QGLContext *wrapperContext =
- QGLContext::fromOpenGLContext(qt5GLContext);
-
- /*
- * Qt5 bug, wrapperContext->requestedFormat() doesn't return
- * originating format, it returns actual format, this may result
- * in wrong OpenGL context version here.
- */
-
- QGLFormat format = QGLFormat::fromSurfaceFormat(qt5GLFormat);
-
- /*
- * Qt5 bug, format set here doesn't always have effect, must
- * set it after QGLWidget is created.
- */
- QGLContext *context = new QGLContext(format);
-
- displayWidget = new DisplayGLWidget(this, context,
- displayForm, uiInfo->getResolution(), getUiState()->getScaleFactor());
-
- context->setFormat(format);
- context->create(wrapperContext);
-
- /* display swapper */
- swapperThread = new QThread(this);
-
- context->doneCurrent();
- context->moveToThread(swapperThread);
-
- swapper = new DisplaySwapper(context);
- swapper->moveToThread(swapperThread);
-
- connect(swapper, SIGNAL(displayFinished()),
- swapperThread, SLOT(quit()), Qt::DirectConnection);
- connect(swapperThread, SIGNAL(finished()), swapper, SLOT(deleteLater()));
- connect(swapperThread, SIGNAL(finished()), swapperThread, SLOT(deleteLater()));
-
- swapperThread->start();
+ if (useGL) { /* on-screen rendering */
+ this->display = new DisplayGLWidget(this,
+ uiInfo->getMainFormDpyType(), uiInfo->getResolution(), getUiState()->getScaleFactor());
} else { /* off-screen rendering */
DisplaySWWidget *widget = new DisplaySWWidget(this,
- displayForm, uiInfo->getResolution(), getUiState()->getScaleFactor());
+ uiInfo->getMainFormDpyType(), uiInfo->getResolution(), getUiState()->getScaleFactor());
- screenWidget = widget;
- displayWidget = widget;
+ this->screenWidget = widget;
+ this->display = widget;
}
-
- return displayWidget;
}
RotaryView *MainWindow::createRotary()
return new RotaryView(this);
}
-void MainWindow::startDisplaySwapper()
-{
- if (swapper != NULL) {
- QMetaObject::invokeMethod(swapper, "display", Qt::QueuedConnection);
- }
-}
-
-void MainWindow::terminateDisplaySwapper()
-{
- if (swapper != NULL) {
- swapper->setTerminating();
- qt5_graphic_hw_update();
- }
-}
-
QLabel *MainWindow::getScreenWidget()
{
return screenWidget;
/* Some part of QGLWidget's surface might be lost on Windows when view changing.
* So, we need an additional updating for display. */
- display->update();
+ display->invalidateDisplay();
#ifdef CONFIG_LINUX
popupMenu->slotOnTop(getUiState()->isOnTop());
/* Some part of QGLWidget's surface might be lost on Windows when view changing.
* So, we need an additional updating for display. */
- display->update();
+ display->invalidateDisplay();
}
/* override */
if (captured) {
qDebug("save captured image: %p", pixels);
+
// pixels's format is ARGB32
QImage image =
QImage((uchar *)pixels, width, height, QImage::Format_ARGB32);
isMovingMode = false;
}
+void MainWindow::updateTexture(unsigned int texture)
+{
+ ((DisplayGLWidget *)getDisplay())->changedTexture(texture);
+}
+
/* override */
void MainWindow::closeEvent(QCloseEvent *event)
{
#define MAINWINDOW_H
#include <QWidget>
-#include <QGLContext>
#include "menu/contextmenu.h"
#include "mainview.h"
#include "displaybase.h"
-#include "displayswapper.h"
#include "rotaryview.h"
#include "uiinformation.h"
#include "controller/dockingcontroller.h"
public:
bool isMovingMode;
- explicit MainWindow(UiInformation *uiInfo, QWidget *parent = 0);
+ explicit MainWindow(UiInformation *uiInfo,
+ bool useGL,
+ QWidget *parent = 0);
~MainWindow();
UiInformation *getUiInfo(void);
FloatingController *getFloatingCon();
void openController(int index, int dockPos);
void closeController();
- void startDisplaySwapper();
- void terminateDisplaySwapper();
void turnOnMovingMode();
void turnOffMovingMode();
+ void updateTexture(unsigned int texture);
+
public slots:
void slotContextMenu(const QPoint &pos);
QLabel *screenWidget;
private:
- DisplayBase *createDisplay(DisplayType *displayForm);
+ void createDisplay(bool useGL);
RotaryView *createRotary();
UiInformation *uiInfo;
RotaryView *rotary;
ContextMenu *popupMenu;
- QThread *swapperThread;
- DisplaySwapper *swapper;
KeyboardShortcut *keyboardShortcut;
MovingWidget *movingWidget;
*/
#include <QApplication>
+#include <QOpenGLContext>
#include "qt5_supplement.h"
#include "propertykeyword.h"
//using namespace std;
bool qt5IsOnscreen;
QApplication *qt5App = NULL;
+QOpenGLContext *qt5GLContext;
bool isForceLegacy;
static int argc = 0;
/* GUI */
qDebug("start!");
- mainwindow = new MainWindow(uiInfo);
+ mainwindow = new MainWindow(uiInfo, qt5IsOnscreen);
mainwindow->setCaptureRequestHandler(captureRequestListener, captureRequestHandler);
/* position */
mainwindow->getMainView()->resize(viewSize / 2);
mainwindow->getMainView()->resize(viewSize);
#endif
-
- mainwindow->startDisplaySwapper();
}
void qt5_destroy()
{
qDebug("qt5 destroy");
- mainwindow->terminateDisplaySwapper();
-
/* write most recently used data information */
QString mruPath(
uiInfo->getVmDataPath() + QDir::separator() + GUI_PROPERTIES_FILE);
Q_INIT_RESOURCE(resource);
+ if (qt5IsOnscreen) {
+ QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
+ QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
+
+ QSurfaceFormat sfcFormat;
+ sfcFormat.setRedBufferSize(8);
+ sfcFormat.setGreenBufferSize(8);
+ sfcFormat.setBlueBufferSize(8);
+ sfcFormat.setAlphaBufferSize(8);
+ sfcFormat.setDepthBufferSize(24);
+ sfcFormat.setStencilBufferSize(8);
+#ifdef CONFIG_DARWIN
+ // The default OpenGL version for QSurfaceFormat is 2.0.
+ if (!isForceLegacy) {
+ sfcFormat.setMajorVersion(3);
+ sfcFormat.setMinorVersion(2);
+ sfcFormat.setProfile(QSurfaceFormat::CoreProfile);
+ }
+#else
+ sfcFormat.setMajorVersion(3);
+ sfcFormat.setMinorVersion(1);
+#endif
+ QSurfaceFormat::setDefaultFormat(sfcFormat);
+ }
+
qt5App = new QApplication(argc, argv);
/* add the path in the application's main() function, right after the
eventFilter = new EventFilter();
qt5App->installNativeEventFilter(eventFilter);
#endif
+ if (qt5IsOnscreen) {
+ qt5GLContext = QOpenGLContext::globalShareContext();
+ }
}
void qt5_prepare(void)
mainwindow->processCaptured(captured, pixels, width, height);
}
}
+
+void qt5_update_texture(unsigned int tex_id)
+{
+ if (mainwindow) {
+ mainwindow->updateTexture(tex_id);
+ }
+}
this->grabPos = SKINVIEW_NULLITY_POSITION;
/* note: do not call setStyleSheet() separately for each style */
- setStyleSheet("QGraphicsView { border-style: none; }" +
+ setStyleSheet("QGraphicsView { background: transparent; border-style: none; }" +
QString(STYLE_TOOLTIP));
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
nextopt = endptr;
} else if (strstart(opts, ",forcelegacy", &nextopt)) {
opts = nextopt;
- //maru_qt5_set_force_legacy(true);
+ maru_qt5_set_force_legacy(true);
} else {
invalid_maru_qt_args:
error_report(FAILED_TO_DISPLAY_PARSING);