Переглянути джерело

Allow to temporarily disable dirty rectangle handling. This allows for huge

speedups when the calling application knows the dirty rectangle covered by
a complex operation.
tags/v0.99.beta17
Sam Hocevar sam 15 роки тому
джерело
коміт
5269cad56c
10 змінених файлів з 96 додано та 21 видалено
  1. +2
    -1
      caca/attr.c
  2. +2
    -0
      caca/caca.h
  3. +1
    -1
      caca/caca_internals.h
  4. +8
    -3
      caca/canvas.c
  5. +45
    -0
      caca/dirty.c
  6. +4
    -2
      caca/frame.c
  7. +10
    -5
      caca/string.c
  8. +12
    -6
      caca/transform.c
  9. +2
    -1
      tests/.gitignore
  10. +10
    -2
      tests/bench.c

+ 2
- 1
caca/attr.c Переглянути файл

@@ -156,7 +156,8 @@ int caca_put_attr(caca_canvas_t *cv, int x, int y, uint32_t attr)
xmax++;
}

caca_add_dirty_rect(cv, xmin, y, xmax - xmin + 1, 1);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, xmin, y, xmax - xmin + 1, 1);

return 0;
}


+ 2
- 0
caca/caca.h Переглянути файл

@@ -240,6 +240,8 @@ __extern int caca_set_canvas_boundaries(caca_canvas_t *, int, int, int, int);
*
* These functions manipulate dirty rectangles for optimised blitting.
* @{ */
__extern int caca_disable_dirty_rect(caca_canvas_t *);
__extern int caca_enable_dirty_rect(caca_canvas_t *);
__extern int caca_get_dirty_rect_count(caca_canvas_t *);
__extern int caca_get_dirty_rect(caca_canvas_t *, int, int *, int *,
int *, int *);


+ 1
- 1
caca/caca_internals.h Переглянути файл

@@ -60,7 +60,7 @@ struct caca_canvas
void *resize_data;

/* Dirty rectangles */
int ndirty;
int ndirty, dirty_disabled;
struct
{
int xmin, ymin, xmax, ymax;


+ 8
- 3
caca/canvas.c Переглянути файл

@@ -433,7 +433,9 @@ int caca_resize(caca_canvas_t *cv, int width, int height)
}
}

caca_add_dirty_rect(cv, old_width, 0, width - old_width, old_height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, old_width, 0,
width - old_width, old_height);
}
else
{
@@ -474,12 +476,15 @@ int caca_resize(caca_canvas_t *cv, int width, int height)
}
}

caca_add_dirty_rect(cv, 0, old_height, old_width, height - old_height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, old_height,
old_width, height - old_height);
}

/* If both width and height are larger, there is a new dirty rectangle
* that needs to be created in the lower right corner. */
if(width > old_width && height > old_height)
if(!cv->dirty_disabled &&
width > old_width && height > old_height)
caca_add_dirty_rect(cv, old_width, old_height,
width - old_width, height - old_height);



+ 45
- 0
caca/dirty.c Переглянути файл

@@ -36,6 +36,51 @@

static void merge_new_rect(caca_canvas_t *cv, int n);

/** \brief Disable dirty rectangles.
*
* Disable dirty rectangle handling for all \e libcaca graphic calls. This
* is handy when the calling application needs to do slow operations within
* a known area. Just call caca_add_dirty_rect() afterwards.
*
* This function is recursive. Dirty rectangles are only reenabled when
* caca_enable_dirty_rect() is called as many times.
*
* This function never fails.
*
* \param cv A libcaca canvas.
* \return This function always returns 0.
*/
int caca_disable_dirty_rect(caca_canvas_t *cv)
{
cv->dirty_disabled++;

return 0;
}

/** \brief Enable dirty rectangles.
*
* This function can only be called after caca_disable_dirty_rect() was
* called.
*
* If an error occurs, -1 is returned and \b errno is set accordingly:
* - \c EINVAL Dirty rectangles were not disabled.
*
* \param cv A libcaca canvas.
* \return 0 in case of success, -1 if an error occurred.
*/
int caca_enable_dirty_rect(caca_canvas_t *cv)
{
if(cv->dirty_disabled <= 0)
{
seterrno(EINVAL);
return -1;
}

cv->dirty_disabled--;

return 0;
}

