[Spice-commits] 12 commits - client/cache.hpp client/display_channel.cpp client/display_channel.h client/red_gl_canvas.cpp client/red_pixmap.h client/red_window.h client/screen.cpp client/utils.h client/x11 spice-common

Marc-André Lureau elmarco at kemper.freedesktop.org
Sun Sep 29 17:20:08 PDT 2013


 client/cache.hpp             |    3 -
 client/display_channel.cpp   |   92 +++++++++++++++++++++++++++++++------------
 client/display_channel.h     |    2 
 client/red_gl_canvas.cpp     |    2 
 client/red_pixmap.h          |   19 ++++++++
 client/red_window.h          |    2 
 client/screen.cpp            |    1 
 client/utils.h               |    6 ++
 client/x11/pixels_source_p.h |    1 
 client/x11/platform.cpp      |    3 -
 client/x11/red_drawable.cpp  |   13 +++---
 client/x11/red_pixmap_gl.cpp |   85 ++++++++++++++++++++-------------------
 client/x11/red_window.cpp    |   50 ++++++++---------------
 client/x11/red_window_p.h    |    3 -
 spice-common                 |    2 
 15 files changed, 176 insertions(+), 108 deletions(-)

New commits:
commit b2b3243031383dcd6e1c07c0bb821123b6a64f25
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:00:06 2013 +0200

    spicec: disable stencil test with primary fbo
    
    The primary buffer doesn't use stencil test. However, this should be
    explicitely disabled, since the canvas might change stencil state, and
    this will affect primary stencil buffer, making some of further update
    operations clipped in unwanted ways.

diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index 475ee6a..b8563b3 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -3231,7 +3231,7 @@ void Platform::init()
             GLX_GREEN_SIZE, 8,
             GLX_BLUE_SIZE, 8,
             GLX_ALPHA_SIZE, 8,
-            GLX_STENCIL_SIZE, 4,
+            GLX_STENCIL_SIZE, 0,
             GLX_DEPTH_SIZE, 0,
             None
         };
diff --git a/client/x11/red_pixmap_gl.cpp b/client/x11/red_pixmap_gl.cpp
index 1a58628..7978a40 100644
--- a/client/x11/red_pixmap_gl.cpp
+++ b/client/x11/red_pixmap_gl.cpp
@@ -246,6 +246,7 @@ void RedPixmapGL::pre_copy()
     glDisable(GL_BLEND);
     glDisable(GL_ALPHA_TEST);
     glDisable(GL_COLOR_LOGIC_OP);
+    glDisable(GL_STENCIL_TEST);
 
     glColor3f(1, 1, 1);
 }
commit 37548f17e45bf21038f13b2820047f43c2d83154
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 21:59:16 2013 +0200

    spicec: use pre/post copy
    
    Ensure the GL state is appropriate for calling GCanvas::copy_pixels.

diff --git a/client/red_gl_canvas.cpp b/client/red_gl_canvas.cpp
index 81203d9..e8c3f1e 100644
--- a/client/red_gl_canvas.cpp
+++ b/client/red_gl_canvas.cpp
@@ -71,6 +71,7 @@ void GCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc)
     pixman_box32_t *rects;
     int num_rects;
 
+    pre_gl_copy();
     rects = pixman_region32_rectangles((pixman_region32_t *)&region, &num_rects);
     for (int i = 0; i < num_rects; i++) {
         SpiceRect r;
@@ -82,6 +83,7 @@ void GCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc)
 
         dest_dc.copy_pixels(*_pixmap, r.left, r.top, r);
     }
+    post_gl_copy();
 }
 
 void GCanvas::copy_pixels(const QRegion& region, RedDrawable* dest_dc, const PixmapHeader* pixmap)
commit c2b1c0e7f33186a7167e6666cd5dbd0ddeb2562e
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 21:58:35 2013 +0200

    spicec: add sw canvas diff check
    
    Setting CHECKDIFF=1 environment variable will compare the rendering of
    the selected canvas with a software canvas. This is useful for debugging
    some rendering issues, however it is far from being perfect, since it's
    not able to tell whether one or the other is actually faulty. It's a
    strong indication though of which operations are incorrect.
    
    Ideally, all operations should be checked, however, a few of them are
    disabled by default because they fail all the time, and it looks like
    pixman is not very accurate for blending/compositing (at least visually,
    it seems gl has better rendering)

diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 9ba93c4..47076ad 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -611,6 +611,7 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
 #endif
     , _interrupt_update (*this)
     , _mig_wait_primary (false)
