[Spice-commits] 4 commits - client/application.cpp client/application.h client/gui client/hot_keys.cpp client/windows client/x11 configure.ac server/red_dispatcher.c server/red_worker.c

Alexander Larsson alexl at kemper.freedesktop.org
Thu Jul 1 04:51:03 PDT 2010


 client/application.cpp     |  124 ++++++++++++++++++++++++++++++---------------
 client/application.h       |   17 ++++++
 client/gui/gui.h           |    6 ++
 client/hot_keys.cpp        |    4 +
 client/windows/redc.vcproj |    4 -
 client/x11/Makefile.am     |   12 +++-
 configure.ac               |   19 +++++-
 server/red_dispatcher.c    |    4 +
 server/red_worker.c        |   85 +++++++++++++++++++++++++-----
 9 files changed, 213 insertions(+), 62 deletions(-)

New commits:
commit 0e16cadc7077d448a5b91be205226620e2bc5191
Author: Alon Levy <alevy at redhat.com>
Date:   Thu Jul 1 13:48:58 2010 +0200

    Make CEGUI optional
    
    This makes the CEGUI dependency optional and off by default. Restoring
    previous behaviour of exiting on disconnect if disabled.

diff --git a/client/application.cpp b/client/application.cpp
index 83160c9..72db03f 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -42,7 +42,9 @@
 #include "cmd_line_parser.h"
 #include "tunnel_channel.h"
 #include "rect.h"
+#ifdef USE_GUI
 #include "gui/gui.h"
+#endif
 #include <stdarg.h>
 #include <stdio.h>
 #include <time.h>
@@ -101,6 +103,7 @@ void SwitchHostEvent::response(AbstractProcessLoop& events_loop)
     app->switch_host(_host, _port, _sport, _cert_subject);
 }
 
+#ifdef USE_GUI
 //todo: add inactive visual appearance
 class GUIBarrier: public ScreenLayer {
 public:
@@ -148,6 +151,43 @@ private:
     AutoRef<LocalCursor> _cursor;
 };
 
+class GUITimer: public Timer {
+public:
+    GUITimer(GUI& gui)
+        : _gui (gui)
+    {
+    }
+
+    virtual void response(AbstractProcessLoop& events_loop)
+    {
+        _gui.idle();
+    }
+
+private:
+    GUI& _gui;
+};
+
+
+#ifdef GUI_DEMO
+class TestTimer: public Timer {
+public:
+    TestTimer(Application& app)
+        : _app (app)
+    {
+    }
+
+    virtual void response(AbstractProcessLoop& events_loop)
+    {
+        _app.message_box_test();
+    }
+
+private:
+    Application& _app;
+};
+#endif
+
+#endif // USE_GUI
+
 class InfoLayer: public ScreenLayer {
 public:
     InfoLayer();
@@ -279,42 +319,6 @@ void StickyKeyTimer::response(AbstractProcessLoop& events_loop)
     app->deactivate_interval_timer(this);
 }
 
-class GUITimer: public Timer {
-public:
-    GUITimer(GUI& gui)
-        : _gui (gui)
-    {
-    }
-
-    virtual void response(AbstractProcessLoop& events_loop)
-    {
-        _gui.idle();
-    }
-
-private:
-    GUI& _gui;
-};
-
-
-#ifdef GUI_DEMO
-class TestTimer: public Timer {
-public:
-    TestTimer(Application& app)
-        : _app (app)
-    {
-    }
-
-    virtual void response(AbstractProcessLoop& events_loop)
-    {
-        _app.message_box_test();
-    }
-
-private:
-    Application& _app;
-};
-#endif
-
-
 static MouseHandler default_mouse_handler;
 static KeyHandler default_key_handler;
 
@@ -330,7 +334,9 @@ enum AppCommands {
     APP_CMD_CONNECT,
     APP_CMD_DISCONNECT,
 #endif
+#ifdef USE_GUI
     APP_CMD_SHOW_GUI,
+#endif // USE_GUI
 };
 
 Application::Application()
@@ -351,7 +357,9 @@ Application::Application()
     , _monitors (NULL)
     , _title (L"SPICEc:%d")
     , _sys_key_intercept_mode (false)
