libvideorender: CB1 abnormal video display on weston [1/1]

PD#SWPL-177568

Problem:
Abnormal video display after switching resolution multiple times

Solution:
release zwp buffers after resolution changed

Verify:
ap222

Change-Id: I16a53c35624a907c23c3273c761274f07d83036f
Signed-off-by: fei.deng <fei.deng@amlogic.com>
diff --git a/weston/wayland_buffer.cpp b/weston/wayland_buffer.cpp
index 01d1cee..60605a3 100644
--- a/weston/wayland_buffer.cpp
+++ b/weston/wayland_buffer.cpp
@@ -49,7 +49,7 @@
     mBufferFormat = VIDEO_FORMAT_UNKNOWN;
     mFrameWidth = 0;
     mFrameHeight = 0;
-    TRACE(mLogCategory,"new WaylandBuffer:%p",this);
+    //TRACE(mLogCategory,"new WaylandBuffer:%p",this);
 }
 
 WaylandBuffer::~WaylandBuffer()
@@ -64,13 +64,13 @@
         delete mWaylandWlWrap;
         mWaylandWlWrap = NULL;
     }
-    TRACE(mLogCategory,"delete WaylandBuffer:%p",this);
+    //TRACE(mLogCategory,"delete WaylandBuffer:%p",this);
 }
 
 void WaylandBuffer::bufferRelease (void *data, struct wl_buffer *wl_buffer)
 {
     WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
-    TRACE(waylandBuffer->mLogCategory,"--wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
+    //TRACE(waylandBuffer->mLogCategory,"--wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
     waylandBuffer->mUsedByCompositor = false;
     //sometimes this callback be called twice
     //this cause double free,so check mRenderBuffer
@@ -79,14 +79,16 @@
         waylandBuffer->mRenderBuffer = NULL;
         waylandBuffer->mRealTime = -1;
     }
-    //release after buffer release callback
+    //release dma buffer if resolution changed after buffer release callback
     int fw = waylandBuffer->mDisplay->getFrameWidth();
     int fh = waylandBuffer->mDisplay->getFrameHeight();
     if ( (waylandBuffer->mFrameWidth != fw || waylandBuffer->mFrameHeight != fh) &&
             waylandBuffer->mWaylandWlWrap) {
         TRACE(waylandBuffer->mLogCategory,"resolution changed,delete WaylandBuffer:%p,WaylandDmaBuffer:%p",waylandBuffer,waylandBuffer->mWaylandWlWrap);
         delete waylandBuffer->mWaylandWlWrap;
+        waylandBuffer->mLock.lock();
         waylandBuffer->mWaylandWlWrap = NULL;
+        waylandBuffer->mLock.unlock();
     }
 }
 
@@ -122,7 +124,7 @@
     waylandBuffer->mRedrawingPending = false;
     waylandBuffer->mLock.unlock();
     if (waylandBuffer->mRenderBuffer && redrawing) {
-        TRACE(waylandBuffer->mLogCategory,"renderBuffer:%p, pts:%lld us",waylandBuffer->mRenderBuffer,waylandBuffer->mRenderBuffer->pts/1000);
+        //TRACE(waylandBuffer->mLogCategory,"renderBuffer:%p, pts:%lld us",waylandBuffer->mRenderBuffer,waylandBuffer->mRenderBuffer->pts/1000);
         waylandBuffer->mDisplay->handleFrameDisplayedCallback(waylandBuffer);
     }
     wl_callback_destroy (callback);
@@ -153,7 +155,7 @@
         mWaylandWlWrap = waylanddma;
         mFrameWidth = buf->dma.width;
         mFrameHeight = buf->dma.height;
-        TRACE(mLogCategory,"WaylandBuffer:%p,WaylandDmaBuffer:%p",this,mWaylandWlWrap);
+        //TRACE(mLogCategory,"WaylandBuffer:%p,WaylandDmaBuffer:%p",this,mWaylandWlWrap);
     }
 
     /*register buffer release listen*/
