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:
parent
63a34f43cb
commit
7b4a7650fc
160
spiceterm.c
160
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");
|
||||
|
||||
/*
|
||||
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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user