+    , _check_diff (getenv("CHECKDIFF") != NULL)
 {
     DisplayHandler* handler = static_cast<DisplayHandler*>(get_message_handler());
 
@@ -1280,6 +1281,22 @@ void DisplayChannel::create_canvas(int surface_id, const std::vector<int>& canva
     // make sure to refresh the whole display
     SpiceRect rect = { 0, 0, width, height };
     invalidate(rect, true);
+
+    try {
+        if (!_check_diff)
+            return;
+
+        SCanvas *canvas = new SCanvas(surface_id == 0, width, height, format,
+                                      screen()->get_window(),
+                                      _pixmap_cache, _palette_cache, _glz_window,
+                                      _surfaces_cache);
+        _swsurfaces_cache[surface_id] = canvas;
+        if (surface_id == 0) {
+            LOG_INFO("display %d: check sw", get_id());
+        }
+    } catch (...) {
+        spice_warn_if_reached();
+    }
 }
 
 void DisplayChannel::handle_mode(RedPeer::InMessage* message)
@@ -1624,29 +1641,52 @@ void DisplayChannel::handle_surface_destroy(RedPeer::InMessage* message)
     }
 }
 
-#define PRE_DRAW
-#define POST_DRAW
+#define DRAW(type, can_diff) {                                          \
+    canvas->draw_##type(*type, message->size());                        \
+    if (type->base.surface_id == 0) {                                   \
+        invalidate(type->base.box, false);                              \
+    }                                                                   \
+    if ((can_diff) && _check_diff) {                                    \
+        Canvas *swcanvas = _swsurfaces_cache[type->base.surface_id];    \
+        swcanvas->draw_##type(*type, message->size());                  \
+        check_diff(swcanvas, canvas, type->base.box);                   \
+    }                                                                   \
+}
+
+#include "red_pixmap_sw.h"
+
+void check_diff(Canvas *a, Canvas *b, const SpiceRect& rect)
+{
+    QRegion region;
+    RedPixmapSw *ap = new RedPixmapSw(rect.right, rect.bottom, RedDrawable::RGB32, true, 0);
+    RedPixmapSw *bp = new RedPixmapSw(rect.right, rect.bottom, RedDrawable::RGB32, true, 0);
+
+    region_init(&region);
+    region_add(&region, &rect);
+    a->copy_pixels(region, *ap);
+    b->copy_pixels(region, *bp);
+    ap->equal(*bp, rect);
 
-#define DRAW(type) {                                \
-    PRE_DRAW;                                       \
-    canvas->draw_##type(*type, message->size());    \
-    POST_DRAW;                                      \
-    if (type->base.surface_id == 0) {               \
-        invalidate(type->base.box, false);          \
-    }                                               \
+    delete ap;
+    delete bp;
 }
 
 void DisplayChannel::handle_copy_bits(RedPeer::InMessage* message)
 {
     Canvas *canvas;
     SpiceMsgDisplayCopyBits* copy_bits = (SpiceMsgDisplayCopyBits*)message->data();
-    PRE_DRAW;
     canvas = _surfaces_cache[copy_bits->base.surface_id];
+    Canvas *swcanvas = _swsurfaces_cache[copy_bits->base.surface_id];
+
     canvas->copy_bits(*copy_bits, message->size());
-    POST_DRAW;
     if (copy_bits->base.surface_id == 0) {
         invalidate(copy_bits->base.box, false);
     }
+
+    if (_check_diff) {
+        swcanvas->copy_bits(*copy_bits, message->size());
+        check_diff(swcanvas, canvas, copy_bits->base.box);
+    }
 }
 
 void DisplayChannel::handle_draw_fill(RedPeer::InMessage* message)
@@ -1654,7 +1694,7 @@ void DisplayChannel::handle_draw_fill(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawFill* fill = (SpiceMsgDisplayDrawFill*)message->data();
     canvas = _surfaces_cache[fill->base.surface_id];
-    DRAW(fill);
+    DRAW(fill, FALSE);
 }
 
 void DisplayChannel::handle_draw_opaque(RedPeer::InMessage* message)
@@ -1662,7 +1702,7 @@ void DisplayChannel::handle_draw_opaque(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawOpaque* opaque = (SpiceMsgDisplayDrawOpaque*)message->data();
     canvas = _surfaces_cache[opaque->base.surface_id];
-    DRAW(opaque);
+    DRAW(opaque, TRUE);
 }
 
 void DisplayChannel::handle_draw_copy(RedPeer::InMessage* message)
