Bladeren bron

Finish the dirty rectangle architecture. They are now reliable in the sense

that anything outside the dirty rectangle is guaranteed to be unchanged, but
we currently mark far too many cells as dirty. This must be optimised.
tags/v0.99.beta17
Sam Hocevar sam 16 jaren geleden
bovenliggende
commit
3a6f4323ec
7 gewijzigde bestanden met toevoegingen van 104 en 27 verwijderingen
  1. +11
    -0
      caca/attr.c
  2. +3
    -3
      caca/caca_internals.h
  3. +32
    -20
      caca/canvas.c
  4. +7
    -0
      caca/frame.c
  5. +3
    -0
      caca/graphics.c
  6. +32
    -4
      caca/string.c
  7. +16
    -0
      caca/transform.c

+ 11
- 0
caca/attr.c Bestand weergeven

@@ -130,10 +130,13 @@ int caca_set_attr(caca_canvas_t *cv, uint32_t attr)
int caca_put_attr(caca_canvas_t *cv, int x, int y, uint32_t attr) int caca_put_attr(caca_canvas_t *cv, int x, int y, uint32_t attr)
{ {
uint32_t *curattr, *curchar; uint32_t *curattr, *curchar;
int xmin, xmax;


if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height) if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
return 0; return 0;


xmin = xmax = x;

curchar = cv->chars + x + y * cv->width; curchar = cv->chars + x + y * cv->width;
curattr = cv->attrs + x + y * cv->width; curattr = cv->attrs + x + y * cv->width;


@@ -143,9 +146,17 @@ int caca_put_attr(caca_canvas_t *cv, int x, int y, uint32_t attr)
curattr[0] = attr; curattr[0] = attr;


if(x && curchar[0] == CACA_MAGIC_FULLWIDTH) if(x && curchar[0] == CACA_MAGIC_FULLWIDTH)
{
curattr[-1] = curattr[0]; curattr[-1] = curattr[0];
xmin--;
}
else if(x + 1 < (int)cv->width && curchar[1] == CACA_MAGIC_FULLWIDTH) else if(x + 1 < (int)cv->width && curchar[1] == CACA_MAGIC_FULLWIDTH)
{
curattr[1] = curattr[0]; curattr[1] = curattr[0];
xmax++;
}

caca_add_dirty_rectangle(cv, xmin, xmax, y, y);


return 0; return 0;
} }


+ 3
- 3
caca/caca_internals.h Bestand weergeven

@@ -39,9 +39,6 @@ struct caca_frame
int handlex, handley; int handlex, handley;
uint32_t curattr; uint32_t curattr;


/* Dirty rectangle */
int dirty_xmin, dirty_xmax, dirty_ymin, dirty_ymax;

/* Frame name */ /* Frame name */
char *name; char *name;
}; };
@@ -61,6 +58,9 @@ struct caca_canvas
int (*resize_callback)(void *); int (*resize_callback)(void *);
void *resize_data; void *resize_data;


/* Dirty rectangle */
int dirty_xmin, dirty_xmax, dirty_ymin, dirty_ymax;

/* Shortcut to the active frame information */ /* Shortcut to the active frame information */
int width, height; int width, height;
uint32_t *chars; uint32_t *chars;


+ 32
- 20
caca/canvas.c Bestand weergeven

@@ -89,14 +89,15 @@ caca_canvas_t * caca_create_canvas(int width, int height)
cv->frames[0].handlex = cv->frames[0].handley = 0; cv->frames[0].handlex = cv->frames[0].handley = 0;
cv->frames[0].curattr = 0; cv->frames[0].curattr = 0;
cv->frames[0].name = strdup("frame#00000000"); cv->frames[0].name = strdup("frame#00000000");
cv->frames[0].dirty_xmin = 0;
cv->frames[0].dirty_xmax = -1;
cv->frames[0].dirty_ymin = 0;
cv->frames[0].dirty_ymax = -1;


_caca_load_frame_info(cv); _caca_load_frame_info(cv);
caca_set_color_ansi(cv, CACA_DEFAULT, CACA_TRANSPARENT); caca_set_color_ansi(cv, CACA_DEFAULT, CACA_TRANSPARENT);


cv->dirty_xmin = 0;
cv->dirty_xmax = -1;
cv->dirty_ymin = 0;
cv->dirty_ymax = -1;

