altos/draw: Add damage tracking
authorKeith Packard <keithp@keithp.com>
Mon, 27 Feb 2023 22:35:36 +0000 (14:35 -0800)
committerKeith Packard <keithp@keithp.com>
Mon, 27 Feb 2023 22:39:39 +0000 (14:39 -0800)
This will allow more efficient updating of the screen

Signed-off-by: Keith Packard <keithp@keithp.com>
13 files changed:
src/draw/Makefile
src/draw/ao_blt.c
src/draw/ao_box.c [new file with mode: 0644]
src/draw/ao_box.h [new file with mode: 0644]
src/draw/ao_copy.c
src/draw/ao_draw.h
src/draw/ao_draw_int.h
src/draw/ao_line.c
src/draw/ao_logo.c
src/draw/ao_pattern.c
src/draw/ao_poly.c
src/draw/ao_rect.c
src/draw/ao_text.c

index f5969f26bde0e83b23819d0369e4c9195ecc56e3..93c10e42381721b360505c642c99d9bc5eaaa5f0 100644 (file)
@@ -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 \
index 951a4a1484eeb6262478d69fe1bbb2717f996ee5..10435d4f3e857bf52ebe68b142904c04564032a5 100644 (file)
@@ -12,8 +12,8 @@
  * General Public License for more details.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 
 #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 (file)
index 0000000..173b720
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2023 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <ao_box.h>
+
+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 (file)
index 0000000..bd3aabd
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2023 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <stdint.h>
+#include <stdbool.h>
+
+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_ */
index 312d1d72bc9603ed26f155b527f0de495ccab369..a506aed7737b203fefe17e919e0fe89bf0eddeb8 100644 (file)
@@ -12,8 +12,8 @@
  * General Public License for more details.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 
 #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,
index b4ca6eacc64c106ac74cf1088da764150aa541b1..29afef9cb043fa3189c6c410ef4bac4e1ed6c325 100644 (file)
 #include <stdint.h>
 #include <stdbool.h>
 #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,
index f353526d338be7558909cce1f2ec416eba7283f3..cd7be34eb5e8b427e5d9c4c10b9965e726161337 100644 (file)
@@ -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,
index 10c071eb4bdbc3cd77931231e937ff3dde39f0d4..14e1a3c1a591aec6b2cdc5341e08f57d2e01fca2 100644 (file)
@@ -12,8 +12,8 @@
  * General Public License for more details.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 
 #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,
index d2d778ae34067e3fbe2faccd326429fa40aeda72..747332765839ba05bd3da05b4176ecd6a5614685 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao_draw.h"
+#include <ao_draw.h>
 #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,
index 892fc49fb58e5ceca084e402a5f96b1e31070bc7..de30c5452ae3b338cea8d8422f0773fd89e0d23a 100644 (file)
@@ -12,8 +12,8 @@
  * General Public License for more details.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 
 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;
index a546e04341cc680392b192137d01efc09b8ee960..546f0db5ab71685d25490673862f15c0879d38fc 100644 (file)
@@ -16,8 +16,8 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 #include <stdio.h>
 #include <math.h>
 #include <float.h>
@@ -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 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
         */
index 266f13461e253062c4edbeaa80c7a9d65f45e196..fadc659ba3ca75973b60e69435d68c59103bc7b0 100644 (file)
  * General Public License for more details.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 
 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),
index cb1bc5abce72380b61af9026d7c15f6940370749..cc43b362cdde9e43d8d142e90fafe486e05e1cc5 100644 (file)
  * General Public License for more details.
  */
 
-#include "ao_draw.h"
-#include "ao_draw_int.h"
+#include <ao_draw.h>
+#include <ao_draw_int.h>
 #include "ao_font.h"
 #include <string.h>
 #include <stdio.h>
 
 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,