@@ -1670,7 +1710,7 @@ void DisplayChannel::handle_draw_copy(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawCopy* copy = (SpiceMsgDisplayDrawCopy*)message->data();
     canvas = _surfaces_cache[copy->base.surface_id];
-    DRAW(copy);
+    DRAW(copy, TRUE);
 }
 
 void DisplayChannel::handle_draw_blend(RedPeer::InMessage* message)
@@ -1678,7 +1718,7 @@ void DisplayChannel::handle_draw_blend(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawBlend* blend = (SpiceMsgDisplayDrawBlend*)message->data();
     canvas = _surfaces_cache[blend->base.surface_id];
-    DRAW(blend);
+    DRAW(blend, TRUE);
 }
 
 void DisplayChannel::handle_draw_blackness(RedPeer::InMessage* message)
@@ -1686,7 +1726,7 @@ void DisplayChannel::handle_draw_blackness(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawBlackness* blackness = (SpiceMsgDisplayDrawBlackness*)message->data();
     canvas = _surfaces_cache[blackness->base.surface_id];
-    DRAW(blackness);
+    DRAW(blackness, TRUE);
 }
 
 void DisplayChannel::handle_draw_whiteness(RedPeer::InMessage* message)
@@ -1694,7 +1734,7 @@ void DisplayChannel::handle_draw_whiteness(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawWhiteness* whiteness = (SpiceMsgDisplayDrawWhiteness*)message->data();
     canvas = _surfaces_cache[whiteness->base.surface_id];
-    DRAW(whiteness);
+    DRAW(whiteness, TRUE);
 }
 
 void DisplayChannel::handle_draw_invers(RedPeer::InMessage* message)
@@ -1702,7 +1742,7 @@ void DisplayChannel::handle_draw_invers(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawInvers* invers = (SpiceMsgDisplayDrawInvers*)message->data();
     canvas = _surfaces_cache[invers->base.surface_id];
-    DRAW(invers);
+    DRAW(invers, TRUE);
 }
 
 void DisplayChannel::handle_draw_rop3(RedPeer::InMessage* message)
@@ -1710,7 +1750,7 @@ void DisplayChannel::handle_draw_rop3(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawRop3* rop3 = (SpiceMsgDisplayDrawRop3*)message->data();
     canvas = _surfaces_cache[rop3->base.surface_id];
-    DRAW(rop3);
+    DRAW(rop3, TRUE);
 }
 
 void DisplayChannel::handle_draw_stroke(RedPeer::InMessage* message)
@@ -1718,7 +1758,7 @@ void DisplayChannel::handle_draw_stroke(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawStroke* stroke = (SpiceMsgDisplayDrawStroke*)message->data();
     canvas = _surfaces_cache[stroke->base.surface_id];
-    DRAW(stroke);
+    DRAW(stroke, TRUE);
 }
 
 void DisplayChannel::handle_draw_text(RedPeer::InMessage* message)
@@ -1726,7 +1766,7 @@ void DisplayChannel::handle_draw_text(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawText* text = (SpiceMsgDisplayDrawText*)message->data();
     canvas = _surfaces_cache[text->base.surface_id];
-    DRAW(text);
+    DRAW(text, FALSE);
 }
 
 void DisplayChannel::handle_draw_transparent(RedPeer::InMessage* message)
@@ -1734,7 +1774,7 @@ void DisplayChannel::handle_draw_transparent(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawTransparent* transparent = (SpiceMsgDisplayDrawTransparent*)message->data();
     canvas = _surfaces_cache[transparent->base.surface_id];
-    DRAW(transparent);
+    DRAW(transparent, TRUE);
 }
 
 void DisplayChannel::handle_draw_alpha_blend(RedPeer::InMessage* message)
@@ -1742,7 +1782,7 @@ void DisplayChannel::handle_draw_alpha_blend(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawAlphaBlend* alpha_blend = (SpiceMsgDisplayDrawAlphaBlend*)message->data();
     canvas = _surfaces_cache[alpha_blend->base.surface_id];
-    DRAW(alpha_blend);
+    DRAW(alpha_blend, FALSE);
 }
 
 void DisplayChannel::handle_draw_composite(RedPeer::InMessage* message)
@@ -1750,7 +1790,7 @@ void DisplayChannel::handle_draw_composite(RedPeer::InMessage* message)
     Canvas *canvas;
     SpiceMsgDisplayDrawComposite* composite = (SpiceMsgDisplayDrawComposite*)message->data();
     canvas = _surfaces_cache[composite->base.surface_id];
