summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-memframe.c
diff options
context:
space:
mode:
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2007, 2011 Michael Sevakis
11 *
12 * Shared C code for memory framebuffer LCDs
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include <sys/types.h> /* off_t */
24#include "config.h"
25#include "system.h"
26#include "lcd.h"
27#include "lcd-target.h"
28
29/*** Misc. functions ***/
30
31static bool lcd_on SHAREDBSS_ATTR = false; /* Is the display turned on? */
32
33bool lcd_active(void)
34{
35 return lcd_on;
36}
37
38/* For use by target driver only! */
39void lcd_set_active(bool active)
40{
41 lcd_on = active;
42}
43
44/*** Blitting functions ***/
45
46/* Copies a rectangle from one framebuffer to another. Can be used in
47 single transfer mode with width = num pixels, and height = 1 which
48 allows a full-width rectangle to be copied more efficiently. */
49extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
50 int width, int height);
51
52/* Update the display.
53 This must be called after all other LCD functions that change the display. */
54void lcd_update(void)
55{
56 if (!lcd_on)
57 return;
58
59 /* Copy the Rockbox framebuffer to the second framebuffer */
60 lcd_copy_buffer_rect(LCD_FRAMEBUF_ADDR(0, 0), &lcd_framebuffer[0][0],
61 LCD_WIDTH*LCD_HEIGHT, 1);
62}
63
64void lcd_update_rect(int x, int y, int width, int height)
65{
66 fb_data *dst, *src;
67
68 if (!lcd_on)
69 return;
70
71 if (x + width > LCD_WIDTH)
72 width = LCD_WIDTH - x; /* Clip right */
73 if (x < 0)
74 width += x, x = 0; /* Clip left */
75 if (width <= 0)
76 return; /* nothing left to do */
77
78 if (y + height > LCD_HEIGHT)
79 height = LCD_HEIGHT - y; /* Clip bottom */
80 if (y < 0)
81 height += y, y = 0; /* Clip top */
82 if (height <= 0)
83 return; /* nothing left to do */
84
85 dst = LCD_FRAMEBUF_ADDR(x, y);
86 src = &lcd_framebuffer[y][x];
87
88 /* Copy part of the Rockbox framebuffer to the second framebuffer */
89 if (width < LCD_WIDTH)
90 {
91 /* Not full width - do line-by-line */
92 lcd_copy_buffer_rect(dst, src, width, height);
93 }
94 else
95 {
96 /* Full width - copy as one line */
97 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
98 }
99}
100
101
102/*** YUV functions ***/
103static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
104
105
106/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
107extern void lcd_write_yuv420_lines(fb_data *dst,
108 unsigned char const * const src[3],
109 int width,
110 int stride);
111extern void lcd_write_yuv420_lines_odither(fb_data *dst,
112 unsigned char const * const src[3],
113 int width,
114 int stride,
115 int x_screen, /* To align dither pattern */
116 int y_screen);
117
118void lcd_yuv_set_options(unsigned options)
119{
120 lcd_yuv_options = options;
121}
122
123/* Performance function to blit a YUV bitmap directly to the LCD */
124/* For the e200 - show it rotated */
125/* So the LCD_WIDTH is now the height */
126void lcd_blit_yuv(unsigned char * const src[3],
127 int src_x, int src_y, int stride,
128 int x, int y, int width, int height)
129{
130 unsigned char const * yuv_src[3];
131 off_t z;
132
133 if (!lcd_on)
134 return;
135
136 /* Sorry, but width and height must be >= 2 or else */
137 width &= ~1;
138 height >>= 1;
139
140 y = LCD_WIDTH - 1 - y;
141 fb_data *dst = LCD_FRAMEBUF_ADDR(y, x);
142
143 z = stride*src_y;
144 yuv_src[0] = src[0] + z + src_x;
145 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
146 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
147
148 if (lcd_yuv_options & LCD_YUV_DITHER)
149 {
150 do
151 {
152 lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x);
153 yuv_src[0] += stride << 1; /* Skip down two luma lines */
154 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
155 yuv_src[2] += stride >> 1;
156 dst -= 2;
157 y -= 2;
158 }
159 while (--height > 0);
160 }
161 else
162 {
163 do
164 {
165 lcd_write_yuv420_lines(dst, yuv_src, width, stride);
166 yuv_src[0] += stride << 1; /* Skip down two luma lines */
167 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
168 yuv_src[2] += stride >> 1;
169 dst -= 2;
170 }
171 while (--height > 0);
172 }
173}