libvideorender: CB2 fix no video when output plugin again [1/1]

PD#SWPL-135215

Problem:
when output do plugout/plugin, it cause no video showed

Solution:
select the wl_output when output plugin again,but video had playing
we will can't change wl_output

Verify:
ap222

Change-Id: If415b752ef9c1cf920260e2ed28cd51a412d55fa
Signed-off-by: fei.deng <fei.deng@amlogic.com>
diff --git a/weston/wayland_display.cpp b/weston/wayland_display.cpp
index 390dee4..eb06a22 100644
--- a/weston/wayland_display.cpp
+++ b/weston/wayland_display.cpp
@@ -29,6 +29,7 @@
 #endif
 
 #define UNUSED_PARAM(x) ((void)(x))
+#define INVALID_OUTPUT_INDEX (-1)
 
 #define TAG "rlib:wayland_display"
 
@@ -135,16 +136,11 @@
                 self->mOutput[i].refreshRate = refreshRate;
             }
         }
-        //if a displayoutput had been selected,set this rectangle to wayland
-        int selectOutput = self->mActiveOutput;
-        DEBUG(self->mLogCategory,"wl_output: %p (%dx%d) refreshrate:%d,active output index %d\n",output, width, height,refreshRate,selectOutput);
-        if (selectOutput >= 0 && selectOutput < DEFAULT_DISPLAY_OUTPUT_NUM) {
-            if (self->mOutput[selectOutput].width > 0 && self->mOutput[selectOutput].height > 0) {
-                self->setRenderRectangle(self->mOutput[selectOutput].offsetX,
-                        self->mOutput[selectOutput].offsetY,
-                        self->mOutput[selectOutput].width,
-                        self->mOutput[selectOutput].height);
-            }
+
+        DEBUG(self->mLogCategory,"wl_output: %p (%dx%d) refreshrate:%d,select output index %d",output, width, height,refreshRate,self->mSelectOutputIndex);
+        if (self->mCurrentDisplayOutput->width > 0 &&
+            self->mCurrentDisplayOutput->height > 0) {
+            self->updateDisplayOutput();
         }
     }
 }
@@ -404,12 +400,12 @@
     if (width <= 0 || height <= 0)
         return;
 
-    int selectOutput = self->mActiveOutput;
-    if (width == self->mOutput[selectOutput].width && height == self->mOutput[selectOutput].height) {
-        self->setRenderRectangle(self->mOutput[selectOutput].offsetX,
-                            self->mOutput[selectOutput].offsetY,
-                            self->mOutput[selectOutput].width,
-                            self->mOutput[selectOutput].height);
+    if (width == self->mCurrentDisplayOutput->width && height == self->mCurrentDisplayOutput->height && self->mUpdateRenderRectangle) {
+        self->mUpdateRenderRectangle = false;
+        self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
+                            self->mCurrentDisplayOutput->offsetY,
+                            self->mCurrentDisplayOutput->width,
+                            self->mCurrentDisplayOutput->height);
     } else{
         self->setRenderRectangle(self->mRenderRect.x, self->mRenderRect.y, width, height);
     }
@@ -429,10 +425,7 @@
     TRACE(self->mLogCategory,"handleXdgSurfaceConfigure");
     Tls::Mutex::Autolock _l(self->mConfigureMutex);
     self->mXdgSurfaceConfigured = true;
