display SDL: Split in top and bottom

Split the SDL display driver in a top and bottom
to enable using it with embedded libCs.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
Alberto Escolar Piedras 2023-07-05 13:20:40 +02:00 committed by Alberto Escolar
parent 35a0b9eed7
commit 1e66ca0de3
5 changed files with 175 additions and 73 deletions

View file

@ -15,7 +15,6 @@ zephyr_library_sources_ifdef(CONFIG_ILI9488 display_ili9488.c)
zephyr_library_sources_ifdef(CONFIG_LS0XX ls0xx.c)
zephyr_library_sources_ifdef(CONFIG_MAX7219 display_max7219.c)
zephyr_library_sources_ifdef(CONFIG_OTM8009A display_otm8009a.c)
zephyr_library_sources_ifdef(CONFIG_SDL_DISPLAY display_sdl.c)
zephyr_library_sources_ifdef(CONFIG_SSD1306 ssd1306.c)
zephyr_library_sources_ifdef(CONFIG_SSD16XX ssd16xx.c)
zephyr_library_sources_ifdef(CONFIG_ST7789V display_st7789v.c)
@ -27,3 +26,12 @@ zephyr_library_sources_ifdef(CONFIG_MICROBIT_DISPLAY
mb_display.c
mb_font.c
)
if (CONFIG_SDL_DISPLAY)
zephyr_library_sources(display_sdl.c)
if (CONFIG_NATIVE_APPLICATION)
zephyr_library_sources(display_sdl_bottom.c)
else()
target_sources(native_simulator INTERFACE display_sdl_bottom.c)
endif()
endif()

View file

@ -7,7 +7,6 @@ menuconfig SDL_DISPLAY
bool "SDL based emulated display"
default y
depends on DT_HAS_ZEPHYR_SDL_DC_ENABLED
depends on EXTERNAL_LIBC
select HAS_SDL
help
Enable SDL based emulated display compliant with display driver API.

View file

