/* FIXME: Not as efficient as it could be. */ static void rf_host_hextile_subrects(void) { CARD8 *ptr; CARD8 pos, dim; int i; ptr = cur_slot->readbuf; if (s_subenc & RFB_HEXTILE_SUBRECTS_COLOURED) { fbs_spool_data(ptr, s_num_subrects * 6); for (i = 0; i < (int)s_num_subrects; i++) { memcpy(&s_fg, ptr, sizeof(s_fg)); ptr += sizeof(s_fg); pos = *ptr++; dim = *ptr++; hextile_fill_subrect(pos, dim); } } else { fbs_spool_data(ptr, s_num_subrects * 2); for (i = 0; i < (int)s_num_subrects; i++) { pos = *ptr++; dim = *ptr++; hextile_fill_subrect(pos, dim); } } hextile_next_tile(); }
static void rf_host_hextile_hex(void) { CARD32 *from_ptr = hextile_buf; int data_size; /* Get background and foreground colors */ if (s_subenc & RFB_HEXTILE_BG_SPECIFIED) { s_bg = *from_ptr++; fill_fb_rect(&s_tile, s_bg); } if (s_subenc & RFB_HEXTILE_FG_SPECIFIED) { s_fg = *from_ptr++; } if (s_subenc & RFB_HEXTILE_ANY_SUBRECTS) { fbs_spool_data(hextile_buf, (from_ptr - hextile_buf) * sizeof(CARD32) + 1); s_num_subrects = *((CARD8 *)from_ptr); if (s_subenc & RFB_HEXTILE_SUBRECTS_COLOURED) { data_size = 6 * (unsigned int)s_num_subrects; } else { data_size = 2 * (unsigned int)s_num_subrects; } if (data_size > 0) { aio_setread(rf_host_hextile_subrects, NULL, data_size); return; } } else { fbs_spool_data(hextile_buf, (from_ptr - hextile_buf) * sizeof(CARD32)); } hextile_next_tile(); }
/** * Called when we get a rfbFramebufferUpdate message. */ static void rf_host_fbupdate_hdr(void) { CARD8 hdr_buf[4]; rect_count = buf_get_CARD16(&cur_slot->readbuf[1]); if (rect_count == 0xFFFF) { log_write(LL_DETAIL, "Receiving framebuffer update"); } else { log_write(LL_DETAIL, "Receiving framebuffer update, %d rectangle(s)", rect_count); } hdr_buf[0] = 0; memcpy(&hdr_buf[1], cur_slot->readbuf, 3); fbs_spool_data(hdr_buf, 4); if (rect_count) { aio_setread(rf_host_fbupdate_recthdr, NULL, 12); } else { log_write(LL_DEBUG, "Requesting incremental framebuffer update"); request_update(1); aio_setread(rf_host_msg, NULL, 1); } }
static void rf_host_copyrect(void) { CARD32 *src_ptr; CARD32 *dst_ptr; int width/* = (int)g_fb_width*/; int row; #ifdef CHROMIUM CARD32 *g_framebuffer; CARD16 g_fb_width, g_fb_height; g_framebuffer = GetFrameBuffer(&g_fb_width, &g_fb_height); width = g_fb_width; #endif fbs_spool_data(cur_slot->readbuf, 4); cur_rect.src_x = buf_get_CARD16(cur_slot->readbuf); cur_rect.src_y = buf_get_CARD16(&cur_slot->readbuf[2]); if ( cur_rect.src_x >= g_fb_width || cur_rect.src_x + cur_rect.w > g_fb_width || cur_rect.src_y >= g_fb_height || cur_rect.src_y + cur_rect.h > g_fb_height ) { log_write(LL_ERROR, "CopyRect from outside of the framebuffer: %dx%d from %d,%d", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.src_x, (int)cur_rect.src_y); aio_close(0); return; } if (cur_rect.src_y > cur_rect.y) { /* Copy rows starting from top */ src_ptr = &g_framebuffer[cur_rect.src_y * width + cur_rect.src_x]; dst_ptr = &g_framebuffer[cur_rect.y * width + cur_rect.x]; for (row = 0; row < cur_rect.h; row++) { memmove(dst_ptr, src_ptr, cur_rect.w * sizeof(CARD32)); src_ptr += width; dst_ptr += width; } } else { /* Copy rows starting from bottom */ src_ptr = &g_framebuffer[(cur_rect.src_y + cur_rect.h - 1) * width + cur_rect.src_x]; dst_ptr = &g_framebuffer[(cur_rect.y + cur_rect.h - 1) * width + cur_rect.x]; for (row = 0; row < cur_rect.h; row++) { memmove(dst_ptr, src_ptr, cur_rect.w * sizeof(CARD32)); src_ptr -= width; dst_ptr -= width; } } fbupdate_rect_done(); }
static void rf_host_richcursor_bmps(void) { fbs_spool_data(cur_slot->readbuf, s_read_size); s_curs_rect = s_new_curs_rect; s_bmps = realloc(s_bmps, s_read_size); if (!s_bmps) { log_write(LL_ERROR, "Failed to allocate memory for cursor pixmaps"); aio_close(0); return; } memcpy(s_bmps, s_new_bmps, s_read_size); s_type = RFB_ENCODING_RICHCURSOR; rf_host_cursor(); fbupdate_rect_done(); }
static void rf_host_xcursor_color(void) { CARD32 size; fbs_spool_data(cur_slot->readbuf, sz_rfbXCursorColors); /* calculate size of two cursor bitmaps to follow */ size = ((s_new_curs_rect.w + 7) / 8) * s_new_curs_rect.h * 2; s_new_bmps = realloc(s_new_bmps, size); if (!s_new_bmps) { log_write(LL_ERROR, "Failed to allocate memory for cursor pixmaps"); aio_close(0); return; } s_read_size = size; aio_setread(rf_host_xcursor_bmps, s_new_bmps, size); }
static void rf_host_hextile_raw(void) { int row; CARD32 *from_ptr; CARD32 *fb_ptr; fbs_spool_data(hextile_buf, s_tile.w * s_tile.h * sizeof(CARD32)); from_ptr = hextile_buf; fb_ptr = &g_framebuffer[s_tile.y * (int)g_fb_width + s_tile.x]; /* Just copy raw data into the framebuffer */ for (row = 0; row < s_tile.h; row++) { memcpy(fb_ptr, from_ptr, s_tile.w * sizeof(CARD32)); from_ptr += s_tile.w; fb_ptr += g_fb_width; } hextile_next_tile(); }
static void rf_host_fbupdate_raw(void) { #ifdef CHROMIUM CARD32 *g_framebuffer; CARD16 g_fb_width, g_fb_height; g_framebuffer = GetFrameBuffer(&g_fb_width, &g_fb_height); #endif fbs_spool_data(cur_slot->readbuf, cur_rect.w * sizeof(CARD32)); if (++rect_cur_row < cur_rect.h) { /* Read next row */ CARD32 *dst = PIXEL_ADDR(g_framebuffer, g_fb_width, g_fb_height, cur_rect.x, cur_rect.y + rect_cur_row); aio_setread(rf_host_fbupdate_raw, dst, cur_rect.w * sizeof(CARD32)); } else { /* Done with this rectangle */ fbupdate_rect_done(); } }
static void rf_host_fbupdate_recthdr(void) { HOST_SLOT *hs = (HOST_SLOT *)cur_slot; #ifdef CHROMIUM CARD32 *g_framebuffer; CARD16 g_fb_width, g_fb_height; g_framebuffer = GetFrameBuffer(&g_fb_width, &g_fb_height); #endif cur_rect.x = buf_get_CARD16(cur_slot->readbuf); cur_rect.y = buf_get_CARD16(&cur_slot->readbuf[2]); cur_rect.w = buf_get_CARD16(&cur_slot->readbuf[4]); cur_rect.h = buf_get_CARD16(&cur_slot->readbuf[6]); cur_rect.enc = buf_get_CARD32(&cur_slot->readbuf[8]); fbs_spool_data(cur_slot->readbuf, 12); /* Handle LastRect "encoding" first */ if (cur_rect.enc == RFB_ENCODING_LASTRECT) { log_write(LL_DEBUG, "LastRect marker received from the host"); cur_rect.x = cur_rect.y = 0; rect_count = 1; fbupdate_rect_done(); return; } /* Ignore zero-size rectangles */ if (cur_rect.h == 0 || cur_rect.w == 0) { log_write(LL_WARN, "Zero-size rectangle %dx%d at %d,%d (ignoring)", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.x, (int)cur_rect.y); fbupdate_rect_done(); return; } /* Handle NewFBSize "encoding", as a special case */ if (cur_rect.enc == RFB_ENCODING_NEWFBSIZE) { log_write(LL_INFO, "New host desktop geometry: %dx%d", (int)cur_rect.w, (int)cur_rect.h); g_screen_info.width = hs->fb_width = cur_rect.w; g_screen_info.height = hs->fb_height = cur_rect.h; /* Reallocate the framebuffer if necessary */ if (!alloc_framebuffer(hs->fb_width, hs->fb_height)) { aio_close(1); return; } cur_rect.x = cur_rect.y = 0; /* NewFBSize is always the last rectangle regardless of rect_count */ rect_count = 1; fbupdate_rect_done(); return; } /* Prevent overflow of the framebuffer */ if (cur_rect.x >= g_fb_width || cur_rect.x + cur_rect.w > g_fb_width || cur_rect.y >= g_fb_height || cur_rect.y + cur_rect.h > g_fb_height) { log_write(LL_ERROR, "Rectangle out of framebuffer bounds: %dx%d at %d,%d", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.x, (int)cur_rect.y); aio_close(0); return; } /* Ok, now the rectangle seems correct */ log_write(LL_DEBUG, "Receiving rectangle %dx%d at %d,%d", (int)cur_rect.w, (int)cur_rect.h, (int)cur_rect.x, (int)cur_rect.y); switch(cur_rect.enc) { case RFB_ENCODING_RAW: log_write(LL_DEBUG, "Receiving raw data, expecting %d byte(s)", cur_rect.w * cur_rect.h * sizeof(CARD32)); rect_cur_row = 0; aio_setread(rf_host_fbupdate_raw, PIXEL_ADDR(g_framebuffer, g_fb_width, g_fb_height, cur_rect.x, cur_rect.y), cur_rect.w * sizeof(CARD32)); break; case RFB_ENCODING_COPYRECT: log_write(LL_DEBUG, "Receiving CopyRect instruction"); aio_setread(rf_host_copyrect, NULL, 4); break; case RFB_ENCODING_HEXTILE: log_write(LL_DEBUG, "Receiving Hextile-encoded data"); setread_decode_hextile(&cur_rect); break; case RFB_ENCODING_TIGHT: log_write(LL_DEBUG, "Receiving Tight-encoded data"); setread_decode_tight(&cur_rect); break; default: log_write(LL_ERROR, "Unknown encoding: 0x%08lX", (unsigned long)cur_rect.enc); aio_close(0); } }