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_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 hextile_next_tile(void) { if (s_tile.x + 16 < s_rect.x + s_rect.w) { /* Next tile in the same row */ s_tile.x += 16; if (s_tile.x + 16 < s_rect.x + s_rect.w) s_tile.w = 16; else s_tile.w = s_rect.x + s_rect.w - s_tile.x; } else if (s_tile.y + 16 < s_rect.y + s_rect.h) { /* First tile in the next row */ s_tile.x = s_rect.x; s_tile.w = (s_rect.w < 16) ? s_rect.w : 16; s_tile.y += 16; if (s_tile.y + 16 < s_rect.y + s_rect.h) s_tile.h = 16; else s_tile.h = s_rect.y + s_rect.h - s_tile.y; } else { fbupdate_rect_done(); /* No more tiles */ return; } aio_setread(rf_host_hextile_subenc, NULL, 1); }
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); } }