summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-memframe.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-12-15 23:07:11 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-12-15 23:07:11 +0000
commit62facd1ff233a4734e4bc3d616ac22c5c56f926c (patch)
tree95d22b472e7ec548fbb0c239de7bd4e657437b88 /firmware/drivers/lcd-memframe.c
parentf53b8ff959ee4443593569440403229108e26b3d (diff)
Collect some of the memory frame LCD C code.
For this commit: Sansa e200v1, Gigabeat F, Gigabeat S and Mini2440 are changed over. Quite a number of other targets probably can be as well. General LCD code is moved out of the target drivers into drivers/lcd-memframe.c. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31311 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-memframe.c')
-rw-r--r--firmware/drivers/lcd-memframe.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/firmware/drivers/lcd-memframe.c b/firmware/drivers/lcd-memframe.c
new file mode 100644
index 0000000000..fda12012b9
--- /dev/null
+++ b/firmware/drivers/lcd-memframe.c
@@ -0,0 +1,173 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2007, 2011 Michael Sevakis
+ *
+ * Shared C code for memory framebuffer LCDs
+ *
+ * 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 <sys/types.h> /* off_t */
+#include "config.h"
+#include "system.h"
+#include "lcd.h"
+#include "lcd-target.h"
+
+/*** Misc. functions ***/
+
+static bool lcd_on SHAREDBSS_ATTR = false; /* Is the display turned on? */
+
+bool lcd_active(void)
+{
+ return lcd_on;
+}
+
+/* For use by target driver only! */
+void lcd_set_active(bool active)
+{
+ lcd_on = active;
+}
+
+/*** Blitting functions ***/
+
+/* Copies a rectangle from one framebuffer to another. Can be used in
+ single transfer mode with width = num pixels, and height = 1 which
+ allows a full-width rectangle to be copied more efficiently. */
+extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
+ int width, int height);
+
+/* Update the display.
+ This must be called after all other LCD functions that change the display. */
+void lcd_update(void)
+{
+ if (!lcd_on)
+ return;
+
+ /* Copy the Rockbox framebuffer to the second framebuffer */
+ lcd_copy_buffer_rect(LCD_FRAMEBUF_ADDR(0, 0), &lcd_framebuffer[0][0],
+ LCD_WIDTH*LCD_HEIGHT, 1);
+}
+
+void lcd_update_rect(int x, int y, int width, int height)
+{
+ fb_data *dst, *src;
+
+ if (!lcd_on)
+ return;
+
+ if (x + width > LCD_WIDTH)
+ width = LCD_WIDTH - x; /* Clip right */
+ if (x < 0)
+ width += x, x = 0; /* Clip left */
+ if (width <= 0)
+ return; /* nothing left to do */
+
+ if (y + height > LCD_HEIGHT)
+ height = LCD_HEIGHT - y; /* Clip bottom */
+ if (y < 0)
+ height += y, y = 0; /* Clip top */
+ if (height <= 0)
+ return; /* nothing left to do */
+
+ dst = LCD_FRAMEBUF_ADDR(x, y);
+ src = &lcd_framebuffer[y][x];
+
+ /* Copy part of the Rockbox framebuffer to the second framebuffer */
+ if (width < LCD_WIDTH)
+ {
+ /* Not full width - do line-by-line */
+ lcd_copy_buffer_rect(dst, src, width, height);
+ }
+ else
+ {
+ /* Full width - copy as one line */
+ lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
+ }
+}
+
+
+/*** YUV functions ***/
+static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
+
+
+/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
+extern void lcd_write_yuv420_lines(fb_data *dst,
+ unsigned char const * const src[3],
+ int width,
+ int stride);
+extern void lcd_write_yuv420_lines_odither(fb_data *dst,
+ unsigned char const * const src[3],
+ int width,
+ int stride,
+ int x_screen, /* To align dither pattern */
+ int y_screen);
+
+void lcd_yuv_set_options(unsigned options)
+{
+ lcd_yuv_options = options;
+}
+
+/* Performance function to blit a YUV bitmap directly to the LCD */
+/* For the e200 - show it rotated */
+/* So the LCD_WIDTH is now the height */
+void lcd_blit_yuv(unsigned char * const src[3],
+ int src_x, int src_y, int stride,
+ int x, int y, int width, int height)
+{
+ unsigned char const * yuv_src[3];
+ off_t z;
+
+ if (!lcd_on)
+ return;
+
+ /* Sorry, but width and height must be >= 2 or else */
+ width &= ~1;
+ height >>= 1;
+
+ y = LCD_WIDTH - 1 - y;
+ fb_data *dst = LCD_FRAMEBUF_ADDR(y, x);
+
+ z = stride*src_y;
+ yuv_src[0] = src[0] + z + src_x;
+ yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
+ yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
+
+ if (lcd_yuv_options & LCD_YUV_DITHER)
+ {
+ do
+ {
+ lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x);
+ yuv_src[0] += stride << 1; /* Skip down two luma lines */
+ yuv_src[1] += stride >> 1; /* Skip down one chroma line */
+ yuv_src[2] += stride >> 1;
+ dst -= 2;
+ y -= 2;
+ }
+ while (--height > 0);
+ }
+ else
+ {
+ do
+ {
+ lcd_write_yuv420_lines(dst, yuv_src, width, stride);
+ yuv_src[0] += stride << 1; /* Skip down two luma lines */
+ yuv_src[1] += stride >> 1; /* Skip down one chroma line */
+ yuv_src[2] += stride >> 1;
+ dst -= 2;
+ }
+ while (--height > 0);
+ }
+}