SPICE协议定义了一组消息集支持远程显示区域在客户端显示。协议支持图像渲染(线、图像)和视频流。协议还支持在客户端缓存图片和色彩调和。显示通道支持多种图像压缩方法来减少网络流量。
enum { SPICE_MSG_DISPLAY_MODE = 101, SPICE_MSG_DISPLAY_MARK, SPICE_MSG_DISPLAY_RESET, SPICE_MSG_DISPLAY_COPY_BITS, SPICE_MSG_DISPLAY_INVAL_LIST, SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS, SPICE_MSG_DISPLAY_INVAL_PALETTE, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES, SPICE_MSG_DISPLAY_STREAM_CREATE = 122, SPICE_MSG_DISPLAY_STREAM_DATA, SPICE_MSG_DISPLAY_STREAM_CLIP, SPICE_MSG_DISPLAY_STREAM_DESTROY, SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL, SPICE_MSG_DISPLAY_DRAW_FILL = 302, SPICE_MSG_DISPLAY_DRAW_OPAQUE, SPICE_MSG_DISPLAY_DRAW_COPY, SPICE_MSG_DISPLAY_DRAW_BLEND, SPICE_MSG_DISPLAY_DRAW_BLACKNESS, SPICE_MSG_DISPLAY_DRAW_WHITENESS, SPICE_MSG_DISPLAY_DRAW_INVERS, SPICE_MSG_DISPLAY_DRAW_ROP3, SPICE_MSG_DISPLAY_DRAW_STROKE, SPICE_MSG_DISPLAY_DRAW_TEXT, SPICE_MSG_DISPLAY_DRAW_TRANSPARENT, SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND, SPICE_MSG_DISPLAY_SURFACE_CREATE, SPICE_MSG_DISPLAY_SURFACE_DESTROY, SPICE_MSG_DISPLAY_STREAM_DATA_SIZED, SPICE_MSG_DISPLAY_MONITORS_CONFIG, SPICE_MSG_DISPLAY_DRAW_COMPOSITE, SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT, SPICE_MSG_END_DISPLAY };
enum { SPICE_MSGC_DISPLAY_INIT = 101, SPICE_MSGC_DISPLAY_STREAM_REPORT, SPICE_MSGC_END_DISPLAY };
SPICE服务器使用SPICE_MSG_DISPLAY_MODE消息发送到客户端指定当前画面的面积和格式,作为回应客户端创建一个显示的区域来呈现所有服务器发送来的渲染指令,客户端在收到服务器发送信息SPICE_MSG_DISPLAY_MARK将刷新远程显示区域。服务器可以使用SPICE_MSG_DISPLAY_RESET通知客户端放弃绘图区域和缓存。 SPICE_MSG_DISPLAY_MODE消息只允许在客户端不存在可用绘图区域。SPICE_MSG_DISPLAY_RESET消息只允许客户端存在可以用绘图区域。
SPICE_MSG_DISPLAY_MARK只允许在上述两消息之间发送一次。
绘图命令、复制命令和视频流命令只允许客户端存在绘图区域时发送。
在显示通道建立的时候,客户端为了使用图像缓存及glz压缩会发送SPICE_MSGC_DISPLAY_INIT消息到服务器。消息包括图像缓存ID及大小和glz压缩窗口的大小。这些尺寸和ID有客户端决定。只允许发送一次。这个大小是主通道建立的时候spice_session_set_caches_hints函数设置的。
绘图缓存是服务器管理的。缓存条目的插入是另外一组命令实现的。缓存条目的删除是通过SPICE_MSG_DISPLAY_INVAL_LIST和SPICE_MSG_DISPLAY_INVAL_PALETTE。重新设置缓存是通过发送SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS和SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES。
1、SpiceMsgDisplayMode
typedef structSpiceMsgDisplayMode { uint32_t x_res; uint32_t y_res; uint32_t bits; } SpiceMsgDisplayMode;
下面顶一个一组标记来描述光栅操作。可以应用在源图像、源刷,目的和结果。结合这些标记定义了必要的步骤。需要预制渲染操作。
typedef enumSpiceRopd { SPICE_ROPD_INVERS_SRC = (1 << 0),//源图像在渲染前需要翻转 SPICE_ROPD_INVERS_BRUSH = (1 << 1),//画笔在渲染前需要翻转 SPICE_ROPD_INVERS_DEST = (1 << 2),//目标区域在渲染前需要翻转 SPICE_ROPD_OP_PUT = (1 << 3),//应该使用复制操作 SPICE_ROPD_OP_OR = (1 << 4),//应该使用或操作 SPICE_ROPD_OP_AND = (1 << 5),//应该使用与操作 SPICE_ROPD_OP_XOR = (1 << 6),//应该使用异或操作 SPICE_ROPD_OP_BLACKNESS = (1 << 7),//目标像素应该为黑色取代 SPICE_ROPD_OP_WHITENESS = (1 << 8),//目标像素应该为白色取代 SPICE_ROPD_OP_INVERS = (1 << 9),//目标像素应该翻转 SPICE_ROPD_INVERS_RES = (1 << 10),//操作的结果需要被翻转 SPICE_ROPD_MASK = 0x7ff } SpiceRopd;
OP_PUT, OP_OR,OP_AND, OP_XOR, OP_BLACKNESS, OP_WHITENESS, and
OP_INVERS 是相互排斥的。
OP_BLACKNESS,OP_WHITENESS, and OP_INVERS 是独有的。
下面的部分介绍SPICE象图,象图是SPICE协议传输图像的方法之一。
typedef enumSpiceBitmapFlags { SPICE_BITMAP_FLAGS_PAL_CACHE_ME = (1 << 0), //指示客户端将此画板加到缓存 SPICE_BITMAP_FLAGS_PAL_FROM_CACHE = (1 << 1), //指示客户端从缓存中检索画板 SPICE_BITMAP_FLAGS_TOP_DOWN = (1 << 2), //象图行命令是从上到下 SPICE_BITMAP_FLAGS_MASK = 0x7 }SpiceBitmapFlags;
typedef enumSpiceBitmapFmt { SPICE_BITMAP_FMT_INVALID, SPICE_BITMAP_FMT_1BIT_LE, //每像素1bit,小端字节序存储。每个像素的值是颜色表的索引。颜色表的大小是2. SPICE_BITMAP_FMT_1BIT_BE, //每像素1bit,大端字节序存储。每个像素的值是颜色表的索引。颜色表的大小是2. SPICE_BITMAP_FMT_4BIT_LE, //每像素4bit,小端半字节存储。每个像素的值是颜色表的索引。颜色表的大小是16 SPICE_BITMAP_FMT_4BIT_BE, //每像素4bit,大端半字节存储。每个像素的值是颜色表的索引。颜色表的大小是16 SPICE_BITMAP_FMT_8BIT, //每像素8bit.每个像素的值是颜色表的索引。颜色表的大小是256 SPICE_BITMAP_FMT_16BIT, //像素格式是 16 位 RGB555 SPICE_BITMAP_FMT_24BIT, //像素格式是 24位 RGB888 SPICE_BITMAP_FMT_32BIT, //像素格式是 32 位 RGB888 SPICE_BITMAP_FMT_RGBA, //像素格式是 32 位ARGB8888 SPICE_BITMAP_FMT_8BIT_A, //不太清楚 SPICE_BITMAP_FMT_ENUM_END }SpiceBitmapFmt;
typedef structSpiceBitmap { uint8_t format; // SpiceBitmapFmt格式 uint8_t flags; // SpiceBitmapFlags 宏 uint32_t x; //位图的宽度 uint32_t y; //位图的高度 uint32_t stride;//从N行到N+1行添加字节的数量。(例如stride*y+x*format) SpicePalette *palette;//调色板的地址,如果没有颜色表所需要的格式必须为0; uint64_t palette_id;//调色板的ID,如果flags设置SPICE_BITMAP_FLAGS_PAL_FROM_CACHE有效 SpiceChunks *data;//数据 } SpiceBitmap;
typedef structSpicePalette { uint64_t unique;//palette的唯一ID uint16_t num_ents;//颜色表中条目的数量 uint32_t ents[0];// 每个条目RGB555或RGB888颜色根据当前显示区域模式。如果显示区域模式颜色深度是32岁的有效格式是RGB888。如果显示区域模式颜色深度是有效的格式是RGB555 16。 } SpicePalette;