summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/display_channel.cpp88
-rw-r--r--client/display_channel.h2
-rw-r--r--client/red_pixmap.h19
-rw-r--r--client/utils.h3
4 files changed, 88 insertions, 24 deletions
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 9ba93c48..47076ad9 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 197ae73a..8a302896 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 240ed768..3f12855e 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 46572795..d8d69626 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 {