[Spice-devel] [PATCH] spice server: surface create/destroy protocol support
Izik Eidus
ieidus at redhat.com
Sat Feb 20 02:40:23 PST 2010
From 3d5ce2e630a02f5edd8b22fe353433bb9a8321d8 Mon Sep 17 00:00:00 2001
From: Izik Eidus <ieidus at redhat.com>
Date: Thu, 18 Feb 2010 01:11:33 +0200
Subject: [PATCH] spice server: surface create/destroy protocol support
Now we can send commands from the server to the client
to destroy surfaces (right now just the primary surface)
(Needed for offscreens support)
Another patch`s on the way.
Signed-off-by: Izik Eidus <ieidus at redhat.com>
---
client/debug.h | 5 +
client/display_channel.cpp | 147 +++++++++++++++++++++--------
client/display_channel.h | 8 ++
server/red_worker.c | 224 +++++++++++++++++++++++++++++++++-----------
4 files changed, 285 insertions(+), 99 deletions(-)
diff --git a/client/debug.h b/client/debug.h
index 1c6f6a4..ce8fc98 100644
--- a/client/debug.h
+++ b/client/debug.h
@@ -92,6 +92,11 @@ LOG4CPP_LOGGER("spice")
ON_PANIC(); \
}
+#define PANIC_ON(x) if ((x)) { \
+ LOG(FATAL, "%s panic %s\n", __FUNCTION__, #x); \
+ ON_PANIC(); \
+}
+
#define DBGLEVEL 1000
#define DBG(level, format, ...) { \
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index a60832a..513ab7b 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -46,9 +46,9 @@
static Mutex avcodec_mutex;
-class SetModeEvent: public SyncEvent {
+class CreatePrimarySurfaceEvent: public SyncEvent {
public:
- SetModeEvent(DisplayChannel& channel, int width, int height, int depth)
+ CreatePrimarySurfaceEvent(DisplayChannel& channel, int width, int height, int depth)
: _channel (channel)
, _width (width)
, _height (height)
@@ -59,7 +59,6 @@ public:
virtual void do_response(AbstractProcessLoop& events_loop)
{
Application* app = (Application*)events_loop.get_owner();
- _channel.destroy_canvas();
_channel.screen()->lock_size();
_channel.screen()->resize(_width, _height);
_channel.create_canvas(app->get_canvas_types(), _width, _height, _depth);
@@ -72,6 +71,22 @@ private:
int _depth;
};
+class DestroyPrimarySurfaceEvent: public SyncEvent {
+public:
+ DestroyPrimarySurfaceEvent(DisplayChannel& channel)
+ : _channel (channel)
+ {
+ }
+
+ virtual void do_response(AbstractProcessLoop& events_loop)
+ {
+ _channel.destroy_canvas();
+ }
+
+private:
+ DisplayChannel& _channel;
+};
+
class UnlockScreenEvent: public Event {
public:
UnlockScreenEvent(RedScreen* screen)
@@ -664,7 +679,6 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
sizeof(SpiceMsgDisconnect));
handler->set_handler(SPICE_MSG_NOTIFY, &DisplayChannel::handle_notify, sizeof(SpiceMsgNotify));
- handler->set_handler(SPICE_MSG_DISPLAY_MODE, &DisplayChannel::handle_mode, sizeof(SpiceMsgDisplayMode));
handler->set_handler(SPICE_MSG_DISPLAY_MARK, &DisplayChannel::handle_mark, 0);
handler->set_handler(SPICE_MSG_DISPLAY_RESET, &DisplayChannel::handle_reset, 0);
@@ -688,6 +702,11 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL,
&DisplayChannel::handle_stream_destroy_all, 0);
+ handler->set_handler(SPICE_MSG_DISPLAY_SURFACE_CREATE, &DisplayChannel::handle_surface_create,
+ sizeof(SpiceMsgSurfaceCreate));
+ handler->set_handler(SPICE_MSG_DISPLAY_SURFACE_DESTROY, &DisplayChannel::handle_surface_destroy,
+ sizeof(SpiceMsgSurfaceDestroy));
+
get_process_loop().add_trigger(_streams_trigger);
#ifdef USE_OGL
get_process_loop().add_trigger(_gl_interrupt_recreate);
@@ -1228,44 +1247,6 @@ void DisplayChannel::create_canvas(const std::vector<int>& canvas_types, int wid
set_draw_handlers();
}
-void DisplayChannel::handle_mode(RedPeer::InMessage* message)
-{
- SpiceMsgDisplayMode *mode = (SpiceMsgDisplayMode *)message->data();
-
- _mark = false;
- attach_to_screen(get_client().get_application(), get_id());
- clear_area();
-#ifdef USE_OGL
- if (screen()) {
- if (_canvas.get()) {
- if (_canvas->get_pixmap_type() == CANVAS_TYPE_GL) {
- screen()->unset_type_gl();
- screen()->untouch_context();
- }
- }
- }
-#endif
- AutoRef<SetModeEvent> event(new SetModeEvent(*this, mode->x_res,
- mode->y_res, mode->bits));
- get_client().push_event(*event);
- (*event)->wait();
- if (!(*event)->success()) {
- THROW("set mode failed");
- }
-
- _x_res = mode->x_res;
- _y_res = mode->y_res;
- _depth = mode->bits;
-
-#ifdef USE_OGL
- if (_canvas->get_pixmap_type() == CANVAS_TYPE_GL) {
- ((GCanvas *)(_canvas.get()))->touch_context();
- screen()->set_update_interrupt_trigger(&_interrupt_update);
- screen()->set_type_gl();
- }
-#endif
-}
-
void DisplayChannel::handle_mark(RedPeer::InMessage *message)
{
_mark = true;
@@ -1367,6 +1348,7 @@ void DisplayChannel::handle_stream_create(RedPeer::InMessage* message)
{
SpiceMsgDisplayStreamCreate* stream_create = (SpiceMsgDisplayStreamCreate*)message->data();
+ PANIC_ON(stream_create->surface_id != 0);
Lock lock(_streams_lock);
if (_streams.size() <= stream_create->id) {
_streams.resize(stream_create->id + 1);
@@ -1465,6 +1447,74 @@ void DisplayChannel::handle_stream_destroy_all(RedPeer::InMessage* message)
destroy_strams();
}
+void DisplayChannel::create_primary_surface(int width, int height, int depth)
+{
+ _mark = false;
+ attach_to_screen(get_client().get_application(), get_id());
+ clear_area();
+
+ AutoRef<CreatePrimarySurfaceEvent> event(new CreatePrimarySurfaceEvent(*this, width, height,
+ depth));
+ get_client().push_event(*event);
+ (*event)->wait();
+ if (!(*event)->success()) {
+ THROW("Create primary surface failed");
+ }
+
+ _x_res = width;
+ _y_res = height;
+ _depth = depth;
+
+#ifdef USE_OGL
+ if (_canvas->get_pixmap_type() == CANVAS_TYPE_GL) {
+ ((GCanvas *)(_canvas.get()))->touch_context();
+ screen()->set_update_interrupt_trigger(&_interrupt_update);
+ screen()->set_type_gl();
+ }
+#endif
+}
+
+void DisplayChannel::destroy_primary_surface()
+{
+#ifdef USE_OGL
+ if (screen()) {
+ if (_canvas.get()) {
+ if (_canvas->get_pixmap_type() == CANVAS_TYPE_GL) {
+ screen()->unset_type_gl();
+ screen()->untouch_context();
+ }
+ }
+ }
+#endif
+
+ AutoRef<DestroyPrimarySurfaceEvent> event(new DestroyPrimarySurfaceEvent(*this));
+ get_client().push_event(*event);
+ (*event)->wait();
+ if (!(*event)->success()) {
+ THROW("Destroying primary surface failed");
+ }
+
+ AutoRef<UnlockScreenEvent> unlock_event(new UnlockScreenEvent(screen()));
+ get_client().push_event(*unlock_event);
+}
+
+void DisplayChannel::handle_surface_create(RedPeer::InMessage* message)
+{
+ SpiceMsgSurfaceCreate* surface_create = (SpiceMsgSurfaceCreate*)message->data();
+ PANIC_ON(surface_create->surface_id != 0);
+ PANIC_ON(surface_create->flags != SPICE_SURFACE_FLAGS_PRIMARY);
+
+ create_primary_surface(surface_create->width, surface_create->height, surface_create->depth);
+}
+
+void DisplayChannel::handle_surface_destroy(RedPeer::InMessage* message)
+{
+ SpiceMsgSurfaceDestroy* surface_destroy = (SpiceMsgSurfaceDestroy*)message->data();
+ PANIC_ON(surface_destroy->surface_id != 0);
+
+ destroy_primary_surface();
+}
+
#define PRE_DRAW
#define POST_DRAW
@@ -1478,6 +1528,7 @@ void DisplayChannel::handle_stream_destroy_all(RedPeer::InMessage* message)
void DisplayChannel::handle_copy_bits(RedPeer::InMessage* message)
{
SpiceMsgDisplayCopyBits* copy_bits = (SpiceMsgDisplayCopyBits*)message->data();
+ PANIC_ON(copy_bits->base.surface_id != 0);
PRE_DRAW;
_canvas->copy_bits(*copy_bits, message->size());
POST_DRAW;
@@ -1487,72 +1538,84 @@ void DisplayChannel::handle_copy_bits(RedPeer::InMessage* message)
void DisplayChannel::handle_draw_fill(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawFill* fill = (SpiceMsgDisplayDrawFill*)message->data();
+ PANIC_ON(fill->base.surface_id != 0);
DRAW(fill);
}
void DisplayChannel::handle_draw_opaque(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawOpaque* opaque = (SpiceMsgDisplayDrawOpaque*)message->data();
+ PANIC_ON(opaque->base.surface_id != 0);
DRAW(opaque);
}
void DisplayChannel::handle_draw_copy(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawCopy* copy = (SpiceMsgDisplayDrawCopy*)message->data();
+ PANIC_ON(copy->base.surface_id != 0);
DRAW(copy);
}
void DisplayChannel::handle_draw_blend(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawBlend* blend = (SpiceMsgDisplayDrawBlend*)message->data();
+ PANIC_ON(blend->base.surface_id != 0);
DRAW(blend);
}
void DisplayChannel::handle_draw_blackness(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawBlackness* blackness = (SpiceMsgDisplayDrawBlackness*)message->data();
+ PANIC_ON(blackness->base.surface_id != 0);
DRAW(blackness);
}
void DisplayChannel::handle_draw_whiteness(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawWhiteness* whiteness = (SpiceMsgDisplayDrawWhiteness*)message->data();
+ PANIC_ON(whiteness->base.surface_id != 0);
DRAW(whiteness);
}
void DisplayChannel::handle_draw_invers(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawInvers* invers = (SpiceMsgDisplayDrawInvers*)message->data();
+ PANIC_ON(invers->base.surface_id != 0);
DRAW(invers);
}
void DisplayChannel::handle_draw_rop3(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawRop3* rop3 = (SpiceMsgDisplayDrawRop3*)message->data();
+ PANIC_ON(rop3->base.surface_id != 0);
DRAW(rop3);
}
void DisplayChannel::handle_draw_stroke(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawStroke* stroke = (SpiceMsgDisplayDrawStroke*)message->data();
+ PANIC_ON(stroke->base.surface_id != 0);
DRAW(stroke);
}
void DisplayChannel::handle_draw_text(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawText* text = (SpiceMsgDisplayDrawText*)message->data();
+ PANIC_ON(text->base.surface_id != 0);
DRAW(text);
}
void DisplayChannel::handle_draw_transparent(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawTransparent* transparent = (SpiceMsgDisplayDrawTransparent*)message->data();
+ PANIC_ON(transparent->base.surface_id != 0);
DRAW(transparent);
}
void DisplayChannel::handle_draw_alpha_blend(RedPeer::InMessage* message)
{
SpiceMsgDisplayDrawAlphaBlend* alpha_blend = (SpiceMsgDisplayDrawAlphaBlend*)message->data();
+ PANIC_ON(alpha_blend->base.surface_id != 0);
DRAW(alpha_blend);
}
diff --git a/client/display_channel.h b/client/display_channel.h
index 802898f..b3157d9 100644
--- a/client/display_channel.h
+++ b/client/display_channel.h
@@ -132,6 +132,9 @@ private:
void destroy_strams();
void update_cursor();
+ void create_primary_surface(int width, int height, int depth);
+ void destroy_primary_surface();
+
void handle_mode(RedPeer::InMessage* message);
void handle_mark(RedPeer::InMessage* message);
void handle_reset(RedPeer::InMessage* message);
@@ -147,6 +150,9 @@ private:
void handle_stream_destroy(RedPeer::InMessage* message);
void handle_stream_destroy_all(RedPeer::InMessage* message);
+ void handle_surface_create(RedPeer::InMessage* message);
+ void handle_surface_destroy(RedPeer::InMessage* message);
+
void handle_draw_fill(RedPeer::InMessage* message);
void handle_draw_opaque(RedPeer::InMessage* message);
void handle_draw_copy(RedPeer::InMessage* message);
@@ -209,6 +215,8 @@ private:
InterruptUpdate _interrupt_update;
friend class SetModeEvent;
+ friend class CreatePrimarySurfaceEvent;
+ friend class DestroyPrimarySurfaceEvent;
friend class ActivateTimerEvent;
friend class VideoStream;
friend class StreamsTrigger;
diff --git a/server/red_worker.c b/server/red_worker.c
index 2b50b9f..54f10dc 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -221,7 +221,6 @@ typedef struct BufDescriptor {
enum {
PIPE_ITEM_TYPE_DRAW,
- PIPE_ITEM_TYPE_MODE,
PIPE_ITEM_TYPE_INVAL_ONE,
PIPE_ITEM_TYPE_CURSOR,
PIPE_ITEM_TYPE_MIGRATE,
@@ -239,6 +238,8 @@ enum {
PIPE_ITEM_TYPE_PIXMAP_RESET,
PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE,
PIPE_ITEM_TYPE_INVAL_PALLET_CACHE,
+ PIPE_ITEM_TYPE_CREATE_SURFACE,
+ PIPE_ITEM_TYPE_DESTROY_SURFACE,
};
typedef struct PipeItem {
@@ -279,6 +280,16 @@ struct CacheItem {
uint32_t inval_type;
};
+typedef struct SurfaceCreateItem {
+ SpiceMsgSurfaceCreate surface_create;
+ PipeItem pipe_item;
+} SurfaceCreateItem;
+
+typedef struct SurfaceDestroyItem {
+ SpiceMsgSurfaceDestroy surface_destroy;
+ PipeItem pipe_item;
+} SurfaceDestroyItem;
+
enum {
CURSOR_TYPE_INVALID,
CURSOR_TYPE_DEV,
@@ -627,6 +638,8 @@ struct DisplayChannel {
Ring glz_drawables_inst_to_free; // list of instances to be freed
pthread_mutex_t glz_drawables_inst_to_free_lock;
+ uint8_t surface_client_created;
+
struct {
union {
SpiceMsgDisplayDrawFill fill;
@@ -644,6 +657,8 @@ struct DisplayChannel {
SpiceMsgDisplayDrawText text;
SpiceMsgDisplayMode mode;
SpiceMsgDisplayInvalOne inval_one;
+ SpiceMsgSurfaceCreate surface_create;
+ SpiceMsgSurfaceDestroy surface_destroy;
WaitForChannels wait;
struct {
SpiceMsgDisplayStreamCreate message;
@@ -878,10 +893,10 @@ typedef struct DrawContext {
void *line_0;
} DrawContext;
-typedef struct Surface {
+typedef struct RedSurface {
uint32_t refs;
DrawContext context;
-} Surface;
+} RedSurface;
#ifdef STREAM_TRACE
typedef struct ItemTrace {
@@ -928,7 +943,7 @@ typedef struct RedWorker {
uint32_t renderer;
DrawFuncs draw_funcs;
- Surface surface;
+ RedSurface surface;
Ring current_list;
Ring current;
@@ -1452,7 +1467,6 @@ static void red_pipe_clear(RedChannel *channel)
case PIPE_ITEM_TYPE_PIXMAP_RESET:
case PIPE_ITEM_TYPE_PIXMAP_SYNC:
case PIPE_ITEM_TYPE_INVAL_ONE:
- case PIPE_ITEM_TYPE_MODE:
case PIPE_ITEM_TYPE_MIGRATE:
case PIPE_ITEM_TYPE_SET_ACK:
case PIPE_ITEM_TYPE_CURSOR_INIT:
@@ -1460,6 +1474,8 @@ static void red_pipe_clear(RedChannel *channel)
case PIPE_ITEM_TYPE_MIGRATE_DATA:
case PIPE_ITEM_TYPE_INVAL_PALLET_CACHE:
case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE:
+ case PIPE_ITEM_TYPE_CREATE_SURFACE:
+ case PIPE_ITEM_TYPE_DESTROY_SURFACE:
free(item);
break;
case PIPE_ITEM_TYPE_IMAGE:
@@ -1533,9 +1549,36 @@ static void drawables_init(RedWorker *worker)
static void red_reset_stream_trace(RedWorker *worker);
+static SurfaceDestroyItem *get_surface_destroy_item(uint32_t surface_id)
+{
+ SurfaceDestroyItem *destroy;
+
+ destroy = (SurfaceDestroyItem *)malloc(sizeof(SurfaceDestroyItem));
+ PANIC_ON(!destroy);
+
+ destroy->surface_destroy.surface_id = surface_id;
+
+ red_pipe_item_init(&destroy->pipe_item, PIPE_ITEM_TYPE_DESTROY_SURFACE);
+
+ return destroy;
+}
+
+static inline void red_destroy_surface_item(RedWorker *worker, uint32_t surface_id)
+{
+ SurfaceDestroyItem *destroy;
+
+ if (!worker->display_channel) {
+ return;
+ }
+
+ destroy = get_surface_destroy_item(surface_id);
+
+ red_pipe_add(&worker->display_channel->base, &destroy->pipe_item);
+}
+
static inline void __red_destroy_surface(RedWorker *worker)
{
- Surface *surface = &worker->surface;
+ RedSurface *surface = &worker->surface;
if (!--worker->surface.refs) {
#ifdef STREAM_TRACE
@@ -1543,12 +1586,13 @@ static inline void __red_destroy_surface(RedWorker *worker)
#endif
worker->draw_funcs.destroy(surface->context.canvas);
surface->context.canvas = NULL;
+ red_destroy_surface_item(worker, 0);
}
}
static inline void red_destroy_surface(RedWorker *worker)
{
- Surface *surface = &worker->surface;
+ RedSurface *surface = &worker->surface;
PANIC_ON(!surface->context.canvas);
__red_destroy_surface(worker);
@@ -4777,10 +4821,11 @@ static inline void fill_rects_clip(RedChannel *channel, QXLPHYSICAL *in_clip, ui
}
static void fill_base(DisplayChannel *display_channel, SpiceMsgDisplayBase *base, Drawable *drawable,
- uint32_t size)
+ uint32_t size, uint32_t surface_id)
{
RedChannel *channel = &display_channel->base;
add_buf(channel, BUF_TYPE_RAW, base, size, 0, 0);
+ base->surface_id = surface_id;
base->box = drawable->qxl_drawable->bbox;
base->clip = drawable->qxl_drawable->clip;
@@ -6183,7 +6228,7 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
case QXL_DRAW_FILL:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_FILL;
fill_base(display_channel, &display_channel->send_data.u.fill.base, item,
- sizeof(SpiceMsgDisplayDrawFill));
+ sizeof(SpiceMsgDisplayDrawFill), 0);
display_channel->send_data.u.fill.data = drawable->u.fill;
fill_brush(display_channel, &display_channel->send_data.u.fill.data.brush, item);
fill_mask(display_channel, &display_channel->send_data.u.fill.data.mask, item);
@@ -6191,7 +6236,7 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
case QXL_DRAW_OPAQUE:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_OPAQUE;
fill_base(display_channel, &display_channel->send_data.u.opaque.base, item,
- sizeof(SpiceMsgDisplayDrawOpaque));
+ sizeof(SpiceMsgDisplayDrawOpaque), 0);
display_channel->send_data.u.opaque.data = drawable->u.opaque;
fill_bits(display_channel, &display_channel->send_data.u.opaque.data.src_bitmap, item);
fill_brush(display_channel, &display_channel->send_data.u.opaque.data.brush, item);
@@ -6199,7 +6244,8 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
break;
case QXL_DRAW_COPY:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_COPY;
- fill_base(display_channel, &display_channel->send_data.u.copy.base, item, sizeof(SpiceMsgDisplayDrawCopy));
+ fill_base(display_channel, &display_channel->send_data.u.copy.base, item,
+ sizeof(SpiceMsgDisplayDrawCopy), 0);
display_channel->send_data.u.copy.data = drawable->u.copy;
fill_bits(display_channel, &display_channel->send_data.u.copy.data.src_bitmap, item);
fill_mask(display_channel, &display_channel->send_data.u.copy.data.mask, item);
@@ -6207,27 +6253,27 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
case QXL_DRAW_TRANSPARENT:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_TRANSPARENT;
fill_base(display_channel, &display_channel->send_data.u.transparent.base, item,
- sizeof(SpiceMsgDisplayDrawTransparent));
+ sizeof(SpiceMsgDisplayDrawTransparent), 0);
display_channel->send_data.u.transparent.data = drawable->u.transparent;
fill_bits(display_channel, &display_channel->send_data.u.transparent.data.src_bitmap, item);
break;
case QXL_DRAW_ALPHA_BLEND:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND;
fill_base(display_channel, &display_channel->send_data.u.alpha_blend.base, item,
- sizeof(SpiceMsgDisplayDrawAlphaBlend));
+ sizeof(SpiceMsgDisplayDrawAlphaBlend), 0);
display_channel->send_data.u.alpha_blend.data = drawable->u.alpha_blend;
fill_bits(display_channel, &display_channel->send_data.u.alpha_blend.data.src_bitmap, item);
break;
case QXL_COPY_BITS:
channel->send_data.header.type = SPICE_MSG_DISPLAY_COPY_BITS;
fill_base(display_channel, &display_channel->send_data.u.copy_bits.base, item,
- sizeof(SpiceMsgDisplayCopyBits));
+ sizeof(SpiceMsgDisplayCopyBits), 0);
display_channel->send_data.u.copy_bits.src_pos = drawable->u.copy_bits.src_pos;
break;
case QXL_DRAW_BLEND:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_BLEND;
fill_base(display_channel, &display_channel->send_data.u.blend.base, item,
- sizeof(SpiceMsgDisplayDrawBlend));
+ sizeof(SpiceMsgDisplayDrawBlend), 0);
display_channel->send_data.u.blend.data = drawable->u.blend;
fill_bits(display_channel, &display_channel->send_data.u.blend.data.src_bitmap, item);
fill_mask(display_channel, &display_channel->send_data.u.blend.data.mask, item);
@@ -6235,28 +6281,28 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
case QXL_DRAW_BLACKNESS:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_BLACKNESS;
fill_base(display_channel, &display_channel->send_data.u.blackness.base, item,
- sizeof(SpiceMsgDisplayDrawBlackness));
+ sizeof(SpiceMsgDisplayDrawBlackness), 0);
display_channel->send_data.u.blackness.data = drawable->u.blackness;
fill_mask(display_channel, &display_channel->send_data.u.blackness.data.mask, item);
break;
case QXL_DRAW_WHITENESS:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_WHITENESS;
fill_base(display_channel, &display_channel->send_data.u.whiteness.base, item,
- sizeof(SpiceMsgDisplayDrawWhiteness));
+ sizeof(SpiceMsgDisplayDrawWhiteness), 0);
display_channel->send_data.u.whiteness.data = drawable->u.whiteness;
fill_mask(display_channel, &display_channel->send_data.u.whiteness.data.mask, item);
break;
case QXL_DRAW_INVERS:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_INVERS;
fill_base(display_channel, &display_channel->send_data.u.invers.base, item,
- sizeof(SpiceMsgDisplayDrawInvers));
+ sizeof(SpiceMsgDisplayDrawInvers), 0);
display_channel->send_data.u.invers.data = drawable->u.invers;
fill_mask(display_channel, &display_channel->send_data.u.invers.data.mask, item);
break;
case QXL_DRAW_ROP3:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ROP3;
fill_base(display_channel, &display_channel->send_data.u.rop3.base, item,
- sizeof(SpiceMsgDisplayDrawRop3));
+ sizeof(SpiceMsgDisplayDrawRop3), 0);
display_channel->send_data.u.rop3.data = drawable->u.rop3;
fill_bits(display_channel, &display_channel->send_data.u.rop3.data.src_bitmap, item);
fill_brush(display_channel, &display_channel->send_data.u.rop3.data.brush, item);
@@ -6265,7 +6311,7 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
case QXL_DRAW_STROKE:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_STROKE;
fill_base(display_channel, &display_channel->send_data.u.stroke.base, item,
- sizeof(SpiceMsgDisplayDrawStroke));
+ sizeof(SpiceMsgDisplayDrawStroke), 0);
display_channel->send_data.u.stroke.data = drawable->u.stroke;
fill_path(display_channel, &display_channel->send_data.u.stroke.data.path, item->group_id);
fill_attr(display_channel, &display_channel->send_data.u.stroke.data.attr, item->group_id);
@@ -6273,7 +6319,8 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
break;
case QXL_DRAW_TEXT:
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_TEXT;
- fill_base(display_channel, &display_channel->send_data.u.text.base, item, sizeof(SpiceMsgDisplayDrawText));
+ fill_base(display_channel, &display_channel->send_data.u.text.base, item,
+ sizeof(SpiceMsgDisplayDrawText), 0);
display_channel->send_data.u.text.data = drawable->u.text;
fill_brush(display_channel, &display_channel->send_data.u.text.data.fore_brush, item);
fill_brush(display_channel, &display_channel->send_data.u.text.data.back_brush, item);
@@ -6737,29 +6784,6 @@ static inline void send_qxl_drawable(DisplayChannel *display_channel, Drawable *
red_send_qxl_drawable(display_channel->base.worker, display_channel, item);
}
-static void red_send_mode(DisplayChannel *display_channel)
-{
- RedChannel *channel;
- RedWorker *worker;
-
- ASSERT(display_channel);
- worker = display_channel->base.worker;
-
- if (!worker->surface.context.canvas) {
- return;
- }
-
- channel = &display_channel->base;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_MODE;
- display_channel->send_data.u.mode.x_res = worker->surface.context.width;
- display_channel->send_data.u.mode.y_res = worker->surface.context.height;
- display_channel->send_data.u.mode.bits = worker->surface.context.depth;
-
- add_buf(channel, BUF_TYPE_RAW, &display_channel->send_data.u.mode, sizeof(SpiceMsgDisplayMode), 0, 0);
-
- display_begin_send_massage(display_channel, NULL);
-}
-
static void red_send_set_ack(RedChannel *channel)
{
ASSERT(channel);
@@ -6920,6 +6944,7 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_COPY;
add_buf(channel, BUF_TYPE_RAW, &display_channel->send_data.u.copy, sizeof(SpiceMsgDisplayDrawCopy), 0, 0);
+ display_channel->send_data.u.copy.base.surface_id = 0;
display_channel->send_data.u.copy.base.box.left = item->pos.x;
display_channel->send_data.u.copy.base.box.top = item->pos.y;
display_channel->send_data.u.copy.base.box.right = item->pos.x + bitmap.x;
@@ -6970,6 +6995,7 @@ static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeIte
ASSERT(qxl_drawable->u.copy.mask.bitmap == 0);
add_buf(channel, BUF_TYPE_RAW, copy, sizeof(SpiceMsgDisplayDrawCopy), 0, 0);
+ copy->base.surface_id = 0;
copy->base.box = qxl_drawable->bbox;
copy->base.clip.type = SPICE_CLIP_TYPE_RECTS;
copy->base.clip.data = channel->send_data.header.size;
@@ -6990,6 +7016,7 @@ static void red_display_send_stream_start(DisplayChannel *display_channel, Strea
ASSERT(stream);
channel->send_data.header.type = SPICE_MSG_DISPLAY_STREAM_CREATE;
SpiceMsgDisplayStreamCreate *stream_create = &display_channel->send_data.u.stream_create.message;
+ stream_create->surface_id = 0;
stream_create->id = agent - display_channel->stream_agents;
stream_create->flags = stream->top_down ? SPICE_STREAM_FLAGS_TOP_DOWN : 0;
stream_create->codec_type = SPICE_VIDEO_CODEC_TYPE_MJPEG;
@@ -7154,6 +7181,41 @@ static void red_send_cursor(CursorChannel *cursor_channel, CursorItem *cursor)
red_release_cursor(channel->worker, cursor);
}
+static void red_send_surface_create(DisplayChannel *display, SpiceMsgSurfaceCreate *surface_create)
+{
+ RedChannel *channel;
+
+ ASSERT(display);
+ channel = &display->base;
+
+ channel->send_data.header.type = SPICE_MSG_DISPLAY_SURFACE_CREATE;
+ display->send_data.u.surface_create = *surface_create;
+
+ add_buf(channel, BUF_TYPE_RAW, &display->send_data.u.surface_create,
+ sizeof(SpiceMsgSurfaceCreate), 0, 0);
+
+ display->surface_client_created = TRUE;
+
+ red_begin_send_massage(channel, NULL);
+}
+
+static void red_send_surface_destroy(DisplayChannel *display, uint32_t surface_id)
+{
+ RedChannel *channel;
+
+ ASSERT(display);
+ channel = &display->base;
+
+ channel->send_data.header.type = SPICE_MSG_DISPLAY_SURFACE_DESTROY;
+ display->send_data.u.surface_destroy.surface_id = surface_id;
+
+ add_buf(channel, BUF_TYPE_RAW, &display->send_data.u.surface_destroy,
+ sizeof(SpiceMsgSurfaceDestroy), 0, 0);
+
+ display->surface_client_created = FALSE;
+ red_begin_send_massage(channel, NULL);
+}
+
static inline PipeItem *red_pipe_get(RedChannel *channel)
{
PipeItem *item;
@@ -7217,10 +7279,6 @@ static void display_channel_push(RedWorker *worker)
display_send_verb(display_channel, ((VerbItem*)pipe_item)->verb);
free(pipe_item);
break;
- case PIPE_ITEM_TYPE_MODE:
- red_send_mode(display_channel);
- free(pipe_item);
- break;
case PIPE_ITEM_TYPE_MIGRATE:
red_printf("PIPE_ITEM_TYPE_MIGRATE");
display_channel_send_migrate(display_channel);
@@ -7251,6 +7309,20 @@ static void display_channel_push(RedWorker *worker)
red_send_verb((RedChannel *)display_channel, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
free(pipe_item);
break;
+ case PIPE_ITEM_TYPE_CREATE_SURFACE: {
+ SurfaceCreateItem *surface_create = CONTAINEROF(pipe_item, SurfaceCreateItem,
+ pipe_item);
+ red_send_surface_create(display_channel, &surface_create->surface_create);
+ free(surface_create);
+ break;
+ }
+ case PIPE_ITEM_TYPE_DESTROY_SURFACE: {
+ SurfaceDestroyItem *surface_destroy = CONTAINEROF(pipe_item, SurfaceDestroyItem,
+ pipe_item);
+ red_send_surface_destroy(display_channel, surface_destroy->surface_destroy.surface_id);
+ free(surface_destroy);
+ break;
+ }
default:
red_error("invalid pipe item type");
}
@@ -7617,7 +7689,7 @@ static inline void surface_init_draw_funcs(RedWorker *worker, uint32_t renderer)
};
}
-static inline void *create_canvas_for_surface(RedWorker *worker, Surface *surface,
+static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface *surface,
uint32_t renderer, uint32_t width, uint32_t height,
int32_t stride, uint8_t depth, void *line_0)
{
@@ -7641,16 +7713,52 @@ static inline void *create_canvas_for_surface(RedWorker *worker, Surface *surfac
};
}
-static inline void red_create_surface(RedWorker *worker, uint32_t width, uint32_t height,
- int32_t stride, uint8_t depth, void *line_0)
+static SurfaceCreateItem *get_surface_create_item(uint32_t surface_id, uint32_t width,
+ uint32_t height, uint8_t depth, uint32_t flags)
+{
+ SurfaceCreateItem *create;
+
+ create = (SurfaceCreateItem *)malloc(sizeof(SurfaceCreateItem));
+ PANIC_ON(!create);
+
+ create->surface_create.surface_id = surface_id;
+ create->surface_create.width = width;
+ create->surface_create.height = height;
+ create->surface_create.flags = flags;
+
+ red_pipe_item_init(&create->pipe_item, PIPE_ITEM_TYPE_CREATE_SURFACE);
+
+ return create;
+}
+
+static inline void red_create_surface_item(RedWorker *worker, RedSurface *surface)
+{
+ SurfaceCreateItem *create;
+
+ if (!surface->context.canvas) {
+ return;
+ }
+
+ if (!worker->display_channel) {
+ return;
+ }
+
+ create = get_surface_create_item(0, surface->context.width, surface->context.height,
+ surface->context.depth, SPICE_SURFACE_FLAGS_PRIMARY);
+ red_pipe_add(&worker->display_channel->base, &create->pipe_item);
+}
+
+static inline void red_create_surface(RedWorker *worker, uint32_t surface_id,uint32_t width,
+ uint32_t height, int32_t stride, uint8_t depth, void *line_0)
{
uint32_t i;
- Surface *surface = &worker->surface;
+ RedSurface *surface = &worker->surface;
if (stride >= 0) {
PANIC("Untested path stride >= 0");
}
PANIC_ON(surface->context.canvas);
+ ASSERT(surface_id == 0);
surface->context.width = width;
surface->context.height = height;
@@ -7666,6 +7774,7 @@ static inline void red_create_surface(RedWorker *worker, uint32_t width, uint32_
if (!surface->context.canvas) {
PANIC("drawing canvas creating failed - can`t create same type canvas");
}
+ red_create_surface_item(worker, surface);
return;
}
@@ -7676,6 +7785,7 @@ static inline void red_create_surface(RedWorker *worker, uint32_t width, uint32_
if (surface->context.canvas) {
worker->renderer = worker->renderers[i];
surface_init_draw_funcs(worker, worker->renderers[i]);
+ red_create_surface_item(worker, surface);
return;
}
}
@@ -7728,14 +7838,14 @@ static inline void red_flush_surface_pipe(RedWorker *worker)
}
}
-static void push_new_mode(RedWorker *worker)
+static void push_new_primary_surface(RedWorker *worker)
{
DisplayChannel *display_channel;
if ((display_channel = worker->display_channel)) {
red_pipe_add_type(&display_channel->base, PIPE_ITEM_TYPE_INVAL_PALLET_CACHE);
if (!display_channel->base.migrate) {
- red_pipe_add_type(&display_channel->base, PIPE_ITEM_TYPE_MODE);
+ red_create_surface_item(worker, &worker->surface);
}
display_channel_push(worker);
}
@@ -7788,7 +7898,7 @@ static void on_new_display_channel(RedWorker *worker)
display_channel->base.messages_window = 0;
if (worker->surface.context.canvas) {
red_current_flush(worker);
- push_new_mode(worker);
+ push_new_primary_surface(worker);
red_add_screen_image(worker);
if (channel_is_connected(&display_channel->base)) {
red_pipe_add_verb(&display_channel->base, SPICE_MSG_DISPLAY_MARK);
@@ -8730,11 +8840,11 @@ static inline void handle_dev_create_primary_surface(RedWorker *worker)
line_0 -= (int32_t)(surface.stride * (surface.height -1));
}
- red_create_surface(worker, surface.width, surface.height, surface.stride, surface.depth,
+ red_create_surface(worker, 0, surface.width, surface.height, surface.stride, surface.depth,
line_0);
if (worker->display_channel) {
- red_pipe_add_type(&worker->display_channel->base, PIPE_ITEM_TYPE_MODE);
+ red_create_surface_item(worker, &worker->surface);
red_pipe_add_verb(&worker->display_channel->base, SPICE_MSG_DISPLAY_MARK);
display_channel_push(worker);
}
--
1.6.6.1
More information about the Spice-devel
mailing list