@ -9,10 +9,10 @@
#include <zephyr/drivers/display.h>
#include <SDL.h>
#include <string.h>
#include <soc.h>
#include <zephyr/sys/byteorder.h>
#include "display_sdl_bottom.h"
#define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL
#include <zephyr/logging/log.h>
@ -24,9 +24,9 @@ struct sdl_display_config {
};
struct sdl_display_data {
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
void *window;
void *renderer;
void *texture;
bool display_on;
enum display_pixel_format current_pixel_format;
uint8_t *buf;
@ -54,36 +54,15 @@ static int sdl_display_init(const struct device *dev)
#endif /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */
;
disp_data->window =
SDL_CreateWindow("Zephyr Display", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, config->width,
config->height, SDL_WINDOW_SHOWN);
if (disp_data->window == NULL) {
LOG_ERR("Failed to create SDL window: %s", SDL_GetError());
return -EIO;
}
int rc = sdl_display_init_bottom(config->height, config->width, &disp_data->window,
&disp_data->renderer, &disp_data->texture);
disp_data->renderer =
SDL_CreateRenderer(disp_data->window, -1, SDL_RENDERER_ACCELERATED);
if (disp_data->renderer == NULL) {
LOG_ERR("Failed to create SDL renderer: %s",
SDL_GetError());
return -EIO;
}
disp_data->texture = SDL_CreateTexture(
disp_data->renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC, config->width,
config->height);
if (disp_data->texture == NULL) {
LOG_ERR("Failed to create SDL texture: %s", SDL_GetError());
if (rc != 0) {
LOG_ERR("Failed to create SDL display");
return -EIO;
}
disp_data->display_on = false;
SDL_SetRenderDrawColor(disp_data->renderer, 0, 0, 0, 0xFF);
SDL_RenderClear(disp_data->renderer);
SDL_RenderPresent(disp_data->renderer);
return 0;
}
@ -222,7 +201,6 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
{
const struct sdl_display_config *config = dev->config;
struct sdl_display_data *disp_data = dev->data;
SDL_Rect rect;
LOG_DBG("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)", desc->width,
desc->height, x, y);
@ -257,20 +235,9 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
sdl_display_write_bgr565(disp_data->buf, desc, buf);
}
rect.x = x;
rect.y = y;
rect.w = desc->width;
rect.h = desc->height;
SDL_UpdateTexture(disp_data->texture, &rect, disp_data->buf,
4 * rect.w);
if (disp_data->display_on) {
SDL_RenderClear(disp_data->renderer);
SDL_RenderCopy(disp_data->renderer, disp_data->texture, NULL,
NULL);
SDL_RenderPresent(disp_data->renderer);
}
sdl_display_write_bottom(desc->height, desc->width, x, y,
disp_data->renderer, disp_data->texture,
disp_data->buf, disp_data->display_on);
return 0;
}
@ -281,12 +248,6 @@ static int sdl_display_read(const struct device *dev, const uint16_t x,
void *buf)
{
struct sdl_display_data *disp_data = dev->data;
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = desc->width;
rect.h = desc->height;
LOG_DBG("Reading %dx%d (w,h) bitmap @ %dx%d (x,y)", desc->width,
desc->height, x, y);
@ -295,8 +256,8 @@ static int sdl_display_read(const struct device *dev, const uint16_t x,
__ASSERT((desc->pitch * 3U * desc->height) <= desc->buf_size,
"Input buffer to small");
return SDL_RenderReadPixels(disp_data->renderer, &rect, 0, buf,
desc->pitch * 4U);
return sdl_display_read_bottom(desc->height, desc->width, x, y,
disp_data->renderer, buf, desc->pitch);
}
static void *sdl_display_get_framebuffer(const struct device *dev)
@ -312,9 +273,7 @@ static int sdl_display_blanking_off(const struct device *dev)
disp_data->display_on = true;
SDL_RenderClear(disp_data->renderer);
SDL_RenderCopy(disp_data->renderer, disp_data->texture, NULL, NULL);
SDL_RenderPresent(disp_data->renderer);
sdl_display_blanking_off_bottom(disp_data->renderer, disp_data->texture);
return 0;
}
@ -327,8 +286,7 @@ static int sdl_display_blanking_on(const struct device *dev)
disp_data->display_on = false;
SDL_RenderClear(disp_data->renderer);
SDL_RenderPresent(disp_data->renderer);
sdl_display_blanking_on_bottom(disp_data->renderer);
return 0;
}
@ -386,20 +344,7 @@ static int sdl_display_set_pixel_format(const struct device *dev,
static void sdl_display_cleanup(struct sdl_display_data *disp_data)
{
if (disp_data->texture != NULL) {
SDL_DestroyTexture(disp_data->texture);
disp_data->texture = NULL;
}
if (disp_data->renderer != NULL) {
SDL_DestroyRenderer(disp_data->renderer);
disp_data->renderer = NULL;
}
if (disp_data->window != NULL) {
SDL_DestroyWindow(disp_data->window);
disp_data->window = NULL;
}
sdl_display_cleanup_bottom(&disp_data->window, &disp_data->renderer, &disp_data->texture);
}
static const struct display_driver_api sdl_display_api = {

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2018 Jan Van Winkel <jan.van_winkel@dxplore.eu>
* Copyright (c) 2023 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <SDL.h>
#include "nsi_tracing.h"
int sdl_display_init_bottom(uint16_t height, uint16_t width,
void **window, void **renderer, void **texture)
{
*window = SDL_CreateWindow("Zephyr Display", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, width,
height, SDL_WINDOW_SHOWN);
if (*window == NULL) {
nsi_print_warning("Failed to create SDL window: %s", SDL_GetError());
return -1;
}
*renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED);
if (*renderer == NULL) {
nsi_print_warning("Failed to create SDL renderer: %s",
SDL_GetError());
return -1;
}
*texture = SDL_CreateTexture(*renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STATIC, width, height);
if (*texture == NULL) {
nsi_print_warning("Failed to create SDL texture: %s", SDL_GetError());
return -1;
}
SDL_SetRenderDrawColor(*renderer, 0, 0, 0, 0xFF);
SDL_RenderClear(*renderer);
SDL_RenderPresent(*renderer);
return 0;
}
void sdl_display_write_bottom(const uint16_t height, const uint16_t width,
const uint16_t x, const uint16_t y,
void *renderer, void *texture,
uint8_t *buf, bool display_on)
{
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = width;
rect.h = height;
SDL_UpdateTexture(texture, &rect, buf, 4 * rect.w);
if (display_on) {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
}
int sdl_display_read_bottom(const uint16_t height, const uint16_t width,
const uint16_t x, const uint16_t y,
void *renderer, void *buf, uint16_t pitch)
{
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = width;
rect.h = height;
return SDL_RenderReadPixels(renderer, &rect, 0, buf, pitch * 4U);
}
void sdl_display_blanking_off_bottom(void *renderer, void *texture)
{
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
void sdl_display_blanking_on_bottom(void *renderer)
{
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void sdl_display_cleanup_bottom(void **window, void **renderer, void **texture)
{
if (*texture != NULL) {
SDL_DestroyTexture(*texture);
*texture = NULL;
}
if (*renderer != NULL) {
SDL_DestroyRenderer(*renderer);
*renderer = NULL;
}
if (*window != NULL) {
SDL_DestroyWindow(*window);
*window = NULL;
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2018 Jan Van Winkel <jan.van_winkel@dxplore.eu>
* Copyright (c) 2023 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*
* "Bottom" of the SDL display driver.
* When built with the native_simulator this will be built in the runner context,
* that is, with the host C library, and with the host include paths.
*/
#ifndef DRIVERS_DISPLAY_DISPLAY_SDL_BOTTOM_H
#define DRIVERS_DISPLAY_DISPLAY_SDL_BOTTOM_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Note: None of these functions are public interfaces. But internal to the SDL display driver */
int sdl_display_init_bottom(uint16_t height, uint16_t width,
void **window, void **renderer, void **texture);
void sdl_display_write_bottom(const uint16_t height, const uint16_t width,
const uint16_t x, const uint16_t y,
void *renderer, void *texture,
uint8_t *buf, bool display_on);
int sdl_display_read_bottom(const uint16_t height, const uint16_t width,
const uint16_t x, const uint16_t y,
void *renderer, void *buf, uint16_t pitch);
void sdl_display_blanking_off_bottom(void *renderer, void *texture);
void sdl_display_blanking_on_bottom(void *renderer);
void sdl_display_cleanup_bottom(void **window, void **renderer, void **texture);
#ifdef __cplusplus
}
#endif
#endif /* DRIVERS_DISPLAY_DISPLAY_SDL_BOTTOM_H */