PicoGraphics: Layers.

Add preliminary support for multiple layered drawing surfaces.

Allows, for example, static content to be loaded into one layer and
remain unmodified while the above layer contains animations.

Particularly useful for drawing PNG or JPEG UI elements which are
then overdrawn with text or animated elements, without paying the
cost of loading/decoding every frame.
pull/1064/head
Phil Howard 2024-10-07 14:36:06 +01:00
rodzic 575e3a17bc
commit e46fec7902
16 zmienionych plików z 193 dodań i 113 usunięć

Wyświetl plik

@ -165,21 +165,17 @@ namespace pimoroni {
// Native 16-bit framebuffer update
void ST7735::update(PicoGraphics *graphics) {
if(graphics->pen_type == PicoGraphics::PEN_RGB565) {
command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)graphics->frame_buffer);
} else {
command(reg::RAMWR);
gpio_put(dc, 1); // data mode
gpio_put(cs, 0);
command(reg::RAMWR);
gpio_put(dc, 1); // data mode
gpio_put(cs, 0);
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
if (length > 0) {
spi_write_blocking(spi, (const uint8_t*)data, length);
}
});
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
if (length > 0) {
spi_write_blocking(spi, (const uint8_t*)data, length);
}
});
gpio_put(cs, 1);
}
gpio_put(cs, 1);
}
void ST7735::set_backlight(uint8_t brightness) {

Wyświetl plik

@ -282,30 +282,26 @@ namespace pimoroni {
void ST7789::update(PicoGraphics *graphics) {
uint8_t cmd = reg::RAMWR;
if(graphics->pen_type == PicoGraphics::PEN_RGB565) { // Display buffer is screen native
command(cmd, width * height * sizeof(uint16_t), (const char*)graphics->frame_buffer);
} else {
gpio_put(dc, 0); // command mode
gpio_put(cs, 0);
if(spi) { // SPI Bus
spi_write_blocking(spi, &cmd, 1);
} else { // Parallel Bus
write_blocking_parallel(&cmd, 1);
}
gpio_put(dc, 1); // data mode
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
if (length > 0) {
write_blocking_dma((const uint8_t*)data, length);
}
else {
dma_channel_wait_for_finish_blocking(st_dma);
}
});
gpio_put(cs, 1);
gpio_put(dc, 0); // command mode
gpio_put(cs, 0);
if(spi) { // SPI Bus
spi_write_blocking(spi, &cmd, 1);
} else { // Parallel Bus
write_blocking_parallel(&cmd, 1);
}
gpio_put(dc, 1); // data mode
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
if (length > 0) {
write_blocking_dma((const uint8_t*)data, length);
}
else {
dma_channel_wait_for_finish_blocking(st_dma);
}
});
gpio_put(cs, 1);
}
void ST7789::set_backlight(uint8_t brightness) {

Wyświetl plik

@ -19,6 +19,13 @@ namespace pimoroni {
RGB* PicoGraphics::get_palette() {return nullptr;}
bool PicoGraphics::supports_alpha_blend() {return false;}
void PicoGraphics::set_layer(uint l) {
this->layer = l;
};
uint PicoGraphics::get_layer() {
return this->layer;
};
void PicoGraphics::set_dimensions(int width, int height) {
bounds = clip = {0, 0, width, height};
}

Wyświetl plik

@ -226,6 +226,9 @@ namespace pimoroni {
Rect clip;
uint thickness = 1;
uint layers = 1;
uint layer = 0;
typedef std::function<void(void *data, size_t length)> conversion_callback_func;
typedef std::function<RGB565()> next_pixel_func;
typedef std::function<RGB888()> next_pixel_func_rgb888;
@ -270,6 +273,12 @@ namespace pimoroni {
PicoGraphics(uint16_t width, uint16_t height, void *frame_buffer)
: frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height) {
set_font(&font6);
layers = 1;
};
PicoGraphics(uint16_t width, uint16_t height, uint16_t layers, void *frame_buffer)
: frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height), layers(layers) {
set_font(&font6);
};
virtual void set_pen(uint c) = 0;
@ -278,6 +287,9 @@ namespace pimoroni {
virtual void set_pixel_span(const Point &p, uint l) = 0;
void set_thickness(uint t);
void set_layer(uint l);
uint get_layer();
virtual int get_palette_size();
virtual RGB* get_palette();
virtual bool supports_alpha_blend();
@ -330,7 +342,7 @@ namespace pimoroni {
public:
uint8_t color;
PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
@ -346,7 +358,7 @@ namespace pimoroni {
public:
uint8_t color;
PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
@ -387,7 +399,7 @@ namespace pimoroni {
bool cache_built = false;
std::array<uint8_t, 16> candidates;
PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
@ -420,7 +432,7 @@ namespace pimoroni {
bool cache_built = false;
std::array<uint8_t, 16> candidates;
PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override;
@ -453,7 +465,7 @@ namespace pimoroni {
bool cache_built = false;
std::array<uint8_t, 16> candidates;
PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override;
@ -478,7 +490,7 @@ namespace pimoroni {
class PicoGraphics_PenRGB332 : public PicoGraphics {
public:
RGB332 color;
PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
@ -503,7 +515,7 @@ namespace pimoroni {
public:
RGB src_color;
RGB565 color;
PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
@ -516,13 +528,15 @@ namespace pimoroni {
static size_t buffer_size(uint w, uint h) {
return w * h * sizeof(RGB565);
}
void frame_convert(PenType type, conversion_callback_func callback) override;
};
class PicoGraphics_PenRGB888 : public PicoGraphics {
public:
RGB src_color;
RGB888 color;
PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer);
PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
@ -600,7 +614,7 @@ namespace pimoroni {
uint color;
IDirectDisplayDriver<uint8_t> &driver;
PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver<uint8_t> &direct_display_driver);
PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver<uint8_t> &direct_display_driver, uint16_t layers = 1);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;

Wyświetl plik

@ -2,11 +2,11 @@
namespace pimoroni {
PicoGraphics_Pen1Bit::PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_Pen1Bit::PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_1BIT;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height) * layers]);
}
}

Wyświetl plik

@ -2,8 +2,8 @@
namespace pimoroni {
PicoGraphics_Pen1BitY::PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_Pen1BitY::PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_1BIT;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);

Wyświetl plik

@ -2,8 +2,8 @@
namespace pimoroni {
PicoGraphics_Pen3Bit::PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_Pen3Bit::PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_3BIT;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);

Wyświetl plik

@ -1,8 +1,8 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_PenInky7::PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver<uint8_t> &direct_display_driver)
: PicoGraphics(width, height, nullptr),
PicoGraphics_PenInky7::PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver<uint8_t> &direct_display_driver, uint16_t layers)
: PicoGraphics(width, height, layers, nullptr),
driver(direct_display_driver) {
this->pen_type = PEN_INKY7;
}

Wyświetl plik

@ -2,8 +2,8 @@
namespace pimoroni {
PicoGraphics_PenP4::PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_PenP4::PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_P4;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);

Wyświetl plik

@ -1,8 +1,8 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_PenP8::PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_PenP8::PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_P8;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);

Wyświetl plik

@ -2,11 +2,11 @@
#include <string.h>
namespace pimoroni {
PicoGraphics_PenRGB332::PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_PenRGB332::PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_RGB332;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height) * layers]);
}
}
void PicoGraphics_PenRGB332::set_pen(uint c) {
@ -23,12 +23,14 @@ namespace pimoroni {
}
void PicoGraphics_PenRGB332::set_pixel(const Point &p) {
uint8_t *buf = (uint8_t *)frame_buffer;
buf += buffer_size(this->bounds.w, this->bounds.h) * layer;
buf[p.y * bounds.w + p.x] = color;
}
void PicoGraphics_PenRGB332::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint8_t *buf = (uint8_t *)frame_buffer;
buf = &buf[p.y * bounds.w + p.x];
buf += buffer_size(this->bounds.w, this->bounds.h) * layer;
buf += p.y * bounds.w + p.x;
while(l--) {
*buf++ = color;
@ -38,6 +40,7 @@ namespace pimoroni {
if(!bounds.contains(p)) return;
uint8_t *buf = (uint8_t *)frame_buffer;
buf += buffer_size(this->bounds.w, this->bounds.h) * layer;
RGB332 blended = RGB(buf[p.y * bounds.w + p.x]).blend(RGB(color), a).to_rgb332();
@ -96,9 +99,20 @@ namespace pimoroni {
// Treat our void* frame_buffer as uint8_t
uint8_t *src = (uint8_t *)frame_buffer;
frame_convert_rgb565(callback, [&]() {
return rgb332_to_rgb565_lut[*src++];
});
if(this->layers > 1) {
// Assume only two layers for now
uint8_t *src_layer2 = src + buffer_size(this->bounds.w, this->bounds.h);
frame_convert_rgb565(callback, [&]() {
RGB565 c1 = rgb332_to_rgb565_lut[*src++];
RGB565 c2 = rgb332_to_rgb565_lut[*src_layer2++];
return c2 ? c2 : c1;
});
} else {
frame_convert_rgb565(callback, [&]() {
return rgb332_to_rgb565_lut[*src++];
});
}
}
}
void PicoGraphics_PenRGB332::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) {

Wyświetl plik

@ -1,8 +1,8 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_PenRGB565::PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_PenRGB565::PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_RGB565;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);
@ -23,11 +23,15 @@ namespace pimoroni {
}
void PicoGraphics_PenRGB565::set_pixel(const Point &p) {
uint16_t *buf = (uint16_t *)frame_buffer;
// We can't use buffer_size because our pointer is uint16_t
buf += this->bounds.w * this->bounds.h * layer;
buf[p.y * bounds.w + p.x] = color;
}
void PicoGraphics_PenRGB565::set_pixel_span(const Point &p, uint l) {
// pointer to byte in framebuffer that contains this pixel
uint16_t *buf = (uint16_t *)frame_buffer;
// We can't use buffer_size because our pointer is uint16_t
buf += this->bounds.w * this->bounds.h * layer;
buf = &buf[p.y * bounds.w + p.x];
while(l--) {
@ -35,26 +39,50 @@ namespace pimoroni {
}
}
void PicoGraphics_PenRGB565::frame_convert(PenType type, conversion_callback_func callback) {
if(type == PEN_RGB565) {
// Treat our void* frame_buffer as uint8_t
uint16_t *src = (uint16_t *)frame_buffer;
void PicoGraphics_PenRGB565::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) {
//int sprite_x = (sprite & 0x0f) << 3;
//int sprite_y = (sprite & 0xf0) >> 1;
Point s {
sprite.x << 3,
sprite.y << 3
};
RGB565 *ptr = (RGB565 *)data;
Point o = {0, 0};
for(o.y = 0; o.y < 8 * scale; o.y++) {
Point so = {
0,
o.y / scale
};
for(o.x = 0; o.x < 8 * scale; o.x++) {
so.x = o.x / scale;
color = ptr[(s.y + so.y) * 128 + (s.x + so.x)];
if(color != transparent) pixel(dest + o);
}
}
}
if(layers > 1) {
// Assume only two layers for now
uint16_t *src_layer2 = src;
// We can't use buffer_size because our pointer is uint16_t
src_layer2 += this->bounds.w * this->bounds.h * layer;
frame_convert_rgb565(callback, [&]() {
RGB565 c1 = *src++;
RGB565 c2 = *src_layer2++;
return c2 ? c2 : c1;
});
} else {
frame_convert_rgb565(callback, [&]() {
return *src++;
});
}
}
}
void PicoGraphics_PenRGB565::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) {
//int sprite_x = (sprite & 0x0f) << 3;
//int sprite_y = (sprite & 0xf0) >> 1;
Point s {
sprite.x << 3,
sprite.y << 3
};
RGB565 *ptr = (RGB565 *)data;
Point o = {0, 0};
for(o.y = 0; o.y < 8 * scale; o.y++) {
Point so = {
0,
o.y / scale
};
for(o.x = 0; o.x < 8 * scale; o.x++) {
so.x = o.x / scale;
color = ptr[(s.y + so.y) * 128 + (s.x + so.x)];
if(color != transparent) pixel(dest + o);
}
}
}
}

