VIGS: Initial qt5 display support 78/25078/3
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 28 Jul 2014 17:07:06 +0000 (21:07 +0400)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 30 Jul 2014 05:03:23 +0000 (14:03 +0900)
There're few things to note:
* X11-only, support for other platforms is to be implemented
* Qt5 only allows accessing raw GLX/WGL/CGL OpenGL contexts and X11 display
  through 'gui-private' package, i.e. gui-private must be installed in system:
  sudo apt-get install qtbase5-private-dev
* 'gui-private' is not stable interface, it depends on Qt minor version, but
  we don't care since we'll have our own Qt build anyway (in order to support windows and mac)

TODO:
* resizing - use bicubic shader
* rotation - use y-flipped ortho matrix
* move swapBuffers to background thread - to avoid block-waiting with some drivers
* support remaining platforms (windows, mac)
* improve Qt5/qemu interoperability - currently there're hacks such
  as global QtApplication object, global QOpenGLContext object, etc. this
  is all because of QEMU's graphics console architecture, currently it's
  completely useless for us, it doesn't help us, it just stands in our way
  and forces us to workaround. It's probably better to just drop it and
  perform the rendering on our own...

Change-Id: Ib613b1457e7bf7166b019ad916178ecdba168d29
Signed-off-by: Stanislav Vorobiov <s.vorobiov@samsung.com>
22 files changed:
configure
hw/vigs/Makefile.objs
hw/vigs/display.c
hw/vigs/vigs_backend.h
hw/vigs/vigs_gl_backend.c
hw/vigs/vigs_gl_backend.h
hw/vigs/vigs_gl_backend_glx.c
hw/vigs/vigs_qt5.cpp [new file with mode: 0644]
hw/vigs/vigs_qt5.h [new file with mode: 0644]
hw/vigs/vigs_server.c
hw/vigs/vigs_server.h
hw/vigs/vigs_sw_backend.c
tizen/src/display/maru_display.c
tizen/src/display/maru_display.h
tizen/src/display/qt5.c
tizen/src/display/qt5_supplement.cpp
tizen/src/display/qt5_supplement.h
tizen/src/ui/displaywidget.cpp
tizen/src/ui/displaywidget.h
tizen/src/ui/mainwindow.cpp
tizen/src/ui/mainwindow.h
vl.c

index aa7bc7945f45438497054151560ecf78898d9c16..b03fa35a9f70042837b4a386334b5b60afea9b39 100755 (executable)
--- a/configure
+++ b/configure
@@ -2087,14 +2087,16 @@ fi
 qtversion=""
 if test "$qt" != "no"; then
     if test "$qtabi" = "5.0" ; then
-        qtpackage="Qt5Widgets Qt5Qml Qt5OpenGL"
+        qtpackage="Qt5Widgets Qt5Qml Qt5OpenGL Qt5Gui"
         qtversion="5.0.0"
 
         if $pkg_config --exists "$qtpackage >= $qtversion"; then
             qt_cflags=`$pkg_config --cflags $qtpackage`
             qt_libs=`$pkg_config --libs $qtpackage`
             libs_softmmu="$qt_libs $libs_softmmu"
-            qt_cflags="$qt_cflags -fPIC"
+            qt_cflags_private=`pkg-config --modversion Qt5Gui`
+            qt_cflags_private=`pkg-config --cflags Qt5Gui | sed "s,QtGui,QtGui/$qt_cflags_private/QtGui,g"`
+            qt_cflags="$qt_cflags $qt_cflags_private -fPIC"
             qt="yes"
         elif test "$qt" = "yes"; then
             feature_not_found "qt" "Install qt devel"
index ca42e65be8c51862c10f2f18ddc84e2d33b17a19..572de90946508d2bbecbf7e70b7c295254272a8f 100644 (file)
@@ -13,6 +13,7 @@ obj-y += vigs_fenceman.o
 obj-y += vigs_gl_pool.o
 obj-y += vigs_gl_backend.o
 obj-y += vigs_sw_backend.o
+obj-y += vigs_qt5.o
 obj-y += work_queue.o
 obj-y += winsys.o
 obj-y += display.o
index 961e7aa63e1c8cc668c6278d76034010554edb49..1c55fed87918dea57d93b10f358664b55c44dff4 100644 (file)
@@ -1,4 +1,5 @@
 #include "display.h"
+#include "vigs_qt5.h"
 #include "qom/object_interfaces.h"
 #if defined(CONFIG_LINUX)
 #include <X11/Xlib.h>
@@ -24,7 +25,7 @@ static void displayobject_complete(UserCreatable *obj, Error **errp)
     XSetErrorHandler(x_error_handler);
     XInitThreads();
 
-    dobj->dpy = XOpenDisplay(0);
+    dobj->dpy = (Display*)vigs_qt5_display();
 
     if (!dobj->dpy) {
         error_setg(errp, "Cannot open X display");
index cffcd2bb553fe963c0f3cb6f1a4d97268ddffda9..0e0830a494a33e9fe70cbf73212f3e283ba30af4 100644 (file)
@@ -36,16 +36,6 @@ struct winsys_info;
 struct vigs_surface;
 struct vigs_plane;
 
-typedef uint8_t *(*vigs_composite_start_cb)(void */*user_data*/,
-                                            uint32_t /*width*/,
-                                            uint32_t /*height*/,
-                                            uint32_t /*stride*/,
-                                            vigsp_surface_format /*format*/);
-
-typedef void (*vigs_composite_end_cb)(void */*user_data*/,
-                                      bool /*was_started*/,
-                                      bool /*dirty*/);
-
 struct vigs_backend
 {
     struct winsys_info *ws_info;
@@ -59,14 +49,12 @@ struct vigs_backend
                                            vigsp_surface_format /*format*/,
                                            vigsp_surface_id /*id*/);
 
-    void (*composite)(struct vigs_surface */*surface*/,
-                      const struct vigs_plane */*planes*/,
-                      vigs_composite_start_cb /*start_cb*/,
-                      vigs_composite_end_cb /*end_cb*/,
-                      void */*user_data*/);
-
     void (*batch_end)(struct vigs_backend */*backend*/);
 
+    bool (*composite)(struct vigs_surface */*surface*/,
+                      const struct vigs_plane */*planes*/,
+                      uint8_t */*display_data*/);
+
     void (*destroy)(struct vigs_backend */*backend*/);
 };
 
index 720e6186ff27362d2bc79403355d380c4102c907..8c79f8c9934bb8ff3440dec6cfccaa7d6e440995 100644 (file)
 #include "vigs_utils.h"
 #include "vigs_ref.h"
 #include "winsys_gl.h"
-#include "work_queue.h"
 
 struct vigs_gl_surface;
 
