display: fix blinking display issue with OpenGL 2.1
authorJinhyung Jo <jinhyung.jo@samsung.com>
Wed, 9 Nov 2016 06:52:27 +0000 (15:52 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Fri, 2 Dec 2016 08:31:25 +0000 (17:31 +0900)
Use the texture arrays to avoid collisions.

The glBufferSubData function makes the display blink
with OpenGL verion 2.1 have no glMapBufferRange support.
The glMapBuffer function helps to solve this problem.

Use the Qt5 class API(QOpenGLShaderProgram) instead of the OpenGL API.
That's a little clearer and better to watch.

Use multiple buffering to avoid performance degration.

Change-Id: I819a52f7e0db5accded86b71c8a15fa1a9e65e28
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
hw/vigs/vigs_gl_backend.c
hw/vigs/vigs_gl_backend.h
hw/vigs/vigs_qt5.cpp
hw/vigs/vigs_qt5.h
hw/yagl/yagl_apis/gles/yagl_host_gles_calls.c
tizen/src/ui/displayglwidget.cpp
tizen/src/ui/displayglwidget.h
tizen/src/ui/mainwindow.cpp
tizen/src/ui/mainwindow.h
tizen/src/ui/qt5_supplement.cpp

index 9995d1c15a087f20d3e04fc26017bfa2f893188c..c09e081b0b5c1522e06dcefd87ae7b30a7dac1a2 100644 (file)
@@ -527,11 +527,19 @@ static void vigs_gl_draw_update_vert_tex_buffer(struct vigs_gl_backend *backend,
             VIGS_LOG_ERROR("glMapBufferRange failed");
         }
     } else {
-        backend->Finish();
-        backend->BufferSubData(GL_ARRAY_BUFFER, 0,
-                               (size / 2), vigs_vector_data(&backend->v1));
-        backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2),
-                               (size / 2), vigs_vector_data(&backend->v2));
+        ptr = backend->MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+        if (ptr) {
+            memcpy(ptr, vigs_vector_data(&backend->v1), size / 2);
+            memcpy(ptr + (size / 2), vigs_vector_data(&backend->v2), size / 2);
+
+            backend->UnmapBuffer(GL_ARRAY_BUFFER);
+        } else {
+            backend->Finish();
+            backend->BufferSubData(GL_ARRAY_BUFFER, 0,
+                                   (size / 2), vigs_vector_data(&backend->v1));
+            backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2),
+                                   (size / 2), vigs_vector_data(&backend->v2));
+        }
     }
 }
 
@@ -583,9 +591,16 @@ static void vigs_gl_draw_color_prog(struct vigs_gl_backend *backend,
             VIGS_LOG_ERROR("glMapBufferRange failed");
         }
     } else {
-        backend->Finish();
-        backend->BufferSubData(GL_ARRAY_BUFFER, 0, size,
-                               vigs_vector_data(&backend->v1));
+        ptr = backend->MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+        if (ptr) {
+            memcpy(ptr, vigs_vector_data(&backend->v1), size);
+
+            backend->UnmapBuffer(GL_ARRAY_BUFFER);
+        } else {
+            backend->Finish();
+            backend->BufferSubData(GL_ARRAY_BUFFER, 0, size,
+                                   vigs_vector_data(&backend->v1));
+        }
     }
 
     backend->Uniform4fv(backend->color_prog_color_loc, 1, color);
@@ -770,14 +785,40 @@ static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend,
 {
     GLuint cur_tex = 0;
 
-    gl_backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex);
+    if (vigs_qt5_onscreen_enabled()) {
+        // find available texture by iteration.
+        // it is OK, since we have only very few textures.
+        gl_backend->current_dpy = NULL;
+        int i;
+        for (i = 0; i < TEXTURE_NUM; ++i) {
+            struct dpy_item *item = &(gl_backend->dpy_items[i]);
+            if(likely(!qemu_mutex_trylock(&item->mutex))) {
+                if (item->available) {
+                    item->available = false;
+                    gl_backend->current_dpy = item;
+                    qemu_mutex_unlock(&item->mutex);
+                    break;
+                }
+                qemu_mutex_unlock(&item->mutex);
+            }
+        }
+        if (unlikely(!gl_backend->current_dpy)) {
+            // can not enter here.
+            // simply we drop this frame.
+            return false;
+        }
+    } else {
+        gl_backend->current_dpy = &gl_backend->dpy_items[0];
+    }
+
+    gl_backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&cur_tex);
 
