From: Dietmar Maurer Date: Wed, 21 Aug 2013 12:30:16 +0000 (+0200) Subject: implement scroll X-Git-Url: https://git.proxmox.com/?p=spiceterm.git;a=commitdiff_plain;h=7b4a7650fc022b6e5b6b3ee8cf955e43f486d05a implement scroll --- diff --git a/spiceterm.c b/spiceterm.c index f45bccd..0104cc7 100644 --- a/spiceterm.c +++ b/spiceterm.c @@ -205,102 +205,84 @@ vncterm_refresh (vncTerm *vt) static void vncterm_scroll_down (vncTerm *vt, int top, int bottom, int lines) { - if ((top + lines) >= bottom) { - lines = bottom - top -1; - } - - if (top < 0 || bottom > vt->height || top >= bottom || lines < 1) { - return; - } - - g_error("vncterm_scroll_down not implemented"); + if ((top + lines) >= bottom) { + lines = bottom - top -1; + } - /* - int h = lines * 16; - int y0 = top*16; - int y1 = y0 + h; - int y2 = bottom*16; - int rowstride = vt->screen->paddedWidthInBytes; - int rows = (bottom - top - lines)*16; + if (top < 0 || bottom > vt->height || top >= bottom || lines < 1) { + return; + } - char *in = vt->screen->frameBuffer+y0*rowstride; - char *out = vt->screen->frameBuffer+y1*rowstride; - memmove(out,in, rowstride*rows); + int i; + for(i = bottom - top - lines - 1; i >= 0; i--) { + int src = ((vt->y_base + top + i) % vt->total_height)*vt->width; + int dst = ((vt->y_base + top + lines + i) % vt->total_height)*vt->width; - memset(vt->screen->frameBuffer+y0*rowstride, 0, h*rowstride); - rfbMarkRectAsModified (vt->screen, 0, y0, vt->screen->width, y2); + memmove(vt->cells + dst, vt->cells + src, vt->width*sizeof (TextCell)); + } - int i; - for(i = bottom - top - lines - 1; i >= 0; i--) { - int src = ((vt->y_base + top + i) % vt->total_height)*vt->width; - int dst = ((vt->y_base + top + lines + i) % vt->total_height)*vt->width; + for (i = 0; i < lines; i++) { + int j; + TextCell *c = vt->cells + ((vt->y_base + top + i) % vt->total_height)*vt->width; + for(j = 0; j < vt->width; j++) { + c->attrib = vt->default_attrib; + c->ch = ' '; + c++; + } + } - memmove(vt->cells + dst, vt->cells + src, vt->width*sizeof (TextCell)); - } + int h = lines * 16; + int y0 = top*16; + int y1 = y0 + h; + int y2 = bottom*16; - for (i = 0; i < lines; i++) { - int j; - TextCell *c = vt->cells + ((vt->y_base + top + i) % vt->total_height)*vt->width; - for(j = 0; j < vt->width; j++) { - c->attrib = vt->default_attrib; - c->ch = ' '; - c++; - } - } - */ + test_spice_scroll(vt->screen, 0, y1, vt->screen->primary_width, y2, 0, y0); + test_spice_clear(vt->screen, 0, y0, vt->screen->primary_width, y1); } static void vncterm_scroll_up (vncTerm *vt, int top, int bottom, int lines, int moveattr) { - if ((top + lines) >= bottom) { - lines = bottom - top - 1; - } - - if (top < 0 || bottom > vt->height || top >= bottom || lines < 1) { - return; - } - - g_error("vncterm_scroll_down not implemented"); - - /* - int h = lines * 16; - int y0 = top*16; - int y1 = (top + lines)*16; - int y2 = bottom*16; - int rowstride = vt->screen->paddedWidthInBytes; - int rows = (bottom - top - lines)*16; + if ((top + lines) >= bottom) { + lines = bottom - top - 1; + } - char *in = vt->screen->frameBuffer+y1*rowstride; - char *out = vt->screen->frameBuffer+y0*rowstride; - memmove(out,in, rowstride*rows); + if (top < 0 || bottom > vt->height || top >= bottom || lines < 1) { + return; + } - memset(vt->screen->frameBuffer+(y2-h)*rowstride, 0, h*rowstride); - rfbMarkRectAsModified (vt->screen, 0, y0, vt->screen->width, y2); + int h = lines * 16; + int y0 = top*16; + int y1 = (top + lines)*16; + int y2 = bottom*16; - if (!moveattr) return; + test_spice_scroll(vt->screen, 0, y0, vt->screen->primary_width, y2 -h, 0, y1); + test_spice_clear(vt->screen, 0, y2 -h, vt->screen->primary_width, y2); + + if (!moveattr) { + return; + } - // move attributes + // move attributes - int i; - for(i = 0; i < (bottom - top - lines); i++) { - int dst = ((vt->y_base + top + i) % vt->total_height)*vt->width; - int src = ((vt->y_base + top + lines + i) % vt->total_height)*vt->width; + int i; + for(i = 0; i < (bottom - top - lines); i++) { + int dst = ((vt->y_base + top + i) % vt->total_height)*vt->width; + int src = ((vt->y_base + top + lines + i) % vt->total_height)*vt->width; - memmove(vt->cells + dst, vt->cells + src, vt->width*sizeof (TextCell)); - } + memmove(vt->cells + dst, vt->cells + src, vt->width*sizeof (TextCell)); + } - for (i = 1; i <= lines; i++) { - int j; - TextCell *c = vt->cells + ((vt->y_base + bottom - i) % vt->total_height)*vt->width; - for(j = 0; j < vt->width; j++) { - c->attrib = vt->default_attrib; - c->ch = ' '; - c++; + for (i = 1; i <= lines; i++) { + int j; + TextCell *c = vt->cells + ((vt->y_base + bottom - i) % vt->total_height)*vt->width; + for(j = 0; j < vt->width; j++) { + c->attrib = vt->default_attrib; + c->ch = ' '; + c++; + } } - } - */ } static void diff --git a/test_display_base.c b/test_display_base.c index 128149a..e6c91fe 100644 --- a/test_display_base.c +++ b/test_display_base.c @@ -85,6 +85,29 @@ static void simple_set_release_info(QXLReleaseInfo *info, intptr_t ptr) //info->group_id = MEM_SLOT_GROUP_ID; } +// We shall now have a ring of commands, so that we can update +// it from a separate thread - since get_command is called from +// the worker thread, and we need to sometimes do an update_area, +// which cannot be done from red_worker context (not via dispatcher, +// since you get a deadlock, and it isn't designed to be done +// any other way, so no point testing that). + + +static void push_command(Test *test, QXLCommandExt *ext) +{ + g_mutex_lock(test->command_mutex); + + while (test->commands_end - test->commands_start >= COMMANDS_SIZE) { + g_cond_wait(test->command_cond, test->command_mutex); + } + g_assert(test->commands_end - test->commands_start < COMMANDS_SIZE); + test->commands[test->commands_end % COMMANDS_SIZE] = ext; + test->commands_end++; + g_mutex_unlock(test->command_mutex); + + test->qxl_worker->wakeup(test->qxl_worker); +} + /* bitmap are freed, so they must be allocated with g_malloc */ SimpleSpiceUpdate *test_spice_create_update_from_bitmap(uint32_t surface_id, QXLRect bbox, @@ -196,6 +219,73 @@ static SimpleSpiceUpdate *test_draw_char(Test *test, int x, int y, int c, int fg return test_spice_create_update_from_bitmap(0, bbox, bitmap); } +void test_spice_scroll(Test *test, int x1, int y1, int x2, int y2, int src_x, int src_y) +{ + SimpleSpiceUpdate *update; + QXLDrawable *drawable; + QXLRect bbox; + + int surface_id = 0; // fixme + + update = g_new0(SimpleSpiceUpdate, 1); + drawable = &update->drawable; + + bbox.left = x1; + bbox.top = y1; + bbox.right = x2; + bbox.bottom = y2; + + drawable->surface_id = surface_id; + + drawable->bbox = bbox; + drawable->clip.type = SPICE_CLIP_TYPE_NONE; + drawable->effect = QXL_EFFECT_OPAQUE; + simple_set_release_info(&drawable->release_info, (intptr_t)update); + drawable->type = QXL_COPY_BITS; + drawable->surfaces_dest[0] = -1; + drawable->surfaces_dest[1] = -1; + drawable->surfaces_dest[2] = -1; + + drawable->u.copy_bits.src_pos.x = src_x; + drawable->u.copy_bits.src_pos.y = src_y; + + set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable); + + push_command(test, &update->ext); +} + +void test_spice_clear(Test *test, int x1, int y1, int x2, int y2) +{ + SimpleSpiceUpdate *update; + QXLDrawable *drawable; + QXLRect bbox; + + int surface_id = 0; // fixme + + update = g_new0(SimpleSpiceUpdate, 1); + drawable = &update->drawable; + + bbox.left = x1; + bbox.top = y1; + bbox.right = x2; + bbox.bottom = y2; + + drawable->surface_id = surface_id; + + drawable->bbox = bbox; + drawable->clip.type = SPICE_CLIP_TYPE_NONE; + drawable->effect = QXL_EFFECT_OPAQUE; + simple_set_release_info(&drawable->release_info, (intptr_t)update); + drawable->type = QXL_DRAW_BLACKNESS; + drawable->surfaces_dest[0] = -1; + drawable->surfaces_dest[1] = -1; + drawable->surfaces_dest[2] = -1; + + set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable); + + push_command(test, &update->ext); +} + static void create_primary_surface(Test *test, uint32_t width, uint32_t height) { @@ -271,30 +361,6 @@ static void get_init_info(QXLInstance *qin, QXLDevInitInfo *info) info->n_surfaces = 1; } - -// We shall now have a ring of commands, so that we can update -// it from a separate thread - since get_command is called from -// the worker thread, and we need to sometimes do an update_area, -// which cannot be done from red_worker context (not via dispatcher, -// since you get a deadlock, and it isn't designed to be done -// any other way, so no point testing that). - - -static void push_command(Test *test, QXLCommandExt *ext) -{ - g_mutex_lock(test->command_mutex); - - while (test->commands_end - test->commands_start >= COMMANDS_SIZE) { - g_cond_wait(test->command_cond, test->command_mutex); - } - g_assert(test->commands_end - test->commands_start < COMMANDS_SIZE); - test->commands[test->commands_end % COMMANDS_SIZE] = ext; - test->commands_end++; - g_mutex_unlock(test->command_mutex); - - test->qxl_worker->wakeup(test->qxl_worker); -} - // called from spice_server thread (i.e. red_worker thread) static int get_command(QXLInstance *qin, struct QXLCommandExt *ext) { diff --git a/test_display_base.h b/test_display_base.h index 6b3c4ca..a4f8ab1 100644 --- a/test_display_base.h +++ b/test_display_base.h @@ -139,6 +139,9 @@ void test_add_keyboard_interface(Test *test); Test* test_new(SpiceCoreInterface* core); void test_draw_update_char(Test *test, int x, int y, int c, TextAttributes attrib); +void test_spice_scroll(Test *test, int x1, int y1, int x2, int y2, int src_x, int src_y); +void test_spice_clear(Test *test, int x1, int y1, int x2, int y2); + uint32_t test_get_width(void); uint32_t test_get_height(void);