-struct vigs_gl_backend_read_pixels_work_item
-{
-    struct work_queue_item base;
-
-    struct vigs_gl_backend *backend;
-
-    vigs_composite_start_cb start_cb;
-    vigs_composite_end_cb end_cb;
-    void *user_data;
-    uint32_t width;
-    uint32_t height;
-    uint32_t stride;
-    vigsp_surface_format format;
-};
-
 struct vigs_winsys_gl_surface
 {
     struct winsys_gl_surface base;
@@ -451,6 +435,54 @@ 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_create_ortho(GLfloat left, GLfloat right,
                                  GLfloat bottom, GLfloat top,
                                  GLfloat nearf, GLfloat farf,
@@ -489,20 +521,20 @@ static void vigs_gl_translate_color(vigsp_color color,
 
 static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface *ws_sfc)
 {
-    GLuint cur_tex = 0;
+    GLuint cur_tex = 0, tmp_tex = 0;
 
     if (ws_sfc->tex) {
         return true;
     }
 
-    ws_sfc->backend->GenTextures(1, &ws_sfc->tex);
+    ws_sfc->backend->GenTextures(1, &tmp_tex);
 
-    if (!ws_sfc->tex) {
+    if (!tmp_tex) {
         return false;
     }
 
     ws_sfc->backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex);
-    ws_sfc->backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
+    ws_sfc->backend->BindTexture(GL_TEXTURE_2D, tmp_tex);
 
     /*
      * Workaround for problem in "Mesa DRI Intel(R) Ivybridge Desktop x86/MMX/SSE2, version 9.0.3":
@@ -518,6 +550,8 @@ static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface
                                 NULL);
     ws_sfc->backend->BindTexture(GL_TEXTURE_2D, cur_tex);
 
+    ws_sfc->tex = tmp_tex;
+
     return true;
 }
 
@@ -1191,50 +1225,9 @@ static struct vigs_surface *vigs_gl_backend_create_surface(struct vigs_backend *
     return &gl_sfc->base;
 }
 
-static void vigs_gl_backend_read_pixels_work(struct work_queue_item *wq_item)
-{
-    struct vigs_gl_backend_read_pixels_work_item *item = (struct vigs_gl_backend_read_pixels_work_item*)wq_item;
-    struct vigs_gl_backend *backend = item->backend;
-    uint8_t *dst = NULL;
-
-    VIGS_LOG_TRACE("enter");
-
-    if (backend->read_pixels_make_current(backend, true)) {
-        uint8_t *src;
-
-        backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, backend->pbo);
-
-        src = backend->MapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
-
-        if (src) {
-            dst = item->start_cb(item->user_data,
-                                 item->width, item->height,
-                                 item->stride, item->format);
-
-            memcpy(dst, src, item->stride * item->height);
-
-            if (!backend->UnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB)) {
-                VIGS_LOG_CRITICAL("glUnmapBuffer failed");
-            }
-        } else {
-            VIGS_LOG_CRITICAL("glMapBuffer failed");
-        }
-
-        backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
-
-        backend->read_pixels_make_current(backend, false);
-    }
-
-    item->end_cb(item->user_data, (dst != NULL), true);
-
-    g_free(item);
-}
-
-static void vigs_gl_backend_composite(struct vigs_surface *surface,
+static bool vigs_gl_backend_composite(struct vigs_surface *surface,
                                       const struct vigs_plane *planes,
-                                      vigs_composite_start_cb start_cb,
-                                      vigs_composite_end_cb end_cb,
-                                      void *user_data)
+                                      uint8_t *display_data)
 {
     struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)surface->backend;
     struct vigs_gl_surface *gl_root_sfc = (struct vigs_gl_surface*)surface;
@@ -1243,25 +1236,29 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
     GLfloat *vert_coords;
     GLfloat *tex_coords;
     const struct vigs_plane *sorted_planes[VIGS_MAX_PLANES];
-    uint32_t size = surface->stride * surface->ws_sfc->height;
-    struct vigs_gl_backend_read_pixels_work_item *item;
 
     VIGS_LOG_TRACE("enter");
 
-    if (!surface->ptr) {
-        if (!ws_root_sfc->tex) {
-            VIGS_LOG_WARN("compositing garbage (root surface) ???");
-        }
+    if (!ws_root_sfc->tex) {
+        VIGS_LOG_WARN("compositing garbage (root surface) ???");
+        return false;
+    }
 
-        if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc)) {
-            goto out;
+    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);
         }
-    }
 
-    if (!vigs_gl_surface_create_tmp_texture(gl_root_sfc)) {
-        goto out;
+        gl_backend->BindVertexArray(gl_backend->dpy_vao);
     }
 
+    gl_backend->BindBuffer(GL_ARRAY_BUFFER, gl_backend->dpy_vbo);
+    gl_backend->Disable(GL_DEPTH_TEST);
+    gl_backend->Disable(GL_BLEND);
+
     for (i = 0; i < VIGS_MAX_PLANES; ++i) {
         struct vigs_gl_surface *gl_sfc;
         struct vigs_winsys_gl_surface *ws_sfc;
@@ -1275,25 +1272,30 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
 
         if (!ws_sfc->tex) {
             VIGS_LOG_WARN("compositing garbage (plane %u) ???", i);
-        }
-
-        if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
-            goto out;
+            return false;
         }
     }
 
-    if (!vigs_gl_surface_setup_framebuffer(gl_root_sfc,
-                                           gl_backend->tex_prog_id,
-                                           gl_backend->tex_prog_proj_loc)) {
-        goto out;
-    }
+    /*
+     * TODO: scale.
+     */
 
-    vigs_vector_resize(&gl_backend->v1, 0);
-    vigs_vector_resize(&gl_backend->v2, 0);
+    gl_backend->Viewport(0, 0,
+                         gl_root_sfc->base.ws_sfc->width / 2,
+                         gl_root_sfc->base.ws_sfc->height / 2);
 
-    vert_coords = vigs_vector_append(&gl_backend->v1,
+    gl_backend->UseProgram(gl_backend->dpy_tex_prog_id);
+    gl_backend->UniformMatrix4fv(gl_backend->dpy_tex_prog_proj_loc, 1, GL_FALSE,
+                                 gl_root_sfc->ortho);
+
+    gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
+
+    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->v2,
+    tex_coords = vigs_vector_append(&gl_backend->dpy_v2,
                                     (12 * sizeof(GLfloat)));
 
     if (surface->ptr) {
@@ -1307,8 +1309,6 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
         gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
         gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
 
-        gl_backend->BindTexture(GL_TEXTURE_2D, gl_root_sfc->tmp_tex);
-
         gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                                   ws_root_sfc->base.base.width,
                                   ws_root_sfc->base.base.height,
@@ -1317,38 +1317,37 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
                                   surface->ptr);
     }
 
-    gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                     GL_TEXTURE_2D, gl_root_sfc->tmp_tex, 0);
-
-    if (!surface->ptr) {
-        /*
-         * If root surface is not scanout then we must render
-         * it.
-         */
-
-        vert_coords[6] = vert_coords[0] = 0;
-        vert_coords[7] = vert_coords[1] = ws_root_sfc->base.base.height;
-        vert_coords[2] = ws_root_sfc->base.base.width;
-        vert_coords[3] = ws_root_sfc->base.base.height;
-        vert_coords[8] = vert_coords[4] = ws_root_sfc->base.base.width;
-        vert_coords[9] = vert_coords[5] = 0;
-        vert_coords[10] = 0;
-        vert_coords[11] = 0;
+    vert_coords[6] = vert_coords[0] = 0;
+    vert_coords[7] = vert_coords[1] = ws_root_sfc->base.base.height;
+    vert_coords[2] = ws_root_sfc->base.base.width;
+    vert_coords[3] = ws_root_sfc->base.base.height;
+    vert_coords[8] = vert_coords[4] = ws_root_sfc->base.base.width;
+    vert_coords[9] = vert_coords[5] = 0;
+    vert_coords[10] = 0;
+    vert_coords[11] = 0;
 
+    if (surface->ptr) {
         tex_coords[6] = tex_coords[0] = 0;
-        tex_coords[7] =tex_coords[1] = 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;
-
-        gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
-
-        vigs_gl_draw_tex_prog(gl_backend, 6);
+    } else {
+        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;
     }
 
+    vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
+
     /*
      * Sort planes, only 2 of them now, don't bother...
      */
@@ -1393,68 +1392,22 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
         vert_coords[11] = plane->dst_y + (int)plane->dst_size.h;
 
         tex_coords[6] = tex_coords[0] = (GLfloat)plane->src_rect.pos.x / src_w;
-        tex_coords[7] = tex_coords[1] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
+        tex_coords[7] = tex_coords[1] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
         tex_coords[2] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
-        tex_coords[3] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
+        tex_coords[3] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
         tex_coords[8] = tex_coords[4] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
-        tex_coords[9] = tex_coords[5] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
+        tex_coords[9] = tex_coords[5] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
         tex_coords[10] = (GLfloat)plane->src_rect.pos.x / src_w;
-        tex_coords[11] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
+        tex_coords[11] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
 
         gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
 
-        vigs_gl_draw_tex_prog(gl_backend, 6);
-    }
-
-    /*
-     * Now schedule asynchronous glReadPixels.
-     */
-
-    gl_backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, gl_backend->pbo);
-
-    if (size > gl_backend->pbo_size) {
-        gl_backend->pbo_size = size;
-        gl_backend->BufferData(GL_PIXEL_PACK_BUFFER_ARB,
-                               size,
-                               0,
-                               GL_STREAM_READ);
+        vigs_gl_draw_dpy_tex_prog(gl_backend, 6);
     }
 
-    gl_backend->PixelStorei(GL_PACK_ALIGNMENT, 1);
-    gl_backend->ReadPixels(0, 0,
-                           surface->ws_sfc->width, surface->ws_sfc->height,
-                           ws_root_sfc->tex_format, ws_root_sfc->tex_type,
-                           NULL);
-
-    gl_backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
-
-    /*
-     * That's a tricky one, if we don't do this then it's not
-     * guaranteed that PBO will actually be updated by the time
-     * 'vigs_gl_backend_read_pixels_work' runs and since
-     * 'vigs_gl_backend_read_pixels_work' uses another OpenGL context
-     * we might get old results.
-     */
     gl_backend->Finish();
 
-    item = g_malloc(sizeof(*item));
-
-    work_queue_item_init(&item->base, &vigs_gl_backend_read_pixels_work);
-
-    item->backend = gl_backend;
-
-    item->start_cb = start_cb;
-    item->end_cb = end_cb;
-    item->user_data = user_data;
-    item->width = surface->ws_sfc->width;
-    item->height = surface->ws_sfc->height;
-    item->stride = surface->stride;
-    item->format = surface->format;
-
-    work_queue_add_item(gl_backend->read_pixels_queue, &item->base);
-
-out:
-    gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
+    return false;
 }
 
 static void vigs_gl_backend_batch_end(struct vigs_backend *backend)