-    if (self->mRenderRect.w > 0 && self->mRenderRect.h) {
-        DEBUG(self->mLogCategory,"set xdg surface geometry(%d,%d,%d,%d)",self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
-        xdg_surface_set_window_geometry(self->mXdgSurface,self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
-    }
+    self->updateDisplayOutput();
 }
 
 static const struct xdg_surface_listener xdg_surface_listener = {
@@ -467,22 +460,44 @@
         self->mDmabuf = (struct zwp_linux_dmabuf_v1 *)wl_registry_bind (registry, name, &zwp_linux_dmabuf_v1_interface, 3);
         zwp_linux_dmabuf_v1_add_listener (self->mDmabuf, &dmabuf_listener, (void *)self);
     }  else if (strcmp (interface, "wl_output") == 0) {
+        int i = 0;
+        uint32_t oriName = self->mCurrentDisplayOutput->name;
         for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
             if (self->mOutput[i].wlOutput ==  NULL) {
                 self->mOutput[i].name = name;
                 self->mOutput[i].wlOutput = (struct wl_output*)wl_registry_bind(registry, name, &wl_output_interface, version);
+                TRACE(self->mLogCategory,"name:%u, wl_output:%p, select:%d",self->mOutput[i].name,self->mOutput[i].wlOutput,self->mSelectOutputIndex);
                 wl_output_add_listener(self->mOutput[i].wlOutput, &outputListener, (void *)self);
                 if (i == 0) { //primary wl_output
                     self->mOutput[i].isPrimary = true;
                 }
-                //if wl_output plugin,active sending frame
-                if (self->mOutput[self->mActiveOutput].wlOutput) {
-                    self->setRedrawingPending(false);
-                }
-                return;
+                break;
             }
         }
-        WARNING(self->mLogCategory,"Not enough free output");
+        if (i == DEFAULT_DISPLAY_OUTPUT_NUM) {
+            WARNING(self->mLogCategory,"Not enough free output");
+        }
+        //select current wl_output
+        if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX && !self->isRunning()) {
+            TRACE(self->mLogCategory,"select %d output",self->mSelectOutputIndex);
+            self->mCurrentDisplayOutput = &self->mOutput[self->mSelectOutputIndex];
+        }
+        //if user select a wrong output index, we using a suiteble wl_output
+        if (self->mCurrentDisplayOutput->wlOutput == NULL) {
+            WARNING(self->mLogCategory,"wl_output is null,we should find a suiteble output");
+            for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
+                if (self->mOutput[i].wlOutput) {
+                    self->mCurrentDisplayOutput = &self->mOutput[i];
+                    break;
+                }
+            }
+        }
+        //if current wl_output update, we should update render rectangle
+        if (self->mCurrentDisplayOutput->name != oriName) {
+            self->mUpdateRenderRectangle = true;
+        }
+        //if wl_output plugin,active sending frame
+        self->setRedrawingPending(false);
     } else if (strcmp(interface, "wl_seat") == 0) {
         //self->mSeat = (struct wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1);
         //wl_seat_add_listener(self->mSeat, &seat_listener, (void *)self);
@@ -492,14 +507,38 @@
 void
 WaylandDisplay::registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name)
 {
+    int i;
     WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
     /* check wl_output changed */
     DEBUG(self->mLogCategory,"wayland display remove registry handle global,name:%u",name);
-    for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
+    //if user selected wl_output removed, reset selected output index
+    if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX &&
+        self->mOutput[self->mSelectOutputIndex].wlOutput &&
+        self->mOutput[self->mSelectOutputIndex].name == name) {
+            self->mSelectOutputIndex = INVALID_OUTPUT_INDEX;
+    }
+    for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
         if (self->mOutput[i].name == name) {
+            DEBUG(self->mLogCategory,"remove wl_output name:%u,wl_output:%p",name,self->mOutput[i].wlOutput);
             self->mOutput[i].name = 0;
             self->mOutput[i].wlOutput = NULL;
-            DEBUG(self->mLogCategory,"remove wl_output name:%u",name);
+        }
+    }
+    //if current output removed, select a suiteble output
+    if (self->mCurrentDisplayOutput->wlOutput == NULL) {
+        for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
+            if (self->mOutput[i].wlOutput) {
+                self->mCurrentDisplayOutput = &self->mOutput[i];
+                self->mUpdateRenderRectangle = true;
+            }
+        }
+        //set new output rectangle
+        if (self->mUpdateRenderRectangle) {
+            self->mUpdateRenderRectangle = false;
+            self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
+                                    self->mCurrentDisplayOutput->offsetY,
+                                    self->mCurrentDisplayOutput->width,
+                                    self->mCurrentDisplayOutput->height);
         }
     }
 }
@@ -528,7 +567,7 @@
     mPointer = NULL;
     mTouch = NULL;
     mKeyboard = NULL;
-    mActiveOutput = 0; //default is primary output
+    mSelectOutputIndex = INVALID_OUTPUT_INDEX;
     mPoll = new Tls::Poll(true);
     //window
     mVideoWidth = 0;
@@ -550,6 +589,8 @@
     mXdgSurfaceConfigured = false;
     mPip = 0;
     mIsSendVideoPlaneId = true;
+    mCurrentDisplayOutput = &mOutput[0];
+    mUpdateRenderRectangle = false;
     memset(&mRenderRect, 0, sizeof(struct Rectangle));
     memset(&mVideoRect, 0, sizeof(struct Rectangle));
     memset(&mWindowRect, 0, sizeof(struct Rectangle));
@@ -807,19 +848,20 @@
         ERROR(mLogCategory, "display output index error,please set 0:primary or 1:extend,now:%d",output);
         return;
     }
-
-    if (mActiveOutput != output) {
-        mActiveOutput = output;
-        if (mOutput[output].wlOutput) {
-            setRenderRectangle(mOutput[output].offsetX, mOutput[output].offsetY,
-                            mOutput[output].width, mOutput[output].height);
-        }
+    //only do select output before video playing
+    if (mSelectOutputIndex != output) {
+        mSelectOutputIndex = output;
+        // if (mOutput[output].wlOutput) {
+        //     mCurrentDisplayOutput = &mOutput[output];
+        //     setRenderRectangle(mOutput[output].offsetX, mOutput[output].offsetY,
+        //                     mOutput[output].width, mOutput[output].height);
+        // }
     }
 }
 
 int WaylandDisplay::getDisplayOutput()
 {
-    return mActiveOutput;
+    return mSelectOutputIndex == INVALID_OUTPUT_INDEX? 0: mSelectOutputIndex;
 }
 
 void WaylandDisplay::setPip(int pip)