-    DRAW(composite);
+    DRAW(composite, TRUE);
 }
 
 void DisplayChannel::streams_time()
diff --git a/client/display_channel.h b/client/display_channel.h
index 197ae73..8a30289 100644
--- a/client/display_channel.h
+++ b/client/display_channel.h
@@ -187,6 +187,7 @@ private:
 
 private:
     SurfacesCache _surfaces_cache;
+    SurfacesCache _swsurfaces_cache;
     PixmapCache& _pixmap_cache;
     PaletteCache _palette_cache;
     GlzDecoderWindow& _glz_window;
@@ -226,6 +227,7 @@ private:
     InterruptUpdate _interrupt_update;
 
     bool _mig_wait_primary;
+    bool _check_diff;
     friend class SetModeEvent;
     friend class CreatePrimarySurfaceEvent;
     friend class DestroyPrimarySurfaceEvent;
diff --git a/client/red_pixmap.h b/client/red_pixmap.h
index 240ed76..3f12855 100644
--- a/client/red_pixmap.h
+++ b/client/red_pixmap.h
@@ -36,6 +36,25 @@ public:
     bool is_big_endian_bits();
     virtual RedDrawable::Format get_format() { return _format; }
 
+    bool equal(const RedPixmap &other, const SpiceRect &rect) const {
+        spice_debug("l:%d r:%d t:%d b:%d", rect.left, rect.right, rect.top, rect.bottom);
+        for (int x = rect.left; x < rect.right; ++x)
+            for (int y = rect.top; y < rect.bottom; ++y) {
+                for (int i = 0; i < 3; i++) { // ignore alpha
+                    int p = x * 4 + y * _stride + i;
+                    if (other._data[p] != _data[p]) {
+                        spice_printerr("equal fails at (+%d+%d) +%d+%d:%d in %dx%d",
+                                       rect.left, rect.top, x-rect.left, y-rect.top, i,
+                                       _width-rect.left, _height-rect.top);
+                        if (getenv("DIFFBP"))
+                            SPICE_BREAKPOINT();
+                        return false;
+                    }
+                }
+            }
+        return true;
+    }
+
 protected:
     Format _format;
     int _width;
diff --git a/client/utils.h b/client/utils.h
index 4657279..d8d6962 100644
--- a/client/utils.h
+++ b/client/utils.h
@@ -50,6 +50,9 @@ private:
     throw Exception(exption_string, err);                       \
 }
 
+#define SPICE_BREAKPOINT() do{                  \
+    __asm__ __volatile__ ("int $03");           \
+}while(0)
 
 template <class T>
 class AutoRef {
commit c3d6f0e1df482f207d0c061465361853c444aad8
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 21:57:11 2013 +0200

    spicec: do not abort if cache error

diff --git a/client/cache.hpp b/client/cache.hpp
index e267f42..7dce671 100644
--- a/client/cache.hpp
+++ b/client/cache.hpp
@@ -45,7 +45,8 @@ public:
 
         while (*item) {
             if ((*item)->id == id) {
-                THROW("%s id %" PRIu64 ", double insert", Treat::name(), id);
+                spice_printerr("%s id %" PRIu64 ", double insert", Treat::name(), id);
+                return;
             }
             item = &(*item)->next;
         }
commit e67caa8516ad040351476076272385d8db81880a
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:06:51 2013 +0200

    spicec: add SPICE_NOGRAB
    
    Similar to spice-gtk, disable mouse and keyboard grab (useful when
    running under a debugger)

diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index d82f5b7..7e16fcd 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -1765,9 +1765,13 @@ void RedWindow::do_start_key_interception()
     // that reason we temporary disable focus event handling. Same happens
     // LeaveNotify and EnterNotify.
 
+    if (getenv("SPICE_NOGRAB"))
+        return;
+
     ASSERT(_focused);
     XLockDisplay(x_display);
     XGrabKeyboard(x_display, _win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+
     XUnlockDisplay(x_display);
     sync(true);
     _listener.on_start_key_interception();
@@ -1845,6 +1849,9 @@ void RedWindow::release_mouse()
 
 void RedWindow::capture_mouse()
 {
+    if (getenv("SPICE_NOGRAB"))
+        return;
+
     int grab_retries = MOUSE_GRAB_RETRIES;
     XLockDisplay(x_display);
     XSync(x_display, False);
commit d524047400f14d0899dcff1a057f0e25b3dfcff9
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:04:47 2013 +0200

    spicec: remove dead GL code

diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index b6e11e1..d82f5b7 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -1073,28 +1073,6 @@ void RedWindow_p::wait_for_unmap()
     }
 }
 
-#ifdef USE_OPENGL
-void RedWindow_p::set_glx(int width, int height)
-{
-    if (_glcont_copy) {
-        XLockDisplay(x_display);
-        XSync(x_display, False);
-        XUnlockDisplay(x_display);
-        glXMakeCurrent(x_display, _win, _glcont_copy);
-        //glDrawBuffer(GL_FRONT);
-        glMatrixMode(GL_PROJECTION);
-        glLoadIdentity();
-        gluOrtho2D(0, width, 0, height);
-        glMatrixMode(GL_MODELVIEW);
-        glLoadIdentity();
-        glViewport(0, 0, width, height);
-        glColor3f(1, 1, 1);
-        glEnable(GL_TEXTURE_2D);
-        GLC_ERROR_TEST_FINISH;
-    }
-}
-#endif // USE_OPENGL
-
 void RedWindow_p::set_minmax(PixelsSource_p& pix_source)
 {
     //todo: auto res
@@ -1134,9 +1112,6 @@ Cursor RedWindow_p::create_invisible_cursor(Window window)
 RedWindow_p::RedWindow_p()
     : _win (None)
     , _show_pos_valid (false)
-#ifdef USE_OPENGL
-    , _glcont_copy (NULL)
-#endif // USE_OPENGL
     , _icon (NULL)
     , _focused (false)
     , _ignore_foucs (false)
@@ -1174,12 +1149,6 @@ void RedWindow_p::destroy(RedWindow& red_window, PixelsSource_p& pix_source)
     XFreeCursor(x_display, _invisible_cursor);
     _invisible_cursor = None;
     XDeleteContext(x_display, window, user_data_context);
-#ifdef USE_OPENGL
-    if (_glcont_copy) {
-        glXDestroyContext(x_display, _glcont_copy);
-        _glcont_copy = NULL;
-    }
-#endif // USE_OPENGL
     XDestroyWindow(x_display, window);
     XFreeColormap(x_display, _colormap);
     XFreeGC(x_display, pix_source.x_drawable.gc);
diff --git a/client/x11/red_window_p.h b/client/x11/red_window_p.h
index 2782539..4856be0 100644
--- a/client/x11/red_window_p.h
+++ b/client/x11/red_window_p.h
@@ -67,9 +67,6 @@ protected:
     bool _expect_parent;
     SpicePoint _show_pos;
     bool _show_pos_valid;
-#ifdef USE_OPENGL
-    GLXContext _glcont_copy;
-#endif // USE_OPENGL
     Icon* _icon;
     bool _focused;
     bool _ignore_foucs;
commit a2be67cbfaf20303704ec549313778729190d89b
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:10:17 2013 +0200

    spicec: use doublebuffer for opengl
    
    This visually reduces glitches without noticeable speed difference.
    
    It's also the traditionnal way of doing opengl.

diff --git a/client/red_window.h b/client/red_window.h
index dbd0c79..bf59d8b 100644
--- a/client/red_window.h
+++ b/client/red_window.h
@@ -82,6 +82,8 @@ public:
 
     void set_type_gl();
     void unset_type_gl();
+
+    void swap_gl();
 #endif
 
     int get_screen_num();
diff --git a/client/screen.cpp b/client/screen.cpp
index a05d562..e76fd50 100644
--- a/client/screen.cpp
+++ b/client/screen.cpp
@@ -357,6 +357,7 @@ inline void RedScreen::update_done()
         }
         layer->on_update_completion(_update_mark - 1);
     }
+    _window.swap_gl();
 }
 
 inline void RedScreen::update_composit(QRegion& composit_rgn)
diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index da6b634..475ee6a 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -3224,7 +3224,7 @@ void Platform::init()
         int num_configs;
         int attrlist[] = {
             GLX_RENDER_TYPE, GLX_RGBA_BIT,
-            GLX_DOUBLEBUFFER, False,
+            GLX_DOUBLEBUFFER, True,
             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
             GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
             GLX_RED_SIZE, 8,
diff --git a/client/x11/red_pixmap_gl.cpp b/client/x11/red_pixmap_gl.cpp
index 693b67d..1a58628 100644
--- a/client/x11/red_pixmap_gl.cpp
+++ b/client/x11/red_pixmap_gl.cpp
@@ -79,8 +79,6 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
             glXDestroyContext(XPlatform::get_display(), _glcont);
             THROW("no GL_EXT_framebuffer_object extension");
         }