@@ -1556,9 +1509,10 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend)
     gl_backend->color_prog_color_loc = gl_backend->GetUniformLocation(gl_backend->color_prog_id, "color");
 
     gl_backend->GenBuffers(1, &gl_backend->vbo);
+    gl_backend->GenBuffers(1, &gl_backend->dpy_vbo);
 
-    if (!gl_backend->vbo) {
-        VIGS_LOG_CRITICAL("cannot create VBO");
+    if (!gl_backend->vbo || !gl_backend->dpy_vbo) {
+        VIGS_LOG_CRITICAL("cannot create VBOs");
         goto fail;
     }
 
@@ -1567,13 +1521,34 @@ 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->GenBuffers(1, &gl_backend->pbo);
+    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->pbo) {
-        VIGS_LOG_CRITICAL("cannot create read_pixels PBO");
+    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_tex_source_gl2 : g_fs_tex_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->Disable(GL_DEPTH_TEST);
     gl_backend->Disable(GL_BLEND);
 
@@ -1586,8 +1561,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);
-
-    gl_backend->read_pixels_queue = work_queue_create("vigs_work_queue");
+    vigs_vector_init(&gl_backend->dpy_v1, 0);
+    vigs_vector_init(&gl_backend->dpy_v2, 0);
 
     return true;
 
@@ -1599,10 +1574,15 @@ fail:
 
 void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend)
 {
-    work_queue_destroy(gl_backend->read_pixels_queue);
-
     if (gl_backend->make_current(gl_backend, true)) {
-        gl_backend->DeleteBuffers(1, &gl_backend->pbo);
+        gl_backend->DeleteBuffers(1, &gl_backend->dpy_vbo);
+        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->color_prog_id,
                                  gl_backend->color_prog_vs_id);
@@ -1629,6 +1609,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);
 }
index e761ed196c370555936a7cffa5008397c4c98f8b..f3643be68925bda1ea5f1811022554fa70d042ac 100644 (file)
@@ -37,7 +37,6 @@
 #include <GL/glext.h>
 #include "winsys_gl.h"
 
-struct work_queue;
 struct vigs_gl_pool;
 
 struct vigs_gl_backend
@@ -53,9 +52,6 @@ struct vigs_gl_backend
     bool (*make_current)(struct vigs_gl_backend */*gl_backend*/,
                          bool /*enable*/);
 
-    bool (*read_pixels_make_current)(struct vigs_gl_backend */*gl_backend*/,
-                                     bool /*enable*/);
-
     /*
      * Mandatory GL functions and extensions.
      * @{
@@ -159,7 +155,8 @@ struct vigs_gl_backend
      */
 
     /*
-     * Other.
+     * Rendering thread related.
+     * @{
      */
 
     GLuint vao;
@@ -183,10 +180,30 @@ struct vigs_gl_backend
 
     GLuint cur_prog_id;
 
-    struct work_queue *read_pixels_queue;
+    /*
+     * @}
+     * Display thread related.
+     * @{
+     */
+
+    struct vigs_vector dpy_v1;
+    struct vigs_vector dpy_v2;
 
