d6dbfef452
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25962 a1c6a512-1295-4272-9138-f99709370657
170 lines
5.4 KiB
C
170 lines
5.4 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 by Linus Nielsen Feltzing
|
|
* Copyright (C) 2009 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 <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "config.h"
|
|
#include "buffer.h"
|
|
#include "settings.h"
|
|
#include "screen_access.h"
|
|
#include "skin_engine.h"
|
|
#include "wps_internals.h"
|
|
#include "skin_tokens.h"
|
|
#include "skin_buffer.h"
|
|
#include "skin_fonts.h"
|
|
|
|
/* skin buffer management.
|
|
* This module is used to allocate space in a single global skin buffer for
|
|
* tokens for both/all screens.
|
|
*
|
|
* This is mostly just copy/paste from firmware/buffer.c
|
|
*
|
|
*
|
|
* MAIN_ and REMOTE_BUFFER are just for reasonable size calibration,
|
|
* both screens can use the whole buffer as they need; it's not split
|
|
* between screens
|
|
*
|
|
* Buffer can be allocated from either "end" of the global buffer.
|
|
* items with unknown sizes get allocated from the start (0->) (data)
|
|
* items with known sizes get allocated from the end (<-buf_size) (tokens)
|
|
* After loading 2 skins the buffer will look like this:
|
|
* |tokens skin1|images skin1|tokens s2|images s2|---SPACE---|data skin2|data skin1|
|
|
* Make sure to never start allocating from the beginning before letting us know
|
|
* how much was used. and RESPECT THE buf_free RETURN VALUES!
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
#define MAIN_BUFFER ((2*LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
|
|
+ (SKINNABLE_SCREENS_COUNT * LCD_BACKDROP_BYTES))
|
|
|
|
#if (NB_SCREENS > 1)
|
|
#define REMOTE_BUFFER (2*(LCD_REMOTE_HEIGHT*LCD_REMOTE_WIDTH*LCD_REMOTE_DEPTH/8) \
|
|
+ (SKINNABLE_SCREENS_COUNT * REMOTE_LCD_BACKDROP_BYTES))
|
|
#else
|
|
#define REMOTE_BUFFER 0
|
|
#endif
|
|
|
|
|
|
#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER + SKIN_FONT_SIZE) + \
|
|
(WPS_MAX_TOKENS * sizeof(struct wps_token))
|
|
#endif
|
|
|
|
#ifdef HAVE_LCD_CHARCELLS
|
|
#define SKIN_BUFFER_SIZE (LCD_HEIGHT * LCD_WIDTH) * 64 + \
|
|
(WPS_MAX_TOKENS * sizeof(struct wps_token))
|
|
#endif
|
|
|
|
static unsigned char buffer[SKIN_BUFFER_SIZE];
|
|
static unsigned char *buffer_front = NULL; /* start of the free space,
|
|
increases with allocation*/
|
|
static unsigned char *buffer_back = NULL; /* end of the free space
|
|
decreases with allocation */
|
|
static size_t buf_size = SKIN_BUFFER_SIZE;
|
|
|
|
void skin_buffer_init(void)
|
|
{
|
|
#if 0 /* this will go in again later probably */
|
|
if (buffer == NULL)
|
|
{
|
|
buf_size = SKIN_BUFFER_SIZE;/* global_settings.skin_buf_size */
|
|
|
|
buffer = buffer_alloc(buf_size);
|
|
buffer_front = buffer;
|
|
buffer_back = bufer + buf_size;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* reset the buffer.... */
|
|
buffer_front = buffer;
|
|
buffer_back = buffer + buf_size;
|
|
}
|
|
}
|
|
|
|
/* get the number of bytes currently being used */
|
|
size_t skin_buffer_usage(void)
|
|
{
|
|
return buf_size - (buffer_back-buffer_front);
|
|
}
|
|
|
|
size_t skin_buffer_freespace(void)
|
|
{
|
|
return buffer_back-buffer_front;
|
|
}
|
|
|
|
/* Allocate size bytes from the buffer
|
|
* allocates from the back end (data end)
|
|
*/
|
|
void* skin_buffer_alloc(size_t size)
|
|
{
|
|
if (skin_buffer_freespace() <= size)
|
|
{
|
|
return NULL;
|
|
}
|
|
buffer_back -= size;
|
|
/* 32-bit aligned */
|
|
buffer_back = (void *)(((unsigned long)buffer_back) & ~3);
|
|
|
|
memset(buffer_back, 0, size);
|
|
return buffer_back;
|
|
}
|
|
|
|
/* Get a pointer to the skin buffer and the count of how much is free
|
|
* used to do your own buffer management.
|
|
* Any memory used will be overwritten next time wps_buffer_alloc()
|
|
* is called unless skin_buffer_increment() is called first
|
|
*
|
|
* This is from the start of the buffer, it is YOUR responsility to make
|
|
* sure you dont ever use more then *freespace, and bear in mind this will only
|
|
* be valid untill skin_buffer_alloc() is next called...
|
|
* so call skin_buffer_increment() and skin_buffer_freespace() regularly
|
|
*/
|
|
void* skin_buffer_grab(size_t *freespace)
|
|
{
|
|
*freespace = buf_size - skin_buffer_usage();
|
|
return buffer_front;
|
|
}
|
|
|
|
/* Use after skin_buffer_grab() to specify how much buffer was used */
|
|
void skin_buffer_increment(size_t used, bool align)
|
|
{
|
|
buffer_front += used;
|
|
if (align)
|
|
{
|
|
/* 32-bit aligned */
|
|
buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
|
|
}
|
|
}
|
|
|
|
/* free previously skin_buffer_increment()'ed space. This just moves the pointer
|
|
* back 'used' bytes so make sure you actually want to do this */
|
|
void skin_buffer_free_from_front(size_t used)
|
|
{
|
|
buffer_front -= used;
|
|
/* 32-bit aligned */
|
|
buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
|
|
}
|
|
|
|
|