Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/releases/release-notes-4.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ Drivers and Sensors

* Display

* Added flag ``frame_incomplete`` to ``display_write`` that indicates whether a write is the last
write of the frame, allowing display drivers to implement double buffering / tearing enable
signal handling (:github:`81250`)
* Added ``frame_incomplete`` handling to SDL display driver (:dtcompatible:`zephyr,sdl-dc`)
(:github:`81250`)

* Ethernet

* Flash
Expand Down Expand Up @@ -278,6 +284,9 @@ Trusted Firmware-M
LVGL
****

* Added ``frame_incomplete`` support to indicate whether a write is the last
write of the frame (:github:`81250`)

Tests and Samples
*****************

Expand Down
1 change: 1 addition & 0 deletions drivers/display/display_gc9x01x.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1
mipi_desc.width = desc->width;
/* Per MIPI API, pitch must always match width */
mipi_desc.pitch = desc->width;
mipi_desc.frame_incomplete = desc->frame_incomplete;

ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, NULL, 0);
if (ret < 0) {
Expand Down
1 change: 1 addition & 0 deletions drivers/display/display_ili9xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static int ili9xxx_write(const struct device *dev, const uint16_t x,
mipi_desc.width = desc->width;
/* Per MIPI API, pitch must always match width */
mipi_desc.pitch = desc->width;
mipi_desc.frame_incomplete = desc->frame_incomplete;

r = ili9xxx_transmit(dev, ILI9XXX_RAMWR, NULL, 0);
if (r < 0) {
Expand Down
6 changes: 3 additions & 3 deletions drivers/display/display_sdl.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,9 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
sdl_display_write_bgr565(disp_data->buf, desc, buf);
}

sdl_display_write_bottom(desc->height, desc->width, x, y,
disp_data->renderer, disp_data->mutex, disp_data->texture,
disp_data->buf, disp_data->display_on);
sdl_display_write_bottom(desc->height, desc->width, x, y, disp_data->renderer,
disp_data->mutex, disp_data->texture, disp_data->buf,
disp_data->display_on, desc->frame_incomplete);

return 0;
}
Expand Down
11 changes: 6 additions & 5 deletions drivers/display/display_sdl_bottom.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include "display_sdl_bottom.h"

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
Expand Down Expand Up @@ -64,10 +66,9 @@ int sdl_display_init_bottom(uint16_t height, uint16_t width, uint16_t zoom_pct,
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 *mutex, void *texture,
uint8_t *buf, bool display_on)
void sdl_display_write_bottom(const uint16_t height, const uint16_t width, const uint16_t x,
const uint16_t y, void *renderer, void *mutex, void *texture,
uint8_t *buf, bool display_on, bool frame_incomplete)
{
SDL_Rect rect;
int err;
Expand All @@ -85,7 +86,7 @@ void sdl_display_write_bottom(const uint16_t height, const uint16_t width,

SDL_UpdateTexture(texture, &rect, buf, 4 * rect.w);

if (display_on) {
if (display_on && !frame_incomplete) {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
Expand Down
14 changes: 6 additions & 8 deletions drivers/display/display_sdl_bottom.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ extern "C" {
int sdl_display_init_bottom(uint16_t height, uint16_t width, uint16_t zoom_pct,
bool use_accelerator, void **window, void **renderer, void **mutex,
void **texture, void **read_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 *mutex, 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 *mutex, void *texture, void **read_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 *mutex, void *texture,
uint8_t *buf, bool display_on, bool frame_incomplete);
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 *mutex, void *texture, void *read_texture);
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 **mutex, void **texture,
Expand Down
2 changes: 2 additions & 0 deletions include/zephyr/drivers/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ struct display_buffer_descriptor {
uint16_t height;
/** Number of pixels between consecutive rows in the data buffer */
uint16_t pitch;
/** Indicates that this is not the last write buffer of the frame */
bool frame_incomplete;
};

/**
Expand Down
2 changes: 2 additions & 0 deletions modules/lvgl/lvgl_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ void lvgl_flush_thread_entry(void *arg1, void *arg2, void *arg3)
k_msgq_get(&flush_queue, &flush, K_FOREVER);
data = (struct lvgl_disp_data *)flush.disp_drv->user_data;

flush.desc.frame_incomplete = !lv_disp_flush_is_last(flush.disp_drv);
display_write(data->display_dev, flush.x, flush.y, &flush.desc,
flush.buf);

Expand Down Expand Up @@ -132,6 +133,7 @@ void lvgl_flush_display(struct lvgl_display_flush *request)
struct lvgl_disp_data *data =
(struct lvgl_disp_data *)request->disp_drv->user_data;

request->desc.frame_incomplete = !lv_disp_flush_is_last(request->disp_drv);
display_write(data->display_dev, request->x, request->y,
&request->desc, request->buf);
lv_disp_flush_ready(request->disp_drv);
Expand Down
13 changes: 8 additions & 5 deletions modules/lvgl/lvgl_display_mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ void lvgl_flush_cb_mono(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color
uint16_t h = area->y2 - area->y1 + 1;
struct lvgl_disp_data *data = (struct lvgl_disp_data *)disp_drv->user_data;
const struct device *display_dev = data->display_dev;
struct display_buffer_descriptor desc;
const bool is_epd = data->cap.screen_info & SCREEN_INFO_EPD;
const bool is_last = lv_disp_flush_is_last(disp_drv);

Expand All @@ -29,10 +28,14 @@ void lvgl_flush_cb_mono(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color
data->blanking_on = true;
}

desc.buf_size = (w * h) / 8U;
desc.width = w;
desc.pitch = w;
desc.height = h;
struct display_buffer_descriptor desc = {
.buf_size = (w * h) / 8U,
.width = w,
.pitch = w,
.height = h,
.frame_incomplete = !is_last,
};

display_write(display_dev, area->x1, area->y1, &desc, (void *)color_p);
if (data->cap.screen_info & SCREEN_INFO_DOUBLE_BUFFER) {
display_write(display_dev, area->x1, area->y1, &desc, (void *)color_p);
Expand Down
15 changes: 15 additions & 0 deletions samples/drivers/display/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,14 @@ int main(void)
buf_desc.width = capabilities.x_resolution;
buf_desc.height = h_step;

/*
* The following writes will only render parts of the image,
* so turn this option on.
* This allows double-buffered displays to hold the pixels
* back until the image is complete.
*/
buf_desc.frame_incomplete = true;

for (int idx = 0; idx < capabilities.y_resolution; idx += h_step) {
/*
* Tweaking the height value not to draw outside of the display.
Expand All @@ -323,6 +331,13 @@ int main(void)
y = 0;
display_write(display_dev, x, y, &buf_desc, buf);

/*
* This is the last write of the frame, so turn this off.
* Double-buffered displays will now present the new image
* to the user.
*/
buf_desc.frame_incomplete = false;

fill_buffer_fnc(BOTTOM_RIGHT, 0, buf, buf_size);
x = capabilities.x_resolution - rect_w;
y = capabilities.y_resolution - rect_h;
Expand Down
12 changes: 6 additions & 6 deletions samples/drivers/video/capture/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ static inline void video_display_frame(const struct device *const display_dev,
const struct video_buffer *const vbuf,
const struct video_format fmt)
{
struct display_buffer_descriptor buf_desc;

buf_desc.buf_size = vbuf->bytesused;
buf_desc.width = fmt.width;
buf_desc.pitch = buf_desc.width;
buf_desc.height = vbuf->bytesused / fmt.pitch;
struct display_buffer_descriptor buf_desc = {
.buf_size = vbuf->bytesused,
.width = fmt.width,
.pitch = buf_desc.width,
.height = vbuf->bytesused / fmt.pitch,
};

display_write(display_dev, 0, vbuf->line_offset, &buf_desc, vbuf->buffer);
}
Expand Down
11 changes: 6 additions & 5 deletions subsys/fb/cfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,17 +460,18 @@ int cfb_framebuffer_finalize(const struct device *dev)
{
const struct display_driver_api *api = dev->api;
const struct char_framebuffer *fb = &char_fb;
struct display_buffer_descriptor desc;
int err;

if (!fb || !fb->buf) {
return -ENODEV;
}

desc.buf_size = fb->size;
desc.width = fb->x_res;
desc.height = fb->y_res;
desc.pitch = fb->x_res;
struct display_buffer_descriptor desc = {
.buf_size = fb->size,
.width = fb->x_res,
.height = fb->y_res,
.pitch = fb->x_res,
};

if (!(fb->pixel_format & PIXEL_FORMAT_MONO10) != !(fb->inverted)) {
cfb_invert(fb);
Expand Down
Loading