+#ifdef USE_GUI
     , _gui_mode (GUI_MODE_FULL)
+#endif // USE_GUI
     , _during_host_switch(false)
     , _state (DISCONNECTED)
 {
@@ -371,7 +379,9 @@ Application::Application()
     _commands_map["connect"] = APP_CMD_CONNECT;
     _commands_map["disconnect"] = APP_CMD_DISCONNECT;
 #endif
+#ifdef USE_GUI
     _commands_map["show-gui"] = APP_CMD_SHOW_GUI;
+#endif // USE_GUI
 
     _canvas_types.resize(1);
 #ifdef WIN32
@@ -391,7 +401,9 @@ Application::Application()
                                                           ",connect=shift+f5"
                                                           ",disconnect=shift+f6"
 #endif
+#ifdef USE_GUI
                                                           ",show-gui=shift+f7"
+#endif // USE_GUI
                                                           , _commands_map));
     _hot_keys = parser->get();
 
@@ -402,6 +414,7 @@ Application::Application()
     _sticky_info.key  = REDKEY_INVALID;
     _sticky_info.timer.reset(new StickyKeyTimer());
 
+#ifdef USE_GUI
     _gui.reset(new GUI(*this, DISCONNECTED));
     _gui_timer.reset(new GUITimer(*_gui.get()));
     activate_interval_timer(*_gui_timer, 1000 / 30);
@@ -409,6 +422,7 @@ Application::Application()
     _gui_test_timer.reset(new TestTimer(*this));
     activate_interval_timer(*_gui_test_timer, 1000 * 30);
 #endif
+#endif // USE_GUI
     for (int i = SPICE_CHANNEL_MAIN; i < SPICE_END_CHANNEL; i++) {
         _peer_con_opt[i] = RedPeer::ConnectionOptions::CON_OP_BOTH;
     }