-    GLuint pbo;
-    uint32_t pbo_size;
+    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;
+
+    GLuint dpy_vbo;
+    uint32_t dpy_vbo_size;
+
+    /*
+     * @}
+     */
 };
 
 bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend);
index 5394b19f85bc4f4f836740a99d28d97f21c16135..294bdef2a85a747b8f815d7381af3fdf100ee388 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "vigs_gl_backend.h"
 #include "vigs_log.h"
+#include "vigs_qt5.h"
 #include <GL/glx.h>
 #include <dlfcn.h>
 
@@ -85,6 +86,7 @@ struct vigs_gl_backend_glx
     PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
     PFNGLXGETCURRENTCONTEXTPROC glXGetCurrentContext;
     PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
+    PFNGLXQUERYCONTEXTPROC glXQueryContext;
 
     /* GLX_ARB_create_context */
     PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
@@ -92,8 +94,6 @@ struct vigs_gl_backend_glx
     Display *dpy;
     GLXPbuffer sfc;
     GLXContext ctx;
-    GLXPbuffer read_pixels_sfc;
-    GLXContext read_pixels_ctx;
 };
 
 static bool vigs_gl_backend_glx_check_gl_version(struct vigs_gl_backend_glx *gl_backend_glx,
@@ -194,22 +194,21 @@ static GLXFBConfig vigs_gl_backend_glx_get_config(struct vigs_gl_backend_glx *gl
 {
     int config_attribs[] =
     {
-        GLX_DOUBLEBUFFER, True,
-        GLX_RED_SIZE, 8,
-        GLX_GREEN_SIZE, 8,
-        GLX_BLUE_SIZE, 8,
-        GLX_ALPHA_SIZE, 8,
-        GLX_BUFFER_SIZE, 32,
-        GLX_DEPTH_SIZE, 24,
-        GLX_STENCIL_SIZE, 8,
-        GLX_RENDER_TYPE, GLX_RGBA_BIT,
-        GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+        GLX_FBCONFIG_ID, 0,
         None
     };
     int n = 0;
     GLXFBConfig *glx_configs;
     GLXFBConfig best_config = NULL;
 
+    if (gl_backend_glx->glXQueryContext(gl_backend_glx->dpy,
+                                        gl_backend_glx->ctx,
+                                        GLX_FBCONFIG_ID,
+                                        &config_attribs[1]) != Success) {
+        VIGS_LOG_CRITICAL("Unable to get context's GLX config");
+        return NULL;
+    }
+
     glx_configs = gl_backend_glx->glXChooseFBConfig(gl_backend_glx->dpy,
                                                     DefaultScreen(gl_backend_glx->dpy),
                                                     config_attribs,
@@ -267,42 +266,6 @@ static bool vigs_gl_backend_glx_create_surface(struct vigs_gl_backend_glx *gl_ba
     return true;
 }
 
-static bool vigs_gl_backend_glx_create_context(struct vigs_gl_backend_glx *gl_backend_glx,
-                                               GLXFBConfig config,
-                                               GLXContext share_ctx,
-                                               GLXContext *ctx)
-{
-    int attribs[] =
-    {
-        GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
-        GLX_CONTEXT_MINOR_VERSION_ARB, 1,
-        GLX_RENDER_TYPE, GLX_RGBA_TYPE,
-        GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
-        None
-    };
-
-    if (gl_backend_glx->base.is_gl_2) {
-        *ctx = gl_backend_glx->glXCreateNewContext(gl_backend_glx->dpy,
-                                                   config,
-                                                   GLX_RGBA_TYPE,
-                                                   share_ctx,
-                                                   True);
-    } else {
-        *ctx = gl_backend_glx->glXCreateContextAttribsARB(gl_backend_glx->dpy,
-                                                          config,
-                                                          share_ctx,
-                                                          True,
-                                                          attribs);
-    }
-
-    if (!*ctx) {
-        VIGS_LOG_CRITICAL("glXCreateContextAttribsARB/glXCreateNewContext failed");
-        return false;
-    }
-
-    return true;
-}
-
 static bool vigs_gl_backend_glx_has_current(struct vigs_gl_backend *gl_backend)
 {
     struct vigs_gl_backend_glx *gl_backend_glx =
@@ -331,41 +294,12 @@ static bool vigs_gl_backend_glx_make_current(struct vigs_gl_backend *gl_backend,
     return true;
 }
 
-static bool vigs_gl_backend_glx_read_pixels_make_current(struct vigs_gl_backend *gl_backend,
-                                                         bool enable)
-{
-    struct vigs_gl_backend_glx *gl_backend_glx =
-        (struct vigs_gl_backend_glx*)gl_backend;
-    Bool ret;
-
-    ret = gl_backend_glx->glXMakeContextCurrent(gl_backend_glx->dpy,
-                                                (enable ? gl_backend_glx->read_pixels_sfc : None),
-                                                (enable ? gl_backend_glx->read_pixels_sfc : None),
-                                                (enable ? gl_backend_glx->read_pixels_ctx : NULL));
-
-    if (!ret) {
-        VIGS_LOG_CRITICAL("glXMakeContextCurrent failed");
-        return false;
-    }
-
-    return true;
-}
-
 static void vigs_gl_backend_glx_destroy(struct vigs_backend *backend)
 {
     struct vigs_gl_backend_glx *gl_backend_glx = (struct vigs_gl_backend_glx*)backend;
 
     vigs_gl_backend_cleanup(&gl_backend_glx->base);
 
-    gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy,
-                                      gl_backend_glx->read_pixels_ctx);
-
-    gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy,
-                                      gl_backend_glx->ctx);
-
-    gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy,
-                                      gl_backend_glx->read_pixels_sfc);
-
     gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy,
                                       gl_backend_glx->sfc);
 
@@ -418,6 +352,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GLX_GET_PROC(PFNGLXGETCURRENTCONTEXTPROC, glXGetCurrentContext);
     VIGS_GLX_GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext);
     VIGS_GLX_GET_PROC(PFNGLXCREATECONTEXTATTRIBSARBPROC, glXCreateContextAttribsARB);
+    VIGS_GLX_GET_PROC(PFNGLXQUERYCONTEXTPROC, glXQueryContext);
 
     VIGS_GL_GET_PROC(GenTextures, glGenTextures);
     VIGS_GL_GET_PROC(DeleteTextures, glDeleteTextures);
@@ -504,6 +439,13 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
         VIGS_GL_GET_PROC(DeleteVertexArrays, glDeleteVertexArrays);
     }
 
+    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) {
@@ -516,49 +458,19 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
         goto fail2;
     }
 
-    if (!vigs_gl_backend_glx_create_surface(gl_backend_glx,
-                                            config,
-                                            &gl_backend_glx->read_pixels_sfc)) {
-        goto fail3;
-    }
-
-    if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
-                                            config,
-                                            NULL,
-                                            &gl_backend_glx->ctx)) {
-        goto fail4;
-    }
-
-    if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
-                                            config,
-                                            gl_backend_glx->ctx,
-                                            &gl_backend_glx->read_pixels_ctx)) {
-        goto fail5;
-    }
-
     gl_backend_glx->base.base.destroy = &vigs_gl_backend_glx_destroy;
     gl_backend_glx->base.has_current = &vigs_gl_backend_glx_has_current;
     gl_backend_glx->base.make_current = &vigs_gl_backend_glx_make_current;
-    gl_backend_glx->base.read_pixels_make_current = &vigs_gl_backend_glx_read_pixels_make_current;
     gl_backend_glx->base.ws_info.context = gl_backend_glx->ctx;
 
     if (!vigs_gl_backend_init(&gl_backend_glx->base)) {
-        goto fail6;
+        goto fail3;
     }
 
     VIGS_LOG_DEBUG("created");
 
     return &gl_backend_glx->base.base;
 
-fail6:
-    gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy,
-                                      gl_backend_glx->read_pixels_ctx);
-fail5:
-    gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy,
-                                      gl_backend_glx->ctx);
-fail4:
-    gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy,
-                                      gl_backend_glx->read_pixels_sfc);
 fail3:
     gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy,
                                       gl_backend_glx->sfc);
diff --git a/hw/vigs/vigs_qt5.cpp b/hw/vigs/vigs_qt5.cpp
new file mode 100644 (file)
index 0000000..6a05acb
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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 "vigs_qt5.h"
+#include "config-host.h"
+#include <QGuiApplication>
+#include <QOpenGLContext>
+#include <qpa/qplatformnativeinterface.h>
+#include <stdio.h>
+
+extern QOpenGLContext *qt5GLContext;
+extern QSurfaceFormat qt5GLFormat;
+
+void *vigs_qt5_display(void)
+{
+    QPlatformNativeInterface *native =
+        QGuiApplication::platformNativeInterface();
+
+    return native->nativeResourceForScreen(QByteArray("display"),
+                                           QGuiApplication::primaryScreen());
+}
+
+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);
+        format.setMinorVersion(1);
+    }
+
+    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;
+
+#if defined(CONFIG_LINUX)
+    ret = native->nativeResourceForContext(QByteArray("glxcontext"), qt5GLContext);
+#elif defined(CONFIG_WIN32)
+    ret = native->nativeResourceForContext(QByteArray("renderingContext"), qt5GLContext);
+#elif defined(CONFIG_DARWIN)
+    ret = native->nativeResourceForContext(QByteArray("cglContextObj"), qt5GLContext);
+#endif
+
+    if (!ret) {
+        fprintf(stderr, "Cannot get native QT5 GL context!\n");
+
+        delete qt5GLContext;
+        qt5GLContext = NULL;
+    }
+
+    qt5GLFormat = format;
+
+    return ret;
+}
diff --git a/hw/vigs/vigs_qt5.h b/hw/vigs/vigs_qt5.h
new file mode 100644 (file)
index 0000000..5d5d31e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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 _QEMU_VIGS_QT5_H
+#define _QEMU_VIGS_QT5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *vigs_qt5_display(void);
+
+void *vigs_qt5_gl_context_create(bool is_gl2);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
index 6be06b75bd1d9822f1e6efb5975a3e537da264f6..6299299ed46844a8075cd1ddf559f3bfc4d48387 100644 (file)
@@ -178,8 +178,12 @@ static void vigs_server_dispatch_destroy_surface(void *user_data,
         return;
     }
 
+    qemu_mutex_lock(&server->dpy_mutex);
+
     vigs_server_unuse_surface(server, sfc);
 
+    qemu_mutex_unlock(&server->dpy_mutex);
+
     g_hash_table_remove(server->surfaces, GUINT_TO_POINTER(id));
 
     VIGS_LOG_TRACE("num_surfaces = %u", g_hash_table_size(server->surfaces));
@@ -322,18 +326,20 @@ static void vigs_server_dispatch_set_plane(void *user_data,
         return;
     }
 
+    qemu_mutex_lock(&server->dpy_mutex);
+
     if (sfc_id) {
         sfc = g_hash_table_lookup(server->surfaces, GUINT_TO_POINTER(sfc_id));
 
         if (!sfc) {
             VIGS_LOG_ERROR("surface %u not found", sfc_id);
-            return;
+            goto out;
         }
     }
 
     if (plane >= VIGS_MAX_PLANES) {
         VIGS_LOG_ERROR("bad plane %u", plane);
-        return;
+        goto out;
     }
 
     server->planes[plane].sfc = sfc;
@@ -343,6 +349,9 @@ static void vigs_server_dispatch_set_plane(void *user_data,
     server->planes[plane].dst_size = *dst_size;
     server->planes[plane].z_pos = z_pos;
     server->planes[plane].is_dirty = true;
+
+out:
+    qemu_mutex_unlock(&server->dpy_mutex);
 }
 
 static void vigs_server_dispatch_batch_end(void *user_data,
@@ -394,6 +403,8 @@ static void vigs_server_set_root_surface_work(struct work_queue_item *wq_item)
         goto out;
     }
 
