diff options
Diffstat (limited to 'firmware/drivers/lcd-memframe.c')
-rw-r--r-- | firmware/drivers/lcd-memframe.c | 173 |
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 | |||
31 | static bool lcd_on SHAREDBSS_ATTR = false; /* Is the display turned on? */ | ||
32 | |||
33 | bool lcd_active(void) | ||
34 | { | ||
35 | return lcd_on; | ||
36 | } | ||
37 | |||
38 | /* For use by target driver only! */ | ||
39 | void 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. */ | ||
49 | extern 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. */ | ||
54 | void 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 | |||
64 | void 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 ***/ | ||
103 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
104 | |||
105 | |||
106 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
107 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
108 | unsigned char const * const src[3], | ||
109 | int width, | ||
110 | int stride); | ||
111 | extern 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 | |||
118 | void 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 */ | ||
126 | void 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 | } | ||