@@ -416,12 +430,14 @@ Application::Application()
 
 Application::~Application()
 {
+#ifdef USE_GUI
     deactivate_interval_timer(*_gui_timer);
 #ifdef GUI_DEMO
     deactivate_interval_timer(*_gui_test_timer);
 #endif
     destroyed_gui_barriers();
     _gui->set_screen(NULL);
+#endif // USE_GUI
 
     if (_info_layer->screen()) {
         _main_screen->detach_layer(*_info_layer);
@@ -511,7 +527,11 @@ void Application::remove_mouse_handler(MouseHandler& handler)
 
 void Application::capture_mouse()
 {
-    if (!_active_screen || _gui->screen()) {
+    if (!_active_screen
+#ifdef USE_GUI
+        || _gui->screen()
+#endif // USE_GUI
+        ) {
         return;
     }
     _active_screen->capture_mouse();
@@ -568,11 +588,15 @@ void Application::switch_host(const std::string& host, int port, int sport,
 
 int Application::run()
 {
+#ifdef USE_GUI
     if (_gui_mode != GUI_MODE_FULL) {
         connect();
     }
 
     show_gui();
+#else
+    connect();
+#endif // HAVE_GUI
     _exit_code = ProcessLoop::run();
     return _exit_code;
 }
@@ -630,7 +654,9 @@ RedScreen* Application::get_screen(int id)
             size.y = SCREEN_INIT_HEIGHT;
         }
         screen = _screens[id] = new RedScreen(*this, id, _title, size.x, size.y);
+#ifdef USE_GUI
         create_gui_barrier(*screen, id);
+#endif // USE_GUI
 
         if (id != 0) {
             if (_full_screen) {
@@ -658,6 +684,7 @@ RedScreen* Application::get_screen(int id)
     return screen;
 }
 
+#ifdef USE_GUI
 void Application::attach_gui_barriers()
 {
     GUIBarriers::iterator iter = _gui_barriers.begin();
@@ -710,12 +737,15 @@ void Application::destroyed_gui_barrier(int id)
         }
     }
 }
+#endif // USE_GUI
 
 void Application::on_screen_destroyed(int id, bool was_captured)
 {
     bool reposition = false;
 
+#ifdef USE_GUI
     destroyed_gui_barrier(id);
+#endif // USE_GUI
 
     if ((int)_screens.size() < id + 1 || !_screens[id]) {
         THROW("no screen");
@@ -772,10 +802,12 @@ void Application::set_state(State state)
         return;
     }
     _state = state;
+#ifdef USE_GUI
     _gui->set_state(_state);
     if (_gui->screen() && !_gui->is_visible()) {
         hide_gui();
     }
+#endif // USE_GUI
     reset_sticky();
 }
 
@@ -789,7 +821,11 @@ void Application::on_connected()
 void Application::on_disconnected(int error_code)
 {
     bool host_switch = _during_host_switch && (error_code == SPICEC_ERROR_CODE_SUCCESS);
-    if (_gui_mode != GUI_MODE_FULL && !host_switch) {
+    if (
+#ifdef USE_GUI
+    _gui_mode != GUI_MODE_FULL &&
+#endif // USE_GUI
+    !host_switch) {
         _during_host_switch = false;
         ProcessLoop::quit(error_code);
         return;
@@ -884,6 +920,7 @@ void Application::message_box_test()
 
 #endif
 
+#ifdef USE_GUI
 void Application::show_gui()
 {
     if (_gui->screen() || !_gui->prepare_dialog()) {
@@ -906,6 +943,7 @@ void Application::hide_gui()
     detach_gui_barriers();
     show_info_layer();
 }
+#endif // USE_GUI
 
 void Application::do_command(int command)
 {
@@ -936,9 +974,11 @@ void Application::do_command(int command)
         do_disconnect();
         break;
 #endif
+#ifdef USE_GUI
     case APP_CMD_SHOW_GUI:
         show_gui();
         break;
+#endif // USE_GUI
     }
 }
 
@@ -1659,10 +1699,12 @@ void Application::hide_me()
     hide_gui();
 }
 
+#ifdef USE_GUI
 bool Application::is_disconnect_allowed()
 {
     return _gui_mode == GUI_MODE_FULL;
 }
+#endif // USE_GUI
 
 const std::string& Application::get_host()
 {
@@ -1910,14 +1952,18 @@ bool Application::process_cmd_line(int argc, char** argv)
         SPICE_OPT_CANVAS_TYPE,
     };
 
+#ifdef USE_GUI
     if (argc == 1) {
         _gui_mode = GUI_MODE_FULL;
         register_channels();
         _main_screen->show(true, NULL);
         return true;
     }
+#endif // USE_GUI
 
+#ifdef USE_GUI
     _gui_mode = GUI_MODE_ACTIVE_SESSION;
+#endif // USE_GUI
 
     CmdLineParser parser("Spice client", false);
 
diff --git a/client/application.h b/client/application.h
index 1e48ab5..01ef517 100644
--- a/client/application.h
+++ b/client/application.h
@@ -35,6 +35,8 @@ class InputsHandler;
 class Monitor;
 class CmdLineParser;
 class Menu;
+
+#ifdef USE_GUI
 class GUI;
 class GUITimer;
 class GUIBarrier;
@@ -42,6 +44,7 @@ class GUIBarrier;
 #ifdef GUI_DEMO
 class TestTimer;
 #endif
+#endif // USE_GUI
 
 
 class ConnectedEvent: public Event {
@@ -131,7 +134,9 @@ typedef struct StickyInfo {
 
 
 typedef std::list<KeyHandler*> KeyHandlersStack;
+#ifdef USE_GUI
 typedef std::list<GUIBarrier*> GUIBarriers;
+#endif // USE_GUI
 
 class Application : public ProcessLoop,
                     public Platform::EventListener,
@@ -147,11 +152,13 @@ public:
         DISCONECTING,
     };
 
+#ifdef USE_GUI
     enum GuiMode {
         GUI_MODE_FULL,
         GUI_MODE_ACTIVE_SESSION,
         GUI_MODE_MINIMAL,
     };
+#endif // USE_GUI
 
     Application();
     virtual ~Application();
@@ -216,7 +223,9 @@ public:
     void quit();
     void hide_me();
     void beep();
+#ifdef USE_GUI
     bool is_disconnect_allowed();
+#endif
 
     const std::string& get_host();
     int get_port();
@@ -272,6 +281,7 @@ private:
 
     void show_info_layer();
     void hide_info_layer();
+#ifdef USE_GUI
     void attach_gui_barriers();
     void detach_gui_barriers();
     void show_gui();
@@ -279,6 +289,11 @@ private:
     void create_gui_barrier(RedScreen& screen, int id);
     void destroyed_gui_barrier(int id);
     void destroyed_gui_barriers();
+#else // USE_GUI
+    void show_gui() {}
+    void hide_gui() {}
+
+#endif // USE_GUI
 
     // returns the press value before operation (i.e., if it was already pressed)
     bool press_key(RedKey key);
@@ -324,6 +339,7 @@ private:
     StickyInfo _sticky_info;
     std::vector<int> _canvas_types;
     AutoRef<Menu> _app_menu;
+#ifdef USE_GUI
     std::auto_ptr<GUI> _gui;
     AutoRef<GUITimer> _gui_timer;
     GUIBarriers _gui_barriers;
@@ -331,6 +347,7 @@ private:
 #ifdef GUI_DEMO
     AutoRef<TestTimer> _gui_test_timer;
 #endif
+#endif // USE_GUI
     bool _during_host_switch;
 
     State _state;
diff --git a/client/gui/gui.h b/client/gui/gui.h
index d51a8c8..3b76b68 100644
--- a/client/gui/gui.h
+++ b/client/gui/gui.h
@@ -22,7 +22,9 @@ public:
     void set_screen(RedScreen* screen); //show and hide
 
     Application& get_application() { return _app;}
+#ifdef USE_GUI
     CEGUI::System& gui_system() { return *_gui_system;}
+#endif // USE_GUI
 
     void set_state(Application::State state);
     bool is_visible() { return !!_dialog;}
@@ -87,8 +89,10 @@ private:
     Application& _app;
     Application::State _state;
     RedPixmapSw* _pixmap;
+#ifdef USE_GUI
     CEGUI::SoftRenderer* _renderer;
     CEGUI::System* _gui_system;
+#endif // USE_GUI
     Dialog* _dialog;
     uint64_t _prev_time;
     TabFactorys _tab_factorys;
@@ -100,7 +104,9 @@ class GUI::Tab {
 public:
     virtual ~Tab() {}
 
+#ifdef USE_GUI
     virtual CEGUI::Window& get_root_window() = 0;
+#endif // USE_GUI
     virtual const std::string& get_name() = 0;
 };
 
diff --git a/client/hot_keys.cpp b/client/hot_keys.cpp
index 1d3c874..d6564b7 100644
--- a/client/hot_keys.cpp
+++ b/client/hot_keys.cpp
@@ -138,7 +138,9 @@ void HotKeysParser::add_hotkey(const std::string& hotkey, const CommandsMap& com
     CommandsMap::const_iterator command = commands_map.find(command_name);
 
     if (commands_map.find(command_name) == commands_map.end()) {
-        THROW("invalid action bname");
+        char buf[1000];
+        sprintf(buf, "invalid action bname %s", command_name.c_str());
+        THROW(buf);
     }
     int command_id = commands_map.find(command_name)->second;
     std::string keys = hotkey.substr(key_start + 1);
diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj
index af7ead4..6f630c2 100644
--- a/client/windows/redc.vcproj
+++ b/client/windows/redc.vcproj
@@ -47,7 +47,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories=".;..;..\..\common;..\..\..\spice-protocol;..\..\common\win;&quot;..\..\common\win\my_getopt-1.5&quot;;&quot;$(SPICE_LIBS)\include&quot;;&quot;$(SPICE_LIBS)\include\pixman-1&quot;;&quot;$(SPICE_LIBS)\include\CEGUI-0.6.2&quot;"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GUI;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
 				MinimalRebuild="false"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -129,7 +129,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalIncludeDirectories=".;..;..\..\..\spice-protocol;..\..\common;..\..\common\win;&quot;..\..\common\win\my_getopt-1.5&quot;;&quot;$(SPICE_LIBS)\include&quot;;&quot;$(SPICE_LIBS)\include\pixman-1&quot;;&quot;$(SPICE_LIBS)\include\CEGUI-0.6.2&quot;"
-				PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
+				PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GUI;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index eaa0314..ce4813b 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -116,6 +116,10 @@ RED_COMMON_SRCS =					\
 	$(CLIENT_DIR)/zlib_decoder.cpp			\
 	$(CLIENT_DIR)/zlib_decoder.h			\
 	$(CLIENT_DIR)/icon.h				\
+	$(NULL)
+
+if SUPPORT_GUI
+RED_GUI_SRCS =						\
 	$(CLIENT_DIR)/gui/softrenderer.h		\
 	$(CLIENT_DIR)/gui/softrenderer.cpp		\
 	$(CLIENT_DIR)/gui/softtexture.h			\
@@ -123,8 +127,11 @@ RED_COMMON_SRCS =					\
 	$(CLIENT_DIR)/gui/resource_provider.h		\
 	$(CLIENT_DIR)/gui/resource_provider.cpp		\
 	$(CLIENT_DIR)/gui/gui.h				\
-	$(CLIENT_DIR)/gui/gui.cpp			\
-	$(NULL)
+	$(CLIENT_DIR)/gui/gui.cpp
+else
+RED_GUI_SRCS =
+endif
+
 
 if SUPPORT_GL
 RED_OGL_SRCS =						\
@@ -167,6 +174,7 @@ spicec_SOURCES =			\
 	x_icon.h			\
 	x_platform.h			\
 	$(RED_COMMON_SRCS)		\
+	$(RED_GUI_SRCS)			\
 	$(RED_OGL_SRCS)			\
 	$(NULL)
 
diff --git a/configure.ac b/configure.ac
index c78d167..dc13caf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -97,6 +97,12 @@ AC_ARG_ENABLE(tunnel,
 [  have_tunnel=yes])
 AM_CONDITIONAL(SUPPORT_TUNNEL, test "x$have_tunnel" = "xyes")
 
+use_gui=no
+AC_ARG_ENABLE(gui,
+[  --enable-gui         Enable start dialog with CEGUI],
+[  use_gui=yes])
+AM_CONDITIONAL(SUPPORT_GUI, test "x$use_gui" = "xyes")
+
 have_opengl=no
 AC_ARG_ENABLE(opengl,
 [  --enable-opengl         Enable opengl requirement / support (not recommended)],
@@ -121,10 +127,13 @@ SPICE_NONPKGCONFIG_LIBS+=" -pthread $LIBM $LIBRT"
 
 SPICE_REQUIRES=""
 
-PKG_CHECK_MODULES(CEGUI, CEGUI >= 0.6.0 CEGUI < 0.7.0)
-AC_SUBST(CEGUI_CFLAGS)
-AC_SUBST(CEGUI_LIBS)
-SPICE_REQUIRES+=" CEGUI"
+if test "x$use_gui" = "xyes"; then
+    PKG_CHECK_MODULES(CEGUI, CEGUI >= 0.6.0 CEGUI < 0.7.0)
+    AC_SUBST(CEGUI_CFLAGS)
+    AC_SUBST(CEGUI_LIBS)
+    SPICE_REQUIRES+=" CEGUI"
+    CEGUI_CFLAGS+="-DUSE_GUI"
+fi
 
 if test "x$have_tunnel" = "xyes"; then
 	PKG_CHECK_MODULES(SLIRP, slirp)
@@ -366,5 +375,7 @@ echo "
 
         OpenGL:                   ${have_opengl}
 
+        GUI:                      ${use_gui}
+
         Now type 'make' to build $PACKAGE
 "
commit d69fd9408cecff72a9261ed5c1cc2de77aee37bb
Author: Alexander Larsson <alexl at redhat.com>
Date:   Thu Jul 1 10:50:12 2010 +0200

    client: Use ASSERT, not assert

diff --git a/client/application.cpp b/client/application.cpp
index 482215c..83160c9 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -2141,7 +2141,7 @@ void spice_log(unsigned int type, const char *function, const char *format, ...)
       return;
     }
 
-    assert(type <= LOG_FATAL);
+    ASSERT(type <= LOG_FATAL);
 
     va_start(ap, format);
     string_vprintf(formated_message, format, ap);
commit 2ec023b89219280aae83429d168a8794abef6e14
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Jun 30 13:28:22 2010 -0400

    - fix for noopengl patch for server
    
    I still don't have commit access (can't ssh to anarchy) so if someone could commit this (alex) thanks,
    
    Alon
    
    Fix for no opengl patch - required to compile the server (fixes missing symbol gl_canvas_init).

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 715bfb6..539c18e 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -29,7 +29,9 @@
 #include "red_worker.h"
 #include "quic.h"
 #include "sw_canvas.h"
+#ifdef USE_OGL
 #include "gl_canvas.h"
+#endif // USE_OGL
 #include "reds.h"
 #include "red_dispatcher.h"
 #include "red_parse_qxl.h"
@@ -496,7 +498,9 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
 
     quic_init();
     sw_canvas_init();
+#ifdef USE_OGL
     gl_canvas_init();
+#endif // USE_OGL
 
     if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) {
         red_error("socketpair failed %s", strerror(errno));
commit 37b4ae416284eecde04459cd5bb7c7b70bd6481e
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Wed Jun 23 16:32:12 2010 +0300

    fix for not clearing the cursor ring when the primary surface is destroyed
    
    fixes a crash in qxl_soft_reset

diff --git a/server/red_worker.c b/server/red_worker.c
index fa1ca44..6ab4b3b 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -1042,6 +1042,7 @@ static void red_display_free_glz_drawable(DisplayChannel *channel, RedGlzDrawabl
 static void reset_rate(StreamAgent *stream_agent);
 static BitmapGradualType _get_bitmap_graduality_level(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id);
 static inline int _stride_is_extra(SpiceBitmap *bitmap);
+static void red_disconnect_cursor(RedChannel *channel);
 
 #ifdef DUMP_BITMAP
 static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id);
@@ -4854,13 +4855,15 @@ static inline uint64_t red_now()
     return time.tv_sec * 1000000000 + time.tv_nsec;
 }
 
-static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size)
+static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty)
 {
     QXLCommandExt ext_cmd;
     int n = 0;
 
+    *ring_is_empty = FALSE;
     while (!worker->cursor_channel || worker->cursor_channel->base.pipe_size <= max_pipe_size) {
         if (!worker->qxl->st->qif->get_cursor_command(worker->qxl, &ext_cmd)) {
+            *ring_is_empty = TRUE;
             if (worker->repoll_cursor_ring < CMD_RING_POLL_RETRIES) {
                 worker->repoll_cursor_ring++;
                 worker->epoll_timeout = MIN(worker->epoll_timeout, CMD_RING_POLL_TIMEOUT);
@@ -4891,14 +4894,16 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size)
     return n;
 }
 
-static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
+static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty)
 {
     QXLCommandExt ext_cmd;
     int n = 0;
     uint64_t start = red_now();
-
+    
+    *ring_is_empty = FALSE;
     while (!worker->display_channel || worker->display_channel->base.pipe_size <= max_pipe_size) {
         if (!worker->qxl->st->qif->get_command(worker->qxl, &ext_cmd)) {
+            *ring_is_empty = TRUE;;
             if (worker->repoll_cmd_ring < CMD_RING_POLL_RETRIES) {
                 worker->repoll_cmd_ring++;
                 worker->epoll_timeout = MIN(worker->epoll_timeout, CMD_RING_POLL_TIMEOUT);
@@ -9743,17 +9748,18 @@ static inline void flush_display_commands(RedWorker *worker)
 {
     for (;;) {
         uint64_t end_time;
+        int ring_is_empty;
 
-        red_process_commands(worker, MAX_PIPE_SIZE);
-        if (!worker->qxl->st->qif->has_command(worker->qxl)) {
+        red_process_commands(worker, MAX_PIPE_SIZE, &ring_is_empty);
+        if (ring_is_empty) {
             break;
         }
 
-        while (red_process_commands(worker, MAX_PIPE_SIZE)) {
+        while (red_process_commands(worker, MAX_PIPE_SIZE, &ring_is_empty)) {
             display_channel_push(worker);
         }
 
-        if (!worker->qxl->st->qif->has_command(worker->qxl)) {
+        if (ring_is_empty) {
             break;
         }
         end_time = red_now() + DISPLAY_CLIENT_TIMEOUT * 10;
@@ -9770,7 +9776,7 @@ static inline void flush_display_commands(RedWorker *worker)
             red_send_data(channel, NULL);
             if (red_now() >= end_time) {
                 red_printf("update timeout");
-                red_disconnect_display((RedChannel *)worker->display_channel);
+                red_disconnect_display(channel);
             } else {
                 sleep_count++;
                 usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
@@ -9780,6 +9786,54 @@ static inline void flush_display_commands(RedWorker *worker)
     }
 }
 
+static inline void flush_cursor_commands(RedWorker *worker)
+{
+    for (;;) {
+        uint64_t end_time;
+        int ring_is_empty = FALSE;
+
+        red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty);
+        if (ring_is_empty) {
+            break;
+        }
+
+        while (red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty)) {
+            cursor_channel_push(worker);
+        }
+
+        if (ring_is_empty) {
+            break;
+        }
+        end_time = red_now() + DISPLAY_CLIENT_TIMEOUT * 10;
+        int sleep_count = 0;
+        for (;;) {
+            cursor_channel_push(worker);
+            if (!worker->cursor_channel ||
+                                        worker->cursor_channel->base.pipe_size <= MAX_PIPE_SIZE) {
+                break;
+            }
+            RedChannel *channel = (RedChannel *)worker->cursor_channel;
+            red_ref_channel(channel);
+            red_receive(channel);
+            red_send_data(channel, NULL);
+            if (red_now() >= end_time) {
+                red_printf("flush cursor timeout");
+                red_disconnect_cursor(channel);
+            } else {
+                sleep_count++;
+                usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
+            }
+            red_unref_channel(channel);
+        }
+    }
+}
+
+static inline void flush_all_qxl_commands(RedWorker *worker)
+{
+    flush_display_commands(worker);
+    flush_cursor_commands(worker);
+}
+
 static inline void red_flush_surface_pipe(RedWorker *worker)
 {
     if (worker->display_channel) {
@@ -10691,8 +10745,9 @@ static inline void handle_dev_destroy_surface_wait(RedWorker *worker)
     receive_data(worker->channel, &surface_id, sizeof(uint32_t));
 
     ASSERT(surface_id == 0);
+    
+    flush_all_qxl_commands(worker);
 
-    flush_display_commands(worker);
     if (worker->surfaces[0].context.canvas) {
         destroy_surface_wait(worker, 0);
     }
@@ -10706,7 +10761,7 @@ static inline void handle_dev_destroy_surfaces(RedWorker *worker)
     int i;
     RedWorkerMessage message;
 
-    flush_display_commands(worker);
+    flush_all_qxl_commands(worker);
     //to handle better
     if (worker->surfaces[0].context.canvas) {
         destroy_surface_wait(worker, 0);
@@ -10809,7 +10864,7 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker)
         ASSERT(!worker->cursor_channel->base.send_data.item);
     }
 
-    flush_display_commands(worker);
+    flush_all_qxl_commands(worker);
     destroy_surface_wait(worker, 0);
     red_destroy_surface(worker, 0);
     ASSERT(ring_is_empty(&worker->streams));
@@ -10828,6 +10883,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
 {
     RedWorker *worker = SPICE_CONTAINEROF(listener, RedWorker, dev_listener);
     RedWorkerMessage message;
+    int ring_is_empty;
 
     read_message(worker->channel, &message);
 
@@ -10841,7 +10897,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         break;
     case RED_WORKER_MESSAGE_OOM:
         ASSERT(worker->running);
-        while (red_process_commands(worker, MAX_PIPE_SIZE)) {
+        while (red_process_commands(worker, MAX_PIPE_SIZE, &ring_is_empty)) {
             display_channel_push(worker);
         }
         if (worker->qxl->st->qif->flush_resources(worker->qxl) == 0) {
@@ -11196,8 +11252,9 @@ void *red_worker_main(void *arg)
         }
 
         if (worker.running) {
-            red_process_cursor(&worker, MAX_PIPE_SIZE);
-            red_process_commands(&worker, MAX_PIPE_SIZE);
+            int ring_is_empty;
+            red_process_cursor(&worker, MAX_PIPE_SIZE, &ring_is_empty);
+            red_process_commands(&worker, MAX_PIPE_SIZE, &ring_is_empty);
         }
         red_push(&worker);
     }


More information about the Spice-commits mailing list