| /*************************************************************************** |
| * __________ __ ___. |
| * 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); |
| } |
| |
| |