#include <spice/enums.h>
#include <spice/macros.h>
#include <spice/qxl_dev.h>
+#include <spice/vd_agent.h>
#include "glyphs.h"
g_free(update);
}
-#define DEFAULT_WIDTH 640
-#define DEFAULT_HEIGHT 320
-
-static int unique = 1;
+static int unique = 0x0ffff + 1;
static void
set_cmd(QXLCommandExt *ext, uint32_t type, QXLPHYSICAL data)
/* bitmap are freed, so they must be allocated with g_malloc */
static SimpleSpiceUpdate *
-spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *bitmap)
+spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *bitmap, int cache_id)
{
SimpleSpiceUpdate *update;
QXLDrawable *drawable;
drawable->u.copy.src_area.right = bw;
drawable->u.copy.src_area.bottom = bh;
- QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, unique);
+ if (cache_id) {
+ QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, cache_id);
+ } else {
+ QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ++unique);
+ }
image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
image->bitmap.stride = bw * 4;
static SimpleSpiceUpdate *
spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c,
- int fg, int bg)
+ int fg, int bg, gboolean uline)
{
int top, left;
uint8_t *dst;
int bw, bh;
int i, j;
QXLRect bbox;
+ int cache_id = 0;
+
+ if (!uline && c < 256) {
+ cache_id = ((fg << 12) | (bg << 8) | (c & 255)) & 0x0ffff;
+ }
left = x*8;
top = y*16;
- unique++;
-
bw = 8;
bh = 16;
unsigned char bgc_green = default_grn[bg];
for (j = 0; j < 16; j++) {
+ gboolean ul = (j == 14) && uline;
for (i = 0; i < 8; i++) {
- if ((i&7) == 0) {
+ if (i == 0) {
d=*data;
data++;
}
- if (d&0x80) {
+ if (ul || d&0x80) {
*(dst) = fgc_blue;
*(dst+1) = fgc_green;
*(dst+2) = fgc_red;
bbox.left = left; bbox.top = top;
bbox.right = left + bw; bbox.bottom = top + bh;
- return spice_screen_update_from_bitmap_cmd(0, bbox, bitmap);
+ return spice_screen_update_from_bitmap_cmd(0, bbox, bitmap, cache_id);
}
void
qxl_worker->create_primary_surface(qxl_worker, 0, &surface);
}
+void
+spice_screen_resize(SpiceScreen *spice_screen, uint32_t width,
+ uint32_t height)
+{
+ QXLWorker *qxl_worker = spice_screen->qxl_worker;
+
+ if (spice_screen->width == width && spice_screen->height == height) {
+ return;
+ }
+
+ qxl_worker->destroy_primary_surface(qxl_worker, 0);
+
+ create_primary_surface(spice_screen, width, height);
+}
+
+
QXLDevMemSlot slot = {
.slot_group_id = MEM_SLOT_GROUP_ID,
.slot_id = 0,
spice_screen->qxl_worker = _qxl_worker;
spice_screen->qxl_worker->add_memslot(spice_screen->qxl_worker, &slot);
- create_primary_surface(spice_screen, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ create_primary_surface(spice_screen, spice_screen->width, spice_screen->height);
spice_screen->qxl_worker->start(spice_screen->qxl_worker);
}
{
SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance);
- DPRINTF(1, "%s: present %d caps %d", __func__, client_present, caps[0]);
+ DPRINTF(1, "present %d caps %d", client_present, caps[0]);
if (spice_screen->on_client_connected && client_present) {
spice_screen->on_client_connected(spice_screen);
{
client_count++;
- DPRINTF(1, "%s: client_count = %d", __func__, client_count);
+ DPRINTF(1, "client_count = %d", client_count);
}
static void
{
if (client_count > 0) {
client_count--;
- DPRINTF(1, "%s: client_count = %d", __func__, client_count);
+ DPRINTF(1, "client_count = %d", client_count);
exit(0); // fixme: cleanup?
}
}
.set_client_capabilities = set_client_capabilities,
};
-void
-spice_screen_add_display_interface(SpiceScreen* spice_screen)
-{
- spice_server_add_interface(spice_screen->server, &spice_screen->qxl_instance.base);
-}
-
-/* vdagent interface - not sure why we need that? */
-static int
-vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-{
- return len;
-}
-
-static int
-vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-{
- return 0;
-}
-
-static void
-vmc_state(SpiceCharDeviceInstance *sin, int connected)
-{
-
-}
-
-static SpiceCharDeviceInterface vdagent_sif = {
- .base.type = SPICE_INTERFACE_CHAR_DEVICE,
- .base.description = "spice virtual channel char device",
- .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
- .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
- .state = vmc_state,
- .write = vmc_write,
- .read = vmc_read,
-};
-
-SpiceCharDeviceInstance vdagent_sin = {
- .base = {
- .sif = &vdagent_sif.base,
- },
- .subtype = "vdagent",
-};
-
-void
-spice_screen_add_agent_interface(SpiceServer *server)
-{
- spice_server_add_interface(server, &vdagent_sin.base);
-}
void
-spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar ch, TextAttributes attrib)
+spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch,
+ TextAttributes attrib)
{
int fg, bg;
+ int invers;
if (attrib.invers) {
+ invers = attrib.selected ? 0 : 1;
+ } else {
+ invers = attrib.selected ? 1 : 0;
+ }
+
+ if (invers) {
bg = attrib.fgcol;
fg = attrib.bgcol;
} else {
// unsuported attributes = (attrib.blink || attrib.unvisible)
- // fixme:
- //if (attrib.uline) {
- //rfbDrawLine (vt->screen, rx, ry + 14, rxe, ry + 14, fg);
- //}
-
int c = vt_fontmap[ch];
SimpleSpiceUpdate *update;
- update = spice_screen_draw_char_cmd(spice_screen, x, y, c, fg, bg);
+ update = spice_screen_draw_char_cmd(spice_screen, x, y, c, fg, bg, attrib.uline);
push_command(spice_screen, &update->ext);
}
SpiceScreen *
-spice_screen_new(SpiceCoreInterface *core)
+spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, guint timeout)
{
int port = 5912;
SpiceScreen *spice_screen = g_new0(SpiceScreen, 1);
SpiceServer* server = spice_server_new();
+ spice_screen->width = width;
+ spice_screen->height = height;
+
spice_screen->command_cond = g_cond_new();
spice_screen->command_mutex = g_mutex_new();
cursor_init();
- int timeout = 10; // max time to wait for client connection
spice_screen->conn_timeout_timer = core->timer_add(do_conn_timeout, spice_screen);
spice_screen->core->timer_start(spice_screen->conn_timeout_timer, timeout*1000);
+ spice_server_add_interface(spice_screen->server, &spice_screen->qxl_instance.base);
+
return spice_screen;
}