rockbox/apps/gui/skin_engine/skin_backdrops.c
William Wilgus c5c17fa799 Fix display regression from c85d8e2
Basically setting a null buffer is valid but it must be selected
into a screen to initialize to the default buffer

I wrongly assumed screen type wouldn't matter but since I decided to
reference backdrops directly to the default buffer
(since they are saved as an offset from what it later assumes to be the
default framebuffer)
SCREEN_MAIN/SCREEN_REMOTE are not longer optional

Change-Id: I8a8afbbe1e3ed0bfe6abd40ce287638e9fc6da60
2020-10-28 22:55:27 -04:00

338 lines
10 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2010 Jonathan Gordon
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "core_alloc.h"
#include "string-extra.h"
#include "settings.h"
#include "wps_internals.h"
#include "skin_engine.h"
#if !defined(__PCTOOL__) && defined(HAVE_BACKDROP_IMAGE)
#define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS
static struct skin_backdrop {
char name[MAX_PATH];
char *buffer;
enum screen_type screen;
bool loaded;
int buflib_handle;
int ref_count;
} backdrops[NB_BDROPS];
#define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS
static int handle_being_loaded;
static int current_lcd_backdrop[NB_SCREENS];
bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *size)
{
if (index + 1 >= NB_BDROPS)
return false;
*path = backdrops[index].name;
*ref_count = backdrops[index].ref_count;
#if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
enum screen_type screen = backdrops[index].screen;
if (screen == SCREEN_REMOTE)
*size = REMOTE_LCD_BACKDROP_BYTES;
else
#endif
*size = LCD_BACKDROP_BYTES;
return true;
}
static int buflib_move_callback(int handle, void* current, void* new)
{
if (handle == handle_being_loaded)
return BUFLIB_CB_CANNOT_MOVE;
for (int i=0; i<NB_BDROPS; i++)
{
if (backdrops[i].buffer == current)
{
backdrops[i].buffer = new;
break;
}
}
FOR_NB_SCREENS(i)
skin_backdrop_show(current_lcd_backdrop[i]);
return BUFLIB_CB_OK;
}
static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL};
static bool first_go = true;
void skin_backdrop_init(void)
{
if (first_go)
{
for (int i=0; i<NB_BDROPS; i++)
{
backdrops[i].buflib_handle = -1;
backdrops[i].name[0] = '\0';
backdrops[i].buffer = NULL;
backdrops[i].loaded = false;
backdrops[i].ref_count = 0;
}
FOR_NB_SCREENS(i)
current_lcd_backdrop[i] = -1;
handle_being_loaded = -1;
first_go = false;
}
}
int skin_backdrop_assign(char* backdrop, char *bmpdir,
enum screen_type screen)
{
char filename[MAX_PATH];
int i, free = -1;
if (!backdrop)
return -1;
if (backdrop[0] == '-')
{
filename[0] = '-';
filename[1] = '\0';
filename[2] = '\0'; /* we check this later to see if we actually have an
image to load. != '\0' means display the image */
}
else if (!strcmp(backdrop, BACKDROP_BUFFERNAME))
{
strcpy(filename, backdrop);
}
else
{
get_image_filename(backdrop, bmpdir, filename, sizeof(filename));
}
for (i=0; i<NB_BDROPS; i++)
{
if (!backdrops[i].name[0] && free < 0)
{
free = i;
break;
}
else if (!strcmp(backdrops[i].name, filename) && backdrops[i].screen == screen)
{
backdrops[i].ref_count++;
break;
}
}
if (free >= 0)
{
strlcpy(backdrops[free].name, filename, MAX_PATH);
backdrops[free].buffer = NULL;
backdrops[free].screen = screen;
backdrops[free].ref_count = 1;
return free;
}
else if (i < NB_BDROPS)
return i;
return -1;
}
bool skin_backdrops_preload(void)
{
bool retval = true;
int i;
char *filename;
for (i=0; i<NB_BDROPS; i++)
{
if (backdrops[i].name[0] && !backdrops[i].buffer)
{
size_t buf_size;
enum screen_type screen = backdrops[i].screen;
#if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
if (screen == SCREEN_REMOTE)
buf_size = REMOTE_LCD_BACKDROP_BYTES;
else
#endif
buf_size = LCD_BACKDROP_BYTES;
filename = backdrops[i].name;
if (screen == SCREEN_MAIN && global_settings.backdrop_file[0] &&
global_settings.backdrop_file[0] != '-' && filename[0] == '-')
{
filename = global_settings.backdrop_file;
}
if (*filename && *filename != '-')
{
backdrops[i].buflib_handle = core_alloc_ex(filename, buf_size, &buflib_ops);
if (backdrops[i].buflib_handle > 0)
{
backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle);
if (strcmp(filename, BACKDROP_BUFFERNAME))
{
handle_being_loaded = backdrops[i].buflib_handle;
backdrops[i].loaded =
screens[screen].backdrop_load(filename, backdrops[i].buffer);
if (!backdrops[i].loaded)
{
core_free(backdrops[i].buflib_handle);
backdrops[i].buflib_handle = -1;
retval = false;
}
handle_being_loaded = -1;
}
else
backdrops[i].loaded = true;
}
else
retval = false;
}
if (backdrops[i].name[0] == '-' && backdrops[i].loaded)
backdrops[i].name[2] = '.';
}
}
return retval;
}
void skin_backdrop_set_buffer(int backdrop_id, struct skin_viewport *svp)
{
if (UNLIKELY(!svp))
return;
else if (backdrop_id < 0)
{
#if 1
/* ensure the current vp has been removed so it has to be reselected */
screens[SCREEN_MAIN].set_viewport_ex(NULL, 0);
# if defined(HAVE_REMOTE_LCD)
screens[SCREEN_REMOTE].set_viewport_ex(NULL, 0);
# endif
#endif
/* WARNING: vp-> buffer is invaid till viewport is set to a screen */
svp->vp.buffer = NULL; /*Default*/
return;
}
enum screen_type screen = backdrops[backdrop_id].screen;
svp->framebuf.ch_ptr = backdrops[backdrop_id].buffer;
#if defined(HAVE_REMOTE_LCD)
if (screen == SCREEN_REMOTE)
svp->framebuf.elems = REMOTE_LCD_BACKDROP_BYTES / sizeof(fb_remote_data);
else
#endif
{
svp->framebuf.elems = LCD_BACKDROP_BYTES / sizeof(fb_data);
}
svp->framebuf.stride = 0; /* default stride */
svp->framebuf.get_address_fn = NULL; /*Default iterator*/
screens[screen].viewport_set_buffer(&svp->vp, &svp->framebuf);
}
void skin_backdrop_show(int backdrop_id)
{
if (backdrop_id < 0)
{
screens[0].backdrop_show(NULL);
current_lcd_backdrop[0] = -1;
return;
}
enum screen_type screen = backdrops[backdrop_id].screen;
if ((backdrops[backdrop_id].loaded == false) ||
(backdrops[backdrop_id].name[0] == '-' &&
backdrops[backdrop_id].name[2] == '\0'))
{
screens[screen].backdrop_show(NULL);
current_lcd_backdrop[screen] = -1;
}
else if (backdrops[backdrop_id].buffer)
{
screens[screen].backdrop_show(backdrops[backdrop_id].buffer);
current_lcd_backdrop[screen] = backdrop_id;
}
}
void skin_backdrop_unload(int backdrop_id)
{
backdrops[backdrop_id].ref_count--;
if (backdrops[backdrop_id].ref_count <= 0)
{
if (backdrops[backdrop_id].buflib_handle > 0)
core_free(backdrops[backdrop_id].buflib_handle);
backdrops[backdrop_id].buffer = NULL;
backdrops[backdrop_id].buflib_handle = -1;
backdrops[backdrop_id].loaded = false;
backdrops[backdrop_id].name[0] = '\0';
backdrops[backdrop_id].ref_count = 0;
}
}
void skin_backdrop_load_setting(void)
{
int i;
for(i=0;i<SKINNABLE_SCREENS_COUNT*NB_SCREENS;i++)
{
if (backdrops[i].name[0] == '-' && backdrops[i].screen == SCREEN_MAIN)
{
if (global_settings.backdrop_file[0] &&
global_settings.backdrop_file[0] != '-')
{
if (backdrops[i].buflib_handle <= 0)
{
backdrops[i].buflib_handle =
core_alloc_ex(global_settings.backdrop_file,
LCD_BACKDROP_BYTES, &buflib_ops);
if (backdrops[i].buflib_handle <= 0)
return;
}
bool loaded;
backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle);
handle_being_loaded = backdrops[i].buflib_handle;
loaded = screens[SCREEN_MAIN].backdrop_load(
global_settings.backdrop_file,
backdrops[i].buffer);
handle_being_loaded = -1;
backdrops[i].name[2] = loaded ? '.' : '\0';
backdrops[i].loaded = loaded;
return;
}
else
backdrops[i].name[2] = '\0';
}
#if NB_SCREENS > 1
else if (backdrops[i].name[0] == '-')
{
backdrops[i].name[2] = '\0';
return;
}
#endif
}
}
#elif defined(__PCTOOL__)
int skin_backdrop_assign(char* backdrop, char *bmpdir,
enum screen_type screen)
{
(void)backdrop;
(void)bmpdir;
(void)screen;
return 0;
}
void skin_backdrop_unload(int backdrop_id)
{
(void)backdrop_id;
}
#else
void skin_backdrop_init(void)
{
}
#endif