diff --git a/caca/attr.c b/caca/attr.c index 9b7208b..8ec0068 100644 --- a/caca/attr.c +++ b/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; } diff --git a/caca/caca.h b/caca/caca.h index 82963f9..6e5a71c 100644 --- a/caca/caca.h +++ b/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 *); diff --git a/caca/caca_internals.h b/caca/caca_internals.h index 1bc8b60..c9875e3 100644 --- a/caca/caca_internals.h +++ b/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; diff --git a/caca/canvas.c b/caca/canvas.c index 6483bc3..e6ce3c0 100644 --- a/caca/canvas.c +++ b/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); diff --git a/caca/dirty.c b/caca/dirty.c index 9e04c07..2df1588 100644 --- a/caca/dirty.c +++ b/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 diff --git a/caca/frame.c b/caca/frame.c index 79c4189..f7d9fff 100644 --- a/caca/frame.c +++ b/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; diff --git a/caca/string.c b/caca/string.c index 62b709f..696dd88 100644 --- a/caca/string.c +++ b/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; } diff --git a/caca/transform.c b/caca/transform.c index 51923fa..81d39bc 100644 --- a/caca/transform.c +++ b/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; } diff --git a/tests/.gitignore b/tests/.gitignore index 091bbf1..5a136f5 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,2 +1,3 @@ -simple +bench caca-test +simple diff --git a/tests/bench.c b/tests/bench.c index 8cfdf58..8fdd5e0 100644 --- a/tests/bench.c +++ b/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; }