source: libcaca/trunk/caca/dirty.c @ 3574

Last change on this file since 3574 was 3574, checked in by Pascal Terjan, 11 years ago
  • Inform code reader that current algorithm is wrong
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: dirty.c 3574 2009-07-24 14:46:14Z pterjan $
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  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.
25 */
26
27#include "config.h"
28
29#if !defined(__KERNEL__)
30#   include <stdio.h>
31#endif
32
33#include "caca.h"
34#include "caca_internals.h"
35
36/** \brief Get the number of dirty rectangles in the canvas.
37 *
38 *  Get the number of dirty rectangles in a canvas. Dirty rectangles are
39 *  areas that contain cells that have changed since the last reset.
40 *
41 *  The dirty rectangles are used internally by display drivers to optimise
42 *  rendering by avoiding to redraw the whole screen. Once the display driver
43 *  has rendered the canvas, it resets the dirty rectangle list.
44 *
45 *  Dirty rectangles are guaranteed not to overlap.
46 *
47 *  This function never fails.
48 *
49 *  \param cv A libcaca canvas.
50 *  \return The number of dirty rectangles in the given canvas.
51 */
52int caca_get_dirty_rect_count(caca_canvas_t *cv)
53{
54    return cv->ndirty;
55}
56
57/** \brief Get a canvas's dirty rectangle.
58 *
59 *  Get the canvas's given dirty rectangle coordinates. The index must be
60 *  within the dirty rectangle count. See caca_get_dirty_rect_count()
61 *  for how to compute this count.
62 *
63 *  If an error occurs, no coordinates are written in the pointer arguments,
64 *  -1 is returned and \b errno is set accordingly:
65 *  - \c EINVAL Specified rectangle index is out of bounds.
66 *
67 *  \param cv A libcaca canvas.
68 *  \param r The requested rectangle index.
69 *  \param x A pointer to an integer where the leftmost edge of the
70 *           dirty rectangle will be stored.
71 *  \param y A pointer to an integer where the topmost edge of the
72 *           dirty rectangle will be stored.
73 *  \param width A pointer to an integer where the width of the
74 *               dirty rectangle will be stored.
75 *  \param height A pointer to an integer where the height of the
76 *                dirty rectangle will be stored.
77 *  \return 0 in case of success, -1 if an error occurred.
78 */
79int caca_get_dirty_rect(caca_canvas_t *cv, int r,
80                        int *x, int *y, int *width, int *height)
81{
82    if(r < 0 || r >= cv->ndirty)
83    {
84        seterrno(EINVAL);
85        return -1;
86    }
87
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);
94
95    return 0;
96}
97
98/** \brief Add an area to the canvas's dirty rectangle list.
99 *
100 *  Add an invalidating zone to the canvas's dirty rectangle list. For more
101 *  information about the dirty rectangles, see caca_get_dirty_rect().
102 *
103 *  This function may be useful to force refresh of a given zone of the
104 *  canvas even if the dirty rectangle tracking indicates that it is
105 *  unchanged. This may happen if the canvas contents were somewhat
106 *  directly modified.
107 *
108 *  If an error occurs, -1 is returned and \b errno is set accordingly:
109 *  - \c EINVAL Specified rectangle coordinates are out of bounds.
110 *
111 *  \param cv A libcaca canvas.
112 *  \param x The leftmost edge of the additional dirty rectangle.
113 *  \param y The topmost edge of the additional dirty rectangle.
114 *  \param width The width of the additional dirty rectangle.
115 *  \param height The height of the additional dirty rectangle.
116 *  \return 0 in case of success, -1 if an error occurred.
117 */
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)
135    {
136        seterrno(EINVAL);
137        return -1;
138    }
139
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++;
150    }
151    else
152    {
153        /* FIXME We may get overlapping rectangles like this */
154        if(x < cv->dirty[0].xmin)
155            cv->dirty[0].xmin = x;
156        if(x + width - 1 > cv->dirty[0].xmax)
157            cv->dirty[0].xmax = x + width - 1;
158        if(y < cv->dirty[0].ymin)
159            cv->dirty[0].ymin = y;
160        if(y + height - 1 > cv->dirty[0].ymax)
161            cv->dirty[0].ymax = y + height - 1;
162    }
163
164    return 0;
165}
166
167/** \brief Remove an area from the dirty rectangle list.
168 *
169 *  Mark a cell area in the canvas as not dirty. For more information about
170 *  the dirty rectangles, see caca_get_dirty_rect().
171 *
172 *  Values such that \b xmin > \b xmax or \b ymin > \b ymax indicate that
173 *  the dirty rectangle is empty. They will be silently ignored.
174 *
175 *  If an error occurs, -1 is returned and \b errno is set accordingly:
176 *  - \c EINVAL Specified rectangle coordinates are out of bounds.
177 *
178 *  \param cv A libcaca canvas.
179 *  \param x The leftmost edge of the clean rectangle.
180 *  \param y The topmost edge of the clean rectangle.
181 *  \param width The width of the clean rectangle.
182 *  \param height The height of the clean rectangle.
183 *  \return 0 in case of success, -1 if an error occurred.
184 */
185int caca_remove_dirty_rect(caca_canvas_t *cv, int x, int y,
186                           int width, int height)
187{
188    /* Clip arguments to canvas size */
189    if(x < 0) { width += x; x = 0; }
190
191    if(x + width > cv->width)
192        width = cv->width - x;
193
194    if(y < 0) { height += y; y = 0; }
195
196    if(y + height > cv->height)
197        height = cv->height - y;
198
199    /* Ignore empty and out-of-canvas rectangles */
200    if(width <= 0 || height <= 0)
201    {
202        seterrno(EINVAL);
203        return -1;
204    }
205
206    /* FIXME: implement this function. It's OK to have it do nothing,
207     * since we take a conservative approach in dirty rectangle handling,
208     * but we ought to help the rendering eventually. */
209
210    return 0;
211}
212
213/** \brief Clear a canvas's dirty rectangle list.
214 *
215 *  Empty the canvas's dirty rectangle list.
216 *
217 *  This function never fails.
218 *
219 *  \param cv A libcaca canvas.
220 *  \return This function always returns 0.
221 */
222int caca_clear_dirty_rect_list(caca_canvas_t *cv)
223{
224    cv->ndirty = 0;
225
226    return 0;
227}
228
229/*
230 * XXX: the following functions are local.
231 */
232
233/* Clip all dirty rectangles in case they're larger than the canvas */
234void _caca_clip_dirty_rect_list(caca_canvas_t *cv)
235{
236    int i;
237
238    for(i = 0; i < cv->ndirty; i++)
239    {
240        if(cv->dirty[i].xmin < 0)
241            cv->dirty[i].xmin = 0;
242
243        if(cv->dirty[i].ymin < 0)
244            cv->dirty[i].ymin = 0;
245
246        if(cv->dirty[i].xmax >= cv->width)
247            cv->dirty[i].xmax = cv->width - 1;
248
249        if(cv->dirty[i].ymax >= cv->height)
250            cv->dirty[i].ymax = cv->height - 1;
251    }
252}
253
Note: See TracBrowser for help on using the repository browser.