Changeset 3568 for libcaca


Ignore:
Timestamp:
Jul 24, 2009, 8:48:35 AM (10 years ago)
Author:
Sam Hocevar
Message:

Store dirty rectangles in a structure list. For now there is still only
one dirty rectangle, but this is the first step to improvement.

Location:
libcaca/trunk/caca
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/caca/caca_internals.h

    r3471 r3568  
    2424#if !defined(_DOXYGEN_SKIP_ME)
    2525#   define EVENTBUF_LEN 10
     26#   define MAX_DIRTY_COUNT 1
    2627#endif
    2728
     
    6162    /* Dirty rectangles */
    6263    int ndirty;
    63     int dirty_xmin, dirty_xmax, dirty_ymin, dirty_ymax;
     64    struct
     65    {
     66        int xmin, xmax, ymin, ymax;
     67    }
     68    dirty[MAX_DIRTY_COUNT];
    6469
    6570    /* Shortcut to the active frame information */
     
    217222};
    218223
     224/* Dirty rectangle functions */
     225extern void _caca_clip_dirty_rect_list(caca_canvas_t *);
     226
    219227/* Colour functions */
    220228extern uint32_t _caca_attr_to_rgb24fg(uint32_t);
  • libcaca/trunk/caca/canvas.c

    r3494 r3568  
    371371    _caca_save_frame_info(cv);
    372372
     373    /* Preload new width and height values into the canvas to optimise
     374     * dirty rectangle handling */
    373375    cv->width = width;
    374376    cv->height = height;
    375377    new_size = width * height;
     378
     379    /* If width or height is smaller (or both), we have the opportunity to
     380     * reduce or even remove dirty rectangles */
     381    if(width < old_width || height < old_height)
     382        _caca_clip_dirty_rect_list(cv);
    376383
    377384    /* Step 1: if new area is bigger, resize the memory area now. */
     
    471478    }
    472479
    473     /* XXX: technically we should not worry about the dirty rectangle in
    474      * the bottom-right corner, because we only handle one dirty rectangle,
    475      * but in case the API changes later, we make sure this is handled. */
     480    /* If both width and height are larger, there is a new dirty rectangle
     481     * that needs to be created in the lower right corner. */
    476482    if(width > old_width && height > old_height)
    477483        caca_add_dirty_rect(cv, old_width, old_height,
  • libcaca/trunk/caca/dirty.c

    r3494 r3568  
    1515/*
    1616 *  This file contains the dirty rectangle handling functions.
     17 *
     18 *
     19 *  About dirty rectangles:
     20 *
     21 *  * Dirty rectangles MUST NOT be larger than the canvas. If the user
     22 *  provides a large rectangle through caca_add_dirty_rect(), or if the
     23 *  canvas changes size to become smaller, all dirty rectangles MUST
     24 *  immediately be clipped to the canvas size.
    1725 */
    1826
     
    7886    }
    7987
    80     /* Normalise dirty rectangle so that the values can be directly used. */
    81     if(cv->dirty_xmin < 0)
    82         cv->dirty_xmin = 0;
    83 
    84     if(cv->dirty_xmax > cv->width - 1)
    85         cv->dirty_xmax = cv->width - 1;
    86 
    87     if(cv->dirty_ymin < 0)
    88         cv->dirty_ymin = 0;
    89 
    90     if(cv->dirty_ymax > cv->height - 1)
    91         cv->dirty_ymax = cv->height - 1;
    92 
    93     *x = cv->dirty_xmin;
    94     *y = cv->dirty_ymin;
    95     *width = cv->dirty_xmax - cv->dirty_xmin + 1;
    96     *height = cv->dirty_ymax - cv->dirty_ymin + 1;
     88    *x = cv->dirty[r].xmin;
     89    *y = cv->dirty[r].ymin;
     90    *width = cv->dirty[r].xmax - cv->dirty[r].xmin + 1;
     91    *height = cv->dirty[r].ymax - cv->dirty[r].ymin + 1;
     92
     93    debug("dirty #%i: %ix%i at (%i,%i)\n", r, *width, *height, *x, *y);
    9794
    9895    return 0;
     
    119116 *  \return 0 in case of success, -1 if an error occurred.
    120117 */
    121 int caca_add_dirty_rect(caca_canvas_t *cv, int x, int y,
    122                              int width, int height)
    123 {
    124     /* Ignore empty and out-of-bounds rectangles */
    125     if(width <= 0 || height <= 0 || x + width <= 0 || x >= cv->width
    126         || y + height <= 0 || y >= cv->height)
     118int caca_add_dirty_rect(caca_canvas_t *cv, int x, int y, int width, int height)
     119{
     120    debug("new dirty: %ix%i at (%i,%i)\n", width, height, x, y);
     121
     122    /* Clip arguments to canvas */
     123    if(x < 0) { width += x; x = 0; }
     124
     125    if(x + width > cv->width)
     126        width = cv->width - x;
     127
     128    if(y < 0) { height += y; y = 0; }
     129
     130    if(y + height > cv->height)
     131        height = cv->height - y;
     132
     133    /* Ignore empty and out-of-canvas rectangles */
     134    if(width <= 0 || height <= 0)
    127135    {
    128136        seterrno(EINVAL);
     
    130138    }
    131139
    132     if(cv->ndirty == 0)
    133     {
    134         cv->ndirty = 1;
    135         cv->dirty_xmin = x;
    136         cv->dirty_xmax = x + width - 1;
    137         cv->dirty_ymin = y;
    138         cv->dirty_ymax = y + height - 1;
     140    /* Add dirty rectangle to list. Current strategy: if there is room
     141     * for rectangles, just append it to the list. Otherwise, merge the
     142     * new rectangle with the first in the list. */
     143    if(cv->ndirty < MAX_DIRTY_COUNT)
     144    {
     145        cv->dirty[cv->ndirty].xmin = x;
     146        cv->dirty[cv->ndirty].xmax = x + width - 1;
     147        cv->dirty[cv->ndirty].ymin = y;
     148        cv->dirty[cv->ndirty].ymax = y + height - 1;
     149        cv->ndirty++;
    139150    }
    140151    else
    141152    {
    142         if(x < cv->dirty_xmin)
    143             cv->dirty_xmin = x;
    144         if(x + width - 1 > cv->dirty_xmax)
    145             cv->dirty_xmax = x + width - 1;
    146         if(y < cv->dirty_ymin)
    147             cv->dirty_ymin = y;
    148         if(y + height - 1 > cv->dirty_ymax)
    149             cv->dirty_ymax = y + height - 1;
     153        if(x < cv->dirty[0].xmin)
     154            cv->dirty[0].xmin = x;
     155        if(x + width - 1 > cv->dirty[0].xmax)
     156            cv->dirty[0].xmax = x + width - 1;
     157        if(y < cv->dirty[0].ymin)
     158            cv->dirty[0].ymin = y;
     159        if(y + height - 1 > cv->dirty[0].ymax)
     160            cv->dirty[0].ymax = y + height - 1;
    150161    }
    151162
     
    174185                           int width, int height)
    175186{
    176     /* Ignore empty and out-of-bounds rectangles */
    177     if(width <= 0 || height <= 0 || x + width <= 0 || x >= cv->width
    178         || y + height <= 0 || y >= cv->height)
     187    /* Clip arguments to canvas size */
     188    if(x < 0) { width += x; x = 0; }
     189
     190    if(x + width > cv->width)
     191        width = cv->width - x;
     192
     193    if(y < 0) { height += y; y = 0; }
     194
     195    if(y + height > cv->height)
     196        height = cv->height - y;
     197
     198    /* Ignore empty and out-of-canvas rectangles */
     199    if(width <= 0 || height <= 0)
    179200    {
    180201        seterrno(EINVAL);
     
    205226}
    206227
     228/*
     229 * XXX: the following functions are local.
     230 */
     231
     232/* Clip all dirty rectangles in case they're larger than the canvas */
     233void _caca_clip_dirty_rect_list(caca_canvas_t *cv)
     234{
     235    int i;
     236
     237    for(i = 0; i < cv->ndirty; i++)
     238    {
     239        if(cv->dirty[i].xmin < 0)
     240            cv->dirty[i].xmin = 0;
     241
     242        if(cv->dirty[i].ymin < 0)
     243            cv->dirty[i].ymin = 0;
     244
     245        if(cv->dirty[i].xmax >= cv->width)
     246            cv->dirty[i].xmax = cv->width - 1;
     247
     248        if(cv->dirty[i].ymax >= cv->height)
     249            cv->dirty[i].ymax = cv->height - 1;
     250    }
     251}
     252
Note: See TracChangeset for help on using the changeset viewer.