cv->ff = NULL; cv->ff = NULL;


if(caca_resize(cv, width, height) < 0) if(caca_resize(cv, width, height) < 0)
@@ -331,10 +332,10 @@ uint8_t const * caca_get_canvas_attrs(caca_canvas_t const *cv)
int caca_get_dirty_rectangle(caca_canvas_t *cv, int *xmin, int *xmax, int caca_get_dirty_rectangle(caca_canvas_t *cv, int *xmin, int *xmax,
int *ymin, int *ymax) int *ymin, int *ymax)
{ {
*xmin = cv->frames[cv->frame].dirty_xmin;
*xmax = cv->frames[cv->frame].dirty_xmax;
*ymin = cv->frames[cv->frame].dirty_ymin;
*ymax = cv->frames[cv->frame].dirty_ymax;
*xmin = cv->dirty_xmin;
*xmax = cv->dirty_xmax;
*ymin = cv->dirty_ymin;
*ymax = cv->dirty_ymax;


return 0; return 0;
} }
@@ -371,17 +372,17 @@ int caca_add_dirty_rectangle(caca_canvas_t *cv, int xmin, int xmax,
if(xmax < 0 || xmin >= cv->width || ymax < 0 || ymin >= cv->height) if(xmax < 0 || xmin >= cv->width || ymax < 0 || ymin >= cv->height)
return 0; return 0;


if(xmin < cv->frames[cv->frame].dirty_xmin)
cv->frames[cv->frame].dirty_xmin = xmin;
if(xmin < cv->dirty_xmin)
cv->dirty_xmin = xmin;


if(xmax > cv->frames[cv->frame].dirty_xmax)
cv->frames[cv->frame].dirty_xmax = xmax;
if(xmax > cv->dirty_xmax)
cv->dirty_xmax = xmax;


if(ymin < cv->frames[cv->frame].dirty_ymin)
cv->frames[cv->frame].dirty_ymin = ymin;
if(ymin < cv->dirty_ymin)
cv->dirty_ymin = ymin;


if(ymax > cv->frames[cv->frame].dirty_ymax)
cv->frames[cv->frame].dirty_ymax = ymax;
if(ymax > cv->dirty_ymax)
cv->dirty_ymax = ymax;


return 0; return 0;
} }
@@ -416,10 +417,10 @@ int caca_set_dirty_rectangle(caca_canvas_t *cv, int xmin, int xmax,
ymax = -1; ymax = -1;
} }


cv->frames[cv->frame].dirty_xmin = xmin;
cv->frames[cv->frame].dirty_xmax = xmax;
cv->frames[cv->frame].dirty_ymin = ymin;
cv->frames[cv->frame].dirty_ymax = ymax;
cv->dirty_xmin = xmin;
cv->dirty_xmax = xmax;
cv->dirty_ymin = ymin;
cv->dirty_ymax = ymax;


return 0; return 0;
} }
@@ -555,6 +556,8 @@ int caca_resize(caca_canvas_t *cv, int width, int height)
} }
} }
} }

caca_add_dirty_rectangle(cv, old_width, 0, width - 1, old_height - 1);
} }
else else
{ {
@@ -594,8 +597,17 @@ int caca_resize(caca_canvas_t *cv, int width, int height)
attrs[old_height * width + x] = attr; attrs[old_height * width + x] = attr;
} }
} }

caca_add_dirty_rectangle(cv, 0, old_height, old_width - 1, height - 1);
} }


/* XXX: technically we should not worry about the dirty rectangle in
* the bottom-right corner, because we only handle one dirty rectangle,
* but in case the API changes later, we make sure this is handled. */
if(width > old_width && height > old_height)
caca_add_dirty_rectangle(cv, old_width, old_height,
width - 1, height - 1);

/* Step 4: if new area is smaller, resize memory area now. */ /* Step 4: if new area is smaller, resize memory area now. */
if(new_size < old_size) if(new_size < old_size)
{ {


+ 7
- 0
caca/frame.c Bestand weergeven

@@ -64,10 +64,16 @@ int caca_set_frame(caca_canvas_t *cv, int id)
return -1; return -1;
} }


/* Bail out if no operation is required */
if(id == cv->frame)
return 0;

