brush cache for > 2 color brushes

git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1482 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Jay Sorg 2008-11-01 02:37:10 +00:00
parent b64678c9ee
commit c3dc159869
6 changed files with 235 additions and 75 deletions

29
cache.c
View File

@ -432,30 +432,41 @@ cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor)
}
/* BRUSH CACHE */
static BRUSHDATA g_brushcache[64];
/* index 0 is 2 colour brush, index 1 is muti colour brush */
static BRUSHDATA g_brushcache[2][64];
/* Retrieve brush from cache */
BRUSHDATA *
cache_get_brush_data(uint16 cache_idx)
cache_get_brush_data(uint8 colour_code, uint8 idx)
{
if (cache_idx < NUM_ELEMENTS(g_brushcache))
colour_code = colour_code == 1 ? 0 : 1;
if (idx < NUM_ELEMENTS(g_brushcache[0]))
{
return &g_brushcache[cache_idx];
return &g_brushcache[colour_code][idx];
}
error("get brush %d\n", cache_idx);
error("get brush %d %d\n", colour_code, idx);
return NULL;
}
/* Store brush in cache */
/* this function takes over the data pointer in struct, eg, caller gives it up */
void
cache_put_brush_data(uint16 cache_idx, BRUSHDATA * brush_data)
cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data)
{
if (cache_idx < NUM_ELEMENTS(g_brushcache))
BRUSHDATA * bd;
colour_code = colour_code == 1 ? 0 : 1;
if (idx < NUM_ELEMENTS(g_brushcache[0]))
{
memcpy(&g_brushcache[cache_idx], brush_data, sizeof(BRUSHDATA));
bd = &g_brushcache[colour_code][idx];
if (bd->data != 0)
{
xfree(bd->data);
}
memcpy(bd, brush_data, sizeof(BRUSHDATA));
}
else
{
error("put brush %d\n", cache_idx);
error("put brush %d %d\n", colour_code, idx);
}
}

110
orders.c
View File

@ -152,30 +152,24 @@ static void
setup_brush(BRUSH * out_brush, BRUSH * in_brush)
{
BRUSHDATA *brush_data;
uint16 cache_idx;
uint8 brush_bpp;
uint8 cache_idx;
uint8 colour_code;
memcpy(out_brush, in_brush, sizeof(BRUSH));
if (out_brush->style & 0x80)
{
brush_bpp = out_brush->style & 0x0f;
if (brush_bpp == 1) /* 1 bpp */
{
colour_code = out_brush->style & 0x0f;
cache_idx = out_brush->pattern[0];
brush_data = cache_get_brush_data(cache_idx);
if (brush_data == NULL)
brush_data = cache_get_brush_data(colour_code, cache_idx);
if ((brush_data == NULL) || (brush_data->data == NULL))
{
error("error getting brush data, style %x\n", out_brush->style);
out_brush->bd = NULL;
memset(out_brush->pattern, 0, 8);
}
else
{
memcpy(out_brush->pattern, brush_data->pattern,
sizeof(out_brush->pattern));
}
}
else
{
error("bad brush bpp %d\n", brush_bpp);
out_brush->bd = brush_data;
}
out_brush->style = 3;
}
@ -1154,31 +1148,105 @@ process_fontcache(STREAM s)
}
}
static void
process_compressed_8x8_brush_data(uint8 * in, uint8 * out, int Bpp)
{
int x, y, pal_index, in_index, shift, do2, i;
uint8 * pal;
in_index = 0;
pal = in + 16;
/* read it bottom up */
for (y = 7; y >= 0; y--)
{
/* 2 bytes per row */
x = 0;
for (do2 = 0; do2 < 2; do2++)
{
/* 4 pixels per byte */
shift = 6;
while (shift >= 0)
{
pal_index = (in[in_index] >> shift) & 3;
/* size of palette entries depends on Bpp */
for (i = 0; i < Bpp; i++)
{
out[(y * 8 + x) * Bpp + i] = pal[pal_index * Bpp + i];
}
x++;
shift -= 2;
}
in_index++;
}
}
}
/* Process a brush cache order */
static void
process_brushcache(STREAM s, uint16 flags)
{
BRUSHDATA brush_data;
uint8 cache_idx, depth, width, height, size;
uint8 cache_idx, colour_code, width, height, size, type;
uint8 * comp_brush;
int index;
int Bpp;
in_uint8(s, cache_idx);
in_uint8(s, depth);
in_uint8(s, colour_code);
in_uint8(s, width);
in_uint8(s, height);
in_uint8s(s, 1); /* type, 0x80 = cached */
in_uint8(s, type); /* type, 0x8x = cached */
in_uint8(s, size);
DEBUG(("BRUSHCACHE(idx=%d,dp=%d,wd=%d,ht=%d,sz=%d)\n", cache_idx, depth,
width, height, size));
if ((depth == 1) && (width == 8) && (height == 8) && (size == 8))
if ((width == 8) && (height == 8))
{
in_uint8a(s, brush_data.pattern, sizeof(brush_data.pattern));
cache_put_brush_data(cache_idx, &brush_data);
if (colour_code == 1)
{
brush_data.colour_code = 1;
brush_data.data_size = 8;
brush_data.data = xmalloc(8);
if (size == 8)
{
/* read it bottom up */
for (index = 7; index >= 0; index--)
{
in_uint8(s, brush_data.data[index]);
}
}
else
{
warning("ignoring incompatible brush type. display may be incorrect\n");
warning("incompatible brush, colour_code %d size %d\n", colour_code, size);
}
cache_put_brush_data(1, cache_idx, &brush_data);
}
else if ((colour_code >= 3) && (colour_code <= 6))
{
Bpp = colour_code - 2;
brush_data.colour_code = colour_code;
brush_data.data_size = 8 * 8 * Bpp;
brush_data.data = xmalloc(8 * 8 * Bpp);
if (size == 16 + 4 * Bpp)
{
in_uint8p(s, comp_brush, 16 + 4 * Bpp);
process_compressed_8x8_brush_data(comp_brush, brush_data.data, Bpp);
}
else
{
in_uint8a(s, brush_data.data, 8 * 8 * Bpp);
}
cache_put_brush_data(colour_code, cache_idx, &brush_data);
}
else
{
warning("incompatible brush, colour_code %d size %d\n", colour_code, size);
}
}
else
{
warning("incompatible brush, width height %d %d\n", width, height);
}
}