+    qemu_mutex_lock(&server->dpy_mutex);
+
     if (item->id == 0) {
         if (server->root_sfc) {
             vigs_surface_set_scanout(server->root_sfc, NULL);
@@ -427,147 +438,8 @@ static void vigs_server_set_root_surface_work(struct work_queue_item *wq_item)
     }
 
 out:
-    g_free(item);
-}
-
-static uint8_t *vigs_server_update_display_start_cb(void *user_data,
-                                                    uint32_t width,
-                                                    uint32_t height,
-                                                    uint32_t stride,
-                                                    vigsp_surface_format format)
-{
-    struct vigs_server *server = user_data;
-
-    qemu_mutex_lock(&server->capture_mutex);
-
-    if ((server->captured.stride != stride) ||
-        (server->captured.height != height)) {
-        g_free(server->captured.data);
-        server->captured.data = g_malloc(stride * height);
-    }
-
-    server->captured.width = width;
-    server->captured.height = height;
-    server->captured.stride = stride;
-    server->captured.format = format;
-
-    return server->captured.data;
-}
-
-static void vigs_server_update_display_end_cb(void *user_data,
-                                              bool was_started,
-                                              bool dirty)
-{
-    struct vigs_server *server = user_data;
-    uint32_t capture_fence_seq;
-
-    if (!was_started) {
-        qemu_mutex_lock(&server->capture_mutex);
-    }
-
-    if (dirty) {
-        server->captured.dirty = true;
-    }
-
-    server->is_capturing = false;
-    capture_fence_seq = server->capture_fence_seq;
-    server->capture_fence_seq = 0;
-
-    qemu_mutex_unlock(&server->capture_mutex);
-
-    if (capture_fence_seq) {
-        server->display_ops->fence_ack(server->display_user_data,
-                                       capture_fence_seq);
-    }
-}
-
-static void vigs_server_update_display_work(struct work_queue_item *wq_item)
-{
-    struct vigs_server_work_item *item = (struct vigs_server_work_item*)wq_item;
-    struct vigs_server *server = item->server;
-    struct vigs_surface *root_sfc = server->root_sfc;
-    int i;
-    bool planes_on = false;
-    bool planes_dirty = false;
-
-    if (!root_sfc) {
-        /*
-         * If no root surface then this is a no-op.
-         * TODO: Can planes be enabled without a root surface ?
-         */
-        vigs_server_update_display_end_cb(server, false, false);
-        goto out;
-    }
-
-    for (i = 0; i < VIGS_MAX_PLANES; ++i) {
-        /*
-         * If plane was moved/resized or turned on/off
-         * then we're dirty.
-         */
-        if (server->planes[i].is_dirty) {
-            planes_dirty = true;
-        }
-
-        if (server->planes[i].sfc) {
-            planes_on = true;
-
-            /*
-             * If plane's surface is dirty then we're dirty.
-             */
-            if (server->planes[i].sfc->is_dirty) {
-                planes_dirty = true;
-            }
-        }
-    }
-
-    if (root_sfc->ptr && !root_sfc->is_dirty && !planes_on) {
-        /*
-         * Root surface is scanout, it's not dirty and planes not on,
-         * finish immediately.
-         */
-        uint8_t *buff = vigs_server_update_display_start_cb(server,
-                                                            root_sfc->ws_sfc->width,
-                                                            root_sfc->ws_sfc->height,
-                                                            root_sfc->stride,
-                                                            root_sfc->format);
-
-        memcpy(buff,
-               root_sfc->ptr,
-               root_sfc->stride * root_sfc->ws_sfc->height);
-
-        vigs_server_update_display_end_cb(server, true, true);
-    } else if (root_sfc->ptr || root_sfc->is_dirty || planes_dirty) {
-        /*
-         * Composite root surface and planes.
-         */
-        server->backend->batch_start(server->backend);
-        server->backend->composite(root_sfc,
-                                   &server->planes[0],
-                                   &vigs_server_update_display_start_cb,
-                                   &vigs_server_update_display_end_cb,
-                                   server);
-        server->backend->batch_end(server->backend);
-
-        root_sfc->is_dirty = false;
-
-        for (i = 0; i < VIGS_MAX_PLANES; ++i) {
-            if (server->planes[i].is_dirty) {
-                server->planes[i].is_dirty = false;
-            }
-
-            if (server->planes[i].sfc &&
-                server->planes[i].sfc->is_dirty) {
-                server->planes[i].sfc->is_dirty = false;
-            }
-        }
-    } else {
-        /*
-         * No changes, no-op.
-         */
-        vigs_server_update_display_end_cb(server, false, false);
-    }
+    qemu_mutex_unlock(&server->dpy_mutex);
 
-out:
     g_free(item);
 }
 
