Skip to content

Commit d4bf0d5

Browse files
authored
Merge pull request #4258 from jepler/pixelbuf-brightness-performance
_pixelbuf: Increase performance of brightness-scaling
2 parents bbe0602 + dac4ac5 commit d4bf0d5

File tree

2 files changed

+48
-33
lines changed

2 files changed

+48
-33
lines changed

shared-module/_pixelbuf/PixelBuf.c

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "py/runtime.h"
3232
#include "shared-bindings/_pixelbuf/PixelBuf.h"
3333
#include <string.h>
34+
#include <math.h>
3435

3536
// Helper to ensure we have the native super class instead of a subclass.
3637
static pixelbuf_pixelbuf_obj_t* native_pixelbuf(mp_obj_t pixelbuf_obj) {
@@ -69,6 +70,7 @@ void common_hal__pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size
6970
}
7071
// Call set_brightness so that it can allocate a second buffer if needed.
7172
self->brightness = 1.0;
73+
self->scaled_brightness = 0x100;
7274
common_hal__pixelbuf_pixelbuf_set_brightness(MP_OBJ_FROM_PTR(self), brightness);
7375

7476
// Turn on auto_write. We don't want to do it with the above brightness call.
@@ -109,26 +111,32 @@ void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t b
109111
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
110112
// Skip out if the brightness is already set. The default of self->brightness is 1.0. So, this
111113
// also prevents the pre_brightness_buffer allocation when brightness is set to 1.0 again.
112-
mp_float_t change = brightness - self->brightness;
113-
if (-0.001 < change && change < 0.001) {
114+
self->brightness = brightness;
115+
// Use 256 steps of brightness so that we can do integer math below.
116+
uint16_t new_scaled_brightness = (uint16_t)(brightness * 256);
117+
if (new_scaled_brightness == self->scaled_brightness) {
114118
return;
115119
}
116-
self->brightness = brightness;
120+
self->scaled_brightness = new_scaled_brightness;
117121
size_t pixel_len = self->pixel_count * self->bytes_per_pixel;
118-
if (self->pre_brightness_buffer == NULL) {
119-
self->pre_brightness_buffer = m_malloc(pixel_len, false);
120-
memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len);
121-
}
122-
for (size_t i = 0; i < pixel_len; i++) {
123-
// Don't adjust per-pixel luminance bytes in dotstar mode
124-
if (self->byteorder.is_dotstar && i % 4 == 0) {
125-
continue;
122+
if (self->scaled_brightness == 0x100 && !self->pre_brightness_buffer) {
123+
return;
124+
} else {
125+
if (self->pre_brightness_buffer == NULL) {
126+
self->pre_brightness_buffer = m_malloc(pixel_len, false);
127+
memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len);
128+
}
129+
for (size_t i = 0; i < pixel_len; i++) {
130+
// Don't adjust per-pixel luminance bytes in dotstar mode
131+
if (self->byteorder.is_dotstar && i % 4 == 0) {
132+
continue;
133+
}
134+
self->post_brightness_buffer[i] = (self->pre_brightness_buffer[i] * self->scaled_brightness) / 256;
126135
}
127-
self->post_brightness_buffer[i] = self->pre_brightness_buffer[i] * self->brightness;
128-
}
129136

130-
if (self->auto_write) {
131-
common_hal__pixelbuf_pixelbuf_show(self_in);
137+
if (self->auto_write) {
138+
common_hal__pixelbuf_pixelbuf_show(self_in);
139+
}
132140
}
133141
}
134142

@@ -197,28 +205,34 @@ void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint
197205
}
198206
pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder;
199207
size_t offset = index * self->bytes_per_pixel;
200-
if (self->pre_brightness_buffer != NULL) {
201-
uint8_t* pre_brightness_buffer = self->pre_brightness_buffer + offset;
202-
if (self->bytes_per_pixel == 4) {
203-
pre_brightness_buffer[rgbw_order->w] = w;
204-
}
205-
206-
pre_brightness_buffer[rgbw_order->r] = r;
207-
pre_brightness_buffer[rgbw_order->g] = g;
208-
pre_brightness_buffer[rgbw_order->b] = b;
208+
uint8_t *scaled_buffer, *unscaled_buffer;
209+
if (self->pre_brightness_buffer) {
210+
scaled_buffer = self->post_brightness_buffer + offset;
211+
unscaled_buffer = self->pre_brightness_buffer + offset;
212+
} else {
213+
scaled_buffer = NULL;
214+
unscaled_buffer = self->post_brightness_buffer + offset;
209215
}
210216

211-
uint8_t* post_brightness_buffer = self->post_brightness_buffer + offset;
212217
if (self->bytes_per_pixel == 4) {
213-
// Only apply brightness if w is actually white (aka not DotStar.)
214-
if (!self->byteorder.is_dotstar) {
215-
w *= self->brightness;
218+
unscaled_buffer[rgbw_order->w] = w;
219+
}
220+
221+
unscaled_buffer[rgbw_order->r] = r;
222+
unscaled_buffer[rgbw_order->g] = g;
223+
unscaled_buffer[rgbw_order->b] = b;
224+
225+
if (scaled_buffer) {
226+
if (self->bytes_per_pixel == 4) {
227+
if (!self->byteorder.is_dotstar) {
228+
w = (w * self->scaled_brightness) / 256;
229+
}
230+
scaled_buffer[rgbw_order->w] = w;
216231
}
217-
post_brightness_buffer[rgbw_order->w] = w;
232+
scaled_buffer[rgbw_order->r] = (r * self->scaled_brightness) / 256;
233+
scaled_buffer[rgbw_order->g] = (g * self->scaled_brightness) / 256;
234+
scaled_buffer[rgbw_order->b] = (b * self->scaled_brightness) / 256;
218235
}
219-
post_brightness_buffer[rgbw_order->r] = r * self->brightness;
220-
post_brightness_buffer[rgbw_order->g] = g * self->brightness;
221-
post_brightness_buffer[rgbw_order->b] = b * self->brightness;
222236
}
223237

224238
void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t value) {

shared-module/_pixelbuf/PixelBuf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ typedef struct {
4949
typedef struct {
5050
mp_obj_base_t base;
5151
size_t pixel_count;
52-
size_t bytes_per_pixel;
52+
uint16_t bytes_per_pixel;
53+
uint16_t scaled_brightness;
5354
pixelbuf_byteorder_details_t byteorder;
5455
mp_float_t brightness;
5556
mp_obj_t transmit_buffer_obj;

0 commit comments

Comments
 (0)