-    if (gl_backend->dpy_tex) {
-        if ((gl_backend->dpy_tex_width == width) &&
-            (gl_backend->dpy_tex_height == height)) {
+    if (gl_backend->current_dpy->tex) {
+        if ((gl_backend->current_dpy->width == width) &&
+            (gl_backend->current_dpy->height == height)) {
             return true;
         }
-        gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->dpy_tex);
+        gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->current_dpy->tex);
     } else {
         GLuint tmp_tex = 0;
 
@@ -787,7 +828,7 @@ static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend,
             return false;
         }
 
-        gl_backend->dpy_tex = tmp_tex;
+        gl_backend->current_dpy->tex = tmp_tex;
 
         gl_backend->BindTexture(GL_TEXTURE_2D, tmp_tex);
 
@@ -804,8 +845,8 @@ static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend,
 
     gl_backend->BindTexture(GL_TEXTURE_2D, cur_tex);
 
-    gl_backend->dpy_tex_width = width;
-    gl_backend->dpy_tex_height = height;
+    gl_backend->current_dpy->width = width;
+    gl_backend->current_dpy->height = height;
 
     return true;
 }
@@ -2040,7 +2081,7 @@ static bool vigs_gl_backend_composite(struct vigs_surface *surface,
     }
 
     gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                     GL_TEXTURE_2D, gl_backend->dpy_tex, 0);
+                                     GL_TEXTURE_2D, gl_backend->current_dpy->tex, 0);
 
     gl_backend->Clear(GL_COLOR_BUFFER_BIT);
 
@@ -2144,10 +2185,10 @@ static bool vigs_gl_backend_capture(struct vigs_surface *surface,
 
         gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb);
         gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                         GL_TEXTURE_2D, gl_backend->dpy_tex, 0);
+                                         GL_TEXTURE_2D, gl_backend->current_dpy->tex, 0);
 
-        gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width,
-                               gl_backend->dpy_tex_height,
+        gl_backend->ReadPixels(0, 0, gl_backend->current_dpy->width,
+                               gl_backend->current_dpy->height,
                                GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                                pixels);
         gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -2176,7 +2217,9 @@ static bool vigs_gl_backend_display(struct vigs_backend *backend,
     VIGS_LOG_TRACE("enter");
 
     if (vigs_qt5_onscreen_enabled()) {
-        vigs_qt5_dpy_render_texture(gl_backend->dpy_tex);
+        if (gl_backend->current_dpy && gl_backend->current_dpy->tex) {
+            vigs_qt5_dpy_render_texture(gl_backend->current_dpy);
+        }
         return true;
     }
 
@@ -2192,10 +2235,10 @@ static bool vigs_gl_backend_display(struct vigs_backend *backend,
         }
 
         gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                         GL_TEXTURE_2D, gl_backend->dpy_tex, 0);
+                                         GL_TEXTURE_2D, gl_backend->current_dpy->tex, 0);
 
-        gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width,
-                               gl_backend->dpy_tex_height,
+        gl_backend->ReadPixels(0, 0, gl_backend->current_dpy->width,
+                               gl_backend->current_dpy->height,
                                GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                                display_data);
 
@@ -2408,6 +2451,12 @@ 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);
 
+    int i;
+    for (i = 0; i < TEXTURE_NUM; ++i) {
+        gl_backend->dpy_items[i].available = true;
+        qemu_mutex_init(&gl_backend->dpy_items[i].mutex);
+    }
+
     return true;
 
 fail:
@@ -2419,8 +2468,12 @@ fail:
 void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend)
 {
     if (gl_backend->make_current(gl_backend, true)) {
-        if (gl_backend->dpy_tex) {
-            gl_backend->DeleteTextures(1, &gl_backend->dpy_tex);
+        int i;
+        for (i = 0; i < TEXTURE_NUM; i++) {
+            if (gl_backend->dpy_items[i].tex) {
+                gl_backend->DeleteTextures(1, &gl_backend->dpy_items[i].tex);
+            }
+            qemu_mutex_destroy(&gl_backend->dpy_items[i].mutex);
         }
         if (gl_backend->dpy_fb) {
             gl_backend->DeleteFramebuffers(1, &gl_backend->dpy_fb);
index ca2d3658abc4cfdbb9f8d5b71debd6e90e8ec897..c9cd54e3c2da651d07e010037f89a4add5af7424 100644 (file)
@@ -37,6 +37,8 @@
 #include <GL/glext.h>
 #include "winsys_gl.h"
 
+#define TEXTURE_NUM 5
+
 struct vigs_gl_pool;
 
 struct vigs_gl_backend
@@ -220,10 +222,19 @@ struct vigs_gl_backend
      * Display thread related.
      * @{
      */
-    GLuint dpy_tex;
+
+    struct dpy_item {
+        GLuint tex;
+        uint32_t width;
+        uint32_t height;
+
+        bool available;
+        QemuMutex mutex;
+    } dpy_items[TEXTURE_NUM], *current_dpy;
+
+    uint32_t dpy_idx;
+
     GLuint dpy_fb;
-    uint32_t dpy_tex_width;
-    uint32_t dpy_tex_height;
 
     /*
      * @}
index 286014eff7069dbd40fae0a3f12f5f50cc1fe677..e33817a61e9a63343a32071aca0e1657166a48b5 100644 (file)
@@ -43,7 +43,7 @@ extern void qt5_register_capture_request_listener(void *listener,
 extern void qt5_unregister_capture_request_listener(void *listener);
 extern void qt5_process_captured(bool captured, void *pixels,
                                  int width, int height);
-extern void qt5_update_texture(unsigned int tex_id);
+extern void qt5_update_texture(void *dpy_item);
 
 bool vigs_qt5_onscreen_enabled(void)
 {
@@ -114,7 +114,7 @@ void vigs_qt5_process_captured(bool captured, void *pixels,
     qt5_process_captured(captured, pixels, width, height);
 }
 
-void vigs_qt5_dpy_render_texture(uint32_t tex_id)
+void vigs_qt5_dpy_render_texture(void *dpy_item)
 {
-    qt5_update_texture(tex_id);
+    qt5_update_texture(dpy_item);
 }
index a27ae6184bc3b7ea8ed60f0b3f586ba67f7c8a62..168095b1d7753594c062057b314632de49797e78 100644 (file)
@@ -45,7 +45,7 @@ void vigs_qt5_register_capture_request_listener(void *listener,
 void vigs_qt5_unregister_capture_request_listener(void *listener);
 void vigs_qt5_process_captured(bool captured, void *pixels,
                                int width, int height);
-void vigs_qt5_dpy_render_texture(uint32_t tex_id);
+void vigs_qt5_dpy_render_texture(void *dpy_item);
 #ifdef __cplusplus
 };
 #endif
index d6eae0ca7daaf3c81a88693c75bef0654c38f45f..af3efbd11d0faf34e1bd6f6bbd00a7727b7f48c5 100644 (file)
@@ -122,10 +122,20 @@ static GLuint yagl_gles_bind_array(uint32_t indx,
             YAGL_LOG_ERROR("glMapBufferRange failed");
         }
     } else {
-        gles_api_ts->driver->Finish();
-        gles_api_ts->driver->BufferSubData(GL_ARRAY_BUFFER,
-                                           first * stride, data_count,
-                                           data);
+        ptr = gles_api_ts->driver->MapBuffer(GL_ARRAY_BUFFER,
+                                             GL_WRITE_ONLY);
+
+        if (ptr) {
+            void *addr = (void *)((uintptr_t)ptr + (uintptr_t)(first * stride));
+            memcpy(addr, data, data_count);
+
+            gles_api_ts->driver->UnmapBuffer(GL_ARRAY_BUFFER);
+        } else {
+            gles_api_ts->driver->Finish();
+            gles_api_ts->driver->BufferSubData(GL_ARRAY_BUFFER,
+                                               first * stride, data_count,
+                                               data);
+        }
     }
 
     return current_vbo;
@@ -168,9 +178,18 @@ static GLuint yagl_gles_bind_ebo(const GLvoid *data, int32_t size)
             YAGL_LOG_ERROR("glMapBufferRange failed");
         }
     } else {
-        gles_api_ts->driver->Finish();
-        gles_api_ts->driver->BufferSubData(GL_ELEMENT_ARRAY_BUFFER,
-                                           0, size, data);
+        ptr = gles_api_ts->driver->MapBuffer(GL_ELEMENT_ARRAY_BUFFER,
+                                             GL_WRITE_ONLY);
+
+        if (ptr) {
+            memcpy(ptr, data, size);
+
+            gles_api_ts->driver->UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+        } else {
+            gles_api_ts->driver->Finish();
+            gles_api_ts->driver->BufferSubData(GL_ELEMENT_ARRAY_BUFFER,
+                                               0, size, data);
+        }
     }
 
     return current_ebo;
@@ -913,8 +932,25 @@ void yagl_host_glBufferSubData(GLenum target,
             YAGL_LOG_ERROR("glMapBufferRange failed");
         }
     } else {
-        gles_api_ts->driver->Finish();
-        gles_api_ts->driver->BufferSubData(target, offset, data_count, data);
+        if (target == GL_ARRAY_BUFFER ||
+            target == GL_ELEMENT_ARRAY_BUFFER ||
+            target == GL_PIXEL_PACK_BUFFER ||
+            target == GL_PIXEL_UNPACK_BUFFER) {
+            ptr = gles_api_ts->driver->MapBuffer(target, GL_WRITE_ONLY);
+
+            if (ptr) {
+                void *addr = (void *)((uintptr_t)ptr + (uintptr_t)(offset));
+                memcpy(addr, data, data_count);
+
+                gles_api_ts->driver->UnmapBuffer(target);
+            } else {
+                YAGL_LOG_ERROR("glMapBuffer failed");
+            }
+        } else {
+            gles_api_ts->driver->Finish();
+            gles_api_ts->driver->BufferSubData(target, offset,
+                                               data_count, data);
+        }
     }
 }
 
index 0a9d06d26d98100b4d83dc59bc482ac39b05b1fb..14aa91b935eaa05188d7bcb09923727a40716518 100644 (file)
@@ -212,20 +212,28 @@ DisplayGLWidget::DisplayGLWidget(QWidget *parent,
     this->maskQImage = displayForm->getMask().toImage();
     this->maskTexture = 0;
     this->needScale = false;
-    this->dpyTexture = 0;
     this->mtTexture = 0;
     this->texProgram = NULL;
     this->scaleProgram = NULL;
+    this->next = NULL;
+    this->current = NULL;
 
     /* to be enable to drop events */
     setAcceptDrops(true);
 }
 
-void DisplayGLWidget::changedTexture(unsigned int id)
+void DisplayGLWidget::changedTexture(struct dpy_item *item)
 {
-    if (dpyTexture != id) {
-        dpyTexture = id;
+    // wait while "next" is being updated since it is fast enough.
+    textureListMutex.lock();
+    if (next) {
+        qemu_mutex_lock(&next->mutex);
+        next->available = true;
+        qemu_mutex_unlock(&next->mutex);
     }
+    next = item;
+    textureListMutex.unlock();
+
     this->update();
 }
 
@@ -247,8 +255,6 @@ void DisplayGLWidget::drawQuad(GLuint textureID, bool isMask)
     program->bind();
     program->enableAttributeArray("vertCoord");
     program->enableAttributeArray("texCoord");
-    int vertCoordLoc = program->attributeLocation("vertCoord");
-    int texCoordLoc = program->attributeLocation("texCoord");
     program->setUniformValue("proj", mOrtho);
     if (needScale) {
         GLfloat texSize[2];
@@ -261,9 +267,8 @@ void DisplayGLWidget::drawQuad(GLuint textureID, bool isMask)
     mVBO->bind();
     mVBO->write(0, mVertCoords, COORDS_SIZE);
     mVBO->write(COORDS_SIZE, mTexCoords, COORDS_SIZE);
-    mFuncs->glVertexAttribPointer(vertCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
-    mFuncs->glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0,
-                                  TO_VOIDP(COORDS_SIZE));
+    program->setAttributeArray("vertCoord", GL_FLOAT, NULL, 2, 0);
+    program->setAttributeArray("texCoord", GL_FLOAT, TO_VOIDP(COORDS_SIZE), 2, 0);
     mVBO->release();
 
     mFuncs->glDrawArrays(GL_TRIANGLES, 0, COORD_COUNT);
@@ -314,8 +319,6 @@ void DisplayGLWidget::drawMultiTouchPoints()
     texProgram->bind();
     texProgram->enableAttributeArray("vertCoord");
     texProgram->enableAttributeArray("texCoord");
-    int vertCoordLoc = texProgram->attributeLocation("vertCoord");
-    int texCoordLoc = texProgram->attributeLocation("texCoord");
 
     QMatrix4x4 mat;
     mat.ortho(0.0f, (float)width(),
@@ -323,10 +326,10 @@ void DisplayGLWidget::drawMultiTouchPoints()
               -1.0f, 1.0f);
     texProgram->setUniformValue("proj", mat);
     texProgram->setUniformValue("brightness", 0.7f);
-
-    mFuncs->glVertexAttribPointer(vertCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
-    mFuncs->glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0,
-                                  TO_VOIDP(pointList.count() * COORDS_SIZE));
+    texProgram->setAttributeArray("vertCoord", GL_FLOAT, NULL, 2, 0);
+    texProgram->setAttributeArray("texCoord", GL_FLOAT,
+                                  TO_VOIDP(pointList.count() * COORDS_SIZE),
+                                  2, 0);
     mVBO->release();
 
     mFuncs->glDrawArrays(GL_TRIANGLES, 0, pointList.count() * COORD_COUNT);
@@ -427,14 +430,14 @@ void DisplayGLWidget::initializeGL()
                              (const void *)maskQImage.constBits());
         mFuncs->glBindTexture(GL_TEXTURE_2D, curTexture);
     }
+    mFuncs->glDisable(GL_DEPTH_TEST);
+    mFuncs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    mFuncs->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 }
 
 /* override */
 void DisplayGLWidget::paintGL()
 {
-    mFuncs->glDisable(GL_DEPTH_TEST);
-    mFuncs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    mFuncs->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
     mFuncs->glEnable(GL_BLEND);
 
     if (maskTexture) {
@@ -450,9 +453,25 @@ void DisplayGLWidget::paintGL()
                  0.0f, (float)mGuestResolution.height(),
                  -1.0f, 1.0f);
     needScale = (mGuestResolution.width() != width())
-                 || (mGuestResolution.height() != height());
+        || (mGuestResolution.height() != height());
+
+    // wait while "next" is being updated since it is fast enough.
+    textureListMutex.lock();
+    if (next) {
+        if (current) {
+            qemu_mutex_lock(&current->mutex);
+            current->available = true;
+            qemu_mutex_unlock(&current->mutex);
+        }
+        current = next;
+        next = NULL;
+    }
+    textureListMutex.unlock();
+
+    if (current) {
+        drawQuad(current->tex, false);
+    }
 
-    drawQuad(dpyTexture, false);
     if (isTsEnabled) {
         drawMultiTouchPoints();
     }
index cc327f56a660bf1f207ef6e630609f9c3a64c510..2008fc793eeaeee191ea2778d4fee4484abb8497 100644 (file)
 
 
 #include "displaybase.h"
+#include <QMutex>
 #include <QOpenGLWidget>
 #include <QMatrix4x4>
 
+extern "C" {
+#include "qemu/thread.h"
+
+// FIXME: move it to common header
+struct dpy_item {
+    GLuint tex;
+    uint32_t width;
+    uint32_t height;
+
+    bool available;
+    QemuMutex mutex;
+};
+}
+
+
 class QOpenGLFunctions;
 class QOpenGLShaderProgram;
 class QOpenGLVertexArrayObject;
@@ -53,7 +69,7 @@ public:
                     QSize resolution, qreal scaleFactor);
     ~DisplayGLWidget();
 
-    void changedTexture(unsigned int texture);
+    void changedTexture(struct dpy_item *tex);
 
 protected:
     void initializeGL();
@@ -82,7 +98,10 @@ private:
     QImage maskQImage;
     GLuint maskTexture;
 
-    GLuint dpyTexture;
+    dpy_item* current;
+    dpy_item* next;
+    QMutex textureListMutex;
+
     GLuint mtTexture;
     QMatrix4x4 mOrtho;
     GLfloat mVertCoords[12];
@@ -92,6 +111,7 @@ private:
     QOpenGLBuffer *mVBO;
     QOpenGLShaderProgram *texProgram;
     QOpenGLShaderProgram *scaleProgram;
+
 };
 
 #endif // DISPLAYGLWIDGET_H
index de3818d88d685d5062211f4ed4f84dc48943f58f..52166086c333ebb8c402672288badb03ef444c34 100644 (file)
@@ -533,9 +533,9 @@ void MainWindow::turnOffMovingMode()
     isMovingMode = false;
 }
 
-void MainWindow::updateTexture(unsigned int texture)
+void MainWindow::updateTexture(void *item)
 {
-    ((DisplayGLWidget *)getDisplay())->changedTexture(texture);
+    ((DisplayGLWidget *)getDisplay())->changedTexture((struct dpy_item *)item);
 }
 
 /* override */
index 55696070e2085d73d18f6d53b29750d8717c1ec7..84159c7caecb568e56a6f6e113dc6734a516e53b 100644 (file)
@@ -88,7 +88,7 @@ public:
     void turnOnMovingMode();
     void turnOffMovingMode();
 
-    void updateTexture(unsigned int texture);
+    void updateTexture(void *dpy_item);
 
 public slots:
     void slotContextMenu(const QPoint &pos);
index 4ae6a2b43b1654f28dd6145a973e51a7d8369d89..ba7091f89aa5475bd80e30d7eb4285bf15ca5611 100644 (file)
@@ -594,9 +594,9 @@ void qt5_process_captured(bool captured, void *pixels, int width, int height)
     }
 }
 
-void qt5_update_texture(unsigned int tex_id)
+void qt5_update_texture(void *dpy_item)
 {
     if (mainwindow) {
-        mainwindow->updateTexture(tex_id);
+        mainwindow->updateTexture(dpy_item);
     }
 }