@@ -198,10 +200,27 @@
     mRedrawingPending = true;
 }
 
+/**
+ * @brief check wayland buffer is free. if this is free
+ * ,it will be delete by waylandbuffer manager
+ *
+ * @return true if this buffer is free
+ * @return false if this buffer will be used
+ */
 bool WaylandBuffer::isFree()
 {
+    int fw = mDisplay->getFrameWidth();
+    int fh = mDisplay->getFrameHeight();
+    Tls::Mutex::Autolock _l(mLock);
     if (!mWaylandWlWrap && !mRenderBuffer) {
         return true;
     }
+    /*if resolution changed,this buffer should be deleted after weston
+    release this buffer */
+    if ((mFrameWidth > 0 && mFrameHeight > 0 && fw > 0 && fh > 0) &&
+        (mFrameWidth != fw || mFrameHeight != fh) &&
+        !mRenderBuffer && !mUsedByCompositor) {
+        return true;
+    }
     return false;
 };
\ No newline at end of file
diff --git a/weston/wayland_display.cpp b/weston/wayland_display.cpp
index aa96bb9..69dac37 100644
--- a/weston/wayland_display.cpp
+++ b/weston/wayland_display.cpp
@@ -1290,6 +1290,7 @@
 {
     WaylandBuffer *waylandBuf = NULL;
     int ret;
+    bool isNew = false;
 
     if (!mDmabuf)
     {
@@ -1300,15 +1301,17 @@
     waylandBuf = findWaylandBuffer(buf);
     if (waylandBuf == NULL) {
         waylandBuf = new WaylandBuffer(this, mLogCategory);
-        waylandBuf->setBufferFormat(mBufferFormat);
-        ret = waylandBuf->constructWlBuffer(buf);
-        if (ret != NO_ERROR) {
-            WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
-            //delete waylanBuf,WaylandBuffer object destruct will call release callback
-            goto waylandbuf_fail;
-        } else {
-            addWaylandBuffer(buf, waylandBuf);
-        }
+        isNew = true;
+    }
+    waylandBuf->setBufferFormat(mBufferFormat);
+    ret = waylandBuf->constructWlBuffer(buf);
+    if (ret != NO_ERROR) {
+        WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
+        //delete waylanBuf,WaylandBuffer object destruct will call release callback
+        goto waylandbuf_fail;
+    }
+    if (isNew) {
+        addWaylandBuffer(buf, waylandBuf);
     }
     return NO_ERROR;
 waylandbuf_fail:
@@ -1336,6 +1339,9 @@
             ensureFullscreen(mFullScreen);
         }
         resizeVideoSurface(true);
+        /*clean wayland buffers those allocated
+        before resolution changed and had release by weston */
+        cleanWaylandBufferBeforeResChanged();
     }
     WaylandBuffer *waylandBuf = NULL;
     struct wl_buffer * wlbuffer = NULL;
@@ -1363,12 +1369,6 @@
         waylandBuf = findWaylandBuffer(buf);
         if (waylandBuf) {
             waylandBuf->setRenderRealTime(realDisplayTime);
-            ret = waylandBuf->constructWlBuffer(buf);
-            if (ret != NO_ERROR) {
-                WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
-                //delete waylanBuf,WaylandBuffer object destruct will call release callback
-                goto waylandbuf_fail;
-            }
         } else {
             ERROR(mLogCategory,"NOT found wayland buffer,please prepare buffer first");
             goto waylandbuf_fail;
@@ -1423,9 +1423,6 @@
     mWaylandPlugin->handleFrameDropped(buf);
     //notify app release this buf
     mWaylandPlugin->handleBufferRelease(buf);
-    //delete waylandbuf
-    delete waylandBuf;
-    waylandBuf = NULL;
     return;
 }
 