@@ -828,6 +870,37 @@
     mPip = pip;
 }
 
+void WaylandDisplay::updateDisplayOutput()
+{
+    if (!mCurrentDisplayOutput->wlOutput || !mXdgToplevel || !mXdgSurface)
+    {
+        return;
+    }
+    if (mUpdateRenderRectangle) {
+        if (mFullScreen) {
+            DEBUG(mLogCategory,"unset full screen");
+            xdg_toplevel_unset_fullscreen (mXdgToplevel);
+        }
+
+        if (mXdgSurface) {
+            DEBUG(mLogCategory,"set geometry");
+            xdg_surface_set_window_geometry(mXdgSurface,
+                                            mCurrentDisplayOutput->offsetX,
+                                            mCurrentDisplayOutput->offsetY,
+                                            mCurrentDisplayOutput->width,
+                                            mCurrentDisplayOutput->height);
+        }
+
+        if (mFullScreen && mXdgToplevel) {
+            DEBUG(mLogCategory,"set full screen");
+            xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
+        }
+        setRenderRectangle(mCurrentDisplayOutput->offsetX, mCurrentDisplayOutput->offsetY,
+                        mCurrentDisplayOutput->width, mCurrentDisplayOutput->height);
+        mUpdateRenderRectangle = false;
+    }
+}
+
 void WaylandDisplay::createCommonWindowSurface()
 {
     struct wl_region *region;
@@ -897,14 +970,8 @@
         }
 
         //full screen show
-        if (mFullScreen && mOutput[mActiveOutput].wlOutput) {
-            ensureFullscreen(mFullScreen);
-        }
-
-        //if wl_output had detected, the width and height of mRenderRect will be set
-        //we need invoking setRenderRectangle
-        // if (mRenderRect.w > 0 && mRenderRect.h > 0) {
-        //     setRenderRectangle(mRenderRect.x, mRenderRect.y, mRenderRect.w, mRenderRect.h);
+        // if (mFullScreen && mCurrentDisplayOutput->wlOutput) {
+        //     //ensureFullscreen(mFullScreen);
         // }
     } else {
         ERROR(mLogCategory,"Unable to use xdg_wm_base ");
@@ -964,7 +1031,7 @@
     if (mXdgWmBase) {
         DEBUG(mLogCategory,"full screen : %d",fullscreen);
         if (fullscreen) {
-            xdg_toplevel_set_fullscreen (mXdgToplevel, mOutput[mActiveOutput].wlOutput);
+            xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
         } else {
             xdg_toplevel_unset_fullscreen (mXdgToplevel);
         }
@@ -1186,7 +1253,7 @@
         wlbuffer = waylandBuf->getWlBuffer();
     }
     //if no wl_output, drop this buffer
-    if (mOutput[mActiveOutput].wlOutput == NULL) {
+    if (mCurrentDisplayOutput->wlOutput == NULL) {
         TRACE(mLogCategory,"No wl_output");
         mWaylandPlugin->handleFrameDropped(buf);
         mWaylandPlugin->handleBufferRelease(buf);
diff --git a/weston/wayland_display.h b/weston/wayland_display.h
index 4328563..bf03ca6 100644
--- a/weston/wayland_display.h
+++ b/weston/wayland_display.h
@@ -93,7 +93,10 @@
     };
     struct wl_output *getWlOutput()
     {
-        return mOutput[mActiveOutput].wlOutput;
+        if (mCurrentDisplayOutput) {
+            return mCurrentDisplayOutput->wlOutput;
+        }
+        return NULL;
     };
     /**
      * @brief Set the Select Display Output index
@@ -127,6 +130,8 @@
         return mRedrawingPending;
     };
 
+    void updateDisplayOutput();
+
     void setRenderRectangle(int x, int y, int w, int h);
     void setFrameSize(int w, int h);
     void setWindowSize(int x, int y, int w, int h);
@@ -259,8 +264,9 @@
 
     /*primary output will signal first,so 0 index is primary wl_output, 1 index is extend wl_output*/
     DisplayOutput mOutput[DEFAULT_DISPLAY_OUTPUT_NUM]; //info about wl_output
-    int mActiveOutput; //default is primary output
-
+    /*default is -1, it means user don't select any output,using primary wl_output*/
+    int mSelectOutputIndex; // value is -1,0,1, value < DEFAULT_DISPLAY_OUTPUT_NUM
+    DisplayOutput *mCurrentDisplayOutput;
     int mLogCategory;
 
     std::list<uint32_t> mShmFormats;
@@ -293,6 +299,8 @@
 
     bool mReCommitAreaSurface;
 
+    bool mUpdateRenderRectangle;
+
     /* the size and position of the area_(sub)surface
     it is full screen size now*/
     struct Rectangle mRenderRect;