/** \brief Get the number of dirty rectangles in the canvas.
*
* Get the number of dirty rectangles in a canvas. Dirty rectangles are


+ 4
- 2
caca/frame.c Переглянути файл

@@ -72,7 +72,8 @@ int caca_set_frame(caca_canvas_t *cv, int id)
cv->frame = id;
_caca_load_frame_info(cv);

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -236,7 +237,8 @@ int caca_free_frame(caca_canvas_t *cv, int id)
{
cv->frame = 0;
_caca_load_frame_info(cv);
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
}

return 0;


+ 10
- 5
caca/string.c Переглянути файл

@@ -180,7 +180,8 @@ int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch)
* or attribute at that place. This does not account for inconsistencies
* in the canvas, ie. if CACA_MAGIC_FULLWIDTH lies at illegal places,
* but it's the caller's responsibility not to corrupt the contents. */
if(curchar[0] != ch || curattr[0] != attr)
if(!cv->dirty_disabled
&& (curchar[0] != ch || curattr[0] != attr))
caca_add_dirty_rect(cv, xmin, y, xmax - xmin + 1, 1);

curchar[0] = ch;
@@ -327,7 +328,8 @@ int caca_clear_canvas(caca_canvas_t *cv)
cv->attrs[n] = attr;
}

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -453,7 +455,8 @@ int caca_blit(caca_canvas_t *dst, int x, int y,
{
dst->chars[dstix + i] = src->chars[srcix + i];
dst->attrs[dstix + i] = src->attrs[srcix + i];
caca_add_dirty_rect(dst, x + starti + i, y + j, 1, 1);
if(!dst->dirty_disabled)
caca_add_dirty_rect(dst, x + starti + i, y + j, 1, 1);
}
}
}
@@ -465,7 +468,8 @@ int caca_blit(caca_canvas_t *dst, int x, int y,
/* FIXME be more precise ? */
memcpy(dst->chars + dstix, src->chars + srcix, stride * 4);
memcpy(dst->attrs + dstix, src->attrs + srcix, stride * 4);
caca_add_dirty_rect(dst, x + starti, y + j, stride, 1);
if(!dst->dirty_disabled)
caca_add_dirty_rect(dst, x + starti, y + j, stride, 1);
}
}

@@ -542,7 +546,8 @@ int caca_set_canvas_boundaries(caca_canvas_t *cv, int x, int y, int w, int h)
_caca_load_frame_info(cv);

/* FIXME: this may be optimised somewhat */
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}


+ 12
- 6
caca/transform.c Переглянути файл

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

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -115,7 +116,8 @@ int caca_flip(caca_canvas_t *cv)
}
}

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -162,7 +164,8 @@ int caca_flop(caca_canvas_t *cv)
*ctop = flopchar(*ctop);
}

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -221,7 +224,8 @@ int caca_rotate_180(caca_canvas_t *cv)
}
}

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -340,7 +344,8 @@ int caca_rotate_left(caca_canvas_t *cv)
/* Reset the current frame shortcuts */
_caca_load_frame_info(cv);

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}
@@ -459,7 +464,8 @@ int caca_rotate_right(caca_canvas_t *cv)
/* Reset the current frame shortcuts */
_caca_load_frame_info(cv);

caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
if(!cv->dirty_disabled)
caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);

return 0;
}


+ 2
- 1
tests/.gitignore Переглянути файл

@@ -1,2 +1,3 @@
simple
bench
caca-test
simple

+ 10
- 2
tests/bench.c Переглянути файл

@@ -47,16 +47,23 @@ static void blit(int mask, int clear)
caca_free_canvas(cv2);
}

static void putchars(void)
static void putchars(int optim)
{
caca_canvas_t *cv;
int i;
cv = caca_create_canvas(40, 40);
if(optim)
caca_disable_dirty_rect(cv);
for (i = 0; i < PUTCHAR_LOOPS; i++)
{
caca_put_char(cv, 1, 1, 'x');
caca_put_char(cv, 1, 1, 'o');
}
if(optim)
{
caca_enable_dirty_rect(cv);
caca_add_dirty_rect(cv, 1, 1, 1, 1);
}
caca_free_canvas(cv);
}

@@ -66,7 +73,8 @@ int main(int argc, char *argv[])
TIME("blit no mask, clear", blit(0, 1));
TIME("blit mask, no clear", blit(1, 0));
TIME("blit mask, clear", blit(1, 1));
TIME("putchars", putchars());
TIME("putchars, no optim", putchars(0));
TIME("putchars, optim", putchars(1));
return 0;
}


Завантаження…
Відмінити
Зберегти