_caca_save_frame_info(cv); _caca_save_frame_info(cv);
cv->frame = id; cv->frame = id;
_caca_load_frame_info(cv); _caca_load_frame_info(cv);


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -230,6 +236,7 @@ int caca_free_frame(caca_canvas_t *cv, int id)
{ {
cv->frame = 0; cv->frame = 0;
_caca_load_frame_info(cv); _caca_load_frame_info(cv);
caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);
} }


return 0; return 0;


+ 3
- 0
caca/graphics.c Bestand weergeven

@@ -154,6 +154,9 @@ int caca_refresh_display(caca_display_t *dp)


dp->drv.display(dp); dp->drv.display(dp);


/* Invalidate the dirty rectangle */
caca_set_dirty_rectangle(dp->cv, -1, -1, -1, -1);

/* Once the display is finished, we can ack resizes */ /* Once the display is finished, we can ack resizes */
if(dp->resize.resized) if(dp->resize.resized)
{ {


+ 32
- 4
caca/string.c Bestand weergeven

@@ -112,7 +112,7 @@ int caca_get_cursor_y(caca_canvas_t const *cv)
int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch) int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch)
{ {
uint32_t *curchar, *curattr, attr; uint32_t *curchar, *curattr, attr;
int fullwidth;
int fullwidth, xmin, xmax;


if(x >= (int)cv->width || y < 0 || y >= (int)cv->height) if(x >= (int)cv->width || y < 0 || y >= (int)cv->height)
return 0; return 0;
@@ -135,10 +135,15 @@ int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch)
curattr = cv->attrs + x + y * cv->width; curattr = cv->attrs + x + y * cv->width;
attr = cv->curattr; attr = cv->curattr;


xmin = xmax = x;

/* When overwriting the right part of a fullwidth character, /* When overwriting the right part of a fullwidth character,
* replace its left part with a space. */ * replace its left part with a space. */
if(x && curchar[0] == CACA_MAGIC_FULLWIDTH) if(x && curchar[0] == CACA_MAGIC_FULLWIDTH)
{
curchar[-1] = ' '; curchar[-1] = ' ';
xmin--;
}


if(fullwidth) if(fullwidth)
{ {
@@ -146,10 +151,15 @@ int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch)
ch = ' '; ch = ' ';
else else
{ {
xmax++;

/* When overwriting the left part of a fullwidth character, /* When overwriting the left part of a fullwidth character,
* replace its right part with a space. */ * replace its right part with a space. */
if(x + 2 < (int)cv->width && curchar[2] == CACA_MAGIC_FULLWIDTH) if(x + 2 < (int)cv->width && curchar[2] == CACA_MAGIC_FULLWIDTH)
{
curchar[2] = ' '; curchar[2] = ' ';
xmax++;
}


curchar[1] = CACA_MAGIC_FULLWIDTH; curchar[1] = CACA_MAGIC_FULLWIDTH;
curattr[1] = attr; curattr[1] = attr;
@@ -163,6 +173,8 @@ int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch)
curchar[1] = ' '; curchar[1] = ' ';
} }


caca_add_dirty_rectangle(cv, xmin, xmax, y, y);

curchar[0] = ch; curchar[0] = ch;
curattr[0] = attr; curattr[0] = attr;


@@ -307,6 +319,8 @@ int caca_clear_canvas(caca_canvas_t *cv)
cv->attrs[n] = attr; cv->attrs[n] = attr;
} }


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -375,9 +389,9 @@ int caca_get_canvas_handle_y(caca_canvas_t const *cv)
* \return 0 in case of success, -1 if an error occurred. * \return 0 in case of success, -1 if an error occurred.
*/ */
int caca_blit(caca_canvas_t *dst, int x, int y, int caca_blit(caca_canvas_t *dst, int x, int y,
caca_canvas_t const *src, caca_canvas_t const *mask)
caca_canvas_t const *src, caca_canvas_t const *mask)
{ {
int i, j, starti, startj, endi, endj;
int i, j, starti, startj, endi, endj, stride, bleed_left, bleed_right;


if(mask && (src->width != mask->width || src->height != mask->height)) if(mask && (src->width != mask->width || src->height != mask->height))
{ {
@@ -392,24 +406,32 @@ int caca_blit(caca_canvas_t *dst, int x, int y,
startj = y < 0 ? -y : 0; startj = y < 0 ? -y : 0;
endi = (x + src->width >= dst->width) ? dst->width - x : src->width; endi = (x + src->width >= dst->width) ? dst->width - x : src->width;
endj = (y + src->height >= dst->height) ? dst->height - y : src->height; endj = (y + src->height >= dst->height) ? dst->height - y : src->height;
stride = endi - starti;


if(starti > src->width || startj > src->height if(starti > src->width || startj > src->height
|| starti >= endi || startj >= endj) || starti >= endi || startj >= endj)
return 0; return 0;


bleed_left = bleed_right = 0;

for(j = startj; j < endj; j++) for(j = startj; j < endj; j++)
{ {
int dstix = (j + y) * dst->width + starti + x; int dstix = (j + y) * dst->width + starti + x;
int srcix = j * src->width + starti; int srcix = j * src->width + starti;
int stride = endi - starti;


/* FIXME: we are ignoring the mask here */ /* FIXME: we are ignoring the mask here */
if((starti + x) && dst->chars[dstix] == CACA_MAGIC_FULLWIDTH) if((starti + x) && dst->chars[dstix] == CACA_MAGIC_FULLWIDTH)
{
dst->chars[dstix - 1] = ' '; dst->chars[dstix - 1] = ' ';
bleed_left = 1;
}


if(endi + x < dst->width if(endi + x < dst->width
&& dst->chars[dstix + stride] == CACA_MAGIC_FULLWIDTH) && dst->chars[dstix + stride] == CACA_MAGIC_FULLWIDTH)
{
dst->chars[dstix + stride] = ' '; dst->chars[dstix + stride] = ' ';
bleed_right = 1;
}


if(mask) if(mask)
{ {
@@ -436,6 +458,9 @@ int caca_blit(caca_canvas_t *dst, int x, int y,
dst->chars[dstix + stride - 1] = ' '; dst->chars[dstix + stride - 1] = ' ';
} }


caca_add_dirty_rectangle(dst, starti + x - bleed_left, startj + y,
endi + x - 1 + bleed_right, endj + y - 1);

return 0; return 0;
} }


@@ -499,6 +524,9 @@ int caca_set_canvas_boundaries(caca_canvas_t *cv, int x, int y, int w, int h)
caca_set_frame(cv, saved_f); caca_set_frame(cv, saved_f);
_caca_load_frame_info(cv); _caca_load_frame_info(cv);


/* FIXME: this may be optimised somewhat */
caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }




+ 16
- 0
caca/transform.c Bestand weergeven

@@ -54,6 +54,8 @@ int caca_invert(caca_canvas_t *cv)
attrs++; attrs++;
} }


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -113,6 +115,8 @@ int caca_flip(caca_canvas_t *cv)
} }
} }


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -158,6 +162,8 @@ int caca_flop(caca_canvas_t *cv)
*ctop = flopchar(*ctop); *ctop = flopchar(*ctop);
} }


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -215,6 +221,8 @@ int caca_rotate_180(caca_canvas_t *cv)
} }
} }


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -332,6 +340,8 @@ int caca_rotate_left(caca_canvas_t *cv)
/* Reset the current frame shortcuts */ /* Reset the current frame shortcuts */
_caca_load_frame_info(cv); _caca_load_frame_info(cv);


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -449,6 +459,8 @@ int caca_rotate_right(caca_canvas_t *cv)
/* Reset the current frame shortcuts */ /* Reset the current frame shortcuts */
_caca_load_frame_info(cv); _caca_load_frame_info(cv);


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -540,6 +552,8 @@ int caca_stretch_left(caca_canvas_t *cv)
/* Reset the current frame shortcuts */ /* Reset the current frame shortcuts */
_caca_load_frame_info(cv); _caca_load_frame_info(cv);


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }


@@ -631,6 +645,8 @@ int caca_stretch_right(caca_canvas_t *cv)
/* Reset the current frame shortcuts */ /* Reset the current frame shortcuts */
_caca_load_frame_info(cv); _caca_load_frame_info(cv);


caca_set_dirty_rectangle(cv, 0, 0, cv->width - 1, cv->height - 1);

return 0; return 0;
} }




Laden…
Annuleren
Opslaan