-        glDrawBuffer(GL_FRONT);
-        glReadBuffer(GL_FRONT);
 
         glGenTextures(1, &tex);
         glBindTexture(GL_TEXTURE_2D, tex);
diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index 83144a5..b6e11e1 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -2122,6 +2122,18 @@ void RedWindow::untouch_context()
     glXMakeCurrent(x_display, 0, 0);
 }
 
+void RedWindow::swap_gl()
+{
+    PixelsSource_p *pix_source = (PixelsSource_p*)get_opaque();
+    RedGlContext context = pix_source->x_drawable.context;
+
+    if (!context)
+        return;
+
+    glXMakeCurrent(x_display, get_window(), context);
+    glXSwapBuffers(x_display, get_window());
+}
+
 void RedWindow::set_type_gl()
 {
     PixelsSource_p *pix_source = (PixelsSource_p*)get_opaque();
commit fe72894bb808969ef6c72a4852fa78477e2f77ef
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:47:06 2013 +0200

    spicec: fix non-doublebuffer drawing
    
    First, context must set it, then Draw/ReadBuffer must be set to FRONT,
    and then explicit Flush is needed.
    
    This patch is mostly for future reference, it is mostly discarded in
    following patch using double-buffer.

diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index 14c6e0c..da6b634 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -3224,6 +3224,7 @@ void Platform::init()
         int num_configs;
         int attrlist[] = {
             GLX_RENDER_TYPE, GLX_RGBA_BIT,
+            GLX_DOUBLEBUFFER, False,
             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
             GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
             GLX_RED_SIZE, 8,
diff --git a/client/x11/red_drawable.cpp b/client/x11/red_drawable.cpp
index 54e53f8..19532c7 100644
--- a/client/x11/red_drawable.cpp
+++ b/client/x11/red_drawable.cpp
@@ -85,6 +85,7 @@ static inline void copy_to_gldrawable_from_gltexture(const RedDrawable_p* dest,
     if (rendertype == RENDER_TYPE_FBO) {
         GLuint fbo;
 
+        glFlush();
         fbo = source->gl.fbo;
         glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo);
     } else {
diff --git a/client/x11/red_pixmap_gl.cpp b/client/x11/red_pixmap_gl.cpp
index 1a58628..693b67d 100644
--- a/client/x11/red_pixmap_gl.cpp
+++ b/client/x11/red_pixmap_gl.cpp
@@ -79,6 +79,8 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
             glXDestroyContext(XPlatform::get_display(), _glcont);
             THROW("no GL_EXT_framebuffer_object extension");
         }
+        glDrawBuffer(GL_FRONT);
+        glReadBuffer(GL_FRONT);
 
         glGenTextures(1, &tex);
         glBindTexture(GL_TEXTURE_2D, tex);
commit c7d1024d9786b88665289182a5ed9e590b3a70c4
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:04:10 2013 +0200

    spicec: use standard opengl 3.0 framebuffer

diff --git a/client/x11/pixels_source_p.h b/client/x11/pixels_source_p.h
index 64b0c50..8431121 100644
--- a/client/x11/pixels_source_p.h
+++ b/client/x11/pixels_source_p.h
@@ -73,6 +73,7 @@ struct PixelsSource_p {
             Win win;
             GLuint tex;
             GLuint stencil_tex;
+            GLuint rbo;
             int width, height;
             int width_powed, height_powed;
             union {
diff --git a/client/x11/red_drawable.cpp b/client/x11/red_drawable.cpp
index bb8ceb4..54e53f8 100644
--- a/client/x11/red_drawable.cpp
+++ b/client/x11/red_drawable.cpp
@@ -62,7 +62,7 @@ static inline void copy_to_gldrawable_from_gltexture(const RedDrawable_p* dest,
 
     rendertype = source->gl.rendertype;
     if (rendertype == RENDER_TYPE_FBO) {
-        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+        glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
     } else {
         win = source->gl.win;
         context = source->gl.context;
@@ -86,7 +86,7 @@ static inline void copy_to_gldrawable_from_gltexture(const RedDrawable_p* dest,
         GLuint fbo;
 
         fbo = source->gl.fbo;
-        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+        glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo);
     } else {
         pbuffer = source->gl.pbuff;
         glXMakeCurrent(XPlatform::get_display(), pbuffer, context);
@@ -107,7 +107,7 @@ static inline void copy_to_gldrawable_from_pixmap(const RedDrawable_p* dest,
 
     rendertype = dest->source.x_drawable.rendertype;
     if (rendertype == RENDER_TYPE_FBO) {
-        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+        glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
         glBindTexture(GL_TEXTURE_2D, 0);
     } else {
         context = dest->source.x_drawable.context;
@@ -130,7 +130,7 @@ static inline void copy_to_gldrawable_from_pixmap(const RedDrawable_p* dest,
         GLuint fbo;
 
         fbo = dest->source.x_drawable.fbo;
-        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+        glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo);
     } else {
         pbuffer = dest->source.x_drawable.pbuff;
         glXMakeCurrent(XPlatform::get_display(), pbuffer, context);
@@ -341,7 +341,7 @@ static inline void copy_to_pixmap_from_gltexture(const RedDrawable_p* dest,
 
     rendertype = source->gl.rendertype;
     if (rendertype == RENDER_TYPE_FBO) {
-        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source->gl.fbo);
+        glBindFramebuffer(GL_FRAMEBUFFER_EXT, source->gl.fbo);
         glBindTexture(GL_TEXTURE_2D, 0);
     } else {
         context = source->gl.context;
@@ -673,7 +673,7 @@ static inline void fill_gl_drawable(RedDrawable_p* dest, const SpiceRect& area,
     vertex_x2 = vertex_x1 + (area.right - area.left);
     vertex_y2 = vertex_y1 + (area.bottom - area.top);
 
-    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+    glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
 
     glColor3f(rgb32_get_red(color), rgb32_get_green(color),
               rgb32_get_blue(color));
diff --git a/client/x11/red_pixmap_gl.cpp b/client/x11/red_pixmap_gl.cpp
index 8d81c31..1a58628 100644
--- a/client/x11/red_pixmap_gl.cpp
+++ b/client/x11/red_pixmap_gl.cpp
@@ -38,9 +38,10 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
                          RenderType rendertype)
     : RedPixmap(width, height, format, top_bottom)
 {
-    GLuint fbo;
-    GLuint tex;
+    GLuint fbo = 0;
+    GLuint tex = 0;
     GLuint stencil_tex = 0;
+    GLuint rbo = 0;
     Win xwin;
     //GLint max_texture_size;
 
@@ -68,6 +69,9 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
     }*/
 
     if (rendertype == RENDER_TYPE_FBO) {
+        int w = gl_get_to_power_two(width);
+        int h = gl_get_to_power_two(height);
+
         glXMakeCurrent(XPlatform::get_display(), xwin, _glcont);
         if (!gluCheckExtension((GLubyte *)"GL_EXT_framebuffer_object",
                                glGetString(GL_EXTENSIONS))) {
@@ -75,41 +79,32 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
             glXDestroyContext(XPlatform::get_display(), _glcont);
             THROW("no GL_EXT_framebuffer_object extension");
         }
-        glEnable(GL_TEXTURE_2D);
-        glGenFramebuffersEXT(1, &fbo);
-        glGenTextures(1, &tex);
-        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
 
+        glGenTextures(1, &tex);
         glBindTexture(GL_TEXTURE_2D, tex);
-
-        glTexImage2D(GL_TEXTURE_2D, 0, 4, gl_get_to_power_two(width),
-                     gl_get_to_power_two(height), 0, GL_BGRA, GL_UNSIGNED_BYTE,
-                     NULL);
-
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                                  GL_TEXTURE_2D, tex, 0);
-
-
-        glGenTextures(1, &stencil_tex);
-        glBindTexture(GL_TEXTURE_2D, stencil_tex);
-        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT,
-                     gl_get_to_power_two(width), gl_get_to_power_two(height), 0,
-                     GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
-        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
-                                  GL_DEPTH_ATTACHMENT_EXT,
-                                  GL_TEXTURE_2D, stencil_tex, 0);
-        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
-                                  GL_STENCIL_ATTACHMENT_EXT,
-                                  GL_TEXTURE_2D, stencil_tex, 0);
         glBindTexture(GL_TEXTURE_2D, 0);
 
+        glGenRenderbuffers(1, &rbo);
+        glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
+        glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+        glGenFramebuffers(1, &fbo);
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
+
+        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+        if (status != GL_FRAMEBUFFER_COMPLETE)
+            THROW("bad fbo status: %d\n", status);
+
         ((PixelsSource_p*)get_opaque())->gl.fbo = fbo;
         win->set_render_fbo(fbo);
-    } else {
+
+    } else if (rendertype == RENDER_TYPE_PBUFF) {
         GLXPbuffer pbuff;
 
         pbuff = win->create_pbuff(gl_get_to_power_two(width),
@@ -133,6 +128,8 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedDrawable::Format format,
         glBindTexture(GL_TEXTURE_2D, 0);
         ((PixelsSource_p*)get_opaque())->gl.pbuff = pbuff;
         win->set_render_pbuff(pbuff);
+    } else {
+        abort();
     }
 
     ((PixelsSource_p*)get_opaque())->gl.stencil_tex = stencil_tex;
@@ -269,11 +266,27 @@ void RedPixmapGL::past_copy()
 RedPixmapGL::~RedPixmapGL()
 {
     GLXPbuffer pbuff;
-    GLuint fbo;
+    GLuint fbo, rbo;
     RenderType rendertype;
     GLuint tex;
     GLuint stencil_tex;
 
+    rendertype = ((PixelsSource_p*)get_opaque())->gl.rendertype;
+    if (rendertype == RENDER_TYPE_FBO) {
+        fbo = ((PixelsSource_p*)get_opaque())->gl.fbo;
+        rbo = ((PixelsSource_p*)get_opaque())->gl.rbo;
+        spice_debug("deletefbo %u", fbo);
+        if (fbo) {
+            glDeleteFramebuffers(1, &fbo);
+        }
+        if (rbo) {
+            glDeleteRenderbuffers(1, &rbo);
+        }
+    } else {
+        pbuff = ((PixelsSource_p*)get_opaque())->gl.pbuff;
+        glXDestroyPbuffer(XPlatform::get_display(), pbuff);
+    }
+
     /*
      * GL textures might be destroyed by res change.
      */
@@ -291,17 +304,6 @@ RedPixmapGL::~RedPixmapGL()
         }
     }
 
-    rendertype = ((PixelsSource_p*)get_opaque())->gl.rendertype;
-    if (rendertype == RENDER_TYPE_FBO) {
-        fbo = ((PixelsSource_p*)get_opaque())->gl.fbo;
-        if (fbo) {
-            glDeleteFramebuffersEXT(1, &fbo);
-        }
-    } else {
-        pbuff = ((PixelsSource_p*)get_opaque())->gl.pbuff;
-        glXDestroyPbuffer(XPlatform::get_display(), pbuff);
-    }
-
     /*
      * Both tex and stenctil_tex are textures and therefore they are destroyed
      * when the context is gone, so we dont free them here as they might have
commit 862bb2cd07e42ead1e0852aba3431eb273155847
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Tue Sep 24 13:37:27 2013 +0200

    spicec: refresh the display after display resize

diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 49a4c6a..9ba93c4 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -1276,6 +1276,10 @@ void DisplayChannel::create_canvas(int surface_id, const std::vector<int>& canva
     if (i == canvas_types.size()) {
         THROW("create canvas failed");
     }
+
+    // make sure to refresh the whole display
+    SpiceRect rect = { 0, 0, width, height };
+    invalidate(rect, true);
 }
 
 void DisplayChannel::handle_mode(RedPeer::InMessage* message)
commit 0ca7704a5ab4417a94c9911ace52eba787535ffe
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 23 22:01:53 2013 +0200

    spicec: warn when throwing exception
    
    This helps to identify the code location of exception

diff --git a/client/utils.h b/client/utils.h
index c23e04f..4657279 100644
--- a/client/utils.h
+++ b/client/utils.h
@@ -19,6 +19,7 @@
 #define _H_UTILS
 
 #include "common.h"
+#include "common/log.h"
 #include <spice/error_codes.h>
 #include <spice/macros.h>
 
@@ -38,12 +39,14 @@ private:
 #define THROW(format, ...)  {                                   \
     std::string exption_string;                                 \
     string_printf(exption_string, format, ## __VA_ARGS__ );     \
+    spice_warning(format, ## __VA_ARGS__ );                    \
     throw Exception(exption_string);                            \
 }
 
 #define THROW_ERR(err, format, ...)  {                          \
     std::string exption_string;                                 \
     string_printf(exption_string, format, ## __VA_ARGS__ );     \
+    spice_warning(format, ## __VA_ARGS__ );      \
     throw Exception(exption_string, err);                       \
 }
 
commit 788418db651080f37fea16690c46f84fa8cf7d81
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Sep 30 02:19:15 2013 +0200

    update spice-common

diff --git a/spice-common b/spice-common
index 3363fe7..e443c9f 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit 3363fe79f9d450774dd018a794c0b4381c1ef0a7
+Subproject commit e443c9f6039407633d38a0eba03c344272ac8559


More information about the Spice-commits mailing list