diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-07-08 17:10:22 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-07-08 17:10:22 +0000 |
commit | 897c64399196745407ff022c595ff07c07cc01bb (patch) | |
tree | 5fcf888e93aa8e51a11a2538629c148d41e0f9e3 | |
parent | 3f8c075f24fdcb4c471a4a0ae149f730e339450d (diff) | |
download | rockbox-897c64399196745407ff022c595ff07c07cc01bb.tar.gz rockbox-897c64399196745407ff022c595ff07c07cc01bb.zip |
Gigabeat: properly confined framebuffer copies and a few pendantic changes to lcd_yuv_blit. No difference full screen but quite a speedup to copy only the required bit: 534->1062 fps for 1/4 screen update using test_fps.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13821 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S | 101 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 86 |
2 files changed, 146 insertions, 41 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S index d431c95f29..f4805fd1e1 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S +++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S | |||
@@ -21,6 +21,87 @@ | |||
21 | #include "cpu.h" | 21 | #include "cpu.h" |
22 | 22 | ||
23 | /**************************************************************************** | 23 | /**************************************************************************** |
24 | * void lcd_copy_buffer_rect(fb_data *dst, fb_data *src, int width, | ||
25 | * int height); | ||
26 | */ | ||
27 | .section .icode, "ax", %progbits | ||
28 | .align 2 | ||
29 | .global lcd_copy_buffer_rect | ||
30 | .type lcd_copy_buffer_rect, %function | ||
31 | @ r0 = dst | ||
32 | @ r1 = src | ||
33 | @ r2 = width | ||
34 | @ r3 = height | ||
35 | lcd_copy_buffer_rect: @ | ||
36 | stmfd sp!, { r4-r12, lr } @ save non-scratch regs | ||
37 | mov r5, r2 @ r5 = cached width | ||
38 | rsb r4, r2, #LCD_WIDTH @ r4 = LCD_WIDTH - width | ||
39 | 10: @ copy line @ | ||
40 | subs r2, r5, #1 @ r2 = width - 1 | ||
41 | beq 40f @ finish line @ one halfword? skip to trailing copy | ||
42 | tst r0, #2 @ word aligned? | ||
43 | beq 20f @ rem copy @ yes? skip to word copy | ||
44 | ldrh r6, [r1], #2 @ copy leading halfword | ||
45 | subs r2, r2, #1 @ | ||
46 | strh r6, [r0], #2 @ | ||
47 | ble 40f @ finish line @ next line if lt or finish | ||
48 | @ trailing halfword if eq | ||
49 | 20: @ rem copy @ | ||
50 | add r14, r2, #1 @ get remaining width mod 16 after word | ||
51 | @ align (rw) | ||
52 | and r14, r14, #0xe @ r14 = 0 (16), 2, 4, 6, 8, 10, 12, 14 | ||
53 | add pc, pc, r14, lsl #3 @ branch to 32-byte align | ||
54 | nop @ | ||
55 | b 30f @ rw % 16 = 0 or 1? use octword loop | ||
56 | nop @ | ||
57 | nop @ | ||
58 | nop @ | ||
59 | ldr r6, [r1], #4 @ rw % 16 = 2 or 3 | ||
60 | subs r2, r2, #2 @ | ||
61 | str r6, [r0], #4 @ | ||
62 | b 25f @ copy up done @ | ||
63 | ldmia r1!, { r6-r7 } @ rw % 16 = 4 or 5 | ||
64 | subs r2, r2, #4 @ | ||
65 | stmia r0!, { r6-r7 } @ | ||
66 | b 25f @ copy up done @ | ||
67 | ldmia r1!, { r6-r8 } @ rw % 16 = 6 or 7 | ||
68 | subs r2, r2, #6 @ | ||
69 | stmia r0!, { r6-r8 } @ | ||
70 | b 25f @ copy up done @ | ||
71 | ldmia r1!, { r6-r9 } @ rw % 16 = 8 or 9 | ||
72 | subs r2, r2, #8 @ | ||
73 | stmia r0!, { r6-r9 } @ | ||
74 | b 25f @ copy up done @ | ||
75 | ldmia r1!, { r6-r10 } @ rw % 16 = 10 or 11 | ||
76 | subs r2, r2, #10 @ | ||
77 | stmia r0!, { r6-r10 } @ | ||
78 | b 25f @ copy up done @ | ||
79 | ldmia r1!, { r6-r11 } @ rw % 16 = 12 or 13 | ||
80 | subs r2, r2, #12 @ | ||
81 | stmia r0!, { r6-r11 } @ | ||
82 | b 25f @ copy up done @ | ||
83 | ldmia r1!, { r6-r12 } @ rw % 16 = 14 or 15 | ||
84 | subs r2, r2, #14 @ | ||
85 | stmia r0!, { r6-r12 } @ | ||
86 | 25: @ copy up done @ | ||
87 | ble 40f @ finish line @ no 32-byte segments remaining? | ||
88 | 30: @ octword loop @ copy 16 pixels per loop | ||
89 | ldmia r1!, { r6-r12, r14 } @ | ||
90 | subs r2, r2, #16 @ | ||
91 | stmia r0!, { r6-r12, r14 } @ | ||
92 | bgt 30b @ octword loop @ | ||
93 | 40: @ finish line @ | ||
94 | ldreqh r6, [r1], #2 @ finish last halfword if eq ... | ||
95 | add r1, r1, r4, lsl #1 @ | ||
96 | streqh r6, [r0], #2 @ ... | ||
97 | add r0, r0, r4, lsl #1 @ | ||
98 | subs r3, r3, #1 @ next line | ||
99 | bgt 10b @ copy line @ | ||
100 | ldmfd sp!, { r4-r12, pc } @ restore regs and return | ||
101 | .size lcd_copy_buffer_rect, .-lcd_copy_buffer_rect | ||
102 | |||
103 | |||
104 | /**************************************************************************** | ||
24 | * void lcd_write_yuv_420_lines(fb_data *dst, | 105 | * void lcd_write_yuv_420_lines(fb_data *dst, |
25 | * unsigned char chroma_buf[LCD_HEIGHT/2*3], | 106 | * unsigned char chroma_buf[LCD_HEIGHT/2*3], |
26 | unsigned char const * const src[3], | 107 | unsigned char const * const src[3], |
@@ -45,8 +126,8 @@ lcd_write_yuv420_lines: | |||
45 | @ r2 = yuv_src | 126 | @ r2 = yuv_src |
46 | @ r3 = width | 127 | @ r3 = width |
47 | @ [sp] = stride | 128 | @ [sp] = stride |
48 | stmdb sp!, { r4-r12, lr } @ save non-scratch | 129 | stmfd sp!, { r4-r12, lr } @ save non-scratch |
49 | stmdb sp!, { r0, r3 } @ save dst and width | 130 | stmfd sp!, { r0, r3 } @ save dst and width |
50 | mov r14, #74 @ r14 = Y factor | 131 | mov r14, #74 @ r14 = Y factor |
51 | ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | 132 | ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p |
52 | @ r5 = yuv_src[1] = Cb_p | 133 | @ r5 = yuv_src[1] = Cb_p |
@@ -105,7 +186,7 @@ lcd_write_yuv420_lines: | |||
105 | orr r12, r2, r7, lsl #5 @ r4 |= (g << 5) | 186 | orr r12, r2, r7, lsl #5 @ r4 |= (g << 5) |
106 | ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ | 187 | ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ |
107 | orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11) | 188 | orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11) |
108 | strh r12, [r0], #240 @ store pixel | 189 | strh r12, [r0], #LCD_WIDTH @ store pixel |
109 | @ | 190 | @ |
110 | sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74 | 191 | sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74 |
111 | mul r7, r2, r14 @ next Y | 192 | mul r7, r2, r14 @ next Y |
@@ -133,14 +214,14 @@ lcd_write_yuv420_lines: | |||
133 | @ | 214 | @ |
134 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) | 215 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) |
135 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) | 216 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) |
136 | strh r12, [r0, #240]! @ store pixel | 217 | strh r12, [r0, #LCD_WIDTH]! @ store pixel |
137 | add r0, r0, #2*240 @ | 218 | add r0, r0, #2*LCD_WIDTH @ |
138 | @ | 219 | @ |
139 | subs r3, r3, #2 @ | 220 | subs r3, r3, #2 @ |
140 | bgt 10b @ loop line 1 @ | 221 | bgt 10b @ loop line 1 @ |
141 | @ do second line | 222 | @ do second line |
142 | @ | 223 | @ |
143 | ldmia sp!, { r0, r3 } @ pop dst and width | 224 | ldmfd sp!, { r0, r3 } @ pop dst and width |
144 | sub r0, r0, #2 @ set dst to start of next line | 225 | sub r0, r0, #2 @ set dst to start of next line |
145 | sub r1, r1, r3, asl #1 @ rewind chroma pointer... | 226 | sub r1, r1, r3, asl #1 @ rewind chroma pointer... |
146 | ldr r2, [sp, #40] @ r2 = stride | 227 | ldr r2, [sp, #40] @ r2 = stride |
@@ -182,7 +263,7 @@ lcd_write_yuv420_lines: | |||
182 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) | 263 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) |
183 | ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ | 264 | ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ |
184 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) | 265 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) |
185 | strh r12, [r0], #240 @ store pixel | 266 | strh r12, [r0], #LCD_WIDTH @ store pixel |
186 | @ | 267 | @ |
187 | @ do second pixel | 268 | @ do second pixel |
188 | @ | 269 | @ |
@@ -212,11 +293,11 @@ lcd_write_yuv420_lines: | |||
212 | @ | 293 | @ |
213 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) | 294 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) |
214 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) | 295 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) |
215 | strh r12, [r0, #240]! @ store pixel | 296 | strh r12, [r0, #LCD_WIDTH]! @ store pixel |
216 | add r0, r0, #2*240 @ | 297 | add r0, r0, #2*LCD_WIDTH @ |
217 | @ | 298 | @ |
218 | subs r3, r3, #2 @ | 299 | subs r3, r3, #2 @ |
219 | bgt 20b @ loop line 2 @ | 300 | bgt 20b @ loop line 2 @ |
220 | @ | 301 | @ |
221 | ldmia sp!, { r4-r12, pc } @ restore registers and return | 302 | ldmfd sp!, { r4-r12, pc } @ restore registers and return |
222 | .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines | 303 | .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines |
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c index c96e0d6d25..5e1110eb3d 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | |||
@@ -15,6 +15,12 @@ volatile bool lcd_poweroff = false; | |||
15 | extern unsigned fg_pattern; | 15 | extern unsigned fg_pattern; |
16 | extern unsigned bg_pattern; | 16 | extern unsigned bg_pattern; |
17 | 17 | ||
18 | /* Copies a rectangle from one framebuffer to another. Can be used in | ||
19 | single transfer mode with width = num pixels, and height = 1 which | ||
20 | allows a full-width rectangle to be copied more efficiently. */ | ||
21 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
22 | int width, int height); | ||
23 | |||
18 | bool lcd_enabled() | 24 | bool lcd_enabled() |
19 | { | 25 | { |
20 | return lcd_on; | 26 | return lcd_on; |
@@ -36,7 +42,6 @@ unsigned int LCDBASEL(unsigned int address) | |||
36 | return (address & ((1 << 22)-1)) >> 1; | 42 | return (address & ((1 << 22)-1)) >> 1; |
37 | } | 43 | } |
38 | 44 | ||
39 | |||
40 | /* LCD init */ | 45 | /* LCD init */ |
41 | void lcd_init_device(void) | 46 | void lcd_init_device(void) |
42 | { | 47 | { |
@@ -122,17 +127,41 @@ void lcd_init_device(void) | |||
122 | /* Update a fraction of the display. */ | 127 | /* Update a fraction of the display. */ |
123 | void lcd_update_rect(int x, int y, int width, int height) | 128 | void lcd_update_rect(int x, int y, int width, int height) |
124 | { | 129 | { |
125 | (void)x; | 130 | fb_data *dst, *src; |
126 | (void)width; | ||
127 | (void)y; | ||
128 | (void)height; | ||
129 | 131 | ||
130 | if(!lcd_on) | 132 | if (!lcd_on) |
131 | { | ||
132 | sleep(200); | ||
133 | return; | 133 | return; |
134 | |||
135 | if (x + width > LCD_WIDTH) | ||
136 | width = LCD_WIDTH - x; /* Clip right */ | ||
137 | if (x < 0) | ||
138 | width += x, x = 0; /* Clip left */ | ||
139 | if (width <= 0) | ||
140 | return; /* nothing left to do */ | ||
141 | |||
142 | if (y + height > LCD_HEIGHT) | ||
143 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
144 | if (y < 0) | ||
145 | height += y, y = 0; /* Clip top */ | ||
146 | if (height <= 0) | ||
147 | return; /* nothing left to do */ | ||
148 | |||
149 | /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer | ||
150 | * and lcd_framebuffer */ | ||
151 | dst = (fb_data *)FRAME + LCD_WIDTH*y + x; | ||
152 | src = &lcd_framebuffer[y][x]; | ||
153 | |||
154 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
155 | if (width < LCD_WIDTH) | ||
156 | { | ||
157 | /* Not full width - do line-by-line */ | ||
158 | lcd_copy_buffer_rect(dst, src, width, height); | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | /* Full width - copy as one line */ | ||
163 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
134 | } | 164 | } |
135 | memcpy(((char*)FRAME) + (y * sizeof(fb_data) * LCD_WIDTH), ((char *)&lcd_framebuffer) + (y * sizeof(fb_data) * LCD_WIDTH), ((height * sizeof(fb_data) * LCD_WIDTH))); | ||
136 | } | 165 | } |
137 | 166 | ||
138 | void lcd_enable(bool state) | 167 | void lcd_enable(bool state) |
@@ -144,7 +173,7 @@ void lcd_enable(bool state) | |||
144 | if(!lcd_on) | 173 | if(!lcd_on) |
145 | { | 174 | { |
146 | lcd_on = true; | 175 | lcd_on = true; |
147 | memcpy(FRAME, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2); | 176 | lcd_update(); |
148 | LCDCON1 |= 1; | 177 | LCDCON1 |= 1; |
149 | } | 178 | } |
150 | } | 179 | } |
@@ -161,7 +190,11 @@ void lcd_enable(bool state) | |||
161 | This must be called after all other LCD functions that change the display. */ | 190 | This must be called after all other LCD functions that change the display. */ |
162 | void lcd_update(void) | 191 | void lcd_update(void) |
163 | { | 192 | { |
164 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 193 | if (!lcd_on) |
194 | return; | ||
195 | |||
196 | lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0], | ||
197 | LCD_WIDTH*LCD_HEIGHT, 1); | ||
165 | } | 198 | } |
166 | 199 | ||
167 | void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | 200 | void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, |
@@ -171,28 +204,19 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
171 | fb_data *dst, *dst_end; | 204 | fb_data *dst, *dst_end; |
172 | unsigned int transcolor; | 205 | unsigned int transcolor; |
173 | 206 | ||
174 | /* nothing to draw? */ | ||
175 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
176 | || (x + width <= 0) || (y + height <= 0)) | ||
177 | return; | ||
178 | |||
179 | /* clipping */ | ||
180 | if (x < 0) | ||
181 | { | ||
182 | width += x; | ||
183 | src_x -= x; | ||
184 | x = 0; | ||
185 | } | ||
186 | if (y < 0) | ||
187 | { | ||
188 | height += y; | ||
189 | src_y -= y; | ||
190 | y = 0; | ||
191 | } | ||
192 | if (x + width > LCD_WIDTH) | 207 | if (x + width > LCD_WIDTH) |
193 | width = LCD_WIDTH - x; | 208 | width = LCD_WIDTH - x; /* Clip right */ |
209 | if (x < 0) | ||
210 | width += x, x = 0; /* Clip left */ | ||
211 | if (width <= 0) | ||
212 | return; /* nothing left to do */ | ||
213 | |||
194 | if (y + height > LCD_HEIGHT) | 214 | if (y + height > LCD_HEIGHT) |
195 | height = LCD_HEIGHT - y; | 215 | height = LCD_HEIGHT - y; /* Clip bottom */ |
216 | if (y < 0) | ||
217 | height += y, y = 0; /* Clip top */ | ||
218 | if (height <= 0) | ||
219 | return; /* nothing left to do */ | ||
196 | 220 | ||
197 | src += stride * src_y + src_x; /* move starting point */ | 221 | src += stride * src_y + src_x; /* move starting point */ |
198 | dst = &lcd_framebuffer[(y)][(x)]; | 222 | dst = &lcd_framebuffer[(y)][(x)]; |