@@ -631,7 +503,6 @@ static void vigs_server_dispatch_set_root_surface(void *user_data,
 {
     struct vigs_server *server = user_data;
     struct vigs_server_set_root_surface_work_item *item;
-    uint32_t capture_fence_seq = 0;
 
     item = g_malloc(sizeof(*item));
 
@@ -644,20 +515,9 @@ static void vigs_server_dispatch_set_root_surface(void *user_data,
 
     work_queue_add_item(server->render_queue, &item->base);
 
-    qemu_mutex_lock(&server->capture_mutex);
-
-    if (server->is_capturing) {
-        capture_fence_seq = server->capture_fence_seq;
-        server->capture_fence_seq = fence_seq;
-    } else {
-        capture_fence_seq = fence_seq;
-    }
-
-    qemu_mutex_unlock(&server->capture_mutex);
-
-    if (capture_fence_seq) {
+    if (fence_seq) {
         server->display_ops->fence_ack(server->display_user_data,
-                                       capture_fence_seq);
+                                       fence_seq);
     }
 }
 
@@ -719,7 +579,7 @@ struct vigs_server *vigs_server_create(uint8_t *vram_ptr,
                                              NULL,
                                              vigs_server_surface_destroy_func);
 
-    qemu_mutex_init(&server->capture_mutex);
+    qemu_mutex_init(&server->dpy_mutex);
 
     return server;
 
@@ -736,8 +596,7 @@ void vigs_server_destroy(struct vigs_server *server)
     g_hash_table_destroy(server->surfaces);
     vigs_comm_destroy(server->comm);
     server->backend->destroy(server->backend);
-    qemu_mutex_destroy(&server->capture_mutex);
-    g_free(server->captured.data);
+    qemu_mutex_destroy(&server->dpy_mutex);
     g_free(server);
 }
 
@@ -776,86 +635,92 @@ void vigs_server_dispatch(struct vigs_server *server,
 bool vigs_server_update_display(struct vigs_server *server, int invalidate_cnt)
 {
     bool updated = false;
-    uint32_t sfc_bpp;
+    struct vigs_surface *root_sfc;
     uint32_t display_stride, display_bpp;
     uint8_t *display_data;
+    int i;
+    bool planes_on = false;
+    bool planes_dirty = false;
+
+    qemu_mutex_lock(&server->dpy_mutex);
 
-    qemu_mutex_lock(&server->capture_mutex);
+    root_sfc = server->root_sfc;
 
-    if (!server->captured.data ||
-        (!server->captured.dirty && invalidate_cnt <= 0)) {
+    if (!root_sfc) {
         goto out;
     }
 
-    server->captured.dirty = false;
-    updated = true;
-
-    sfc_bpp = vigs_format_bpp(server->captured.format);
-
     server->display_ops->resize(server->display_user_data,
-                                server->captured.width,
-                                server->captured.height);
+                                root_sfc->ws_sfc->width,
+                                root_sfc->ws_sfc->height);
 
     display_stride = server->display_ops->get_stride(server->display_user_data);
     display_bpp = server->display_ops->get_bpp(server->display_user_data);
     display_data = server->display_ops->get_data(server->display_user_data);
 
-    if (sfc_bpp != display_bpp) {
-        VIGS_LOG_CRITICAL("bpp mismatch");
+    if ((vigs_format_bpp(root_sfc->format) != display_bpp) ||
+        (root_sfc->stride != display_stride)) {
+        VIGS_LOG_CRITICAL("bpp/format mismatch");
         assert(false);
-        exit(1);
-    }
-
-    if (display_stride == server->captured.stride) {
-        switch (server->captured.format) {
-        case vigsp_surface_bgrx8888:
-        case vigsp_surface_bgra8888:
-            memcpy(display_data,
-                   server->captured.data,
-                   server->captured.height * display_stride);
-            break;
-        default:
-            assert(false);
-            VIGS_LOG_CRITICAL("unknown format: %d", server->captured.format);
-            exit(1);
+        goto out;
+    }
+
+    for (i = 0; i < VIGS_MAX_PLANES; ++i) {
+        /*
+         * If plane was moved/resized or turned on/off
+         * then we're dirty.
+         */
+        if (server->planes[i].is_dirty) {
+            planes_dirty = true;
         }
-    } else {
-        uint32_t i;
-        uint8_t *src = server->captured.data;
-        uint8_t *dst = display_data;
-
-        for (i = 0; i < server->captured.height; ++i) {
-            switch (server->captured.format) {
-            case vigsp_surface_bgrx8888:
-            case vigsp_surface_bgra8888:
-                memcpy(dst, src, server->captured.width * sfc_bpp);
-                break;
-            default:
-                assert(false);
-                VIGS_LOG_CRITICAL("unknown format: %d", server->captured.format);
-                exit(1);
+
+        if (server->planes[i].sfc) {
+            planes_on = true;
+
+            /*
+             * If plane's surface is dirty then we're dirty.
+             */
+            if (server->planes[i].sfc->is_dirty) {
+                planes_dirty = true;
             }
-            src += server->captured.stride;
-            dst += display_stride;
         }
     }
 
-out:
-    qemu_mutex_unlock(&server->capture_mutex);
+    if (root_sfc->ptr && !root_sfc->is_dirty && !planes_on) {
+        /*
+         * Root surface is scanout, it's not dirty and planes not on.
+         */
 
-    if (!server->is_capturing) {
-        struct vigs_server_work_item *item;
+        memcpy(display_data,
+               root_sfc->ptr,
+               root_sfc->stride * root_sfc->ws_sfc->height);
 
-        item = g_malloc(sizeof(*item));
+        updated = true;
+    } else if (root_sfc->ptr || root_sfc->is_dirty || planes_dirty || (invalidate_cnt > 0)) {
+        /*
+         * Composite root surface and planes.
+         */
 
-        work_queue_item_init(&item->base, &vigs_server_update_display_work);
+        updated = server->backend->composite(root_sfc,
+                                             &server->planes[0],
+                                             display_data);
 
-        item->server = server;
+        root_sfc->is_dirty = false;
 
-        server->is_capturing = true;
+        for (i = 0; i < VIGS_MAX_PLANES; ++i) {
+            if (server->planes[i].is_dirty) {
+                server->planes[i].is_dirty = false;
+            }
 
-        work_queue_add_item(server->render_queue, &item->base);
+            if (server->planes[i].sfc &&
+                server->planes[i].sfc->is_dirty) {
+                server->planes[i].sfc->is_dirty = false;
+            }
+        }
     }
 
+out:
+    qemu_mutex_unlock(&server->dpy_mutex);
+
     return updated;
 }
index 7bb902bd8717789f79c2875d78befc7c1149f3e7..6614dce83cdc098f163d7856e7d8ec6e1393f4ab 100644 (file)
@@ -96,21 +96,7 @@ struct vigs_server
 
     struct vigs_plane planes[VIGS_MAX_PLANES];
 
-    QemuMutex capture_mutex;
-
-    bool is_capturing;
-
-    uint32_t capture_fence_seq;
-
-    struct
-    {
-        uint8_t *data;
-        uint32_t width;
-        uint32_t height;
-        uint32_t stride;
-        vigsp_surface_format format;
-        bool dirty;
-    } captured;
+    QemuMutex dpy_mutex;
 
     /*
      * @}
index 5991089237fc766718251cef2ec89ba3f426512d..991661b4308a585ea7a8e8054bb9e2f777031718 100644 (file)
@@ -364,33 +364,29 @@ static struct vigs_surface *vigs_sw_backend_create_surface(struct vigs_backend *
     return &sw_sfc->base;
 }
 
-static void vigs_sw_backend_composite(struct vigs_surface *surface,
+static bool vigs_sw_backend_composite(struct vigs_surface *surface,
                                       const struct vigs_plane *planes,
-                                      vigs_composite_start_cb start_cb,
-                                      vigs_composite_end_cb end_cb,
-                                      void *user_data)
+                                      uint8_t *display_data)
 {
     struct vigs_sw_surface *sw_sfc = (struct vigs_sw_surface*)surface;
-    uint8_t *buff;
 
     /*
      * TODO: Render planes.
      */
 
-    buff = start_cb(user_data, surface->ws_sfc->width, surface->ws_sfc->height,
-                    surface->stride, surface->format);
-
     if (surface->ptr) {
-        memcpy(buff,
+        memcpy(display_data,
                surface->ptr,
                surface->stride * surface->ws_sfc->height);
+        return true;
     } else if (surface->is_dirty) {
-        memcpy(buff,
+        memcpy(display_data,
                sw_sfc->data,
                surface->stride * surface->ws_sfc->height);
+        return true;
     }
 
-    end_cb(user_data, true, true);
+    return false;
 }
 
 static void vigs_sw_backend_batch_end(struct vigs_backend *backend)
index 5c585e662043e669f8d4a37938a2898310cbc31c..d351ae90212855a97525ecec013a4a5b0cf1dbbd 100644 (file)
@@ -54,6 +54,19 @@ static void maru_display_notify_exit(Notifier *notifier, void *data) {
 }
 static Notifier maru_display_exit = { .notify = maru_display_notify_exit };
 
+void maru_display_early_init(DisplayType display_type)
+{
+    switch (display_type) {
+#ifdef CONFIG_QT
+    case DT_MARU_QT:
+        maru_qt5_display_early_init();
+        break;
+#endif
+    default:
+        break;
+    }
+}
+
 //TODO: interface
 void maru_display_init(DisplayState *ds, DisplayType display_type, int full_screen)
 {
index b1ff6f63d7178b8f346a1ebc7efd9fa651b32540..a4814cbfd3e864495bbb8bbb0b72b17296faf98b 100644 (file)
@@ -52,6 +52,7 @@ typedef struct MaruScreenShot {
     bool ready;
 } MaruScreenShot;
 
+void maru_display_early_init(DisplayType display_type);
 void maru_display_init(DisplayState *ds, DisplayType display_type, int full_screen);
 void maru_display_resize(void);
 void maru_display_update(void);
@@ -72,6 +73,8 @@ void maru_sdl_pre_init(MaruDisplayChangeListener *mdcl);
 void maru_shm_pre_init(MaruDisplayChangeListener *mdcl);
 
 // maru_qt
+void maru_qt5_display_early_init(void);
+
 void maru_qt5_display_init(MaruDisplayChangeListener *mdcl, int full_screen);
 
 #endif /* __MARU_DISPLAY_H__ */
index 64e3976f6ade7aa7fcc5bdcf588a9318f0991495..43d3c30aab6ce36b7c50f2029230cfdd87d53646 100644 (file)
@@ -60,8 +60,9 @@ static void qt5_switch(DisplayChangeListener *dcl,
 
 static void qt5_refresh(DisplayChangeListener *dcl)
 {
+    qt5_pre_refresh_internal();
     graphic_hw_update(dcl->con);
-    qt5_refresh_internal();
+    qt5_post_refresh_internal();
 }
 
 static void qt5_mouse_warp(DisplayChangeListener *dcl,
@@ -83,6 +84,11 @@ static const DisplayChangeListenerOps dcl_ops = {
     .dpy_cursor_define = qt5_mouse_define,
 };
 
+void maru_qt5_display_early_init(void)
+{
+    qt5_early_prepare();
+}
+
 void maru_qt5_display_init(MaruDisplayChangeListener *mdcl, int full_screen)
 {
     int i;
index 87a1507823879e5e522bcd11b05232193a1669f7..0003cd9589e1872ef01903d8beddc2335dbebe59 100644 (file)
@@ -115,6 +115,13 @@ void qt5_skin_init(void)
 //    app.exec();
 }
 
+void qt5_early_prepare(void)
+{
+    Q_INIT_RESOURCE(resource);
+
+    app = new QApplication(argc, argv);
+}
+
 void qt5_prepare(void)
 {
     qt5_skin_init();
@@ -140,8 +147,14 @@ void qt5_switch_internal(void)
 {
 }
 
-void qt5_refresh_internal(void)
+void qt5_pre_refresh_internal(void)
+{
+    mainwindow->makeCurrent(true);
+}
+
+void qt5_post_refresh_internal(void)
 {
+    mainwindow->makeCurrent(false);
     app->processEvents();
 }
 
index c83410b04796a58d57c45424fef11a2154672a61..999c34ebc8bae472c1646e57149110b8f6194bd1 100644 (file)
@@ -48,11 +48,13 @@ private:
 #ifdef __cplusplus
 extern "C" {
 #endif
+void qt5_early_prepare(void);
 void qt5_prepare(void);
 
 void qt5_update_internal(void *data, int width, int height);
 void qt5_switch_internal(void);
-void qt5_refresh_internal(void);
+void qt5_pre_refresh_internal(void);
+void qt5_post_refresh_internal(void);
 #ifdef __cplusplus
 }
 #endif
index b1593618528588385f2dee4c3604ed76e0eebb6b..e92fd36ee362a11abba7078b0b251832bcbcf592 100644 (file)
@@ -8,8 +8,8 @@ void do_mouse_event(int button_type, int event_type,
     int origin_x, int origin_y, int x, int y, int z);
 }
 
-DisplayWidget::DisplayWidget(QSize resolution, QWidget *parent) :
-    QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
+DisplayWidget::DisplayWidget(QSize resolution, QGLContext *context, QWidget *parent) :
+    QGLWidget(context, parent)
 {
     /* initialize */
     // TODO: compare display region with resolution
@@ -21,51 +21,13 @@ DisplayWidget::DisplayWidget(QSize resolution, QWidget *parent) :
     elapsed = 0;
 
     //setAutoFillBackground(false);
+
+    setAutoBufferSwap(false);
 }
 
 void DisplayWidget::initializeGL()
 {
     qDebug("initialize GL");
-
-    QTimer *timer = new QTimer(this);
-    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
-    timer->start(300);
-}
-
-void DisplayWidget::update()
-{
-    elapsed += 100;
-    repaint();
-}
-
-void DisplayWidget::paintEvent(QPaintEvent *event)
-{
-    /* temporary */
-
-    QPainter painter;
-    painter.begin(this);
-    painter.setRenderHint(QPainter::Antialiasing);
-
-    painter.fillRect(event->rect(), QBrush(QColor(255, 255, 255)));
-    painter.translate(size().width() / 2, size().height() / 2);
-
-    painter.scale(scaleFactor, scaleFactor);
-    painter.rotate(rotateAngle);
-
-    /* drawing */
-    painter.save();
-    painter.rotate(elapsed * 0.030);
-
-    for (int i = 0; i < 11; ++i) {
-        painter.rotate(30);
-        qreal circleRadius = 20;
-        painter.drawEllipse(QRect(120, -circleRadius, circleRadius * 2, circleRadius * 2));
-    }
-    painter.restore();
-
-    painter.drawText(QRect(0, 0, 50, 50), Qt::AlignCenter, "Tizen");
-
-    painter.end();
 }
 
 void DisplayWidget::rotate(int angle)
index 69e6a39c725f19cf11d26280775afea6bac1edb7..6bdf09ab04f69c23b16e57904a9ef6ca78275a05 100644 (file)
@@ -8,19 +8,15 @@ class DisplayWidget : public QGLWidget
     Q_OBJECT
 
 public:
-    DisplayWidget(QSize resolution, QWidget *parent = 0);
+    DisplayWidget(QSize resolution, QGLContext *context, QWidget *parent = 0);
     ~DisplayWidget();
 
     void rotate(int angle);
     void scale(int scale);
 
-public slots:
-    void update();
-
 protected:
     void initializeGL();
 
-    void paintEvent(QPaintEvent *event);
     void resizeEvent(QResizeEvent *event);
 
     void mousePressEvent(QMouseEvent *event);
index 5a4b609ae7a14acf298a3a5e7a6796e22751ae90..09c48b038e0752083b72e383a740e040c4ae24b8 100644 (file)
@@ -9,6 +9,9 @@
 extern "C" void shutdown_qemu_gracefully(void);
 #endif
 
+QOpenGLContext *qt5GLContext = NULL;
+QSurfaceFormat qt5GLFormat;
+
 MainWindow::MainWindow(UIInformation *uiInfo, QWidget *parent) :
     QWidget(parent)
 {
@@ -61,8 +64,28 @@ MainWindow::MainWindow(UIInformation *uiInfo, QWidget *parent) :
         winLayout->addWidget(conView);
     }
 
+    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);
+
     /* display */
-    display = new DisplayWidget(uiInfo->resolution, skinView);
+    display = new DisplayWidget(uiInfo->resolution, context, skinView);
+
+    context->setFormat(format);
+
+    context->create(wrapperContext);
 
     /* popup menu */
     popupMenu = new ContextMenu(this);
@@ -77,6 +100,16 @@ QLabel *MainWindow::getLabel()
     return label;
 }
 
+void MainWindow::makeCurrent(bool value)
+{
+    if (value) {
+        display->makeCurrent();
+    } else {
+        display->swapBuffers();
+        display->doneCurrent();
+    }
+}
+
 void MainWindow::showContextMenu(const QPoint& pos)
 {
     QPoint globalPos = this->mapToGlobal(pos);
index 2ffd47dc5a445b28c1af832140eb8c79141361f0..363b599dcfd3f3f179d83586973db07d638f54d8 100644 (file)
@@ -29,6 +29,9 @@ public:
     UIInformation *uiInfo;
     QLabel *getLabel();
     QImage *image;
+
+    void makeCurrent(bool value);
+
 public slots:
     void showContextMenu(const QPoint& pos);
 
diff --git a/vl.c b/vl.c
index bfbd739c8b4210d6c6ca5ea1e46d6ac8fcbe81f0..35a248e6b026f36d0aaff96f84ac6d35d7cd2ee0 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -4065,6 +4065,8 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+    maru_display_early_init(display_type);
+
     current_machine = MACHINE(object_new(object_class_get_name(
                           OBJECT_CLASS(machine_class))));
     object_property_add_child(object_get_root(), "machine",