Skip to content
Snippets Groups Projects
Commit 7a7e49a5 authored by q3k's avatar q3k
Browse files

st3m: switch to rendering to SPIRAM, limiting glitches

This doesn't seem to be less performant than the rube goldberg we had
previously, but somehow fixes up rendering glitches.
parent 5ceab0f3
No related branches found
No related tags found
1 merge request!19bump to ESP-IDF 5
...@@ -16,21 +16,11 @@ ...@@ -16,21 +16,11 @@
static const char *TAG = "st3m-gfx"; static const char *TAG = "st3m-gfx";
// SRAM framebuffer into which ctx drawlists will be rasterized. After // Framebuffer descriptors, containing framebuffer and ctx for each of the
// rasterization, their contents will be copied into SPIRAM. Then, the ESP SPI // framebuffers.
// driver will piecewise copy the buffer back into DMA-able memory to send it
// over to the display.
// //
// This Rube Goldberg contraption is still faster than directly rasterizing into // These live in SPIRAM, as we don't have enough space in SRAM/IRAM.
// SPIRAM (~20% faster). Ideally we would also keep both buffers in DMAble SRAM, EXT_RAM_BSS_ATTR static st3m_framebuffer_desc_t framebuffer_descs[ST3M_GFX_NBUFFERS];
// but we don't have enough SRAM for that.
static uint16_t framebuffer_staging[240*240];
// framebuffer_staging-backed Ctx instance, used to render drawlists into
// framebuffer_staging.
static Ctx *framebuffer_staging_ctx;
static st3m_framebuffer_desc_t framebuffer_descs[ST3M_GFX_NBUFFERS];
static st3m_ctx_desc_t dctx_descs[ST3M_GFX_NCTX]; static st3m_ctx_desc_t dctx_descs[ST3M_GFX_NCTX];
...@@ -112,22 +102,20 @@ static void st3m_gfx_rast_task(void *_arg) { ...@@ -112,22 +102,20 @@ static void st3m_gfx_rast_task(void *_arg) {
int fb_descno, dctx_descno; int fb_descno, dctx_descno;
int64_t start = esp_timer_get_time(); int64_t start = esp_timer_get_time();
xQueueReceiveNotifyStarved(framebuffer_freeq, &fb_descno, "rast task starved (freeq)!"); xQueueReceiveNotifyStarved(framebuffer_freeq, &fb_descno, "rast task starved (freeq)!");
st3m_framebuffer_desc_t *fb = &framebuffer_descs[fb_descno];
int64_t end = esp_timer_get_time(); int64_t end = esp_timer_get_time();
st3m_counter_timer_sample(&rast_read_fb_time, end-start); st3m_counter_timer_sample(&rast_read_fb_time, end-start);
start = esp_timer_get_time(); start = esp_timer_get_time();
xQueueReceiveNotifyStarved(dctx_rastq, &dctx_descno, "rast task starved (dctx)!"); xQueueReceiveNotifyStarved(dctx_rastq, &dctx_descno, "rast task starved (dctx)!");
st3m_ctx_desc_t *draw = &dctx_descs[dctx_descno];
end = esp_timer_get_time(); end = esp_timer_get_time();
st3m_counter_timer_sample(&rast_read_dctx_time, end-start); st3m_counter_timer_sample(&rast_read_dctx_time, end-start);
// Render drawctx into fbctx.
start = esp_timer_get_time(); start = esp_timer_get_time();
ctx_render_ctx(draw->ctx, fb->ctx);
// Render to staging and memcpy to framebuffer. ctx_drawlist_clear(draw->ctx);
ctx_render_ctx(dctx_descs[dctx_descno].ctx, framebuffer_staging_ctx);
memcpy(framebuffer_descs[fb_descno].buffer, framebuffer_staging, 240*240*2);
ctx_drawlist_clear(dctx_descs[dctx_descno].ctx);
end = esp_timer_get_time(); end = esp_timer_get_time();
st3m_counter_timer_sample(&rast_work_time, end-start); st3m_counter_timer_sample(&rast_work_time, end-start);
...@@ -195,27 +183,23 @@ void st3m_gfx_init(void) { ...@@ -195,27 +183,23 @@ void st3m_gfx_init(void) {
dctx_rastq = xQueueCreate(ST3M_GFX_NCTX+1, sizeof(int)); dctx_rastq = xQueueCreate(ST3M_GFX_NCTX+1, sizeof(int));
assert(dctx_rastq != NULL); assert(dctx_rastq != NULL);
// Create staging framebuffer Ctx.
framebuffer_staging_ctx = ctx_new_for_framebuffer(
framebuffer_staging,
FLOW3R_BSP_DISPLAY_WIDTH,
FLOW3R_BSP_DISPLAY_HEIGHT,
FLOW3R_BSP_DISPLAY_WIDTH * 2,
CTX_FORMAT_RGB565_BYTESWAPPED
);
assert(framebuffer_staging_ctx != NULL);
// Rotate by 180 deg and translate x and y by 120 px to have (0,0) at the center of the screen
int32_t offset_x = FLOW3R_BSP_DISPLAY_WIDTH / 2;
int32_t offset_y = FLOW3R_BSP_DISPLAY_HEIGHT / 2;
ctx_apply_transform(framebuffer_staging_ctx, -1, 0, offset_x, 0, -1, offset_y, 0, 0, 1);
for (int i = 0; i < ST3M_GFX_NBUFFERS; i++) { for (int i = 0; i < ST3M_GFX_NBUFFERS; i++) {
// Setup framebuffer descriptor. // Setup framebuffer descriptor.
st3m_framebuffer_desc_t *fb_desc = &framebuffer_descs[i]; st3m_framebuffer_desc_t *fb_desc = &framebuffer_descs[i];
fb_desc->num = i; fb_desc->num = i;
fb_desc->buffer = malloc(2 * FLOW3R_BSP_DISPLAY_WIDTH * FLOW3R_BSP_DISPLAY_HEIGHT); fb_desc->ctx = ctx_new_for_framebuffer(
assert(fb_desc->buffer != NULL); fb_desc->buffer,
memset(fb_desc->buffer, 0, 2 * FLOW3R_BSP_DISPLAY_WIDTH * FLOW3R_BSP_DISPLAY_HEIGHT); FLOW3R_BSP_DISPLAY_WIDTH,
FLOW3R_BSP_DISPLAY_HEIGHT,
FLOW3R_BSP_DISPLAY_WIDTH * 2,
CTX_FORMAT_RGB565_BYTESWAPPED
);
assert(fb_desc->ctx != NULL);
// Rotate by 180 deg and translate x and y by 120 px to have (0,0) at the center of the screen
int32_t offset_x = FLOW3R_BSP_DISPLAY_WIDTH / 2;
int32_t offset_y = FLOW3R_BSP_DISPLAY_HEIGHT / 2;
ctx_apply_transform(fb_desc->ctx, -1, 0, offset_x, 0, -1, offset_y, 0, 0, 1);
// Push descriptor to freeq. // Push descriptor to freeq.
BaseType_t res = xQueueSend(framebuffer_freeq, &i, 0); BaseType_t res = xQueueSend(framebuffer_freeq, &i, 0);
......
...@@ -17,7 +17,8 @@ typedef struct { ...@@ -17,7 +17,8 @@ typedef struct {
// The numeric ID of this descriptor. // The numeric ID of this descriptor.
int num; int num;
// SPIRAM buffer. // SPIRAM buffer.
uint16_t *buffer; uint16_t buffer[240*240];
Ctx *ctx;
} st3m_framebuffer_desc_t; } st3m_framebuffer_desc_t;
// Initialize the gfx subsystem of st3m, includng the rasterization and // Initialize the gfx subsystem of st3m, includng the rasterization and
......
...@@ -20,6 +20,7 @@ CONFIG_SPIRAM_TYPE_ESPPSRAM64=y ...@@ -20,6 +20,7 @@ CONFIG_SPIRAM_TYPE_ESPPSRAM64=y
CONFIG_SPIRAM_SPEED_80M=y CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
CONFIG_ESP32S3_DATA_CACHE_64KB=y CONFIG_ESP32S3_DATA_CACHE_64KB=y
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment