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

Last change on this file since 3470 was 3470, checked in by Sam Hocevar, 11 years ago

Change the dirty rectangle API so that it can handle several rectangles. The
inner implementation still only handles one dirty rectangle, but this way
we can prepare supporting applictions for the future.

  • Property svn:keywords set to Id
File size: 6.9 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 3470 2009-05-19 00:51:47Z sam $
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#include "config.h"
20
21#if !defined(__KERNEL__)
22#   include <stdio.h>
23#endif
24
25#include "caca.h"
26#include "caca_internals.h"
27
28/** \brief Get the number of dirty rectangles in the canvas.
29 *
30 *  Get the number of dirty rectangles in a canvas. Dirty rectangles are
31 *  areas that contain cells that have changed since the last reset.
32 *
33 *  The dirty rectangles are used internally by display drivers to optimise
34 *  rendering by avoiding to redraw the whole screen. Once the display driver
35 *  has rendered the canvas, it resets the dirty rectangle list.
36 *
37 *  Dirty rectangles are guaranteed not to overlap.
38 *
39 *  This function never fails.
40 *
41 *  \param cv A libcaca canvas.
42 *  \return The number of dirty rectangles in the given canvas.
43 */
44int caca_get_dirty_rectangle_count(caca_canvas_t *cv)
45{
46    /* Ignore empty rectangles. */
47    if(cv->dirty_xmin > cv->dirty_xmax || cv->dirty_ymin > cv->dirty_ymax)
48        return 0;
49
50    /* Ignore out-of-bounds rectangles. */
51    if(cv->dirty_xmax < 0 || cv->dirty_xmin >= cv->width
52        || cv->dirty_ymax < 0 || cv->dirty_ymin >= cv->height)
53        return 0;
54
55    return 1;
56}
57
58/** \brief Get a canvas's dirty rectangle.
59 *
60 *  Get the canvas's given dirty rectangle coordinates. The index must be
61 *  within the dirty rectangle count. See caca_get_dirty_rectangle_count()
62 *  for how to compute this count.
63 *
64 *  If an error occurs, no coordinates are written in the pointer arguments,
65 *  -1 is returned and \b errno is set accordingly:
66 *  - \c EINVAL Specified rectangle index is out of bounds.
67 *
68 *  \param cv A libcaca canvas.
69 *  \param index The requested rectangle index.
70 *  \param xmin A pointer to an integer where the leftmost edge of the
71 *              dirty rectangle will be stored.
72 *  \param ymin A pointer to an integer where the topmost edge of the
73 *              dirty rectangle will be stored.
74 *  \param xmax A pointer to an integer where the rightmost edge of the
75 *              dirty rectangle will be stored.
76 *  \param ymax A pointer to an integer where the bottommost edge of the
77 *              dirty rectangle will be stored.
78 *  \return 0 in case of success, -1 if an error occurred.
79 */
80int caca_get_dirty_rectangle(caca_canvas_t *cv, int index,
81                             int *xmin, int *ymin, int *xmax, int *ymax)
82{
83    /* For now, index can only be zero, and if the dirty rectangle is
84     * empty, we don't return anything. */
85    if(index < 0 || index > 0
86        || cv->dirty_xmin > cv->dirty_xmax || cv->dirty_ymin > cv->dirty_ymax
87        || cv->dirty_xmax < 0 || cv->dirty_xmin >= cv->width
88        || cv->dirty_ymax < 0 || cv->dirty_ymin >= cv->height)
89    {
90        seterrno(EINVAL);
91        return -1;
92    }
93
94    /* Normalise dirty rectangle so that the values can be directly used. */
95    if(cv->dirty_xmin < 0)
96        cv->dirty_xmin = 0;
97
98    if(cv->dirty_xmax > cv->width - 1)
99        cv->dirty_xmax = cv->width - 1;
100
101    if(cv->dirty_ymin < 0)
102        cv->dirty_ymin = 0;
103
104    if(cv->dirty_ymax > cv->height - 1)
105        cv->dirty_ymax = cv->height - 1;
106
107    *xmin = cv->dirty_xmin;
108    *xmax = cv->dirty_xmax;
109    *ymin = cv->dirty_ymin;
110    *ymax = cv->dirty_ymax;
111
112    return 0;
113}
114
115/** \brief Add an area to the canvas's dirty rectangle list.
116 *
117 *  Add an invalidating zone to the canvas's dirty rectangle list. For more
118 *  information about the dirty rectangles, see caca_get_dirty_rectangle().
119 *
120 *  This function may be useful to force refresh of a given zone of the
121 *  canvas even if the dirty rectangle tracking indicates that it is
122 *  unchanged. This may happen if the canvas contents were somewhat
123 *  directly modified.
124 *
125 *  If an error occurs, -1 is returned and \b errno is set accordingly:
126 *  - \c EINVAL Specified rectangle coordinates are out of bounds.
127 *
128 *  \param cv A libcaca canvas.
129 *  \param xmin The leftmost edge of the additional dirty rectangle.
130 *  \param ymin The topmost edge of the additional dirty rectangle.
131 *  \param xmax The rightmost edge of the additional dirty rectangle.
132 *  \param ymax The bottommost edge of the additional dirty rectangle.
133 *  \return 0 in case of success, -1 if an error occurred.
134 */
135int caca_add_dirty_rectangle(caca_canvas_t *cv, int xmin, int ymin,
136                             int xmax, int ymax)
137{
138    /* Ignore empty and out-of-bounds rectangles */
139    if(xmin > xmax || ymin > ymax
140        || xmax < 0 || xmin >= cv->width || ymax < 0 || ymin >= cv->height)
141    {
142        seterrno(EINVAL);
143        return -1;
144    }
145
146    if(xmin < cv->dirty_xmin)
147        cv->dirty_xmin = xmin;
148
149    if(xmax > cv->dirty_xmax)
150        cv->dirty_xmax = xmax;
151
152    if(ymin < cv->dirty_ymin)
153        cv->dirty_ymin = ymin;
154
155    if(ymax > cv->dirty_ymax)
156        cv->dirty_ymax = ymax;
157
158    return 0;
159}
160
161/** \brief Remove an area from the dirty rectangle list.
162 *
163 *  Mark a cell area in the canvas as not dirty. For more information about
164 *  the dirty rectangles, see caca_get_dirty_rectangle().
165 *
166 *  Values such that \b xmin > \b xmax or \b ymin > \b ymax indicate that
167 *  the dirty rectangle is empty. They will be silently ignored.
168 *
169 *  If an error occurs, -1 is returned and \b errno is set accordingly:
170 *  - \c EINVAL Specified rectangle coordinates are out of bounds.
171 *
172 *  \param cv A libcaca canvas.
173 *  \param xmin The leftmost edge of the clean rectangle.
174 *  \param ymin The topmost edge of the clean rectangle.
175 *  \param xmax The rightmost edge of the clean rectangle.
176 *  \param ymax The bottommost edge of the clean rectangle.
177 *  \return 0 in case of success, -1 if an error occurred.
178 */
179int caca_remove_dirty_rectangle(caca_canvas_t *cv, int xmin, int ymin,
180                                int xmax, int ymax)
181{
182    /* Ignore empty and out-of-bounds rectangles */
183    if(xmin > xmax || ymin > ymax
184        || xmax < 0 || xmin >= cv->width || ymax < 0 || ymin >= cv->height)
185    {
186        seterrno(EINVAL);
187        return -1;
188    }
189
190    /* FIXME: implement this function. It's OK to have it do nothing,
191     * since we take a conservative approach in dirty rectangle handling,
192     * but we ought to help the rendering eventually. */
193
194    return 0;
195}
196
197/** \brief Clear a canvas's dirty rectangle list.
198 *
199 *  Empty the canvas's dirty rectangle list.
200 *
201 *  This function never fails.
202 *
203 *  \param cv A libcaca canvas.
204 *  \return This function always returns 0.
205 */
206int caca_clear_dirty_rectangle_list(caca_canvas_t *cv)
207{
208    cv->dirty_xmin = cv->width;
209    cv->dirty_xmax = -1;
210    cv->dirty_ymin = cv->height;
211    cv->dirty_ymax = -1;
212
213    return 0;
214}
215
Note: See TracBrowser for help on using the repository browser.