Move bitstream.[ch] to codecs/lib/ffmpeg_bitstream.[ch] to avoid duplicate copies...
[kugel-rb.git] / firmware / drivers / lcd-1bit-vert.c
blobdb8cc6771bbb2b1ada17a0bb49675043ca69f85d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Alan Korr
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
24 #include "lcd.h"
25 #include "kernel.h"
26 #include "thread.h"
27 #include <string.h>
28 #include <stdlib.h>
29 #include "file.h"
30 #include "debug.h"
31 #include "system.h"
32 #include "font.h"
33 #include "rbunicode.h"
34 #include "bidi.h"
35 #include "scroll_engine.h"
37 #ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */
38 #define LCDFN(fn) lcd_ ## fn
39 #define FBFN(fn) fb_ ## fn
40 #define LCDM(ma) LCD_ ## ma
41 #define LCDNAME "lcd_"
42 #define MAIN_LCD
43 #endif
45 /*** globals ***/
47 FBFN(data) LCDFN(framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)]
48 #if CONFIG_CPU != SH7034
49 IBSS_ATTR
50 #endif
53 static struct viewport default_vp =
55 .x = 0,
56 .y = 0,
57 .width = LCDM(WIDTH),
58 .height = LCDM(HEIGHT),
59 .font = FONT_SYSFIXED,
60 .drawmode = DRMODE_SOLID,
63 static struct viewport* current_vp = &default_vp;
65 /*** Viewports ***/
67 void LCDFN(set_viewport)(struct viewport* vp)
69 if (vp == NULL)
70 current_vp = &default_vp;
71 else
72 current_vp = vp;
75 void LCDFN(update_viewport)(void)
77 LCDFN(update_rect)(current_vp->x, current_vp->y,
78 current_vp->width, current_vp->height);
81 void LCDFN(update_viewport_rect)(int x, int y, int width, int height)
83 LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height);
86 /* LCD init */
87 void LCDFN(init)(void)
89 LCDFN(clear_display)();
90 #ifndef SIMULATOR
91 LCDFN(init_device)();
92 #endif
93 #ifdef MAIN_LCD
94 scroll_init();
95 #endif
98 #ifdef MAIN_LCD
99 #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
100 static void (*lcd_activation_hook)(void) = NULL;
102 void lcd_activation_set_hook(void (*func)(void))
104 lcd_activation_hook = func;
107 void lcd_activation_call_hook(void)
109 void (*func)(void) = lcd_activation_hook;
111 if (func != NULL)
112 func();
114 #endif
115 #endif
117 /*** parameter handling ***/
119 void LCDFN(set_drawmode)(int mode)
121 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
124 int LCDFN(get_drawmode)(void)
126 return current_vp->drawmode;
129 int LCDFN(getwidth)(void)
131 return current_vp->width;
134 int LCDFN(getheight)(void)
136 return current_vp->height;
139 void LCDFN(setfont)(int newfont)
141 current_vp->font = newfont;
144 int LCDFN(getfont)(void)
146 return current_vp->font;
149 int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h)
151 return font_getstringsize(str, w, h, current_vp->font);
154 /*** low-level drawing functions ***/
156 static void setpixel(int x, int y)
158 LCDFN(framebuffer)[y>>3][x] |= BIT_N(y & 7);
161 static void clearpixel(int x, int y)
163 LCDFN(framebuffer)[y>>3][x] &= ~BIT_N(y & 7);
166 static void flippixel(int x, int y)
168 LCDFN(framebuffer)[y>>3][x] ^= BIT_N(y & 7);
171 static void nopixel(int x, int y)
173 (void)x;
174 (void)y;
177 LCDFN(pixelfunc_type)* const LCDFN(pixelfuncs)[8] = {
178 flippixel, nopixel, setpixel, setpixel,
179 nopixel, clearpixel, nopixel, clearpixel
182 static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask,
183 unsigned bits)
185 *address ^= bits & mask;
188 static void ICODE_ATTR bgblock(FBFN(data) *address, unsigned mask,
189 unsigned bits)
191 *address &= bits | ~mask;
194 static void ICODE_ATTR fgblock(FBFN(data) *address, unsigned mask,
195 unsigned bits)
197 *address |= bits & mask;
200 static void ICODE_ATTR solidblock(FBFN(data) *address, unsigned mask,
201 unsigned bits)
203 unsigned data = *(char*)address;
205 bits ^= data;
206 *address = data ^ (bits & mask);
209 static void ICODE_ATTR flipinvblock(FBFN(data) *address, unsigned mask,
210 unsigned bits)
212 *address ^= ~bits & mask;
215 static void ICODE_ATTR bginvblock(FBFN(data) *address, unsigned mask,
216 unsigned bits)
218 *address &= ~(bits & mask);
221 static void ICODE_ATTR fginvblock(FBFN(data) *address, unsigned mask,
222 unsigned bits)
224 *address |= ~bits & mask;
227 static void ICODE_ATTR solidinvblock(FBFN(data) *address, unsigned mask,
228 unsigned bits)
230 unsigned data = *(char *)address;
232 bits = ~bits ^ data;
233 *address = data ^ (bits & mask);
236 LCDFN(blockfunc_type)* const LCDFN(blockfuncs)[8] = {
237 flipblock, bgblock, fgblock, solidblock,
238 flipinvblock, bginvblock, fginvblock, solidinvblock
241 /*** drawing functions ***/
243 /* Clear the whole display */
244 void LCDFN(clear_display)(void)
246 unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0;
248 memset(LCDFN(framebuffer), bits, sizeof LCDFN(framebuffer));
249 LCDFN(scroll_info).lines = 0;
252 /* Clear the current viewport */
253 void LCDFN(clear_viewport)(void)
255 int oldmode;
257 if (current_vp == &default_vp)
259 LCDFN(clear_display)();
261 else
263 oldmode = current_vp->drawmode;
265 /* Invert the INVERSEVID bit and set basic mode to SOLID */
266 current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) |
267 DRMODE_SOLID;
269 LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height);
271 current_vp->drawmode = oldmode;
273 LCDFN(scroll_stop)(current_vp);
277 /* Set a single pixel */
278 void LCDFN(drawpixel)(int x, int y)
280 if (((unsigned)x < (unsigned)current_vp->width) &&
281 ((unsigned)y < (unsigned)current_vp->height))
282 LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y);
285 /* Draw a line */
286 void LCDFN(drawline)(int x1, int y1, int x2, int y2)
288 int numpixels;
289 int i;
290 int deltax, deltay;
291 int d, dinc1, dinc2;
292 int x, xinc1, xinc2;
293 int y, yinc1, yinc2;
294 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode];
296 deltax = abs(x2 - x1);
297 if (deltax == 0)
299 DEBUGF(LCDNAME "drawline() called for vertical line - optimisation.\n");
300 LCDFN(vline)(x1, y1, y2);
301 return;
303 deltay = abs(y2 - y1);
304 if (deltay == 0)
306 DEBUGF(LCDNAME "drawline() called for horizontal line - optimisation.\n");
307 LCDFN(hline)(x1, x2, y1);
308 return;
310 xinc2 = 1;
311 yinc2 = 1;
313 if (deltax >= deltay)
315 numpixels = deltax;
316 d = 2 * deltay - deltax;
317 dinc1 = deltay * 2;
318 dinc2 = (deltay - deltax) * 2;
319 xinc1 = 1;
320 yinc1 = 0;
322 else
324 numpixels = deltay;
325 d = 2 * deltax - deltay;
326 dinc1 = deltax * 2;
327 dinc2 = (deltax - deltay) * 2;
328 xinc1 = 0;
329 yinc1 = 1;
331 numpixels++; /* include endpoints */
333 if (x1 > x2)
335 xinc1 = -xinc1;
336 xinc2 = -xinc2;
339 if (y1 > y2)
341 yinc1 = -yinc1;
342 yinc2 = -yinc2;
345 x = x1;
346 y = y1;
348 for (i = 0; i < numpixels; i++)
350 if (((unsigned)x < (unsigned)current_vp->width)
351 && ((unsigned)y < (unsigned)current_vp->height))
352 pfunc(current_vp->x + x, current_vp->y + y);
354 if (d < 0)
356 d += dinc1;
357 x += xinc1;
358 y += yinc1;
360 else
362 d += dinc2;
363 x += xinc2;
364 y += yinc2;
369 /* Draw a horizontal line (optimised) */
370 void LCDFN(hline)(int x1, int x2, int y)
372 int x, width;
373 unsigned char *dst, *dst_end;
374 unsigned mask;
375 LCDFN(blockfunc_type) *bfunc;
377 /* direction flip */
378 if (x2 < x1)
380 x = x1;
381 x1 = x2;
382 x2 = x;
385 /* nothing to draw? */
386 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width)
387 || (x2 < 0))
388 return;
390 /* clipping */
391 if (x1 < 0)
392 x1 = 0;
393 if (x2 >= current_vp->width)
394 x2 = current_vp->width-1;
396 width = x2 - x1 + 1;
398 /* adjust to viewport */
399 x1 += current_vp->x;
400 y += current_vp->y;
402 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
403 dst = &LCDFN(framebuffer)[y>>3][x1];
404 mask = BIT_N(y & 7);
406 dst_end = dst + width;
408 bfunc(dst++, mask, 0xFFu);
409 while (dst < dst_end);
412 /* Draw a vertical line (optimised) */
413 void LCDFN(vline)(int x, int y1, int y2)
415 int ny;
416 FBFN(data) *dst;
417 unsigned mask, mask_bottom;
418 LCDFN(blockfunc_type) *bfunc;
420 /* direction flip */
421 if (y2 < y1)
423 ny = y1;
424 y1 = y2;
425 y2 = ny;
428 /* nothing to draw? */
429 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height)
430 || (y2 < 0))
431 return;
433 /* clipping */
434 if (y1 < 0)
435 y1 = 0;
436 if (y2 >= current_vp->height)
437 y2 = current_vp->height-1;
439 /* adjust for viewport */
440 y1 += current_vp->y;
441 y2 += current_vp->y;
442 x += current_vp->x;
444 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
445 dst = &LCDFN(framebuffer)[y1>>3][x];
446 ny = y2 - (y1 & ~7);
447 mask = 0xFFu << (y1 & 7);
448 mask_bottom = 0xFFu >> (~ny & 7);
450 for (; ny >= 8; ny -= 8)
452 bfunc(dst, mask, 0xFFu);
453 dst += LCDM(WIDTH);
454 mask = 0xFFu;
456 mask &= mask_bottom;
457 bfunc(dst, mask, 0xFFu);
460 /* Draw a rectangular box */
461 void LCDFN(drawrect)(int x, int y, int width, int height)
463 if ((width <= 0) || (height <= 0))
464 return;
466 int x2 = x + width - 1;
467 int y2 = y + height - 1;
469 LCDFN(vline)(x, y, y2);
470 LCDFN(vline)(x2, y, y2);
471 LCDFN(hline)(x, x2, y);
472 LCDFN(hline)(x, x2, y2);
475 /* Fill a rectangular area */
476 void LCDFN(fillrect)(int x, int y, int width, int height)
478 int ny;
479 FBFN(data) *dst, *dst_end;
480 unsigned mask, mask_bottom;
481 unsigned bits = 0;
482 LCDFN(blockfunc_type) *bfunc;
483 bool fillopt = false;
485 /* nothing to draw? */
486 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
487 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
488 return;
490 /* clipping */
491 if (x < 0)
493 width += x;
494 x = 0;
496 if (y < 0)
498 height += y;
499 y = 0;
501 if (x + width > current_vp->width)
502 width = current_vp->width - x;
503 if (y + height > current_vp->height)
504 height = current_vp->height - y;
506 /* adjust for viewport */
507 x += current_vp->x;
508 y += current_vp->y;
510 if (current_vp->drawmode & DRMODE_INVERSEVID)
512 if (current_vp->drawmode & DRMODE_BG)
514 fillopt = true;
517 else
519 if (current_vp->drawmode & DRMODE_FG)
521 fillopt = true;
522 bits = 0xFFu;
525 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
526 dst = &LCDFN(framebuffer)[y>>3][x];
527 ny = height - 1 + (y & 7);
528 mask = 0xFFu << (y & 7);
529 mask_bottom = 0xFFu >> (~ny & 7);
531 for (; ny >= 8; ny -= 8)
533 if (fillopt && (mask == 0xFFu))
534 memset(dst, bits, width);
535 else
537 FBFN(data) *dst_row = dst;
539 dst_end = dst_row + width;
541 bfunc(dst_row++, mask, 0xFFu);
542 while (dst_row < dst_end);
545 dst += LCDM(WIDTH);
546 mask = 0xFFu;
548 mask &= mask_bottom;
550 if (fillopt && (mask == 0xFFu))
551 memset(dst, bits, width);
552 else
554 dst_end = dst + width;
556 bfunc(dst++, mask, 0xFFu);
557 while (dst < dst_end);
561 /* About Rockbox' internal bitmap format:
563 * A bitmap contains one bit for every pixel that defines if that pixel is
564 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
565 * at top.
566 * The bytes are stored in row-major order, with byte 0 being top left,
567 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
568 * 0..7, the second row defines pixel row 8..15 etc.
570 * This is the same as the internal lcd hw format. */
572 /* Draw a partial bitmap */
573 void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
574 int src_y, int stride, int x, int y,
575 int width, int height)
577 int shift, ny;
578 FBFN(data) *dst, *dst_end;
579 unsigned mask, mask_bottom;
580 LCDFN(blockfunc_type) *bfunc;
582 /* nothing to draw? */
583 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
584 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
585 return;
587 /* clipping */
588 if (x < 0)
590 width += x;
591 src_x -= x;
592 x = 0;
594 if (y < 0)
596 height += y;
597 src_y -= y;
598 y = 0;
600 if (x + width > current_vp->width)
601 width = current_vp->width - x;
602 if (y + height > current_vp->height)
603 height = current_vp->height - y;
605 /* adjust for viewport */
606 x += current_vp->x;
607 y += current_vp->y;
609 src += stride * (src_y >> 3) + src_x; /* move starting point */
610 src_y &= 7;
611 y -= src_y;
612 dst = &LCDFN(framebuffer)[y>>3][x];
613 shift = y & 7;
614 ny = height - 1 + shift + src_y;
616 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
617 mask = 0xFFu << (shift + src_y);
618 mask_bottom = 0xFFu >> (~ny & 7);
620 if (shift == 0)
622 bool copyopt = (current_vp->drawmode == DRMODE_SOLID);
624 for (; ny >= 8; ny -= 8)
626 if (copyopt && (mask == 0xFFu))
627 memcpy(dst, src, width);
628 else
630 const unsigned char *src_row = src;
631 FBFN(data) *dst_row = dst;
633 dst_end = dst_row + width;
635 bfunc(dst_row++, mask, *src_row++);
636 while (dst_row < dst_end);
639 src += stride;
640 dst += LCDM(WIDTH);
641 mask = 0xFFu;
643 mask &= mask_bottom;
645 if (copyopt && (mask == 0xFFu))
646 memcpy(dst, src, width);
647 else
649 dst_end = dst + width;
651 bfunc(dst++, mask, *src++);
652 while (dst < dst_end);
655 else
657 dst_end = dst + width;
660 const unsigned char *src_col = src++;
661 FBFN(data) *dst_col = dst++;
662 unsigned mask_col = mask;
663 unsigned data = 0;
665 for (y = ny; y >= 8; y -= 8)
667 data |= *src_col << shift;
669 if (mask_col & 0xFFu)
671 bfunc(dst_col, mask_col, data);
672 mask_col = 0xFFu;
674 else
675 mask_col >>= 8;
677 src_col += stride;
678 dst_col += LCDM(WIDTH);
679 data >>= 8;
681 data |= *src_col << shift;
682 bfunc(dst_col, mask_col & mask_bottom, data);
684 while (dst < dst_end);
688 /* Draw a full bitmap */
689 void LCDFN(bitmap)(const unsigned char *src, int x, int y, int width,
690 int height)
692 LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height);
695 #include "lcd-bitmap-common.c"