* @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;
bool stopping;
SDL_Texture *texture;
SDL_Renderer *renderer;
+ int src_depth;
} sdl;
static void sandbox_sdl_poll_events(void)
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,
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);
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;
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());
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;
}