Wyświetl plik

@ -1,8 +1,8 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_PenRGB888::PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
PicoGraphics_PenRGB888::PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers)
: PicoGraphics(width, height, layers, frame_buffer) {
this->pen_type = PEN_RGB888;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);

Wyświetl plik

@ -24,6 +24,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_obj, 4, 4, ModPic
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_hsv_obj, 4, 4, ModPicoGraphics_create_pen_hsv);
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_thickness_obj, ModPicoGraphics_set_thickness);
// Layers
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_layer_obj, ModPicoGraphics_set_layer);
// Primitives
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_set_clip_obj, 5, 5, ModPicoGraphics_set_clip);
MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_remove_clip_obj, ModPicoGraphics_remove_clip);
@ -60,6 +63,8 @@ static const mp_rom_map_elem_t ModPicoGraphics_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_thickness), MP_ROM_PTR(&ModPicoGraphics_set_thickness_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&ModPicoGraphics_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_layer), MP_ROM_PTR(&ModPicoGraphics_set_layer_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&ModPicoGraphics_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_partial_update), MP_ROM_PTR(&ModPicoGraphics_partial_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_update_speed), MP_ROM_PTR(&ModPicoGraphics_set_update_speed_obj) },

Wyświetl plik

@ -254,24 +254,24 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height,
return true;
}
size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint height) {
size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint height, uint layers) {
switch(pen_type) {
case PEN_1BIT:
return PicoGraphics_Pen1Bit::buffer_size(width, height);
return PicoGraphics_Pen1Bit::buffer_size(width, height) * layers;
case PEN_3BIT:
return PicoGraphics_Pen3Bit::buffer_size(width, height);
return PicoGraphics_Pen3Bit::buffer_size(width, height) * layers;
case PEN_P4:
return PicoGraphics_PenP4::buffer_size(width, height);
return PicoGraphics_PenP4::buffer_size(width, height) * layers;
case PEN_P8:
return PicoGraphics_PenP8::buffer_size(width, height);
return PicoGraphics_PenP8::buffer_size(width, height) * layers;
case PEN_RGB332:
return PicoGraphics_PenRGB332::buffer_size(width, height);
return PicoGraphics_PenRGB332::buffer_size(width, height) * layers;
case PEN_RGB565:
return PicoGraphics_PenRGB565::buffer_size(width, height);
return PicoGraphics_PenRGB565::buffer_size(width, height) * layers;
case PEN_RGB888:
return PicoGraphics_PenRGB888::buffer_size(width, height);
return PicoGraphics_PenRGB888::buffer_size(width, height) * layers;
case PEN_INKY7:
return PicoGraphics_PenInky7::buffer_size(width, height);
return PicoGraphics_PenInky7::buffer_size(width, height) * layers;
default:
return 0;
}
@ -280,7 +280,7 @@ size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint h
mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
ModPicoGraphics_obj_t *self = nullptr;
enum { ARG_display, ARG_rotate, ARG_bus, ARG_buffer, ARG_pen_type, ARG_extra_pins, ARG_i2c_address };
enum { ARG_display, ARG_rotate, ARG_bus, ARG_buffer, ARG_pen_type, ARG_extra_pins, ARG_i2c_address, ARG_layers };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_display, MP_ARG_INT | MP_ARG_REQUIRED },
{ MP_QSTR_rotate, MP_ARG_INT, { .u_int = -1 } },
@ -289,6 +289,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
{ MP_QSTR_pen_type, MP_ARG_INT, { .u_int = -1 } },
{ MP_QSTR_extra_pins, MP_ARG_OBJ, { .u_obj = mp_const_none } },
{ MP_QSTR_i2c_address, MP_ARG_INT, { .u_int = -1 } },
{ MP_QSTR_layers, MP_ARG_INT, { .u_int = 1 } },
};
// Parse args.
@ -304,6 +305,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
int height = 0;
int pen_type = args[ARG_pen_type].u_int;
int rotate = args[ARG_rotate].u_int;
int layers = args[ARG_layers].u_int;
PicoGraphicsBusType bus_type = BUS_SPI;
if(!get_display_settings(display, width, height, rotate, pen_type, bus_type)) mp_raise_ValueError("Unsupported display!");
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
@ -395,7 +397,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
}
// Create or fetch buffer
size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height);
size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height, layers);
if(required_size == 0) mp_raise_ValueError("Unsupported pen type!");
if(pen_type == PEN_INKY7) {
@ -418,31 +420,31 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
switch((PicoGraphicsPenType)pen_type) {
case PEN_1BIT:
if (display == DISPLAY_INKY_PACK) {
self->graphics = m_new_class(PicoGraphics_Pen1BitY, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_Pen1BitY, self->display->width, self->display->height, self->buffer, layers);
} else {
self->graphics = m_new_class(PicoGraphics_Pen1Bit, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_Pen1Bit, self->display->width, self->display->height, self->buffer, layers);
}
break;
case PEN_3BIT:
self->graphics = m_new_class(PicoGraphics_Pen3Bit, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_Pen3Bit, self->display->width, self->display->height, self->buffer, layers);
break;
case PEN_P4:
self->graphics = m_new_class(PicoGraphics_PenP4, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_PenP4, self->display->width, self->display->height, self->buffer, layers);
break;
case PEN_P8:
self->graphics = m_new_class(PicoGraphics_PenP8, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_PenP8, self->display->width, self->display->height, self->buffer, layers);
break;
case PEN_RGB332:
self->graphics = m_new_class(PicoGraphics_PenRGB332, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_PenRGB332, self->display->width, self->display->height, self->buffer, layers);
break;
case PEN_RGB565:
self->graphics = m_new_class(PicoGraphics_PenRGB565, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_PenRGB565, self->display->width, self->display->height, self->buffer, layers);
break;
case PEN_RGB888:
self->graphics = m_new_class(PicoGraphics_PenRGB888, self->display->width, self->display->height, self->buffer);
self->graphics = m_new_class(PicoGraphics_PenRGB888, self->display->width, self->display->height, self->buffer, layers);
break;
case PEN_INKY7:
self->graphics = m_new_class(PicoGraphics_PenInky7, self->display->width, self->display->height, *(IDirectDisplayDriver<uint8_t> *)self->buffer);
self->graphics = m_new_class(PicoGraphics_PenInky7, self->display->width, self->display->height, *(IDirectDisplayDriver<uint8_t> *)self->buffer, layers);
break;
default:
break;
@ -453,8 +455,15 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
self->spritedata = nullptr;
// Clear the buffer
self->graphics->set_layer(0);
self->graphics->set_pen(0);
self->graphics->clear();
if(layers > 1) {
self->graphics->set_layer(1);
self->graphics->set_pen(0);
self->graphics->clear();
self->graphics->set_layer(0);
}
// Update the LCD from the graphics library
if (display != DISPLAY_INKY_FRAME && display != DISPLAY_INKY_FRAME_4 && display != DISPLAY_INKY_PACK && display != DISPLAY_INKY_FRAME_7) {
@ -477,7 +486,7 @@ mp_obj_t ModPicoGraphics_set_spritesheet(mp_obj_t self_in, mp_obj_t spritedata)
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(spritedata, &bufinfo, MP_BUFFER_RW);
int required_size = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, 128, 128);
int required_size = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, 128, 128, 1);
if(bufinfo.len != (size_t)(required_size)) {
mp_raise_ValueError("Spritesheet the wrong size!");
@ -562,7 +571,7 @@ mp_int_t ModPicoGraphics_get_framebuffer(mp_obj_t self_in, mp_buffer_info_t *buf
mp_raise_ValueError("No local framebuffer.");
}
bufinfo->buf = self->graphics->frame_buffer;
bufinfo->len = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, self->graphics->bounds.w, self->graphics->bounds.h);
bufinfo->len = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, self->graphics->bounds.w, self->graphics->bounds.h, 1);
bufinfo->typecode = 'B';
return 0;
}
@ -603,7 +612,7 @@ mp_obj_t ModPicoGraphics_get_required_buffer_size(mp_obj_t display_in, mp_obj_t
int pen_type = mp_obj_get_int(pen_type_in);
PicoGraphicsBusType bus_type = BUS_SPI;
if(!get_display_settings(display, width, height, rotation, pen_type, bus_type)) mp_raise_ValueError("Unsupported display!");
size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height);
size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height, 1);
if(required_size == 0) mp_raise_ValueError("Unsupported pen type!");
return mp_obj_new_int(required_size);
@ -755,6 +764,14 @@ mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen) {
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_layer(mp_obj_t self_in, mp_obj_t layer) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_layer(mp_obj_get_int(layer));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);

Wyświetl plik

@ -77,6 +77,9 @@ extern mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen);
extern mp_obj_t ModPicoGraphics_set_palette(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_hsv_to_rgb(size_t n_args, const mp_obj_t *args);
// Layers
extern mp_obj_t ModPicoGraphics_set_layer(mp_obj_t self_in, mp_obj_t layer);
// Pen
extern mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen);
extern mp_obj_t ModPicoGraphics_create_pen(size_t n_args, const mp_obj_t *args);