View File

@ -44,8 +44,8 @@ void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_pe
uint8 * data);
RD_HCURSOR cache_get_cursor(uint16 cache_idx);
void cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor);
BRUSHDATA *cache_get_brush_data(uint16 cache_idx);
void cache_put_brush_data(uint16 cache_idx, BRUSHDATA * brush_data);
BRUSHDATA *cache_get_brush_data(uint8 colour_code, uint8 idx);
void cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data);
/* channels.c */
VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM));
STREAM channel_init(VCHANNEL * channel, uint32 length);

4
rdp.c
View File

@ -858,6 +858,7 @@ rdp_send_confirm_active(void)
RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
RDP_CAPLEN_BRUSHCACHE +
0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
4 /* w2k fix, why? */ ;
@ -885,10 +886,7 @@ rdp_send_confirm_active(void)
rdp_out_control_caps(s);
rdp_out_pointer_caps(s);
rdp_out_share_caps(s);
#if 0
/* Temporarily disabled due to bug 2167833. When re-enabling, add RDP_CAPLEN_BRUSHCACHE to caplen. */
rdp_out_brushcache_caps(s);
#endif
rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);

View File

@ -82,7 +82,9 @@ PEN;
/* this is whats in the brush cache */
typedef struct _BRUSHDATA
{
uint8 pattern[8];
uint32 colour_code;
uint32 data_size;
uint8 * data;
}
BRUSHDATA;
@ -92,7 +94,7 @@ typedef struct _BRUSH
uint8 yorigin;
uint8 style;
uint8 pattern[8];
BRUSHDATA * bd;
}
BRUSH;

81
xwin.c
View File

@ -3070,6 +3070,8 @@ ui_patblt(uint8 opcode,
break;
case 3: /* Pattern */
if (brush->bd == 0) /* rdp4 brush */
{
for (i = 0; i != 8; i++)
ipattern[7 - i] = brush->pattern[i];
fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
@ -3082,6 +3084,31 @@ ui_patblt(uint8 opcode,
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((RD_HGLYPH) fill);
}
else if (brush->bd->colour_code > 1) /* > 1 bpp */
{
fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
XSetFillStyle(g_display, g_gc, FillTiled);
XSetTile(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_bitmap((RD_HBITMAP) fill);
}
else
{
fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
SET_FOREGROUND(bgcolour);
SET_BACKGROUND(fgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((RD_HGLYPH) fill);
}
break;
default:
@ -3244,6 +3271,8 @@ ui_polygon(uint8 opcode,
break;
case 3: /* Pattern */
if (brush->bd == 0) /* rdp4 brush */
{
for (i = 0; i != 8; i++)
ipattern[7 - i] = brush->pattern[i];
fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
@ -3256,6 +3285,31 @@ ui_polygon(uint8 opcode,
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((RD_HGLYPH) fill);
}
else if (brush->bd->colour_code > 1) /* > 1 bpp */
{
fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
XSetFillStyle(g_display, g_gc, FillTiled);
XSetTile(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
FILL_POLYGON((XPoint *) point, npoints);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_bitmap((RD_HBITMAP) fill);
}
else
{
fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
SET_FOREGROUND(bgcolour);
SET_BACKGROUND(fgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
FILL_POLYGON((XPoint *) point, npoints);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((RD_HGLYPH) fill);
}
break;
default:
@ -3322,6 +3376,8 @@ ui_ellipse(uint8 opcode,
break;
case 3: /* Pattern */
if (brush->bd == 0) /* rdp4 brush */
{
for (i = 0; i != 8; i++)
ipattern[7 - i] = brush->pattern[i];
fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
@ -3334,6 +3390,31 @@ ui_ellipse(uint8 opcode,
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((RD_HGLYPH) fill);
}
else if (brush->bd->colour_code > 1) /* > 1 bpp */
{
fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
XSetFillStyle(g_display, g_gc, FillTiled);
XSetTile(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
DRAW_ELLIPSE(x, y, cx, cy, fillmode);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_bitmap((RD_HBITMAP) fill);
}
else
{
fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
SET_FOREGROUND(bgcolour);
SET_BACKGROUND(fgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
DRAW_ELLIPSE(x, y, cx, cy, fillmode);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((RD_HGLYPH) fill);
}
break;
default: