Skip to content

Commit e084a92

Browse files
authored
Merge pull request #4432 from jepler/bitmap-dirty-improvements
Bitmap dirty improvements
2 parents 4b42932 + 9b18893 commit e084a92

File tree

5 files changed

+71
-110
lines changed

5 files changed

+71
-110
lines changed

shared-module/bitmaptools/__init__.c

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16
9595
// # */
9696

9797

98-
if (self->read_only) {
99-
mp_raise_RuntimeError(translate("Read-only object"));
100-
}
101-
10298
int16_t x,y;
10399

104100
int16_t minx = dest_clip1_x;
@@ -199,14 +195,17 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16
199195
float rowu = startu + miny * duCol;
200196
float rowv = startv + miny * dvCol;
201197

198+
displayio_area_t dirty_area = {minx, miny, maxx + 1, maxy + 1};
199+
displayio_bitmap_set_dirty_area(self, &dirty_area);
200+
202201
for (y = miny; y <= maxy; y++) {
203202
float u = rowu + minx * duRow;
204203
float v = rowv + minx * dvRow;
205204
for (x = minx; x <= maxx; x++) {
206205
if (u >= source_clip0_x && u < source_clip1_x && v >= source_clip0_y && v < source_clip1_y) {
207206
uint32_t c = common_hal_displayio_bitmap_get_pixel(source, u, v);
208207
if ((skip_index_none) || (c != skip_index)) {
209-
common_hal_displayio_bitmap_set_pixel(self, x, y, c);
208+
displayio_bitmap_write_pixel(self, x, y, c);
210209
}
211210
}
212211
u += duRow;
@@ -236,34 +235,18 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination,
236235
//
237236
// input checks should ensure that x1 < x2 and y1 < y2 and are within the bitmap region
238237

239-
if (destination->read_only) {
240-
mp_raise_RuntimeError(translate("Read-only object"));
241-
}
242-
243-
// Ensure x1 < x2 and y1 < y2
244-
if (x1 > x2) {
245-
int16_t temp = x2;
246-
x2 = x1;
247-
x1 = temp;
248-
}
249-
if (y1 > y2) {
250-
int16_t temp = y2;
251-
y2 = y1;
252-
y1 = temp;
253-
}
238+
displayio_area_t area = { x1, y1, x2, y2 };
239+
displayio_area_canon(&area);
254240

255-
// constrain to bitmap dimensions
256-
x1 = constrain(x1, 0, destination->width);
257-
x2 = constrain(x2, 0, destination->width);
258-
y1 = constrain(y1, 0, destination->height);
259-
y2 = constrain(y2, 0, destination->height);
241+
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height };
242+
displayio_area_compute_overlap(&area, &bitmap_area, &area);
260243

261244
// update the dirty rectangle
262-
displayio_bitmap_set_dirty_area(destination, x1, y1, x2, y2);
245+
displayio_bitmap_set_dirty_area(destination, &area);
263246

264247
int16_t x, y;
265-
for (x = x1; x < x2; x++) {
266-
for (y = y1; y < y2; y++) {
248+
for (x = area.x1; x < area.x2; x++) {
249+
for (y = area.y1; y < area.y2; y++) {
267250
displayio_bitmap_write_pixel(destination, x, y, value);
268251
}
269252
}
@@ -274,10 +257,6 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
274257
int16_t x1, int16_t y1,
275258
uint32_t value) {
276259

277-
if (destination->read_only) {
278-
mp_raise_RuntimeError(translate("Read-only object"));
279-
}
280-
281260
//
282261
// adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line
283262
//
@@ -298,13 +277,11 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
298277
ybb0 = y1;
299278
ybb1 = y0 + 1;
300279
}
280+
displayio_area_t area = { xbb0, ybb0, xbb1, ybb1 };
281+
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height };
282+
displayio_area_compute_overlap(&area, &bitmap_area, &area);
301283

302-
xbb0 = constrain(xbb0, 0, destination->width);
303-
xbb1 = constrain(xbb1, 0, destination->width);
304-
ybb0 = constrain(ybb0, 0, destination->height);
305-
ybb1 = constrain(ybb1, 0, destination->height);
306-
307-
displayio_bitmap_set_dirty_area(destination, xbb0, ybb0, xbb1, ybb1);
284+
displayio_bitmap_set_dirty_area(destination, &area);
308285

309286
int16_t temp, x, y;
310287

@@ -401,15 +378,15 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int
401378
}
402379
}
403380
}
404-
displayio_bitmap_set_dirty_area(self, x1, y1, x2, y2);
381+
displayio_area_t area = { x1, y1, x2, y2 };
382+
displayio_bitmap_set_dirty_area(self, &area);
405383
}
406384

