From 48742b9a80528a51d01462f6d2c57c0c5ef1b069 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Wed, 31 Aug 2016 17:30:50 +0900 Subject: monitor: avoid clang shifting negative signed warning clang 3.7.0 on x86_64 warns about the following: target-i386/monitor.c:38:22: warning: shifting a negative signed value is undefined [-Wshift-negative-value] addr |= -1LL << 48; ~~~~ ^ Change-Id: I0885a0fbadc0273b09e58ef756fea34208ca7230 Signed-off-by: Stefan Hajnoczi Signed-off-by: Jinhyung Jo --- target-i386/monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/monitor.c b/target-i386/monitor.c index fccfe40ab7..1f0e46cb7e 100644 --- a/target-i386/monitor.c +++ b/target-i386/monitor.c @@ -36,7 +36,7 @@ static void print_pte(Monitor *mon, hwaddr addr, { #ifdef TARGET_X86_64 if (addr & (1ULL << 47)) { - addr |= -1LL << 48; + addr |= ~0ULL << 48; } #endif monitor_printf(mon, TARGET_FMT_plx ": " TARGET_FMT_plx -- cgit v1.2.3 From fc7b6a78204b506068da09a2fba5b04b62cfcac5 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Mon, 5 Sep 2016 18:52:34 +0900 Subject: tablet: fix unexpected termination issue 'Null Pointer Dereference' occurs, the emulator dies unexpectedly. It is caused by commit f998ca30b51b5c549898763d4bd5041380a60416. The committer have made a mistake when applying the virtio API modification. The virtio API has been changed as follows: previous: int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) current: void *virtqueue_pop(VirtQueue *vq, size_t sz) Change-Id: I2c5a20c2741633f855ab0128f7e4dd989404b2b2 Signed-off-by: Jinhyung Jo --- tizen/src/hw/virtio/maru_virtio_tablet.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tizen/src/hw/virtio/maru_virtio_tablet.c b/tizen/src/hw/virtio/maru_virtio_tablet.c index 9a564ba502..5bab39cc95 100644 --- a/tizen/src/hw/virtio/maru_virtio_tablet.c +++ b/tizen/src/hw/virtio/maru_virtio_tablet.c @@ -148,9 +148,7 @@ static void maru_tablet_bh(void *opaque) qemu_mutex_unlock(&vt->mutex); /* Get a queue buffer which is written by guest side. */ - do { - elem = virtqueue_pop(vt->vq, sizeof(VirtQueueElement)); - } while (elem); + elem = virtqueue_pop(vt->vq, sizeof(VirtQueueElement)); qemu_mutex_lock(&vt->mutex); while (!QTAILQ_EMPTY(&events_queue)) { @@ -160,10 +158,10 @@ static void maru_tablet_bh(void *opaque) /* copy event into virtio buffer */ len = iov_from_buf(elem->in_sg, elem->in_num, push_len, &(event_entry->tablet), sizeof(EmulTabletEvent)); - if(len != sizeof(EmulTabletEvent)) { + if (len != sizeof(EmulTabletEvent)) { LOG_WARNING("len != sizeof(EmulTabletEvent).\n"); LOG_WARNING("len: %zu, sizeof(EmulTabletEvent): %zu\n", - len, sizeof(EmulTabletEvent)); + len, sizeof(EmulTabletEvent)); } push_len += sizeof(EmulTabletEvent); -- cgit v1.2.3 From 99ffcba1997dade13316bd09023f93597db0f2df Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Wed, 22 Jun 2016 19:32:42 +0900 Subject: display: move display functionality to Qt5 GUI Qt5 GUI paints final display with all processing, not in VIGS. The followings are in this commit. - VIGS: remove the code about display rendering - VIGS: modify the code about onscreen rendering server - VIGS: add functions to delivery the texture id to Qt5 UI - Qt5 UI: change the deprecated classes to the new classes - Qt5 UI: add OpenGL rendering functionality - Qt5 UI: fix the transparent issue with OpenGL - Qt5 UI: bug fix caused by image formats - etc. : minor modifications Change-Id: I39471237b5d526751fac95e9fe88f05f6939142c Signed-off-by: Jinhyung Jo --- hw/vigs/vigs_gl_backend.c | 576 +------------------------ hw/vigs/vigs_gl_backend.h | 32 -- hw/vigs/vigs_gl_backend_cgl.c | 10 +- hw/vigs/vigs_gl_backend_glx.c | 75 ++-- hw/vigs/vigs_gl_backend_wgl.c | 9 +- hw/vigs/vigs_onscreen_server.c | 92 ++-- hw/vigs/vigs_onscreen_server.h | 6 +- hw/vigs/vigs_qt5.cpp | 96 ++--- hw/vigs/vigs_qt5.h | 4 +- hw/vigs/vigs_qt5_stub.c | 19 +- tizen/src/ui/Makefile.objs | 3 - tizen/src/ui/controller/dockingcontroller.cpp | 4 +- tizen/src/ui/controller/floatingcontroller.cpp | 4 +- tizen/src/ui/displaybase.cpp | 26 +- tizen/src/ui/displaybase.h | 6 +- tizen/src/ui/displayglwidget.cpp | 462 ++++++++++++++++++-- tizen/src/ui/displayglwidget.h | 47 +- tizen/src/ui/displayswapper.cpp | 62 --- tizen/src/ui/displayswapper.h | 57 --- tizen/src/ui/displayswwidget.cpp | 4 +- tizen/src/ui/input/multitouchtracker.cpp | 25 -- tizen/src/ui/mainwindow.cpp | 100 ++--- tizen/src/ui/mainwindow.h | 14 +- tizen/src/ui/menu/screenshotdialog.cpp | 14 +- tizen/src/ui/qt5_supplement.cpp | 39 +- tizen/src/ui/skinview.cpp | 2 +- 26 files changed, 695 insertions(+), 1093 deletions(-) delete mode 100644 tizen/src/ui/displayswapper.cpp delete mode 100644 tizen/src/ui/displayswapper.h diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c index 7fcd2c092f..9995d1c15a 100644 --- a/hw/vigs/vigs_gl_backend.c +++ b/hw/vigs/vigs_gl_backend.c @@ -36,20 +36,8 @@ #include "vigs_ref.h" #include "vigs_qt5.h" #include "winsys_gl.h" -#include "hw/pci/maru_brightness.h" #include -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 @@ -201,136 +189,6 @@ static const char *g_fs_color_source_gl3 = " 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" @@ -742,102 +600,6 @@ static void vigs_gl_draw_color_prog(struct vigs_gl_backend *backend, 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) { @@ -894,28 +656,6 @@ static void vigs_gl_create_ortho(GLfloat left, GLfloat right, 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]) @@ -1026,8 +766,7 @@ static bool vigs_gl_surface_setup_framebuffer(struct vigs_gl_surface *gl_sfc, } 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; @@ -1065,9 +804,6 @@ static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend, 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; @@ -2235,8 +1971,7 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface, 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; } @@ -2441,219 +2176,34 @@ static bool vigs_gl_backend_display(struct vigs_backend *backend, 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->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb); } - 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); - } - - 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; } } @@ -2823,9 +2373,7 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) 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; } @@ -2844,65 +2392,6 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) 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); @@ -2918,8 +2407,6 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) 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; @@ -2932,27 +2419,12 @@ fail: 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); } - 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); + if (gl_backend->dpy_fb) { + gl_backend->DeleteFramebuffers(1, &gl_backend->dpy_fb); + } gl_backend->DeleteBuffers(1, &gl_backend->vbo); gl_backend->DetachShader(gl_backend->yuv420_prog_id, gl_backend->yuv420_prog_vs_id); @@ -2993,8 +2465,6 @@ void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend) 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); } diff --git a/hw/vigs/vigs_gl_backend.h b/hw/vigs/vigs_gl_backend.h index dca456b06c..ca2d3658ab 100644 --- a/hw/vigs/vigs_gl_backend.h +++ b/hw/vigs/vigs_gl_backend.h @@ -220,43 +220,11 @@ struct vigs_gl_backend * 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; - /* * @} */ diff --git a/hw/vigs/vigs_gl_backend_cgl.c b/hw/vigs/vigs_gl_backend_cgl.c index 7a41d0a8ab..cc0eabe2e5 100644 --- a/hw/vigs/vigs_gl_backend_cgl.c +++ b/hw/vigs/vigs_gl_backend_cgl.c @@ -62,7 +62,7 @@ static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] = kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFAPBuffer, + kCGLPFAOpenGLProfile, kCGLOGLPVersion_Legacy, 0 }; @@ -255,7 +255,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, CGLError error; CGLPixelFormatObj pixel_format; int n; - CGLContextObj qt5_ctx = NULL; + CGLContextObj share_ctx = NULL; gl_backend_cgl = g_malloc0(sizeof(*gl_backend_cgl)); @@ -378,15 +378,15 @@ struct vigs_backend *vigs_gl_backend_create(void *display, } 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; } diff --git a/hw/vigs/vigs_gl_backend_glx.c b/hw/vigs/vigs_gl_backend_glx.c index 4014a832e3..8212b88dbb 100644 --- a/hw/vigs/vigs_gl_backend_glx.c +++ b/hw/vigs/vigs_gl_backend_glx.c @@ -238,7 +238,7 @@ static GLXFBConfig vigs_gl_backend_glx_get_config(struct vigs_gl_backend_glx *gl }; 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"); @@ -417,7 +417,7 @@ static void vigs_gl_backend_glx_destroy(struct vigs_backend *backend) 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); } @@ -443,6 +443,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, { 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)); @@ -574,57 +575,35 @@ struct vigs_backend *vigs_gl_backend_create(void *display, } 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, @@ -655,7 +634,7 @@ fail2: 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); } diff --git a/hw/vigs/vigs_gl_backend_wgl.c b/hw/vigs/vigs_gl_backend_wgl.c index b5b45bcef0..9db01a0a7e 100644 --- a/hw/vigs/vigs_gl_backend_wgl.c +++ b/hw/vigs/vigs_gl_backend_wgl.c @@ -482,7 +482,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, }; 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; @@ -687,9 +687,8 @@ struct vigs_backend *vigs_gl_backend_create(void *display, 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; } } @@ -729,7 +728,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, } if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl, - qt5_ctx, + share_ctx, &gl_backend_wgl->ctx)) { goto fail; } diff --git a/hw/vigs/vigs_onscreen_server.c b/hw/vigs/vigs_onscreen_server.c index 7fcc352b33..d6830783cd 100644 --- a/hw/vigs/vigs_onscreen_server.c +++ b/hw/vigs/vigs_onscreen_server.c @@ -32,6 +32,24 @@ #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) @@ -52,10 +70,6 @@ static bool vigs_onscreen_server_begin_update(struct vigs_server *server, goto out; } - onscreen_server->updated = false; - onscreen_server->composited = false; - onscreen_server->dirty = false; - out: qemu_mutex_unlock(&onscreen_server->mutex); @@ -65,23 +79,6 @@ out: static void vigs_onscreen_server_finish_update(struct vigs_server *server, bool composited, bool dirty) -{ - 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; @@ -89,52 +86,33 @@ static bool vigs_onscreen_server_display(struct vigs_server *server, 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; } @@ -150,7 +128,6 @@ static void vigs_onscreen_server_destroy(struct vigs_server *server) 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); @@ -178,7 +155,8 @@ struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr, } 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; diff --git a/hw/vigs/vigs_onscreen_server.h b/hw/vigs/vigs_onscreen_server.h index b0ea1e93d7..19d083e49c 100644 --- a/hw/vigs/vigs_onscreen_server.h +++ b/hw/vigs/vigs_onscreen_server.h @@ -37,12 +37,8 @@ struct vigs_onscreen_server 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, diff --git a/hw/vigs/vigs_qt5.cpp b/hw/vigs/vigs_qt5.cpp index 927d558320..286014eff7 100644 --- a/hw/vigs/vigs_qt5.cpp +++ b/hw/vigs/vigs_qt5.cpp @@ -27,27 +27,26 @@ * */ -#include "vigs_qt5.h" -#include "config-host.h" +#include #include #include #include -#include +#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; } @@ -67,7 +66,7 @@ void *vigs_qt5_display(void) 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"); @@ -75,79 +74,27 @@ void *vigs_qt5_gl_context_create(bool is_gl2) } 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, @@ -166,3 +113,8 @@ void vigs_qt5_process_captured(bool captured, void *pixels, { qt5_process_captured(captured, pixels, width, height); } + +void vigs_qt5_dpy_render_texture(uint32_t tex_id) +{ + qt5_update_texture(tex_id); +} diff --git a/hw/vigs/vigs_qt5.h b/hw/vigs/vigs_qt5.h index b88c84ebf8..a27ae6184b 100644 --- a/hw/vigs/vigs_qt5.h +++ b/hw/vigs/vigs_qt5.h @@ -38,14 +38,14 @@ bool vigs_qt5_onscreen_enabled(void); 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 diff --git a/hw/vigs/vigs_qt5_stub.c b/hw/vigs/vigs_qt5_stub.c index 9b3c80729b..cf490f323c 100644 --- a/hw/vigs/vigs_qt5_stub.c +++ b/hw/vigs/vigs_qt5_stub.c @@ -34,17 +34,6 @@ #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; @@ -55,7 +44,7 @@ void *vigs_qt5_display(void) return NULL; } -void *vigs_qt5_gl_context_create(bool is_gl2) +void *vigs_qt5_gl_context_get(void) { return NULL; } @@ -76,3 +65,9 @@ void vigs_qt5_process_captured(bool captured, void *pixels, { return; } + +void vigs_qt5_dpy_render_texture(uint32_t tex_id) +{ + return; +} + diff --git a/tizen/src/ui/Makefile.objs b/tizen/src/ui/Makefile.objs index b18942f2a1..76ddc8469c 100644 --- a/tizen/src/ui/Makefile.objs +++ b/tizen/src/ui/Makefile.objs @@ -11,7 +11,6 @@ $(obj)/qrc_resource.cpp: $(TIZEN_UI)/resource/resource.qrc 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 @@ -34,8 +33,6 @@ $(obj)/moc_displayglwidget.cpp: $(obj)/displayglwidget.h 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 diff --git a/tizen/src/ui/controller/dockingcontroller.cpp b/tizen/src/ui/controller/dockingcontroller.cpp index ec6030a5e6..51d4daf0f5 100644 --- a/tizen/src/ui/controller/dockingcontroller.cpp +++ b/tizen/src/ui/controller/dockingcontroller.cpp @@ -38,10 +38,10 @@ DockingController::DockingController(ControllerForm *conForm, 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); diff --git a/tizen/src/ui/controller/floatingcontroller.cpp b/tizen/src/ui/controller/floatingcontroller.cpp index 0d6eab0bd5..1f807d85eb 100644 --- a/tizen/src/ui/controller/floatingcontroller.cpp +++ b/tizen/src/ui/controller/floatingcontroller.cpp @@ -36,12 +36,12 @@ FloatingController::FloatingController(ControllerForm *conForm, 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()); diff --git a/tizen/src/ui/displaybase.cpp b/tizen/src/ui/displaybase.cpp index e35b7653e5..92f702e76c 100644 --- a/tizen/src/ui/displaybase.cpp +++ b/tizen/src/ui/displaybase.cpp @@ -41,10 +41,6 @@ void qt5_graphic_hw_invalidate(void); 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) { @@ -127,6 +123,7 @@ void DisplayBase::showOffGuideImg() maskImage.height() * scaleFactor).mask()); } + widget->update(); offGuide->show(); } @@ -149,7 +146,7 @@ void DisplayBase::switchForm(DisplayType *displayForm) { qDebug() << "display switch angle:" << displayForm->getAngle(); - qt5_window_angle = rotateAngle = displayForm->getAngle(); + rotateAngle = displayForm->getAngle(); rect = displayForm->getRect(); maskImage = displayForm->getMask(); @@ -157,8 +154,8 @@ void DisplayBase::switchForm(DisplayType *displayForm) req_set_sensor_accel_angle(rotateAngle); /* update sensor */ updateGeometry(); - update(); - widget->repaint(); + invalidateDisplay(); + widget->update(); } void DisplayBase::scaleForm(qreal scaleFactor) @@ -169,11 +166,11 @@ void DisplayBase::scaleForm(qreal scaleFactor) updateGeometry(); - update(); - widget->repaint(); + invalidateDisplay(); + widget->update(); } -void DisplayBase::update() +void DisplayBase::invalidateDisplay() { qt5_graphic_hw_invalidate(); } @@ -201,17 +198,14 @@ QRegion DisplayBase::getMask() 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(); diff --git a/tizen/src/ui/displaybase.h b/tizen/src/ui/displaybase.h index 73d96c6274..ffed69593d 100644 --- a/tizen/src/ui/displaybase.h +++ b/tizen/src/ui/displaybase.h @@ -50,7 +50,7 @@ public: SdbHelper *sdbHelper; void switchForm(DisplayType *displayForm); void scaleForm(qreal scaleFactor); - void update(); + void invalidateDisplay(); void updateGeometry(); QWidget *getWidget(); const QRect &getGeometry(); @@ -74,8 +74,8 @@ protected: 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); diff --git a/tizen/src/ui/displayglwidget.cpp b/tizen/src/ui/displayglwidget.cpp index f4dcb67ed0..d88947b441 100644 --- a/tizen/src/ui/displayglwidget.cpp +++ b/tizen/src/ui/displayglwidget.cpp @@ -4,9 +4,9 @@ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * Jinhyung Jo * GiWoong Kim * SeokYeon Hwang - * Sangho Park * Stanislav Vorobiov * * This program is free software; you can redistribute it and/or @@ -29,61 +29,455 @@ * */ +#include +#include #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 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); + + 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' + 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()); } /* 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 */ @@ -141,7 +535,23 @@ void DisplayGLWidget::leaveEvent(QEvent *event) } } +// 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(); } diff --git a/tizen/src/ui/displayglwidget.h b/tizen/src/ui/displayglwidget.h index 491d6fe594..cc327f56a6 100644 --- a/tizen/src/ui/displayglwidget.h +++ b/tizen/src/ui/displayglwidget.h @@ -4,9 +4,9 @@ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * Jinhyung Jo * GiWoong Kim * SeokYeon Hwang - * Sangho Park * Stanislav Vorobiov * * This program is free software; you can redistribute it and/or @@ -32,25 +32,33 @@ #ifndef DISPLAYGLWIDGET_H #define DISPLAYGLWIDGET_H -#include #include "displaybase.h" +#include +#include -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); @@ -61,6 +69,29 @@ protected: 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 diff --git a/tizen/src/ui/displayswapper.cpp b/tizen/src/ui/displayswapper.cpp deleted file mode 100644 index 95b30db5c1..0000000000 --- a/tizen/src/ui/displayswapper.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Qt UI - * - * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * GiWoong Kim - * Sangho Park - * 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(); -} diff --git a/tizen/src/ui/displayswapper.h b/tizen/src/ui/displayswapper.h deleted file mode 100644 index aa5714b0c2..0000000000 --- a/tizen/src/ui/displayswapper.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Qt UI - * - * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * GiWoong Kim - * Sangho Park - * 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 -#include - -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 diff --git a/tizen/src/ui/displayswwidget.cpp b/tizen/src/ui/displayswwidget.cpp index 3880f7deb1..9ca59a673f 100644 --- a/tizen/src/ui/displayswwidget.cpp +++ b/tizen/src/ui/displayswwidget.cpp @@ -71,7 +71,7 @@ void DisplaySWWidget::drawMtPoints(QPainter &painter) void DisplaySWWidget::paintEvent(QPaintEvent *event) { QLabel::paintEvent(event); - handlePaint(event); + handlePaint(); if (isTsEnabled == true) { /* draw multi-touch points */ @@ -96,7 +96,7 @@ void DisplaySWWidget::dropEvent(QDropEvent *event) void DisplaySWWidget::resizeEvent(QResizeEvent *event) { QLabel::resizeEvent(event); - handleResize(event); + handleResize(); repaint(); } diff --git a/tizen/src/ui/input/multitouchtracker.cpp b/tizen/src/ui/input/multitouchtracker.cpp index 04594f58f5..8f1bc33588 100644 --- a/tizen/src/ui/input/multitouchtracker.cpp +++ b/tizen/src/ui/input/multitouchtracker.cpp @@ -34,12 +34,6 @@ #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); @@ -79,8 +73,6 @@ void TouchPoint::updatePos(QPoint hostPos, QPoint guestPos) 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(); } @@ -109,11 +101,6 @@ MultiTouchTracker::MultiTouchTracker( 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() @@ -169,9 +156,6 @@ int MultiTouchTracker::addTouchPoint(QPoint hostPos, QPoint guestPos) 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(); @@ -239,8 +223,6 @@ int MultiTouchTracker::limitTouchCnt(int max) delete point; } touchPointList.removeLast(); - - qt5_mt_count--; } diff = beforeCnt - touchPointList.count(); @@ -522,7 +504,6 @@ void MultiTouchTracker::finishTracking() } touchPointList.clear(); - qt5_mt_count = 0; qt5_graphic_hw_invalidate(); } @@ -531,10 +512,4 @@ MultiTouchTracker::~MultiTouchTracker() 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; } diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp index dd8a5d02ef..c8065064bc 100644 --- a/tizen/src/ui/mainwindow.cpp +++ b/tizen/src/ui/mainwindow.cpp @@ -46,10 +46,7 @@ void qt5_graphic_hw_update(void); 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 */ @@ -59,8 +56,6 @@ MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : this->display = NULL; this->rotary = NULL; - this->swapper = NULL; - this->swapperThread = NULL; this->screenWidget = NULL; this->captureRequestHandler = NULL; @@ -72,10 +67,11 @@ MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : 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); @@ -98,7 +94,7 @@ MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : /* display */ updateDisplayMatrix(); - display = createDisplay(uiInfo->getMainFormDpyType()); + createDisplay(useGL); /* set HW Key shortcut */ keyboardShortcut = new KeyboardShortcut(this); @@ -111,60 +107,20 @@ MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : 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() @@ -173,21 +129,6 @@ 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; @@ -326,7 +267,7 @@ void MainWindow::openController(int index, int dockPos) /* 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()); @@ -363,7 +304,7 @@ void MainWindow::closeController() /* 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 */ @@ -519,8 +460,12 @@ void MainWindow::processCaptured(bool captured, void *pixels, if (captured) { qDebug("save captured image: %p", pixels); - QImage image = QImage((uchar *)pixels, width, height, QImage::Format_RGB32); - QPixmap pixmap = QPixmap::fromImage(image); /* deep copy the data */ + // pixels's format is ARGB32 + QImage image = + QImage((uchar *)pixels, width, height, QImage::Format_ARGB32); + // deep copy from image & set all alpha channel value to 0xFF + QPixmap pixmap = + QPixmap::fromImage(image.convertToFormat(QImage::Format_RGB32)); QMetaObject::invokeMethod(popupMenu, "slotShowScreenshot", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap)); @@ -528,6 +473,8 @@ void MainWindow::processCaptured(bool captured, void *pixels, qDebug("save blank image"); QPixmap pixmap(uiInfo->getResolution().width(), uiInfo->getResolution().height()); + // fill the uninitialized buffer of the pixmap with 0xFF000000 + pixmap.fill(QColor(0, 0, 0, 255)); QMetaObject::invokeMethod(popupMenu, "slotShowScreenshot", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap)); } @@ -582,6 +529,11 @@ bool MainWindow::isMovingMode() return (movingWidget != NULL); } +void MainWindow::updateTexture(unsigned int texture) +{ + ((DisplayGLWidget *)getDisplay())->changedTexture(texture); +} + /* override */ void MainWindow::closeEvent(QCloseEvent *event) { diff --git a/tizen/src/ui/mainwindow.h b/tizen/src/ui/mainwindow.h index 183aeb337c..5e10476cc4 100644 --- a/tizen/src/ui/mainwindow.h +++ b/tizen/src/ui/mainwindow.h @@ -35,12 +35,10 @@ #define MAINWINDOW_H #include -#include #include "menu/contextmenu.h" #include "mainview.h" #include "displaybase.h" -#include "displayswapper.h" #include "rotaryview.h" #include "uiinformation.h" #include "controller/dockingcontroller.h" @@ -53,7 +51,9 @@ class MainWindow : public QWidget Q_OBJECT public: - explicit MainWindow(UiInformation *uiInfo, QWidget *parent = 0); + explicit MainWindow(UiInformation *uiInfo, + bool useGL, + QWidget *parent = 0); ~MainWindow(); UiInformation *getUiInfo(void); @@ -79,13 +79,13 @@ public: FloatingController *getFloatingCon(); void openController(int index, int dockPos); void closeController(); - void startDisplaySwapper(); - void terminateDisplaySwapper(); void turnOnMovingMode(); void turnOffMovingMode(); bool isMovingMode(); + void updateTexture(unsigned int texture); + public slots: void slotContextMenu(const QPoint &pos); @@ -99,7 +99,7 @@ protected: QLabel *screenWidget; private: - DisplayBase *createDisplay(DisplayType *displayForm); + void createDisplay(bool useGL); RotaryView *createRotary(); UiInformation *uiInfo; @@ -112,8 +112,6 @@ private: RotaryView *rotary; ContextMenu *popupMenu; - QThread *swapperThread; - DisplaySwapper *swapper; KeyboardShortcut *keyboardShortcut; MovingWidget *movingWidget; diff --git a/tizen/src/ui/menu/screenshotdialog.cpp b/tizen/src/ui/menu/screenshotdialog.cpp index b41798c905..09b2759bbc 100644 --- a/tizen/src/ui/menu/screenshotdialog.cpp +++ b/tizen/src/ui/menu/screenshotdialog.cpp @@ -231,14 +231,12 @@ void ScreenShotDialog::updateRatio(int level) void ScreenShotDialog::updateScreenShot(QPixmap &shotData) { - /* scaling */ - QPixmap shotImage = shotData.scaled(shotData.size() * ratio, - Qt::KeepAspectRatio, Qt::FastTransformation); - - /* rotate */ - QMatrix matrix; - matrix.rotate(getDisplayAngle()); - shotImage = shotImage.transformed(matrix); + /* scaling & rotate */ + QTransform transform; + QPixmap shotImage = + shotData.transformed( + transform.scale(ratio, ratio).rotate(getDisplayAngle()), + Qt::SmoothTransformation); /* update */ scene->setSceneRect(0, 0, shotImage.width(), shotImage.height()); diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index 4df02d7634..c2a462a39f 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -29,6 +29,7 @@ */ #include +#include #include "qt5_supplement.h" #include "propertykeyword.h" @@ -54,6 +55,7 @@ void loadConFormFromXML(QFile *, UiInformation *); bool qt5IsOnscreen; QApplication *qt5App = NULL; +QOpenGLContext *qt5GLContext; static int argc = 0; static char *argv[0]; @@ -208,7 +210,7 @@ static void qt5_gui_init(void) /* GUI */ qDebug("start!"); - mainwindow = new MainWindow(uiInfo); + mainwindow = new MainWindow(uiInfo, qt5IsOnscreen); mainwindow->setCaptureRequestHandler(captureRequestListener, captureRequestHandler); /* position */ @@ -267,16 +269,12 @@ static void qt5_gui_init(void) 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); @@ -337,6 +335,27 @@ void qt5_early_prepare(bool isOnscreen) * QApplication is constructed. */ QCoreApplication::setAttribute(Qt::AA_X11InitThreads); #endif + 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); + // FIXME: modify the version using the gl_version proerty of VIGS + sfcFormat.setMajorVersion(3); +#ifdef CONFIG_DARWIN + sfcFormat.setMinorVersion(2); + sfcFormat.setProfile(QSurfaceFormat::CoreProfile); +#else + sfcFormat.setMinorVersion(1); +#endif + QSurfaceFormat::setDefaultFormat(sfcFormat); + } qt5App = new QApplication(argc, argv); @@ -352,6 +371,9 @@ void qt5_early_prepare(bool isOnscreen) eventFilter = new EventFilter(); qt5App->installNativeEventFilter(eventFilter); #endif + if (qt5IsOnscreen) { + qt5GLContext = QOpenGLContext::globalShareContext(); + } } void qt5_prepare(void) @@ -429,6 +451,13 @@ void qt5_process_captured(bool captured, void *pixels, int width, int height) } } +void qt5_update_texture(unsigned int tex_id) +{ + if (mainwindow) { + mainwindow->updateTexture(tex_id); + } +} + void qMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); diff --git a/tizen/src/ui/skinview.cpp b/tizen/src/ui/skinview.cpp index 83b33889a3..fd4ee5602b 100644 --- a/tizen/src/ui/skinview.cpp +++ b/tizen/src/ui/skinview.cpp @@ -38,7 +38,7 @@ SkinView::SkinView(QWidget *parent, QGraphicsScene *scene) : 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); -- cgit v1.2.3 From 6b1f06f25070e6d54afe1c887480a0b0f5a9eeda Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Tue, 26 Jul 2016 16:45:42 +0900 Subject: display: add initialization option Add code to run with OpenGL Legacy Profile in Mac OS X. Change-Id: I23967ccdd33d87d96df858460ceaa688b129d41e Signed-off-by: Jinhyung Jo --- tizen/src/ui/qt5.c | 5 +++++ tizen/src/ui/qt5.h | 2 ++ tizen/src/ui/qt5_supplement.cpp | 17 +++++++++++++---- tizen/src/ui/qt5_supplement.h | 2 ++ vl.c | 3 +++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/tizen/src/ui/qt5.c b/tizen/src/ui/qt5.c index 928c85e871..fe5adaa53c 100644 --- a/tizen/src/ui/qt5.c +++ b/tizen/src/ui/qt5.c @@ -176,6 +176,11 @@ int get_display_pixel_density(void) return pixel_density_dpi; } +void maru_qt5_set_force_legacy(bool isLegacy) +{ + qt5_set_force_legacy(isLegacy); +} + void maru_qt5_display_init(DisplayState *ds, int full_screen) { int i; diff --git a/tizen/src/ui/qt5.h b/tizen/src/ui/qt5.h index 83ee83ac77..68afb3559e 100644 --- a/tizen/src/ui/qt5.h +++ b/tizen/src/ui/qt5.h @@ -39,4 +39,6 @@ void maru_qt5_display_init(DisplayState *ds, int full_screen); void set_display_pixel_density(int dpi); int get_display_pixel_density(void); +void maru_qt5_set_force_legacy(bool isLegacy); + #endif // __QT5_H__ diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index c2a462a39f..50e8e1c468 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -56,6 +56,7 @@ void loadConFormFromXML(QFile *, UiInformation *); bool qt5IsOnscreen; QApplication *qt5App = NULL; QOpenGLContext *qt5GLContext; +bool isForceLegacy; static int argc = 0; static char *argv[0]; @@ -319,6 +320,11 @@ void qt5_destroy() uiInfo = NULL; } +void qt5_set_force_legacy(bool isLegacy) +{ + isForceLegacy = isLegacy; +} + void qt5_early_prepare(bool isOnscreen) { qt5IsOnscreen = isOnscreen; @@ -346,12 +352,15 @@ void qt5_early_prepare(bool isOnscreen) sfcFormat.setAlphaBufferSize(8); sfcFormat.setDepthBufferSize(24); sfcFormat.setStencilBufferSize(8); - // FIXME: modify the version using the gl_version proerty of VIGS - sfcFormat.setMajorVersion(3); #ifdef CONFIG_DARWIN - sfcFormat.setMinorVersion(2); - sfcFormat.setProfile(QSurfaceFormat::CoreProfile); + // 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); diff --git a/tizen/src/ui/qt5_supplement.h b/tizen/src/ui/qt5_supplement.h index 836af47ce9..dbdcd06be2 100644 --- a/tizen/src/ui/qt5_supplement.h +++ b/tizen/src/ui/qt5_supplement.h @@ -46,6 +46,8 @@ void qt5_switch_internal(void); void qt5_refresh_internal(void); const char* qt5_get_version(void); + +void qt5_set_force_legacy(bool isLegacy); #ifdef __cplusplus } #endif diff --git a/vl.c b/vl.c index 36172f6199..9bd7b3bb74 100644 --- a/vl.c +++ b/vl.c @@ -2282,6 +2282,9 @@ static DisplayType select_display(const char *p) } set_display_pixel_density(dpi); nextopt = endptr; + } else if (strstart(opts, ",forcelegacy", &nextopt)) { + opts = nextopt; + maru_qt5_set_force_legacy(true); } else { invalid_maru_qt_args: error_report(FAILED_TO_DISPLAY_PARSING); -- cgit v1.2.3 From f97e348d82261ed0e5d7b0a20666d066fcd8e730 Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Mon, 12 Sep 2016 11:27:53 +0900 Subject: net: use https_proxy as ecp parameter Search box on location tab uses https protocol to communicate with map server. To access to map server, need https_proxy value. Change-Id: Ice4847644abc9939d4e7a5c16e10a224d66c5acd Signed-off-by: Munkyu Im --- tizen/src/emul_state.c | 28 ++++++++++++++-------------- tizen/src/emul_state.h | 2 +- tizen/src/ui/menu/contextmenu.cpp | 18 ++++++++---------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index 43fdb5010b..101bff6885 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -311,38 +311,38 @@ const char *get_kernel_file(void) return qemu_opt_get(qemu_get_machine_opts(), "kernel"); } -// http proxy -static const char *http_proxy_addr = NULL; +// https proxy +static const char *https_proxy_addr = NULL; -const char *get_http_proxy_addr(void) +const char *get_https_proxy_addr(void) { - if (http_proxy_addr) { - return http_proxy_addr; + if (https_proxy_addr) { + return https_proxy_addr; } const char *kernel_cmdline = qemu_opt_get(qemu_get_machine_opts(), "append"); // kernel cmdline always contains proxy information - char *buf = g_strstr_len(kernel_cmdline, -1, "http_proxy="); + char *buf = g_strstr_len(kernel_cmdline, -1, "https_proxy="); if (buf) { char **token = g_strsplit_set(buf, "= ", 3); if (token[0] && token[1] && g_strcmp0(token[1], "")) { - http_proxy_addr = g_strdup(token[1]); + https_proxy_addr = g_strdup(token[1]); g_strfreev(token); - LOG_INFO("HTTP proxy address: %s\n", http_proxy_addr); + LOG_INFO("HTTPS proxy address: %s\n", https_proxy_addr); - return http_proxy_addr; + return https_proxy_addr; } g_strfreev(token); } - http_proxy_addr = g_strdup(""); + https_proxy_addr = g_strdup(""); - LOG_INFO("HTTP proxy address is not set.\n"); + LOG_INFO("HTTPS proxy address is not set.\n"); - return http_proxy_addr; + return https_proxy_addr; } // vm_name @@ -742,8 +742,8 @@ static void emul_state_notify_exit(Notifier *notifier, void *data) g_free((void *)swap_image_file); swap_image_file = NULL; - g_free((void *)http_proxy_addr); - http_proxy_addr = NULL; + g_free((void *)https_proxy_addr); + https_proxy_addr = NULL; g_free((void *)vm_name); vm_name = NULL; diff --git a/tizen/src/emul_state.h b/tizen/src/emul_state.h index b360e88332..91a427a952 100644 --- a/tizen/src/emul_state.h +++ b/tizen/src/emul_state.h @@ -128,7 +128,7 @@ const char *get_drive_image_file(void); const char *get_drive_image_ver(void); const char *get_swap_image_file(void); const char *get_kernel_file(void); -const char *get_http_proxy_addr(void); +const char *get_https_proxy_addr(void); const char *get_vm_name(void); const char *get_profile_name(void); const char *get_platform_version(void); diff --git a/tizen/src/ui/menu/contextmenu.cpp b/tizen/src/ui/menu/contextmenu.cpp index cf60abdc21..4d0cd4c346 100644 --- a/tizen/src/ui/menu/contextmenu.cpp +++ b/tizen/src/ui/menu/contextmenu.cpp @@ -941,21 +941,19 @@ void ContextMenu::slotShell() void ContextMenu::launchControlPanel(QString& command, QStringList& arguments) { - QString httpProxyAddr; - QString httpProxyPort; - const char *http_proxy_addr = get_http_proxy_addr(); - if (http_proxy_addr) { - char **proxy = g_strsplit(http_proxy_addr, ":", 2); + const char *https_proxy_addr = get_https_proxy_addr(); + if (https_proxy_addr) { + char **proxy = g_strsplit(https_proxy_addr, ":", 2); if (proxy[0] && proxy[1]) { - httpProxyAddr = "-Dhttp.proxyHost=" + QString(proxy[0]); - httpProxyPort = "-Dhttp.proxyPort=" + QString(proxy[1]); + QString httpsProxyAddr = "-Dhttps.proxyHost=" + QString(proxy[0]); + QString httpsProxyPort = "-Dhttps.proxyPort=" + QString(proxy[1]); + if (httpsProxyAddr != NULL && httpsProxyPort != NULL) { + arguments << httpsProxyAddr << httpsProxyPort; + } } g_strfreev(proxy); } - if (httpProxyAddr != NULL && httpProxyPort != NULL) { - arguments << httpProxyAddr << httpProxyPort; - } QString loggingCommand = QString("launching ecp: \"" + command + "\""); -- cgit v1.2.3 From 4cc9531734b166f870b4b1392d70fc02ae7a46fa Mon Sep 17 00:00:00 2001 From: "jihye424.kim" Date: Tue, 20 Sep 2016 16:19:09 +0900 Subject: detail dialog: remove ?(about) button Change-Id: I26c70ba1b868b1a769a37cf973231dc764e78da7 Signed-off-by: jihye424.kim --- tizen/src/ui/menu/detailedinfodialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tizen/src/ui/menu/detailedinfodialog.cpp b/tizen/src/ui/menu/detailedinfodialog.cpp index 7f404902fa..a7b104b543 100644 --- a/tizen/src/ui/menu/detailedinfodialog.cpp +++ b/tizen/src/ui/menu/detailedinfodialog.cpp @@ -54,6 +54,9 @@ DetailedInfoDialog::DetailedInfoDialog(QWidget *parent) : win = ((MainWindow *)parent); keyboardShortcut = win->getKeyboardShortcut(); + // remove ? button + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + setWindowTitle(DETAILED_INFO_TITLE); setMinimumWidth(DIALOG_MIN_WIDTH); setMinimumHeight(DIALOG_MIN_HEIGHT); -- cgit v1.2.3 From 469e1487bf96f72eb4d493b207c1d0751e513e61 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Mon, 19 Sep 2016 20:22:20 +0900 Subject: display: fix transparency bug If the alpha value of the color less than 1.0, there is a issue that the desktop background is blended on the offscreen mode. So fixed it. Change-Id: Ic5c80aa7274a8ce6e9b433dc87e2581b0761619c Signed-off-by: Jinhyung Jo --- tizen/src/ui/displayswwidget.cpp | 4 ++-- tizen/src/ui/qt5_supplement.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tizen/src/ui/displayswwidget.cpp b/tizen/src/ui/displayswwidget.cpp index 9ca59a673f..97c968ee32 100644 --- a/tizen/src/ui/displayswwidget.cpp +++ b/tizen/src/ui/displayswwidget.cpp @@ -40,11 +40,11 @@ DisplaySWWidget::DisplaySWWidget(QWidget *parent, DisplayType *displayForm, QSize resolution, qreal scaleFactor) : QLabel(parent), DisplayBase(displayForm, resolution, scaleFactor, this) { - /* fill the screen with black surface */ + /* fill the screen with black(with full alpha) surface */ QPixmap initImage( displayForm->getRect().width() * scaleFactor, displayForm->getRect().height() * scaleFactor); - initImage.fill(Qt::black); + initImage.fill(QColor(0, 0, 0, 255)); setPixmap(initImage); /* to be enable to drop events */ setAcceptDrops(true); diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index 016a2ec98c..d87d2d3df2 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -513,10 +513,10 @@ void qt5_prepare(void) void qt5_update_internal(void *data, int width, int height) { - QImage image((uchar *)data, width, height, QImage::Format_RGB32); + QImage image((uchar *)data, width, height, QImage::Format_ARGB32); - mainwindow->getScreenWidget()->setPixmap( - QPixmap::fromImage(image.transformed( + mainwindow->getScreenWidget()->setPixmap(QPixmap::fromImage( + image.convertToFormat(QImage::Format_RGB32).transformed( mainwindow->getDisplayMatrix(), Qt::SmoothTransformation))); } -- cgit v1.2.3 From 9d4610a7ec9a6e3cd3ca89accbe57a9409593d50 Mon Sep 17 00:00:00 2001 From: Minkee Lee Date: Mon, 12 Sep 2016 19:57:09 +0900 Subject: ecp-launch: launch .app file in mac os x In mac os x, launch ecp using 'open' command like following # open emulator-control-panel.app --args [params ...] Change-Id: I9dbf1246decd5ef01272cce18a8841b103e311b1 Signed-off-by: Minkee Lee --- tizen/src/ui/menu/contextmenu.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tizen/src/ui/menu/contextmenu.cpp b/tizen/src/ui/menu/contextmenu.cpp index 4d0cd4c346..264847c4e3 100644 --- a/tizen/src/ui/menu/contextmenu.cpp +++ b/tizen/src/ui/menu/contextmenu.cpp @@ -1013,18 +1013,28 @@ void ContextMenu::slotControlPanel() QStringList arguments; // check for new ECP -#ifndef CONFIG_WIN32 - QString newCommand = QDir(QCoreApplication::applicationDirPath() + +#if defined(CONFIG_WIN32) + QString ecpCommand = QDir(QCoreApplication::applicationDirPath() + + QDir::separator() + SDK_EMULATOR_TOOLS_BIN_PATH + + SDK_ECP_FILE + ".cmd").absolutePath(); +#elif defined(CONFIG_LINUX) + QString ecpCommand = QDir(QCoreApplication::applicationDirPath() + QDir::separator() + SDK_EMULATOR_TOOLS_BIN_PATH + SDK_ECP_FILE).absolutePath(); #else - QString newCommand = QDir(QCoreApplication::applicationDirPath() + + QString ecpCommand = QDir(QCoreApplication::applicationDirPath() + QDir::separator() + SDK_EMULATOR_TOOLS_BIN_PATH + - SDK_ECP_FILE + ".cmd").absolutePath(); + SDK_ECP_FILE + ".app").absolutePath(); +#endif + if (QFileInfo(ecpCommand).exists()) { +#if defined(CONFIG_DARWIN) + // In mac os x, launch .app using "open" command + // ex : open emulator-control-panel.app --args vm_name=... platform_version=... + command = "open"; + arguments << ecpCommand << "--args"; +#else + command = ecpCommand; #endif - if (QFileInfo(newCommand).exists()) { - command = newCommand; - QString vmNameOpt = "vm_name=" + parent->getUiInfo()->getVmName(); QString platformVersionOpt = "platform_version=" + QString::fromLocal8Bit(get_platform_version()); -- cgit v1.2.3 From ecd40c78bd3483f72725b44ef1df45b585ba33c8 Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Tue, 20 Sep 2016 13:23:05 +0900 Subject: ecs: separate cli vm searching cannot find vm between old and later version by ecp cli - old version: 2.3, 2.3.1 - later version: 2.3.2, 2.4, 3.0 Change-Id: I6833c03063573cb1329c74fce77cdafab12a5e58 Signed-off-by: Jinhyung Choi --- tizen/src/ecs/ecs_msg_device.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tizen/src/ecs/ecs_msg_device.c b/tizen/src/ecs/ecs_msg_device.c index 3000478bde..1cdbe91fa0 100644 --- a/tizen/src/ecs/ecs_msg_device.c +++ b/tizen/src/ecs/ecs_msg_device.c @@ -431,9 +431,6 @@ bool msgproc_device_req(ECS_Client *ccli, ECS__DeviceReq *msg) #endif } else if (!strcmp(cmd, "input")) { msgproc_device_req_input(ccli, msg, cmd); - } else if (!strcmp(cmd, "vmname")) { - const char *vmname = get_vm_name(); - msgproc_device_ans(ccli, cmd, true, vmname); } else if (!strcmp(cmd, "vminfo")) { gchar vminfo[128]; g_snprintf(vminfo, sizeof(vminfo) - 1, "%s %s %s", -- cgit v1.2.3 From 938a29b318b0de4e53c4e22a001e6562dff5a255 Mon Sep 17 00:00:00 2001 From: "jihye424.kim" Date: Wed, 21 Sep 2016 11:09:40 +0900 Subject: package: update version(2.6.4) Change-Id: I05290052483fc021d074c4e0529fae937773e177 Signed-off-by: jihye424.kim --- package/changelog | 5 +++++ package/pkginfo.manifest | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index 62caaf7bc5..5f598dbe13 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,8 @@ +* 2.6.4 +- fix transparency bug +- separate cli vm searching +- launch ecp using .app file in mac os +== jihye kim 2016-09-21 * 2.6.2 - tizen-kvm is moved to emulator-supplements package == SeokYeon Hwang 2016-03-22 diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index b7b6b20495..6df08d7770 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.3 +Version: 2.6.4 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From 92456f96a9696c8a405f587979cbd1d838083d6e Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Wed, 21 Sep 2016 13:40:04 +0900 Subject: ui: add missing "break" statement Change-Id: Iff825869360222d3beaf3d158de5121c7537b1e9 Signed-off-by: SeokYeon Hwang --- tizen/src/ui/qt5_supplement.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index d87d2d3df2..7bf99152f6 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -184,6 +184,7 @@ static void qMessageOutput(QtMsgType type, const QMessageLogContext &context, case QtCriticalMsg: case QtFatalMsg: typeChar = 'S'; + break; default: qFatal("invalid message type"); break; -- cgit v1.2.3 From 88478db5ad8b252a75ef3c354d712173f1a89b2e Mon Sep 17 00:00:00 2001 From: "jihye424.kim" Date: Wed, 21 Sep 2016 14:44:04 +0900 Subject: detail dialog: temporarily remove shortcut info in mac Change-Id: I5f2b6a8471699c963084e52e3ad0d499b37473c1 Signed-off-by: jihye424.kim --- tizen/src/ui/menu/detailedinfodialog.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tizen/src/ui/menu/detailedinfodialog.cpp b/tizen/src/ui/menu/detailedinfodialog.cpp index a7b104b543..6bd9be74f1 100644 --- a/tizen/src/ui/menu/detailedinfodialog.cpp +++ b/tizen/src/ui/menu/detailedinfodialog.cpp @@ -76,8 +76,10 @@ DetailedInfoDialog::DetailedInfoDialog(QWidget *parent) : /* VM information table */ vmInfoTable = createVmInfoTable(); tabWidget->addTab(vmInfoTable, tr(DETAILED_INFO_VMTAB_TITLE)); - +// FIXME: temporarily remove shortcut dialog in DARWIN +#ifndef CONFIG_DARWIN /* shortcut information table */ + QTabWidget *shortcutTab = new QTabWidget(tabWidget); menuShortcutTable = createShortcutInfoTable(); @@ -86,6 +88,8 @@ DetailedInfoDialog::DetailedInfoDialog(QWidget *parent) : shortcutTab->addTab(keyShortcutTable, "HW Key"); tabWidget->addTab(shortcutTab, DETAILED_INFO_SHORTCUTTAB_TITLE); +#endif + } upsideLayout->addWidget(tabWidget); @@ -322,7 +326,10 @@ void DetailedInfoDialog::insertHwKeyShortcutInfo( /* override */ void DetailedInfoDialog::showEvent(QShowEvent *event) { +// FIXME: temporarily remove shortcut dialog in DARWIN +#ifndef CONFIG_DARWIN updateShortcutTableItems(); +#endif if ((windowState() & Qt::WindowMaximized) == 0) { tabWidget->setCurrentIndex(0); -- cgit v1.2.3 From 168fae707fb10068ea59795f3e4e49a59b2ef688 Mon Sep 17 00:00:00 2001 From: "jihye424.kim" Date: Thu, 22 Sep 2016 13:20:07 +0900 Subject: package: update version (2.6.5) Change-Id: I2e9b643c64e385b24f417d008a2440d491b46300 Signed-off-by: jihye424.kim --- package/changelog | 4 ++++ package/pkginfo.manifest | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index 5f598dbe13..f489127dc2 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,7 @@ +* 2.6.5 +- temporarily remove shortcut info in mac +- add missing "break" statement in skin +== jihye kim 2016-09-22 * 2.6.4 - fix transparency bug - separate cli vm searching diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index 6df08d7770..78ccd8e4c6 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.4 +Version: 2.6.5 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From c14765c5052b04ec3b85a1adb458e400c0e0a5e7 Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Mon, 26 Sep 2016 18:14:21 +0900 Subject: osutil: adjust vm lock module - move it to an earlier time.(early launching time) - make the same lock file(vm.lock) on each host OS. Change-Id: I80744500bf7c25c536061d2952f7f6552a0406f1 Signed-off-by: Munkyu Im --- tizen/src/emulator.c | 2 +- tizen/src/util/osutil-darwin.c | 4 ++-- tizen/src/util/osutil-linux.c | 4 ++-- tizen/src/util/osutil-win32.c | 5 +++-- tizen/src/util/osutil.c | 29 +++++++++++++++++++++-------- tizen/src/util/osutil.h | 5 +++-- 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index b1d6bab6c8..940e0d1409 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -240,7 +240,6 @@ const char *prepare_maru(const char * const kernel_cmdline) void prepare_maru_after_device_init(void) { - make_vm_lock_os(); init_device_hotplug(); start_ecs(); @@ -308,6 +307,7 @@ static int emulator_main(int argc, char *argv[], char **envp) set_bin_path_os(_qemu_argv[0]); if (launch_conf_file) { + make_vm_lock_os(g_path_get_dirname(launch_conf_file)); if (!load_conf(launch_conf_file)) { return -1; } diff --git a/tizen/src/util/osutil-darwin.c b/tizen/src/util/osutil-darwin.c index b27ed7ca24..c797ca8df0 100644 --- a/tizen/src/util/osutil-darwin.c +++ b/tizen/src/util/osutil-darwin.c @@ -47,8 +47,8 @@ #include "new_debug_ch.h" DECLARE_DEBUG_CHANNEL(osutil); -void make_vm_lock_os(void) { - make_vm_lock_posix(); +void make_vm_lock_os(gchar *vms_path) { + make_vm_lock_posix(vms_path); } void set_bin_path_os(char const *const exec_argv) diff --git a/tizen/src/util/osutil-linux.c b/tizen/src/util/osutil-linux.c index 8e432f990b..c46e46123f 100644 --- a/tizen/src/util/osutil-linux.c +++ b/tizen/src/util/osutil-linux.c @@ -50,8 +50,8 @@ #include "new_debug_ch.h" DECLARE_DEBUG_CHANNEL(osutil); -void make_vm_lock_os(void) { - make_vm_lock_posix(); +void make_vm_lock_os(gchar *vms_path) { + make_vm_lock_posix(vms_path); } void set_bin_path_os(char const *const exec_argv) diff --git a/tizen/src/util/osutil-win32.c b/tizen/src/util/osutil-win32.c index a76edfc2e6..bced9f8e7a 100644 --- a/tizen/src/util/osutil-win32.c +++ b/tizen/src/util/osutil-win32.c @@ -83,12 +83,13 @@ image file and kernel log file are aleady opened with exclusive write lock by pre-executed emulator. But it is still useful for emulator-manager. */ -void make_vm_lock_os(void) +void make_vm_lock_os(gchar *vms_path) { + g_assert(lock_file == INVALID_HANDLE_VALUE); g_assert(lock_filename == NULL); - lock_filename = g_strdup_printf("%s.lock", get_drive_image_file()); + lock_filename = g_strdup_printf("%s\\%s", vms_path, VMLOCK_FILE); if (g_mkdir_with_parents(g_path_get_dirname(lock_filename), 0777)) { LOG_WARNING("Can not create directory for lock file: %ld\n", diff --git a/tizen/src/util/osutil.c b/tizen/src/util/osutil.c index 099e1780b7..de78c53d42 100644 --- a/tizen/src/util/osutil.c +++ b/tizen/src/util/osutil.c @@ -46,6 +46,7 @@ DECLARE_DEBUG_CHANNEL(osutil) static int lock_file = -1; +static gchar *lock_filename = NULL; static struct flock _lock = { .l_type = F_WRLCK, .l_start = 0, @@ -101,6 +102,7 @@ static bool fd_checklock(int fd) static void remove_vm_lock_posix(void) { + int error = 0; if (lock_file == -1) { return; } @@ -110,6 +112,16 @@ static void remove_vm_lock_posix(void) } close(lock_file); + if (lock_filename != NULL) { + if (unlink(lock_filename) == -1) { + error = errno; + LOG_WARNING("Failed to unlink lock file(%d): %s\n", + error, strerror(error)); + } + g_free(lock_filename); + lock_filename = NULL; + } + lock_file = -1; } @@ -120,21 +132,22 @@ static void notify_remove_lock(Notifier *notifier, void *data) static Notifier remove_lock = { .notify = notify_remove_lock }; -void make_vm_lock_posix(void) +void make_vm_lock_posix(gchar *vms_path) { - const char *image_file = get_drive_image_file(); int error = 0; + lock_filename = g_strdup_printf("%s/%s", vms_path, VMLOCK_FILE); - g_assert(lock_file == -1); - g_assert(image_file != NULL); + g_assert(lock_filename != NULL); retry: - lock_file = open(image_file, O_RDWR); + lock_file = open(lock_filename, O_RDWR|O_CREAT, 0666); if (lock_file == -1) { error = errno; - LOG_WARNING("Failed to open image file for lock: %s\n", - strerror(error)); - return; + LOG_WARNING("Failed to open file for lock(%d): %s\n", + error, strerror(error)); + error_report("Can not execute this VM. " + "The same VM may be running now."); + exit(1); } if (fd_lock(lock_file) == -1) { diff --git a/tizen/src/util/osutil.h b/tizen/src/util/osutil.h index 8e9d2ac519..7dc9fea2f4 100644 --- a/tizen/src/util/osutil.h +++ b/tizen/src/util/osutil.h @@ -42,15 +42,16 @@ #define ERR_NODEV 4 /* ACT_SDCARD_DETACH_FAIL. No sdcard attached. */ #define ERR_BUSY 5 /* ACT_SDCARD_ATTACH_FAIL. Already sdcard attached. */ #define ERR_NOENT 6 /* ACT_SDCARD_NO_ATTACH_FOUND. Other sdcard attached. */ +#define VMLOCK_FILE "vm.lock" extern const char *pac_tempfile; -void make_vm_lock_os(void); +void make_vm_lock_os(gchar *vms_path); bool make_sdcard_lock_os(char *sdcard); int remove_sdcard_lock_os(char *sdcard); #ifndef CONFIG_WIN32 -void make_vm_lock_posix(void); +void make_vm_lock_posix(gchar *dirname); bool make_sdcard_lock_posix(char *sdcard); int remove_sdcard_lock_posix(char *sdcard); -- cgit v1.2.3 From 32cd89a98e701ba1a8badd98b25a60ea409ca129 Mon Sep 17 00:00:00 2001 From: jihye Date: Mon, 26 Sep 2016 18:19:00 +0900 Subject: about: change version from build version to platform version Change-Id: I4095209a97b751f51ce7c9696a98202399892493 Signed-off-by: jihye --- tizen/src/ui/menu/aboutdialog.cpp | 7 ++++++- tizen/src/ui/menu/detailedinfodialog.cpp | 3 ++- tizen/src/ui/resource/ui_strings.h | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tizen/src/ui/menu/aboutdialog.cpp b/tizen/src/ui/menu/aboutdialog.cpp index 491eef6ed2..9b921554ba 100644 --- a/tizen/src/ui/menu/aboutdialog.cpp +++ b/tizen/src/ui/menu/aboutdialog.cpp @@ -30,6 +30,8 @@ #include "aboutdialog.h" #include "resource/ui_strings.h" #include "build_info.h" +#include "mainwindow.h" +#include "emul_state.h" AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent, Qt::Dialog | Qt::WindowStaysOnTopHint) @@ -56,6 +58,9 @@ AboutDialog::AboutDialog(QWidget *parent) : } upsideLayout->addWidget(imageLabel); + /* Emulator platform version*/ + QString platformVersion = QString(get_platform_version()).section('-', 1).trimmed(); + /* SDK version */ QString versionFilePath = QDir(QCoreApplication::applicationDirPath() + QDir::separator() + SDK_ROOT_PATH + SDK_VERSION_FILE).absolutePath(); @@ -90,7 +95,7 @@ AboutDialog::AboutDialog(QWidget *parent) : */ QString aboutText = - "" + QString(EMULATOR_TITLE) + " for " + EMULATOR_BUILD_VER + "

" + + "" + QString(EMULATOR_TITLE) + " for " + platformVersion + "

" + ABOUT_SDK_VERSION_TEXT + " : " + sdkVer + "
" + ABOUT_PKG_VERSION_TEXT + " : " + pkgVer + "
" + /* "Snapshot : " + SnapshotName + "
" + */ diff --git a/tizen/src/ui/menu/detailedinfodialog.cpp b/tizen/src/ui/menu/detailedinfodialog.cpp index 6bd9be74f1..cbf6640552 100644 --- a/tizen/src/ui/menu/detailedinfodialog.cpp +++ b/tizen/src/ui/menu/detailedinfodialog.cpp @@ -34,6 +34,7 @@ #include "resource/ui_strings.h" #include "mainwindow.h" #include "menu/advancedmenuitem.h" +#include "emul_state.h" extern "C" { int get_display_pixel_density(void); @@ -202,7 +203,7 @@ QTableWidget *DetailedInfoDialog::createVmInfoTable() } QString pkgVer = QString(pkginfo_version).section(':', 1).trimmed(); - insertTableRow(vmInfo, QString(DETAILED_INFO_EMUL_VER), QString(EMULATOR_BUILD_VER) + + insertTableRow(vmInfo, QString(DETAILED_INFO_EMUL_VER), QString(get_platform_version()).section('-', 1).trimmed() + " Release on " + sdkVer + " SDK (" + pkgVer + ")"); /* add double click event listener */ diff --git a/tizen/src/ui/resource/ui_strings.h b/tizen/src/ui/resource/ui_strings.h index 65566ffcf8..3a5c3afa5c 100644 --- a/tizen/src/ui/resource/ui_strings.h +++ b/tizen/src/ui/resource/ui_strings.h @@ -33,7 +33,6 @@ #define UI_STRINGS_H #define EMULATOR_TITLE "Tizen Emulator" -#define EMULATOR_BUILD_VER "3.0" #define SDK_OFFICIAL_NAME "Tizen SDK" #define SDK_OFFICIAL_URL "https://developer.tizen.org" -- cgit v1.2.3 From 1232e04f68b60a65b31716b40f199aabaf28df6b Mon Sep 17 00:00:00 2001 From: jihye Date: Tue, 27 Sep 2016 13:39:48 +0900 Subject: about dialog: remove ?(about) button Change-Id: I0041d77d293b7149a93321df2349697055a1dc7a Signed-off-by: jihye --- tizen/src/ui/menu/aboutdialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tizen/src/ui/menu/aboutdialog.cpp b/tizen/src/ui/menu/aboutdialog.cpp index 9b921554ba..b956dd83ad 100644 --- a/tizen/src/ui/menu/aboutdialog.cpp +++ b/tizen/src/ui/menu/aboutdialog.cpp @@ -38,6 +38,9 @@ AboutDialog::AboutDialog(QWidget *parent) : { setWindowTitle(ABOUT_TITLE); + // remove ? button + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + QVBoxLayout *baseLayout = new QVBoxLayout(this); baseLayout->setMargin(0); baseLayout->setSpacing(5); -- cgit v1.2.3 From 79aa7aeed2cbf343d465f42bdf4a8509e0546449 Mon Sep 17 00:00:00 2001 From: jihye Date: Wed, 28 Sep 2016 11:49:10 +0900 Subject: package: update version(2.6.6) Change-Id: Ided4434d646ffe0aaf21e7f451567cb06d512d41 Signed-off-by: jihye --- package/changelog | 5 +++++ package/pkginfo.manifest | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index f489127dc2..4368274cd4 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,8 @@ +* 2.6.6 +- adjust vm lock module +- change version of about dialog +- add surface option for AMD gpu driver +==jihye kim 2016-09-28 * 2.6.5 - temporarily remove shortcut info in mac - add missing "break" statement in skin diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index 78ccd8e4c6..a51e19eebe 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.5 +Version: 2.6.6 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From c4145f7dc2d523e446b28738410288764bb0910a Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Fri, 30 Sep 2016 20:47:28 +0900 Subject: display: fix display rotation failure The degree 0(90) & degree 180(270) have same size of display. For that reason, the resize event does not occur when the rotate angle is changed. So update the status of the rotate & scale before drawing. Change-Id: I2092a45ad60e65d4ee14ed8bb66def210b28cc68 Signed-off-by: Jinhyung Jo --- tizen/src/ui/displayglwidget.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tizen/src/ui/displayglwidget.cpp b/tizen/src/ui/displayglwidget.cpp index d88947b441..6ccb3eb2a0 100644 --- a/tizen/src/ui/displayglwidget.cpp +++ b/tizen/src/ui/displayglwidget.cpp @@ -442,6 +442,14 @@ void DisplayGLWidget::paintGL() } 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(); @@ -459,13 +467,6 @@ void DisplayGLWidget::resizeGL(int w, int h) // TODO: check changing of the guest resolution // for 'Runtime Resolution Change' - 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()); } /* override */ -- cgit v1.2.3 From f569c289168ec579bcb62231d2572a80be5d6d52 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Fri, 30 Sep 2016 21:14:32 +0900 Subject: Revert "display: move display functionality to Qt5 GUI" With AMD GPUs, reverted commit makes a ciritical bug that GUI is invisible. This reverts commit 99ffcba1997dade13316bd09023f93597db0f2df. Conflicts: tizen/src/ui/displayglwidget.cpp tizen/src/ui/qt5_supplement.cpp Change-Id: Ie5b4655bdf1beb228c788dd7dc874bb6f1cba63c Signed-off-by: Jinhyung Jo --- hw/vigs/vigs_gl_backend.c | 573 ++++++++++++++++++++++++- hw/vigs/vigs_gl_backend.h | 32 ++ hw/vigs/vigs_gl_backend_cgl.c | 10 +- hw/vigs/vigs_gl_backend_glx.c | 75 ++-- hw/vigs/vigs_gl_backend_wgl.c | 9 +- hw/vigs/vigs_onscreen_server.c | 92 ++-- hw/vigs/vigs_onscreen_server.h | 6 +- hw/vigs/vigs_qt5.cpp | 96 +++-- hw/vigs/vigs_qt5.h | 4 +- hw/vigs/vigs_qt5_stub.c | 19 +- tizen/src/ui/Makefile.objs | 3 + tizen/src/ui/controller/dockingcontroller.cpp | 4 +- tizen/src/ui/controller/floatingcontroller.cpp | 4 +- tizen/src/ui/displaybase.cpp | 26 +- tizen/src/ui/displaybase.h | 6 +- tizen/src/ui/displayglwidget.cpp | 463 ++------------------ tizen/src/ui/displayglwidget.h | 47 +- tizen/src/ui/displayswapper.cpp | 62 +++ tizen/src/ui/displayswapper.h | 57 +++ tizen/src/ui/displayswwidget.cpp | 4 +- tizen/src/ui/input/multitouchtracker.cpp | 25 ++ tizen/src/ui/mainwindow.cpp | 91 +++- tizen/src/ui/mainwindow.h | 14 +- tizen/src/ui/qt5_supplement.cpp | 42 +- tizen/src/ui/skinview.cpp | 2 +- vl.c | 2 +- 26 files changed, 1084 insertions(+), 684 deletions(-) create mode 100644 tizen/src/ui/displayswapper.cpp create mode 100644 tizen/src/ui/displayswapper.h diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c index 9995d1c15a..94b95ff5c0 100644 --- a/hw/vigs/vigs_gl_backend.c +++ b/hw/vigs/vigs_gl_backend.c @@ -36,8 +36,20 @@ #include "vigs_ref.h" #include "vigs_qt5.h" #include "winsys_gl.h" +#include "hw/pci/maru_brightness.h" #include +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 @@ -189,6 +201,136 @@ static const char *g_fs_color_source_gl3 = " 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" @@ -600,6 +742,102 @@ static void vigs_gl_draw_color_prog(struct vigs_gl_backend *backend, 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) { @@ -656,6 +894,28 @@ static void vigs_gl_create_ortho(GLfloat left, GLfloat right, 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]) @@ -766,7 +1026,8 @@ static bool vigs_gl_surface_setup_framebuffer(struct vigs_gl_surface *gl_sfc, } static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend, - uint32_t width, uint32_t height) + uint32_t width, uint32_t height, + GLfloat ortho[16]) { GLuint cur_tex = 0; @@ -804,6 +1065,9 @@ static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend, 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; @@ -1971,7 +2235,8 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface, if (!vigs_gl_update_dpy_texture(gl_backend, surface->ws_sfc->width, - surface->ws_sfc->height)) { + surface->ws_sfc->height, + gl_root_sfc->ortho)) { goto out; } @@ -2176,34 +2441,219 @@ static bool vigs_gl_backend_display(struct vigs_backend *backend, VIGS_LOG_TRACE("enter"); if (vigs_qt5_onscreen_enabled()) { - vigs_qt5_dpy_render_texture(gl_backend->dpy_tex); - return true; - } + 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->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"); + if (!gl_backend->is_gl_2 && !gl_backend->dpy_vao) { + gl_backend->GenVertexArrays(1, &gl_backend->dpy_vao); + + if (!gl_backend->dpy_vao) { + VIGS_LOG_CRITICAL("cannot create VAO"); exit(1); } - gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb); + gl_backend->BindVertexArray(gl_backend->dpy_vao); } - gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, gl_backend->dpy_tex, 0); + gl_backend->BindBuffer(GL_ARRAY_BUFFER, gl_backend->dpy_vbo); + gl_backend->Disable(GL_DEPTH_TEST); + 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); + 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; + } - gl_backend->read_pixels_make_current(gl_backend, false); + 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); + } + + 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->Disable(GL_BLEND); + } + +out: + gl_backend->Finish(); return true; } else { - return false; + 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; + } } } @@ -2373,7 +2823,9 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) gl_backend->yuv420_prog_vtex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtex"); gl_backend->GenBuffers(1, &gl_backend->vbo); - if (!gl_backend->vbo) { + gl_backend->GenBuffers(1, &gl_backend->dpy_vbo); + + if (!gl_backend->vbo || !gl_backend->dpy_vbo) { VIGS_LOG_CRITICAL("cannot create VBOs"); goto fail; } @@ -2392,6 +2844,65 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) 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); @@ -2407,6 +2918,8 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) 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; @@ -2419,12 +2932,30 @@ fail: 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); @@ -2465,6 +2996,8 @@ void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend) 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); } diff --git a/hw/vigs/vigs_gl_backend.h b/hw/vigs/vigs_gl_backend.h index ca2d3658ab..dca456b06c 100644 --- a/hw/vigs/vigs_gl_backend.h +++ b/hw/vigs/vigs_gl_backend.h @@ -220,11 +220,43 @@ struct vigs_gl_backend * 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; + /* * @} */ diff --git a/hw/vigs/vigs_gl_backend_cgl.c b/hw/vigs/vigs_gl_backend_cgl.c index cc0eabe2e5..7a41d0a8ab 100644 --- a/hw/vigs/vigs_gl_backend_cgl.c +++ b/hw/vigs/vigs_gl_backend_cgl.c @@ -62,7 +62,7 @@ static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] = kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFAOpenGLProfile, kCGLOGLPVersion_Legacy, + kCGLPFAPBuffer, 0 }; @@ -255,7 +255,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, CGLError error; CGLPixelFormatObj pixel_format; int n; - CGLContextObj share_ctx = NULL; + CGLContextObj qt5_ctx = NULL; gl_backend_cgl = g_malloc0(sizeof(*gl_backend_cgl)); @@ -378,15 +378,15 @@ struct vigs_backend *vigs_gl_backend_create(void *display, } if (vigs_qt5_onscreen_enabled()) { - share_ctx = (CGLContextObj)vigs_qt5_gl_context_get(); - if (!share_ctx) { + qt5_ctx = (CGLContextObj)vigs_qt5_gl_context_create(gl_backend_cgl->base.is_gl_2); + if (!qt5_ctx) { goto fail2; } } if (!vigs_gl_backend_cgl_create_context(gl_backend_cgl, pixel_format, - share_ctx, + qt5_ctx, &gl_backend_cgl->context)) { goto fail3; } diff --git a/hw/vigs/vigs_gl_backend_glx.c b/hw/vigs/vigs_gl_backend_glx.c index 8212b88dbb..4014a832e3 100644 --- a/hw/vigs/vigs_gl_backend_glx.c +++ b/hw/vigs/vigs_gl_backend_glx.c @@ -238,7 +238,7 @@ static GLXFBConfig vigs_gl_backend_glx_get_config(struct vigs_gl_backend_glx *gl }; if (gl_backend_glx->glXQueryContext(gl_backend_glx->dpy, - vigs_qt5_gl_context_get(), + gl_backend_glx->ctx, GLX_FBCONFIG_ID, &config_attribs[1]) != Success) { VIGS_LOG_CRITICAL("Unable to get context's GLX config"); @@ -417,7 +417,7 @@ static void vigs_gl_backend_glx_destroy(struct vigs_backend *backend) gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, gl_backend_glx->read_pixels_sfc); } - if (gl_backend_glx->ctx) { + if (!vigs_qt5_onscreen_enabled() && gl_backend_glx->ctx) { gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, gl_backend_glx->ctx); } @@ -443,7 +443,6 @@ struct vigs_backend *vigs_gl_backend_create(void *display, { 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)); @@ -575,35 +574,57 @@ struct vigs_backend *vigs_gl_backend_create(void *display, } if (vigs_qt5_onscreen_enabled()) { - share_ctx = (GLXContext)vigs_qt5_gl_context_get(); - if (!share_ctx) { + 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; - } + config = vigs_gl_backend_glx_get_config(gl_backend_glx); - if (!vigs_gl_backend_glx_create_surface(gl_backend_glx, - config, - &gl_backend_glx->read_pixels_sfc)) { - goto fail2; - } + if (!config) { + 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_surface(gl_backend_glx, + config, + &gl_backend_glx->read_pixels_sfc)) { + 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; + } + } else { + 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_context(gl_backend_glx, + config, + NULL, + &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_surface(gl_backend_glx, @@ -634,7 +655,7 @@ fail2: gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, gl_backend_glx->read_pixels_sfc); } - if (gl_backend_glx->ctx) { + if (!vigs_qt5_onscreen_enabled() && gl_backend_glx->ctx) { gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, gl_backend_glx->ctx); } diff --git a/hw/vigs/vigs_gl_backend_wgl.c b/hw/vigs/vigs_gl_backend_wgl.c index 9db01a0a7e..b5b45bcef0 100644 --- a/hw/vigs/vigs_gl_backend_wgl.c +++ b/hw/vigs/vigs_gl_backend_wgl.c @@ -482,7 +482,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, }; const char *ext_str = NULL; struct vigs_gl_backend_wgl *gl_backend_wgl = NULL; - HGLRC share_ctx = NULL; + HGLRC qt5_ctx = NULL; vigs_win_class.cbSize = sizeof(WNDCLASSEXA); vigs_win_class.style = 0; @@ -687,8 +687,9 @@ struct vigs_backend *vigs_gl_backend_create(void *display, tmp_win = NULL; if (vigs_qt5_onscreen_enabled()) { - share_ctx = (HGLRC)vigs_qt5_gl_context_get(); - if (!share_ctx) { + qt5_ctx = + (HGLRC)vigs_qt5_gl_context_create(gl_backend_wgl->base.is_gl_2); + if (!qt5_ctx) { goto fail; } } @@ -728,7 +729,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display, } if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl, - share_ctx, + qt5_ctx, &gl_backend_wgl->ctx)) { goto fail; } diff --git a/hw/vigs/vigs_onscreen_server.c b/hw/vigs/vigs_onscreen_server.c index d6830783cd..7fcc352b33 100644 --- a/hw/vigs/vigs_onscreen_server.c +++ b/hw/vigs/vigs_onscreen_server.c @@ -32,24 +32,6 @@ #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) @@ -70,6 +52,10 @@ static bool vigs_onscreen_server_begin_update(struct vigs_server *server, goto out; } + onscreen_server->updated = false; + onscreen_server->composited = false; + onscreen_server->dirty = false; + out: qemu_mutex_unlock(&onscreen_server->mutex); @@ -79,6 +65,23 @@ out: static void vigs_onscreen_server_finish_update(struct vigs_server *server, bool composited, bool dirty) +{ + 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; @@ -86,33 +89,52 @@ static void vigs_onscreen_server_finish_update(struct vigs_server *server, 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; } - qemu_mutex_unlock(&onscreen_server->mutex); - - if (composited || force) { - struct vigs_display_work_item *item; - - item = g_malloc(sizeof(*item)); + onscreen_server->updated = false; - work_queue_item_init(&item->base, &vigs_onscreen_server_display_work); + qemu_mutex_unlock(&onscreen_server->mutex); - item->server = server; + *displayed = true; - work_queue_add_item(onscreen_server->display_queue, &item->base); + 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); + } } else { - vigs_server_finish_update_display(server, false); + *displayed = false; } -} + vigs_server_finish_update_display(server, false); -static bool vigs_onscreen_server_display(struct vigs_server *server, - bool *displayed) -{ - *displayed = false; return false; } @@ -128,6 +150,7 @@ static void vigs_onscreen_server_destroy(struct vigs_server *server) 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); @@ -155,8 +178,7 @@ struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr, } qemu_mutex_init(&server->mutex); - - server->display_queue = render_queue; + qemu_cond_init(&server->cond); server->base.begin_update = &vigs_onscreen_server_begin_update; server->base.finish_update = &vigs_onscreen_server_finish_update; diff --git a/hw/vigs/vigs_onscreen_server.h b/hw/vigs/vigs_onscreen_server.h index 19d083e49c..b0ea1e93d7 100644 --- a/hw/vigs/vigs_onscreen_server.h +++ b/hw/vigs/vigs_onscreen_server.h @@ -37,8 +37,12 @@ struct vigs_onscreen_server 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, diff --git a/hw/vigs/vigs_qt5.cpp b/hw/vigs/vigs_qt5.cpp index 286014eff7..927d558320 100644 --- a/hw/vigs/vigs_qt5.cpp +++ b/hw/vigs/vigs_qt5.cpp @@ -27,26 +27,27 @@ * */ -#include +#include "vigs_qt5.h" +#include "config-host.h" #include #include #include -#include "config-host.h" -#include "vigs_qt5.h" +#include 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; } @@ -66,7 +67,7 @@ void *vigs_qt5_display(void) QGuiApplication::primaryScreen()); } -void *vigs_qt5_gl_context_get(void) +void *vigs_qt5_gl_context_create(bool is_gl2) { if (!qt5App) { fprintf(stderr, "QT5 not enabled!\n"); @@ -74,27 +75,79 @@ void *vigs_qt5_gl_context_get(void) } if (qt5GLContext) { - QPlatformNativeInterface *native = - QGuiApplication::platformNativeInterface(); + 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(); - 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"); - } - return ret; + + if (!ret) { + fprintf(stderr, "Cannot get native QT5 GL context!\n"); + + delete qt5GLContext; + qt5GLContext = NULL; } - return NULL; + + qt5GLFormat = format; + + return ret; } void vigs_qt5_register_capture_request_listener(void *listener, @@ -113,8 +166,3 @@ void vigs_qt5_process_captured(bool captured, void *pixels, { qt5_process_captured(captured, pixels, width, height); } - -void vigs_qt5_dpy_render_texture(uint32_t tex_id) -{ - qt5_update_texture(tex_id); -} diff --git a/hw/vigs/vigs_qt5.h b/hw/vigs/vigs_qt5.h index a27ae6184b..b88c84ebf8 100644 --- a/hw/vigs/vigs_qt5.h +++ b/hw/vigs/vigs_qt5.h @@ -38,14 +38,14 @@ bool vigs_qt5_onscreen_enabled(void); void *vigs_qt5_display(void); -void *vigs_qt5_gl_context_get(void); +void *vigs_qt5_gl_context_create(bool is_gl2); 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 diff --git a/hw/vigs/vigs_qt5_stub.c b/hw/vigs/vigs_qt5_stub.c index cf490f323c..9b3c80729b 100644 --- a/hw/vigs/vigs_qt5_stub.c +++ b/hw/vigs/vigs_qt5_stub.c @@ -34,6 +34,17 @@ #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; @@ -44,7 +55,7 @@ void *vigs_qt5_display(void) return NULL; } -void *vigs_qt5_gl_context_get(void) +void *vigs_qt5_gl_context_create(bool is_gl2) { return NULL; } @@ -65,9 +76,3 @@ void vigs_qt5_process_captured(bool captured, void *pixels, { return; } - -void vigs_qt5_dpy_render_texture(uint32_t tex_id) -{ - return; -} - diff --git a/tizen/src/ui/Makefile.objs b/tizen/src/ui/Makefile.objs index 76ddc8469c..b18942f2a1 100644 --- a/tizen/src/ui/Makefile.objs +++ b/tizen/src/ui/Makefile.objs @@ -11,6 +11,7 @@ $(obj)/qrc_resource.cpp: $(TIZEN_UI)/resource/resource.qrc 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 @@ -33,6 +34,8 @@ $(obj)/moc_displayglwidget.cpp: $(obj)/displayglwidget.h 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 diff --git a/tizen/src/ui/controller/dockingcontroller.cpp b/tizen/src/ui/controller/dockingcontroller.cpp index 51d4daf0f5..ec6030a5e6 100644 --- a/tizen/src/ui/controller/dockingcontroller.cpp +++ b/tizen/src/ui/controller/dockingcontroller.cpp @@ -38,10 +38,10 @@ DockingController::DockingController(ControllerForm *conForm, this->menu = menu; this->dockPos = dockPos; - setStyleSheet("background: transparent; border-style: none"); + setStyleSheet("border-style: none"); QGraphicsScene *conScene = new QGraphicsScene(this); - conScene->setBackgroundBrush(Qt::transparent); + conScene->setBackgroundBrush(Qt::black); conView = new DockingConView(this, conForm, conScene); conView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); diff --git a/tizen/src/ui/controller/floatingcontroller.cpp b/tizen/src/ui/controller/floatingcontroller.cpp index 1f807d85eb..0d6eab0bd5 100644 --- a/tizen/src/ui/controller/floatingcontroller.cpp +++ b/tizen/src/ui/controller/floatingcontroller.cpp @@ -36,12 +36,12 @@ FloatingController::FloatingController(ControllerForm *conForm, this->conForm = conForm; this->menu = menu; - setStyleSheet("background: transparent; border-style: none"); + setStyleSheet("border-style: none"); setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); setWindowTitle(conForm->getName()); QGraphicsScene *conScene = new QGraphicsScene(this); - conScene->setBackgroundBrush(Qt::transparent); + conScene->setBackgroundBrush(Qt::black); conView = new FloatingConView(this, conForm, conScene); conView->resize(conForm->skinImg[LayoutForm::normal].size()); diff --git a/tizen/src/ui/displaybase.cpp b/tizen/src/ui/displaybase.cpp index 04601fa952..80b8b9b9e1 100644 --- a/tizen/src/ui/displaybase.cpp +++ b/tizen/src/ui/displaybase.cpp @@ -41,6 +41,10 @@ void qt5_graphic_hw_invalidate(void); 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) { @@ -123,7 +127,6 @@ void DisplayBase::showOffGuideImg() maskImage.height() * scaleFactor).mask()); } - widget->update(); offGuide->show(); } @@ -146,7 +149,7 @@ void DisplayBase::switchForm(DisplayType *displayForm) { qDebug() << "display switch angle:" << displayForm->getAngle(); - rotateAngle = displayForm->getAngle(); + qt5_window_angle = rotateAngle = displayForm->getAngle(); rect = displayForm->getRect(); maskImage = displayForm->getMask(); @@ -154,8 +157,8 @@ void DisplayBase::switchForm(DisplayType *displayForm) req_set_sensor_accel_angle(rotateAngle); /* update sensor */ updateGeometry(); - invalidateDisplay(); - widget->update(); + update(); + widget->repaint(); } void DisplayBase::scaleForm(qreal scaleFactor) @@ -166,11 +169,11 @@ void DisplayBase::scaleForm(qreal scaleFactor) updateGeometry(); - invalidateDisplay(); - widget->update(); + update(); + widget->repaint(); } -void DisplayBase::invalidateDisplay() +void DisplayBase::update() { qt5_graphic_hw_invalidate(); } @@ -198,14 +201,17 @@ QRegion DisplayBase::getMask() return widget->mask(); } -void DisplayBase::handlePaint() +void DisplayBase::handlePaint(QPaintEvent *event) { /* do nothing */ } -void DisplayBase::handleResize() +void DisplayBase::handleResize(QResizeEvent *event) { - qDebug() << "resize display:" << widget->size(); + qDebug() << "resize display:" << event->size(); + + qt5_window_width = widget->width(); + qt5_window_height = widget->height(); qt5_graphic_hw_invalidate(); diff --git a/tizen/src/ui/displaybase.h b/tizen/src/ui/displaybase.h index ffed69593d..73d96c6274 100644 --- a/tizen/src/ui/displaybase.h +++ b/tizen/src/ui/displaybase.h @@ -50,7 +50,7 @@ public: SdbHelper *sdbHelper; void switchForm(DisplayType *displayForm); void scaleForm(qreal scaleFactor); - void invalidateDisplay(); + void update(); void updateGeometry(); QWidget *getWidget(); const QRect &getGeometry(); @@ -74,8 +74,8 @@ protected: DisplayBase(DisplayType *displayForm, QSize resolution, qreal scaleFactor, QWidget *w); virtual ~DisplayBase(); - void handlePaint(); - void handleResize(); + void handlePaint(QPaintEvent *event); + void handleResize(QResizeEvent *event); void handleMousePress(QMouseEvent *event); void handleMouseRelease(QMouseEvent *event); diff --git a/tizen/src/ui/displayglwidget.cpp b/tizen/src/ui/displayglwidget.cpp index 6ccb3eb2a0..f4dcb67ed0 100644 --- a/tizen/src/ui/displayglwidget.cpp +++ b/tizen/src/ui/displayglwidget.cpp @@ -4,9 +4,9 @@ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: - * Jinhyung Jo * GiWoong Kim * SeokYeon Hwang + * Sangho Park * Stanislav Vorobiov * * This program is free software; you can redistribute it and/or @@ -29,456 +29,61 @@ * */ -#include -#include #include "displayglwidget.h" -#include "input/multitouchtracker.h" extern "C" { -extern uint32_t brightness_level; -extern bool display_off; -extern uint8_t brightness_tbl[]; +#include "emul_state.h" }; -// 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, +DisplayGLWidget::DisplayGLWidget(QWidget *parent, QGLContext *context, DisplayType *displayForm, QSize resolution, qreal scaleFactor) : - QOpenGLWidget(parent), DisplayBase(displayForm, resolution, scaleFactor, this), - mGuestResolution(resolution) + QGLWidget(context, parent), DisplayBase(displayForm, resolution, scaleFactor, this) { - this->maskQImage = displayForm->getMask().toImage(); - this->maskTexture = 0; - this->needScale = false; - this->dpyTexture = 0; - this->mtTexture = 0; - this->texProgram = NULL; - this->scaleProgram = NULL; - + setAutoBufferSwap(false); /* 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 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::paintGL() +void DisplayGLWidget::dragEnterEvent(QDragEnterEvent *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(); + handleDragEnterEvent(event); } /* override */ -void DisplayGLWidget::resizeGL(int w, int h) +void DisplayGLWidget::dropEvent(QDropEvent *event) { - qDebug("resizeGL"); - handleResize(); - - // TODO: check changing of the guest resolution - // for 'Runtime Resolution Change' + handleDropEvent(event); } /* override */ -void DisplayGLWidget::dragEnterEvent(QDragEnterEvent *event) +void DisplayGLWidget::paintEvent(QPaintEvent *event) { - handleDragEnterEvent(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); } /* override */ -void DisplayGLWidget::dropEvent(QDropEvent *event) +void DisplayGLWidget::resizeEvent(QResizeEvent *event) { - handleDropEvent(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); } /* override */ @@ -536,23 +141,7 @@ void DisplayGLWidget::leaveEvent(QEvent *event) } } -// TODO: To correct releasing resources DisplayGLWidget::~DisplayGLWidget() { - 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(); + /* do nothing */ } diff --git a/tizen/src/ui/displayglwidget.h b/tizen/src/ui/displayglwidget.h index cc327f56a6..491d6fe594 100644 --- a/tizen/src/ui/displayglwidget.h +++ b/tizen/src/ui/displayglwidget.h @@ -4,9 +4,9 @@ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: - * Jinhyung Jo * GiWoong Kim * SeokYeon Hwang + * Sangho Park * Stanislav Vorobiov * * This program is free software; you can redistribute it and/or @@ -32,33 +32,25 @@ #ifndef DISPLAYGLWIDGET_H #define DISPLAYGLWIDGET_H +#include #include "displaybase.h" -#include -#include -class QOpenGLFunctions; -class QOpenGLShaderProgram; -class QOpenGLVertexArrayObject; -class QOpenGLBuffer; - -class DisplayGLWidget : public QOpenGLWidget, +class DisplayGLWidget : public QGLWidget, public DisplayBase { Q_OBJECT public: - DisplayGLWidget(QWidget *parent, - DisplayType *displayForm, - QSize resolution, qreal scaleFactor); + DisplayGLWidget(QWidget *parent, QGLContext *context, + DisplayType *displayForm, QSize resolution, qreal scaleFactor); ~DisplayGLWidget(); - void changedTexture(unsigned int texture); - protected: void initializeGL(); - void paintGL(); - void resizeGL(int w, int h); + + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); @@ -69,29 +61,6 @@ protected: 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 diff --git a/tizen/src/ui/displayswapper.cpp b/tizen/src/ui/displayswapper.cpp new file mode 100644 index 0000000000..95b30db5c1 --- /dev/null +++ b/tizen/src/ui/displayswapper.cpp @@ -0,0 +1,62 @@ +/* + * Qt UI + * + * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * 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(); +} diff --git a/tizen/src/ui/displayswapper.h b/tizen/src/ui/displayswapper.h new file mode 100644 index 0000000000..aa5714b0c2 --- /dev/null +++ b/tizen/src/ui/displayswapper.h @@ -0,0 +1,57 @@ +/* + * Qt UI + * + * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * 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 +#include + +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 diff --git a/tizen/src/ui/displayswwidget.cpp b/tizen/src/ui/displayswwidget.cpp index 97c968ee32..ec149a5c9f 100644 --- a/tizen/src/ui/displayswwidget.cpp +++ b/tizen/src/ui/displayswwidget.cpp @@ -71,7 +71,7 @@ void DisplaySWWidget::drawMtPoints(QPainter &painter) void DisplaySWWidget::paintEvent(QPaintEvent *event) { QLabel::paintEvent(event); - handlePaint(); + handlePaint(event); if (isTsEnabled == true) { /* draw multi-touch points */ @@ -96,7 +96,7 @@ void DisplaySWWidget::dropEvent(QDropEvent *event) void DisplaySWWidget::resizeEvent(QResizeEvent *event) { QLabel::resizeEvent(event); - handleResize(); + handleResize(event); repaint(); } diff --git a/tizen/src/ui/input/multitouchtracker.cpp b/tizen/src/ui/input/multitouchtracker.cpp index 8f1bc33588..04594f58f5 100644 --- a/tizen/src/ui/input/multitouchtracker.cpp +++ b/tizen/src/ui/input/multitouchtracker.cpp @@ -34,6 +34,12 @@ #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); @@ -73,6 +79,8 @@ void TouchPoint::updatePos(QPoint hostPos, QPoint guestPos) 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(); } @@ -101,6 +109,11 @@ MultiTouchTracker::MultiTouchTracker( 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() @@ -156,6 +169,9 @@ int MultiTouchTracker::addTouchPoint(QPoint hostPos, QPoint guestPos) 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(); @@ -223,6 +239,8 @@ int MultiTouchTracker::limitTouchCnt(int max) delete point; } touchPointList.removeLast(); + + qt5_mt_count--; } diff = beforeCnt - touchPointList.count(); @@ -504,6 +522,7 @@ void MultiTouchTracker::finishTracking() } touchPointList.clear(); + qt5_mt_count = 0; qt5_graphic_hw_invalidate(); } @@ -512,4 +531,10 @@ MultiTouchTracker::~MultiTouchTracker() 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; } diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp index aeab23c9ab..7737da1d66 100644 --- a/tizen/src/ui/mainwindow.cpp +++ b/tizen/src/ui/mainwindow.cpp @@ -46,7 +46,10 @@ void qt5_graphic_hw_update(void); void qemu_system_graceful_shutdown_request(unsigned int sec); } -MainWindow::MainWindow(UiInformation *uiInfo, bool useGL, QWidget *parent) : +QOpenGLContext *qt5GLContext = NULL; +QSurfaceFormat qt5GLFormat; + +MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : QWidget(parent) { /* initialize */ @@ -56,6 +59,8 @@ MainWindow::MainWindow(UiInformation *uiInfo, bool useGL, QWidget *parent) : this->display = NULL; this->rotary = NULL; + this->swapper = NULL; + this->swapperThread = NULL; this->screenWidget = NULL; this->captureRequestHandler = NULL; @@ -67,11 +72,10 @@ MainWindow::MainWindow(UiInformation *uiInfo, bool useGL, QWidget *parent) : 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::transparent); + mainScene->setBackgroundBrush(Qt::black); /* view */ mainView = new MainView(mainScene, this); @@ -94,7 +98,7 @@ MainWindow::MainWindow(UiInformation *uiInfo, bool useGL, QWidget *parent) : /* display */ updateDisplayMatrix(); - createDisplay(useGL); + display = createDisplay(uiInfo->getMainFormDpyType()); /* set HW Key shortcut */ keyboardShortcut = new KeyboardShortcut(this); @@ -107,20 +111,60 @@ MainWindow::MainWindow(UiInformation *uiInfo, bool useGL, QWidget *parent) : SLOT(slotContextMenu(const QPoint&))); } -void MainWindow::createDisplay(bool useGL) +DisplayBase *MainWindow::createDisplay(DisplayType *displayForm) { qDebug("create a display"); - if (useGL) { /* on-screen rendering */ - this->display = new DisplayGLWidget(this, - uiInfo->getMainFormDpyType(), uiInfo->getResolution(), getUiState()->getScaleFactor()); + 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(); } else { /* off-screen rendering */ DisplaySWWidget *widget = new DisplaySWWidget(this, - uiInfo->getMainFormDpyType(), uiInfo->getResolution(), getUiState()->getScaleFactor()); + displayForm, uiInfo->getResolution(), getUiState()->getScaleFactor()); - this->screenWidget = widget; - this->display = widget; + screenWidget = widget; + displayWidget = widget; } + + return displayWidget; } RotaryView *MainWindow::createRotary() @@ -129,6 +173,21 @@ 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; @@ -267,7 +326,7 @@ void MainWindow::openController(int index, int dockPos) /* Some part of QGLWidget's surface might be lost on Windows when view changing. * So, we need an additional updating for display. */ - display->invalidateDisplay(); + display->update(); #ifdef CONFIG_LINUX popupMenu->slotOnTop(getUiState()->isOnTop()); @@ -304,7 +363,7 @@ void MainWindow::closeController() /* Some part of QGLWidget's surface might be lost on Windows when view changing. * So, we need an additional updating for display. */ - display->invalidateDisplay(); + display->update(); } /* override */ @@ -459,7 +518,6 @@ void MainWindow::processCaptured(bool captured, void *pixels, if (captured) { qDebug("save captured image: %p", pixels); - // pixels's format is ARGB32 QImage image = QImage((uchar *)pixels, width, height, QImage::Format_ARGB32); @@ -529,11 +587,6 @@ bool MainWindow::isMovingMode() return (movingWidget != NULL); } -void MainWindow::updateTexture(unsigned int texture) -{ - ((DisplayGLWidget *)getDisplay())->changedTexture(texture); -} - /* override */ void MainWindow::closeEvent(QCloseEvent *event) { diff --git a/tizen/src/ui/mainwindow.h b/tizen/src/ui/mainwindow.h index 5e10476cc4..183aeb337c 100644 --- a/tizen/src/ui/mainwindow.h +++ b/tizen/src/ui/mainwindow.h @@ -35,10 +35,12 @@ #define MAINWINDOW_H #include +#include #include "menu/contextmenu.h" #include "mainview.h" #include "displaybase.h" +#include "displayswapper.h" #include "rotaryview.h" #include "uiinformation.h" #include "controller/dockingcontroller.h" @@ -51,9 +53,7 @@ class MainWindow : public QWidget Q_OBJECT public: - explicit MainWindow(UiInformation *uiInfo, - bool useGL, - QWidget *parent = 0); + explicit MainWindow(UiInformation *uiInfo, QWidget *parent = 0); ~MainWindow(); UiInformation *getUiInfo(void); @@ -79,13 +79,13 @@ public: FloatingController *getFloatingCon(); void openController(int index, int dockPos); void closeController(); + void startDisplaySwapper(); + void terminateDisplaySwapper(); void turnOnMovingMode(); void turnOffMovingMode(); bool isMovingMode(); - void updateTexture(unsigned int texture); - public slots: void slotContextMenu(const QPoint &pos); @@ -99,7 +99,7 @@ protected: QLabel *screenWidget; private: - void createDisplay(bool useGL); + DisplayBase *createDisplay(DisplayType *displayForm); RotaryView *createRotary(); UiInformation *uiInfo; @@ -112,6 +112,8 @@ private: RotaryView *rotary; ContextMenu *popupMenu; + QThread *swapperThread; + DisplaySwapper *swapper; KeyboardShortcut *keyboardShortcut; MovingWidget *movingWidget; diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index 7bf99152f6..33c68a49f9 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -29,7 +29,6 @@ */ #include -#include #include "qt5_supplement.h" #include "propertykeyword.h" @@ -55,7 +54,6 @@ bool is_display_off(void); //using namespace std; bool qt5IsOnscreen; QApplication *qt5App = NULL; -QOpenGLContext *qt5GLContext; bool isForceLegacy; static int argc = 0; @@ -333,7 +331,7 @@ static void qt5_gui_init(void) /* GUI */ qDebug("start!"); - mainwindow = new MainWindow(uiInfo, qt5IsOnscreen); + mainwindow = new MainWindow(uiInfo); mainwindow->setCaptureRequestHandler(captureRequestListener, captureRequestHandler); /* position */ @@ -392,12 +390,16 @@ static void qt5_gui_init(void) 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); @@ -463,30 +465,6 @@ void qt5_early_prepare(bool isOnscreen) * QApplication is constructed. */ QCoreApplication::setAttribute(Qt::AA_X11InitThreads); #endif - 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); @@ -502,9 +480,6 @@ void qt5_early_prepare(bool isOnscreen) eventFilter = new EventFilter(); qt5App->installNativeEventFilter(eventFilter); #endif - if (qt5IsOnscreen) { - qt5GLContext = QOpenGLContext::globalShareContext(); - } } void qt5_prepare(void) @@ -581,10 +556,3 @@ void qt5_process_captured(bool captured, void *pixels, int width, int height) mainwindow->processCaptured(captured, pixels, width, height); } } - -void qt5_update_texture(unsigned int tex_id) -{ - if (mainwindow) { - mainwindow->updateTexture(tex_id); - } -} diff --git a/tizen/src/ui/skinview.cpp b/tizen/src/ui/skinview.cpp index fd4ee5602b..83b33889a3 100644 --- a/tizen/src/ui/skinview.cpp +++ b/tizen/src/ui/skinview.cpp @@ -38,7 +38,7 @@ SkinView::SkinView(QWidget *parent, QGraphicsScene *scene) : this->grabPos = SKINVIEW_NULLITY_POSITION; /* note: do not call setStyleSheet() separately for each style */ - setStyleSheet("QGraphicsView { background: transparent; border-style: none; }" + + setStyleSheet("QGraphicsView { border-style: none; }" + QString(STYLE_TOOLTIP)); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); diff --git a/vl.c b/vl.c index 0adf7f2d8b..d8b5697e93 100644 --- a/vl.c +++ b/vl.c @@ -2295,7 +2295,7 @@ static DisplayType select_display(const char *p) 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); -- cgit v1.2.3 From 07cfe62467612339476b3a83ef61ffcb9f3ee3e9 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Mon, 19 Sep 2016 20:04:13 +0900 Subject: util: improve backtrace feature improve & clean up the code: - correct coding convention - add backtrace feature to Mac OS X : remove #ifdef CONFIG_DARWIN ... #endif The 'backtarce' family functions first appeared in Mac OS X 10.5 - modify the Windows code using the APIs in DbgHelp - change debug channel: from debug_ch to new_debug_ch - remove some lines like redundant/unclear/unwanted/etc. - modify output form Change-Id: I8b57d996fa9daabf990932fcfb82e45a5e453636 Signed-off-by: Jinhyung Jo --- tizen/src/util/Makefile.objs | 3 + tizen/src/util/error_handler.c | 286 ++++++++++++++++++++++------------------- 2 files changed, 156 insertions(+), 133 deletions(-) diff --git a/tizen/src/util/Makefile.objs b/tizen/src/util/Makefile.objs index a4a2969fcc..a322caf7d7 100644 --- a/tizen/src/util/Makefile.objs +++ b/tizen/src/util/Makefile.objs @@ -30,6 +30,9 @@ obj-y += qt5_error_report.o # error handler obj-y += error_handler.o +ifdef CONFIG_WIN32 +LIBS += -ldbghelp +endif # debug channel obj-y += new_debug_ch.o diff --git a/tizen/src/util/error_handler.c b/tizen/src/util/error_handler.c index 1f91e8df85..5a41b054ea 100644 --- a/tizen/src/util/error_handler.c +++ b/tizen/src/util/error_handler.c @@ -4,6 +4,7 @@ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * Jinhyung Jo * SeokYeon Hwang * GiWoong Kim * @@ -37,6 +38,7 @@ #ifdef CONFIG_WIN32 #include +#include #else #include #endif @@ -47,60 +49,40 @@ #include "emulator_common.h" #include "emulator.h" -#include "debug_ch.h" - -MULTI_DEBUG_CHANNEL(qemu, backtrace); - #ifdef CONFIG_QT #include "qt5_error_report.h" #endif -#if defined(CONFIG_WIN32) -static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; -#elif defined(CONFIG_LINUX) -static pthread_spinlock_t siglock; -#endif +#include "new_debug_ch.h" -bool print_backtrace_at_normal_exit_enabled = false; +DECLARE_DEBUG_CHANNEL(backtrace); -/* Print 'backtrace' */ -#ifdef _WIN32 -struct frame_layout { - void *pNext; - void *pReturnAddr; -}; +bool print_backtrace_at_normal_exit_enabled; -static char *get_filename_from_path(char *path_buf) +void enable_print_backtrace_at_normal_exit(void) { - char *ret_slash; - char *ret_rslash; - - ret_slash = strrchr(path_buf, '/'); - ret_rslash = strrchr(path_buf, '\\'); - - if (ret_slash || ret_rslash) { - if (ret_slash > ret_rslash) { - return ret_slash + 1; - } else{ - return ret_rslash + 1; - } - } - - return path_buf; + print_backtrace_at_normal_exit_enabled = true; } +#ifdef CONFIG_WIN32 +static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; + +/* Windows 32 bit */ +#ifndef _WIN64 +struct frame_layout { + void *pNext; + void *pReturnAddr; +}; static HMODULE get_module_handle(void *dwAddress) { MEMORY_BASIC_INFORMATION Buffer; - return VirtualQuery((LPCVOID) dwAddress, &Buffer, sizeof(Buffer)) - ? (HMODULE) Buffer.AllocationBase : (HMODULE) 0; + return VirtualQuery((LPCVOID)dwAddress, &Buffer, sizeof(Buffer)) + ? (HMODULE)Buffer.AllocationBase : (HMODULE)0; } -#endif -static void dump_backtrace(void *ptr, int depth) +static void dump_backtrace(void *ptr) { -#ifdef _WIN32 int nCount; void *pTopFrame; struct frame_layout currentFrame; @@ -113,15 +95,11 @@ static void dump_backtrace(void *ptr, int depth) if (!pContext) { __asm__ __volatile__ ("movl %%ebp, %0" : "=m" (pTopFrame)); } else { -#ifdef _WIN64 - pTopFrame = (void *)((PCONTEXT)pContext)->Rbp; -#else pTopFrame = (void *)((PCONTEXT)pContext)->Ebp; -#endif } if (pTopFrame == NULL) { - INFO("ebp is null, skip this for now\n"); + LOG_INFO("ebp is null, skip this for now\n"); return ; } @@ -130,30 +108,23 @@ static void dump_backtrace(void *ptr, int depth) currentFrame.pReturnAddr = ((struct frame_layout *)pTopFrame)->pReturnAddr; pCurrentFrame = (struct frame_layout *)pTopFrame; - ERR("\nBacktrace Dump Start :\n"); if (pContext) { memset(module_buf, 0, sizeof(module_buf)); -#ifdef _WIN64 - hModule = get_module_handle((void *)((PCONTEXT)pContext)->Rip); -#else hModule = get_module_handle((void *)((PCONTEXT)pContext)->Eip); -#endif if (hModule) { if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) { memset(module_buf, 0, sizeof(module_buf)); } } -#ifdef _WIN64 - ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Rip, get_filename_from_path(module_buf)); -#else - ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Eip, get_filename_from_path(module_buf)); -#endif + LOG_SEVERE("#%04d 0x%08x from %s\n", + nCount, ((PCONTEXT)pContext)->Eip, module_buf); nCount++; } while (1) { if (((void *)pCurrentFrame < pTopFrame) - || ((void *)pCurrentFrame >= (void *)0xC0000000)) { + || ((void *)pCurrentFrame >= (void *)0xC0000000) + || !currentFrame.pReturnAddr) { break; } @@ -164,127 +135,174 @@ static void dump_backtrace(void *ptr, int depth) memset(module_buf, 0, sizeof(module_buf)); } } - ERR("[%02d]Addr = 0x%p : %s\n", nCount, currentFrame.pReturnAddr, get_filename_from_path(module_buf)); + LOG_SEVERE("#%04d 0x%08x from %s\n", + nCount, currentFrame.pReturnAddr, module_buf); - if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext, + if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext, (void *)¤tFrame, sizeof(struct frame_layout), NULL)) { break; } pCurrentFrame = (struct frame_layout *)pCurrentFrame->pNext; - if (depth) { - if (!--depth) { - break; - } - } nCount++; } -#else - void *trace[1024]; - int ndepth = backtrace(trace, 1024); - ERR("Backtrace depth is %d.\n", ndepth); - - backtrace_symbols_fd(trace, ndepth, fileno(stderr)); -#endif } -static void handle_error_at_exit(void) +#else + +/* Windows 64 bit */ +static void dump_backtrace(void *ptr) { - if (print_backtrace_at_normal_exit_enabled) { - INFO("Stack backtrace for tracing...\n"); - INFO("This is not an error.\n"); - dump_backtrace(NULL, 0); + int i; + DWORD image; + STACKFRAME64 frame; + CONTEXT context; + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + if (!ptr) { + ZeroMemory(&context, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_FULL; + RtlCaptureContext(&context); + } else { + CopyMemory(&context, ptr, sizeof(CONTEXT)); } -} -void enable_print_backtrace_at_normal_exit(void) { - print_backtrace_at_normal_exit_enabled = true; + SymSetOptions(SYMOPT_LOAD_LINES); + SymInitialize(hProcess, NULL, TRUE); + + ZeroMemory(&frame, sizeof(STACKFRAME64)); + image = IMAGE_FILE_MACHINE_AMD64; + frame.AddrPC.Offset = context.Rip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Rbp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Rsp; + frame.AddrStack.Mode = AddrModeFlat; + + i = 0; + while (1) { + BOOL result = StackWalk64(image, hProcess, hThread, + &frame, &context, NULL, + SymFunctionTableAccess64, + SymGetModuleBase64, NULL); + if (!result) { + break; + } + TCHAR buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + pSymbol->MaxNameLen = MAX_SYM_NAME; + DWORD64 displacement = 0; + TCHAR pFileName[MAX_PATH] = {0, }; + DWORD64 dwBase = SymGetModuleBase64(hProcess, frame.AddrPC.Offset); + if (dwBase) { + HMODULE hModule = (HMODULE)((DWORD_PTR)dwBase); + if (!GetModuleFileNameA(hModule, pFileName, MAX_PATH)) { + snprintf(pFileName, MAX_PATH, "Unknown Module"); + } + } + if (SymFromAddr(hProcess, + frame.AddrPC.Offset, + &displacement, pSymbol)) { + LOG_SEVERE("#%04d 0x%016x in %s from %s\n", + i, frame.AddrPC.Offset, pSymbol->Name, pFileName); + } else { + LOG_SEVERE("#%04d 0x%016x in ???????? from %s\n", + i, frame.AddrPC.Offset, pFileName); + } + i++; + } + SymCleanup(hProcess); } +#endif -#ifdef CONFIG_WIN32 -static WINAPI LONG maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pExceptionInfo){ - char module_buf[1024]; +static WINAPI LONG +maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pException) +{ + LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%016x]\n", + pException->ExceptionRecord->ExceptionCode, + pException->ExceptionRecord->ExceptionAddress); - // print system information again - print_system_info(); + dump_backtrace(pException->ContextRecord); - DWORD dwException = pExceptionInfo->ExceptionRecord->ExceptionCode; - ERR("%d\n ", (int)dwException); + return EXCEPTION_CONTINUE_SEARCH; +} - PEXCEPTION_RECORD pExceptionRecord; - HMODULE hModule; - PCONTEXT pContext; +static void register_exception_handler(void) +{ + prevExceptionFilter = + SetUnhandledExceptionFilter(maru_unhandled_exception_filter); +} - pExceptionRecord = pExceptionInfo->ExceptionRecord; +#else /* END FOR WINDOWS, START FOR LINUX & DARWIN */ - memset(module_buf, 0, sizeof(module_buf)); - hModule = get_module_handle(pExceptionRecord->ExceptionAddress); - if(hModule){ - if(!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))){ - memset(module_buf, 0, sizeof(module_buf)); - } - } +/* prevent an interrupt by another signal */ +QemuMutex siglock; +/* uses in case SIGSEGV */ +struct sigaction old_sa; - ERR("Exception [%X] occured at %s:0x%08x\n", - pExceptionRecord->ExceptionCode, - get_filename_from_path(module_buf), - pExceptionRecord->ExceptionAddress - ); +/* Print 'backtrace' */ +static void dump_backtrace(void *ptr) +{ + int i; + void *trace[1024]; + int ndepth = backtrace(trace, 1024); + char **syms = backtrace_symbols(trace, ndepth); - pContext = pExceptionInfo->ContextRecord; - dump_backtrace(pContext, 0); - _exit(0); - //return EXCEPTION_CONTINUE_SEARCH; + LOG_SEVERE("Backtrace depth is %d\n", ndepth); + for (i = 0; i < ndepth; i++) { + LOG_SEVERE("#%04d %s\n", i, syms[i]); + } + free(syms); } -#endif -#ifdef CONFIG_LINUX static void maru_sighandler(int sig) { - ERR("Got signal %d\n", sig); - // print system information again - print_system_info(); - - pthread_spin_lock(&siglock); - dump_backtrace(NULL, 0); - pthread_spin_unlock(&siglock); - _exit(0); + LOG_SEVERE("Got signal: %d(%s)\n", sig, strsignal(sig)); + + qemu_mutex_lock(&siglock); + dump_backtrace(NULL); + qemu_mutex_unlock(&siglock); + qemu_mutex_destroy(&siglock); + if (sig == SIGSEGV) { + sigaction(SIGSEGV, &old_sa, NULL); + raise(SIGSEGV); + } } -#endif - -#ifndef CONFIG_DARWIN static void register_exception_handler(void) { - #ifdef CONFIG_WIN32 - prevExceptionFilter = SetUnhandledExceptionFilter(maru_unhandled_exception_filter); - #else // LINUX void *trace[1]; struct sigaction sa; - // make dummy call to explicitly load glibc library + /* make dummy call to explicitly load glibc library */ backtrace(trace, 1); - pthread_spin_init(&siglock,0); - sa.sa_handler = (void*) maru_sighandler; + qemu_mutex_init(&siglock); + sa.sa_handler = maru_sighandler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - sigaction(SIGSEGV, &sa, NULL); + /* store previous signal action */ + sigaction(SIGSEGV, &sa, &old_sa); sigaction(SIGBUS, &sa, NULL); sigaction(SIGILL, &sa, NULL); sigaction(SIGFPE, &sa, NULL); sigaction(SIGABRT, &sa, NULL); - // main thread only + /* main thread only */ sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); - #endif } -#else // CONFIG_DARWIN -static void register_exception_handler(void) +#endif /* END FOR LINUX & DARWIN */ + +static void handle_error_at_exit(void) { - // TODO: Exception handling on darwin + if (print_backtrace_at_normal_exit_enabled) { + LOG_INFO("Stack backtrace for tracing...\n"); + LOG_INFO("This is not an error\n"); + dump_backtrace(NULL); + } } -#endif #define MAX_MESSAGE_LEN 2048 static size_t message_len; @@ -296,9 +314,9 @@ static void report(const char *fmt, va_list ap) message_len = g_strlcat(message, new_message, MAX_MESSAGE_LEN); g_free(new_message); - // We are wating for '\n' + /* We are waiting for '\n' */ if (message[message_len - 1] == '\n') { -#if defined(CONFIG_QT) +#ifdef CONFIG_QT start_qt5_msgbox(CRITICAL_ICON, message); #endif @@ -307,10 +325,12 @@ static void report(const char *fmt, va_list ap) } } -static ErrorReporter error_reporter = - { .report = report }; +static ErrorReporter error_reporter = { + .report = report +}; -void init_error_handler(void) { +void init_error_handler(void) +{ register_exception_handler(); add_error_reporter(&error_reporter); -- cgit v1.2.3 From d9569bc324b6ae1dfa6fb63b7ab106faf12958cc Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Wed, 5 Oct 2016 21:25:25 +0900 Subject: package: update version(2.6.7) Change-Id: I921963c6bc6feb7fd98a7d18bbbd4a5c9b76d2cc Signed-off-by: Jinhyung Jo --- package/changelog | 4 ++++ package/pkginfo.manifest | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index 4368274cd4..69dcabafb6 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,7 @@ +* 2.6.7 +- display: Revert "display: move display functionality to Qt5 GUI" for AMD gpu issue +- display: fix display rotation failure +== Jinhyung Jo 2016-10-05 * 2.6.6 - adjust vm lock module - change version of about dialog diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index a51e19eebe..242023bf8d 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.6 +Version: 2.6.7 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From 71d39cb8c22781add76c426664320be46225b042 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Wed, 5 Oct 2016 15:15:30 +0900 Subject: display: change QMatrix to QTransform QMatrix class that we use for 2D transformation is obsolete. QTransform is the recommended transformation class in Qt. Change-Id: Ib4361575ac8fc519c4947ad927b3fa58b506a3a3 Signed-off-by: Jinhyung Jo --- tizen/src/ui/mainwindow.cpp | 18 +++++++++--------- tizen/src/ui/mainwindow.h | 6 +++--- tizen/src/ui/qt5_supplement.cpp | 2 +- tizen/src/ui/skinpainter.cpp | 7 +++---- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp index 7737da1d66..04936100a4 100644 --- a/tizen/src/ui/mainwindow.cpp +++ b/tizen/src/ui/mainwindow.cpp @@ -97,7 +97,7 @@ MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : } /* display */ - updateDisplayMatrix(); + updateDisplayTransform(); display = createDisplay(uiInfo->getMainFormDpyType()); /* set HW Key shortcut */ @@ -211,9 +211,9 @@ UIState *MainWindow::getUiState() return uiInfo->getUiState(); } -const QMatrix &MainWindow::getDisplayMatrix() +const QTransform &MainWindow::getDisplayTransform() { - return dpyMatrix; + return dpyTransform; } MainView *MainWindow::getMainView() @@ -412,12 +412,12 @@ void MainWindow::setMask(const QRegion ®ion) } } -void MainWindow::updateDisplayMatrix() +void MainWindow::updateDisplayTransform() { - dpyMatrix.reset(); - dpyMatrix.scale( + dpyTransform.reset(); + dpyTransform.scale( getUiState()->getScaleFactor(), getUiState()->getScaleFactor()); - dpyMatrix.rotate(uiInfo->getMainFormDpyType()->getAngle()); + dpyTransform.rotate(uiInfo->getMainFormDpyType()->getAngle()); } void MainWindow::switchForm(int index) @@ -436,7 +436,7 @@ void MainWindow::switchForm(int index) /* register new HW key shortcuts */ keyboardShortcut->registerHwKeyShortcuts(uiInfo->getMainForm()->getKeyList()); - updateDisplayMatrix(); + updateDisplayTransform(); if (getDockingCon() != NULL) { getDockingCon()->updateGeometry(); @@ -467,7 +467,7 @@ void MainWindow::scaleForm(int scale) /* scale changing */ getUiState()->setScalePct(scale); - updateDisplayMatrix(); + updateDisplayTransform(); if (getDockingCon() != NULL) { getDockingCon()->updateGeometry(); diff --git a/tizen/src/ui/mainwindow.h b/tizen/src/ui/mainwindow.h index 183aeb337c..b83ff7ea65 100644 --- a/tizen/src/ui/mainwindow.h +++ b/tizen/src/ui/mainwindow.h @@ -58,14 +58,14 @@ public: UiInformation *getUiInfo(void); UIState *getUiState(void); - const QMatrix &getDisplayMatrix(); + const QTransform &getDisplayTransform(); MainView *getMainView(); ContextMenu *getPopupMenu(); DisplayBase *getDisplay(); KeyboardShortcut *getKeyboardShortcut(); QLabel *getScreenWidget(); - void updateDisplayMatrix(); + void updateDisplayTransform(); void switchForm(int angle); void scaleForm(int scale); void capture(void); @@ -105,7 +105,7 @@ private: UiInformation *uiInfo; /* windowing */ - QMatrix dpyMatrix; + QTransform dpyTransform; QGraphicsScene *mainScene; MainView *mainView; DisplayBase *display; diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index 33c68a49f9..00dec85f97 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -493,7 +493,7 @@ void qt5_update_internal(void *data, int width, int height) mainwindow->getScreenWidget()->setPixmap(QPixmap::fromImage( image.convertToFormat(QImage::Format_RGB32).transformed( - mainwindow->getDisplayMatrix(), Qt::SmoothTransformation))); + mainwindow->getDisplayTransform(), Qt::SmoothTransformation))); } void qt5_switch_internal(void) diff --git a/tizen/src/ui/skinpainter.cpp b/tizen/src/ui/skinpainter.cpp index 0dac529d34..2c2bb3d3dc 100644 --- a/tizen/src/ui/skinpainter.cpp +++ b/tizen/src/ui/skinpainter.cpp @@ -88,12 +88,11 @@ void SkinPainter::drawSkin(QString patchPath, QSize center, int degree, painter.drawEllipse(tagLeftTop, COLOR_TAG_SIZE, COLOR_TAG_SIZE); /* rotate */ - QMatrix matrix; - matrix.rotate(degree); - skin = new QPixmap(image.transformed(matrix)); + QTransform transform; + skin = new QPixmap(image.transformed(transform.rotate(degree))); centeralRect = QRect( - centeralRect0.topLeft(), matrix.mapRect(centeralRect0).size()); + centeralRect0.topLeft(), transform.mapRect(centeralRect0).size()); } QImage SkinPainter::getSkinImage() const -- cgit v1.2.3 From 83b7cfac879b3acb26f9469ae31922b9f674ca7c Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Wed, 5 Oct 2016 15:22:40 +0900 Subject: screenshot: fix abnormal exit issue If user close the emulator that have opened screenshot dialog, the emulator becomes abnormal termination. Change-Id: I0da1eac81ed575c8e1b13270246158a254ea4813 Signed-off-by: Jinhyung Jo --- tizen/src/ui/menu/screenshotdialog.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tizen/src/ui/menu/screenshotdialog.cpp b/tizen/src/ui/menu/screenshotdialog.cpp index 09b2759bbc..42505d07ae 100644 --- a/tizen/src/ui/menu/screenshotdialog.cpp +++ b/tizen/src/ui/menu/screenshotdialog.cpp @@ -275,6 +275,4 @@ void ScreenShotDialog::showEvent(QShowEvent *event) ScreenShotDialog::~ScreenShotDialog() { qDebug("destroy screenshot dialog"); - - win->getPopupMenu()->screenshotDialog = NULL; } -- cgit v1.2.3 From 0326aed1c0adfa30a7ce647c1d43711a61d0b055 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Wed, 5 Oct 2016 17:12:21 +0900 Subject: display: remove Qt::AA_X11InitThreads attribute The Qt::AA_X11InitThreads attribute is obsolete and has no effect. Change-Id: I6b0373b08e80b056f7f2a49700f4e07ade366a42 Signed-off-by: Jinhyung Jo --- tizen/src/ui/qt5_supplement.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tizen/src/ui/qt5_supplement.cpp b/tizen/src/ui/qt5_supplement.cpp index 00dec85f97..81202fe124 100644 --- a/tizen/src/ui/qt5_supplement.cpp +++ b/tizen/src/ui/qt5_supplement.cpp @@ -455,17 +455,6 @@ void qt5_early_prepare(bool isOnscreen) Q_INIT_RESOURCE(resource); -#ifdef CONFIG_LINUX - /* QGLWidget threading: Note that under X11 it is necessary to set the - * Qt::AA_X11InitThreads application attribute to make the X11 library - * and GLX calls thread safe, otherwise the above scenarios will fail. */ - - /* Calls XInitThreads() as part of the QApplication construction in order - * to make Xlib calls thread-safe. This attribute must be set before - * QApplication is constructed. */ - QCoreApplication::setAttribute(Qt::AA_X11InitThreads); -#endif - qt5App = new QApplication(argc, argv); /* add the path in the application's main() function, right after the -- cgit v1.2.3 From 1e884dfd8d10ad3c5cbd415467c1723b1e37c0f8 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Tue, 11 Oct 2016 20:06:06 +0900 Subject: util: modify backtrace feature for Windows integrate the 32-bit & 64-bit implementation Change-Id: I7540eeec080ba7fb3f10dcbba663dc4d677b8db9 Signed-off-by: Jinhyung Jo Signed-off-by: Sooyoung Ha --- tizen/src/util/error_handler.c | 153 ++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 92 deletions(-) diff --git a/tizen/src/util/error_handler.c b/tizen/src/util/error_handler.c index 5a41b054ea..959594e83c 100644 --- a/tizen/src/util/error_handler.c +++ b/tizen/src/util/error_handler.c @@ -67,95 +67,30 @@ void enable_print_backtrace_at_normal_exit(void) #ifdef CONFIG_WIN32 static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; -/* Windows 32 bit */ -#ifndef _WIN64 -struct frame_layout { - void *pNext; - void *pReturnAddr; -}; - -static HMODULE get_module_handle(void *dwAddress) -{ - MEMORY_BASIC_INFORMATION Buffer; - return VirtualQuery((LPCVOID)dwAddress, &Buffer, sizeof(Buffer)) - ? (HMODULE)Buffer.AllocationBase : (HMODULE)0; -} - +/* The MSDN says as followed in "Updated Platform Support" page, + (https://msdn.microsoft.com/en-us/library/windows/desktop/ + ms681408(v=vs.85).aspx) + "Where necessary, the DbgHelp library has been widened to support both 32- + and 64-bit Windows. The original function and structure definitions are + still in DbgHelp.h, but there are also updated versions of these + definitions that are compatible with 64-bit Windows. If you use the updated + functions in your code, it can be compiled for both 32- and 64-bit Windows. + Your code will also be more efficient, since the original functions simply + call the updated functions to perform the work." + However, using the updated functinos does not work on the Windows 32-bit. + IMHO, in the MinGW cross compile environment rather than the Visual Studio + it does not compile correctly. + Thus, use explicitly. +*/ static void dump_backtrace(void *ptr) { - int nCount; - void *pTopFrame; - struct frame_layout currentFrame; - struct frame_layout *pCurrentFrame; - - char module_buf[1024]; - HMODULE hModule; - - PCONTEXT pContext = ptr; - if (!pContext) { - __asm__ __volatile__ ("movl %%ebp, %0" : "=m" (pTopFrame)); - } else { - pTopFrame = (void *)((PCONTEXT)pContext)->Ebp; - } - - if (pTopFrame == NULL) { - LOG_INFO("ebp is null, skip this for now\n"); - return ; - } - - nCount = 0; - currentFrame.pNext = ((struct frame_layout *)pTopFrame)->pNext; - currentFrame.pReturnAddr = ((struct frame_layout *)pTopFrame)->pReturnAddr; - pCurrentFrame = (struct frame_layout *)pTopFrame; - - if (pContext) { - memset(module_buf, 0, sizeof(module_buf)); - hModule = get_module_handle((void *)((PCONTEXT)pContext)->Eip); - if (hModule) { - if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) { - memset(module_buf, 0, sizeof(module_buf)); - } - } - LOG_SEVERE("#%04d 0x%08x from %s\n", - nCount, ((PCONTEXT)pContext)->Eip, module_buf); - nCount++; - } - - while (1) { - if (((void *)pCurrentFrame < pTopFrame) - || ((void *)pCurrentFrame >= (void *)0xC0000000) - || !currentFrame.pReturnAddr) { - break; - } - - memset(module_buf, 0, sizeof(module_buf)); - hModule = get_module_handle(currentFrame.pReturnAddr); - if (hModule) { - if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) { - memset(module_buf, 0, sizeof(module_buf)); - } - } - LOG_SEVERE("#%04d 0x%08x from %s\n", - nCount, currentFrame.pReturnAddr, module_buf); - - if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext, - (void *)¤tFrame, sizeof(struct frame_layout), NULL)) { - break; - } - pCurrentFrame = (struct frame_layout *)pCurrentFrame->pNext; - - nCount++; - } -} - +#ifdef _WIN64 + STACKFRAME64 frame; #else - -/* Windows 64 bit */ -static void dump_backtrace(void *ptr) -{ + STACKFRAME frame; +#endif int i; DWORD image; - STACKFRAME64 frame; CONTEXT context; HANDLE hProcess = GetCurrentProcess(); HANDLE hThread = GetCurrentThread(); @@ -168,9 +103,9 @@ static void dump_backtrace(void *ptr) CopyMemory(&context, ptr, sizeof(CONTEXT)); } - SymSetOptions(SYMOPT_LOAD_LINES); SymInitialize(hProcess, NULL, TRUE); +#ifdef _WIN64 ZeroMemory(&frame, sizeof(STACKFRAME64)); image = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Offset = context.Rip; @@ -179,48 +114,82 @@ static void dump_backtrace(void *ptr) frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Rsp; frame.AddrStack.Mode = AddrModeFlat; +#else + ZeroMemory(&frame, sizeof(STACKFRAME)); + image = IMAGE_FILE_MACHINE_I386; + frame.AddrPC.Offset = context.Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.AddrStack.Mode = AddrModeFlat; +#endif i = 0; while (1) { +#ifdef _WIN64 BOOL result = StackWalk64(image, hProcess, hThread, &frame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL); +#else + BOOL result = StackWalk(image, hProcess, hThread, + &frame, &context, NULL, + SymFunctionTableAccess, + SymGetModuleBase, NULL); +#endif if (!result) { break; } - TCHAR buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + TCHAR buffer[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME - 1) * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; DWORD64 displacement = 0; TCHAR pFileName[MAX_PATH] = {0, }; +#ifdef _WIN64 DWORD64 dwBase = SymGetModuleBase64(hProcess, frame.AddrPC.Offset); +#else + DWORD dwBase = SymGetModuleBase(hProcess, frame.AddrPC.Offset); +#endif if (dwBase) { HMODULE hModule = (HMODULE)((DWORD_PTR)dwBase); if (!GetModuleFileNameA(hModule, pFileName, MAX_PATH)) { snprintf(pFileName, MAX_PATH, "Unknown Module"); } } + /* TODO: take the symbols for the static functions + without import .pdb */ if (SymFromAddr(hProcess, frame.AddrPC.Offset, &displacement, pSymbol)) { - LOG_SEVERE("#%04d 0x%016x in %s from %s\n", +#ifdef _WIN64 + LOG_INFO("#%04d 0x%016I64x in %s from %s\n", +#else + LOG_INFO("#%04d 0x%08x in %s from %s\n", +#endif i, frame.AddrPC.Offset, pSymbol->Name, pFileName); } else { - LOG_SEVERE("#%04d 0x%016x in ???????? from %s\n", +#ifdef _WIN64 + LOG_INFO("#%04d 0x%016I64x in ???????? from %s\n", +#else + LOG_INFO("#%04d 0x%08x in ???????? from %s\n", +#endif i, frame.AddrPC.Offset, pFileName); } i++; } SymCleanup(hProcess); } -#endif static WINAPI LONG maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pException) { - LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%016x]\n", +#ifdef _WIN64 + LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%016I64x]\n", +#else + LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%08x]\n", +#endif pException->ExceptionRecord->ExceptionCode, pException->ExceptionRecord->ExceptionAddress); @@ -250,9 +219,9 @@ static void dump_backtrace(void *ptr) int ndepth = backtrace(trace, 1024); char **syms = backtrace_symbols(trace, ndepth); - LOG_SEVERE("Backtrace depth is %d\n", ndepth); + LOG_INFO("Backtrace depth is %d\n", ndepth); for (i = 0; i < ndepth; i++) { - LOG_SEVERE("#%04d %s\n", i, syms[i]); + LOG_INFO("#%04d %s\n", i, syms[i]); } free(syms); } -- cgit v1.2.3 From 98046ab6c35ce83999c9a18811a4e40f307bc0f1 Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Thu, 13 Oct 2016 22:18:30 +0900 Subject: emulator: respawning when elevated In order to prevent potential elevation of privilege attack, lower privilege processes can't interfere with higher privilege on Windows. Emulator is usually launched by emulator manager that has high integrity level, then drag-and-drop from Explorer (mostly medium integrity level) does not work. So, when emulator process has elevated integrity level, we try to respawn emulator with medium integrity level. Change-Id: I17f29e411252758098304ba25b60219d07aa0d7c Signed-off-by: Munkyu Im Signed-off-by: SeokYeon Hwang --- tizen/src/emulator.c | 14 +++- tizen/src/util/osutil-win32.c | 168 +++++++++++++++++++++++++++++++++++------- tizen/src/util/osutil.h | 1 + version.rc | 4 + 4 files changed, 159 insertions(+), 28 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 940e0d1409..94b0fcc2e9 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -47,7 +47,10 @@ #include "ecs/ecs.h" #include "util/device_hotplug.h" #include "util/exported_strings.h" - +#ifdef CONFIG_WIN32 +#include +#include +#endif #ifdef CONFIG_QT #include #endif @@ -346,6 +349,15 @@ int main(int argc, char *argv[], char **envp) init_error_handler(); return emulator_main(argc, argv, envp); } +#elif defined (CONFIG_WIN32) +int main(int argc, char *argv[]) +{ + if (!check_integrity_level_and_respawn()) { + init_error_handler(); + return emulator_main(argc, argv, NULL); + } + return 0; +} #else int main(int argc, char *argv[]) { diff --git a/tizen/src/util/osutil-win32.c b/tizen/src/util/osutil-win32.c index bced9f8e7a..f733aedc67 100644 --- a/tizen/src/util/osutil-win32.c +++ b/tizen/src/util/osutil-win32.c @@ -96,12 +96,12 @@ void make_vm_lock_os(gchar *vms_path) GetLastError()); } lock_file = CreateFile(lock_filename, - GENERIC_READ | GENERIC_WRITE, - 0, // No share - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, - NULL); + GENERIC_READ | GENERIC_WRITE, + 0, // No share + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); if (lock_file == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); // On Windows, the file opened by CreateFile has exclusive lock @@ -202,12 +202,12 @@ bool make_sdcard_lock_os(char *sdcard) fname = g_strdup_printf("%s.lck", sdcard); h = CreateFile(fname, - GENERIC_READ, - 0, // No share - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, - NULL); + GENERIC_READ, + 0, // No share + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); if (h == INVALID_HANDLE_VALUE) { LOG_WARNING("Failed to CreateFile a sdcard lock file: %d\n", @@ -278,11 +278,11 @@ void get_java_path_win32(const char **java_path) /* Opens above key to query the current version */ res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - strKey, - 0, - KEY_QUERY_VALUE | - MY_KEY_WOW64_64KEY, - &hKey); + strKey, + 0, + KEY_QUERY_VALUE | + MY_KEY_WOW64_64KEY, + &hKey); if (res != ERROR_SUCCESS) { LOG_WARNING("Java Runtime Environment key not found\n"); goto javahome_not_found; @@ -290,11 +290,11 @@ void get_java_path_win32(const char **java_path) /* Queries for the current version */ res = RegQueryValueEx(hKey, - "CurrentVersion", - NULL, - NULL, - (LPBYTE)strVersion, - &dwBufLen); + "CurrentVersion", + NULL, + NULL, + (LPBYTE)strVersion, + &dwBufLen); RegCloseKey(hKey); if (res != ERROR_SUCCESS) { LOG_WARNING("JRE CurrentVersion not found\n"); @@ -307,11 +307,11 @@ void get_java_path_win32(const char **java_path) /* Opens above key to query the JavaHome */ res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - strKey, - 0, - KEY_QUERY_VALUE | - MY_KEY_WOW64_64KEY, - &hKey); + strKey, + 0, + KEY_QUERY_VALUE | + MY_KEY_WOW64_64KEY, + &hKey); if (res == ERROR_SUCCESS) { /* Queries for the JavaHome */ dwBufLen = PATH_MAX; @@ -337,3 +337,117 @@ javahome_not_found: *java_path = current_java_path; } + +bool check_integrity_level_and_respawn(void) +{ + BOOL bResult = false; + HANDLE hToken = NULL; + HANDLE hNewToken = NULL; + PSID pIntegritySid = NULL; + TOKEN_MANDATORY_LABEL TIL = { { 0, }, }; + PTOKEN_MANDATORY_LABEL pTIL = NULL; + PROCESS_INFORMATION ProcInfo = { 0, }; + STARTUPINFO StartupInfo = { 0, }; + SID_IDENTIFIER_AUTHORITY + MLAuthority = { SECURITY_MANDATORY_LABEL_AUTHORITY }; + DWORD dwIntegrityLevel, dwSize = 0; + + if(!OpenProcessToken(GetCurrentProcess(), + TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | + TOKEN_ASSIGN_PRIMARY, &hToken)) { + LOG_WARNING("OpenProcessToken Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) { + DWORD dwResult = GetLastError(); + if (dwResult != ERROR_INSUFFICIENT_BUFFER) { + LOG_WARNING("GetTokenInformation Error %lu\n", dwResult); + goto CleanExit; + } + } + + pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwSize); + if (!pTIL) { + LOG_WARNING("LocalAlloc Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, + dwSize, &dwSize)) { + LOG_WARNING("GetTokenInformation Error %lu\n", GetLastError()); + goto CleanExit; + } + + dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, + (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1)); + + if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && + dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { + // We have medium integrity level. So keep going on. + goto CleanExit; + } + + LOG_INFO("Running with elevated integrity level. Try to respawn.\n"); + + if (!DuplicateTokenEx(hToken, 0, NULL, SecurityImpersonation, + TokenPrimary, &hNewToken)) { + LOG_WARNING("DuplicateTokenEx Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!AllocateAndInitializeSid(&MLAuthority, 1, SECURITY_MANDATORY_MEDIUM_RID, + 0, 0, 0, 0, 0, 0, 0, &pIntegritySid)) { + LOG_WARNING("AllocateAndInitializeSid Error %lu\n", GetLastError()); + goto CleanExit; + } + + TIL.Label.Attributes = SE_GROUP_INTEGRITY; + TIL.Label.Sid = pIntegritySid; + + if (!SetTokenInformation(hNewToken, + TokenIntegrityLevel, + &TIL, + sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid))) { + LOG_WARNING("SetTokenInformation Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!CreateProcessAsUser(hNewToken, 0, GetCommandLine(), + NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcInfo)) { + LOG_WARNING( "CreateProcessAsUser Error %lu\n", GetLastError()); + goto CleanExit; + } + + LOG_INFO("Respawning success. Waiting for child process.\n"); + bResult = true; + WaitForSingleObject(ProcInfo.hProcess, INFINITE); + +CleanExit: + if (ProcInfo.hProcess != NULL) { + CloseHandle(ProcInfo.hProcess); + } + + if (ProcInfo.hThread != NULL) { + CloseHandle(ProcInfo.hThread); + } + + if (pIntegritySid != NULL) { + LocalFree(pIntegritySid); + } + + if (hNewToken != NULL) { + CloseHandle(hNewToken); + } + + if (hToken != NULL) { + CloseHandle(hToken); + } + + if (pTIL != NULL) { + LocalFree(pTIL); + } + + return bResult; +} + diff --git a/tizen/src/util/osutil.h b/tizen/src/util/osutil.h index 7dc9fea2f4..d478155f28 100644 --- a/tizen/src/util/osutil.h +++ b/tizen/src/util/osutil.h @@ -57,6 +57,7 @@ bool make_sdcard_lock_posix(char *sdcard); int remove_sdcard_lock_posix(char *sdcard); #else void get_java_path_win32(const char **java_path); +bool check_integrity_level_and_respawn(void); #endif void set_bin_path_os(char const *const); diff --git a/version.rc b/version.rc index c7922d5200..86455bb873 100644 --- a/version.rc +++ b/version.rc @@ -14,7 +14,11 @@ FILESUBTYPE VFT2_UNKNOWN BLOCK "040904E4" { VALUE "CompanyName", "http://www.qemu-project.org" +#ifdef CONFIG_MARU + VALUE "FileDescription", "Tizen Emulator" +#else VALUE "FileDescription", "QEMU machine emulators and tools" +#endif VALUE "FileVersion", QEMU_VERSION VALUE "LegalCopyright", "Copyright various authors. Released under the GNU General Public License." VALUE "LegalTrademarks", "QEMU is a trademark of Fabrice Bellard." -- cgit v1.2.3 From a9021cc59242785b0685889c07b9861b763696f3 Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Thu, 13 Oct 2016 22:09:18 +0900 Subject: package: update version(2.6.8) Change-Id: I53e6e26d189819c39611b321f1fe6d7448e7aa2c Signed-off-by: Sooyoung Ha --- package/changelog | 6 ++++++ package/pkginfo.manifest | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index 69dcabafb6..29f91a297f 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,9 @@ +* 2.6.8 +- change QMatrix to QTransform +- fix abnormal exit issue +- remove Qt::AA_X11InitThreads attribute +- modify backtrace feature for Windows +== Sooyoung Ha 2016-10-13 * 2.6.7 - display: Revert "display: move display functionality to Qt5 GUI" for AMD gpu issue - display: fix display rotation failure diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index 242023bf8d..79d008349e 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.7 +Version: 2.6.8 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From 0fa0698937d3fd10b8d6353c22260e870ffb8df9 Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Tue, 25 Oct 2016 13:53:16 +0900 Subject: emulator: tighten validation for conf file Change-Id: Iaae354e0815a568a7685d430959e60f8e5b424b9 Signed-off-by: SeokYeon Hwang --- tizen/src/emulator_options.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tizen/src/emulator_options.c b/tizen/src/emulator_options.c index 209bbabd94..03ea020bb5 100644 --- a/tizen/src/emulator_options.c +++ b/tizen/src/emulator_options.c @@ -220,7 +220,12 @@ bool load_conf(const char * const conf) assert(!!conf); filename = g_strdup(conf); - file = fopen(filename, "r"); + if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + fprintf(stderr, + "Profile configuration file [%s] is invalid.\n", filename); + return false; + } + file = g_fopen(filename, "r"); if (!file) { fprintf(stderr, "Profile configuration file [%s] is not found.\n", filename); -- cgit v1.2.3 From c51bd7f11ee4d81e082bdeb89b841cecadbdbeb5 Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Tue, 25 Oct 2016 18:02:25 +0900 Subject: net: fix checking tap device nic[i]->peer value is null currently. Change-Id: I4a4d4fcea1687ed1e924569b7321ef19f686c09f Signed-off-by: Munkyu Im --- tizen/src/emul_state.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index 101bff6885..adb0b37c44 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -549,10 +549,7 @@ bool is_netclient_tap_attached(void) NET_CLIENT_OPTIONS_KIND_NIC, MAX_QUEUE_NUM); for (i = 0; i < queues; ++i) { - if (ncs[i]->info->type == NET_CLIENT_OPTIONS_KIND_TAP && - (ncs[i]->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC || - // for legacy -net option. - ncs[i]->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT)) { + if (ncs[i]->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { return true; } } -- cgit v1.2.3 From cac18e0fa5d8e678d95a640c5bb213259be578de Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Tue, 25 Oct 2016 18:32:22 +0900 Subject: package: update version (2.6.9) Change-Id: Icfae54729c6e7b68e65f3933c790c936af6eca35 Signed-off-by: Munkyu Im --- package/changelog | 3 +++ package/pkginfo.manifest | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index 29f91a297f..c3978c116c 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,6 @@ +* 2.6.9 +- fix checking tap device +== Munkyu Im 2016-10-25 * 2.6.8 - change QMatrix to QTransform - fix abnormal exit issue diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index 79d008349e..06e25d859b 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.8 +Version: 2.6.9 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From 928cb68b0b257eeb34a6555ffe1882fddf975c59 Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Tue, 25 Oct 2016 11:21:23 +0900 Subject: ui: move Qt5 clean-up codes inside main() Qt5 resource clean-up in exit handler cause several unexpected behaviors include segmentation fault. So it is moved inside main() function, then clean-up is done before main function exit. Change-Id: I4f53d531261f376de869e9c286bd700f9acbf726 Signed-off-by: SeokYeon Hwang --- tizen/src/ui/qt5.c | 4 ++-- tizen/src/ui/qt5.h | 1 + tizen/src/ui/rotaryview.cpp | 2 -- vl.c | 11 +++++++++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tizen/src/ui/qt5.c b/tizen/src/ui/qt5.c index 561fe9c492..0b19be65bd 100644 --- a/tizen/src/ui/qt5.c +++ b/tizen/src/ui/qt5.c @@ -156,7 +156,8 @@ void maru_early_qt5_display_init(bool isOnscreen) } } -static void maru_qt5_display_fini(void) +// should be called before exit main() +void maru_qt5_display_fini(void) { if (qt5_console) { g_free(qt5_console); @@ -212,7 +213,6 @@ void maru_qt5_display_init(DisplayState *ds, int full_screen) if (full_screen) { /* TODO */ } - atexit(maru_qt5_display_fini); /* TODO mouse_mode_notifier.notify = qt2_mouse_mode_change; diff --git a/tizen/src/ui/qt5.h b/tizen/src/ui/qt5.h index d5e5de1a3d..226ea3759d 100644 --- a/tizen/src/ui/qt5.h +++ b/tizen/src/ui/qt5.h @@ -36,6 +36,7 @@ void maru_early_qt5_display_init(bool isOnscreen); void maru_qt5_display_init(DisplayState *ds, int full_screen); +void maru_qt5_display_fini(void); void set_display_pixel_density(int dpi); int get_display_pixel_density(void); diff --git a/tizen/src/ui/rotaryview.cpp b/tizen/src/ui/rotaryview.cpp index 3297f3fc34..fdb6816d7f 100644 --- a/tizen/src/ui/rotaryview.cpp +++ b/tizen/src/ui/rotaryview.cpp @@ -193,6 +193,4 @@ RotaryView::~RotaryView() qDebug("destroy rotary view"); timer->stop(); - - scene()->clear(); } diff --git a/vl.c b/vl.c index d8b5697e93..2b9a29c1b4 100644 --- a/vl.c +++ b/vl.c @@ -4884,5 +4884,16 @@ int main(int argc, char **argv, char **envp) tpm_cleanup(); #endif +#if defined(CONFIG_MARU) && defined(CONFIG_QT) + switch (display_type) { + case DT_MARU_QT_ONSCREEN: + case DT_MARU_QT_OFFSCREEN: + maru_qt5_display_fini(); + break; + default: + break; + } +#endif + return 0; } -- cgit v1.2.3 From 0a6e2d1eacbaef2421a559e5b98d09d5cbea1d42 Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Tue, 25 Oct 2016 11:27:12 +0900 Subject: ui: reuse resource when it is reusable Some resources are unique and reusable. So we do not "free" and "new" them repeatedly. Change-Id: I2c1c0c15b9162a9f0eed49ed209e7073a102d821 Signed-off-by: SeokYeon Hwang --- tizen/src/ui/displaybase.cpp | 32 ++++++++++----------- tizen/src/ui/mainwindow.cpp | 54 +++++++++++++++++++++++------------ tizen/src/ui/mainwindow.h | 6 +++- tizen/src/ui/menu/contextmenu.cpp | 39 ++++--------------------- tizen/src/ui/menu/contextmenu.h | 4 --- tizen/src/ui/menu/sdbhelper.cpp | 1 + tizen/src/ui/menu/sdbhelperthread.cpp | 22 ++------------ tizen/src/ui/menu/sdbhelperthread.h | 3 -- tizen/src/ui/movingwidget.cpp | 1 - 9 files changed, 65 insertions(+), 97 deletions(-) diff --git a/tizen/src/ui/displaybase.cpp b/tizen/src/ui/displaybase.cpp index 80b8b9b9e1..1daff0677c 100644 --- a/tizen/src/ui/displaybase.cpp +++ b/tizen/src/ui/displaybase.cpp @@ -110,21 +110,22 @@ void DisplayBase::showOffGuideImg() { offGuideShown = true; - offGuide = new QLabel(win); - offGuide->setAttribute(Qt::WA_DeleteOnClose); - offGuide->setStyleSheet( - "background-color: black; border-style: none;"); - offGuide->setAlignment(Qt::AlignCenter); - - offGuide->setGeometry(getGeometry()); - offGuide->setPixmap(offGuideImg.scaled( - getGeometry().width(), getGeometry().height(), - Qt::KeepAspectRatio, Qt::SmoothTransformation)); - - if (maskImage.size() != QSize(0, 0)) { - offGuide->setMask(maskImage.scaled( - maskImage.width() * scaleFactor, - maskImage.height() * scaleFactor).mask()); + if (!offGuide) { + offGuide = new QLabel(win); + offGuide->setStyleSheet( + "background-color: black; border-style: none;"); + offGuide->setAlignment(Qt::AlignCenter); + + offGuide->setGeometry(getGeometry()); + offGuide->setPixmap(offGuideImg.scaled( + getGeometry().width(), getGeometry().height(), + Qt::KeepAspectRatio, Qt::SmoothTransformation)); + + if (maskImage.size() != QSize(0, 0)) { + offGuide->setMask(maskImage.scaled( + maskImage.width() * scaleFactor, + maskImage.height() * scaleFactor).mask()); + } } offGuide->show(); @@ -134,7 +135,6 @@ void DisplayBase::hideOffGuideImg() { if (offGuide != NULL) { offGuide->close(); - offGuide = NULL; } offGuideShown = false; diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp index 04936100a4..54f441d46b 100644 --- a/tizen/src/ui/mainwindow.cpp +++ b/tizen/src/ui/mainwindow.cpp @@ -67,6 +67,8 @@ MainWindow::MainWindow(UiInformation *uiInfo, QWidget *parent) : this->captureRequestData = NULL; this->movingWidget = NULL; + this->isMovingMode = false; + /* windowing */ setWindowTitle(EMULATOR_TITLE); setWindowIcon(QIcon(":/icons/emulator_icon.ico")); @@ -561,12 +563,17 @@ void MainWindow::turnOnMovingMode() { qDebug("enter the moving mode"); + if (isMovingMode) { + return; + } + getDisplay()->turnOnMovingMode(); - if (isMovingMode() == false) { + if (movingWidget == NULL) { movingWidget = new MovingWidget(this); } + isMovingMode = true; movingWidget->show(); } @@ -574,17 +581,14 @@ void MainWindow::turnOffMovingMode() { qDebug("leave the moving mode"); - getDisplay()->turnOffMovingMode(); - - if (isMovingMode() == true) { - movingWidget->close(); - movingWidget = NULL; + if (!isMovingMode) { + return; } -} -bool MainWindow::isMovingMode() -{ - return (movingWidget != NULL); + getDisplay()->turnOffMovingMode(); + + movingWidget->close(); + isMovingMode = false; } /* override */ @@ -604,17 +608,29 @@ void MainWindow::closeEvent(QCloseEvent *event) } } -MainWindow::~MainWindow() +QMessageBox *MainWindow::showMsgBox( + QMessageBox::Icon iconType, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { - qDebug("destroy main window"); + qWarning() << text; - if (popupMenu) { - delete popupMenu; - popupMenu = NULL; + QMessageBox *msgBox = new QMessageBox(iconType, + EMULATOR_TITLE, text, buttons, this); + if (defaultButton != QMessageBox::NoButton) { + msgBox->setDefaultButton(defaultButton); } + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->show(); /* non-blocking */ - if (rotary != NULL) { - delete rotary; - rotary = NULL; - } +#ifdef CONFIG_LINUX + popupMenu->slotOnTop(getUiState()->isOnTop()); +#endif + + return msgBox; +} + +MainWindow::~MainWindow() +{ + qDebug("destroy main window"); } diff --git a/tizen/src/ui/mainwindow.h b/tizen/src/ui/mainwindow.h index b83ff7ea65..cd90e7395f 100644 --- a/tizen/src/ui/mainwindow.h +++ b/tizen/src/ui/mainwindow.h @@ -53,6 +53,8 @@ class MainWindow : public QWidget Q_OBJECT public: + bool isMovingMode; + explicit MainWindow(UiInformation *uiInfo, QWidget *parent = 0); ~MainWindow(); @@ -64,6 +66,9 @@ public: DisplayBase *getDisplay(); KeyboardShortcut *getKeyboardShortcut(); QLabel *getScreenWidget(); + QMessageBox *showMsgBox(QMessageBox::Icon iconType, const QString &text, + QMessageBox::StandardButtons buttons = QMessageBox::NoButton, + QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); void updateDisplayTransform(); void switchForm(int angle); @@ -84,7 +89,6 @@ public: void turnOnMovingMode(); void turnOffMovingMode(); - bool isMovingMode(); public slots: void slotContextMenu(const QPoint &pos); diff --git a/tizen/src/ui/menu/contextmenu.cpp b/tizen/src/ui/menu/contextmenu.cpp index 264847c4e3..0c0c348f9d 100644 --- a/tizen/src/ui/menu/contextmenu.cpp +++ b/tizen/src/ui/menu/contextmenu.cpp @@ -925,12 +925,12 @@ void ContextMenu::slotShell() QFileInfo sdbFileInfo(sdbPath); if (sdbFileInfo.exists() == false) { - showMsgBox(QMessageBox::Warning, MSG_SDB_NOT_EXIST + sdbPath); + parent->showMsgBox(QMessageBox::Warning, MSG_SDB_NOT_EXIST + sdbPath); return; } if (!is_sdb_daemon_initialized()) { - showMsgBox(QMessageBox::Warning, MSG_SDB_NOT_READY); + parent->showMsgBox(QMessageBox::Warning, MSG_SDB_NOT_READY); return; } @@ -971,7 +971,7 @@ void ContextMenu::launchControlPanel(QString& command, try { QProcess::startDetached(command, arguments, workingDir); } catch (QString &error) { - showMsgBox(QMessageBox::Warning, MSG_INVALID_ECP_OPEN + error); + parent->showMsgBox(QMessageBox::Warning, MSG_INVALID_ECP_OPEN + error); return; } #else @@ -997,7 +997,7 @@ void ContextMenu::launchControlPanel(QString& command, QString error = QString::number(GetLastError()); qWarning() << qPrintable(QString("error occured during launching \ ECP: ") + error); - showMsgBox(QMessageBox::Warning, MSG_INVALID_ECP_OPEN + error); + parent->showMsgBox(QMessageBox::Warning, MSG_INVALID_ECP_OPEN + error); } CloseHandle(pinfo.hThread); @@ -1069,7 +1069,7 @@ void ContextMenu::slotControlPanel() command = QString::fromLocal8Bit(path); } else { // can not enter here... - showMsgBox(QMessageBox::Warning, MSG_INVALID_JAVA_PATH); + parent->showMsgBox(QMessageBox::Warning, MSG_INVALID_JAVA_PATH); return; } @@ -1096,7 +1096,7 @@ void ContextMenu::slotControlPanel() } // we can not launch ControlPanel - showMsgBox(QMessageBox::Warning, MSG_ECP_NOT_EXIST); + parent->showMsgBox(QMessageBox::Warning, MSG_ECP_NOT_EXIST); return; } @@ -1212,37 +1212,10 @@ QSignalMapper *ContextMenu::getControllerMapper() return controllerMapper; } -QMessageBox *ContextMenu::showMsgBox( - QMessageBox::Icon iconType, const QString &text, - QMessageBox::StandardButtons buttons, - QMessageBox::StandardButton defaultButton) -{ - qWarning() << text; - - QMessageBox *msgBox = new QMessageBox(iconType, - EMULATOR_TITLE, text, buttons, parent); - if (defaultButton != QMessageBox::NoButton) { - msgBox->setDefaultButton(defaultButton); - } - msgBox->setAttribute(Qt::WA_DeleteOnClose); - msgBox->show(); /* non-blocking */ - -#ifdef CONFIG_LINUX - slotOnTop(parent->getUiState()->isOnTop()); -#endif - - return msgBox; -} - ContextMenu::~ContextMenu() { qDebug("destroy menu"); - if (infoDialog) { - delete infoDialog; - infoDialog = NULL; - } - delete sdbHelper; longPressTimer->stop(); diff --git a/tizen/src/ui/menu/contextmenu.h b/tizen/src/ui/menu/contextmenu.h index 88370a483d..f8518de322 100644 --- a/tizen/src/ui/menu/contextmenu.h +++ b/tizen/src/ui/menu/contextmenu.h @@ -128,10 +128,6 @@ private: const QString &text, QShortcut *shortcut, const char *slot); void attachShortcut(QAction *action, QShortcut *shortcut, const char *slot); - QMessageBox *showMsgBox(QMessageBox::Icon iconType, const QString &text, - QMessageBox::StandardButtons buttons = QMessageBox::NoButton, - QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); - MainWindow *parent; QString vmName; DetailedInfoDialog *infoDialog; diff --git a/tizen/src/ui/menu/sdbhelper.cpp b/tizen/src/ui/menu/sdbhelper.cpp index 742966ffb2..c1da058892 100644 --- a/tizen/src/ui/menu/sdbhelper.cpp +++ b/tizen/src/ui/menu/sdbhelper.cpp @@ -30,6 +30,7 @@ #include "config-host.h" #include "mainwindow.h" +#include "displaybase.h" #include "sdbhelper.h" #include "sdbhelperthread.h" #include "resource/ui_strings.h" diff --git a/tizen/src/ui/menu/sdbhelperthread.cpp b/tizen/src/ui/menu/sdbhelperthread.cpp index 2c0389ec6f..dec4171205 100644 --- a/tizen/src/ui/menu/sdbhelperthread.cpp +++ b/tizen/src/ui/menu/sdbhelperthread.cpp @@ -28,6 +28,7 @@ */ #include "sdbhelperthread.h" +#include "mainwindow.h" #include "sdbhelper.h" #include "displaybase.h" #include "resource/ui_strings.h" @@ -82,24 +83,5 @@ void SdbHelperThread::handleErrorOccured(QString errString, int exitCode) { qDebug() << "exitcode: " << exitCode; //FIXME: (sdb) cannot returns exit code like "no space left" - showMsgBox(QMessageBox::Warning, MSG_SDB_FAILED_PROCESSING + errString); -} - -QMessageBox *SdbHelperThread::showMsgBox( - QMessageBox::Icon iconType, const QString &text, - QMessageBox::StandardButtons buttons, - QMessageBox::StandardButton defaultButton) -{ - qWarning() << text; - - QMessageBox *msgBox = new QMessageBox(iconType, - EMULATOR_TITLE, text, buttons, (QWidget *)parent->getMainWindow()); - if (defaultButton != QMessageBox::NoButton) { - msgBox->setDefaultButton(defaultButton); - } - msgBox->setAttribute(Qt::WA_DeleteOnClose); - msgBox->setModal(false); - msgBox->show(); /* non-blocking */ - - return msgBox; + ((MainWindow *)parent->getMainWindow())->showMsgBox(QMessageBox::Warning, MSG_SDB_FAILED_PROCESSING + errString); } diff --git a/tizen/src/ui/menu/sdbhelperthread.h b/tizen/src/ui/menu/sdbhelperthread.h index 5cdfcfc389..162ce1813a 100644 --- a/tizen/src/ui/menu/sdbhelperthread.h +++ b/tizen/src/ui/menu/sdbhelperthread.h @@ -53,9 +53,6 @@ private: int command; QString errorMsg; QString outMsg; - QMessageBox *showMsgBox(QMessageBox::Icon iconType, const QString &text, - QMessageBox::StandardButtons buttons = QMessageBox::NoButton, - QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); signals: void errorOccured(QString errString, int exitCode); diff --git a/tizen/src/ui/movingwidget.cpp b/tizen/src/ui/movingwidget.cpp index e3daff486a..669da8fe36 100644 --- a/tizen/src/ui/movingwidget.cpp +++ b/tizen/src/ui/movingwidget.cpp @@ -43,7 +43,6 @@ MovingWidget::MovingWidget(QWidget *parent) : QWidget(parent) setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_TranslucentBackground); - setAttribute(Qt::WA_DeleteOnClose); resize(win->size()); qDebug() << "moving widget size:" << win->size(); -- cgit v1.2.3 From 8be043116387c9dbe1154e7819feb922404b91dc Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Tue, 1 Nov 2016 09:58:25 +0900 Subject: emulator: "--conf" should be first argument "--conf" should be first argument. Do not proceed if it is not. Print more kind usage if arguments are not valid. Change-Id: Ifb62075f3b130974b4a54d5900289c66c772dabd Signed-off-by: SeokYeon Hwang --- tizen/src/emulator.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 94b0fcc2e9..e4a170754b 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -285,7 +285,10 @@ static int emulator_main(int argc, char *argv[], char **envp) set_variable(argv[optind - 1], argv[optind], true); break; case 'c': - launch_conf_file = g_strdup(optarg); + if (optind == 3) { + // "--conf" should be a first argument + launch_conf_file = g_strdup(optarg); + } break; case 'q': c = -1; @@ -297,8 +300,12 @@ static int emulator_main(int argc, char *argv[], char **envp) } if (!launch_conf_file && qemu_arg_index == 0) { - fprintf(stderr, "Usage: %s {-c|--conf} conf_file ...\n", - basename(argv[0])); + char *executable = basename(argv[0]); + fprintf(stderr, "Usage: %s {-c|--conf} conf_file [-- ]...\n" + " %*s [{-q|--qemu} ...]\n", + executable, (int)strlen(executable), ""); + fprintf(stderr, " %s {-q|--qemu} ...\n", + executable); return -1; } -- cgit v1.2.3 From c7d607bb43e8ca008ba8c0dcdc34dc148ae286a0 Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Mon, 24 Oct 2016 15:36:22 +0900 Subject: ecs: handle device capabilities * capability values are set by emulator daemon |-------| |-----| |---------| | emuld | -------> | ECS | --------> | clients | |-------| set |-----| result |---------| * ECS stores the value and send it when ECP requests. |-----| |-----| |---------| | ECP | --------> | ECS | --------> | clients | |-----| request |-----| result |---------| check sensor & nfc device status additionally. Change-Id: Icebefa564f0263afff0f0e1b139335c7c6f2ba3d Signed-off-by: Jinhyung Choi --- tizen/src/ecs/ecs.c | 109 +++++++++++++++++++++++++++++++ tizen/src/ecs/ecs.h | 5 ++ tizen/src/ecs/ecs_msg.c | 2 + tizen/src/ecs/ecs_msg_device.c | 3 + tizen/src/ecs/ecs_msg_injector.c | 4 ++ tizen/src/hw/virtio/maru_virtio_sensor.c | 5 ++ tizen/src/hw/virtio/maru_virtio_sensor.h | 2 + 7 files changed, 130 insertions(+) diff --git a/tizen/src/ecs/ecs.c b/tizen/src/ecs/ecs.c index c77b6c0a55..758579281c 100644 --- a/tizen/src/ecs/ecs.c +++ b/tizen/src/ecs/ecs.c @@ -51,6 +51,9 @@ #include "ecs.h" #include "emul_state.h" +#include "hw/virtio/maru_virtio_sensor.h" +#include "hw/virtio/maru_virtio_nfc.h" + #include "debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, ecs); @@ -77,6 +80,40 @@ static QemuThread ecs_thread_id; static int suspend_state = 1; +static char device_capabilities [16]; + +enum ecs_check_cap_list { + CHECK_CAP_BATTERY = 0, + CHECK_CAP_LOCATION, + CHECK_CAP_NFC, + CHECK_CAP_TELEPHONY, + CHECK_CAP_ACCEL, + CHECK_CAP_GYRO, + CHECK_CAP_GEO, + CHECK_CAP_PROXI, + CHECK_CAP_LIGHT, + CHECK_CAP_PRESSURE, + CHECK_CAP_HEARTRATE, + CHECK_CAP_UV, + CHECK_CAP_PEDO +}; + +static int cap_device_list[] = { + 0x0001, // Battery + 0x0002, // Location + 0x0004, // NFC + 0x0008, // Telephony + 0x0010, // Accelerometer + 0x0020, // Gyroscope + 0x0040, // Magnetometer + 0x0080, // Proximity + 0x0100, // Light + 0x0200, // Pressure + 0x0400, // HeartRate + 0x0800, // Ultraviolet + 0x1000, // Pedometer +}; + void ecs_set_suspend_state(int state) { suspend_state = state; @@ -87,6 +124,78 @@ int ecs_get_suspend_state(void) return suspend_state; } +static void check_sensor_capability(int* capacity) +{ + int sensor_cap = get_sensor_capability(); + if ((sensor_cap & sensor_cap_accel) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_ACCEL]; + } + if ((sensor_cap & sensor_cap_geo) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_GEO]; + } + + if ((sensor_cap & sensor_cap_gyro) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_GYRO]; + } + + if ((sensor_cap & sensor_cap_proxi) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_PROXI]; + } + + if ((sensor_cap & sensor_cap_light) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_LIGHT]; + } + + if ((sensor_cap & sensor_cap_pressure) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_PRESSURE]; + } + + if ((sensor_cap & sensor_cap_uv) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_UV]; + } + + if ((sensor_cap & sensor_cap_hrm) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_HEARTRATE]; + } + + if ((sensor_cap & sensor_cap_pedo) == 0) { + *capacity &= ~cap_device_list[CHECK_CAP_PEDO]; + } +} + +extern VirtIONFC *vio_nfc; +static void check_nfc_capability(int* capacity) +{ + if (!vio_nfc) { + *capacity &= ~cap_device_list[CHECK_CAP_NFC]; + } +} + +void ecs_set_device_capabilities(const char* cap) +{ + int capability = 0; + + memset(device_capabilities, 0, sizeof(device_capabilities)); + + if (cap != NULL) { + capability = atoi(cap); + // check sensor capability + check_sensor_capability(&capability); + // check nfc capability + check_nfc_capability(&capability); + + LOG_INFO("check_sensor_capability: %04x\n", capability); + snprintf(device_capabilities, sizeof(device_capabilities), "%d", capability); + } + + make_send_device_ntf((char*)MSG_TYPE_CAP, MSG_GROUP_STATUS, 0, device_capabilities); +} + +const char* ecs_get_device_capabilities(void) +{ + return device_capabilities; +} + int ecs_write(int fd, const uint8_t *buf, int len) { int ret, remain; diff --git a/tizen/src/ecs/ecs.h b/tizen/src/ecs/ecs.h index 028c2f0675..3458dfaaa5 100644 --- a/tizen/src/ecs/ecs.h +++ b/tizen/src/ecs/ecs.h @@ -55,6 +55,7 @@ #define MSG_TYPE_HDS "hds" #define MSG_TYPE_PACKAGE "package" #define MSG_TYPE_SYSTEM "system" +#define MSG_TYPE_CAP "cap" #define MSG_GROUP_STATUS 15 @@ -95,4 +96,8 @@ int ecs_get_suspend_state(void); void ecs_set_suspend_state(int state); void ecs_suspend_lock_state(int state); +/* Device capabilities check */ +const char* ecs_get_device_capabilities(void); +void ecs_set_device_capabilities(const char* cap); + #endif /* __ECS_H__ */ diff --git a/tizen/src/ecs/ecs_msg.c b/tizen/src/ecs/ecs_msg.c index 3eb314823a..305eb77051 100644 --- a/tizen/src/ecs/ecs_msg.c +++ b/tizen/src/ecs/ecs_msg.c @@ -197,6 +197,8 @@ void send_shutdown_request(int action) if (!ret) { LOG_SEVERE("fail to send evdi shutdown system call to emuld.\n"); } + + ecs_set_device_capabilities(NULL); } bool ntf_to_injector(const char *data, const int len) diff --git a/tizen/src/ecs/ecs_msg_device.c b/tizen/src/ecs/ecs_msg_device.c index 1cdbe91fa0..4e7f5c1e84 100644 --- a/tizen/src/ecs/ecs_msg_device.c +++ b/tizen/src/ecs/ecs_msg_device.c @@ -436,6 +436,9 @@ bool msgproc_device_req(ECS_Client *ccli, ECS__DeviceReq *msg) g_snprintf(vminfo, sizeof(vminfo) - 1, "%s %s %s", get_vm_name(), get_profile_name(), get_platform_version()); msgproc_device_ans(ccli, cmd, true, vminfo); + } else if (!strcmp(cmd, MSG_TYPE_CAP)) { + const char* cap = ecs_get_device_capabilities(); + make_send_device_ntf(cmd, MSG_GROUP_STATUS, 0, (char*)cap); } else if (!strcmp(cmd, "nfc")) { msgproc_device_req_nfc(ccli, msg); } else if (!strcmp(cmd, "sdcard")) { diff --git a/tizen/src/ecs/ecs_msg_injector.c b/tizen/src/ecs/ecs_msg_injector.c index a65f70c044..c577ea3b9e 100644 --- a/tizen/src/ecs/ecs_msg_injector.c +++ b/tizen/src/ecs/ecs_msg_injector.c @@ -463,6 +463,10 @@ static bool injector_req_handle(char *cat, type_action action, const char *data) LOG_WARNING("VirtFS is not enabled.\n"); return false; #endif + } else if (!strcmp(cat, MSG_TYPE_CAP)) { + LOG_INFO("set capabilities: %s\n", data); + ecs_set_device_capabilities(data); + return true; } else if (!strcmp(cat, MSG_TYPE_PACKAGE)) { do_package(cat, action, data); return true; diff --git a/tizen/src/hw/virtio/maru_virtio_sensor.c b/tizen/src/hw/virtio/maru_virtio_sensor.c index b6522ac4b8..94d892d619 100644 --- a/tizen/src/hw/virtio/maru_virtio_sensor.c +++ b/tizen/src/hw/virtio/maru_virtio_sensor.c @@ -726,6 +726,11 @@ static void parse_sensor_capability(char *lists) LOG_INFO("sensor device capabilty enabled with %02x\n", sensor_capability); } +int get_sensor_capability(void) +{ + return sensor_capability; +} + static void virtio_sensor_realize(DeviceState *dev, Error **errp) { LOG_INFO("initialize virtio-sensor device\n"); diff --git a/tizen/src/hw/virtio/maru_virtio_sensor.h b/tizen/src/hw/virtio/maru_virtio_sensor.h index 1c0a743934..1cb5b19de9 100644 --- a/tizen/src/hw/virtio/maru_virtio_sensor.h +++ b/tizen/src/hw/virtio/maru_virtio_sensor.h @@ -143,6 +143,8 @@ typedef struct VirtIOSENSOR { char *sensors; } VirtIOSENSOR; +int get_sensor_capability(void); + void req_sensor_data(enum sensor_types type, enum request_cmd req, char *data, int len); #define get_sensor_accel() \ -- cgit v1.2.3 From 4d4fd2839367e8f8082412b3e47156044160087b Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Thu, 3 Nov 2016 20:08:11 +0900 Subject: hax: sync with recent updates Some CPU state synchronization has been missing on HAX. So, some logics are updated. This updates are refered to recent KVM sources and Intel's updated sources. Change-Id: I181a3c98076ab114575875f0f566e12db457e267 Signed-off-by: SeokYeon Hwang --- Makefile.target | 15 ++- cpus.c | 5 + include/sysemu/hax.h | 3 +- target-i386/hax-all.c | 173 +++++++++++++++++++----- target-i386/hax-darwin.c | 38 ++---- target-i386/hax-slot.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++ target-i386/hax-slot.h | 58 ++++++++ target-i386/hax-windows.c | 47 ++----- 8 files changed, 560 insertions(+), 107 deletions(-) create mode 100644 target-i386/hax-slot.c create mode 100644 target-i386/hax-slot.h diff --git a/Makefile.target b/Makefile.target index 29c3dda3c7..2c224bb72a 100644 --- a/Makefile.target +++ b/Makefile.target @@ -147,13 +147,16 @@ obj-$(CONFIG_XEN_I386) += xen-hvm.o xen-mapcache.o obj-$(call lnot,$(CONFIG_XEN)) += xen-common-stub.o obj-$(call lnot,$(CONFIG_XEN_I386)) += xen-hvm-stub.o -# HAX support -ifdef CONFIG_WIN32 -obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-windows.o -endif -ifdef CONFIG_DARWIN -obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-darwin.o +# HAX support, only when targetting i386 or x86_64 +ifeq (y,$(CONFIG_HAX)) +ifneq (,$(filter i386 x86_64,$(TARGET_NAME))) +obj-y += target-i386/hax-all.o target-i386/hax-slot.o +obj-$(CONFIG_WIN32) += target-i386/hax-windows.o +obj-$(CONFIG_DARWIN) += target-i386/hax-darwin.o +else +obj-y += hax-stub.o endif +endif # CONFIG_HAX obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o # Hardware support diff --git a/cpus.c b/cpus.c index 07d6bd70dd..5d3d0f39d5 100644 --- a/cpus.c +++ b/cpus.c @@ -710,6 +710,11 @@ void cpu_synchronize_all_states(void) CPU_FOREACH(cpu) { cpu_synchronize_state(cpu); +#ifdef CONFIG_HAX + if (hax_enabled() && hax_ug_platform()) { + hax_cpu_synchronize_state(cpu); + } +#endif } } diff --git a/include/sysemu/hax.h b/include/sysemu/hax.h index 58fb039e75..ac4cf7d3ad 100644 --- a/include/sysemu/hax.h +++ b/include/sysemu/hax.h @@ -44,8 +44,9 @@ int hax_vcpu_exec(CPUState *cpu); int hax_smp_cpu_exec(CPUState *cpu); void hax_cpu_synchronize_post_reset(CPUState *cpu); void hax_cpu_synchronize_post_init(CPUState *cpu); +void hax_cpu_synchronize_state(CPUState *cpu); int hax_populate_ram(uint64_t va, uint32_t size); -int hax_set_phys_mem(MemoryRegionSection *section); +int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags); int hax_vcpu_emulation_mode(CPUState *cpu); int hax_stop_emulation(CPUState *cpu); int hax_stop_translate(CPUState *cpu); diff --git a/target-i386/hax-all.c b/target-i386/hax-all.c index 916fcd47c1..dfff5279db 100644 --- a/target-i386/hax-all.c +++ b/target-i386/hax-all.c @@ -26,6 +26,7 @@ #include "strings.h" #include "hax-i386.h" +#include "hax-slot.h" #include "hw/boards.h" #include "sysemu/accel.h" #include "exec/address-spaces.h" @@ -371,7 +372,8 @@ struct hax_vm *hax_vm_create(struct hax_state *hax) } hax->vm = vm; - dprint("End of VM create, id %d\n", vm->id); + hax_slot_init_registry(); + return vm; error: @@ -384,6 +386,7 @@ int hax_vm_destroy(struct hax_vm *vm) { int i; + hax_slot_free_registry(); for (i = 0; i < HAX_MAX_VCPU; i++) if (vm->vcpus[i]) { @@ -396,6 +399,41 @@ int hax_vm_destroy(struct hax_vm *vm) return 0; } +static void hax_set_phys_mem(MemoryRegionSection *section) +{ + MemoryRegion *mr = section->mr; + hwaddr start_pa = section->offset_within_address_space; + ram_addr_t size = int128_get64(section->size); + unsigned int delta; + void *host_ptr; + int flags; + + /* We only care about RAM and ROM */ + if (!memory_region_is_ram(mr)) { + return; + } + + /* Adjust start_pa and size so that they are page-aligned. (Cf + * kvm_set_phys_mem() in kvm-all.c). + */ + delta = TARGET_PAGE_SIZE - (start_pa & ~TARGET_PAGE_MASK); + delta &= ~TARGET_PAGE_MASK; + if (delta > size) { + return; + } + start_pa += delta; + size -= delta; + size &= TARGET_PAGE_MASK; + if (!size || start_pa & ~TARGET_PAGE_MASK) { + return; + } + + host_ptr = memory_region_get_ram_ptr(mr) + section->offset_within_region + + delta; + flags = memory_region_is_rom(mr) ? 1 : 0; + hax_slot_register(start_pa, size, (uintptr_t) host_ptr, flags); +} + static void hax_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -405,7 +443,7 @@ hax_region_add(MemoryListener *listener, MemoryRegionSection *section) static void hax_region_del(MemoryListener *listener, MemoryRegionSection *section) { - hax_set_phys_mem(section); + // Memory mappings will be removed at VM close. } @@ -417,11 +455,17 @@ hax_region_del(MemoryListener *listener, MemoryRegionSection *section) static void hax_log_sync(MemoryListener *listener, MemoryRegionSection *section) { MemoryRegion *mr = section->mr; + + if (!memory_region_is_ram(mr)) { + /* Skip MMIO regions */ + return; + } + unsigned long c; unsigned int len = ((int128_get64(section->size) / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS; unsigned long bitmap[len]; - int i, j; + unsigned int i, j; for (i = 0; i < len; i++) { bitmap[i] = 1; @@ -767,13 +811,6 @@ static int hax_vcpu_hax_exec(CPUArchState *env, int ug_platform) break; } -#if 0 - if (cpu->hax_vcpu_dirty) { - hax_vcpu_sync_state(env, 1); - cpu->hax_vcpu_dirty = 0; - } -#endif - hax_vcpu_interrupt(env); if (!ug_platform) { @@ -863,37 +900,52 @@ static int hax_vcpu_hax_exec(CPUArchState *env, int ug_platform) return ret; } -#if 0 -static void do_hax_cpu_synchronize_state(void *_env) +static void do_hax_cpu_synchronize_state(void *arg) { - CPUArchState *env = _env; - CPUState *cpu = ENV_GET_CPU(env); - if (!cpu->hax_vcpu_dirty) { - hax_vcpu_sync_state(env, 0); - cpu->hax_vcpu_dirty = 1; - } + CPUState *cpu = arg; + CPUArchState *env = cpu->env_ptr; + + hax_arch_get_registers(env); + cpu->hax_vcpu_dirty = true; } -static void hax_cpu_synchronize_state(CPUState *cpu) +void hax_cpu_synchronize_state(CPUState *cpu) { - if (!cpu->hax_vcpu_dirty) { - run_on_cpu(cpu, do_hax_cpu_synchronize_state, cpu); - } + /* TODO: Do not sync if cpu->hax_vcpu_dirty is true. (Cf + * kvm_cpu_synchronize_state() in kvm-all.c) + * This would require that this flag be updated properly and consistently + * wherever a vCPU state sync between QEMU and HAX takes place. For now, + * just perform the sync regardless of hax_vcpu_dirty. + */ + run_on_cpu(cpu, do_hax_cpu_synchronize_state, cpu); } -#endif -void hax_cpu_synchronize_post_reset(CPUState *cpu) +static void do_hax_cpu_synchronize_post_reset(void *arg) { - CPUArchState *env = (CPUArchState *)(cpu->env_ptr); + CPUState *cpu = arg; + CPUArchState *env = cpu->env_ptr; + hax_vcpu_sync_state(env, 1); - cpu->hax_vcpu_dirty = 0; + cpu->hax_vcpu_dirty = false; } -void hax_cpu_synchronize_post_init(CPUState *cpu) +void hax_cpu_synchronize_post_reset(CPUState * cpu) { - CPUArchState *env = (CPUArchState *)(cpu->env_ptr); + run_on_cpu(cpu, do_hax_cpu_synchronize_post_reset, cpu); +} + +static void do_hax_cpu_synchronize_post_init(void *arg) +{ + CPUState *cpu = arg; + CPUArchState *env = cpu->env_ptr; + hax_vcpu_sync_state(env, 1); - cpu->hax_vcpu_dirty = 0; + cpu->hax_vcpu_dirty = false; +} + +void hax_cpu_synchronize_post_init(CPUState * cpu) +{ + run_on_cpu(cpu, do_hax_cpu_synchronize_post_init, cpu); } /* @@ -1145,7 +1197,16 @@ static int hax_sync_vcpu_register(CPUArchState *env, int set) hax_getput_reg(®s._rdi, &env->regs[R_EDI], set); hax_getput_reg(®s._rsp, &env->regs[R_ESP], set); hax_getput_reg(®s._rbp, &env->regs[R_EBP], set); - +#ifdef TARGET_X86_64 + hax_getput_reg(®s._r8, &env->regs[8], set); + hax_getput_reg(®s._r9, &env->regs[9], set); + hax_getput_reg(®s._r10, &env->regs[10], set); + hax_getput_reg(®s._r11, &env->regs[11], set); + hax_getput_reg(®s._r12, &env->regs[12], set); + hax_getput_reg(®s._r13, &env->regs[13], set); + hax_getput_reg(®s._r14, &env->regs[14], set); + hax_getput_reg(®s._r15, &env->regs[15], set); +#endif hax_getput_reg(®s._rflags, &env->eflags, set); hax_getput_reg(®s._rip, &env->eip, set); @@ -1196,6 +1257,14 @@ static int hax_get_msrs(CPUArchState *env) msrs[n++].entry = MSR_IA32_SYSENTER_ESP; msrs[n++].entry = MSR_IA32_SYSENTER_EIP; msrs[n++].entry = MSR_IA32_TSC; +#ifdef TARGET_X86_64 + msrs[n++].entry = MSR_EFER; + msrs[n++].entry = MSR_STAR; + msrs[n++].entry = MSR_LSTAR; + msrs[n++].entry = MSR_CSTAR; + msrs[n++].entry = MSR_FMASK; + msrs[n++].entry = MSR_KERNELGSBASE; +#endif md.nr_msr = n; ret = hax_sync_msr(env, &md, 0); if (ret < 0) @@ -1215,6 +1284,26 @@ static int hax_get_msrs(CPUArchState *env) case MSR_IA32_TSC: env->tsc = msrs[i].value; break; +#ifdef TARGET_X86_64 + case MSR_EFER: + env->efer = msrs[i].value; + break; + case MSR_STAR: + env->star = msrs[i].value; + break; + case MSR_LSTAR: + env->lstar = msrs[i].value; + break; + case MSR_CSTAR: + env->cstar = msrs[i].value; + break; + case MSR_FMASK: + env->fmask = msrs[i].value; + break; + case MSR_KERNELGSBASE: + env->kernelgsbase = msrs[i].value; + break; +#endif } } @@ -1233,6 +1322,14 @@ static int hax_set_msrs(CPUArchState *env) hax_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); hax_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip); hax_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc); +#ifdef TARGET_X86_64 + hax_msr_entry_set(&msrs[n++], MSR_EFER, env->efer); + hax_msr_entry_set(&msrs[n++], MSR_STAR, env->star); + hax_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar); + hax_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); + hax_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask); + hax_msr_entry_set(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase); +#endif md.nr_msr = n; md.done = 0; @@ -1255,9 +1352,13 @@ static int hax_get_fpu(CPUArchState *env) for (i = 0; i < 8; ++i) env->fptags[i] = !((fpu.ftw >> i) & 1); memcpy(env->fpregs, fpu.st_mm, sizeof(env->fpregs)); + for (i = 0; i < 8; ++i) { + memcpy(&env->xmm_regs[i], fpu.mmx_1[i], sizeof(fpu.mmx_1[i])); + } + for (i = 0; i < 8; ++i) { + memcpy(&env->xmm_regs[8 + i], fpu.mmx_2[i], sizeof(fpu.mmx_2[i])); + } - memcpy(env->xmm_regs, fpu.mmx_1, sizeof(fpu.mmx_1)); - memcpy((ZMMReg *)(env->xmm_regs) + 8, fpu.mmx_2, sizeof(fpu.mmx_2)); env->mxcsr = fpu.mxcsr; return 0; @@ -1277,8 +1378,12 @@ static int hax_set_fpu(CPUArchState *env) fpu.ftw |= (!env->fptags[i]) << i; memcpy(fpu.st_mm, env->fpregs, sizeof (env->fpregs)); - memcpy(fpu.mmx_1, env->xmm_regs, sizeof (fpu.mmx_1)); - memcpy(fpu.mmx_2, (ZMMReg *)(env->xmm_regs) + 8, sizeof (fpu.mmx_2)); + for (i = 0; i < 8; i++) { + memcpy(fpu.mmx_1[i], &env->xmm_regs[i], sizeof(fpu.mmx_1[i])); + } + for (i = 0; i < 8; i++) { + memcpy(fpu.mmx_2[i], &env->xmm_regs[i + 8], sizeof(fpu.mmx_2[i])); + } fpu.mxcsr = env->mxcsr; diff --git a/target-i386/hax-darwin.c b/target-i386/hax-darwin.c index b8dcbd40ab..be30d74af6 100644 --- a/target-i386/hax-darwin.c +++ b/target-i386/hax-darwin.c @@ -63,43 +63,23 @@ int hax_populate_ram(uint64_t va, uint32_t size) return 0; } -int hax_set_phys_mem(MemoryRegionSection *section) +int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags) { - struct hax_set_ram_info info, *pinfo = &info; - MemoryRegion *mr = section->mr; - hwaddr start_addr = section->offset_within_address_space; - ram_addr_t size = int128_get64(section->size); + struct hax_set_ram_info info; int ret; - /*We only care for the RAM and ROM*/ - if(!memory_region_is_ram(mr)) - return 0; - - if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK)) - { - dprint("set_phys_mem %llx %lx requires page aligned addr and size\n", start_addr, size); - exit(1); - return -1; - } - - info.pa_start = start_addr; + info.pa_start = start_pa; info.size = size; - info.va = (uint64_t)(intptr_t)(memory_region_get_ram_ptr(mr) + section->offset_within_region); - info.flags = memory_region_is_rom(mr) ? 1 : 0; + info.va = host_va; + info.flags = (uint8_t) flags; - ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, pinfo); - if (ret < 0) - { - dprint("has set phys mem failed\n"); - exit(1); + ret = ioctl(hax_global.vm->fd, HAX_VM_IOCTL_SET_RAM, &info); + if (ret < 0) { + return -errno; } - - return ret; - + return 0; } - - int hax_capability(struct hax_state *hax, struct hax_capabilityinfo *cap) { int ret; diff --git a/target-i386/hax-slot.c b/target-i386/hax-slot.c new file mode 100644 index 0000000000..b0b3ed9dab --- /dev/null +++ b/target-i386/hax-slot.c @@ -0,0 +1,328 @@ +/* +** HAX memory slot operations +** +** Copyright (c) 2015-16 Intel Corporation +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** 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. +*/ + +#include "target-i386/hax-slot.h" +#include "target-i386/hax-i386.h" +#include "qemu/queue.h" + +//#define DEBUG_HAX_SLOT + +#ifdef DEBUG_HAX_SLOT +#define DPRINTF(fmt, ...) \ + do { fprintf(stdout, fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + +/** + * HAXSlot: describes a guest physical memory region and its mapping + * + * @start_pa: a guest physical address marking the start of the region; must be + * page-aligned + * @end_pa: a guest physical address marking the end of the region; must be + * page-aligned + * @hva_pa_delta: the host virtual address to which guest physical address 0 is + * mapped; in other words, for any guest physical address within + * the region (start_pa <= pa < end_pa), the corresponding host + * virtual address is calculated by host_va = pa + hva_pa_delta + * @flags: parameters for the mapping; must be non-negative + * @entry: additional fields for linking #HAXSlot instances together + */ +typedef struct HAXSlot { + uint64_t start_pa; + uint64_t end_pa; + uint64_t hva_pa_delta; + int flags; + QTAILQ_ENTRY(HAXSlot) entry; +} HAXSlot; + +/* A doubly-linked list (actually a tail queue) of all registered slots */ +static QTAILQ_HEAD(HAXSlotListHead, HAXSlot) slot_list = + QTAILQ_HEAD_INITIALIZER(slot_list); + +void hax_slot_init_registry(void) +{ + HAXSlot *initial_slot; + + g_assert(QTAILQ_EMPTY(&slot_list)); + + initial_slot = (HAXSlot *) g_malloc0(sizeof(*initial_slot)); + /* Implied: initial_slot->start_pa = 0; */ + /* Ideally we want to set end_pa to 2^64, but that is too large for + * uint64_t. We don't need to support such a large guest physical address + * space anyway; (2^64 - TARGET_PAGE_SIZE) should be (more than) enough. + */ + initial_slot->end_pa = TARGET_PAGE_MASK; + /* hva_pa_delta and flags are initialized with invalid values */ + initial_slot->hva_pa_delta = ~TARGET_PAGE_MASK; + initial_slot->flags = -1; + QTAILQ_INSERT_TAIL(&slot_list, initial_slot, entry); +} + +void hax_slot_free_registry(void) +{ + DPRINTF("%s: Deleting all registered slots\n", __func__); + while (!QTAILQ_EMPTY(&slot_list)) { + HAXSlot *slot = QTAILQ_FIRST(&slot_list); + QTAILQ_REMOVE(&slot_list, slot, entry); + g_free(slot); + } +} + +/** + * hax_slot_dump: dumps a slot to stdout (for debugging) + * + * @slot: the slot to dump + */ +static void hax_slot_dump(HAXSlot *slot) +{ + DPRINTF("[ start_pa=0x%016" PRIx64 ", end_pa=0x%016" PRIx64 + ", hva_pa_delta=0x%016" PRIx64 ", flags=%d ]\n", slot->start_pa, + slot->end_pa, slot->hva_pa_delta, slot->flags); +} + +/** + * hax_slot_dump_list: dumps @slot_list to stdout (for debugging) + */ +static void hax_slot_dump_list(void) +{ +#ifdef DEBUG_HAX_SLOT + HAXSlot *slot; + int i = 0; + + DPRINTF("**** BEGIN HAX SLOT LIST DUMP ****\n"); + QTAILQ_FOREACH(slot, &slot_list, entry) { + DPRINTF("Slot %d:\n\t", i++); + hax_slot_dump(slot); + } + DPRINTF("**** END HAX SLOT LIST DUMP ****\n"); +#endif +} + +/** + * hax_slot_find: locates the slot containing a guest physical address + * + * Traverses @slot_list, starting from @start_slot, and returns the slot which + * contains @pa. There should be one and only one such slot, because: + * + * 1) @slot_list is initialized with a slot which covers all valid @pa values. + * This coverage stays unchanged as new slots are inserted into @slot_list. + * 2) @slot_list does not contain overlapping slots. + * + * @start_slot: the first slot from which @slot_list is traversed and searched; + * must not be %NULL + * @pa: the guest physical address to locate; must not be less than the lower + * bound of @start_slot + */ +static HAXSlot * hax_slot_find(HAXSlot *start_slot, uint64_t pa) +{ + HAXSlot *slot; + + g_assert(start_slot); + g_assert(start_slot->start_pa <= pa); + + slot = start_slot; + do { + if (slot->end_pa > pa) { + return slot; + } + slot = QTAILQ_NEXT(slot, entry); + } while (slot); + + /* Should never reach here */ + g_assert_not_reached(); + return NULL; +} + +/** + * hax_slot_split: splits a slot into two + * + * Shrinks @slot and creates a new slot from the vacated region. Returns the + * new slot. + * + * @slot: the slot to be split/shrinked + * @pa: the splitting point; must be page-aligned and within @slot + */ +static HAXSlot * hax_slot_split(HAXSlot *slot, uint64_t pa) +{ + HAXSlot *new_slot; + + g_assert(slot); + g_assert(pa > slot->start_pa && pa < slot->end_pa); + g_assert(!(pa & ~TARGET_PAGE_MASK)); + + new_slot = (HAXSlot *) g_malloc0(sizeof(*new_slot)); + new_slot->start_pa = pa; + new_slot->end_pa = slot->end_pa; + new_slot->hva_pa_delta = slot->hva_pa_delta; + new_slot->flags = slot->flags; + + slot->end_pa = pa; + QTAILQ_INSERT_AFTER(&slot_list, slot, new_slot, entry); + return new_slot; +} + +/** + * hax_slot_can_merge: tests if two slots are compatible + * + * Two slots are considered compatible if they share the same memory mapping + * attributes. Compatible slots can be merged if they overlap or are adjacent. + * + * Returns %true if @slot1 and @slot2 are compatible. + * + * @slot1: one of the slots to be tested; must not be %NULL + * @slot2: the other slot to be tested; must not be %NULL + */ +static bool hax_slot_can_merge(HAXSlot *slot1, HAXSlot *slot2) +{ + g_assert(slot1 && slot2); + + return slot1->hva_pa_delta == slot2->hva_pa_delta + && slot1->flags == slot2->flags; +} + +/** + * hax_slot_insert: inserts a slot into @slot_list, with the potential side + * effect of creating/updating memory mappings + * + * Causes memory mapping attributes of @slot to override those of overlapping + * slots (including partial slots) in @slot_list. For any slot whose mapping + * attributes have changed, performs an ioctl to enforce the new mapping. + * + * Aborts QEMU on error. + * + * @slot: the slot to be inserted + */ +static void hax_slot_insert(HAXSlot *slot) +{ + HAXSlot *low_slot, *high_slot; + HAXSlot *low_slot_prev, *high_slot_next; + HAXSlot *old_slot, *old_slot_next; + + g_assert(!QTAILQ_EMPTY(&slot_list)); + + low_slot = hax_slot_find(QTAILQ_FIRST(&slot_list), slot->start_pa); + g_assert(low_slot); + low_slot_prev = QTAILQ_PREV(low_slot, HAXSlotListHead, entry); + + /* Adjust slot and/or low_slot such that their lower bounds (start_pa) + * align. + */ + if (hax_slot_can_merge(low_slot, slot)) { + slot->start_pa = low_slot->start_pa; + } else if (slot->start_pa == low_slot->start_pa && low_slot_prev + && hax_slot_can_merge(low_slot_prev, slot)) { + low_slot = low_slot_prev; + slot->start_pa = low_slot->start_pa; + } else if (slot->start_pa != low_slot->start_pa) { + /* low_slot->start_pa < slot->start_pa < low_slot->end_pa */ + low_slot = hax_slot_split(low_slot, slot->start_pa); + g_assert(low_slot); + } + /* Now we have slot->start_pa == low_slot->start_pa */ + + high_slot = hax_slot_find(low_slot, slot->end_pa - 1); + g_assert(high_slot); + high_slot_next = QTAILQ_NEXT(high_slot, entry); + + /* Adjust slot and/or high_slot such that their upper bounds (end_pa) + * align. + */ + if (hax_slot_can_merge(slot, high_slot)) { + slot->end_pa = high_slot->end_pa; + } else if (slot->end_pa == high_slot->end_pa && high_slot_next + && hax_slot_can_merge(slot, high_slot_next)) { + high_slot = high_slot_next; + slot->end_pa = high_slot->end_pa; + } else if (slot->end_pa != high_slot->end_pa) { + /* high_slot->start_pa < slot->end_pa < high_slot->end_pa */ + high_slot_next = hax_slot_split(high_slot, slot->end_pa); + g_assert(high_slot_next); + } + /* Now we have slot->end_pa == high_slot->end_pa */ + + /* We are ready for substitution: replace all slots between low_slot and + * high_slot (inclusive) with slot. */ + + /* Step 1: insert slot into the list, before low_slot */ + QTAILQ_INSERT_BEFORE(low_slot, slot, entry); + + /* Step 2: remove low_slot..high_slot, one by one */ + for (old_slot = low_slot; + /* This condition always evaluates to 1. See: + * https://en.wikipedia.org/wiki/Comma_operator + */ + old_slot_next = QTAILQ_NEXT(old_slot, entry), 1; + old_slot = old_slot_next) { + g_assert(old_slot); + + QTAILQ_REMOVE(&slot_list, old_slot, entry); + if (!hax_slot_can_merge(slot, old_slot)) { + /* Mapping for guest memory region [old_slot->start_pa, + * old_slot->end_pa) has changed - must do ioctl. */ + /* TODO: Further reduce the number of ioctl calls by preprocessing + * the low_slot..high_slot sublist and combining any two adjacent + * slots that are both incompatible with slot. + */ + uint32_t size = old_slot->end_pa - old_slot->start_pa; + uint64_t host_va = old_slot->start_pa + slot->hva_pa_delta; + int err; + + DPRINTF("%s: Doing ioctl (size=0x%08" PRIx32 ")\n", __func__, size); + /* Use the new host_va and flags */ + err = hax_set_ram(old_slot->start_pa, size, host_va, slot->flags); + if (err) { + fprintf(stderr, "%s: Failed to set memory mapping (err=%d)\n", + __func__, err); + abort(); + } + } + g_free(old_slot); + + /* Exit the infinite loop following the removal of high_slot */ + if (old_slot == high_slot) { + break; + } + } +} + +void hax_slot_register(uint64_t start_pa, uint32_t size, uint64_t host_va, + int flags) +{ + uint64_t end_pa = start_pa + size; + HAXSlot *slot; + + g_assert(!(start_pa & ~TARGET_PAGE_MASK)); + g_assert(!(end_pa & ~TARGET_PAGE_MASK)); + g_assert(start_pa < end_pa); + g_assert(host_va); + g_assert(flags >= 0); + + slot = g_malloc0(sizeof(*slot)); + slot->start_pa = start_pa; + slot->end_pa = end_pa; + slot->hva_pa_delta = host_va - start_pa; + slot->flags = flags; + + DPRINTF("%s: Inserting slot:\n\t", __func__); + hax_slot_dump(slot); + hax_slot_dump_list(); + + hax_slot_insert(slot); + + DPRINTF("%s: Done\n", __func__); + hax_slot_dump_list(); +} diff --git a/target-i386/hax-slot.h b/target-i386/hax-slot.h new file mode 100644 index 0000000000..d991c53d38 --- /dev/null +++ b/target-i386/hax-slot.h @@ -0,0 +1,58 @@ +/* +** HAX memory slot operations +** +** Copyright (c) 2015-16 Intel Corporation +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** 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. +*/ + +#ifndef _HAX_SLOT_H +#define _HAX_SLOT_H + +#include + +/** + * hax_slot_init_registry: initializes the registry of memory slots. + * + * Should be called during HAX initialization, before any call to + * hax_slot_register(). + */ +void hax_slot_init_registry(void); + +/** + * hax_slot_free_registry: destroys the registry of memory slots. + * + * Should be called during HAX cleanup to free up resources used by the + * registry of memory slots. + */ +void hax_slot_free_registry(void); + +/** + * hax_slot_register: registers a memory slot, updating HAX memory mappings if + * necessary. + * + * Must be called after hax_slot_init_registry(). Can be called multiple times + * to create new memory mappings or update existing ones. This function is smart + * enough to avoid asking the HAXM driver to do the same mapping twice for any + * guest physical page. + * + * Aborts QEMU on error. + * + * @start_pa: a guest physical address marking the start of the slot to + * register; must be page-aligned + * @size: size of the slot to register; must be page-aligned and positive + * @host_va: a host virtual address to which @start_pa should be mapped + * @flags: parameters for the mapping, passed verbatim to the HAXM driver if + * necessary; must be non-negative + */ +void hax_slot_register(uint64_t start_pa, uint32_t size, uint64_t host_va, + int flags); + +#endif diff --git a/target-i386/hax-windows.c b/target-i386/hax-windows.c index 5ff5916db5..f24a9e195e 100644 --- a/target-i386/hax-windows.c +++ b/target-i386/hax-windows.c @@ -90,48 +90,21 @@ int hax_populate_ram(uint64_t va, uint32_t size) return 0; } - -/* - * much simpler than kvm, at least in first stage because: - * We don't need consider the device pass-through, we don't need - * consider the framebuffer, and we may even remove the bios at all - */ - -int hax_set_phys_mem(MemoryRegionSection *section) +int hax_set_ram(uint64_t start_pa, uint32_t size, uint64_t host_va, int flags) { - struct hax_set_ram_info info, *pinfo = &info; - MemoryRegion *mr = section->mr; - hwaddr start_addr = section->offset_within_address_space; - ram_addr_t size = int128_get64(section->size); - HANDLE hDeviceVM; + struct hax_set_ram_info info; + HANDLE hDeviceVM = hax_global.vm->fd; DWORD dSize = 0; - int ret = 0; - - /* We only care for the RAM and ROM */ - if (!memory_region_is_ram(mr)) { - return 0; - } - - if ( (start_addr & ~TARGET_PAGE_MASK) || (size & ~TARGET_PAGE_MASK)) { - dprint( - "set_phys_mem %" PRIx64 " %" PRIxPTR " requires page aligned addr and size\n", - start_addr, size); - return -1; - } + int ret; - info.pa_start = start_addr; + info.pa_start = start_pa; info.size = size; - info.va = (uint64_t)(intptr_t)(memory_region_get_ram_ptr(mr) + section->offset_within_region); - info.flags = memory_region_is_rom(mr) ? 1 : 0; - - hDeviceVM = hax_global.vm->fd; + info.va = host_va; + info.flags = (uint8_t) flags; - ret = DeviceIoControl(hDeviceVM, - HAX_VM_IOCTL_SET_RAM, - pinfo, sizeof(*pinfo), - NULL, 0, - &dSize, - (LPOVERLAPPED) NULL); + ret = DeviceIoControl(hDeviceVM, HAX_VM_IOCTL_SET_RAM, + &info, sizeof(info), NULL, 0, &dSize, + (LPOVERLAPPED) NULL); if (!ret) return -EFAULT; -- cgit v1.2.3 From 315fb3aca5b9eb6e7c79c103362dc8340590721d Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Thu, 3 Nov 2016 20:09:08 +0900 Subject: yagl: sync with CPUState on HAX CPUState should contain some special register and state not only KVM but also HAX. Especially, "HF_LMA_MASK" on hflags is very important flag for walking page table on 64bit environments. Change-Id: I432804d684c009de0a7c79d560f5a869918bb1a5 Signed-off-by: SeokYeon Hwang --- hw/yagl/yagl_process.c | 21 +++++++++++++++------ hw/yagl/yagl_process.h | 3 ++- hw/yagl/yagl_thread.c | 18 +++++++++++++----- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/hw/yagl/yagl_process.c b/hw/yagl/yagl_process.c index eb740315c2..16bff173a3 100644 --- a/hw/yagl/yagl_process.c +++ b/hw/yagl/yagl_process.c @@ -34,6 +34,7 @@ #include "yagl_stats.h" #include "yagl_object_map.h" #include "sysemu/kvm.h" +#include "sysemu/hax.h" struct yagl_process_state *yagl_process_state_create(struct yagl_server_state *ss, @@ -47,13 +48,21 @@ struct yagl_process_state ps->object_map = yagl_object_map_create(); QLIST_INIT(&ps->threads); -#ifdef CONFIG_KVM - if (kvm_enabled()) { - cpu_synchronize_state(current_cpu); +#if defined (CONFIG_KVM) || defined (CONFIG_HAX) + if (kvm_enabled() || hax_enabled()) { + if (kvm_enabled()) { + cpu_synchronize_state(current_cpu); + } else { +#ifdef CONFIG_HAX + hax_cpu_synchronize_state(current_cpu); +#endif + } + CPUX86State *env = current_cpu->env_ptr; memcpy(&ps->cr[0], - &((CPUX86State *)current_cpu->env_ptr)->cr[0], - sizeof(ps->cr)); - ps->hflags = ((CPUX86State *)current_cpu->env_ptr)->hflags; + &((CPUX86State *)current_cpu->env_ptr)->cr[0], + sizeof(ps->cr)); + ps->hflags = env->hflags; + ps->efer = env->efer; } #endif diff --git a/hw/yagl/yagl_process.h b/hw/yagl/yagl_process.h index 4cbae5212c..0768f07c41 100644 --- a/hw/yagl/yagl_process.h +++ b/hw/yagl/yagl_process.h @@ -55,9 +55,10 @@ struct yagl_process_state QLIST_HEAD(, yagl_thread_state) threads; -#ifdef CONFIG_KVM +#if defined (CONFIG_KVM) || defined (CONFIG_HAX) target_ulong cr[5]; uint32_t hflags; + uint64_t efer; #endif }; diff --git a/hw/yagl/yagl_thread.c b/hw/yagl/yagl_thread.c index 82a8d808dd..9481f48131 100644 --- a/hw/yagl/yagl_thread.c +++ b/hw/yagl/yagl_thread.c @@ -53,14 +53,22 @@ struct yagl_thread_work_item uint32_t out_arrays_size; }; -#ifdef CONFIG_KVM +#if defined (CONFIG_KVM) || defined (CONFIG_HAX) static __inline void yagl_cpu_synchronize_state(struct yagl_process_state *ps) { - if (kvm_enabled()) { + if (kvm_enabled() || hax_enabled()) { + CPUX86State *env = current_cpu->env_ptr; memcpy(&((CPUX86State *)current_cpu->env_ptr)->cr[0], - &ps->cr[0], - sizeof(ps->cr)); - ((CPUX86State *)current_cpu->env_ptr)->hflags = ps->hflags; + &ps->cr[0], + sizeof(ps->cr)); + env->hflags = ps->hflags; + + // FIXME: Somtimes "hflags" is not synced propery on HAX. + // It can be bug on synchronizing CPU state + env->efer = ps->efer; + if (env->efer & MSR_EFER_LMA) { + env->hflags |= HF_LMA_MASK; + } } } #else -- cgit v1.2.3 From ffdc326b70237b660ac9a6a7cea3117d6c0f249f Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Tue, 1 Nov 2016 16:09:12 +0900 Subject: emulator: modify VM lock check whether vm_launch.conf file exist. skip making lock file if it's failed to create. Change-Id: I2073d752e7fca9dfcce137b6ac0b6ecffcc0d05d Signed-off-by: Munkyu Im --- tizen/src/emulator.c | 5 +++++ tizen/src/util/osutil-win32.c | 6 ++++++ tizen/src/util/osutil.c | 12 +++++------- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index e4a170754b..b63d020518 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -317,6 +317,11 @@ static int emulator_main(int argc, char *argv[], char **envp) set_bin_path_os(_qemu_argv[0]); if (launch_conf_file) { + if (!g_file_test(launch_conf_file, G_FILE_TEST_EXISTS)) { + fprintf(stderr, "conf_file(%s) does not exist.\n", launch_conf_file); + return -1; + } + make_vm_lock_os(g_path_get_dirname(launch_conf_file)); if (!load_conf(launch_conf_file)) { return -1; diff --git a/tizen/src/util/osutil-win32.c b/tizen/src/util/osutil-win32.c index f733aedc67..48220da10c 100644 --- a/tizen/src/util/osutil-win32.c +++ b/tizen/src/util/osutil-win32.c @@ -94,6 +94,10 @@ void make_vm_lock_os(gchar *vms_path) if (g_mkdir_with_parents(g_path_get_dirname(lock_filename), 0777)) { LOG_WARNING("Can not create directory for lock file: %ld\n", GetLastError()); + // do not create the lock file. + g_free(lock_filename); + lock_filename = NULL; + return; } lock_file = CreateFile(lock_filename, GENERIC_READ | GENERIC_WRITE, @@ -107,6 +111,8 @@ void make_vm_lock_os(gchar *vms_path) // On Windows, the file opened by CreateFile has exclusive lock // naturally unless FILE_SHARE_* attribute is set. if (error == ERROR_SHARING_VIOLATION) { + g_free(lock_filename); + lock_filename = NULL; error_report("Can not execute this VM. " "The same VM may be running now."); exit(1); diff --git a/tizen/src/util/osutil.c b/tizen/src/util/osutil.c index de78c53d42..540579381b 100644 --- a/tizen/src/util/osutil.c +++ b/tizen/src/util/osutil.c @@ -145,9 +145,10 @@ retry: error = errno; LOG_WARNING("Failed to open file for lock(%d): %s\n", error, strerror(error)); - error_report("Can not execute this VM. " - "The same VM may be running now."); - exit(1); + // do not create the lock file. + g_free(lock_filename); + lock_filename = NULL; + return; } if (fd_lock(lock_file) == -1) { @@ -165,10 +166,7 @@ retry: exit(1); } - LOG_WARNING("Failed to lock image file: %s\n", strerror(error)); - close(lock_file); - lock_file = -1; - return; + LOG_WARNING("Failed to lock file: %s\n", strerror(error)); } emulator_add_exit_notifier(&remove_lock); -- cgit v1.2.3 From c4b3287b13f9e63aa7588d410b64428c34ed2105 Mon Sep 17 00:00:00 2001 From: Jinhyung Jo Date: Fri, 4 Nov 2016 11:46:47 +0900 Subject: keyboard: change the function to use QMap::take(const Key &key) is more efficient. Short description for take(): "Removes the item with the key from the map and returns the value associated with it." For more information, see 'http://doc.qt.io/qt-5/qmap.html#take'. And the value function is a constant function. Change-Id: Ibdaf578c6eef49ebfa8beb3a00fc61785e4b74ed Signed-off-by: Jinhyung Jo --- tizen/src/ui/input/keyboardshortcut.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tizen/src/ui/input/keyboardshortcut.cpp b/tizen/src/ui/input/keyboardshortcut.cpp index c14f2cfdb6..a5f598c8a3 100644 --- a/tizen/src/ui/input/keyboardshortcut.cpp +++ b/tizen/src/ui/input/keyboardshortcut.cpp @@ -87,11 +87,10 @@ void KeyboardShortcut::registerHwKeyShortcuts(QList &list) void KeyboardShortcut::cancelHwKeyShortcuts(QList &list) { for (int index = 0; index < list.count(); index++) { - delete hwKeyShortcutMap.value(list.at(index)); - hwKeyShortcutMap.remove(list.at(index)); + delete hwKeyShortcutMap.take(list.at(index)); } - qDebug() << hwKeyShortcutMap.count() << "shortcuts have been registered"; + qDebug() << hwKeyShortcutMap.count() << "shortcuts have been unregistered"; } void KeyboardShortcut::slotHwKeyShortcut(int keycode) -- cgit v1.2.3 From 06ee5058a1bf30ed300a62143c7b54f8cfde40ba Mon Sep 17 00:00:00 2001 From: Munkyu Im Date: Tue, 8 Nov 2016 11:31:06 +0900 Subject: package: update version (2.6.10) Change-Id: I507823d8044939815bfe443a1e2832da319d9363 Signed-off-by: Munkyu Im --- package/changelog | 3 +++ package/pkginfo.manifest | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package/changelog b/package/changelog index c3978c116c..21583477be 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,6 @@ +* 2.6.10 +- modify VM lock +== Munkyu Im 2016-11-08 * 2.6.9 - fix checking tap device == Munkyu Im 2016-10-25 diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index 06e25d859b..c900929a76 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.6.9 +Version: 2.6.10 Maintainer: SeokYeon Hwang Source: emulator -- cgit v1.2.3 From 10313ec1de30cbcd794075e91f002d0d5f727fa3 Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Thu, 3 Nov 2016 22:07:55 +0900 Subject: hax: fix "hflags" synchronization problem CPUState synchronization should be done after MSR_EFER is updated. Change-Id: I904564896d64ec9c31137cd5f2c47738ef2b79fd Signed-off-by: SeokYeon Hwang --- hw/yagl/yagl_process.c | 1 - hw/yagl/yagl_process.h | 1 - hw/yagl/yagl_thread.c | 7 ------- target-i386/hax-all.c | 8 ++++++++ 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/yagl/yagl_process.c b/hw/yagl/yagl_process.c index 16bff173a3..1e6844f831 100644 --- a/hw/yagl/yagl_process.c +++ b/hw/yagl/yagl_process.c @@ -62,7 +62,6 @@ struct yagl_process_state &((CPUX86State *)current_cpu->env_ptr)->cr[0], sizeof(ps->cr)); ps->hflags = env->hflags; - ps->efer = env->efer; } #endif diff --git a/hw/yagl/yagl_process.h b/hw/yagl/yagl_process.h index 0768f07c41..bbf4568b58 100644 --- a/hw/yagl/yagl_process.h +++ b/hw/yagl/yagl_process.h @@ -58,7 +58,6 @@ struct yagl_process_state #if defined (CONFIG_KVM) || defined (CONFIG_HAX) target_ulong cr[5]; uint32_t hflags; - uint64_t efer; #endif }; diff --git a/hw/yagl/yagl_thread.c b/hw/yagl/yagl_thread.c index 9481f48131..b965e32371 100644 --- a/hw/yagl/yagl_thread.c +++ b/hw/yagl/yagl_thread.c @@ -62,13 +62,6 @@ static __inline void yagl_cpu_synchronize_state(struct yagl_process_state *ps) &ps->cr[0], sizeof(ps->cr)); env->hflags = ps->hflags; - - // FIXME: Somtimes "hflags" is not synced propery on HAX. - // It can be bug on synchronizing CPU state - env->efer = ps->efer; - if (env->efer & MSR_EFER_LMA) { - env->hflags |= HF_LMA_MASK; - } } } #else diff --git a/target-i386/hax-all.c b/target-i386/hax-all.c index dfff5279db..10fec180a3 100644 --- a/target-i386/hax-all.c +++ b/target-i386/hax-all.c @@ -1234,8 +1234,14 @@ static int hax_sync_vcpu_register(CPUArchState *env, int set) if (ret < 0) return -1; } + + // it should be done after get_msrs, since it needs + // EFER synchonization +#if 0 if (!set) hax_setup_qemu_emulator(env); +#endif + return 0; } @@ -1406,6 +1412,8 @@ static int hax_arch_get_registers(CPUArchState *env) if (ret < 0) return ret; + hax_setup_qemu_emulator(env); + return 0; } -- cgit v1.2.3