@@ -1520,15 +1517,15 @@
 void WaylandDisplay::videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling)
 {
     //if dst is a small window, we scale video to map window size,don't doing center
-    if (mRenderRect.w != dst.w && mRenderRect.h != dst.h) {
-        result->x = dst.x;
-        result->y = dst.y;
-        result->w = dst.w;
-        result->h = dst.h;
-        TRACE(mLogCategory,"small window source is %dx%d dest is %dx%d, result is %d,%d,%d,%d",
-        src.w, src.h, dst.w, dst.h, result->x, result->y, result->w, result->h);
-        return;
-    }
+    // if (mRenderRect.w != dst.w && mRenderRect.h != dst.h) {
+    //     result->x = dst.x;
+    //     result->y = dst.y;
+    //     result->w = dst.w;
+    //     result->h = dst.h;
+    //     TRACE(mLogCategory,"small window source is %dx%d dest is %dx%d, result is %d,%d,%d,%d",
+    //     src.w, src.h, dst.w, dst.h, result->x, result->y, result->w, result->h);
+    //     return;
+    // }
     if (!scaling) {
         result->w = MIN (src.w, dst.w);
         result->h = MIN (src.h, dst.h);
@@ -1593,7 +1590,7 @@
     std::string hashString("");
     for (int i = 0; i < dmabuf.planeCnt; i++) {
         char hashtmp[1024];
-        snprintf (hashtmp, 1024, "%d%d%d%d%d%d", dmabuf.width,dmabuf.height,dmabuf.planeCnt,
+        snprintf (hashtmp, 1024, "%d%d%d%d%d%d%d",i,dmabuf.width,dmabuf.height,dmabuf.planeCnt,
                 dmabuf.stride[i],dmabuf.offset[i],dmabuf.fd[i]);
         std::string tmp(hashtmp);
         hashString += tmp;
@@ -1612,17 +1609,6 @@
         //TRACE(mLogCategory,"fd:%d,w:%d,h:%d,%p,hash:%zu",buf->dma.fd[0],buf->dma.width,buf->dma.height,waylandbuf,hashval);
         mWaylandBuffersMap.insert(item);
     }
-
-    //clean invalid wayland buffer,if video resolution changed
-    for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
-        WaylandBuffer *wlbuf = (WaylandBuffer*)item->second;
-        if (wlbuf->isFree()) {
-            mWaylandBuffersMap.erase(item++);
-            delete wlbuf;
-        } else {
-            item++;
-        }
-    }
     TRACE(mLogCategory,"mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
 }
 
@@ -1647,6 +1633,24 @@
     }
 }
 
+
+/**
+ * @brief clean wayland buffers those malloc before resolution changed
+ *
+ */
+void WaylandDisplay::cleanWaylandBufferBeforeResChanged()
+{
+    for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
+        WaylandBuffer *wlbuf = (WaylandBuffer*)item->second;
+        if (wlbuf->isFree()) {
+            mWaylandBuffersMap.erase(item++);
+            delete wlbuf;
+        } else {
+            item++;
+        }
+    }
+}
+
 void WaylandDisplay::flushBuffers()
 {
     INFO(mLogCategory,"flushBuffers");
diff --git a/weston/wayland_display.h b/weston/wayland_display.h
index a8349ba..abf5ab9 100644
--- a/weston/wayland_display.h
+++ b/weston/wayland_display.h
@@ -289,6 +289,7 @@
     void addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf);
     WaylandBuffer* findWaylandBuffer(RenderBuffer * buf);
     void cleanAllWaylandBuffer();
+    void cleanWaylandBufferBeforeResChanged();
 
     WaylandPlugin *mWaylandPlugin;
     struct wl_display *mWlDisplay;
diff --git a/weston/wayland_plugin.cpp b/weston/wayland_plugin.cpp
index 95c7841..dc41c9f 100644
--- a/weston/wayland_plugin.cpp
+++ b/weston/wayland_plugin.cpp
@@ -393,7 +393,6 @@
         close(fd);
         fd = -1;
     }
-    Logger_set_level(4);
 
     WaylandPlugin *pluginInstance = new WaylandPlugin(category);
     return static_cast<void *>(pluginInstance);