407385
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes, bool reverse_rows) {
408386
uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1;
409387

410-
if (self->read_only) {
411-
mp_raise_RuntimeError(translate("Read-only object"));
412-
}
388+
displayio_area_t a = {0, 0, self->width, self->height};
389+
displayio_bitmap_set_dirty_area(self, &a);
413390

414391
size_t elements_per_row = (self->width * bits_per_pixel + element_size * 8 - 1) / (element_size * 8);
415392
size_t rowsize = element_size * elements_per_row;
@@ -486,6 +463,4 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f
486463
displayio_bitmap_write_pixel(self, x, y_draw, value & mask);
487464
}
488465
}
489-
490-
displayio_bitmap_set_dirty_area(self, 0, 0, self->width, self->height);
491466
}

shared-module/displayio/Bitmap.c

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -105,41 +105,16 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
105105
return 0;
106106
}
107107

108-
void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
109-
// Update the bitmap's dirty region with the rectangle bounded by (x1,y1) and (x2, y2)
110-
111-
// Arrange x1 < x2, y1 < y2
112-
if (x1 > x2) {
113-
int16_t temp = x1;
114-
x1 = x2;
115-
x2 = temp;
116-
}
117-
if (y1 > y2) {
118-
int16_t temp = y1;
119-
y1 = y2;
120-
y2 = temp;
108+
void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, const displayio_area_t *dirty_area) {
109+
if (self->read_only) {
110+
mp_raise_RuntimeError(translate("Read-only object"));
121111
}
122112

123-
// Update the dirty area.
124-
if (self->dirty_area.x1 == self->dirty_area.x2) {
125-
self->dirty_area.x1 = x1;
126-
self->dirty_area.x2 = x2;
127-
self->dirty_area.y1 = y1;
128-
self->dirty_area.y2 = y2;
129-
} else {
130-
if (x1 < self->dirty_area.x1) {
131-
self->dirty_area.x1 = x1;
132-
}
133-
if (x2 > self->dirty_area.x2) {
134-
self->dirty_area.x2 = x2;
135-
}
136-
if (y1 < self->dirty_area.y1) {
137-
self->dirty_area.y1 = y1;
138-
}
139-
if (y2 > self->dirty_area.y2) {
140-
self->dirty_area.y2 = y2;
141-
}
142-
}
113+
displayio_area_t area = *dirty_area;
114+
displayio_area_canon(&area);
115+
displayio_area_union(&area, &self->dirty_area, &area);
116+
displayio_area_t bitmap_area = {0, 0, self->width, self->height};
117+
displayio_area_compute_overlap(&area, &bitmap_area, &self->dirty_area);
143118
}
144119

145120
void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
@@ -175,10 +150,6 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16
175150
// If skip_value is `None`, then all pixels are copied.
176151
// This function assumes input checks were performed for pixel index entries.
177152

178-
if (self->read_only) {
179-
mp_raise_RuntimeError(translate("Read-only object"));
180-
}
181-
182153
// Update the dirty area
183154
int16_t dirty_x_max = (x + (x2 - x1));
184155
if (dirty_x_max > self->width) {
@@ -189,7 +160,8 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16
189160
dirty_y_max = self->height;
190161
}
191162

192-
displayio_bitmap_set_dirty_area(self, x, y, dirty_x_max, dirty_y_max);
163+
displayio_area_t a = { x, y, dirty_x_max, dirty_y_max};
164+
displayio_bitmap_set_dirty_area(self, &a);
193165

194166
bool x_reverse = false;
195167
bool y_reverse = false;
@@ -226,12 +198,9 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16
226198
}
227199

