5
0
mirror of git://git.proxmox.com/git/spiceterm.git synced 2025-02-07 01:58:16 +03:00

implement scroll

This commit is contained in:
Dietmar Maurer 2013-08-21 14:30:16 +02:00
parent 63a34f43cb
commit 7b4a7650fc
3 changed files with 164 additions and 113 deletions

View File

@ -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");
/*
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;
char *in = vt->screen->frameBuffer+y0*rowstride;
char *out = vt->screen->frameBuffer+y1*rowstride;
memmove(out,in, rowstride*rows);
memset(vt->screen->frameBuffer+y0*rowstride, 0, h*rowstride);
rfbMarkRectAsModified (vt->screen, 0, y0, vt->screen->width, y2);
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;
memmove(vt->cells + dst, vt->cells + src, vt->width*sizeof (TextCell));
}
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++;
if ((top + lines) >= bottom) {
lines = bottom - top -1;
}
}
*/
if (top < 0 || bottom > vt->height || top >= bottom || lines < 1) {
return;
}
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;
memmove(vt->cells + dst, vt->cells + src, vt->width*sizeof (TextCell));
}
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++;
}
}
int h = lines * 16;
int y0 = top*16;
int y1 = y0 + h;
int y2 = bottom*16;
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;
char *in = vt->screen->frameBuffer+y1*rowstride;
char *out = vt->screen->frameBuffer+y0*rowstride;
memmove(out,in, rowstride*rows);
memset(vt->screen->frameBuffer+(y2-h)*rowstride, 0, h*rowstride);
rfbMarkRectAsModified (vt->screen, 0, y0, vt->screen->width, y2);
if (!moveattr) return;
// 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;
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++;
if ((top + lines) >= bottom) {
lines = bottom - top - 1;
}
if (top < 0 || bottom > vt->height || top >= bottom || lines < 1) {
return;
}
int h = lines * 16;
int y0 = top*16;
int y1 = (top + lines)*16;
int y2 = bottom*16;
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
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));
}
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

View File

@ -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)
{

View File

@ -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);