diff options
-rw-r--r-- | arch/sandbox/cpu/sdl.c | 65 | ||||
-rw-r--r-- | drivers/video/sandbox_sdl.c | 23 |
2 files changed, 77 insertions, 11 deletions
diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c index bef5abd039..7ff0df2ee5 100644 --- a/arch/sandbox/cpu/sdl.c +++ b/arch/sandbox/cpu/sdl.c @@ -44,6 +44,8 @@ struct buf_info { * @stopping: true if audio will stop once it runs out of data * @texture: SDL texture to use for U-Boot display contents * @renderer: SDL renderer to use + * @src_depth: Number of bits per pixel in the source frame buffer (that we read + * from and render to SDL) */ static struct sdl_info { int width; @@ -61,6 +63,7 @@ static struct sdl_info { bool stopping; SDL_Texture *texture; SDL_Renderer *renderer; + int src_depth; } sdl; static void sandbox_sdl_poll_events(void) @@ -126,6 +129,9 @@ int sandbox_sdl_init_display(int width, int height, int log2_bpp, if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) printf("Unable to init hinting: %s", SDL_GetError()); + sdl.src_depth = 1 << log2_bpp; + if (log2_bpp != 4 && log2_bpp != 5) + log2_bpp = 5; sdl.depth = 1 << log2_bpp; sdl.pitch = sdl.width * sdl.depth / 8; SDL_Window *screen = SDL_CreateWindow("U-Boot", SDL_WINDOWPOS_UNDEFINED, @@ -137,10 +143,6 @@ int sandbox_sdl_init_display(int width, int height, int log2_bpp, SDL_GetError()); return -EIO; } - if (log2_bpp != 4 && log2_bpp != 5) { - printf("U-Boot SDL does not support depth %d\n", log2_bpp); - return -EINVAL; - } sdl.renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); @@ -165,6 +167,55 @@ int sandbox_sdl_init_display(int width, int height, int log2_bpp, return 0; } +static int copy_to_texture(void *lcd_base) +{ + char *dest; + int pitch, x, y; + int src_pitch; + void *pixels; + char *src; + int ret; + + if (sdl.src_depth == sdl.depth) { + SDL_UpdateTexture(sdl.texture, NULL, lcd_base, sdl.pitch); + return 0; + } + + /* + * We only support copying from an 8bpp to a 32bpp texture since the + * other cases are supported directly by the texture. + */ + if (sdl.depth != 32 && sdl.src_depth != 8) { + printf("Need depth 32bpp for copy\n"); + return -EINVAL; + } + + ret = SDL_LockTexture(sdl.texture, NULL, &pixels, &pitch); + if (ret) { + printf("SDL lock %d: %s\n", ret, SDL_GetError()); + return ret; + } + + /* Copy the pixels one by one */ + src_pitch = sdl.width * sdl.src_depth / 8; + for (y = 0; y < sdl.height; y++) { + char val; + + dest = pixels + y * pitch; + src = lcd_base + src_pitch * y; + for (x = 0; x < sdl.width; x++, dest += 4) { + val = *src++; + dest[0] = val; + dest[1] = val; + dest[2] = val; + dest[3] = 0; + } + } + SDL_UnlockTexture(sdl.texture); + + return 0; +} + int sandbox_sdl_sync(void *lcd_base) { struct SDL_Rect rect; @@ -173,7 +224,11 @@ int sandbox_sdl_sync(void *lcd_base) if (!sdl.texture) return 0; SDL_RenderClear(sdl.renderer); - SDL_UpdateTexture(sdl.texture, NULL, lcd_base, sdl.pitch); + ret = copy_to_texture(lcd_base); + if (ret) { + printf("copy_to_texture: %d: %s\n", ret, SDL_GetError()); + return -EIO; + } ret = SDL_RenderCopy(sdl.renderer, sdl.texture, NULL, NULL); if (ret) { printf("SDL copy %d: %s\n", ret, SDL_GetError()); diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c index 5956b59ce4..32739de4fe 100644 --- a/drivers/video/sandbox_sdl.c +++ b/drivers/video/sandbox_sdl.c @@ -48,22 +48,33 @@ static int sandbox_sdl_probe(struct udevice *dev) return 0; } -static int sandbox_sdl_bind(struct udevice *dev) +static void set_bpp(struct udevice *dev, enum video_log2_bpp l2bpp) { struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); struct sandbox_sdl_plat *plat = dev_get_plat(dev); - int ret = 0; - plat->xres = dev_read_u32_default(dev, "xres", LCD_MAX_WIDTH); - plat->yres = dev_read_u32_default(dev, "yres", LCD_MAX_HEIGHT); - plat->bpix = dev_read_u32_default(dev, "log2-depth", VIDEO_BPP16); - plat->rot = dev_read_u32_default(dev, "rotate", 0); + plat->bpix = l2bpp; + uc_plat->size = plat->xres * plat->yres * (1 << plat->bpix) / 8; /* Allow space for two buffers, the lower one being the copy buffer */ log_debug("Frame buffer size %x\n", uc_plat->size); if (IS_ENABLED(CONFIG_VIDEO_COPY)) uc_plat->size *= 2; +} + +static int sandbox_sdl_bind(struct udevice *dev) +{ + struct sandbox_sdl_plat *plat = dev_get_plat(dev); + enum video_log2_bpp l2bpp; + int ret = 0; + + plat->xres = dev_read_u32_default(dev, "xres", LCD_MAX_WIDTH); + plat->yres = dev_read_u32_default(dev, "yres", LCD_MAX_HEIGHT); + l2bpp = dev_read_u32_default(dev, "log2-depth", VIDEO_BPP16); + plat->rot = dev_read_u32_default(dev, "rotate", 0); + + set_bpp(dev, l2bpp); return ret; } |