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"
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
#include "display.h"
+#include "vigs_qt5.h"
#include "qom/object_interfaces.h"
#if defined(CONFIG_LINUX)
#include <X11/Xlib.h>
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");
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;
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*/);
};
#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;
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,
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":
NULL);
ws_sfc->backend->BindTexture(GL_TEXTURE_2D, cur_tex);
+ ws_sfc->tex = tmp_tex;
+
return true;
}
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;
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;
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) {
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,
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...
*/
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)
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;
}
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);
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;
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);
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);
}
#include <GL/glext.h>
#include "winsys_gl.h"
-struct work_queue;
struct vigs_gl_pool;
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.
* @{
*/
/*
- * Other.
+ * Rendering thread related.
+ * @{
*/
GLuint vao;
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);
#include "vigs_gl_backend.h"
#include "vigs_log.h"
+#include "vigs_qt5.h"
#include <GL/glx.h>
#include <dlfcn.h>
PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
PFNGLXGETCURRENTCONTEXTPROC glXGetCurrentContext;
PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
+ PFNGLXQUERYCONTEXTPROC glXQueryContext;
/* GLX_ARB_create_context */
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
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,
{
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,
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 =
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);
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);
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) {
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);
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
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));
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;
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,
goto out;
}
+ qemu_mutex_lock(&server->dpy_mutex);
+
if (item->id == 0) {
if (server->root_sfc) {
vigs_surface_set_scanout(server->root_sfc, NULL);
}
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);
}
{
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));
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);
}
}
NULL,
vigs_server_surface_destroy_func);
- qemu_mutex_init(&server->capture_mutex);
+ qemu_mutex_init(&server->dpy_mutex);
return 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);
}
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;
}
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;
/*
* @}
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)
}
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)
{
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);
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__ */
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,
.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;
// app.exec();
}
+void qt5_early_prepare(void)
+{
+ Q_INIT_RESOURCE(resource);
+
+ app = new QApplication(argc, argv);
+}
+
void qt5_prepare(void)
{
qt5_skin_init();
{
}
-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();
}
#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
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
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)
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);
extern "C" void shutdown_qemu_gracefully(void);
#endif
+QOpenGLContext *qt5GLContext = NULL;
+QSurfaceFormat qt5GLFormat;
+
MainWindow::MainWindow(UIInformation *uiInfo, QWidget *parent) :
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);
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);
UIInformation *uiInfo;
QLabel *getLabel();
QImage *image;
+
+ void makeCurrent(bool value);
+
public slots:
void showContextMenu(const QPoint& pos);
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",