228200
void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
229-
if (self->read_only) {
230-
mp_raise_RuntimeError(translate("Read-only object"));
231-
}
232-
233201
// update the dirty region
234-
displayio_bitmap_set_dirty_area(self, x, y, x + 1, y + 1);
202+
displayio_area_t a = {x, y, x + 1, y + 1};
203+
displayio_bitmap_set_dirty_area(self, &a);
235204

236205
// write the pixel
237206
displayio_bitmap_write_pixel(self, x, y, value);
@@ -252,14 +221,8 @@ void displayio_bitmap_finish_refresh(displayio_bitmap_t *self) {
252221
}
253222

254223
void common_hal_displayio_bitmap_fill(displayio_bitmap_t *self, uint32_t value) {
255-
if (self->read_only) {
256-
mp_raise_RuntimeError(translate("Read-only object"));
257-
}
258-
// Update the dirty area.
259-
self->dirty_area.x1 = 0;
260-
self->dirty_area.x2 = self->width;
261-
self->dirty_area.y1 = 0;
262-
self->dirty_area.y2 = self->height;
224+
displayio_area_t a = {0, 0, self->width, self->height};
225+
displayio_bitmap_set_dirty_area(self, &a);
263226

264227
// build the packed word
265228
uint32_t word = 0;

shared-module/displayio/Bitmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ typedef struct {
4949

5050
void displayio_bitmap_finish_refresh(displayio_bitmap_t *self);
5151
displayio_area_t *displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t *tail);
52-
void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
52+
void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, const displayio_area_t *area);
5353
void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value);
5454

5555
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H

shared-module/displayio/__init__.c

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -309,26 +309,46 @@ bool displayio_area_compute_overlap(const displayio_area_t *a,
309309
return true;
310310
}
311311

312+
void displayio_copy_coords(const displayio_area_t *src, displayio_area_t *dest) {
313+
dest->x1 = src->x1;
314+
dest->y1 = src->y1;
315+
dest->x2 = src->x2;
316+
dest->y2 = src->y2;
317+
}
318+
319+
bool displayio_area_empty(const displayio_area_t *a) {
320+
return (a->x1 == a->x2) || (a->y1 == a->y2);
321+
}
322+
323+
void displayio_area_canon(displayio_area_t *a) {
324+
if (a->x1 > a->x2) {
325+
int16_t t = a->x1;
326+
a->x1 = a->x2;
327+
a->x2 = t;
328+
}
329+
if (a->y1 > a->y2) {
330+
int16_t t = a->y1;
331+
a->y1 = a->y2;
332+
a->y2 = t;
333+
}
334+
}
335+
312336
void displayio_area_union(const displayio_area_t *a,
313337
const displayio_area_t *b,
314338
displayio_area_t *u) {
315-
u->x1 = a->x1;
316-
if (b->x1 < u->x1) {
317-
u->x1 = b->x1;
318-
}
319-
u->x2 = a->x2;
320-
if (b->x2 > u->x2) {
321-
u->x2 = b->x2;
322-
}
323339

324-
u->y1 = a->y1;
325-
if (b->y1 < u->y1) {
326-
u->y1 = b->y1;
340+
if (displayio_area_empty(a)) {
341+
displayio_copy_coords(b, u);
342+
return;
327343
}
328-
u->y2 = a->y2;
329-
if (b->y2 > u->y2) {
330-
u->y2 = b->y2;
344+
if (displayio_area_empty(b)) {
345+
displayio_copy_coords(a, u);
346+
return;
331347
}
348+
u->x1 = MIN(a->x1, b->x1);
349+
u->y1 = MIN(a->y1, b->y1);
350+
u->x2 = MAX(a->x2, b->x2);
351+
u->y2 = MAX(a->y2, b->y2);
332352
}
333353

334354
uint16_t displayio_area_width(const displayio_area_t *area) {

shared-module/displayio/area.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ typedef struct {
5353

5454
extern displayio_buffer_transform_t null_transform;
5555

56+
bool displayio_area_empty(const displayio_area_t *a);
57+
void displayio_area_copy_coords(const displayio_area_t *src, displayio_area_t *dest);
58+
void displayio_area_canon(displayio_area_t *a);
5659
void displayio_area_union(const displayio_area_t *a,
5760
const displayio_area_t *b,
5861
displayio_area_t *u);

0 commit comments

Comments
 (0)