From c1255f7f471cab1024440e107faa63c5cf49262b Mon Sep 17 00:00:00 2001 From: cstout Date: Thu, 10 Mar 2016 09:49:22 -0800 Subject: [PATCH] [display] Refactor to avoid implicit framebuffer allocation. Preparation to allow other images to be presented to the display. Separate definitions of display and image formats. display_get_info no longer provides a framebuffer. display_get_framebuffer allocates a framebuffer for convenience. Review URL: https://codereview.chromium.org/1777783003 . --- dev/virtio/gpu/virtio-gpu.c | 29 +++-- include/dev/display.h | 55 ++++++--- include/lib/gfx.h | 6 +- lib/gfx/gfx.c | 45 ++++---- lib/gfxconsole/gfxconsole.c | 6 +- lib/text/text.c | 6 +- platform/armemu/display.c | 31 ++++-- target/dartuinoP0/display/LS013B7DH06.c | 104 ++++++++++-------- target/dartuinoP0/display/memory_lcd_mono.c | 29 +++-- .../include/target/display/LS013B7DH03.h | 9 +- .../include/target/display/LS013B7DH06.h | 15 +-- .../include/target/display/LS027B7DH01.h | 9 +- target/dartuinoP0/memory_lcd.c | 58 ++++++++-- target/qemu-m4/m4display.c | 33 ++++-- target/stm32746g-eval2/lcd.c | 35 ++++-- target/stm32f746g-disco/lcd.c | 35 ++++-- 16 files changed, 333 insertions(+), 172 deletions(-) diff --git a/dev/virtio/gpu/virtio-gpu.c b/dev/virtio/gpu/virtio-gpu.c index b5dff6ff..f9e78bd1 100644 --- a/dev/virtio/gpu/virtio-gpu.c +++ b/dev/virtio/gpu/virtio-gpu.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "virtio_gpu.h" @@ -557,21 +556,37 @@ void virtio_gpu_gfx_flush(uint starty, uint endy) event_signal(&the_gdev->flush_event, !arch_ints_disabled()); } +status_t display_get_framebuffer(struct display_framebuffer *fb) +{ + DEBUG_ASSERT(fb); + memset(fb, 0, sizeof(*fb)); + + if (!the_gdev) + return ERR_NOT_FOUND; + + fb->image.pixels = the_gdev->fb; + fb->image.format = IMAGE_FORMAT_RGB_x888; + fb->image.width = the_gdev->pmode.r.width; + fb->image.height = the_gdev->pmode.r.height; + fb->image.stride = fb->image.width; + fb->image.rowbytes = fb->image.width * 4; + fb->flush = virtio_gpu_gfx_flush; + fb->format = DISPLAY_FORMAT_RGB_x888; + + return NO_ERROR; +} + status_t display_get_info(struct display_info *info) { + DEBUG_ASSERT(info); memset(info, 0, sizeof(*info)); if (!the_gdev) return ERR_NOT_FOUND; - info->framebuffer = the_gdev->fb; - info->format = GFX_FORMAT_RGB_x888; + info->format = DISPLAY_FORMAT_RGB_x888; info->width = the_gdev->pmode.r.width; info->height = the_gdev->pmode.r.height; - info->stride = info->width; - info->flush = virtio_gpu_gfx_flush; return NO_ERROR; } - - diff --git a/include/dev/display.h b/include/dev/display.h index 45105737..6337d981 100644 --- a/include/dev/display.h +++ b/include/dev/display.h @@ -35,30 +35,57 @@ int display_enable(bool enable); void display_pre_freq_change(void); void display_post_freq_change(void); -#define DISPLAY_FORMAT_NONE (-1) -#define DISPLAY_FORMAT_RGB_565 (0) -#define DISPLAY_FORMAT_RGB_332 (1) -#define DISPLAY_FORMAT_RGB_2220 (2) -#define DISPLAY_FORMAT_ARGB_8888 (3) -#define DISPLAY_FORMAT_RGB_x888 (4) -#define DISPLAY_FORMAT_RGB_x111 (5) -#define DISPLAY_FORMAT_MONO_1 (6) -#define DISPLAY_FORMAT_MONO_8 (7) +enum display_format { + DISPLAY_FORMAT_UNKNOWN, + DISPLAY_FORMAT_MONO_1, + DISPLAY_FORMAT_RGB_111, + DISPLAY_FORMAT_RGB_565, + DISPLAY_FORMAT_RGB_x888, + DISPLAY_FORMAT_ARGB_8888, +}; + +enum image_format { + IMAGE_FORMAT_UNKNOWN, + IMAGE_FORMAT_MONO_1, + IMAGE_FORMAT_MONO_8, + IMAGE_FORMAT_RGB_x111, + IMAGE_FORMAT_RGB_332, + IMAGE_FORMAT_RGB_565, + IMAGE_FORMAT_RGB_2220, + IMAGE_FORMAT_RGB_x888, + IMAGE_FORMAT_ARGB_8888, +}; struct display_info { - void *framebuffer; - int format; + enum display_format format; uint width; uint height; - uint stride; +}; +status_t display_get_info(struct display_info *info) __NONNULL((1)); + +struct display_image { + enum image_format format; + void *pixels; + uint width; + uint height; + int stride; // row length in pixels + int rowbytes; // row length in bytes +}; + +status_t display_present(struct display_image *image, uint starty, uint endy) + __NONNULL((1)); + +struct display_framebuffer { + enum display_format format; + struct display_image image; // Update function void (*flush)(uint starty, uint endy); }; -status_t display_get_info(struct display_info *info); +status_t display_get_framebuffer(struct display_framebuffer *fb) + __NONNULL((1)); __END_CDECLS #endif - diff --git a/include/lib/gfx.h b/include/lib/gfx.h index 8c68daa8..ca5c3797 100644 --- a/include/lib/gfx.h +++ b/include/lib/gfx.h @@ -103,9 +103,9 @@ void gfx_flush_rows(struct gfx_surface *surface, uint start, uint end); // surface setup gfx_surface *gfx_create_surface(void *ptr, uint width, uint height, uint stride, gfx_format format); -// utility routine to make a surface out of a display info -struct display_info; -gfx_surface *gfx_create_surface_from_display(struct display_info *); +// utility routine to make a surface out of a display framebuffer +struct display_framebuffer; +gfx_surface *gfx_create_surface_from_display(struct display_framebuffer *) __NONNULL((1)); // free the surface // optionally frees the buffer if the free bit is set diff --git a/lib/gfx/gfx.c b/lib/gfx/gfx.c index 757c1d11..75f6d088 100644 --- a/lib/gfx/gfx.c +++ b/lib/gfx/gfx.c @@ -657,27 +657,28 @@ gfx_surface *gfx_create_surface(void *ptr, uint width, uint height, uint stride, /** * @brief Create a new graphics surface object from a display */ -gfx_surface *gfx_create_surface_from_display(struct display_info *info) +gfx_surface *gfx_create_surface_from_display(struct display_framebuffer *fb) { + DEBUG_ASSERT(fb); gfx_surface *surface; gfx_format format; - switch (info->format) { - case DISPLAY_FORMAT_RGB_565: + switch (fb->image.format) { + case IMAGE_FORMAT_RGB_565: format = GFX_FORMAT_RGB_565; break; - case DISPLAY_FORMAT_RGB_332: + case IMAGE_FORMAT_RGB_332: format = GFX_FORMAT_RGB_332; break; - case DISPLAY_FORMAT_RGB_2220: + case IMAGE_FORMAT_RGB_2220: format = GFX_FORMAT_RGB_2220; break; - case DISPLAY_FORMAT_ARGB_8888: + case IMAGE_FORMAT_ARGB_8888: format = GFX_FORMAT_ARGB_8888; break; - case DISPLAY_FORMAT_RGB_x888: + case IMAGE_FORMAT_RGB_x888: format = GFX_FORMAT_RGB_x888; break; - case DISPLAY_FORMAT_MONO_8: + case IMAGE_FORMAT_MONO_8: format = GFX_FORMAT_MONO; break; default: @@ -686,9 +687,9 @@ gfx_surface *gfx_create_surface_from_display(struct display_info *info) return NULL; } - surface = gfx_create_surface(info->framebuffer, info->width, info->height, info->stride, format); + surface = gfx_create_surface(fb->image.pixels, fb->image.width, fb->image.height, fb->image.stride, format); - surface->flush = info->flush; + surface->flush = fb->flush; return surface; } @@ -711,11 +712,11 @@ void gfx_surface_destroy(struct gfx_surface *surface) */ void gfx_draw_pattern(void) { - struct display_info info; - if (display_get_info(&info) < 0) + struct display_framebuffer fb; + if (display_get_framebuffer(&fb) < 0) return; - gfx_surface *surface = gfx_create_surface_from_display(&info); + gfx_surface *surface = gfx_create_surface_from_display(&fb); uint x, y; for (y = 0; y < surface->height; y++) { @@ -740,11 +741,11 @@ void gfx_draw_pattern(void) */ void gfx_draw_pattern_white(void) { - struct display_info info; - if (display_get_info(&info) < 0) + struct display_framebuffer fb; + if (display_get_framebuffer(&fb) < 0) return; - gfx_surface *surface = gfx_create_surface_from_display(&info); + gfx_surface *surface = gfx_create_surface_from_display(&fb); uint x, y; for (y = 0; y < surface->height; y++) { @@ -809,19 +810,19 @@ static int cmd_gfx(int argc, const cmd_args *argv) return -1; } - struct display_info info; - if (display_get_info(&info) < 0) { + struct display_framebuffer fb; + if (display_get_framebuffer(&fb) < 0) { printf("no display to draw on!\n"); return -1; } - gfx_surface *surface = gfx_create_surface_from_display(&info); + gfx_surface *surface = gfx_create_surface_from_display(&fb); if (!strcmp(argv[1].str, "display_info")) { printf("display:\n"); - printf("\tframebuffer %p\n", info.framebuffer); - printf("\twidth %u height %u stride %u\n", info.width, info.height, info.stride); - printf("\tformat %u\n", info.format); + printf("\tframebuffer %p\n", fb.image.pixels); + printf("\twidth %u height %u stride %u\n", fb.image.width, fb.image.height, fb.image.stride); + printf("\tformat %u\n", fb.image.format); } else if (!strcmp(argv[1].str, "rgb_bars")) { gfx_draw_rgb_bars(surface); } else if (!strcmp(argv[1].str, "test_pattern")) { diff --git a/lib/gfxconsole/gfxconsole.c b/lib/gfxconsole/gfxconsole.c index eb208c53..f874f650 100644 --- a/lib/gfxconsole/gfxconsole.c +++ b/lib/gfxconsole/gfxconsole.c @@ -164,11 +164,11 @@ void gfxconsole_start_on_display(void) return; /* pop up the console */ - struct display_info info; - if (display_get_info(&info) < 0) + struct display_framebuffer fb; + if (display_get_framebuffer(&fb) < 0) return; - gfx_surface *s = gfx_create_surface_from_display(&info); + gfx_surface *s = gfx_create_surface_from_display(&fb); gfxconsole_start(s); started = true; } diff --git a/lib/text/text.c b/lib/text/text.c index faad4d93..349ac8d1 100644 --- a/lib/text/text.c +++ b/lib/text/text.c @@ -76,12 +76,12 @@ void text_draw(int x, int y, const char *string) */ void text_update(void) { - struct display_info info; - if (display_get_info(&info) < 0) + struct display_framebuffer fb; + if (display_get_framebuffer(&fb) < 0) return; /* get the display's surface */ - gfx_surface *surface = gfx_create_surface_from_display(&info); + gfx_surface *surface = gfx_create_surface_from_display(&fb); struct text_line *line; list_for_every_entry(&text_list, line, struct text_line, node) { diff --git a/platform/armemu/display.c b/platform/armemu/display.c index 72ecb7be..0ab09bae 100644 --- a/platform/armemu/display.c +++ b/platform/armemu/display.c @@ -28,6 +28,7 @@ #include #include #include +#include #define DRAW_TEST_PATTERN 0 @@ -53,17 +54,33 @@ void platform_init_display(void) #endif } -status_t display_get_info(struct display_info *info) +status_t display_get_framebuffer(struct display_framebuffer *fb) { + DEBUG_ASSERT(fb); if (!has_display()) return ERR_NOT_FOUND; - info->framebuffer = display_fb; - info->format = GFX_FORMAT_RGB_x888; - info->width = display_w; - info->height = display_h; - info->stride = display_w; - info->flush = NULL; + fb->image.format = IMAGE_FORMAT_RGB_x888; + fb->image.pixels = display_fb; + fb->image.width = display_w; + fb->image.height = display_h; + fb->image.stride = display_w; + fb->image.rowbytes = display_w * 4; + fb->flush = NULL; + fb->format = DISPLAY_FORMAT_RGB_x888; + + return NO_ERROR; +} + +status_t display_get_info(struct display_info *info) +{ + DEBUG_ASSERT(info); + if (!has_display()) + return ERR_NOT_FOUND; + + info->format = DISPLAY_FORMAT_RGB_x888; + info->width = display_w; + info->height = display_h; return NO_ERROR; } diff --git a/target/dartuinoP0/display/LS013B7DH06.c b/target/dartuinoP0/display/LS013B7DH06.c index 21730324..3e3bceab 100644 --- a/target/dartuinoP0/display/LS013B7DH06.c +++ b/target/dartuinoP0/display/LS013B7DH06.c @@ -24,63 +24,77 @@ // 1.33 Inch 3-Bit RGB Sharp Color LCD #include #include +#include -#define SET_BIT(BUF, BITNUM) ((BUF)[(BITNUM) >> 3] |= (0xff & (0x1 << ((BITNUM) & 0x07)))) +#define SET_BIT(BUF, BITNUM) ((BUF)[(BITNUM) >> 3] |= (0x1 << ((BITNUM) & 0x07))) -uint8_t lcd_get_line(uint8_t *framebuffer, uint8_t idx, uint8_t *result) +uint8_t lcd_get_line(struct display_image *image, uint8_t idx, uint8_t *result) { - framebuffer += FB_STRIDE * idx; + uint8_t *framebuffer = (uint8_t *)image->pixels + image->rowbytes * idx; memset(result, 0, MLCD_BYTES_LINE); -#if FB_FORMAT == DISPLAY_FORMAT_RGB_332 - for (int i = 0; i < MLCD_WIDTH; ++i) { - uint8_t inpix = framebuffer[i]; + if (image->format == IMAGE_FORMAT_RGB_332) { + for (int i = 0; i < MLCD_WIDTH; ++i) { + uint8_t inpix = framebuffer[i]; - int j = i * 3; + int j = i * 3; - if (inpix & 0x80) { - SET_BIT(result, j); + if (inpix & 0x80) { + SET_BIT(result, j); + } + if (inpix & 0x10) { + SET_BIT(result, j + 1); + } + if (inpix & 0x02) { + SET_BIT(result, j + 2); + } } - if (inpix & 0x10) { - SET_BIT(result, j + 1); + } else if (image->format == IMAGE_FORMAT_RGB_x111) { + int j = 0; + for (uint i = 0; i < image->width; i += 2) { + uint8_t val = *framebuffer++; + uint8_t inpix = val & 0xf; + + if (inpix & 0x4) { + SET_BIT(result, j); + } + if (inpix & 0x2) { + SET_BIT(result, j + 1); + } + if (inpix & 0x1) { + SET_BIT(result, j + 2); + } + + inpix = val >> 4; + if (inpix & 0x4) { + SET_BIT(result, j + 3); + } + if (inpix & 0x2) { + SET_BIT(result, j + 4); + } + if (inpix & 0x1) { + SET_BIT(result, j + 5); + } + j += 6; } - if (inpix & 0x02) { - SET_BIT(result, j + 2); + if (image->width & 1) { + uint8_t val = *framebuffer; + uint8_t inpix = val & 0xf; + + if (inpix & 0x4) { + SET_BIT(result, j); + } + if (inpix & 0x2) { + SET_BIT(result, j + 1); + } + if (inpix & 0x1) { + SET_BIT(result, j + 2); + } } + } else { + DEBUG_ASSERT(false); } -#elif FB_FORMAT == DISPLAY_FORMAT_RGB_x111 - for (int i = 0; i < FB_STRIDE; ++i) { - uint8_t val = framebuffer[i]; - uint8_t inpix; - - int j = i * 6; - - inpix = val & 0xf; - if (inpix & 0x4) { - SET_BIT(result, j); - } - if (inpix & 0x2) { - SET_BIT(result, j + 1); - } - if (inpix & 0x1) { - SET_BIT(result, j + 2); - } - - inpix = val >> 4; - if (inpix & 0x4) { - SET_BIT(result, j + 3); - } - if (inpix & 0x2) { - SET_BIT(result, j + 4); - } - if (inpix & 0x1) { - SET_BIT(result, j + 5); - } - } -#else - #error Unhandled FB_FORMAT -#endif return MLCD_BYTES_LINE; } diff --git a/target/dartuinoP0/display/memory_lcd_mono.c b/target/dartuinoP0/display/memory_lcd_mono.c index 7c09c07b..959afee4 100644 --- a/target/dartuinoP0/display/memory_lcd_mono.c +++ b/target/dartuinoP0/display/memory_lcd_mono.c @@ -32,26 +32,23 @@ #include #include -#define SET_BIT(BUF, BITNUM) ((BUF)[(BITNUM) >> 3] |= (0xff & (0x1 << ((BITNUM) & 0x07)))) +#define SET_BIT(BUF, BITNUM) ((BUF)[(BITNUM) >> 3] |= (0x1 << ((BITNUM) & 0x07))) -uint8_t lcd_get_line(uint8_t *framebuffer, uint8_t idx, uint8_t *result) +uint8_t lcd_get_line(struct display_image *image, uint8_t idx, uint8_t *result) { - framebuffer += FB_STRIDE * idx; + uint8_t *framebuffer = (uint8_t *) image->pixels + image->rowbytes * idx; -#if FB_FORMAT == DISPLAY_FORMAT_MONO_1 - memcpy(result, framebuffer, MLCD_BYTES_LINE); - -#elif FB_FORMAT == DISPLAY_FORMAT_MONO_8 - memset(result, 0, MLCD_BYTES_LINE); - for (uint i = 0; i < MLCD_WIDTH; ++i) { - if (framebuffer[i] > 128) { - SET_BIT(result, i); + if (image->format == IMAGE_FORMAT_MONO_1) { + memcpy(result, framebuffer, MLCD_BYTES_LINE); + } else if (image->format == IMAGE_FORMAT_MONO_8) { + memset(result, 0, MLCD_BYTES_LINE); + for (uint i = 0; i < MLCD_WIDTH; ++i) { + if (framebuffer[i] > 128) { + SET_BIT(result, i); + } } + } else { + DEBUG_ASSERT(false); } - -#else -#error Unhandled FB_FORMAT -#endif - return MLCD_BYTES_LINE; } diff --git a/target/dartuinoP0/include/target/display/LS013B7DH03.h b/target/dartuinoP0/include/target/display/LS013B7DH03.h index 5f70aae0..3e389776 100644 --- a/target/dartuinoP0/include/target/display/LS013B7DH03.h +++ b/target/dartuinoP0/include/target/display/LS013B7DH03.h @@ -30,10 +30,11 @@ #define MLCD_WIDTH ((uint16_t)128) #define MLCD_HEIGHT ((uint16_t)128) +// Ensure width corresponds to an integral number of bytes +STATIC_ASSERT((MLCD_WIDTH & 0x3) == 0); + // 1 bit per pixel divided by 8 bits per byte #define MLCD_BYTES_LINE (MLCD_WIDTH / 8) +#define MLCD_FORMAT (DISPLAY_FORMAT_MONO_1) -#define FB_FORMAT (DISPLAY_FORMAT_MONO_1) -#define FB_STRIDE (MLCD_BYTES_LINE) - -uint8_t lcd_get_line(uint8_t *framebuffer, uint8_t idx, uint8_t *result); +uint8_t lcd_get_line(struct display_image *image, uint8_t idx, uint8_t *result); diff --git a/target/dartuinoP0/include/target/display/LS013B7DH06.h b/target/dartuinoP0/include/target/display/LS013B7DH06.h index e4cd964c..1adbef2f 100644 --- a/target/dartuinoP0/include/target/display/LS013B7DH06.h +++ b/target/dartuinoP0/include/target/display/LS013B7DH06.h @@ -30,16 +30,11 @@ #define MLCD_WIDTH ((uint16_t)128) #define MLCD_HEIGHT ((uint16_t)128) +// Ensure width corresponds to an integral number of bytes +STATIC_ASSERT(((MLCD_WIDTH * 3) & 0x3) == 0); + // 3 bits per pixel (1 for each of RBG) divided by 8 bits per byte. #define MLCD_BYTES_LINE ((MLCD_WIDTH * 3) / 8) +#define MLCD_FORMAT (DISPLAY_FORMAT_RGB_111) -#if 0 -// For gbskia -#define FB_FORMAT (DISPLAY_FORMAT_RGB_x111) -#define FB_STRIDE ((MLCD_WIDTH + 1) >> 1) -#else -#define FB_FORMAT (DISPLAY_FORMAT_RGB_332) -#define FB_STRIDE (MLCD_WIDTH) -#endif - -uint8_t lcd_get_line(uint8_t *framebuffer, uint8_t idx, uint8_t *result); +uint8_t lcd_get_line(struct display_image *image, uint8_t idx, uint8_t *result); diff --git a/target/dartuinoP0/include/target/display/LS027B7DH01.h b/target/dartuinoP0/include/target/display/LS027B7DH01.h index e34889f1..b8433a44 100644 --- a/target/dartuinoP0/include/target/display/LS027B7DH01.h +++ b/target/dartuinoP0/include/target/display/LS027B7DH01.h @@ -30,10 +30,11 @@ #define MLCD_WIDTH ((uint16_t)400) #define MLCD_HEIGHT ((uint16_t)240) +// Ensure width corresponds to an integral number of bytes +STATIC_ASSERT((MLCD_WIDTH & 0x3) == 0); + // 1 bit per pixel divided by 8 bits per byte #define MLCD_BYTES_LINE (MLCD_WIDTH / 8) +#define MLCD_FORMAT (DISPLAY_FORMAT_MONO_1) -#define FB_FORMAT (DISPLAY_FORMAT_MONO_8) -#define FB_STRIDE (MLCD_WIDTH) - -uint8_t lcd_get_line(uint8_t *framebuffer, uint8_t idx, uint8_t *result); +uint8_t lcd_get_line(struct display_image *image, uint8_t idx, uint8_t *result); diff --git a/target/dartuinoP0/memory_lcd.c b/target/dartuinoP0/memory_lcd.c index 0249211e..d85488f6 100644 --- a/target/dartuinoP0/memory_lcd.c +++ b/target/dartuinoP0/memory_lcd.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -52,7 +54,7 @@ SPI_HandleTypeDef SpiHandle; #define VCOM_HI 0x02 #define VCOM_LO 0x00 -static uint8_t framebuffer[MLCD_HEIGHT * FB_STRIDE]; +static struct display_framebuffer default_fb; static uint8_t vcom_state; static void chip_select(bool s) @@ -114,10 +116,46 @@ status_t memory_lcd_init(void) return NO_ERROR; } - - static void mlcd_flush(uint starty, uint endy) { + display_present(&default_fb.image, starty, endy); +} + +status_t display_get_framebuffer(struct display_framebuffer *fb) +{ + DEBUG_ASSERT(fb); + if (!default_fb.image.pixels) { + switch (MLCD_FORMAT) { + // Use closest match format supported by gfx lib + case DISPLAY_FORMAT_RGB_111: + default_fb.image.format = IMAGE_FORMAT_RGB_332; + default_fb.image.stride = MLCD_WIDTH; + default_fb.image.rowbytes = MLCD_WIDTH; + break; + case DISPLAY_FORMAT_MONO_1: + default_fb.image.format = IMAGE_FORMAT_MONO_8; + default_fb.image.stride = MLCD_WIDTH; + default_fb.image.rowbytes = MLCD_WIDTH; + break; + default: + DEBUG_ASSERT(false); + return ERR_NOT_SUPPORTED; + } + default_fb.image.pixels = malloc(MLCD_HEIGHT * + default_fb.image.rowbytes); + default_fb.image.width = MLCD_WIDTH; + default_fb.image.height = MLCD_HEIGHT; + default_fb.flush = mlcd_flush; + default_fb.format = MLCD_FORMAT; + } + *fb = default_fb; + return NO_ERROR; +} + +status_t display_present(struct display_image *image, uint starty, uint endy) +{ + DEBUG_ASSERT(image); + status_t status = NO_ERROR; chip_select(true); static uint8_t localbuf[MLCD_BUF_SIZE]; @@ -133,7 +171,7 @@ static void mlcd_flush(uint starty, uint endy) for (uint j = starty; j <= endy; ++j) { *bufptr++ = (j + 1); - bufptr += lcd_get_line(framebuffer, j, bufptr); + bufptr += lcd_get_line(image, j, bufptr); // 8 bit trailer per line *bufptr++ = trailer; @@ -142,7 +180,9 @@ static void mlcd_flush(uint starty, uint endy) *bufptr++ = trailer; } - if (HAL_SPI_Transmit(&SpiHandle, localbuf, bufptr - localbuf, HAL_MAX_DELAY) != HAL_OK) { + if (HAL_SPI_Transmit(&SpiHandle, localbuf, bufptr - localbuf, + HAL_MAX_DELAY) != HAL_OK) { + status = ERR_GENERIC; goto finish; } @@ -151,18 +191,18 @@ static void mlcd_flush(uint starty, uint endy) finish: chip_select(false); + + return status; } status_t display_get_info(struct display_info *info) { + DEBUG_ASSERT(info); LTRACEF("display_info %p\n", info); - info->framebuffer = (void *)framebuffer; - info->format = FB_FORMAT; + info->format = MLCD_FORMAT; info->width = MLCD_WIDTH; info->height = MLCD_HEIGHT; - info->stride = FB_STRIDE; - info->flush = mlcd_flush; return NO_ERROR; } diff --git a/target/qemu-m4/m4display.c b/target/qemu-m4/m4display.c index c038dfed..a4718858 100644 --- a/target/qemu-m4/m4display.c +++ b/target/qemu-m4/m4display.c @@ -34,8 +34,8 @@ #include #include -#include #include +#include #define LOCAL_TRACE 0 @@ -202,16 +202,31 @@ static void s4lcd_flush(uint starty, uint endy) chip_select(true); } -status_t display_get_info(struct display_info *info) +status_t display_get_framebuffer(struct display_framebuffer *fb) { - LTRACEF("display_info %p\n", info); + DEBUG_ASSERT(fb); + LTRACEF("display_get_framebuffer %p\n", fb); - info->framebuffer = (void *)framebuffer; - info->format = GFX_FORMAT_RGB_2220; - info->width = M4DISPLAY_WIDTH; - info->height = M4DISPLAY_HEIGHT; - info->stride = M4DISPLAY_WIDTH; - info->flush = s4lcd_flush; + fb->image.pixels = (void *)framebuffer; + fb->image.format = IMAGE_FORMAT_RGB_2220; + fb->image.width = M4DISPLAY_WIDTH; + fb->image.height = M4DISPLAY_HEIGHT; + fb->image.stride = M4DISPLAY_WIDTH; + fb->image.rowbytes = M4DISPLAY_WIDTH; + fb->flush = s4lcd_flush; + fb->format = DISPLAY_FORMAT_UNKNOWN; //TODO + + return NO_ERROR; +} + +status_t display_get_info(struct display_info *info) +{ + DEBUG_ASSERT(info); + LTRACEF("display_info %p\n", info); + + info->format = DISPLAY_FORMAT_UNKNOWN; //TODO + info->width = M4DISPLAY_WIDTH; + info->height = M4DISPLAY_HEIGHT; return NO_ERROR; } diff --git a/target/stm32746g-eval2/lcd.c b/target/stm32746g-eval2/lcd.c index 41e08afe..ea61b396 100644 --- a/target/stm32746g-eval2/lcd.c +++ b/target/stm32746g-eval2/lcd.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include @@ -389,14 +388,37 @@ uint8_t BSP_LCD_Init(void) } /* LK display api here */ -status_t display_get_info(struct display_info *info) +status_t display_get_framebuffer(struct display_framebuffer *fb) { - info->framebuffer = (void *)hLtdcEval.LayerCfg[ActiveLayer].FBStartAdress; + fb->image.pixels = (void *)hLtdcEval.LayerCfg[ActiveLayer].FBStartAdress; if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) { - info->format = GFX_FORMAT_ARGB_8888; + fb->format = DISPLAY_FORMAT_ARGB_8888; + fb->image.format = IMAGE_FORMAT_ARGB_8888; + fb->image.rowbytes = BSP_LCD_GetXSize() * 4; } else if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) { - info->format = GFX_FORMAT_RGB_565; + fb->format = DISPLAY_FORMAT_RGB_565; + fb->image.format = IMAGE_FORMAT_RGB_565; + fb->image.rowbytes = BSP_LCD_GetXSize() * 2; + } else { + panic("unhandled pixel format\n"); + return ERR_NOT_FOUND; + } + + fb->image.width = BSP_LCD_GetXSize(); + fb->image.height = BSP_LCD_GetYSize(); + fb->image.stride = BSP_LCD_GetXSize(); + fb->flush = NULL; + + return NO_ERROR; +} + +status_t display_get_info(struct display_info *info) +{ + if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) { + info->format = DISPLAY_FORMAT_ARGB_8888; + } else if (hLtdcEval.LayerCfg[ActiveLayer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) { + info->format = DISPLAY_FORMAT_RGB_565; } else { panic("unhandled pixel format\n"); return ERR_NOT_FOUND; @@ -404,9 +426,6 @@ status_t display_get_info(struct display_info *info) info->width = BSP_LCD_GetXSize(); info->height = BSP_LCD_GetYSize(); - info->stride = BSP_LCD_GetXSize(); - info->flush = NULL; return NO_ERROR; } - diff --git a/target/stm32f746g-disco/lcd.c b/target/stm32f746g-disco/lcd.c index fd0f6bbe..3a279964 100644 --- a/target/stm32f746g-disco/lcd.c +++ b/target/stm32f746g-disco/lcd.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include @@ -402,14 +401,37 @@ uint8_t BSP_LCD_Init(void) } /* LK display (lib/gfx.h) calls this function */ -status_t display_get_info(struct display_info *info) +status_t display_get_framebuffer(struct display_framebuffer *fb) { - info->framebuffer = (void *)ltdc_handle.LayerCfg[active_layer].FBStartAdress; + fb->image.pixels = (void *)ltdc_handle.LayerCfg[active_layer].FBStartAdress; if (ltdc_handle.LayerCfg[active_layer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) { - info->format = GFX_FORMAT_ARGB_8888; + fb->format = DISPLAY_FORMAT_ARGB_8888; + fb->image.format = IMAGE_FORMAT_ARGB_8888; + fb->image.rowbytes = BSP_LCD_GetXSize() * 4; } else if (ltdc_handle.LayerCfg[active_layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) { - info->format = GFX_FORMAT_RGB_565; + fb->format = DISPLAY_FORMAT_RGB_565; + fb->image.format = IMAGE_FORMAT_RGB_565; + fb->image.rowbytes = BSP_LCD_GetXSize() * 2; + } else { + panic("unhandled pixel format\n"); + return ERR_NOT_FOUND; + } + + fb->image.width = BSP_LCD_GetXSize(); + fb->image.height = BSP_LCD_GetYSize(); + fb->image.stride = BSP_LCD_GetXSize(); + fb->flush = NULL; + + return NO_ERROR; +} + +status_t display_get_info(struct display_info *info) +{ + if (ltdc_handle.LayerCfg[active_layer].PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) { + info->format = DISPLAY_FORMAT_ARGB_8888; + } else if (ltdc_handle.LayerCfg[active_layer].PixelFormat == LTDC_PIXEL_FORMAT_RGB565) { + info->format = DISPLAY_FORMAT_RGB_565; } else { panic("unhandled pixel format\n"); return ERR_NOT_FOUND; @@ -417,9 +439,6 @@ status_t display_get_info(struct display_info *info) info->width = BSP_LCD_GetXSize(); info->height = BSP_LCD_GetYSize(); - info->stride = BSP_LCD_GetXSize(); - info->flush = NULL; return NO_ERROR; } -