From: Keith Packard Date: Mon, 27 Feb 2023 22:35:36 +0000 (-0800) Subject: altos/draw: Add damage tracking X-Git-Tag: 1.9.16~1^2~23 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=c3414603bb9993e4cf3f0163ae0575758201b041 altos/draw: Add damage tracking This will allow more efficient updating of the screen Signed-off-by: Keith Packard --- diff --git a/src/draw/Makefile b/src/draw/Makefile index f5969f26..93c10e42 100644 --- a/src/draw/Makefile +++ b/src/draw/Makefile @@ -91,6 +91,7 @@ ao_logo.h: make-logo LIB_SRCS=\ ao_blt.c \ + ao_box.c \ ao_copy.c \ ao_line.c \ ao_pattern.c \ @@ -108,7 +109,7 @@ LINE_TEST_OBJS=$(LINE_TEST_SRCS:.c=.o) TEST_LIBS=-lXrender -lXext -lX11 -lm -Wl,--gc-sections -CFLAGS=-O0 -g $(WARN_FLAGS) -DVALIDATE +CFLAGS=-O0 -g $(WARN_FLAGS) -DVALIDATE -I. HEADERS=\ ao_draw.h \ diff --git a/src/draw/ao_blt.c b/src/draw/ao_blt.c index 951a4a14..10435d4f 100644 --- a/src/draw/ao_blt.c +++ b/src/draw/ao_blt.c @@ -12,8 +12,8 @@ * General Public License for more details. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include #define O 0 #define I AO_ALLONES diff --git a/src/draw/ao_box.c b/src/draw/ao_box.c new file mode 100644 index 00000000..173b7204 --- /dev/null +++ b/src/draw/ao_box.c @@ -0,0 +1,28 @@ +/* + * Copyright © 2023 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +void +ao_box_union(struct ao_box *dst, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +{ + if (x1 < dst->x1) dst->x1 = x1; + if (x2 > dst->x2) dst->x2 = x2; + if (y1 < dst->y1) dst->y1 = y1; + if (y2 > dst->y2) dst->y2 = y2; +} diff --git a/src/draw/ao_box.h b/src/draw/ao_box.h new file mode 100644 index 00000000..bd3aabd4 --- /dev/null +++ b/src/draw/ao_box.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2023 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BOX_H_ +#define _AO_BOX_H_ + +#include +#include + +struct ao_box { + int16_t x1, y1; + int16_t x2, y2; +}; + +static inline bool +ao_box_is_empty(struct ao_box *box) +{ + return box->x1 == INT16_MAX; +} + +static inline void +ao_box_set_empty(struct ao_box *box) +{ + box->x1 = INT16_MAX; + box->y1 = INT16_MAX; + box->x2 = INT16_MIN; + box->y2 = INT16_MIN; +} + +#define AO_BOX_INIT { .x1 = INT16_MAX, .y1 = INT16_MAX, .x2 = INT16_MIN, .y2 = INT16_MIN } + +void +ao_box_union(struct ao_box *dst, int16_t x1, int16_t y1, int16_t x2, int16_t y2); + +#endif /* _AO_BOX_H_ */ diff --git a/src/draw/ao_copy.c b/src/draw/ao_copy.c index 312d1d72..a506aed7 100644 --- a/src/draw/ao_copy.c +++ b/src/draw/ao_copy.c @@ -12,8 +12,8 @@ * General Public License for more details. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include #define bound(val,max,other) do { \ if (val < 0) { \ @@ -32,7 +32,7 @@ } while (0) void -ao_copy(const struct ao_bitmap *dst, +ao_copy(struct ao_bitmap *dst, int16_t dst_x, int16_t dst_y, int16_t width, @@ -57,6 +57,8 @@ ao_copy(const struct ao_bitmap *dst, upsidedown = (dst_y > src_y); } + ao_damage(dst, dst_x, dst_y, dst_x2, dst_y2); + if (dst_x < dst_x2 && dst_y < dst_y2) { ao_blt(src->base + src_y * src->stride, src->stride, diff --git a/src/draw/ao_draw.h b/src/draw/ao_draw.h index b4ca6eac..29afef9c 100644 --- a/src/draw/ao_draw.h +++ b/src/draw/ao_draw.h @@ -18,12 +18,14 @@ #include #include #include "ao_font.h" +#include "ao_box.h" struct ao_bitmap { uint32_t *base; int16_t stride; /* in units */ int16_t width; /* in pixels */ int16_t height; /* in pixels */ + struct ao_box damage; }; struct ao_coord { @@ -81,6 +83,12 @@ ao_stride_bytes(int16_t width) return (int16_t) ((width + 7) >> 3); } +static inline void +ao_damage_set_empty(struct ao_bitmap *dst) +{ + ao_box_set_empty(&dst->damage); +} + struct ao_pattern { uint8_t pattern[8]; }; @@ -103,7 +111,7 @@ struct ao_font { }; void -ao_copy(const struct ao_bitmap *dst, +ao_copy(struct ao_bitmap *dst, int16_t dst_x, int16_t dst_y, int16_t width, @@ -114,7 +122,7 @@ ao_copy(const struct ao_bitmap *dst, uint8_t rop); void -ao_rect(const struct ao_bitmap *dst, +ao_rect(struct ao_bitmap *dst, int16_t x, int16_t y, int16_t width, @@ -123,7 +131,7 @@ ao_rect(const struct ao_bitmap *dst, uint8_t rop); void -ao_pattern(const struct ao_bitmap *dst, +ao_pattern(struct ao_bitmap *dst, int16_t x, int16_t y, int16_t width, @@ -134,7 +142,7 @@ ao_pattern(const struct ao_bitmap *dst, uint8_t rop); void -ao_line(const struct ao_bitmap *dst, +ao_line(struct ao_bitmap *dst, int16_t x1, int16_t y1, int16_t x2, @@ -143,7 +151,7 @@ ao_line(const struct ao_bitmap *dst, uint8_t rop); void -ao_poly(const struct ao_bitmap *dst, +ao_poly(struct ao_bitmap *dst, const struct ao_coord *coords, uint16_t ncoords, const struct ao_transform *transform, @@ -151,7 +159,7 @@ ao_poly(const struct ao_bitmap *dst, uint8_t rop); void -ao_text(const struct ao_bitmap *dst, +ao_text(struct ao_bitmap *dst, const struct ao_font *font, int16_t x, int16_t y, @@ -160,7 +168,7 @@ ao_text(const struct ao_bitmap *dst, uint8_t rop); void -ao_logo(const struct ao_bitmap *dst, +ao_logo(struct ao_bitmap *dst, const struct ao_transform *transform, const struct ao_font *font, uint32_t fill, diff --git a/src/draw/ao_draw_int.h b/src/draw/ao_draw_int.h index f353526d..cd7be34e 100644 --- a/src/draw/ao_draw_int.h +++ b/src/draw/ao_draw_int.h @@ -94,6 +94,18 @@ ao_bits_mask(int16_t x, int16_t w) { } \ } while (0) +static inline int16_t +ao_min16(int16_t a, int16_t b) +{ + return a < b ? a : b; +} + +static inline int16_t +ao_max16(int16_t a, int16_t b) +{ + return a > b ? a : b; +} + static inline uint32_t ao_do_mask_rrop(uint32_t dst, uint32_t and, uint32_t xor, uint32_t mask) { return (dst & (and | ~mask)) ^ (xor & mask); @@ -104,6 +116,16 @@ ao_do_rrop(uint32_t dst, uint32_t and, uint32_t xor) { return (dst & and) ^ xor; } +static inline void +ao_damage(struct ao_bitmap *dst, + int16_t x1, + int16_t y1, + int16_t x2, + int16_t y2) +{ + ao_box_union(&dst->damage, x1, y1, x2, y2); +} + void ao_blt(uint32_t *src_line, int16_t src_stride, diff --git a/src/draw/ao_line.c b/src/draw/ao_line.c index 10c071eb..14e1a3c1 100644 --- a/src/draw/ao_line.c +++ b/src/draw/ao_line.c @@ -12,8 +12,8 @@ * General Public License for more details. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include #define ao_mask(x,w) (ao_right(AO_ALLONES,(x) & AO_MASK) & \ ao_left(AO_ALLONES,(FB_UNIT - ((x)+(w))) & AO_MASK)) @@ -239,7 +239,7 @@ ao_clip_line(struct ao_cc *c, struct ao_cbox *b) } void -ao_line(const struct ao_bitmap *dst, +ao_line(struct ao_bitmap *dst, int16_t x1, int16_t y1, int16_t x2, @@ -325,10 +325,17 @@ ao_line(const struct ao_bitmap *dst, if (adx > ady) { x1 = clip_1.major; y1 = clip_1.minor; + x2 = clip_2.major; + y2 = clip_2.minor; } else { x1 = clip_1.minor; y1 = clip_1.major; + x2 = clip_2.minor; + y2 = clip_2.major; } + + ao_damage(dst, ao_min16(x1, x2), ao_max16(x1, x2), ao_min16(y1, y2), ao_max16(y1, y2)); + ao_bres(dst, signdx, signdy, diff --git a/src/draw/ao_logo.c b/src/draw/ao_logo.c index d2d778ae..74733276 100644 --- a/src/draw/ao_logo.c +++ b/src/draw/ao_logo.c @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao_draw.h" +#include #include "ao_logo.h" #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) void -ao_logo(const struct ao_bitmap *dst, +ao_logo(struct ao_bitmap *dst, const struct ao_transform *transform, const struct ao_font *font, uint32_t fill, diff --git a/src/draw/ao_pattern.c b/src/draw/ao_pattern.c index 892fc49f..de30c545 100644 --- a/src/draw/ao_pattern.c +++ b/src/draw/ao_pattern.c @@ -12,8 +12,8 @@ * General Public License for more details. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include static inline uint32_t ao_pattern_expand(uint8_t v, uint8_t rot) @@ -32,7 +32,7 @@ min(int a, int b) { } void -ao_pattern(const struct ao_bitmap *dst, +ao_pattern(struct ao_bitmap *dst, int16_t x, int16_t y, int16_t width, @@ -52,6 +52,8 @@ ao_pattern(const struct ao_bitmap *dst, ao_clip(y, 0, dst->height); ao_clip(y2, 0, dst->height); + ao_damage(dst, x, y, x2, y2); + if (x < x2 && y < y2) { uint8_t xrot = (x - pat_x) & 7; uint8_t yrot = (y - pat_y) & 7; diff --git a/src/draw/ao_poly.c b/src/draw/ao_poly.c index a546e043..546f0db5 100644 --- a/src/draw/ao_poly.c +++ b/src/draw/ao_poly.c @@ -16,8 +16,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include #include #include #include @@ -175,7 +175,7 @@ ao_wind(const struct ao_coord *coords, * Fill the specified polygon with non-zero winding rule */ void -ao_poly(const struct ao_bitmap *dst, +ao_poly(struct ao_bitmap *dst, const struct ao_coord *coords, uint16_t ncoords, const struct ao_transform *transform, @@ -183,6 +183,7 @@ ao_poly(const struct ao_bitmap *dst, uint8_t rop) { float y_min, y_max; + float x_min, x_max; uint16_t edge; float y; float x; @@ -193,10 +194,16 @@ ao_poly(const struct ao_bitmap *dst, transform = &ao_identity; /* - * Find the y limits of the polygon + * Find the limits of the polygon */ + x_min = x_max = _x(coords, transform, 0); y_min = y_max = _y(coords, transform, 0); for (edge = 1; edge < ncoords; edge++) { + x = _x(coords, transform, edge); + if (x < x_min) + x_min = x; + else if (x > x_max) + x_max = x; y = _y(coords, transform, edge); if (y < y_min) y_min = y; @@ -204,12 +211,18 @@ ao_poly(const struct ao_bitmap *dst, y_max = y; } + x_min = floorf(x_min); + x_max = ceilf(x_max); + ao_clip(x_min, 0, dst->width); + ao_clip(x_max, 0, dst->width); + y_min = floorf(y_min); y_max = ceilf(y_max); - ao_clip(y_min, 0, dst->height); ao_clip(y_max, 0, dst->height); + ao_damage(dst, (int16_t) x_min, (int16_t) y_min, (int16_t) x_max, (int16_t) y_max); + /* * Walk each scanline in the range and fill included spans */ diff --git a/src/draw/ao_rect.c b/src/draw/ao_rect.c index 266f1346..fadc659b 100644 --- a/src/draw/ao_rect.c +++ b/src/draw/ao_rect.c @@ -12,11 +12,11 @@ * General Public License for more details. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include void -ao_rect(const struct ao_bitmap *dst, +ao_rect(struct ao_bitmap *dst, int16_t x, int16_t y, int16_t width, @@ -32,6 +32,8 @@ ao_rect(const struct ao_bitmap *dst, ao_clip(y, 0, dst->height); ao_clip(y2, 0, dst->height); + ao_damage(dst, x, y, x2, y2); + if (x < x2 && y < y2) { ao_solid(ao_and(rop, fill), ao_xor(rop, fill), diff --git a/src/draw/ao_text.c b/src/draw/ao_text.c index cb1bc5ab..cc43b362 100644 --- a/src/draw/ao_text.c +++ b/src/draw/ao_text.c @@ -12,14 +12,14 @@ * General Public License for more details. */ -#include "ao_draw.h" -#include "ao_draw_int.h" +#include +#include #include "ao_font.h" #include #include void -ao_text(const struct ao_bitmap *dst, +ao_text(struct ao_bitmap *dst, const struct ao_font *font, int16_t x, int16_t y,