From c6b5d5531b1e1ea53ee860e939dc9eb638c415a9 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Sun, 13 Jan 2008 00:21:45 +0000 Subject: [PATCH] The old grayscale library is now officially dead. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16067 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/lib/SOURCES | 4 - apps/plugins/lib/gray.h | 164 --- apps/plugins/lib/gray_core.c | 2520 -------------------------------- apps/plugins/lib/gray_draw.c | 2418 ------------------------------ apps/plugins/lib/gray_parm.c | 116 -- apps/plugins/lib/gray_scroll.c | 930 ------------ 6 files changed, 6152 deletions(-) delete mode 100644 apps/plugins/lib/gray.h delete mode 100644 apps/plugins/lib/gray_core.c delete mode 100644 apps/plugins/lib/gray_draw.c delete mode 100644 apps/plugins/lib/gray_parm.c delete mode 100644 apps/plugins/lib/gray_scroll.c diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index 5433f7e1d7..94372dcf97 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -4,10 +4,6 @@ fixedpoint.c playback_control.c rgb_hsv.c #if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) -gray_core.c -gray_draw.c -gray_parm.c -gray_scroll.c grey_core.c grey_draw.c grey_parm.c diff --git a/apps/plugins/lib/gray.h b/apps/plugins/lib/gray.h deleted file mode 100644 index 70808945bb..0000000000 --- a/apps/plugins/lib/gray.h +++ /dev/null @@ -1,164 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Greyscale framework -* -* This is a generic framework to display up to 33 shades of grey -* on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey) within plugins. -* -* Copyright (C) 2004-2006 Jens Arnold -* -* All files in this archive are subject to the GNU General Public License. -* See the file COPYING in the source tree root for full license agreement. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#ifndef __GRAY_H__ -#define __GRAY_H__ - -#include "plugin.h" - -#ifdef HAVE_LCD_BITMAP /* not for the Player */ - -#define GRAY_BRIGHTNESS(y) (y) - -#define GRAY_BLACK GRAY_BRIGHTNESS(0) -#define GRAY_DARKGRAY GRAY_BRIGHTNESS(85) -#define GRAY_LIGHTGRAY GRAY_BRIGHTNESS(170) -#define GRAY_WHITE GRAY_BRIGHTNESS(255) - -/* Library initialisation and release */ -int gray_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, - bool buffered, int width, int bheight, int depth, int gamma, - long *buf_taken); -void gray_release(void); - -/* Special functions */ -void gray_show(bool enable); -void gray_deferred_lcd_update(void); - -/* Update functions */ -void gray_update(void); -void gray_update_rect(int x, int y, int width, int height); - -/* Parameter handling */ -void gray_set_position(int x, int by); -void gray_set_drawmode(int mode); -int gray_get_drawmode(void); -void gray_set_foreground(unsigned brightness); -unsigned gray_get_foreground(void); -void gray_set_background(unsigned brightness); -unsigned gray_get_background(void); -void gray_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness); -void gray_setfont(int newfont); -int gray_getstringsize(const unsigned char *str, int *w, int *h); - -/* Whole display */ -void gray_clear_display(void); -void gray_ub_clear_display(void); - -/* Pixel */ -void gray_drawpixel(int x, int y); - -/* Lines */ -void gray_drawline(int x1, int y1, int x2, int y2); -void gray_hline(int x1, int x2, int y); -void gray_vline(int x, int y1, int y2); -void gray_drawrect(int x, int y, int nx, int ny); - -/* Filled primitives */ -void gray_fillrect(int x, int y, int nx, int ny); -void gray_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3); - -/* Bitmaps */ -void gray_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height); -void gray_mono_bitmap(const unsigned char *src, int x, int y, int width, - int height); -void gray_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height); -void gray_gray_bitmap(const unsigned char *src, int x, int y, int width, - int height); -void gray_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height); -void gray_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, - int height); - -/* Text */ -void gray_putsxyofs(int x, int y, int ofs, const unsigned char *str); -void gray_putsxy(int x, int y, const unsigned char *str); - -/* Scrolling */ -void gray_scroll_left(int count); -void gray_scroll_right(int count); -void gray_scroll_up(int count); -void gray_scroll_down(int count); -void gray_ub_scroll_left(int count); -void gray_ub_scroll_right(int count); -void gray_ub_scroll_up(int count); -void gray_ub_scroll_down(int count); - -/*** Internal stuff ***/ - -/* flag definitions */ -#define _GRAY_RUNNING 0x0001 /* greyscale overlay is running */ -#define _GRAY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */ - -/* fast unsigned multiplication (16x16bit->32bit or 32x32bit->32bit, - * whichever is faster for the architecture) */ -#ifdef CPU_ARM -#define _GRAY_MULUQ(a, b) ((uint32_t) (((uint32_t) (a)) * ((uint32_t) (b)))) -#else -#define _GRAY_MULUQ(a, b) ((uint32_t) (((uint16_t) (a)) * ((uint16_t) (b)))) -#endif - -/* The grayscale buffer management structure */ -struct _gray_info -{ - int x; - int y; - int width; - int height; -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - int bx; /* 8-pixel units */ - int bwidth; /* 8-pixel units */ -#else /* vertical packing */ - int by; /* 8-pixel units */ - int bheight; /* 8-pixel units */ -#endif - int depth; /* number_of_bitplanes = (number_of_grayscales - 1) */ - unsigned long flags; /* various flags, see #defines */ -#ifndef SIMULATOR - int cur_plane; /* for the timer isr */ - long plane_size; - unsigned long randmask; /* mask for random value in _writepixel() */ - unsigned long *bitpattern; /* start of pattern table */ - unsigned char *plane_data; /* start of bitplane data */ -#endif - unsigned char *cur_buffer; /* start of current chunky pixel buffer */ - unsigned char *back_buffer;/* start of chunky pixel back buffer */ - unsigned char idxtable[256]; /* calculated brightness -> index translation table */ - int fg_index; /* current foreground index */ - int bg_index; /* current background index */ - int fg_brightness; /* current foreground brightness, for returning */ - int bg_brightness; /* current background brightness, for returning */ - int drawmode; /* current draw mode */ - int curfont; /* current selected font */ -}; - -/* Global variables */ -extern struct plugin_api *_gray_rb; -extern struct _gray_info _gray_info; -extern short _gray_random_buffer; - -#endif /* HAVE_LCD_BITMAP */ -#endif /* __GRAY_H__ */ diff --git a/apps/plugins/lib/gray_core.c b/apps/plugins/lib/gray_core.c deleted file mode 100644 index e28d56e84d..0000000000 --- a/apps/plugins/lib/gray_core.c +++ /dev/null @@ -1,2520 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Greyscale framework -* Core & miscellaneous functions -* -* This is a generic framework to display up to 33 shades of grey -* on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey, iPod 4-grey) -* within plugins. -* -* Copyright (C) 2004-2006 Jens Arnold -* -* All files in this archive are subject to the GNU General Public License. -* See the file COPYING in the source tree root for full license agreement. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "plugin.h" - -#ifdef HAVE_LCD_BITMAP -#include "gray.h" - -#if defined(CPU_PP) && defined(HAVE_ADJUSTABLE_CPU_FREQ) -#define NEED_BOOST -#endif - -/* Global variables */ -struct plugin_api *_gray_rb = NULL; /* global api struct pointer */ -struct _gray_info _gray_info; /* global info structure */ - -#ifndef SIMULATOR -short _gray_random_buffer; /* buffer for random number generator */ - -#if CONFIG_LCD == LCD_SSD1815 || CONFIG_LCD == LCD_IFP7XX || CONFIG_LCD == LCD_MROBE100 -/* measured and interpolated curve */ -/* TODO: check for iFP & m:robe 100 */ -static const unsigned char lcdlinear[256] = { - 0, 3, 5, 8, 11, 13, 16, 18, - 21, 23, 26, 28, 31, 33, 36, 38, - 40, 42, 45, 47, 49, 51, 53, 55, - 57, 59, 60, 62, 64, 66, 67, 69, - 70, 72, 73, 74, 76, 77, 78, 79, - 81, 82, 83, 84, 85, 86, 87, 88, - 88, 89, 90, 91, 92, 92, 93, 94, - 95, 95, 96, 97, 97, 98, 99, 99, - 100, 101, 102, 102, 103, 104, 104, 105, - 106, 106, 107, 107, 108, 109, 109, 110, - 111, 111, 112, 113, 113, 114, 114, 115, - 116, 116, 117, 117, 118, 119, 119, 120, - 120, 121, 121, 122, 122, 123, 123, 124, - 124, 125, 125, 126, 126, 127, 127, 128, - 128, 128, 129, 129, 130, 130, 131, 131, - 132, 132, 133, 133, 133, 134, 134, 135, - 135, 136, 136, 137, 137, 138, 138, 138, - 139, 139, 140, 140, 141, 141, 142, 142, - 143, 143, 144, 144, 145, 145, 146, 146, - 147, 147, 148, 148, 148, 149, 149, 150, - 150, 151, 151, 152, 152, 153, 153, 153, - 154, 154, 155, 155, 156, 156, 157, 157, - 158, 158, 158, 159, 159, 160, 160, 161, - 161, 162, 162, 163, 163, 164, 164, 165, - 165, 166, 167, 167, 168, 168, 169, 169, - 170, 171, 171, 172, 173, 173, 174, 175, - 176, 176, 177, 178, 179, 180, 181, 181, - 182, 183, 184, 185, 186, 188, 189, 190, - 191, 192, 194, 195, 196, 198, 199, 201, - 202, 204, 205, 207, 209, 211, 213, 215, - 217, 219, 222, 224, 226, 229, 231, 234, - 236, 239, 242, 244, 247, 250, 252, 255 -}; -#elif CONFIG_LCD == LCD_S1D15E06 -/* measured and interpolated curve */ -static const unsigned char lcdlinear[256] = { - 0, 5, 11, 16, 21, 27, 32, 37, - 42, 47, 51, 56, 60, 64, 68, 72, - 75, 78, 81, 84, 87, 89, 91, 93, - 95, 96, 98, 99, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 111, - 112, 113, 113, 114, 115, 115, 116, 117, - 117, 118, 118, 119, 119, 120, 120, 121, - 121, 122, 122, 123, 123, 124, 124, 125, - 125, 126, 126, 127, 127, 127, 128, 128, - 129, 129, 130, 130, 131, 131, 132, 132, - 133, 133, 134, 134, 135, 135, 136, 136, - 137, 137, 138, 138, 138, 139, 139, 140, - 140, 141, 141, 141, 142, 142, 143, 143, - 143, 144, 144, 145, 145, 145, 146, 146, - 146, 147, 147, 147, 148, 148, 149, 149, - 149, 150, 150, 150, 151, 151, 151, 152, - 152, 153, 153, 153, 154, 154, 155, 155, - 155, 156, 156, 157, 157, 157, 158, 158, - 159, 159, 159, 160, 160, 161, 161, 162, - 162, 162, 163, 163, 164, 164, 164, 165, - 165, 166, 166, 167, 167, 167, 168, 168, - 169, 169, 170, 170, 170, 171, 171, 172, - 172, 173, 173, 174, 174, 175, 175, 176, - 176, 177, 177, 178, 178, 179, 179, 180, - 180, 181, 182, 182, 183, 184, 184, 185, - 186, 186, 187, 188, 188, 189, 190, 191, - 191, 192, 193, 194, 195, 196, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 213, 214, - 215, 216, 218, 219, 220, 222, 223, 225, - 227, 228, 230, 232, 233, 235, 237, 239, - 241, 243, 245, 247, 249, 251, 253, 255 -}; -#elif (CONFIG_LCD == LCD_IPOD2BPP) || (CONFIG_LCD == LCD_IPODMINI) || (CONFIG_LCD == LCD_IFP7XX) -/* measured and interpolated curve for mini LCD */ -/* TODO: verify this curve on the fullsize greyscale LCD */ -static const unsigned char lcdlinear[256] = { - 0, 3, 6, 8, 11, 14, 17, 19, - 22, 24, 27, 29, 32, 34, 36, 38, - 40, 42, 44, 45, 47, 48, 50, 51, - 52, 54, 55, 56, 57, 58, 58, 59, - 60, 61, 62, 62, 63, 64, 64, 65, - 66, 66, 67, 67, 68, 68, 69, 69, - 70, 70, 70, 71, 71, 71, 72, 72, - 73, 73, 73, 74, 74, 74, 74, 75, - 75, 75, 76, 76, 76, 77, 77, 77, - 78, 78, 78, 79, 79, 79, 80, 80, - 80, 80, 81, 81, 81, 82, 82, 82, - 83, 83, 83, 84, 84, 84, 85, 85, - 85, 85, 86, 86, 86, 87, 87, 87, - 87, 88, 88, 88, 89, 89, 89, 89, - 90, 90, 90, 91, 91, 91, 92, 92, - 92, 93, 93, 93, 94, 94, 94, 95, - 95, 96, 96, 96, 97, 97, 98, 98, - 99, 99, 99, 100, 100, 101, 101, 102, - 102, 103, 103, 104, 104, 105, 105, 106, - 106, 107, 107, 108, 108, 109, 109, 110, - 110, 111, 111, 112, 113, 113, 114, 114, - 115, 115, 116, 117, 117, 118, 118, 119, - 120, 120, 121, 122, 122, 123, 124, 124, - 125, 126, 126, 127, 128, 128, 129, 130, - 131, 131, 132, 133, 134, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 152, 153, - 154, 156, 157, 159, 160, 162, 163, 165, - 167, 168, 170, 172, 174, 176, 178, 180, - 182, 184, 187, 189, 192, 194, 197, 200, - 203, 206, 209, 212, 215, 219, 222, 226, - 229, 233, 236, 240, 244, 248, 251, 255 -}; -#endif -#else /* SIMULATOR */ -/* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */ -static const unsigned char lcdlinear[256] = { - 0, 16, 23, 28, 32, 36, 39, 42, - 45, 48, 50, 53, 55, 58, 60, 62, - 64, 66, 68, 70, 71, 73, 75, 77, - 78, 80, 81, 83, 84, 86, 87, 89, - 90, 92, 93, 94, 96, 97, 98, 100, - 101, 102, 103, 105, 106, 107, 108, 109, - 111, 112, 113, 114, 115, 116, 117, 118, - 119, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, - 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 145, 146, 147, 148, 149, - 150, 151, 151, 152, 153, 154, 155, 156, - 156, 157, 158, 159, 160, 160, 161, 162, - 163, 164, 164, 165, 166, 167, 167, 168, - 169, 170, 170, 171, 172, 173, 173, 174, - 175, 176, 176, 177, 178, 179, 179, 180, - 181, 181, 182, 183, 183, 184, 185, 186, - 186, 187, 188, 188, 189, 190, 190, 191, - 192, 192, 193, 194, 194, 195, 196, 196, - 197, 198, 198, 199, 199, 200, 201, 201, - 202, 203, 203, 204, 204, 205, 206, 206, - 207, 208, 208, 209, 209, 210, 211, 211, - 212, 212, 213, 214, 214, 215, 215, 216, - 217, 217, 218, 218, 219, 220, 220, 221, - 221, 222, 222, 223, 224, 224, 225, 225, - 226, 226, 227, 228, 228, 229, 229, 230, - 230, 231, 231, 232, 233, 233, 234, 234, - 235, 235, 236, 236, 237, 237, 238, 238, - 239, 240, 240, 241, 241, 242, 242, 243, - 243, 244, 244, 245, 245, 246, 246, 247, - 247, 248, 248, 249, 249, 250, 250, 251, - 251, 252, 252, 253, 253, 254, 254, 255 -}; -#endif /* SIMULATOR */ - -/* Prototypes */ -static inline void _deferred_update(void) __attribute__ ((always_inline)); -static int exp_s16p16(int x); -static int log_s16p16(int x); -static void gray_screendump_hook(int fd); -#ifdef SIMULATOR -static unsigned long _gray_get_pixel(int x, int y); -#else -static void _timer_isr(void); -#endif - -/* Update LCD areas not covered by the greyscale overlay */ -static inline void _deferred_update(void) -{ - int x1 = MAX(_gray_info.x, 0); - int x2 = MIN(_gray_info.x + _gray_info.width, LCD_WIDTH); - int y1 = MAX(_gray_info.y, 0); - int y2 = MIN(_gray_info.y + _gray_info.height, LCD_HEIGHT); - - if (y1 > 0) /* refresh part above overlay, full width */ - _gray_rb->lcd_update_rect(0, 0, LCD_WIDTH, y1); - - if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */ - _gray_rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2); - - if (x1 > 0) /* refresh part to the left of overlay */ - _gray_rb->lcd_update_rect(0, y1, x1, y2 - y1); - - if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */ - _gray_rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1); -} - -#ifndef SIMULATOR -/* Timer interrupt handler: display next bitplane */ -static void _timer_isr(void) -{ -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - _gray_rb->lcd_blit(_gray_info.plane_data + _GRAY_MULUQ(_gray_info.plane_size, - _gray_info.cur_plane), _gray_info.bx, _gray_info.y, - _gray_info.bwidth, _gray_info.height, _gray_info.bwidth); -#else - _gray_rb->lcd_blit(_gray_info.plane_data + _GRAY_MULUQ(_gray_info.plane_size, - _gray_info.cur_plane), _gray_info.x, _gray_info.by, - _gray_info.width, _gray_info.bheight, _gray_info.width); -#endif - - if (++_gray_info.cur_plane >= _gray_info.depth) - _gray_info.cur_plane = 0; - - if (_gray_info.flags & _GRAY_DEFERRED_UPDATE) /* lcd_update() requested? */ - { - _deferred_update(); - _gray_info.flags &= ~_GRAY_DEFERRED_UPDATE; /* clear request */ - } -} -#endif /* !SIMULATOR */ - -/* fixed point exp() */ -static int exp_s16p16(int x) -{ - int t; - int y = 0x00010000; - - if (x < 0) x += 0xb1721, y >>= 16; - t = x - 0x58b91; if (t >= 0) x = t, y <<= 8; - t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4; - t = x - 0x162e4; if (t >= 0) x = t, y <<= 2; - t = x - 0x0b172; if (t >= 0) x = t, y <<= 1; - t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1; - t = x - 0x03920; if (t >= 0) x = t, y += y >> 2; - t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3; - t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4; - t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5; - t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6; - t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7; - y += ((y >> 8) * x) >> 8; - - return y; -} - -/* fixed point log() */ -static int log_s16p16(int x) -{ - int t; - int y = 0xa65af; - - if (x < 0x00008000) x <<=16, y -= 0xb1721; - if (x < 0x00800000) x <<= 8, y -= 0x58b91; - if (x < 0x08000000) x <<= 4, y -= 0x2c5c8; - if (x < 0x20000000) x <<= 2, y -= 0x162e4; - if (x < 0x40000000) x <<= 1, y -= 0x0b172; - t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd; - t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920; - t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27; - t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85; - t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1; - t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8; - t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe; - x = 0x80000000 - x; - y -= x >> 15; - - return y; -} - -/* Initialise the framework and prepare the greyscale display buffer - - arguments: - newrb = pointer to plugin api - gbuf = pointer to the memory area to use (e.g. plugin buffer) - gbuf_size = max usable size of the buffer - buffered = use chunky pixel buffering with delta buffer? - This allows to use all drawing functions, but needs more - memory. Unbuffered operation provides only a subset of - drawing functions. (only gray_bitmap drawing and scrolling) - width = width in pixels (1..LCD_WIDTH) - height = height in pixels (1..LCD_HEIGHT) - Note that depending on the target LCD, either height or - width are rounded up to a multiple of 8. - depth = number of bitplanes to use (1..32). - gamma = gamma value as s8p8 fixed point. gamma <= 0 means no - correction at all, i.e. no LCD linearisation as well. - - result: - = depth if there was enough memory - < depth if there wasn't enough memory. The number of displayable - shades is smaller than desired, but it still works - = 0 if there wasn't even enough memory for 1 bitplane - - You can request any depth in the allowed range, not just powers of 2. The - routine performs "graceful degradation" if the memory is not sufficient for - the desired depth. As long as there is at least enough memory for 1 bitplane, - it creates as many bitplanes as fit into memory, although 1 bitplane won't - deliver an enhancement over the native display. - - The number of displayable shades is calculated as follows: - shades = depth + 1 - - If you need info about the memory taken by the greyscale buffer, supply a - long* as the last parameter. This long will then contain the number of bytes - used. The total memory needed can be calculated as follows: - total_mem = - shades * sizeof(long) (bitpatterns) - + [horizontal_packing] ? (bitplane data) - ((width + 7) / 8) * height * depth : width * ((height + 7) / 8) * depth - + buffered ? (chunky front- & backbuffer) - (width * height * 2) : 0 - + 0..3 (longword alignment) - - The function tries to be as authentic as possible regarding memory usage on - the simulator, even if it doesn't use all of the allocated memory. There's - one situation where it will consume more memory on the sim than on the - target: if you're allocating a low depth (< 8) without buffering. */ -int gray_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, - bool buffered, int width, int height, int depth, int gamma, - long *buf_taken) -{ - int possible_depth, bdim, i; - long plane_size, buftaken; - unsigned data; -#ifndef SIMULATOR - int j, bitfill; -#endif - - _gray_rb = newrb; - - if ((unsigned) width > LCD_WIDTH - || (unsigned) height > LCD_HEIGHT - || depth < 1) - return 0; - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - bdim = (width + 7) >> 3; - width = bdim << 3; -#else - bdim = (height + 7) >> 3; - height = bdim << 3; -#endif - - /* the buffer has to be long aligned */ - buftaken = (-(long)gbuf) & 3; - gbuf += buftaken; - - /* chunky front- & backbuffer */ - if (buffered) - { - plane_size = _GRAY_MULUQ(width, height); - buftaken += 2 * plane_size; - if (buftaken > gbuf_size) - return 0; - - _gray_info.cur_buffer = gbuf; - gbuf += plane_size; - /* set backbuffer to 0xFF to guarantee the initial full update */ - _gray_rb->memset(gbuf, 0xFF, plane_size); - _gray_info.back_buffer = gbuf; - gbuf += plane_size; - } - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - plane_size = _GRAY_MULUQ(bdim, height); -#else - plane_size = _GRAY_MULUQ(width, bdim); -#endif - possible_depth = (gbuf_size - buftaken - sizeof(long)) - / (plane_size + sizeof(long)); - - if (possible_depth < 1) - return 0; - - depth = MIN(depth, 32); - depth = MIN(depth, possible_depth); - -#ifdef SIMULATOR - if (!buffered) - { - long orig_size = _GRAY_MULUQ(depth, plane_size) + (depth + 1) * sizeof(long); - - plane_size = _GRAY_MULUQ(width, height); - if (plane_size > orig_size) - { - buftaken += plane_size; - if (buftaken > gbuf_size) - return 0; - } - else - { - buftaken += orig_size; - } - _gray_info.cur_buffer = gbuf; - } - else -#endif - buftaken += _GRAY_MULUQ(depth, plane_size) + (depth + 1) * sizeof(long); - - _gray_info.x = 0; - _gray_info.y = 0; - _gray_info.width = width; - _gray_info.height = height; -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - _gray_info.bx = 0; - _gray_info.bwidth = bdim; -#else - _gray_info.by = 0; - _gray_info.bheight = bdim; -#endif - _gray_info.depth = depth; - _gray_info.flags = 0; -#ifndef SIMULATOR - _gray_info.cur_plane = 0; - _gray_info.plane_size = plane_size; - _gray_info.plane_data = gbuf; - _gray_rb->memset(gbuf, 0, _GRAY_MULUQ(depth, plane_size)); - gbuf += _GRAY_MULUQ(depth, plane_size); - _gray_info.bitpattern = (unsigned long *)gbuf; - - i = depth - 1; - j = 8; - while (i != 0) - { - i >>= 1; - j--; - } - _gray_info.randmask = 0xFFu >> j; - bitfill = (-depth) & 7; - - /* Precalculate the bit patterns for all possible pixel values */ - for (i = 0; i <= depth; i++) - { - unsigned long pattern = 0; - int value = 0; - - for (j = 0; j < depth; j++) - { - pattern <<= 1; - value += i; - - if (value >= depth) - value -= depth; /* "white" bit */ - else - pattern |= 1; /* "black" bit */ - } - /* now the lower bits contain the pattern */ - - _gray_info.bitpattern[i] = pattern << bitfill; - } -#endif - - /* precalculate the value -> pattern index conversion table, taking - linearisation and gamma correction into account */ - if (gamma <= 0) - { - for (i = 0; i < 256; i++) - { - data = _GRAY_MULUQ(depth, i) + 127; - _gray_info.idxtable[i] = (data + (data >> 8)) >> 8; - /* approx. data / 255 */ - } - } - else - { - for (i = 0; i < 256; i++) - { - data = exp_s16p16((gamma * log_s16p16(i * 257 + 1)) >> 8) + 128; - data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */ - data = _GRAY_MULUQ(depth, lcdlinear[data]) + 127; - _gray_info.idxtable[i] = (data + (data >> 8)) >> 8; - /* approx. data / 255 */ - } - } - - _gray_info.fg_index = 0; - _gray_info.bg_index = depth; - _gray_info.fg_brightness = 0; - _gray_info.bg_brightness = 255; - _gray_info.drawmode = DRMODE_SOLID; - _gray_info.curfont = FONT_SYSFIXED; - - if (buf_taken) /* caller requested info about space taken */ - *buf_taken = buftaken; - - return depth; -} - -/* Release the greyscale display buffer and the library - DO CALL either this function or at least gray_show_display(false) - before you exit, otherwise nasty things may happen. */ -void gray_release(void) -{ - gray_show(false); -} - -/* Switch the greyscale overlay on or off - DO NOT call lcd_update() or any other api function that directly accesses - the lcd while the greyscale overlay is running! If you need to do - lcd_update() to update something outside the greyscale overlay area, use - gray_deferred_update() instead. - - Other functions to avoid are: - lcd_blit() (obviously), lcd_update_rect(), lcd_set_contrast(), - lcd_set_invert_display(), lcd_set_flip(), lcd_roll() */ -void gray_show(bool enable) -{ - if (enable && !(_gray_info.flags & _GRAY_RUNNING)) - { - _gray_info.flags |= _GRAY_RUNNING; -#ifdef SIMULATOR - _gray_rb->sim_lcd_ex_init(_gray_info.depth + 1, _gray_get_pixel); - gray_update(); -#else /* !SIMULATOR */ -#ifdef NEED_BOOST - _gray_rb->cpu_boost(true); -#endif -#if CONFIG_LCD == LCD_SSD1815 - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 67, 1, _timer_isr); -#elif CONFIG_LCD == LCD_S1D15E06 - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 70, 1, _timer_isr); -#elif CONFIG_LCD == LCD_IPOD2BPP -#ifdef IPOD_1G2G - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 95, 1, _timer_isr); /* verified */ -#elif defined IPOD_3G - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 87, 1, _timer_isr); /* verified */ -#else - /* FIXME: verify value */ - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 80, 1, _timer_isr); -#endif -#elif CONFIG_LCD == LCD_IPODMINI - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 88, 1, _timer_isr); -#elif CONFIG_LCD == LCD_IFP7XX - _gray_rb->timer_register(1, NULL, TIMER_FREQ / 83, 1, _timer_isr); -#endif /* CONFIG_LCD */ -#endif /* !SIMULATOR */ - _gray_rb->screen_dump_set_hook(gray_screendump_hook); - } - else if (!enable && (_gray_info.flags & _GRAY_RUNNING)) - { -#ifdef SIMULATOR - _gray_rb->sim_lcd_ex_init(0, NULL); -#else - _gray_rb->timer_unregister(); -#ifdef NEED_BOOST - _gray_rb->cpu_boost(false); -#endif -#endif - _gray_info.flags &= ~_GRAY_RUNNING; - _gray_rb->screen_dump_set_hook(NULL); - _gray_rb->lcd_update(); /* restore whatever there was before */ - } -} - -#ifdef SIMULATOR -/* Callback function for gray_update_rect() to read a pixel from the graybuffer. - Note that x and y are in LCD coordinates, not graybuffer coordinates! */ -static unsigned long _gray_get_pixel(int x, int y) -{ -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - return _gray_info.cur_buffer[_GRAY_MULUQ(y - _gray_info.y, _gray_info.width) - + x - _gray_info.x] - + (1 << LCD_DEPTH); -#else - return _gray_info.cur_buffer[_GRAY_MULUQ(x - _gray_info.x, _gray_info.height) - + y - _gray_info.y] - + (1 << LCD_DEPTH); -#endif -} - -/* Update a rectangular area of the greyscale overlay */ -void gray_update_rect(int x, int y, int width, int height) -{ - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (y + height > _gray_info.height) - height = _gray_info.height - y; - - x += _gray_info.x; - y += _gray_info.y; - - if (x + width > LCD_WIDTH) - width = LCD_WIDTH - x; - if (y + height > LCD_HEIGHT) - height = LCD_HEIGHT - y; - - _gray_rb->sim_lcd_ex_update_rect(x, y, width, height); -} - -#else /* !SIMULATOR */ - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - -/* Update a rectangular area of the greyscale overlay */ -void gray_update_rect(int x, int y, int width, int height) -{ - int xmax, bwidth; - long srcofs; - unsigned char *dst; - - if ((width <= 0) || (height <= 0)) - return; /* nothing to do */ - - /* The X coordinates have to work on whole pixel block columns */ - xmax = (x + width - 1) >> 3; - x >>= 3; - - if (y + height > _gray_info.height) - height = _gray_info.height - y; - if (xmax >= _gray_info.bwidth) - xmax = _gray_info.bwidth - 1; - bwidth = xmax - x + 1; - - srcofs = _GRAY_MULUQ(_gray_info.width, y) + (x << 3); - dst = _gray_info.plane_data + _GRAY_MULUQ(_gray_info.bwidth, y) + x; - - /* Copy specified rectangle bitmap to hardware */ - for (; height > 0; height--) - { - long srcofs_row = srcofs; - unsigned char *dst_row = dst; - unsigned char *dst_end = dst_row + bwidth; - - do - { - unsigned long pat_stack[8]; - unsigned long *pat_ptr; - unsigned char *cbuf, *bbuf; - unsigned change; - - cbuf = _gray_info.cur_buffer + srcofs_row; - bbuf = _gray_info.back_buffer + srcofs_row; - -#ifdef CPU_ARM - asm volatile - ( - "ldr r0, [%[cbuf]] \n" - "ldr r1, [%[bbuf]] \n" - "eor r1, r0, r1 \n" - "ldr r0, [%[cbuf], #4] \n" - "ldr %[chg], [%[bbuf], #4] \n" - "eor %[chg], r0, %[chg] \n" - "orr %[chg], %[chg], r1 \n" - : /* outputs */ - [chg] "=&r"(change) - : /* inputs */ - [cbuf]"r"(cbuf), - [bbuf]"r"(bbuf) - : /* clobbers */ - "r0", "r1" - ); - - if (change != 0) - { - unsigned char *addr; - unsigned mask, depth, trash; - - pat_ptr = &pat_stack[8]; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "mov r3, #8 \n" /* loop count */ - "mov %[mask], #0 \n" - - ".ur_pre_loop: \n" - "mov %[mask], %[mask], lsl #1 \n" /* shift mask */ - "ldrb r0, [%[cbuf]], #1 \n" /* read current buffer */ - "ldrb r1, [%[bbuf]] \n" /* read back buffer */ - "strb r0, [%[bbuf]], #1 \n" /* update back buffer */ - "mov r2, #0 \n" /* preset for skipped pixel */ - "cmp r0, r1 \n" /* no change? */ - "beq .ur_skip \n" /* -> skip */ - - "ldr r2, [%[bpat], r0, lsl #2] \n" /* r2 = bitpattern[byte]; */ - - "add %[rnd], %[rnd], %[rnd], lsl #2 \n" /* multiply by 75 */ - "rsb %[rnd], %[rnd], %[rnd], lsl #4 \n" - "add %[rnd], %[rnd], #74 \n" /* add another 74 */ - /* Since the lower bits are not very random: get bits 8..15 (need max. 5) */ - "and r1, %[rmsk], %[rnd], lsr #8 \n" /* ..and mask out unneeded bits */ - - "cmp r1, %[dpth] \n" /* random >= depth ? */ - "subhs r1, r1, %[dpth] \n" /* yes: random -= depth */ - - "mov r0, r2, lsl r1 \n" /** rotate pattern **/ - "sub r1, %[dpth], r1 \n" - "orr r2, r0, r2, lsr r1 \n" - - "orr %[mask], %[mask], #1 \n" /* set mask bit */ - - ".ur_skip: \n" - "str r2, [%[patp], #-4]! \n" /* push on pattern stack */ - - "subs r3, r3, #1 \n" /* loop 8 times (pixel block) */ - "bne .ur_pre_loop \n" - : /* outputs */ - [cbuf]"+r"(cbuf), - [bbuf]"+r"(bbuf), - [patp]"+r"(pat_ptr), - [rnd] "+r"(_gray_random_buffer), - [mask]"=&r"(mask) - : /* inputs */ - [bpat]"r"(_gray_info.bitpattern), - [dpth]"r"(_gray_info.depth), - [rmsk]"r"(_gray_info.randmask) - : /* clobbers */ - "r0", "r1", "r2", "r3" - ); - - addr = dst_row; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "ldmia %[patp], {r1 - r8} \n" /* pop all 8 patterns */ - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "mov %[rx], #0xF0 \n" /** Stage 1: 4 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11110000 */ - "eor r0, r1, r5, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */ - "eor r5, r5, r0, lsr #4 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */ - "eor r0, r2, r6, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */ - "eor r6, r6, r0, lsr #4 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */ - "eor r0, r3, r7, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */ - "eor r7, r7, r0, lsr #4 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */ - "eor r0, r4, r8, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r4, r4, r0 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */ - "eor r8, r8, r0, lsr #4 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */ - - "mov %[rx], #0xCC \n" /** Stage 2: 2 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11001100 */ - "eor r0, r1, r3, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */ - "eor r3, r3, r0, lsr #2 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */ - "eor r0, r2, r4, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "eor r4, r4, r0, lsr #2 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */ - "eor r0, r5, r7, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */ - "eor r7, r7, r0, lsr #2 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */ - "eor r0, r6, r8, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r6, r6, r0 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */ - "eor r8, r8, r0, lsr #2 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */ - - "mov %[rx], #0xAA \n" /** Stage 3: 1 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...10101010 */ - "eor r0, r1, r2, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */ - "eor r2, r2, r0, lsr #1 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */ - "eor r0, r3, r4, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */ - "eor r4, r4, r0, lsr #1 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */ - "eor r0, r5, r6, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */ - "eor r6, r6, r0, lsr #1 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */ - "eor r0, r7, r8, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r7, r7, r0 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */ - "eor r8, r8, r0, lsr #1 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */ - - "sub r0, %[dpth], #1 \n" /** shift out unused low bytes **/ - "and r0, r0, #7 \n" - "add pc, pc, r0, lsl #2 \n" /* jump into shift streak */ - "mov r8, r8, lsr #8 \n" /* r8: never reached */ - "mov r7, r7, lsr #8 \n" - "mov r6, r6, lsr #8 \n" - "mov r5, r5, lsr #8 \n" - "mov r4, r4, lsr #8 \n" - "mov r3, r3, lsr #8 \n" - "mov r2, r2, lsr #8 \n" - "mov r1, r1, lsr #8 \n" - - "mvn %[mask], %[mask] \n" /* "set" mask -> "keep" mask */ - "ands %[mask], %[mask], #0xff \n" - "beq .ur_sstart \n" /* short loop if no bits to keep */ - - "ldrb r0, [pc, r0] \n" /* jump into full loop */ - "add pc, pc, r0 \n" - ".ur_ftable: \n" - ".byte .ur_f1 - .ur_ftable - 4 \n" /* [jump tables are tricky] */ - ".byte .ur_f2 - .ur_ftable - 4 \n" - ".byte .ur_f3 - .ur_ftable - 4 \n" - ".byte .ur_f4 - .ur_ftable - 4 \n" - ".byte .ur_f5 - .ur_ftable - 4 \n" - ".byte .ur_f6 - .ur_ftable - 4 \n" - ".byte .ur_f7 - .ur_ftable - 4 \n" - ".byte .ur_f8 - .ur_ftable - 4 \n" - - ".ur_floop: \n" /** full loop (bits to keep)**/ - ".ur_f8: \n" - "ldrb r0, [%[addr]] \n" /* load old byte */ - "and r0, r0, %[mask] \n" /* mask out replaced bits */ - "orr r0, r0, r1 \n" /* set new bits */ - "strb r0, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".ur_f7: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r2 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".ur_f6: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r3 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".ur_f5: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r4 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".ur_f4: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r5 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".ur_f3: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r6 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".ur_f2: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r7 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".ur_f1: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r8 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .ur_floop \n" - - "b .ur_end \n" - - ".ur_sstart: \n" - "ldrb r0, [pc, r0] \n" /* jump into short loop*/ - "add pc, pc, r0 \n" - ".ur_stable: \n" - ".byte .ur_s1 - .ur_stable - 4 \n" - ".byte .ur_s2 - .ur_stable - 4 \n" - ".byte .ur_s3 - .ur_stable - 4 \n" - ".byte .ur_s4 - .ur_stable - 4 \n" - ".byte .ur_s5 - .ur_stable - 4 \n" - ".byte .ur_s6 - .ur_stable - 4 \n" - ".byte .ur_s7 - .ur_stable - 4 \n" - ".byte .ur_s8 - .ur_stable - 4 \n" - - ".ur_sloop: \n" /** short loop (nothing to keep) **/ - ".ur_s8: \n" - "strb r1, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".ur_s7: \n" - "strb r2, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".ur_s6: \n" - "strb r3, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".ur_s5: \n" - "strb r4, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".ur_s4: \n" - "strb r5, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".ur_s3: \n" - "strb r6, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".ur_s2: \n" - "strb r7, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".ur_s1: \n" - "strb r8, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .ur_sloop \n" - - ".ur_end: \n" - : /* outputs */ - [addr]"+r"(addr), - [mask]"+r"(mask), - [dpth]"+r"(depth), - [rx] "=&r"(trash) - : /* inputs */ - [psiz]"r"(_gray_info.plane_size), - [patp]"[rx]"(pat_ptr) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" - ); - } -#else /* C version, for reference*/ -#warning C version of gray_update_rect() used - (void)pat_ptr; - /* check whether anything changed in the 8-pixel block */ - change = *(uint32_t *)cbuf ^ *(uint32_t *)bbuf; - change |= *(uint32_t *)(cbuf + 4) ^ *(uint32_t *)(bbuf + 4); - - if (change != 0) - { - unsigned char *addr, *end; - unsigned mask = 0; - unsigned test = 1 << ((-_gray_info.depth) & 7); - int i; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - for (i = 7; i >= 0; i--) - { - unsigned pat = 0; - unsigned char cur = *cbuf++; - unsigned char back = *bbuf; - - *bbuf++ = cur; - - mask <<= 1; - if (cur != back) - { - int shift; - - pat = _gray_info.bitpattern[cur]; - - /* shift pattern pseudo-random, simple & fast PRNG */ - _gray_random_buffer = 75 * _gray_random_buffer + 74; - shift = (_gray_random_buffer >> 8) & _gray_info.randmask; - if (shift >= _gray_info.depth) - shift -= _gray_info.depth; - - pat = (pat << shift) | (pat >> (_gray_info.depth - shift)); - - mask |= 1; - } - pat_stack[i] = pat; - } - - addr = dst_row; - end = addr + _GRAY_MULUQ(_gray_info.depth, _gray_info.plane_size); - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - mask = (~mask & 0xff); - if (mask == 0) - { - do - { - unsigned data = 0; - - for (i = 7; i >= 0; i--) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } - else - { - do - { - unsigned data = 0; - - for (i = 7; i >= 0; i--) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = (*addr & mask) | data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } - - } -#endif /* CONFIG_CPU */ - srcofs_row += 8; - dst_row++; - } - while (dst_row < dst_end); - - srcofs += _gray_info.width; - dst += _gray_info.bwidth; - } -} -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - -/* Update a rectangular area of the greyscale overlay */ -void gray_update_rect(int x, int y, int width, int height) -{ - int ymax; - long srcofs; - unsigned char *dst; - - if ((width <= 0) || (height <= 0)) - return; /* nothing to do */ - - /* The Y coordinates have to work on whole pixel block rows */ - ymax = (y + height - 1) >> 3; - y >>= 3; - - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (ymax >= _gray_info.bheight) - ymax = _gray_info.bheight - 1; - - srcofs = (y << 3) + _GRAY_MULUQ(_gray_info.height, x); - dst = _gray_info.plane_data + _GRAY_MULUQ(_gray_info.width, y) + x; - - /* Copy specified rectangle bitmap to hardware */ - for (; y <= ymax; y++) - { - long srcofs_row = srcofs; - unsigned char *dst_row = dst; - unsigned char *dst_end = dst_row + width; - - do - { - unsigned long pat_stack[8]; - unsigned long *pat_ptr; - unsigned char *cbuf, *bbuf; - unsigned change; - - cbuf = _gray_info.cur_buffer + srcofs_row; - bbuf = _gray_info.back_buffer + srcofs_row; - -#if CONFIG_CPU == SH7034 - asm volatile ( - "mov.l @%[bbuf], r2 \n" - "mov.l @%[cbuf], r1 \n" - "mov.l @(4,%[bbuf]), %[chg]\n" - "xor r1, r2 \n" - "mov.l @(4,%[cbuf]), r1 \n" - "xor r1, %[chg] \n" - "or r2, %[chg] \n" - : /* outputs */ - [chg] "=r"(change) - : /* inputs */ - [cbuf]"r"(cbuf), - [bbuf]"r"(bbuf) - : /* clobbers */ - "r1", "r2" - ); - - if (change != 0) - { - unsigned char *addr; - unsigned mask, depth, trash; - - pat_ptr = &pat_stack[8]; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "mov #8, r3 \n" /* loop count */ - - ".ur_pre_loop: \n" - "mov.b @%[cbuf]+, r0 \n" /* read current buffer */ - "mov.b @%[bbuf], r1 \n" /* read back buffer */ - "mov #0, r2 \n" /* preset for skipped pixel */ - "mov.b r0, @%[bbuf] \n" /* update back buffer */ - "add #1, %[bbuf] \n" - "cmp/eq r0, r1 \n" /* no change? */ - "bt .ur_skip \n" /* -> skip */ - - "mov #75, r1 \n" - "mulu r1, %[rnd] \n" /* multiply by 75 */ - "shll2 r0 \n" /* pixel value -> pattern offset */ - "mov.l @(r0,%[bpat]), r4 \n" /* r4 = bitpattern[byte]; */ - "sts macl, %[rnd] \n" - "add #74, %[rnd] \n" /* add another 74 */ - /* Since the lower bits are not very random: */ - "swap.b %[rnd], r1 \n" /* get bits 8..15 (need max. 5) */ - "and %[rmsk], r1 \n" /* mask out unneeded bits */ - - "cmp/hs %[dpth], r1 \n" /* random >= depth ? */ - "bf .ur_ntrim \n" - "sub %[dpth], r1 \n" /* yes: random -= depth; */ - ".ur_ntrim: \n" - - "mov.l .ashlsi3, r0 \n" /** rotate pattern **/ - "jsr @r0 \n" /* r4 -> r0, shift left by r5 */ - "mov r1, r5 \n" - - "mov %[dpth], r5 \n" - "sub r1, r5 \n" /* r5 = depth - r1 */ - "mov.l .lshrsi3, r1 \n" - "jsr @r1 \n" /* r4 -> r0, shift right by r5 */ - "mov r0, r2 \n" /* store previous result in r2 */ - - "or r0, r2 \n" /* rotated_pattern = r2 | r0 */ - "clrt \n" /* mask bit = 0 (replace) */ - - ".ur_skip: \n" /* T == 1 if skipped */ - "rotcr %[mask] \n" /* get mask bit */ - "mov.l r2, @-%[patp] \n" /* push on pattern stack */ - - "add #-1, r3 \n" /* loop 8 times (pixel block) */ - "cmp/pl r3 \n" - "bt .ur_pre_loop \n" - - "shlr8 %[mask] \n" /* shift mask to low byte */ - "shlr16 %[mask] \n" - : /* outputs */ - [cbuf]"+r"(cbuf), - [bbuf]"+r"(bbuf), - [rnd] "+r"(_gray_random_buffer), - [patp]"+r"(pat_ptr), - [mask]"=&r"(mask) - : /* inputs */ - [dpth]"r"(_gray_info.depth), - [bpat]"r"(_gray_info.bitpattern), - [rmsk]"r"(_gray_info.randmask) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "macl", "pr" - ); - - addr = dst_row; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "mov.l @%[patp]+, r8 \n" /* pop all 8 patterns */ - "mov.l @%[patp]+, r7 \n" - "mov.l @%[patp]+, r6 \n" - "mov.l @%[patp]+, r5 \n" - "mov.l @%[patp]+, r4 \n" - "mov.l @%[patp]+, r3 \n" - "mov.l @%[patp]+, r2 \n" - "mov.l @%[patp], r1 \n" - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "mov.l .ur_mask4, %[rx] \n" /* bitmask = ...11110000 */ - "mov r5, r0 \n" /** Stage 1: 4 bit "comb" **/ - "shll2 r0 \n" - "shll2 r0 \n" - "xor r1, r0 \n" - "and %[rx], r0 \n" - "xor r0, r1 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r5 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */ - "mov r6, r0 \n" - "shll2 r0 \n" - "shll2 r0 \n" - "xor r2, r0 \n" - "and %[rx], r0 \n" - "xor r0, r2 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r6 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */ - "mov r7, r0 \n" - "shll2 r0 \n" - "shll2 r0 \n" - "xor r3, r0 \n" - "and %[rx], r0 \n" - "xor r0, r3 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r7 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */ - "mov r8, r0 \n" - "shll2 r0 \n" - "shll2 r0 \n" - "xor r4, r0 \n" - "and %[rx], r0 \n" - "xor r0, r4 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r8 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */ - - "mov.l .ur_mask2, %[rx] \n" /* bitmask = ...11001100 */ - "mov r3, r0 \n" /** Stage 2: 2 bit "comb" **/ - "shll2 r0 \n" - "xor r1, r0 \n" - "and %[rx], r0 \n" - "xor r0, r1 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */ - "shlr2 r0 \n" - "xor r0, r3 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */ - "mov r4, r0 \n" - "shll2 r0 \n" - "xor r2, r0 \n" - "and %[rx], r0 \n" - "xor r0, r2 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "shlr2 r0 \n" - "xor r0, r4 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */ - "mov r7, r0 \n" - "shll2 r0 \n" - "xor r5, r0 \n" - "and %[rx], r0 \n" - "xor r0, r5 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */ - "shlr2 r0 \n" - "xor r0, r7 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */ - "mov r8, r0 \n" - "shll2 r0 \n" - "xor r6, r0 \n" - "and %[rx], r0 \n" - "xor r0, r6 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */ - "shlr2 r0 \n" - "xor r0, r8 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */ - - "mov.l .ur_mask1, %[rx] \n" /* bitmask = ...10101010 */ - "mov r2, r0 \n" /** Stage 3: 1 bit "comb" **/ - "shll r0 \n" - "xor r1, r0 \n" - "and %[rx], r0 \n" - "xor r0, r1 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */ - "shlr r0 \n" - "xor r0, r2 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */ - "mov r4, r0 \n" - "shll r0 \n" - "xor r3, r0 \n" - "and %[rx], r0 \n" - "xor r0, r3 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */ - "shlr r0 \n" - "xor r0, r4 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */ - "mov r6, r0 \n" - "shll r0 \n" - "xor r5, r0 \n" - "and %[rx], r0 \n" - "xor r0, r5 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */ - "shlr r0 \n" - "xor r0, r6 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */ - "mov r8, r0 \n" - "shll r0 \n" - "xor r7, r0 \n" - "and %[rx], r0 \n" - "xor r0, r7 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */ - "shlr r0 \n" - "xor r0, r8 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */ - - "mov %[dpth], %[rx] \n" /** shift out unused low bytes **/ - "add #-1, %[rx] \n" - "mov #7, r0 \n" - "and r0, %[rx] \n" - "mova .ur_pshift, r0 \n" - "add %[rx], r0 \n" - "add %[rx], r0 \n" - "jmp @r0 \n" /* jump into shift streak */ - "nop \n" - - ".align 2 \n" - ".ur_pshift: \n" - "shlr8 r7 \n" - "shlr8 r6 \n" - "shlr8 r5 \n" - "shlr8 r4 \n" - "shlr8 r3 \n" - "shlr8 r2 \n" - "shlr8 r1 \n" - - "tst %[mask], %[mask] \n" - "bt .ur_sstart \n" /* short loop if nothing to keep */ - - "mova .ur_ftable, r0 \n" /* jump into full loop */ - "mov.b @(r0, %[rx]), %[rx] \n" - "add %[rx], r0 \n" - "jmp @r0 \n" - "nop \n" - - ".align 2 \n" - ".ur_ftable: \n" - ".byte .ur_f1 - .ur_ftable \n" - ".byte .ur_f2 - .ur_ftable \n" - ".byte .ur_f3 - .ur_ftable \n" - ".byte .ur_f4 - .ur_ftable \n" - ".byte .ur_f5 - .ur_ftable \n" - ".byte .ur_f6 - .ur_ftable \n" - ".byte .ur_f7 - .ur_ftable \n" - ".byte .ur_f8 - .ur_ftable \n" - - ".ur_floop: \n" /** full loop (there are bits to keep)**/ - ".ur_f8: \n" - "mov.b @%[addr], r0 \n" /* load old byte */ - "and %[mask], r0 \n" /* mask out replaced bits */ - "or r1, r0 \n" /* set new bits */ - "mov.b r0, @%[addr] \n" /* store byte */ - "add %[psiz], %[addr] \n" - "shlr8 r1 \n" /* shift out used-up byte */ - ".ur_f7: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r2, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r2 \n" - ".ur_f6: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r3, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r3 \n" - ".ur_f5: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r4, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r4 \n" - ".ur_f4: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r5, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r5 \n" - ".ur_f3: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r6, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r6 \n" - ".ur_f2: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r7, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r7 \n" - ".ur_f1: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r8, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r8 \n" - - "add #-8, %[dpth] \n" - "cmp/pl %[dpth] \n" /* next round if anything left */ - "bt .ur_floop \n" - - "bra .ur_end \n" - "nop \n" - - /* References to C library routines used in the precalc block */ - ".align 2 \n" - ".ashlsi3: \n" /* C library routine: */ - ".long ___ashlsi3 \n" /* shift r4 left by r5, result in r0 */ - ".lshrsi3: \n" /* C library routine: */ - ".long ___lshrsi3 \n" /* shift r4 right by r5, result in r0 */ - /* both routines preserve r4, destroy r5 and take ~16 cycles */ - - /* Bitmasks for the bit block rotation */ - ".ur_mask4: \n" - ".long 0xF0F0F0F0 \n" - ".ur_mask2: \n" - ".long 0xCCCCCCCC \n" - ".ur_mask1: \n" - ".long 0xAAAAAAAA \n" - - ".ur_sstart: \n" - "mova .ur_stable, r0 \n" /* jump into short loop */ - "mov.b @(r0, %[rx]), %[rx] \n" - "add %[rx], r0 \n" - "jmp @r0 \n" - "nop \n" - - ".align 2 \n" - ".ur_stable: \n" - ".byte .ur_s1 - .ur_stable \n" - ".byte .ur_s2 - .ur_stable \n" - ".byte .ur_s3 - .ur_stable \n" - ".byte .ur_s4 - .ur_stable \n" - ".byte .ur_s5 - .ur_stable \n" - ".byte .ur_s6 - .ur_stable \n" - ".byte .ur_s7 - .ur_stable \n" - ".byte .ur_s8 - .ur_stable \n" - - ".ur_sloop: \n" /** short loop (nothing to keep) **/ - ".ur_s8: \n" - "mov.b r1, @%[addr] \n" /* store byte */ - "add %[psiz], %[addr] \n" - "shlr8 r1 \n" /* shift out used-up byte */ - ".ur_s7: \n" - "mov.b r2, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r2 \n" - ".ur_s6: \n" - "mov.b r3, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r3 \n" - ".ur_s5: \n" - "mov.b r4, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r4 \n" - ".ur_s4: \n" - "mov.b r5, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r5 \n" - ".ur_s3: \n" - "mov.b r6, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r6 \n" - ".ur_s2: \n" - "mov.b r7, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r7 \n" - ".ur_s1: \n" - "mov.b r8, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r8 \n" - - "add #-8, %[dpth] \n" - "cmp/pl %[dpth] \n" /* next round if anything left */ - "bt .ur_sloop \n" - - ".ur_end: \n" - : /* outputs */ - [addr]"+r"(addr), - [dpth]"+r"(depth), - [rx] "=&r"(trash) - : /* inputs */ - [mask]"r"(mask), - [psiz]"r"(_gray_info.plane_size), - [patp]"[rx]"(pat_ptr) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "macl" - ); - } -#elif defined(CPU_COLDFIRE) - asm volatile ( - "move.l (%[cbuf]), %%d0 \n" - "move.l (%[bbuf]), %%d1 \n" - "eor.l %%d0, %%d1 \n" - "move.l (4,%[cbuf]), %%d0 \n" - "move.l (4,%[bbuf]), %[chg] \n" - "eor.l %%d0, %[chg] \n" - "or.l %%d1, %[chg] \n" - : /* outputs */ - [chg] "=&d"(change) - : /* inputs */ - [cbuf]"a"(cbuf), - [bbuf]"a"(bbuf) - : /* clobbers */ - "d0", "d1" - ); - - if (change != 0) - { - unsigned char *addr; - unsigned mask, depth, trash; - - pat_ptr = &pat_stack[8]; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "moveq.l #8, %%d3 \n" /* loop count */ - "clr.l %[mask] \n" - - ".ur_pre_loop: \n" - "clr.l %%d0 \n" - "move.b (%[cbuf])+, %%d0 \n" /* read current buffer */ - "clr.l %%d1 \n" - "move.b (%[bbuf]), %%d1 \n" /* read back buffer */ - "move.b %%d0, (%[bbuf])+ \n" /* update back buffer */ - "clr.l %%d2 \n" /* preset for skipped pixel */ - "cmp.l %%d0, %%d1 \n" /* no change? */ - "beq.b .ur_skip \n" /* -> skip */ - - "move.l (%%d0:l:4, %[bpat]), %%d2 \n" /* d2 = bitpattern[byte]; */ - - "mulu.w #75, %[rnd] \n" /* multiply by 75 */ - "add.l #74, %[rnd] \n" /* add another 74 */ - /* Since the lower bits are not very random: */ - "move.l %[rnd], %%d1 \n" - "lsr.l #8, %%d1 \n" /* get bits 8..15 (need max. 5) */ - "and.l %[rmsk], %%d1 \n" /* mask out unneeded bits */ - - "cmp.l %[dpth], %%d1 \n" /* random >= depth ? */ - "blo.b .ur_ntrim \n" - "sub.l %[dpth], %%d1 \n" /* yes: random -= depth; */ - ".ur_ntrim: \n" - - "move.l %%d2, %%d0 \n" /** rotate pattern **/ - "lsl.l %%d1, %%d0 \n" - "sub.l %[dpth], %%d1 \n" - "neg.l %%d1 \n" /* d1 = depth - d1 */ - "lsr.l %%d1, %%d2 \n" - "or.l %%d0, %%d2 \n" /* rotated_pattern = d2 | d0 */ - - "or.l #0x0100, %[mask] \n" /* set mask bit */ - - ".ur_skip: \n" - "lsr.l #1, %[mask] \n" /* shift mask */ - "move.l %%d2, -(%[patp]) \n" /* push on pattern stack */ - - "subq.l #1, %%d3 \n" /* loop 8 times (pixel block) */ - "bne.b .ur_pre_loop \n" - : /* outputs */ - [cbuf]"+a"(cbuf), - [bbuf]"+a"(bbuf), - [patp]"+a"(pat_ptr), - [rnd] "+d"(_gray_random_buffer), - [mask]"=&d"(mask) - : /* inputs */ - [bpat]"a"(_gray_info.bitpattern), - [dpth]"d"(_gray_info.depth), - [rmsk]"d"(_gray_info.randmask) - : /* clobbers */ - "d0", "d1", "d2", "d3" - ); - - addr = dst_row; - mask = ~mask & 0xff; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "movem.l (%[patp]), %%d1-%%d7/%%a0 \n" /* pop all 8 patterns */ - /* move.l %%d5, %[ax] */ /* need %%d5 as workspace, but not yet */ - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "move.l %%d1, %%d0 \n" /** Stage 1: 4 bit "comb" **/ - "lsl.l #4, %%d0 \n" - /* move.l %[ax], %%d5 */ /* already in d5 */ - "eor.l %%d5, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" /* bitmask = ...11110000 */ - "eor.l %%d0, %%d5 \n" - "move.l %%d5, %[ax] \n" /* ax = ...h3h2h1h0d3d2d1d0 */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d1 \n" /* d1 = ...h7h6h5h4d7d6d5d4 */ - "move.l %%d2, %%d0 \n" - "lsl.l #4, %%d0 \n" - "eor.l %%d6, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" - "eor.l %%d0, %%d6 \n" /* d6 = ...g3g2g1g0c3c2c1c0 */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d2 \n" /* d2 = ...g7g6g5g4c7c6c5c4 */ - "move.l %%d3, %%d0 \n" - "lsl.l #4, %%d0 \n" - "eor.l %%d7, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" - "eor.l %%d0, %%d7 \n" /* d7 = ...f3f2f1f0b3b2b1b0 */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d3 \n" /* d3 = ...f7f6f5f4f7f6f5f4 */ - "move.l %%d4, %%d0 \n" - "lsl.l #4, %%d0 \n" - "move.l %%a0, %%d5 \n" - "eor.l %%d5, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" - "eor.l %%d0, %%d5 \n" /* (a0 = ...e3e2e1e0a3a2a1a0) */ - /* move.l %%d5, %%a0 */ /* but d5 is kept until next usage */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d4 \n" /* d4 = ...e7e6e5e4a7a6a5a4 */ - - "move.l %%d6, %%d0 \n" /** Stage 2: 2 bit "comb" **/ - "lsl.l #2, %%d0 \n" - /* move.l %%a0, %%d5 */ /* still in d5 */ - "eor.l %%d5, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" /* bitmask = ...11001100 */ - "eor.l %%d0, %%d5 \n" - "move.l %%d5, %%a0 \n" /* a0 = ...g1g0e1e0c1c0a1a0 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d6 \n" /* d6 = ...g3g2e3e2c3c2a3a2 */ - "move.l %[ax], %%d5 \n" - "move.l %%d5, %%d0 \n" - "lsl.l #2, %%d0 \n" - "eor.l %%d7, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" - "eor.l %%d0, %%d7 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d5 \n" /* (ax = ...h3h2f3f2d3d2b3b2) */ - /* move.l %%d5, %[ax] */ /* but d5 is kept until next usage */ - "move.l %%d2, %%d0 \n" - "lsl.l #2, %%d0 \n" - "eor.l %%d4, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" - "eor.l %%d0, %%d4 \n" /* d4 = ...g5g4e5e4c5c4a5a4 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d2 \n" /* d2 = ...g7g6e7e6c7c6a7a6 */ - "move.l %%d1, %%d0 \n" - "lsl.l #2, %%d0 \n" - "eor.l %%d3, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" - "eor.l %%d0, %%d3 \n" /* d3 = ...h5h4f5f4d5d4b5b4 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d1 \n" /* d1 = ...h7h6f7f6d7d6b7b6 */ - - "move.l %%d1, %%d0 \n" /** Stage 3: 1 bit "comb" **/ - "lsl.l #1, %%d0 \n" - "eor.l %%d2, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" /* bitmask = ...10101010 */ - "eor.l %%d0, %%d2 \n" /* d2 = ...h6g6f6e6d6c6b6a6 */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d1 \n" /* d1 = ...h7g7f7e7d7c7b7a7 */ - "move.l %%d3, %%d0 \n" - "lsl.l #1, %%d0 \n" - "eor.l %%d4, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" - "eor.l %%d0, %%d4 \n" /* d4 = ...h4g4f4e4d4c4b4a4 */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d3 \n" /* d3 = ...h5g5f5e5d5c5b5a5 */ - /* move.l %[ax], %%d5 */ /* still in d5 */ - "move.l %%d5, %%d0 \n" - "lsl.l #1, %%d0 \n" - "eor.l %%d6, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" - "eor.l %%d0, %%d6 \n" /* d6 = ...h2g2f2e2d2c2b2a2 */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d5 \n" - "move.l %%d5, %[ax] \n" /* ax = ...h3g3f3e3d3c3b3a3 */ - "move.l %%d7, %%d0 \n" - "lsl.l #1, %%d0 \n" - "move.l %%a0, %%d5 \n" - "eor.l %%d5, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" - "eor.l %%d0, %%d5 \n" /* (a0 = ...h0g0f0e0d0c0b0a0) */ - /* move.l %%d5, %%a0 */ /* but keep in d5 for shift streak */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d7 \n" /* d7 = ...h1g1f1e1d1c1b1a1 */ - - "move.l %[dpth], %%d0 \n" /** shift out unused low bytes **/ - "subq.l #1, %%d0 \n" - "and.l #7, %%d0 \n" - "move.l %%d0, %%a0 \n" - "move.l %[ax], %%d0 \n" /* all data in D registers */ - "jmp (2, %%pc, %%a0:l:2) \n" /* jump into shift streak */ - "lsr.l #8, %%d2 \n" - "lsr.l #8, %%d3 \n" - "lsr.l #8, %%d4 \n" - "lsr.l #8, %%d0 \n" - "lsr.l #8, %%d6 \n" - "lsr.l #8, %%d7 \n" - "lsr.l #8, %%d5 \n" - "move.l %%d0, %[ax] \n" /* put the 2 extra words back.. */ - "move.l %%a0, %%d0 \n" /* keep the value for later */ - "move.l %%d5, %%a0 \n" /* ..into their A registers */ - - "tst.l %[mask] \n" - "jeq .ur_sstart \n" /* short loop if nothing to keep */ - - "move.l %[mask], %%d5 \n" /* need mask in data reg. */ - "move.l %%d1, %[mask] \n" /* free d1 as working reg. */ - - "jmp (2, %%pc, %%d0:l:2) \n" /* jump into full loop */ - "bra.s .ur_f1 \n" - "bra.s .ur_f2 \n" - "bra.s .ur_f3 \n" - "bra.s .ur_f4 \n" - "bra.s .ur_f5 \n" - "bra.s .ur_f6 \n" - "bra.s .ur_f7 \n" - /* bra.s .ur_f8 */ /* identical with target */ - - ".ur_floop: \n" /** full loop (there are bits to keep)**/ - ".ur_f8: \n" - "move.b (%[addr]), %%d0 \n" /* load old byte */ - "and.l %%d5, %%d0 \n" /* mask out replaced bits */ - "move.l %%a0, %%d1 \n" - "or.l %%d1, %%d0 \n" /* set new bits */ - "move.b %%d0, (%[addr]) \n" /* store byte */ - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" /* shift out used-up byte */ - "move.l %%d1, %%a0 \n" - ".ur_f7: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d7, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d7 \n" - ".ur_f6: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d6, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d6 \n" - ".ur_f5: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "move.l %[ax], %%d1 \n" - "or.l %%d1, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" - "move.l %%d1, %[ax] \n" - ".ur_f4: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d4, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d4 \n" - ".ur_f3: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d3, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d3 \n" - ".ur_f2: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d2, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d2 \n" - ".ur_f1: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "move.l %[mask], %%d1 \n" - "or.l %%d1, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" - "move.l %%d1, %[mask] \n" - - "subq.l #8, %[dpth] \n" - "tst.l %[dpth] \n" /* subq doesn't set flags for A reg */ - "jgt .ur_floop \n" /* next round if anything left */ - - "jra .ur_end \n" - - ".ur_sstart: \n" - "jmp (2, %%pc, %%d0:l:2) \n" /* jump into short loop */ - "bra.s .ur_s1 \n" - "bra.s .ur_s2 \n" - "bra.s .ur_s3 \n" - "bra.s .ur_s4 \n" - "bra.s .ur_s5 \n" - "bra.s .ur_s6 \n" - "bra.s .ur_s7 \n" - /* bra.s .ur_s8 */ /* identical with target */ - - ".ur_sloop: \n" /** short loop (nothing to keep) **/ - ".ur_s8: \n" - "move.l %%a0, %%d5 \n" - "move.b %%d5, (%[addr]) \n" /* store byte */ - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d5 \n" /* shift out used-up byte */ - "move.l %%d5, %%a0 \n" - ".ur_s7: \n" - "move.b %%d7, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d7 \n" - ".ur_s6: \n" - "move.b %%d6, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d6 \n" - ".ur_s5: \n" - "move.l %[ax], %%d5 \n" - "move.b %%d5, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d5 \n" - "move.l %%d5, %[ax] \n" - ".ur_s4: \n" - "move.b %%d4, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d4 \n" - ".ur_s3: \n" - "move.b %%d3, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d3 \n" - ".ur_s2: \n" - "move.b %%d2, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d2 \n" - ".ur_s1: \n" - "move.b %%d1, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" - - "subq.l #8, %[dpth] \n" - "tst.l %[dpth] \n" /* subq doesn't set flags for A reg */ - "jgt .ur_sloop \n" /* next round if anything left */ - - ".ur_end: \n" - : /* outputs */ - [addr]"+a"(addr), - [dpth]"+a"(depth), - [mask]"+a"(mask), - [ax] "=&a"(trash) - : /* inputs */ - [psiz]"a"(_gray_info.plane_size), - [patp]"[ax]"(pat_ptr) - : /* clobbers */ - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0" - ); - } -#elif defined(CPU_ARM) - asm volatile - ( - "ldr r0, [%[cbuf]] \n" - "ldr r1, [%[bbuf]] \n" - "eor r1, r0, r1 \n" - "ldr r0, [%[cbuf], #4] \n" - "ldr %[chg], [%[bbuf], #4] \n" - "eor %[chg], r0, %[chg] \n" - "orr %[chg], %[chg], r1 \n" - : /* outputs */ - [chg] "=&r"(change) - : /* inputs */ - [cbuf]"r"(cbuf), - [bbuf]"r"(bbuf) - : /* clobbers */ - "r0", "r1" - ); - - if (change != 0) - { - unsigned char *addr; - unsigned mask, depth, trash; - - pat_ptr = &pat_stack[0]; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "mov r3, #8 \n" /* loop count */ - "mov %[mask], #0 \n" - - ".ur_pre_loop: \n" - "ldrb r0, [%[cbuf]], #1 \n" /* read current buffer */ - "ldrb r1, [%[bbuf]] \n" /* read back buffer */ - "strb r0, [%[bbuf]], #1 \n" /* update back buffer */ - "mov r2, #0 \n" /* preset for skipped pixel */ - "cmp r0, r1 \n" /* no change? */ - "beq .ur_skip \n" /* -> skip */ - - "ldr r2, [%[bpat], r0, lsl #2] \n" /* r2 = bitpattern[byte]; */ - - "add %[rnd], %[rnd], %[rnd], lsl #2 \n" /* multiply by 75 */ - "rsb %[rnd], %[rnd], %[rnd], lsl #4 \n" - "add %[rnd], %[rnd], #74 \n" /* add another 74 */ - /* Since the lower bits are not very random: get bits 8..15 (need max. 5) */ - "and r1, %[rmsk], %[rnd], lsr #8 \n" /* ..and mask out unneeded bits */ - - "cmp r1, %[dpth] \n" /* random >= depth ? */ - "subhs r1, r1, %[dpth] \n" /* yes: random -= depth */ - - "mov r0, r2, lsl r1 \n" /** rotate pattern **/ - "sub r1, %[dpth], r1 \n" - "orr r2, r0, r2, lsr r1 \n" - - "orr %[mask], %[mask], #0x100 \n" /* set mask bit */ - - ".ur_skip: \n" - "mov %[mask], %[mask], lsr #1 \n" /* shift mask */ - "str r2, [%[patp]], #4 \n" /* push on pattern stack */ - - "subs r3, r3, #1 \n" /* loop 8 times (pixel block) */ - "bne .ur_pre_loop \n" - : /* outputs */ - [cbuf]"+r"(cbuf), - [bbuf]"+r"(bbuf), - [patp]"+r"(pat_ptr), - [rnd] "+r"(_gray_random_buffer), - [mask]"=&r"(mask) - : /* inputs */ - [bpat]"r"(_gray_info.bitpattern), - [dpth]"r"(_gray_info.depth), - [rmsk]"r"(_gray_info.randmask) - : /* clobbers */ - "r0", "r1", "r2", "r3" - ); - - addr = dst_row; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "ldmdb %[patp], {r1 - r8} \n" /* pop all 8 patterns */ - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "mov %[rx], #0xF0 \n" /** Stage 1: 4 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11110000 */ - "eor r0, r1, r5, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */ - "eor r5, r5, r0, lsr #4 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */ - "eor r0, r2, r6, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */ - "eor r6, r6, r0, lsr #4 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */ - "eor r0, r3, r7, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */ - "eor r7, r7, r0, lsr #4 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */ - "eor r0, r4, r8, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r4, r4, r0 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */ - "eor r8, r8, r0, lsr #4 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */ - - "mov %[rx], #0xCC \n" /** Stage 2: 2 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11001100 */ - "eor r0, r1, r3, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */ - "eor r3, r3, r0, lsr #2 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */ - "eor r0, r2, r4, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "eor r4, r4, r0, lsr #2 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */ - "eor r0, r5, r7, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */ - "eor r7, r7, r0, lsr #2 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */ - "eor r0, r6, r8, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r6, r6, r0 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */ - "eor r8, r8, r0, lsr #2 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */ - - "mov %[rx], #0xAA \n" /** Stage 3: 1 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...10101010 */ - "eor r0, r1, r2, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */ - "eor r2, r2, r0, lsr #1 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */ - "eor r0, r3, r4, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */ - "eor r4, r4, r0, lsr #1 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */ - "eor r0, r5, r6, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */ - "eor r6, r6, r0, lsr #1 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */ - "eor r0, r7, r8, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r7, r7, r0 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */ - "eor r8, r8, r0, lsr #1 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */ - - "sub r0, %[dpth], #1 \n" /** shift out unused low bytes **/ - "and r0, r0, #7 \n" - "add pc, pc, r0, lsl #2 \n" /* jump into shift streak */ - "mov r8, r8, lsr #8 \n" /* r8: never reached */ - "mov r7, r7, lsr #8 \n" - "mov r6, r6, lsr #8 \n" - "mov r5, r5, lsr #8 \n" - "mov r4, r4, lsr #8 \n" - "mov r3, r3, lsr #8 \n" - "mov r2, r2, lsr #8 \n" - "mov r1, r1, lsr #8 \n" - - "mvn %[mask], %[mask] \n" /* "set" mask -> "keep" mask */ - "ands %[mask], %[mask], #0xff \n" - "beq .ur_sstart \n" /* short loop if no bits to keep */ - - "ldrb r0, [pc, r0] \n" /* jump into full loop */ - "add pc, pc, r0 \n" - ".ur_ftable: \n" - ".byte .ur_f1 - .ur_ftable - 4 \n" /* [jump tables are tricky] */ - ".byte .ur_f2 - .ur_ftable - 4 \n" - ".byte .ur_f3 - .ur_ftable - 4 \n" - ".byte .ur_f4 - .ur_ftable - 4 \n" - ".byte .ur_f5 - .ur_ftable - 4 \n" - ".byte .ur_f6 - .ur_ftable - 4 \n" - ".byte .ur_f7 - .ur_ftable - 4 \n" - ".byte .ur_f8 - .ur_ftable - 4 \n" - - ".ur_floop: \n" /** full loop (bits to keep)**/ - ".ur_f8: \n" - "ldrb r0, [%[addr]] \n" /* load old byte */ - "and r0, r0, %[mask] \n" /* mask out replaced bits */ - "orr r0, r0, r1 \n" /* set new bits */ - "strb r0, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".ur_f7: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r2 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".ur_f6: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r3 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".ur_f5: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r4 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".ur_f4: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r5 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".ur_f3: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r6 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".ur_f2: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r7 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".ur_f1: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r8 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .ur_floop \n" - - "b .ur_end \n" - - ".ur_sstart: \n" - "ldrb r0, [pc, r0] \n" /* jump into short loop*/ - "add pc, pc, r0 \n" - ".ur_stable: \n" - ".byte .ur_s1 - .ur_stable - 4 \n" - ".byte .ur_s2 - .ur_stable - 4 \n" - ".byte .ur_s3 - .ur_stable - 4 \n" - ".byte .ur_s4 - .ur_stable - 4 \n" - ".byte .ur_s5 - .ur_stable - 4 \n" - ".byte .ur_s6 - .ur_stable - 4 \n" - ".byte .ur_s7 - .ur_stable - 4 \n" - ".byte .ur_s8 - .ur_stable - 4 \n" - - ".ur_sloop: \n" /** short loop (nothing to keep) **/ - ".ur_s8: \n" - "strb r1, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".ur_s7: \n" - "strb r2, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".ur_s6: \n" - "strb r3, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".ur_s5: \n" - "strb r4, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".ur_s4: \n" - "strb r5, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".ur_s3: \n" - "strb r6, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".ur_s2: \n" - "strb r7, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".ur_s1: \n" - "strb r8, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .ur_sloop \n" - - ".ur_end: \n" - : /* outputs */ - [addr]"+r"(addr), - [mask]"+r"(mask), - [dpth]"+r"(depth), - [rx] "=&r"(trash) - : /* inputs */ - [psiz]"r"(_gray_info.plane_size), - [patp]"[rx]"(pat_ptr) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" - ); - } -#else /* C version, for reference*/ -#warning C version of gray_update_rect() used - (void)pat_ptr; - /* check whether anything changed in the 8-pixel block */ - change = *(uint32_t *)cbuf ^ *(uint32_t *)bbuf; - change |= *(uint32_t *)(cbuf + 4) ^ *(uint32_t *)(bbuf + 4); - - if (change != 0) - { - unsigned char *addr, *end; - unsigned mask = 0; - unsigned test = 1 << ((-_gray_info.depth) & 7); - int i; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - for (i = 0; i < 8; i++) - { - unsigned pat = 0; - unsigned char cur = *cbuf++; - unsigned char back = *bbuf; - - *bbuf++ = cur; - - if (cur != back) - { - int shift; - - pat = _gray_info.bitpattern[cur]; - - /* shift pattern pseudo-random, simple & fast PRNG */ - _gray_random_buffer = 75 * _gray_random_buffer + 74; - shift = (_gray_random_buffer >> 8) & _gray_info.randmask; - if (shift >= _gray_info.depth) - shift -= _gray_info.depth; - - pat = (pat << shift) | (pat >> (_gray_info.depth - shift)); - - mask |= 0x100; - } - mask >>= 1; - pat_stack[i] = pat; - } - - addr = dst_row; - end = addr + _GRAY_MULUQ(_gray_info.depth, _gray_info.plane_size); - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - mask = (~mask & 0xff); - if (mask == 0) - { - do - { - unsigned data = 0; - - for (i = 7; i >= 0; i--) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } - else - { - do - { - unsigned data = 0; - - for (i = 7; i >= 0; i--) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = (*addr & mask) | data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } - - } -#endif /* CONFIG_CPU */ - srcofs_row += _gray_info.height; - dst_row++; - } - while (dst_row < dst_end); - - srcofs += 8; - dst += _gray_info.width; - } -} -#endif /* LCD_PIXELFORMAT */ - -#endif /* !SIMULATOR */ - -/* Update the whole greyscale overlay */ -void gray_update(void) -{ - gray_update_rect(0, 0, _gray_info.width, _gray_info.height); -} - -/* Do an lcd_update() to show changes done by rb->lcd_xxx() functions - (in areas of the screen not covered by the greyscale overlay). */ -void gray_deferred_lcd_update(void) -{ - if (_gray_info.flags & _GRAY_RUNNING) - { -#ifdef SIMULATOR - _deferred_update(); -#else - _gray_info.flags |= _GRAY_DEFERRED_UPDATE; -#endif - } - else - _gray_rb->lcd_update(); -} - -/*** Screenshot ***/ - -#define BMP_FIXEDCOLORS (1 << LCD_DEPTH) -#define BMP_VARCOLORS 33 -#define BMP_NUMCOLORS (BMP_FIXEDCOLORS + BMP_VARCOLORS) -#define BMP_BPP 8 -#define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3) -#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS) -#define BMP_DATASIZE (BMP_LINESIZE * LCD_HEIGHT) -#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE) - -#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff -#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff - -static const unsigned char bmpheader[] = -{ - 0x42, 0x4d, /* 'BM' */ - LE32_CONST(BMP_TOTALSIZE), /* Total file size */ - 0x00, 0x00, 0x00, 0x00, /* Reserved */ - LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */ - - 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */ - LE32_CONST(LCD_WIDTH), /* Width in pixels */ - LE32_CONST(LCD_HEIGHT), /* Height in pixels */ - 0x01, 0x00, /* Number of planes (always 1) */ - LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */ - 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */ - LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */ - 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */ - 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */ - LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */ - LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */ - - /* Fixed colours */ -#if LCD_DEPTH == 1 - 0x90, 0xee, 0x90, 0x00, /* Colour #0 */ - 0x00, 0x00, 0x00, 0x00 /* Colour #1 */ -#elif LCD_DEPTH == 2 - 0xe6, 0xd8, 0xad, 0x00, /* Colour #0 */ - 0x99, 0x90, 0x73, 0x00, /* Colour #1 */ - 0x4c, 0x48, 0x39, 0x00, /* Colour #2 */ - 0x00, 0x00, 0x00, 0x00 /* Colour #3 */ -#endif -}; - -#if LCD_DEPTH == 1 -#define BMP_RED 0x90 -#define BMP_GREEN 0xee -#define BMP_BLUE 0x90 -#elif LCD_DEPTH == 2 -#define BMP_RED 0xad -#define BMP_GREEN 0xd8 -#define BMP_BLUE 0xe6 -#endif - -/* Hook function for core screen_dump() to save the current display - content (b&w and greyscale overlay) to an 8-bit BMP file. */ -static void gray_screendump_hook(int fd) -{ - int i; - int x, y; - int gx, gy; -#if (LCD_DEPTH == 1) || !defined(SIMULATOR) - int mask; -#endif -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - unsigned data; -#else - int by; -#if LCD_DEPTH == 2 - int shift; -#endif -#endif - unsigned char *clut_entry; - unsigned char *lcdptr; - unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)]; - - _gray_rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */ - - /* build clut */ - _gray_rb->memset(linebuf, 0, 4*BMP_VARCOLORS); - clut_entry = linebuf; - - for (i = _gray_info.depth; i > 0; i--) - { - *clut_entry++ = _GRAY_MULUQ(BMP_BLUE, i) / _gray_info.depth; - *clut_entry++ = _GRAY_MULUQ(BMP_GREEN, i) / _gray_info.depth; - *clut_entry++ = _GRAY_MULUQ(BMP_RED, i) / _gray_info.depth; - clut_entry++; - } - _gray_rb->write(fd, linebuf, 4*BMP_VARCOLORS); - - /* BMP image goes bottom -> top */ - for (y = LCD_HEIGHT - 1; y >= 0; y--) - { - _gray_rb->memset(linebuf, 0, BMP_LINESIZE); - - gy = y - _gray_info.y; -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING -#if LCD_DEPTH == 2 - lcdptr = _gray_rb->lcd_framebuffer + _GRAY_MULUQ(LCD_FBWIDTH, y); - - if ((unsigned) gy < (unsigned) _gray_info.height) - { - /* line contains greyscale (and maybe b&w) graphics */ -#ifndef SIMULATOR - unsigned char *grayptr = _gray_info.plane_data - + _GRAY_MULUQ(_gray_info.bwidth, gy); -#endif - - for (x = 0; x < LCD_WIDTH; x += 4) - { - gx = x - _gray_info.x; - - if ((unsigned)gx < (unsigned)_gray_info.width) - { -#ifdef SIMULATOR - data = _GRAY_MULUQ(gy, _gray_info.width) + gx; - - for (i = 0; i < 4; i++) - linebuf[x + i] = BMP_FIXEDCOLORS + _gray_info.depth - - _gray_info.cur_buffer[data + i]; -#else - mask = 0x80 >> (gx & 7); - - for (i = 0; i < 4; i++) - { - int j; - int idx = BMP_FIXEDCOLORS; - unsigned char *grayptr2 = grayptr + (gx >> 3); - - for (j = _gray_info.depth; j > 0; j--) - { - if (*grayptr2 & mask) - idx++; - grayptr2 += _gray_info.plane_size; - } - linebuf[x + i] = idx; - mask >>= 1; - } -#endif - } - else - { - data = *lcdptr; - linebuf[x] = (data >> 6) & 3; - linebuf[x + 1] = (data >> 4) & 3; - linebuf[x + 2] = (data >> 2) & 3; - linebuf[x + 3] = data & 3; - } - lcdptr++; - } - } - else - { - /* line contains only b&w graphics */ - for (x = 0; x < LCD_WIDTH; x += 4) - { - data = *lcdptr++; - linebuf[x] = (data >> 6) & 3; - linebuf[x + 1] = (data >> 4) & 3; - linebuf[x + 2] = (data >> 2) & 3; - linebuf[x + 3] = data & 3; - } - } -#endif /* LCD_DEPTH */ -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ -#if LCD_DEPTH == 1 - mask = 1 << (y & 7); - by = y >> 3; - lcdptr = _gray_rb->lcd_framebuffer + _GRAY_MULUQ(LCD_WIDTH, by); - - if ((unsigned) gy < (unsigned) _gray_info.height) - { - /* line contains greyscale (and maybe b&w) graphics */ -#ifndef SIMULATOR - unsigned char *grayptr = _gray_info.plane_data - + _GRAY_MULUQ(_gray_info.width, gy >> 3); -#endif - - for (x = 0; x < LCD_WIDTH; x++) - { - gx = x - _gray_info.x; - - if ((unsigned)gx < (unsigned)_gray_info.width) - { -#ifdef SIMULATOR - linebuf[x] = BMP_FIXEDCOLORS + _gray_info.depth - - _gray_info.cur_buffer[_GRAY_MULUQ(gx, _gray_info.height) + gy]; -#else - int idx = BMP_FIXEDCOLORS; - unsigned char *grayptr2 = grayptr + gx; - - for (i = _gray_info.depth; i > 0; i--) - { - if (*grayptr2 & mask) - idx++; - grayptr2 += _gray_info.plane_size; - } - linebuf[x] = idx; -#endif - } - else - { - linebuf[x] = (*lcdptr & mask) ? 1 : 0; - } - lcdptr++; - } - } - else - { - /* line contains only b&w graphics */ - for (x = 0; x < LCD_WIDTH; x++) - linebuf[x] = (*lcdptr++ & mask) ? 1 : 0; - } -#elif LCD_DEPTH == 2 - shift = 2 * (y & 3); - by = y >> 2; - lcdptr = _gray_rb->lcd_framebuffer + _GRAY_MULUQ(LCD_WIDTH, by); - - if ((unsigned)gy < (unsigned)_gray_info.height) - { - /* line contains greyscale (and maybe b&w) graphics */ -#ifndef SIMULATOR - unsigned char *grayptr = _gray_info.plane_data - + _GRAY_MULUQ(_gray_info.width, gy >> 3); - mask = 1 << (gy & 7); -#endif - - for (x = 0; x < LCD_WIDTH; x++) - { - gx = x - _gray_info.x; - - if ((unsigned)gx < (unsigned)_gray_info.width) - { -#ifdef SIMULATOR - linebuf[x] = BMP_FIXEDCOLORS + _gray_info.depth - - _gray_info.cur_buffer[_GRAY_MULUQ(gx, _gray_info.height) + gy]; -#else - int idx = BMP_FIXEDCOLORS; - unsigned char *grayptr2 = grayptr + gx; - - for (i = _gray_info.depth; i > 0; i--) - { - if (*grayptr2 & mask) - idx++; - grayptr2 += _gray_info.plane_size; - } - linebuf[x] = idx; -#endif - } - else - { - linebuf[x] = (*lcdptr >> shift) & 3; - } - lcdptr++; - } - } - else - { - /* line contains only b&w graphics */ - for (x = 0; x < LCD_WIDTH; x++) - linebuf[x] = (*lcdptr++ >> shift) & 3; - } -#endif /* LCD_DEPTH */ -#endif /* LCD_PIXELFORMAT */ - - _gray_rb->write(fd, linebuf, BMP_LINESIZE); - } -} - -#endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/lib/gray_draw.c b/apps/plugins/lib/gray_draw.c deleted file mode 100644 index 4d75af5c9b..0000000000 --- a/apps/plugins/lib/gray_draw.c +++ /dev/null @@ -1,2418 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Greyscale framework -* Drawing functions -* -* This is a generic framework to display up to 33 shades of grey -* on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey, iPod 4-grey) -* within plugins. -* -* Copyright (C) 2004-2006 Jens Arnold -* -* All files in this archive are subject to the GNU General Public License. -* See the file COPYING in the source tree root for full license agreement. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "plugin.h" - -#ifdef HAVE_LCD_BITMAP -#include "gray.h" - -/*** low-level drawing functions ***/ - -static void setpixel(unsigned char *address) -{ - *address = _gray_info.fg_index; -} - -static void clearpixel(unsigned char *address) -{ - *address = _gray_info.bg_index; -} - -static void flippixel(unsigned char *address) -{ - *address = _gray_info.depth - *address; -} - -static void nopixel(unsigned char *address) -{ - (void)address; -} - -void (* const _gray_pixelfuncs[8])(unsigned char *address) = { - flippixel, nopixel, setpixel, setpixel, - nopixel, clearpixel, nopixel, clearpixel -}; - -/*** Drawing functions ***/ - -/* Clear the whole display */ -void gray_clear_display(void) -{ - int brightness = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - _gray_rb->memset(_gray_info.cur_buffer, brightness, - _GRAY_MULUQ(_gray_info.width, _gray_info.height)); -} - -/* Set a single pixel */ -void gray_drawpixel(int x, int y) -{ - if (((unsigned)x < (unsigned)_gray_info.width) - && ((unsigned)y < (unsigned)_gray_info.height)) -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - _gray_pixelfuncs[_gray_info.drawmode](&_gray_info.cur_buffer[_GRAY_MULUQ(y, - _gray_info.width) + x]); -#else - _gray_pixelfuncs[_gray_info.drawmode](&_gray_info.cur_buffer[_GRAY_MULUQ(x, - _gray_info.height) + y]); -#endif -} - -/* Draw a line */ -void gray_drawline(int x1, int y1, int x2, int y2) -{ - int numpixels; - int i; - int deltax, deltay; - int d, dinc1, dinc2; - int x, xinc1, xinc2; - int y, yinc1, yinc2; - void (*pfunc)(unsigned char *address) = _gray_pixelfuncs[_gray_info.drawmode]; - - deltax = abs(x2 - x1); - deltay = abs(y2 - y1); - xinc2 = 1; - yinc2 = 1; - - if (deltax >= deltay) - { - numpixels = deltax; - d = 2 * deltay - deltax; - dinc1 = deltay * 2; - dinc2 = (deltay - deltax) * 2; - xinc1 = 1; - yinc1 = 0; - } - else - { - numpixels = deltay; - d = 2 * deltax - deltay; - dinc1 = deltax * 2; - dinc2 = (deltax - deltay) * 2; - xinc1 = 0; - yinc1 = 1; - } - numpixels++; /* include endpoints */ - - if (x1 > x2) - { - xinc1 = -xinc1; - xinc2 = -xinc2; - } - - if (y1 > y2) - { - yinc1 = -yinc1; - yinc2 = -yinc2; - } - - x = x1; - y = y1; - - for (i = 0; i < numpixels; i++) - { - if (((unsigned)x < (unsigned)_gray_info.width) - && ((unsigned)y < (unsigned)_gray_info.height)) -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - pfunc(&_gray_info.cur_buffer[_GRAY_MULUQ(y, _gray_info.width) + x]); -#else - pfunc(&_gray_info.cur_buffer[_GRAY_MULUQ(x, _gray_info.height) + y]); -#endif - - if (d < 0) - { - d += dinc1; - x += xinc1; - y += yinc1; - } - else - { - d += dinc2; - x += xinc2; - y += yinc2; - } - } -} - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - -/* Draw a horizontal line (optimised) */ -void gray_hline(int x1, int x2, int y) -{ - int x; - int bits = 0; - unsigned char *dst; - bool fillopt = false; - void (*pfunc)(unsigned char *address); - - /* direction flip */ - if (x2 < x1) - { - x = x1; - x1 = x2; - x2 = x; - } - - /* nothing to draw? */ - if (((unsigned)y >= (unsigned)_gray_info.height) - || (x1 >= _gray_info.width) || (x2 < 0)) - return; - - /* clipping */ - if (x1 < 0) - x1 = 0; - if (x2 >= _gray_info.width) - x2 = _gray_info.width - 1; - - if (_gray_info.drawmode & DRMODE_INVERSEVID) - { - if (_gray_info.drawmode & DRMODE_BG) - { - fillopt = true; - bits = _gray_info.bg_index; - } - } - else - { - if (_gray_info.drawmode & DRMODE_FG) - { - fillopt = true; - bits = _gray_info.fg_index; - } - } - pfunc = _gray_pixelfuncs[_gray_info.drawmode]; - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(y, _gray_info.width) + x1]; - - if (fillopt) - _gray_rb->memset(dst, bits, x2 - x1 + 1); - else - { - unsigned char *dst_end = dst + x2 - x1; - do - pfunc(dst++); - while (dst <= dst_end); - } -} - -/* Draw a vertical line (optimised) */ -void gray_vline(int x, int y1, int y2) -{ - int y; - unsigned char *dst, *dst_end; - void (*pfunc)(unsigned char *address); - - /* direction flip */ - if (y2 < y1) - { - y = y1; - y1 = y2; - y2 = y; - } - - /* nothing to draw? */ - if (((unsigned)x >= (unsigned)_gray_info.width) - || (y1 >= _gray_info.height) || (y2 < 0)) - return; - - /* clipping */ - if (y1 < 0) - y1 = 0; - if (y2 >= _gray_info.height) - y2 = _gray_info.height - 1; - - pfunc = _gray_pixelfuncs[_gray_info.drawmode]; - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(y1, _gray_info.width) + x]; - - dst_end = dst + _GRAY_MULUQ(y2 - y1, _gray_info.width); - do - { - pfunc(dst); - dst += _gray_info.width; - } - while (dst <= dst_end); -} - -/* Draw a filled triangle */ -void gray_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) -{ - int x, y; - long fp_x1, fp_x2, fp_dx1, fp_dx2; - - /* sort vertices by increasing y value */ - if (y1 > y3) - { - if (y2 < y3) /* y2 < y3 < y1 */ - { - x = x1; x1 = x2; x2 = x3; x3 = x; - y = y1; y1 = y2; y2 = y3; y3 = y; - } - else if (y2 > y1) /* y3 < y1 < y2 */ - { - x = x1; x1 = x3; x3 = x2; x2 = x; - y = y1; y1 = y3; y3 = y2; y2 = y; - } - else /* y3 <= y2 <= y1 */ - { - x = x1; x1 = x3; x3 = x; - y = y1; y1 = y3; y3 = y; - } - } - else - { - if (y2 < y1) /* y2 < y1 <= y3 */ - { - x = x1; x1 = x2; x2 = x; - y = y1; y1 = y2; y2 = y; - } - else if (y2 > y3) /* y1 <= y3 < y2 */ - { - x = x2; x2 = x3; x3 = x; - y = y2; y2 = y3; y3 = y; - } - /* else already sorted */ - } - - if (y1 < y3) /* draw */ - { - fp_dx1 = ((x3 - x1) << 16) / (y3 - y1); - fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1); - - if (y1 < y2) /* first part */ - { - fp_dx2 = ((x2 - x1) << 16) / (y2 - y1); - fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1); - for (y = y1; y < y2; y++) - { - gray_hline(fp_x1 >> 16, fp_x2 >> 16, y); - fp_x1 += fp_dx1; - fp_x2 += fp_dx2; - } - } - if (y2 < y3) /* second part */ - { - fp_dx2 = ((x3 - x2) << 16) / (y3 - y2); - fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1); - for (y = y2; y < y3; y++) - { - gray_hline(fp_x1 >> 16, fp_x2 >> 16, y); - fp_x1 += fp_dx1; - fp_x2 += fp_dx2; - } - } - } -} -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - -/* Draw a horizontal line (optimised) */ -void gray_hline(int x1, int x2, int y) -{ - int x; - unsigned char *dst, *dst_end; - void (*pfunc)(unsigned char *address); - - /* direction flip */ - if (x2 < x1) - { - x = x1; - x1 = x2; - x2 = x; - } - - /* nothing to draw? */ - if (((unsigned)y >= (unsigned)_gray_info.height) - || (x1 >= _gray_info.width) || (x2 < 0)) - return; - - /* clipping */ - if (x1 < 0) - x1 = 0; - if (x2 >= _gray_info.width) - x2 = _gray_info.width - 1; - - pfunc = _gray_pixelfuncs[_gray_info.drawmode]; - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(x1, _gray_info.height) + y]; - - dst_end = dst + _GRAY_MULUQ(x2 - x1, _gray_info.height); - do - { - pfunc(dst); - dst += _gray_info.height; - } - while (dst <= dst_end); -} - -/* Draw a vertical line (optimised) */ -void gray_vline(int x, int y1, int y2) -{ - int y; - int bits = 0; - unsigned char *dst; - bool fillopt = false; - void (*pfunc)(unsigned char *address); - - /* direction flip */ - if (y2 < y1) - { - y = y1; - y1 = y2; - y2 = y; - } - - /* nothing to draw? */ - if (((unsigned)x >= (unsigned)_gray_info.width) - || (y1 >= _gray_info.height) || (y2 < 0)) - return; - - /* clipping */ - if (y1 < 0) - y1 = 0; - if (y2 >= _gray_info.height) - y2 = _gray_info.height - 1; - - if (_gray_info.drawmode & DRMODE_INVERSEVID) - { - if (_gray_info.drawmode & DRMODE_BG) - { - fillopt = true; - bits = _gray_info.bg_index; - } - } - else - { - if (_gray_info.drawmode & DRMODE_FG) - { - fillopt = true; - bits = _gray_info.fg_index; - } - } - pfunc = _gray_pixelfuncs[_gray_info.drawmode]; - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(x, _gray_info.height) + y1]; - - if (fillopt) - _gray_rb->memset(dst, bits, y2 - y1 + 1); - else - { - unsigned char *dst_end = dst + y2 - y1; - do - pfunc(dst++); - while (dst <= dst_end); - } -} - -/* Draw a filled triangle */ -void gray_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) -{ - int x, y; - long fp_y1, fp_y2, fp_dy1, fp_dy2; - - /* sort vertices by increasing x value */ - if (x1 > x3) - { - if (x2 < x3) /* x2 < x3 < x1 */ - { - x = x1; x1 = x2; x2 = x3; x3 = x; - y = y1; y1 = y2; y2 = y3; y3 = y; - } - else if (x2 > x1) /* x3 < x1 < x2 */ - { - x = x1; x1 = x3; x3 = x2; x2 = x; - y = y1; y1 = y3; y3 = y2; y2 = y; - } - else /* x3 <= x2 <= x1 */ - { - x = x1; x1 = x3; x3 = x; - y = y1; y1 = y3; y3 = y; - } - } - else - { - if (x2 < x1) /* x2 < x1 <= x3 */ - { - x = x1; x1 = x2; x2 = x; - y = y1; y1 = y2; y2 = y; - } - else if (x2 > x3) /* x1 <= x3 < x2 */ - { - x = x2; x2 = x3; x3 = x; - y = y2; y2 = y3; y3 = y; - } - /* else already sorted */ - } - - if (x1 < x3) /* draw */ - { - fp_dy1 = ((y3 - y1) << 16) / (x3 - x1); - fp_y1 = (y1 << 16) + (1<<15) + (fp_dy1 >> 1); - - if (x1 < x2) /* first part */ - { - fp_dy2 = ((y2 - y1) << 16) / (x2 - x1); - fp_y2 = (y1 << 16) + (1<<15) + (fp_dy2 >> 1); - for (x = x1; x < x2; x++) - { - gray_vline(x, fp_y1 >> 16, fp_y2 >> 16); - fp_y1 += fp_dy1; - fp_y2 += fp_dy2; - } - } - if (x2 < x3) /* second part */ - { - fp_dy2 = ((y3 - y2) << 16) / (x3 - x2); - fp_y2 = (y2 << 16) + (1<<15) + (fp_dy2 >> 1); - for (x = x2; x < x3; x++) - { - gray_vline(x, fp_y1 >> 16, fp_y2 >> 16); - fp_y1 += fp_dy1; - fp_y2 += fp_dy2; - } - } - } -} -#endif /* LCD_PIXELFORMAT */ - -/* Draw a rectangular box */ -void gray_drawrect(int x, int y, int width, int height) -{ - if ((width <= 0) || (height <= 0)) - return; - - int x2 = x + width - 1; - int y2 = y + height - 1; - - gray_vline(x, y, y2); - gray_vline(x2, y, y2); - gray_hline(x, x2, y); - gray_hline(x, x2, y2); -} - -/* Fill a rectangular area */ -void gray_fillrect(int x, int y, int width, int height) -{ - int bits = 0; - unsigned char *dst, *dst_end; - bool fillopt = false; - void (*pfunc)(unsigned char *address); - - /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= _gray_info.width) - || (y >= _gray_info.height) || (x + width <= 0) || (y + height <= 0)) - return; - - /* clipping */ - if (x < 0) - { - width += x; - x = 0; - } - if (y < 0) - { - height += y; - y = 0; - } - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (y + height > _gray_info.height) - height = _gray_info.height - y; - - if (_gray_info.drawmode & DRMODE_INVERSEVID) - { - if (_gray_info.drawmode & DRMODE_BG) - { - fillopt = true; - bits = _gray_info.bg_index; - } - } - else - { - if (_gray_info.drawmode & DRMODE_FG) - { - fillopt = true; - bits = _gray_info.fg_index; - } - } - pfunc = _gray_pixelfuncs[_gray_info.drawmode]; -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(y, _gray_info.width) + x]; - dst_end = dst + _GRAY_MULUQ(height, _gray_info.width); - - do - { - if (fillopt) - _gray_rb->memset(dst, bits, width); - else - { - unsigned char *dst_row = dst; - unsigned char *row_end = dst_row + width; - - do - pfunc(dst_row++); - while (dst_row < row_end); - } - dst += _gray_info.width; - } - while (dst < dst_end); -#else - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(x, _gray_info.height) + y]; - dst_end = dst + _GRAY_MULUQ(width, _gray_info.height); - - do - { - if (fillopt) - _gray_rb->memset(dst, bits, height); - else - { - unsigned char *dst_col = dst; - unsigned char *col_end = dst_col + height; - - do - pfunc(dst_col++); - while (dst_col < col_end); - } - dst += _gray_info.height; - } - while (dst < dst_end); -#endif -} - -/* About Rockbox' internal monochrome bitmap format: - * - * A bitmap contains one bit for every pixel that defines if that pixel is - * foreground (1) or background (0). Bits within a byte are arranged - * vertically, LSB at top. - * The bytes are stored in row-major order, with byte 0 being top left, - * byte 1 2nd from left etc. The first row of bytes defines pixel rows - * 0..7, the second row defines pixel row 8..15 etc. */ - -/* Draw a partial monochrome bitmap */ -void gray_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height) -{ - const unsigned char *src_end; - unsigned char *dst, *dst_end; - void (*fgfunc)(unsigned char *address); - void (*bgfunc)(unsigned char *address); - - /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= _gray_info.width) - || (y >= _gray_info.height) || (x + width <= 0) || (y + height <= 0)) - return; - - /* clipping */ - if (x < 0) - { - width += x; - src_x -= x; - x = 0; - } - if (y < 0) - { - height += y; - src_y -= y; - y = 0; - } - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (y + height > _gray_info.height) - height = _gray_info.height - y; - - src += _GRAY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */ - src_y &= 7; - src_end = src + width; - - fgfunc = _gray_pixelfuncs[_gray_info.drawmode]; - bgfunc = _gray_pixelfuncs[_gray_info.drawmode ^ DRMODE_INVERSEVID]; -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(y, _gray_info.width) + x]; - - do - { - const unsigned char *src_col = src++; - unsigned char *dst_col = dst++; - unsigned data = *src_col >> src_y; - int numbits = 8 - src_y; - - dst_end = dst_col + _GRAY_MULUQ(height, _gray_info.width); - do - { - if (data & 0x01) - fgfunc(dst_col); - else - bgfunc(dst_col); - - dst_col += _gray_info.width; - - data >>= 1; - if (--numbits == 0) - { - src_col += stride; - data = *src_col; - numbits = 8; - } - } - while (dst_col < dst_end); - } - while (src < src_end); -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(x, _gray_info.height) + y]; - - do - { - const unsigned char *src_col = src++; - unsigned char *dst_col = dst; - unsigned data = *src_col >> src_y; - int numbits = 8 - src_y; - - dst_end = dst_col + height; - do - { - if (data & 0x01) - fgfunc(dst_col++); - else - bgfunc(dst_col++); - - data >>= 1; - if (--numbits == 0) - { - src_col += stride; - data = *src_col; - numbits = 8; - } - } - while (dst_col < dst_end); - - dst += _gray_info.height; - } - while (src < src_end); -#endif /* LCD_PIXELFORMAT */ -} - -/* Draw a full monochrome bitmap */ -void gray_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) -{ - gray_mono_bitmap_part(src, 0, 0, width, x, y, width, height); -} - -/* Draw a partial greyscale bitmap, canonical format */ -void gray_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height) -{ - unsigned char *dst, *dst_end; - - /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= _gray_info.width) - || (y >= _gray_info.height) || (x + width <= 0) || (y + height <= 0)) - return; - - /* clipping */ - if (x < 0) - { - width += x; - src_x -= x; - x = 0; - } - if (y < 0) - { - height += y; - src_y -= y; - y = 0; - } - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (y + height > _gray_info.height) - height = _gray_info.height - y; - - src += _GRAY_MULUQ(stride, src_y) + src_x; /* move starting point */ -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(y, _gray_info.width) + x]; - dst_end = dst + _GRAY_MULUQ(height, _gray_info.width); - - do - { - const unsigned char *src_row = src; - unsigned char *dst_row = dst; - unsigned char *row_end = dst_row + width; - - do - *dst_row++ = _gray_info.idxtable[*src_row++]; - while (dst_row < row_end); - - src += stride; - dst += _gray_info.width; - } - while (dst < dst_end); -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - dst = &_gray_info.cur_buffer[_GRAY_MULUQ(x, _gray_info.height) + y]; - dst_end = dst + height; - - do - { - const unsigned char *src_row = src; - unsigned char *dst_row = dst++; - unsigned char *row_end = dst_row + _GRAY_MULUQ(width, _gray_info.height); - - do - { - *dst_row = _gray_info.idxtable[*src_row++]; - dst_row += _gray_info.height; - } - while (dst_row < row_end); - - src += stride; - } - while (dst < dst_end); -#endif /* LCD_PIXELFORMAT */ -} - -/* Draw a full greyscale bitmap, canonical format */ -void gray_gray_bitmap(const unsigned char *src, int x, int y, int width, - int height) -{ - gray_gray_bitmap_part(src, 0, 0, width, x, y, width, height); -} - -/* Put a string at a given pixel position, skipping first ofs pixel columns */ -void gray_putsxyofs(int x, int y, int ofs, const unsigned char *str) -{ - int ch; - struct font* pf = _gray_rb->font_get(_gray_info.curfont); - - while ((ch = *str++) != '\0' && x < _gray_info.width) - { - int width; - const unsigned char *bits; - - /* check input range */ - if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) - ch = pf->defaultchar; - ch -= pf->firstchar; - - /* get proportional width and glyph bits */ - width = pf->width ? pf->width[ch] : pf->maxwidth; - - if (ofs > width) - { - ofs -= width; - continue; - } - - bits = pf->bits + (pf->offset ? - pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch)); - - gray_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); - - x += width - ofs; - ofs = 0; - } -} - -/* Put a string at a given pixel position */ -void gray_putsxy(int x, int y, const unsigned char *str) -{ - gray_putsxyofs(x, y, 0, str); -} - -/*** Unbuffered drawing functions ***/ - -#ifdef SIMULATOR - -/* Clear the greyscale display (sets all pixels to white) */ -void gray_ub_clear_display(void) -{ - _gray_rb->memset(_gray_info.cur_buffer, _gray_info.depth, - _GRAY_MULUQ(_gray_info.width, _gray_info.height)); - gray_update(); -} - -/* Draw a partial greyscale bitmap, canonical format */ -void gray_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height) -{ - gray_gray_bitmap_part(src, src_x, src_y, stride, x, y, width, height); - gray_update_rect(x, y, width, height); -} - -#else /* !SIMULATOR */ - -/* Clear the greyscale display (sets all pixels to white) */ -void gray_ub_clear_display(void) -{ - _gray_rb->memset(_gray_info.plane_data, 0, _GRAY_MULUQ(_gray_info.depth, - _gray_info.plane_size)); -} - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - -/* Write a pixel block, defined by their brightnesses in a greymap. - Address is the byte in the first bitplane, src is the greymap start address, - mask determines which pixels of the destination block are changed. */ -static void _writearray(unsigned char *address, const unsigned char *src, - unsigned mask) -{ - unsigned long pat_stack[8]; - unsigned long *pat_ptr = &pat_stack[8]; - unsigned char *addr; -#ifdef CPU_ARM - const unsigned char *_src; - unsigned _mask, depth, trash; - - _mask = mask; - _src = src; - - /* precalculate the bit patterns with random shifts - for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "mov %[mask], %[mask], lsl #24 \n" /* shift mask to upper byte */ - "mov r3, #8 \n" /* loop count */ - - ".wa_loop: \n" /** load pattern for pixel **/ - "mov r2, #0 \n" /* pattern for skipped pixel must be 0 */ - "movs %[mask], %[mask], lsl #1 \n" /* shift out msb of mask */ - "bcc .wa_skip \n" /* skip this pixel */ - - "ldrb r0, [%[src]] \n" /* load src byte */ - "ldrb r0, [%[trns], r0] \n" /* idxtable into pattern index */ - "ldr r2, [%[bpat], r0, lsl #2] \n" /* r2 = bitpattern[byte]; */ - - "add %[rnd], %[rnd], %[rnd], lsl #2 \n" /* multiply by 75 */ - "rsb %[rnd], %[rnd], %[rnd], lsl #4 \n" - "add %[rnd], %[rnd], #74 \n" /* add another 74 */ - /* Since the lower bits are not very random: get bits 8..15 (need max. 5) */ - "and r1, %[rmsk], %[rnd], lsr #8 \n" /* ..and mask out unneeded bits */ - - "cmp r1, %[dpth] \n" /* random >= depth ? */ - "subhs r1, r1, %[dpth] \n" /* yes: random -= depth */ - - "mov r0, r2, lsl r1 \n" /** rotate pattern **/ - "sub r1, %[dpth], r1 \n" - "orr r2, r0, r2, lsr r1 \n" - - ".wa_skip: \n" - "str r2, [%[patp], #-4]! \n" /* push on pattern stack */ - - "add %[src], %[src], #1 \n" /* src++; */ - "subs r3, r3, #1 \n" /* loop 8 times (pixel block) */ - "bne .wa_loop \n" - : /* outputs */ - [src] "+r"(_src), - [patp]"+r"(pat_ptr), - [rnd] "+r"(_gray_random_buffer), - [mask]"+r"(_mask) - : /* inputs */ - [bpat]"r"(_gray_info.bitpattern), - [trns]"r"(_gray_info.idxtable), - [dpth]"r"(_gray_info.depth), - [rmsk]"r"(_gray_info.randmask) - : /* clobbers */ - "r0", "r1", "r2", "r3" - ); - - addr = address; - _mask = mask; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "ldmia %[patp], {r1 - r8} \n" /* pop all 8 patterns */ - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "mov %[rx], #0xF0 \n" /** Stage 1: 4 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11110000 */ - "eor r0, r1, r5, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */ - "eor r5, r5, r0, lsr #4 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */ - "eor r0, r2, r6, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */ - "eor r6, r6, r0, lsr #4 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */ - "eor r0, r3, r7, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */ - "eor r7, r7, r0, lsr #4 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */ - "eor r0, r4, r8, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r4, r4, r0 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */ - "eor r8, r8, r0, lsr #4 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */ - - "mov %[rx], #0xCC \n" /** Stage 2: 2 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11001100 */ - "eor r0, r1, r3, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */ - "eor r3, r3, r0, lsr #2 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */ - "eor r0, r2, r4, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "eor r4, r4, r0, lsr #2 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */ - "eor r0, r5, r7, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */ - "eor r7, r7, r0, lsr #2 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */ - "eor r0, r6, r8, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r6, r6, r0 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */ - "eor r8, r8, r0, lsr #2 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */ - - "mov %[rx], #0xAA \n" /** Stage 3: 1 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...10101010 */ - "eor r0, r1, r2, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */ - "eor r2, r2, r0, lsr #1 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */ - "eor r0, r3, r4, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */ - "eor r4, r4, r0, lsr #1 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */ - "eor r0, r5, r6, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */ - "eor r6, r6, r0, lsr #1 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */ - "eor r0, r7, r8, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r7, r7, r0 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */ - "eor r8, r8, r0, lsr #1 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */ - - "sub r0, %[dpth], #1 \n" /** shift out unused low bytes **/ - "and r0, r0, #7 \n" - "add pc, pc, r0, lsl #2 \n" /* jump into shift streak */ - "mov r8, r8, lsr #8 \n" /* r8: never reached */ - "mov r7, r7, lsr #8 \n" - "mov r6, r6, lsr #8 \n" - "mov r5, r5, lsr #8 \n" - "mov r4, r4, lsr #8 \n" - "mov r3, r3, lsr #8 \n" - "mov r2, r2, lsr #8 \n" - "mov r1, r1, lsr #8 \n" - - "mvn %[mask], %[mask] \n" /* "set" mask -> "keep" mask */ - "ands %[mask], %[mask], #0xff \n" - "beq .wa_sstart \n" /* short loop if no bits to keep */ - - "ldrb r0, [pc, r0] \n" /* jump into full loop */ - "add pc, pc, r0 \n" - ".wa_ftable: \n" - ".byte .wa_f1 - .wa_ftable - 4 \n" /* [jump tables are tricky] */ - ".byte .wa_f2 - .wa_ftable - 4 \n" - ".byte .wa_f3 - .wa_ftable - 4 \n" - ".byte .wa_f4 - .wa_ftable - 4 \n" - ".byte .wa_f5 - .wa_ftable - 4 \n" - ".byte .wa_f6 - .wa_ftable - 4 \n" - ".byte .wa_f7 - .wa_ftable - 4 \n" - ".byte .wa_f8 - .wa_ftable - 4 \n" - - ".wa_floop: \n" /** full loop (bits to keep)**/ - ".wa_f8: \n" - "ldrb r0, [%[addr]] \n" /* load old byte */ - "and r0, r0, %[mask] \n" /* mask out replaced bits */ - "orr r0, r0, r1 \n" /* set new bits */ - "strb r0, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".wa_f7: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r2 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".wa_f6: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r3 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".wa_f5: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r4 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".wa_f4: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r5 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".wa_f3: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r6 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".wa_f2: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r7 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".wa_f1: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r8 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .wa_floop \n" - - "b .wa_end \n" - - ".wa_sstart: \n" - "ldrb r0, [pc, r0] \n" /* jump into short loop*/ - "add pc, pc, r0 \n" - ".wa_stable: \n" - ".byte .wa_s1 - .wa_stable - 4 \n" - ".byte .wa_s2 - .wa_stable - 4 \n" - ".byte .wa_s3 - .wa_stable - 4 \n" - ".byte .wa_s4 - .wa_stable - 4 \n" - ".byte .wa_s5 - .wa_stable - 4 \n" - ".byte .wa_s6 - .wa_stable - 4 \n" - ".byte .wa_s7 - .wa_stable - 4 \n" - ".byte .wa_s8 - .wa_stable - 4 \n" - - ".wa_sloop: \n" /** short loop (nothing to keep) **/ - ".wa_s8: \n" - "strb r1, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".wa_s7: \n" - "strb r2, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".wa_s6: \n" - "strb r3, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".wa_s5: \n" - "strb r4, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".wa_s4: \n" - "strb r5, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".wa_s3: \n" - "strb r6, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".wa_s2: \n" - "strb r7, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".wa_s1: \n" - "strb r8, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .wa_sloop \n" - - ".wa_end: \n" - : /* outputs */ - [addr]"+r"(addr), - [mask]"+r"(_mask), - [dpth]"+r"(depth), - [rx] "=&r"(trash) - : /* inputs */ - [psiz]"r"(_gray_info.plane_size), - [patp]"[rx]"(pat_ptr) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" - ); -#else /* C version, for reference*/ -#warning C version of _writearray() used - unsigned char *end; - unsigned test = 0x80; - int i; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - for (i = 7; i >= 0; i--) - { - unsigned pat = 0; - - if (mask & test) - { - int shift; - - pat = _gray_info.bitpattern[_gray_info.idxtable[*src]]; - - /* shift pattern pseudo-random, simple & fast PRNG */ - _gray_random_buffer = 75 * _gray_random_buffer + 74; - shift = (_gray_random_buffer >> 8) & _gray_info.randmask; - if (shift >= _gray_info.depth) - shift -= _gray_info.depth; - - pat = (pat << shift) | (pat >> (_gray_info.depth - shift)); - } - *(--pat_ptr) = pat; - src++; - test >>= 1; - } - - addr = address; - end = addr + _GRAY_MULUQ(_gray_info.depth, _gray_info.plane_size); - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - test = 1 << ((-_gray_info.depth) & 7); - mask = (~mask & 0xff); - if (mask == 0) - { - do - { - unsigned data = 0; - - for (i = 7; i >= 0; i--) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } - else - { - do - { - unsigned data = 0; - - for (i = 7; i >= 0; i--) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = (*addr & mask) | data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } -#endif -} - -/* Draw a partial greyscale bitmap, canonical format */ -void gray_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height) -{ - int shift, nx; - unsigned char *dst, *dst_end; - unsigned mask, mask_right; - - /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= _gray_info.width) - || (y >= _gray_info.height) || (x + width <= 0) || (y + height <= 0)) - return; - - /* clipping */ - if (x < 0) - { - width += x; - src_x -= x; - x = 0; - } - if (y < 0) - { - height += y; - src_y -= y; - y = 0; - } - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (y + height > _gray_info.height) - height = _gray_info.height - y; - - shift = x & 7; - src += _GRAY_MULUQ(stride, src_y) + src_x - shift; - dst = _gray_info.plane_data + (x >> 3) + _GRAY_MULUQ(_gray_info.bwidth, y); - nx = width - 1 + shift; - - mask = 0xFFu >> shift; - mask_right = 0xFFu << (~nx & 7); - - dst_end = dst + _GRAY_MULUQ(_gray_info.bwidth, height); - do - { - const unsigned char *src_row = src; - unsigned char *dst_row = dst; - unsigned mask_row = mask; - - for (x = nx; x >= 8; x -= 8) - { - _writearray(dst_row++, src_row, mask_row); - src_row += 8; - mask_row = 0xFFu; - } - _writearray(dst_row, src_row, mask_row & mask_right); - - src += stride; - dst += _gray_info.bwidth; - } - while (dst < dst_end); -} -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - -/* Write a pixel block, defined by their brightnesses in a greymap. - Address is the byte in the first bitplane, src is the greymap start address, - stride is the increment for the greymap to get to the next pixel, mask - determines which pixels of the destination block are changed. */ -static void _writearray(unsigned char *address, const unsigned char *src, - int stride, unsigned mask) __attribute__((noinline)); -static void _writearray(unsigned char *address, const unsigned char *src, - int stride, unsigned mask) -{ - unsigned long pat_stack[8]; - unsigned long *pat_ptr = &pat_stack[8]; - unsigned char *addr; -#if CONFIG_CPU == SH7034 - const unsigned char *_src; - unsigned _mask, depth, trash; - - _mask = mask; - _src = src; - - /* precalculate the bit patterns with random shifts - for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "mov #8, r3 \n" /* loop count */ - - ".wa_loop: \n" /** load pattern for pixel **/ - "mov #0, r0 \n" /* pattern for skipped pixel must be 0 */ - "shlr %[mask] \n" /* shift out lsb of mask */ - "bf .wa_skip \n" /* skip this pixel */ - - "mov.b @%[src], r0 \n" /* load src byte */ - "mov #75, r1 \n" - "extu.b r0, r0 \n" /* extend unsigned */ - "mov.b @(r0,%[trns]), r0 \n" /* idxtable into pattern index */ - "mulu r1, %[rnd] \n" /* multiply by 75 */ - "extu.b r0, r0 \n" /* extend unsigned */ - "shll2 r0 \n" - "mov.l @(r0,%[bpat]), r4 \n" /* r4 = bitpattern[byte]; */ - "sts macl, %[rnd] \n" - "add #74, %[rnd] \n" /* add another 74 */ - /* Since the lower bits are not very random: */ - "swap.b %[rnd], r1 \n" /* get bits 8..15 (need max. 5) */ - "and %[rmsk], r1 \n" /* mask out unneeded bits */ - - "cmp/hs %[dpth], r1 \n" /* random >= depth ? */ - "bf .wa_ntrim \n" - "sub %[dpth], r1 \n" /* yes: random -= depth; */ - ".wa_ntrim: \n" - - "mov.l .ashlsi3, r0 \n" /** rotate pattern **/ - "jsr @r0 \n" /* r4 -> r0, shift left by r5 */ - "mov r1, r5 \n" - - "mov %[dpth], r5 \n" - "sub r1, r5 \n" /* r5 = depth - r1 */ - "mov.l .lshrsi3, r1 \n" - "jsr @r1 \n" /* r4 -> r0, shift right by r5 */ - "mov r0, r1 \n" /* store previous result in r1 */ - - "or r1, r0 \n" /* rotated_pattern = r0 | r1 */ - - ".wa_skip: \n" - "mov.l r0, @-%[patp] \n" /* push on pattern stack */ - - "add %[stri], %[src] \n" /* src += stride; */ - "add #-1, r3 \n" /* loop 8 times (pixel block) */ - "cmp/pl r3 \n" - "bt .wa_loop \n" - : /* outputs */ - [src] "+r"(_src), - [rnd] "+r"(_gray_random_buffer), - [patp]"+r"(pat_ptr), - [mask]"+r"(_mask) - : /* inputs */ - [stri]"r"(stride), - [dpth]"r"(_gray_info.depth), - [bpat]"r"(_gray_info.bitpattern), - [rmsk]"r"(_gray_info.randmask), - [trns]"r"(_gray_info.idxtable) - : /* clobbers */ - "r0", "r1", "r3", "r4", "r5", "macl", "pr" - ); - - addr = address; - _mask = mask; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "mov.l @%[patp]+, r8 \n" /* pop all 8 patterns */ - "mov.l @%[patp]+, r7 \n" - "mov.l @%[patp]+, r6 \n" - "mov.l @%[patp]+, r5 \n" - "mov.l @%[patp]+, r4 \n" - "mov.l @%[patp]+, r3 \n" - "mov.l @%[patp]+, r2 \n" - "mov.l @%[patp], r1 \n" - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "mov.l .wa_mask4, %[rx] \n" /* bitmask = ...11110000 */ - "mov r5, r0 \n" /** Stage 1: 4 bit "comb" **/ - "shll2 r0 \n" - "shll2 r0 \n" - "xor r1, r0 \n" - "and %[rx], r0 \n" - "xor r0, r1 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r5 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */ - "mov r6, r0 \n" - "shll2 r0 \n" - "shll2 r0 \n" - "xor r2, r0 \n" - "and %[rx], r0 \n" - "xor r0, r2 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r6 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */ - "mov r7, r0 \n" - "shll2 r0 \n" - "shll2 r0 \n" - "xor r3, r0 \n" - "and %[rx], r0 \n" - "xor r0, r3 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r7 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */ - "mov r8, r0 \n" - "shll2 r0 \n" - "shll2 r0 \n" - "xor r4, r0 \n" - "and %[rx], r0 \n" - "xor r0, r4 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */ - "shlr2 r0 \n" - "shlr2 r0 \n" - "xor r0, r8 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */ - - "mov.l .wa_mask2, %[rx] \n" /* bitmask = ...11001100 */ - "mov r3, r0 \n" /** Stage 2: 2 bit "comb" **/ - "shll2 r0 \n" - "xor r1, r0 \n" - "and %[rx], r0 \n" - "xor r0, r1 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */ - "shlr2 r0 \n" - "xor r0, r3 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */ - "mov r4, r0 \n" - "shll2 r0 \n" - "xor r2, r0 \n" - "and %[rx], r0 \n" - "xor r0, r2 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "shlr2 r0 \n" - "xor r0, r4 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */ - "mov r7, r0 \n" - "shll2 r0 \n" - "xor r5, r0 \n" - "and %[rx], r0 \n" - "xor r0, r5 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */ - "shlr2 r0 \n" - "xor r0, r7 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */ - "mov r8, r0 \n" - "shll2 r0 \n" - "xor r6, r0 \n" - "and %[rx], r0 \n" - "xor r0, r6 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */ - "shlr2 r0 \n" - "xor r0, r8 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */ - - "mov.l .wa_mask1, %[rx] \n" /* bitmask = ...10101010 */ - "mov r2, r0 \n" /** Stage 3: 1 bit "comb" **/ - "shll r0 \n" - "xor r1, r0 \n" - "and %[rx], r0 \n" - "xor r0, r1 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */ - "shlr r0 \n" - "xor r0, r2 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */ - "mov r4, r0 \n" - "shll r0 \n" - "xor r3, r0 \n" - "and %[rx], r0 \n" - "xor r0, r3 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */ - "shlr r0 \n" - "xor r0, r4 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */ - "mov r6, r0 \n" - "shll r0 \n" - "xor r5, r0 \n" - "and %[rx], r0 \n" - "xor r0, r5 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */ - "shlr r0 \n" - "xor r0, r6 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */ - "mov r8, r0 \n" - "shll r0 \n" - "xor r7, r0 \n" - "and %[rx], r0 \n" - "xor r0, r7 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */ - "shlr r0 \n" - "xor r0, r8 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */ - - "mov %[dpth], %[rx] \n" /** shift out unused low bytes **/ - "add #-1, %[rx] \n" - "mov #7, r0 \n" - "and r0, %[rx] \n" - "mova .wa_pshift, r0 \n" - "add %[rx], r0 \n" - "add %[rx], r0 \n" - "jmp @r0 \n" /* jump into shift streak */ - "nop \n" - - ".align 2 \n" - ".wa_pshift: \n" - "shlr8 r7 \n" - "shlr8 r6 \n" - "shlr8 r5 \n" - "shlr8 r4 \n" - "shlr8 r3 \n" - "shlr8 r2 \n" - "shlr8 r1 \n" - - "not %[mask], %[mask] \n" /* "set" mask -> "keep" mask */ - "extu.b %[mask], %[mask] \n" /* mask out high bits */ - "tst %[mask], %[mask] \n" - "bt .wa_sstart \n" /* short loop if nothing to keep */ - - "mova .wa_ftable, r0 \n" /* jump into full loop */ - "mov.b @(r0, %[rx]), %[rx] \n" - "add %[rx], r0 \n" - "jmp @r0 \n" - "nop \n" - - ".align 2 \n" - ".wa_ftable: \n" - ".byte .wa_f1 - .wa_ftable \n" - ".byte .wa_f2 - .wa_ftable \n" - ".byte .wa_f3 - .wa_ftable \n" - ".byte .wa_f4 - .wa_ftable \n" - ".byte .wa_f5 - .wa_ftable \n" - ".byte .wa_f6 - .wa_ftable \n" - ".byte .wa_f7 - .wa_ftable \n" - ".byte .wa_f8 - .wa_ftable \n" - - ".wa_floop: \n" /** full loop (there are bits to keep)**/ - ".wa_f8: \n" - "mov.b @%[addr], r0 \n" /* load old byte */ - "and %[mask], r0 \n" /* mask out replaced bits */ - "or r1, r0 \n" /* set new bits */ - "mov.b r0, @%[addr] \n" /* store byte */ - "add %[psiz], %[addr] \n" - "shlr8 r1 \n" /* shift out used-up byte */ - ".wa_f7: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r2, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r2 \n" - ".wa_f6: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r3, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r3 \n" - ".wa_f5: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r4, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r4 \n" - ".wa_f4: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r5, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r5 \n" - ".wa_f3: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r6, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r6 \n" - ".wa_f2: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r7, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r7 \n" - ".wa_f1: \n" - "mov.b @%[addr], r0 \n" - "and %[mask], r0 \n" - "or r8, r0 \n" - "mov.b r0, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r8 \n" - - "add #-8, %[dpth] \n" - "cmp/pl %[dpth] \n" /* next round if anything left */ - "bt .wa_floop \n" - - "bra .wa_end \n" - "nop \n" - - /* References to C library routines used in the precalc block */ - ".align 2 \n" - ".ashlsi3: \n" /* C library routine: */ - ".long ___ashlsi3 \n" /* shift r4 left by r5, result in r0 */ - ".lshrsi3: \n" /* C library routine: */ - ".long ___lshrsi3 \n" /* shift r4 right by r5, result in r0 */ - /* both routines preserve r4, destroy r5 and take ~16 cycles */ - - /* Bitmasks for the bit block rotation */ - ".wa_mask4: \n" - ".long 0xF0F0F0F0 \n" - ".wa_mask2: \n" - ".long 0xCCCCCCCC \n" - ".wa_mask1: \n" - ".long 0xAAAAAAAA \n" - - ".wa_sstart: \n" - "mova .wa_stable, r0 \n" /* jump into short loop */ - "mov.b @(r0, %[rx]), %[rx] \n" - "add %[rx], r0 \n" - "jmp @r0 \n" - "nop \n" - - ".align 2 \n" - ".wa_stable: \n" - ".byte .wa_s1 - .wa_stable \n" - ".byte .wa_s2 - .wa_stable \n" - ".byte .wa_s3 - .wa_stable \n" - ".byte .wa_s4 - .wa_stable \n" - ".byte .wa_s5 - .wa_stable \n" - ".byte .wa_s6 - .wa_stable \n" - ".byte .wa_s7 - .wa_stable \n" - ".byte .wa_s8 - .wa_stable \n" - - ".wa_sloop: \n" /** short loop (nothing to keep) **/ - ".wa_s8: \n" - "mov.b r1, @%[addr] \n" /* store byte */ - "add %[psiz], %[addr] \n" - "shlr8 r1 \n" /* shift out used-up byte */ - ".wa_s7: \n" - "mov.b r2, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r2 \n" - ".wa_s6: \n" - "mov.b r3, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r3 \n" - ".wa_s5: \n" - "mov.b r4, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r4 \n" - ".wa_s4: \n" - "mov.b r5, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r5 \n" - ".wa_s3: \n" - "mov.b r6, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r6 \n" - ".wa_s2: \n" - "mov.b r7, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r7 \n" - ".wa_s1: \n" - "mov.b r8, @%[addr] \n" - "add %[psiz], %[addr] \n" - "shlr8 r8 \n" - - "add #-8, %[dpth] \n" - "cmp/pl %[dpth] \n" /* next round if anything left */ - "bt .wa_sloop \n" - - ".wa_end: \n" - : /* outputs */ - [addr]"+r"(addr), - [mask]"+r"(_mask), - [dpth]"+r"(depth), - [rx] "=&r"(trash) - : /* inputs */ - [psiz]"r"(_gray_info.plane_size), - [patp]"[rx]"(pat_ptr) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "macl" - ); -#elif defined(CPU_COLDFIRE) - const unsigned char *_src; - unsigned _mask, depth, trash; - - _mask = mask; - _src = src; - - /* precalculate the bit patterns with random shifts - for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "moveq.l #8, %%d3 \n" /* loop count */ - - ".wa_loop: \n" /** load pattern for pixel **/ - "clr.l %%d2 \n" /* pattern for skipped pixel must be 0 */ - "lsr.l #1, %[mask] \n" /* shift out lsb of mask */ - "bcc.b .wa_skip \n" /* skip this pixel */ - - "clr.l %%d0 \n" - "move.b (%[src]), %%d0 \n" /* load src byte */ - "move.b (%%d0:l:1, %[trns]), %%d0 \n" /* idxtable into pattern index */ - "move.l (%%d0:l:4, %[bpat]), %%d2 \n" /* d2 = bitpattern[byte]; */ - - "mulu.w #75, %[rnd] \n" /* multiply by 75 */ - "add.l #74, %[rnd] \n" /* add another 74 */ - /* Since the lower bits are not very random: */ - "move.l %[rnd], %%d1 \n" - "lsr.l #8, %%d1 \n" /* get bits 8..15 (need max. 5) */ - "and.l %[rmsk], %%d1 \n" /* mask out unneeded bits */ - - "cmp.l %[dpth], %%d1 \n" /* random >= depth ? */ - "blo.b .wa_ntrim \n" - "sub.l %[dpth], %%d1 \n" /* yes: random -= depth; */ - ".wa_ntrim: \n" - - "move.l %%d2, %%d0 \n" /** rotate pattern **/ - "lsl.l %%d1, %%d0 \n" - "sub.l %[dpth], %%d1 \n" - "neg.l %%d1 \n" /* d1 = depth - d1 */ - "lsr.l %%d1, %%d2 \n" - "or.l %%d0, %%d2 \n" - - ".wa_skip: \n" - "move.l %%d2, -(%[patp]) \n" /* push on pattern stack */ - - "add.l %[stri], %[src] \n" /* src += stride; */ - "subq.l #1, %%d3 \n" /* loop 8 times (pixel block) */ - "bne.b .wa_loop \n" - : /* outputs */ - [src] "+a"(_src), - [patp]"+a"(pat_ptr), - [rnd] "+d"(_gray_random_buffer), - [mask]"+d"(_mask) - : /* inputs */ - [stri]"r"(stride), - [bpat]"a"(_gray_info.bitpattern), - [trns]"a"(_gray_info.idxtable), - [dpth]"d"(_gray_info.depth), - [rmsk]"d"(_gray_info.randmask) - : /* clobbers */ - "d0", "d1", "d2", "d3" - ); - - addr = address; - _mask = ~mask & 0xff; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "movem.l (%[patp]), %%d1-%%d7/%%a0 \n" /* pop all 8 patterns */ - /* move.l %%d5, %[ax] */ /* need %%d5 as workspace, but not yet */ - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "move.l %%d1, %%d0 \n" /** Stage 1: 4 bit "comb" **/ - "lsl.l #4, %%d0 \n" - /* move.l %[ax], %%d5 */ /* already in d5 */ - "eor.l %%d5, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" /* bitmask = ...11110000 */ - "eor.l %%d0, %%d5 \n" - "move.l %%d5, %[ax] \n" /* ax = ...h3h2h1h0d3d2d1d0 */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d1 \n" /* d1 = ...h7h6h5h4d7d6d5d4 */ - "move.l %%d2, %%d0 \n" - "lsl.l #4, %%d0 \n" - "eor.l %%d6, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" - "eor.l %%d0, %%d6 \n" /* d6 = ...g3g2g1g0c3c2c1c0 */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d2 \n" /* d2 = ...g7g6g5g4c7c6c5c4 */ - "move.l %%d3, %%d0 \n" - "lsl.l #4, %%d0 \n" - "eor.l %%d7, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" - "eor.l %%d0, %%d7 \n" /* d7 = ...f3f2f1f0b3b2b1b0 */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d3 \n" /* d3 = ...f7f6f5f4f7f6f5f4 */ - "move.l %%d4, %%d0 \n" - "lsl.l #4, %%d0 \n" - "move.l %%a0, %%d5 \n" - "eor.l %%d5, %%d0 \n" - "and.l #0xF0F0F0F0, %%d0 \n" - "eor.l %%d0, %%d5 \n" /* (a0 = ...e3e2e1e0a3a2a1a0) */ - /* move.l %%d5, %%a0 */ /* but d5 is kept until next usage */ - "lsr.l #4, %%d0 \n" - "eor.l %%d0, %%d4 \n" /* d4 = ...e7e6e5e4a7a6a5a4 */ - - "move.l %%d6, %%d0 \n" /** Stage 2: 2 bit "comb" **/ - "lsl.l #2, %%d0 \n" - /* move.l %%a0, %%d5 */ /* still in d5 */ - "eor.l %%d5, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" /* bitmask = ...11001100 */ - "eor.l %%d0, %%d5 \n" - "move.l %%d5, %%a0 \n" /* a0 = ...g1g0e1e0c1c0a1a0 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d6 \n" /* d6 = ...g3g2e3e2c3c2a3a2 */ - "move.l %[ax], %%d5 \n" - "move.l %%d5, %%d0 \n" - "lsl.l #2, %%d0 \n" - "eor.l %%d7, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" - "eor.l %%d0, %%d7 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d5 \n" /* (ax = ...h3h2f3f2d3d2b3b2) */ - /* move.l %%d5, %[ax] */ /* but d5 is kept until next usage */ - "move.l %%d2, %%d0 \n" - "lsl.l #2, %%d0 \n" - "eor.l %%d4, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" - "eor.l %%d0, %%d4 \n" /* d4 = ...g5g4e5e4c5c4a5a4 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d2 \n" /* d2 = ...g7g6e7e6c7c6a7a6 */ - "move.l %%d1, %%d0 \n" - "lsl.l #2, %%d0 \n" - "eor.l %%d3, %%d0 \n" - "and.l #0xCCCCCCCC, %%d0 \n" - "eor.l %%d0, %%d3 \n" /* d3 = ...h5h4f5f4d5d4b5b4 */ - "lsr.l #2, %%d0 \n" - "eor.l %%d0, %%d1 \n" /* d1 = ...h7h6f7f6d7d6b7b6 */ - - "move.l %%d1, %%d0 \n" /** Stage 3: 1 bit "comb" **/ - "lsl.l #1, %%d0 \n" - "eor.l %%d2, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" /* bitmask = ...10101010 */ - "eor.l %%d0, %%d2 \n" /* d2 = ...h6g6f6e6d6c6b6a6 */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d1 \n" /* d1 = ...h7g7f7e7d7c7b7a7 */ - "move.l %%d3, %%d0 \n" - "lsl.l #1, %%d0 \n" - "eor.l %%d4, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" - "eor.l %%d0, %%d4 \n" /* d4 = ...h4g4f4e4d4c4b4a4 */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d3 \n" /* d3 = ...h5g5f5e5d5c5b5a5 */ - /* move.l %[ax], %%d5 */ /* still in d5 */ - "move.l %%d5, %%d0 \n" - "lsl.l #1, %%d0 \n" - "eor.l %%d6, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" - "eor.l %%d0, %%d6 \n" /* d6 = ...h2g2f2e2d2c2b2a2 */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d5 \n" - "move.l %%d5, %[ax] \n" /* ax = ...h3g3f3e3d3c3b3a3 */ - "move.l %%d7, %%d0 \n" - "lsl.l #1, %%d0 \n" - "move.l %%a0, %%d5 \n" - "eor.l %%d5, %%d0 \n" - "and.l #0xAAAAAAAA, %%d0 \n" - "eor.l %%d0, %%d5 \n" /* (a0 = ...h0g0f0e0d0c0b0a0) */ - /* move.l %%d5, %%a0 */ /* but keep in d5 for shift streak */ - "lsr.l #1, %%d0 \n" - "eor.l %%d0, %%d7 \n" /* d7 = ...h1g1f1e1d1c1b1a1 */ - - "move.l %[dpth], %%d0 \n" /** shift out unused low bytes **/ - "subq.l #1, %%d0 \n" - "and.l #7, %%d0 \n" - "move.l %%d0, %%a0 \n" - "move.l %[ax], %%d0 \n" /* all data in D registers */ - "jmp (2, %%pc, %%a0:l:2) \n" /* jump into shift streak */ - "lsr.l #8, %%d2 \n" - "lsr.l #8, %%d3 \n" - "lsr.l #8, %%d4 \n" - "lsr.l #8, %%d0 \n" - "lsr.l #8, %%d6 \n" - "lsr.l #8, %%d7 \n" - "lsr.l #8, %%d5 \n" - "move.l %%d0, %[ax] \n" /* put the 2 extra words back.. */ - "move.l %%a0, %%d0 \n" /* keep the value for later */ - "move.l %%d5, %%a0 \n" /* ..into their A registers */ - - "tst.l %[mask] \n" - "jeq .wa_sstart \n" /* short loop if nothing to keep */ - - "move.l %[mask], %%d5 \n" /* need mask in data reg. */ - "move.l %%d1, %[mask] \n" /* free d1 as working reg. */ - - "jmp (2, %%pc, %%d0:l:2) \n" /* jump into full loop */ - "bra.s .wa_f1 \n" - "bra.s .wa_f2 \n" - "bra.s .wa_f3 \n" - "bra.s .wa_f4 \n" - "bra.s .wa_f5 \n" - "bra.s .wa_f6 \n" - "bra.s .wa_f7 \n" - /* bra.s .wa_f8 */ /* identical with target */ - - ".wa_floop: \n" /** full loop (there are bits to keep)**/ - ".wa_f8: \n" - "move.b (%[addr]), %%d0 \n" /* load old byte */ - "and.l %%d5, %%d0 \n" /* mask out replaced bits */ - "move.l %%a0, %%d1 \n" - "or.l %%d1, %%d0 \n" /* set new bits */ - "move.b %%d0, (%[addr]) \n" /* store byte */ - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" /* shift out used-up byte */ - "move.l %%d1, %%a0 \n" - ".wa_f7: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d7, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d7 \n" - ".wa_f6: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d6, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d6 \n" - ".wa_f5: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "move.l %[ax], %%d1 \n" - "or.l %%d1, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" - "move.l %%d1, %[ax] \n" - ".wa_f4: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d4, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d4 \n" - ".wa_f3: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d3, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d3 \n" - ".wa_f2: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "or.l %%d2, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d2 \n" - ".wa_f1: \n" - "move.b (%[addr]), %%d0 \n" - "and.l %%d5, %%d0 \n" - "move.l %[mask], %%d1 \n" - "or.l %%d1, %%d0 \n" - "move.b %%d0, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" - "move.l %%d1, %[mask] \n" - - "subq.l #8, %[dpth] \n" - "tst.l %[dpth] \n" /* subq doesn't set flags for A reg */ - "jgt .wa_floop \n" /* next round if anything left */ - - "jra .wa_end \n" - - ".wa_sstart: \n" - "jmp (2, %%pc, %%d0:l:2) \n" /* jump into short loop */ - "bra.s .wa_s1 \n" - "bra.s .wa_s2 \n" - "bra.s .wa_s3 \n" - "bra.s .wa_s4 \n" - "bra.s .wa_s5 \n" - "bra.s .wa_s6 \n" - "bra.s .wa_s7 \n" - /* bra.s .wa_s8 */ /* identical with target */ - - ".wa_sloop: \n" /** short loop (nothing to keep) **/ - ".wa_s8: \n" - "move.l %%a0, %%d5 \n" - "move.b %%d5, (%[addr]) \n" /* store byte */ - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d5 \n" /* shift out used-up byte */ - "move.l %%d5, %%a0 \n" - ".wa_s7: \n" - "move.b %%d7, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d7 \n" - ".wa_s6: \n" - "move.b %%d6, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d6 \n" - ".wa_s5: \n" - "move.l %[ax], %%d5 \n" - "move.b %%d5, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d5 \n" - "move.l %%d5, %[ax] \n" - ".wa_s4: \n" - "move.b %%d4, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d4 \n" - ".wa_s3: \n" - "move.b %%d3, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d3 \n" - ".wa_s2: \n" - "move.b %%d2, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d2 \n" - ".wa_s1: \n" - "move.b %%d1, (%[addr]) \n" - "add.l %[psiz], %[addr] \n" - "lsr.l #8, %%d1 \n" - - "subq.l #8, %[dpth] \n" - "tst.l %[dpth] \n" /* subq doesn't set flags for A reg */ - "jgt .wa_sloop \n" /* next round if anything left */ - - ".wa_end: \n" - : /* outputs */ - [addr]"+a"(addr), - [dpth]"+a"(depth), - [mask]"+a"(_mask), - [ax] "=&a"(trash) - : /* inputs */ - [psiz]"a"(_gray_info.plane_size), - [patp]"[ax]"(pat_ptr) - : /* clobbers */ - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0" - ); -#elif defined(CPU_ARM) - const unsigned char *_src; - unsigned _mask, depth, trash; - - _mask = mask; - _src = src; - - pat_ptr = &pat_stack[0]; - - /* precalculate the bit patterns with random shifts - for all 8 pixels and put them on an extra "stack" */ - asm volatile - ( - "mov r3, #8 \n" /* loop count */ - - ".wa_loop: \n" /** load pattern for pixel **/ - "mov r2, #0 \n" /* pattern for skipped pixel must be 0 */ - "movs %[mask], %[mask], lsr #1 \n" /* shift out msb of mask */ - "bcc .wa_skip \n" /* skip this pixel */ - - "ldrb r0, [%[src]] \n" /* load src byte */ - "ldrb r0, [%[trns], r0] \n" /* idxtable into pattern index */ - "ldr r2, [%[bpat], r0, lsl #2] \n" /* r2 = bitpattern[byte]; */ - - "add %[rnd], %[rnd], %[rnd], lsl #2 \n" /* multiply by 75 */ - "rsb %[rnd], %[rnd], %[rnd], lsl #4 \n" - "add %[rnd], %[rnd], #74 \n" /* add another 74 */ - /* Since the lower bits are not very random: get bits 8..15 (need max. 5) */ - "and r1, %[rmsk], %[rnd], lsr #8 \n" /* ..and mask out unneeded bits */ - - "cmp r1, %[dpth] \n" /* random >= depth ? */ - "subhs r1, r1, %[dpth] \n" /* yes: random -= depth */ - - "mov r0, r2, lsl r1 \n" /** rotate pattern **/ - "sub r1, %[dpth], r1 \n" - "orr r2, r0, r2, lsr r1 \n" - - ".wa_skip: \n" - "str r2, [%[patp]], #4 \n" /* push on pattern stack */ - - "add %[src], %[src], %[stri] \n" /* src += stride; */ - "subs r3, r3, #1 \n" /* loop 8 times (pixel block) */ - "bne .wa_loop \n" - : /* outputs */ - [src] "+r"(_src), - [patp]"+r"(pat_ptr), - [rnd] "+r"(_gray_random_buffer), - [mask]"+r"(_mask) - : /* inputs */ - [stri]"r"(stride), - [bpat]"r"(_gray_info.bitpattern), - [trns]"r"(_gray_info.idxtable), - [dpth]"r"(_gray_info.depth), - [rmsk]"r"(_gray_info.randmask) - : /* clobbers */ - "r0", "r1", "r2", "r3" - ); - - addr = address; - _mask = mask; - depth = _gray_info.depth; - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - asm volatile - ( - "ldmdb %[patp], {r1 - r8} \n" /* pop all 8 patterns */ - - /** Rotate the four 8x8 bit "blocks" within r1..r8 **/ - - "mov %[rx], #0xF0 \n" /** Stage 1: 4 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11110000 */ - "eor r0, r1, r5, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */ - "eor r5, r5, r0, lsr #4 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */ - "eor r0, r2, r6, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */ - "eor r6, r6, r0, lsr #4 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */ - "eor r0, r3, r7, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */ - "eor r7, r7, r0, lsr #4 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */ - "eor r0, r4, r8, lsl #4 \n" - "and r0, r0, %[rx] \n" - "eor r4, r4, r0 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */ - "eor r8, r8, r0, lsr #4 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */ - - "mov %[rx], #0xCC \n" /** Stage 2: 2 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11001100 */ - "eor r0, r1, r3, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */ - "eor r3, r3, r0, lsr #2 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */ - "eor r0, r2, r4, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r2, r2, r0 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */ - "eor r4, r4, r0, lsr #2 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */ - "eor r0, r5, r7, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */ - "eor r7, r7, r0, lsr #2 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */ - "eor r0, r6, r8, lsl #2 \n" - "and r0, r0, %[rx] \n" - "eor r6, r6, r0 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */ - "eor r8, r8, r0, lsr #2 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */ - - "mov %[rx], #0xAA \n" /** Stage 3: 1 bit "comb" **/ - "orr %[rx], %[rx], %[rx], lsl #8 \n" - "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...10101010 */ - "eor r0, r1, r2, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r1, r1, r0 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */ - "eor r2, r2, r0, lsr #1 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */ - "eor r0, r3, r4, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r3, r3, r0 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */ - "eor r4, r4, r0, lsr #1 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */ - "eor r0, r5, r6, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r5, r5, r0 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */ - "eor r6, r6, r0, lsr #1 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */ - "eor r0, r7, r8, lsl #1 \n" - "and r0, r0, %[rx] \n" - "eor r7, r7, r0 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */ - "eor r8, r8, r0, lsr #1 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */ - - "sub r0, %[dpth], #1 \n" /** shift out unused low bytes **/ - "and r0, r0, #7 \n" - "add pc, pc, r0, lsl #2 \n" /* jump into shift streak */ - "mov r8, r8, lsr #8 \n" /* r8: never reached */ - "mov r7, r7, lsr #8 \n" - "mov r6, r6, lsr #8 \n" - "mov r5, r5, lsr #8 \n" - "mov r4, r4, lsr #8 \n" - "mov r3, r3, lsr #8 \n" - "mov r2, r2, lsr #8 \n" - "mov r1, r1, lsr #8 \n" - - "mvn %[mask], %[mask] \n" /* "set" mask -> "keep" mask */ - "ands %[mask], %[mask], #0xff \n" - "beq .wa_sstart \n" /* short loop if no bits to keep */ - - "ldrb r0, [pc, r0] \n" /* jump into full loop */ - "add pc, pc, r0 \n" - ".wa_ftable: \n" - ".byte .wa_f1 - .wa_ftable - 4 \n" /* [jump tables are tricky] */ - ".byte .wa_f2 - .wa_ftable - 4 \n" - ".byte .wa_f3 - .wa_ftable - 4 \n" - ".byte .wa_f4 - .wa_ftable - 4 \n" - ".byte .wa_f5 - .wa_ftable - 4 \n" - ".byte .wa_f6 - .wa_ftable - 4 \n" - ".byte .wa_f7 - .wa_ftable - 4 \n" - ".byte .wa_f8 - .wa_ftable - 4 \n" - - ".wa_floop: \n" /** full loop (bits to keep)**/ - ".wa_f8: \n" - "ldrb r0, [%[addr]] \n" /* load old byte */ - "and r0, r0, %[mask] \n" /* mask out replaced bits */ - "orr r0, r0, r1 \n" /* set new bits */ - "strb r0, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".wa_f7: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r2 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".wa_f6: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r3 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".wa_f5: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r4 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".wa_f4: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r5 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".wa_f3: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r6 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".wa_f2: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r7 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".wa_f1: \n" - "ldrb r0, [%[addr]] \n" - "and r0, r0, %[mask] \n" - "orr r0, r0, r8 \n" - "strb r0, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .wa_floop \n" - - "b .wa_end \n" - - ".wa_sstart: \n" - "ldrb r0, [pc, r0] \n" /* jump into short loop*/ - "add pc, pc, r0 \n" - ".wa_stable: \n" - ".byte .wa_s1 - .wa_stable - 4 \n" - ".byte .wa_s2 - .wa_stable - 4 \n" - ".byte .wa_s3 - .wa_stable - 4 \n" - ".byte .wa_s4 - .wa_stable - 4 \n" - ".byte .wa_s5 - .wa_stable - 4 \n" - ".byte .wa_s6 - .wa_stable - 4 \n" - ".byte .wa_s7 - .wa_stable - 4 \n" - ".byte .wa_s8 - .wa_stable - 4 \n" - - ".wa_sloop: \n" /** short loop (nothing to keep) **/ - ".wa_s8: \n" - "strb r1, [%[addr]], %[psiz] \n" /* store byte */ - "mov r1, r1, lsr #8 \n" /* shift out used-up byte */ - ".wa_s7: \n" - "strb r2, [%[addr]], %[psiz] \n" - "mov r2, r2, lsr #8 \n" - ".wa_s6: \n" - "strb r3, [%[addr]], %[psiz] \n" - "mov r3, r3, lsr #8 \n" - ".wa_s5: \n" - "strb r4, [%[addr]], %[psiz] \n" - "mov r4, r4, lsr #8 \n" - ".wa_s4: \n" - "strb r5, [%[addr]], %[psiz] \n" - "mov r5, r5, lsr #8 \n" - ".wa_s3: \n" - "strb r6, [%[addr]], %[psiz] \n" - "mov r6, r6, lsr #8 \n" - ".wa_s2: \n" - "strb r7, [%[addr]], %[psiz] \n" - "mov r7, r7, lsr #8 \n" - ".wa_s1: \n" - "strb r8, [%[addr]], %[psiz] \n" - "mov r8, r8, lsr #8 \n" - - "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */ - "bhi .wa_sloop \n" - - ".wa_end: \n" - : /* outputs */ - [addr]"+r"(addr), - [mask]"+r"(_mask), - [dpth]"+r"(depth), - [rx] "=&r"(trash) - : /* inputs */ - [psiz]"r"(_gray_info.plane_size), - [patp]"[rx]"(pat_ptr) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" - ); -#else /* C version, for reference*/ -#warning C version of _writearray() used - unsigned char *end; - unsigned test = 1; - int i; - - /* precalculate the bit patterns with random shifts - * for all 8 pixels and put them on an extra "stack" */ - for (i = 7; i >= 0; i--) - { - unsigned pat = 0; - - if (mask & test) - { - int shift; - - pat = _gray_info.bitpattern[_gray_info.idxtable[*src]]; - - /* shift pattern pseudo-random, simple & fast PRNG */ - _gray_random_buffer = 75 * _gray_random_buffer + 74; - shift = (_gray_random_buffer >> 8) & _gray_info.randmask; - if (shift >= _gray_info.depth) - shift -= _gray_info.depth; - - pat = (pat << shift) | (pat >> (_gray_info.depth - shift)); - } - *(--pat_ptr) = pat; - src += stride; - test <<= 1; - } - - addr = address; - end = addr + _GRAY_MULUQ(_gray_info.depth, _gray_info.plane_size); - - /* set the bits for all 8 pixels in all bytes according to the - * precalculated patterns on the pattern stack */ - test = 1 << ((-_gray_info.depth) & 7); - mask = (~mask & 0xff); - if (mask == 0) - { - do - { - unsigned data = 0; - - for (i = 0; i < 8; i++) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } - else - { - do - { - unsigned data = 0; - - for (i = 0; i < 8; i++) - data = (data << 1) | ((pat_stack[i] & test) ? 1 : 0); - - *addr = (*addr & mask) | data; - addr += _gray_info.plane_size; - test <<= 1; - } - while (addr < end); - } -#endif -} - -/* Draw a partial greyscale bitmap, canonical format */ -void gray_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height) -{ - int shift, ny; - unsigned char *dst, *dst_end; - unsigned mask, mask_bottom; - - /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= _gray_info.width) - || (y >= _gray_info.height) || (x + width <= 0) || (y + height <= 0)) - return; - - /* clipping */ - if (x < 0) - { - width += x; - src_x -= x; - x = 0; - } - if (y < 0) - { - height += y; - src_y -= y; - y = 0; - } - if (x + width > _gray_info.width) - width = _gray_info.width - x; - if (y + height > _gray_info.height) - height = _gray_info.height - y; - - shift = y & 7; - src += _GRAY_MULUQ(stride, src_y) + src_x - _GRAY_MULUQ(stride, shift); - dst = _gray_info.plane_data + x - + _GRAY_MULUQ(_gray_info.width, y >> 3); - ny = height - 1 + shift; - - mask = 0xFFu << shift; - mask_bottom = 0xFFu >> (~ny & 7); - - for (; ny >= 8; ny -= 8) - { - const unsigned char *src_row = src; - unsigned char *dst_row = dst; - - dst_end = dst_row + width; - do - _writearray(dst_row++, src_row++, stride, mask); - while (dst_row < dst_end); - - src += stride << 3; - dst += _gray_info.width; - mask = 0xFFu; - } - mask &= mask_bottom; - dst_end = dst + width; - do - _writearray(dst++, src++, stride, mask); - while (dst < dst_end); -} -#endif /* LCD_PIXELFORMAT */ - -#endif /* !SIMULATOR */ - -/* Draw a full greyscale bitmap, canonical format */ -void gray_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, - int height) -{ - gray_ub_gray_bitmap_part(src, 0, 0, width, x, y, width, height); -} - -#endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/lib/gray_parm.c b/apps/plugins/lib/gray_parm.c deleted file mode 100644 index ea39eadc66..0000000000 --- a/apps/plugins/lib/gray_parm.c +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Greyscale framework -* Parameter handling -* -* This is a generic framework to display up to 33 shades of grey -* on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey, iPod 4-grey) -* within plugins. -* -* Copyright (C) 2004-2006 Jens Arnold -* -* All files in this archive are subject to the GNU General Public License. -* See the file COPYING in the source tree root for full license agreement. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "plugin.h" - -#ifdef HAVE_LCD_BITMAP -#include "gray.h" - -/* Set position of the top left corner of the greyscale overlay - Note that depending on the target LCD, either x or y gets rounded - to the nearest multiple of 8 */ -void gray_set_position(int x, int y) -{ -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - _gray_info.bx = (x + 3) / 8; - x = 8 * _gray_info.bx; -#else - _gray_info.by = (y + 3) / 8; - y = 8 * _gray_info.by; -#endif - _gray_info.x = x; - _gray_info.y = y; - - if (_gray_info.flags & _GRAY_RUNNING) - { -#ifdef SIMULATOR - gray_deferred_lcd_update(); - gray_update(); -#else - _gray_info.flags |= _GRAY_DEFERRED_UPDATE; -#endif - } -} - -/* Set the draw mode for subsequent drawing operations */ -void gray_set_drawmode(int mode) -{ - _gray_info.drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); -} - -/* Return the current draw mode */ -int gray_get_drawmode(void) -{ - return _gray_info.drawmode; -} - -/* Set the foreground shade for subsequent drawing operations */ -void gray_set_foreground(unsigned brightness) -{ - _gray_info.fg_brightness = brightness; - _gray_info.fg_index = _gray_info.idxtable[brightness]; -} - -/* Return the current foreground shade */ -unsigned gray_get_foreground(void) -{ - return _gray_info.fg_brightness; -} - -/* Set the background shade for subsequent drawing operations */ -void gray_set_background(unsigned brightness) -{ - _gray_info.bg_brightness = brightness; - _gray_info.bg_index = _gray_info.idxtable[brightness]; -} - -/* Return the current background shade */ -unsigned gray_get_background(void) -{ - return _gray_info.bg_brightness; -} - -/* Set draw mode, foreground and background shades at once */ -void gray_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) -{ - gray_set_drawmode(mode); - gray_set_foreground(fg_brightness); - gray_set_background(bg_brightness); -} - -/* Set font for the text output routines */ -void gray_setfont(int newfont) -{ - _gray_info.curfont = newfont; -} - -/* Get width and height of a text when printed with the current font */ -int gray_getstringsize(const unsigned char *str, int *w, int *h) -{ - return _gray_rb->font_getstringsize(str, w, h, _gray_info.curfont); -} - -#endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/lib/gray_scroll.c b/apps/plugins/lib/gray_scroll.c deleted file mode 100644 index b366e8db5d..0000000000 --- a/apps/plugins/lib/gray_scroll.c +++ /dev/null @@ -1,930 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Greyscale framework -* Scrolling routines -* -* This is a generic framework to display up to 33 shades of grey -* on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey, iPod 4-grey) -* within plugins. -* -* Copyright (C) 2004-2006 Jens Arnold -* -* All files in this archive are subject to the GNU General Public License. -* See the file COPYING in the source tree root for full license agreement. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "plugin.h" - -#ifdef HAVE_LCD_BITMAP -#include "gray.h" - -/*** Scrolling ***/ - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - -/* Scroll left */ -void gray_scroll_left(int count) -{ - unsigned char *data, *data_end; - int length, blank; - - if ((unsigned)count >= (unsigned)_gray_info.width) - return; - - data = _gray_info.cur_buffer; - data_end = data + _GRAY_MULUQ(_gray_info.width, _gray_info.height); - length = _gray_info.width - count; - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - do - { - _gray_rb->memmove(data, data + count, length); - _gray_rb->memset(data + length, blank, count); - data += _gray_info.width; - } - while (data < data_end); -} - -/* Scroll right */ -void gray_scroll_right(int count) -{ - unsigned char *data, *data_end; - int length, blank; - - if ((unsigned)count >= (unsigned)_gray_info.width) - return; - - data = _gray_info.cur_buffer; - data_end = data + _GRAY_MULUQ(_gray_info.width, _gray_info.height); - length = _gray_info.width - count; - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - do - { - _gray_rb->memmove(data + count, data, length); - _gray_rb->memset(data, blank, count); - data += _gray_info.width; - } - while (data < data_end); -} - -/* Scroll up */ -void gray_scroll_up(int count) -{ - long shift, length; - int blank; - - if ((unsigned)count >= (unsigned)_gray_info.height) - return; - - shift = _GRAY_MULUQ(_gray_info.width, count); - length = _GRAY_MULUQ(_gray_info.width, _gray_info.height - count); - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - _gray_rb->memmove(_gray_info.cur_buffer, _gray_info.cur_buffer + shift, - length); - _gray_rb->memset(_gray_info.cur_buffer + length, blank, shift); -} - -/* Scroll down */ -void gray_scroll_down(int count) -{ - long shift, length; - int blank; - - if ((unsigned)count >= (unsigned)_gray_info.height) - return; - - shift = _GRAY_MULUQ(_gray_info.width, count); - length = _GRAY_MULUQ(_gray_info.width, _gray_info.height - count); - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - _gray_rb->memmove(_gray_info.cur_buffer + shift, _gray_info.cur_buffer, - length); - _gray_rb->memset(_gray_info.cur_buffer, blank, shift); -} - -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - -/* Scroll left */ -void gray_scroll_left(int count) -{ - long shift, length; - int blank; - - if ((unsigned)count >= (unsigned)_gray_info.width) - return; - - shift = _GRAY_MULUQ(_gray_info.height, count); - length = _GRAY_MULUQ(_gray_info.height, _gray_info.width - count); - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - _gray_rb->memmove(_gray_info.cur_buffer, _gray_info.cur_buffer + shift, - length); - _gray_rb->memset(_gray_info.cur_buffer + length, blank, shift); -} - -/* Scroll right */ -void gray_scroll_right(int count) -{ - long shift, length; - int blank; - - if ((unsigned)count >= (unsigned)_gray_info.width) - return; - - shift = _GRAY_MULUQ(_gray_info.height, count); - length = _GRAY_MULUQ(_gray_info.height, _gray_info.width - count); - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - _gray_rb->memmove(_gray_info.cur_buffer + shift, _gray_info.cur_buffer, - length); - _gray_rb->memset(_gray_info.cur_buffer, blank, shift); -} - -/* Scroll up */ -void gray_scroll_up(int count) -{ - unsigned char *data, *data_end; - int length, blank; - - if ((unsigned)count >= (unsigned)_gray_info.height) - return; - - data = _gray_info.cur_buffer; - data_end = data + _GRAY_MULUQ(_gray_info.width, _gray_info.height); - length = _gray_info.height - count; - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - do - { - _gray_rb->memmove(data, data + count, length); - _gray_rb->memset(data + length, blank, count); - data += _gray_info.height; - } - while (data < data_end); -} - -/* Scroll down */ -void gray_scroll_down(int count) -{ - unsigned char *data, *data_end; - int length, blank; - - if ((unsigned)count >= (unsigned)_gray_info.height) - return; - - data = _gray_info.cur_buffer; - data_end = data + _GRAY_MULUQ(_gray_info.width, _gray_info.height); - length = _gray_info.height - count; - blank = (_gray_info.drawmode & DRMODE_INVERSEVID) ? - _gray_info.fg_index : _gray_info.bg_index; - - do - { - _gray_rb->memmove(data + count, data, length); - _gray_rb->memset(data, blank, count); - data += _gray_info.height; - } - while (data < data_end); -} -#endif /* LCD_PIXELFORMAT */ - -/*** Unbuffered scrolling functions ***/ - -#ifdef SIMULATOR - -/* Scroll left */ -void gray_ub_scroll_left(int count) -{ - gray_scroll_left(count); - gray_update(); -} - -/* Scroll right */ -void gray_ub_scroll_right(int count) -{ - gray_scroll_right(count); - gray_update(); -} - -/* Scroll up */ -void gray_ub_scroll_up(int count) -{ - gray_scroll_up(count); - gray_update(); -} - -/* Scroll down */ -void gray_ub_scroll_down(int count) -{ - gray_scroll_down(count); - gray_update(); -} - -#else /* !SIMULATOR */ - -#if LCD_PIXELFORMAT == HORIZONTAL_PACKING - -/* Scroll left */ -void gray_ub_scroll_left(int count) -{ - int shift, length; - unsigned char *ptr, *ptr_end; - - if ((unsigned) count >= (unsigned) _gray_info.width) - return; - - shift = count >> 3; - count &= 7; - - if (shift) - { - length = _gray_info.bwidth - shift; - ptr = _gray_info.plane_data; - ptr_end = ptr + _gray_info.plane_size; - - /* Scroll row by row to minimize flicker */ - do - { - unsigned char *ptr_row = ptr; - unsigned char *row_end = ptr_row - + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - do - { - _gray_rb->memmove(ptr_row, ptr_row + shift, length); - _gray_rb->memset(ptr_row + length, 0, shift); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - - ptr += _gray_info.bwidth; - } - while (ptr < ptr_end); - } - if (count) - { - asm ( - "mov r4, %[high] \n" /* rows = height */ - - ".sl_rloop: \n" /* repeat for every row */ - "mov r5, %[addr] \n" /* get start address */ - "mov r2, %[dpth] \n" /* planes = depth */ - - ".sl_oloop: \n" /* repeat for every bitplane */ - "mov r6, r5 \n" /* get start address */ - "mov r3, %[cols] \n" /* cols = col_count */ - "mov r1, #0 \n" /* fill with zero */ - - ".sl_iloop: \n" /* repeat for all cols */ - "mov r1, r1, lsr #8 \n" /* shift right to get residue */ - "ldrb r0, [r6, #-1]! \n" /* decrement addr & get data byte */ - "orr r1, r1, r0, lsl %[cnt] \n" /* combine with last residue */ - "strb r1, [r6] \n" /* store data */ - - "subs r3, r3, #1 \n" /* cols-- */ - "bne .sl_iloop \n" - - "add r5, r5, %[psiz] \n" /* start_address += plane_size */ - "subs r2, r2, #1 \n" /* planes-- */ - "bne .sl_oloop \n" - - "add %[addr],%[addr],%[bwid] \n" /* start_address += bwidth */ - "subs r4, r4, #1 \n" /* rows-- */ - "bne .sl_rloop \n" - : /* outputs */ - : /* inputs */ - [dpth]"r"(_gray_info.depth), - [high]"r"(_gray_info.height), - [bwid]"r"(_gray_info.bwidth), - [cols]"r"(_gray_info.bwidth - shift), - [psiz]"r"(_gray_info.plane_size), - [addr]"r"(_gray_info.plane_data + _gray_info.bwidth - shift), - [cnt] "r"(count) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6" - ); - } -} - -/* Scroll right */ -void gray_ub_scroll_right(int count) -{ - int shift, length; - unsigned char *ptr, *ptr_end; - - if ((unsigned) count >= (unsigned) _gray_info.width) - return; - - shift = count >> 3; - count &= 7; - - if (shift) - { - length = _gray_info.bwidth - shift; - ptr = _gray_info.plane_data; - ptr_end = ptr + _gray_info.plane_size; - - /* Scroll row by row to minimize flicker */ - do - { - unsigned char *ptr_row = ptr; - unsigned char *row_end = ptr_row - + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - do - { - _gray_rb->memmove(ptr_row + shift, ptr_row, length); - _gray_rb->memset(ptr_row, 0, shift); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - - ptr += _gray_info.bwidth; - } - while (ptr < ptr_end); - } - if (count) - { - asm ( - "mov r4, %[high] \n" /* rows = height */ - - ".sr_rloop: \n" /* repeat for every row */ - "mov r5, %[addr] \n" /* get start address */ - "mov r2, %[dpth] \n" /* planes = depth */ - - ".sr_oloop: \n" /* repeat for every bitplane */ - "mov r6, r5 \n" /* get start address */ - "mov r3, %[cols] \n" /* cols = col_count */ - "mov r1, #0 \n" /* fill with zero */ - - ".sr_iloop: \n" /* repeat for all cols */ - "ldrb r0, [r6] \n" /* get data byte */ - "orr r1, r0, r1, lsl #8 \n" /* combine w/ old data shifted to 2nd byte */ - "mov r0, r1, lsr %[cnt] \n" /* shift right */ - "strb r0, [r6], #1 \n" /* store data, increment addr */ - - "subs r3, r3, #1 \n" /* cols-- */ - "bne .sr_iloop \n" - - "add r5, r5, %[psiz] \n" /* start_address += plane_size */ - "subs r2, r2, #1 \n" /* planes-- */ - "bne .sr_oloop \n" - - "add %[addr],%[addr],%[bwid] \n" /* start_address += bwidth */ - "subs r4, r4, #1 \n" /* rows-- */ - "bne .sr_rloop \n" - : /* outputs */ - : /* inputs */ - [dpth]"r"(_gray_info.depth), - [high]"r"(_gray_info.height), - [bwid]"r"(_gray_info.bwidth), - [cols]"r"(_gray_info.bwidth - shift), - [psiz]"r"(_gray_info.plane_size), - [addr]"r"(_gray_info.plane_data + shift), - [cnt] "r"(count) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6" - ); - } -} - -/* Scroll up */ -void gray_ub_scroll_up(int count) -{ - long blockshift; - unsigned char *ptr, *ptr_end1, *ptr_end2; - - if ((unsigned) count >= (unsigned) _gray_info.height) - return; - - blockshift = _GRAY_MULUQ(_gray_info.bwidth, count); - ptr = _gray_info.plane_data; - ptr_end2 = ptr + _gray_info.plane_size; - ptr_end1 = ptr_end2 - blockshift; - /* Scroll row by row to minimize flicker */ - do - { - unsigned char *ptr_row = ptr; - unsigned char *row_end = ptr_row - + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - if (ptr < ptr_end1) - { - do - { - _gray_rb->memcpy(ptr_row, ptr_row + blockshift, - _gray_info.bwidth); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - else - { - do - { - _gray_rb->memset(ptr_row, 0, _gray_info.bwidth); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - - ptr += _gray_info.bwidth; - } - while (ptr < ptr_end2); -} - -/* Scroll down */ -void gray_ub_scroll_down(int count) -{ - long blockshift; - unsigned char *ptr, *ptr_end1, *ptr_end2; - - if ((unsigned) count >= (unsigned) _gray_info.height) - return; - - blockshift = _GRAY_MULUQ(_gray_info.bwidth, count); - ptr_end2 = _gray_info.plane_data; - ptr_end1 = ptr_end2 + blockshift; - ptr = ptr_end2 + _gray_info.plane_size; - /* Scroll row by row to minimize flicker */ - do - { - unsigned char *ptr_row, *row_end; - - ptr -= _gray_info.bwidth; - ptr_row = ptr; - row_end = ptr_row + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - - if (ptr >= ptr_end1) - { - do - { - _gray_rb->memcpy(ptr_row, ptr_row - blockshift, - _gray_info.bwidth); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - else - { - do - { - _gray_rb->memset(ptr_row, 0, _gray_info.bwidth); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - } - while (ptr > ptr_end2); -} -#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ - -/* Scroll left */ -void gray_ub_scroll_left(int count) -{ - int length; - unsigned char *ptr, *ptr_end; - - if ((unsigned) count >= (unsigned) _gray_info.width) - return; - - length = _gray_info.width - count; - ptr = _gray_info.plane_data; - ptr_end = ptr + _gray_info.plane_size; - - /* Scroll row by row to minimize flicker (pixel block rows) */ - do - { - unsigned char *ptr_row = ptr; - unsigned char *row_end = ptr_row - + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - do - { - _gray_rb->memmove(ptr_row, ptr_row + count, length); - _gray_rb->memset(ptr_row + length, 0, count); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - - ptr += _gray_info.width; - } - while (ptr < ptr_end); -} - -/* Scroll right */ -void gray_ub_scroll_right(int count) -{ - int length; - unsigned char *ptr, *ptr_end; - - if ((unsigned) count >= (unsigned) _gray_info.width) - return; - - length = _gray_info.width - count; - ptr = _gray_info.plane_data; - ptr_end = ptr + _gray_info.plane_size; - - /* Scroll row by row to minimize flicker (pixel block rows) */ - do - { - unsigned char *ptr_row = ptr; - unsigned char *row_end = ptr_row - + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - do - { - _gray_rb->memmove(ptr_row + count, ptr_row, length); - _gray_rb->memset(ptr_row, 0, count); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - - ptr += _gray_info.width; - } - while (ptr < ptr_end); -} - -/* Scroll up */ -void gray_ub_scroll_up(int count) -{ - int shift; - long blockshift = 0; - unsigned char *ptr, *ptr_end1, *ptr_end2; - - if ((unsigned) count >= (unsigned) _gray_info.height) - return; - - shift = count >> 3; - count &= 7; - - if (shift) - { - blockshift = _GRAY_MULUQ(_gray_info.width, shift); - ptr = _gray_info.plane_data; - ptr_end2 = ptr + _gray_info.plane_size; - ptr_end1 = ptr_end2 - blockshift; - /* Scroll row by row to minimize flicker (pixel block rows) */ - do - { - unsigned char *ptr_row = ptr; - unsigned char *row_end = ptr_row - + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - if (ptr < ptr_end1) - { - do - { - _gray_rb->memcpy(ptr_row, ptr_row + blockshift, - _gray_info.width); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - else - { - do - { - _gray_rb->memset(ptr_row, 0, _gray_info.width); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - - ptr += _gray_info.width; - } - while (ptr < ptr_end2); - } - if (count) - { -#if CONFIG_CPU == SH7034 - /* scroll column by column to minimize flicker */ - asm ( - "mov #0,r6 \n" /* x = 0 */ - "mova .su_shifttbl,r0 \n" /* calculate jump destination for */ - "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */ - "bra .su_cloop \n" /* skip table */ - "add r0,%[cnt] \n" - - ".align 2 \n" - ".su_shifttbl: \n" /* shift jump offset table */ - ".byte .su_shift0 - .su_shifttbl \n" - ".byte .su_shift1 - .su_shifttbl \n" - ".byte .su_shift2 - .su_shifttbl \n" - ".byte .su_shift3 - .su_shifttbl \n" - ".byte .su_shift4 - .su_shifttbl \n" - ".byte .su_shift5 - .su_shifttbl \n" - ".byte .su_shift6 - .su_shifttbl \n" - ".byte .su_shift7 - .su_shifttbl \n" - - ".su_cloop: \n" /* repeat for every column */ - "mov %[addr],r2 \n" /* get start address */ - "mov #0,r3 \n" /* current_plane = 0 */ - - ".su_oloop: \n" /* repeat for every bitplane */ - "mov r2,r4 \n" /* get start address */ - "mov #0,r5 \n" /* current_row = 0 */ - "mov #0,r1 \n" /* fill with zero */ - - ".su_iloop: \n" /* repeat for all rows */ - "sub %[wide],r4 \n" /* address -= width */ - "mov.b @r4,r0 \n" /* get data byte */ - "shll8 r1 \n" /* old data to 2nd byte */ - "extu.b r0,r0 \n" /* extend unsigned */ - "or r1,r0 \n" /* combine old data */ - "jmp @%[cnt] \n" /* jump into shift "path" */ - "extu.b r0,r1 \n" /* store data for next round */ - - ".su_shift6: \n" /* shift right by 0..7 bits */ - "shll2 r0 \n" - "bra .su_shift0 \n" - "shlr8 r0 \n" - ".su_shift4: \n" - "shlr2 r0 \n" - ".su_shift2: \n" - "bra .su_shift0 \n" - "shlr2 r0 \n" - ".su_shift7: \n" - "shlr2 r0 \n" - ".su_shift5: \n" - "shlr2 r0 \n" - ".su_shift3: \n" - "shlr2 r0 \n" - ".su_shift1: \n" - "shlr r0 \n" - ".su_shift0: \n" - - "mov.b r0,@r4 \n" /* store data */ - "add #1,r5 \n" /* current_row++ */ - "cmp/hi r5,%[rows] \n" /* current_row < bheight - shift ? */ - "bt .su_iloop \n" - - "add %[psiz],r2 \n" /* start_address += plane_size */ - "add #1,r3 \n" /* current_plane++ */ - "cmp/hi r3,%[dpth] \n" /* current_plane < depth ? */ - "bt .su_oloop \n" - - "add #1,%[addr] \n" /* start_address++ */ - "add #1,r6 \n" /* x++ */ - "cmp/hi r6,%[wide] \n" /* x < width ? */ - "bt .su_cloop \n" - : /* outputs */ - : /* inputs */ - [dpth]"r"(_gray_info.depth), - [addr]"r"(_gray_info.plane_data + _gray_info.plane_size - blockshift), - [wide]"r"(_gray_info.width), - [rows]"r"(_gray_info.bheight - shift), - [psiz]"r"(_gray_info.plane_size), - [cnt] "r"(count) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6" - ); -#elif defined(CPU_COLDFIRE) - /* scroll column by column to minimize flicker */ - asm ( - "move.l %[wide],%%d4\n" /* columns = width */ - - ".su_cloop: \n" /* repeat for every column */ - "move.l %[addr],%%a0\n" /* get start address */ - "move.l %[dpth],%%d2\n" /* planes = depth */ - - ".su_oloop: \n" /* repeat for every bitplane */ - "move.l %%a0,%%a1 \n" /* get start address */ - "move.l %[rows],%%d3\n" /* rows = row_count */ - "clr.l %%d1 \n" /* fill with zero */ - - ".su_iloop: \n" /* repeat for all rows */ - "sub.l %[wide],%%a1\n" /* address -= width */ - - "clr.l %%d0 \n" - "move.b (%%a1),%%d0 \n" /* get data byte */ - "lsl.l #8,%%d1 \n" /* old data to 2nd byte */ - "or.l %%d1,%%d0 \n" /* combine old data */ - "move.l %%d0,%%d1 \n" /* keep data for next round */ - "lsr.l %[cnt],%%d0 \n" /* shift right */ - "move.b %%d0,(%%a1) \n" /* store data */ - - "subq.l #1,%%d3 \n" /* rows-- */ - "bne.b .su_iloop \n" - - "add.l %[psiz],%%a0\n" /* start_address += plane_size */ - "subq.l #1,%%d2 \n" /* planes-- */ - "bne.b .su_oloop \n" - - "addq.l #1,%[addr] \n" /* start_address++ */ - "subq.l #1,%%d4 \n" /* columns-- */ - "bne.b .su_cloop \n" - : /* outputs */ - : /* inputs */ - [psiz]"r"(_gray_info.plane_size), - [dpth]"r"(_gray_info.depth), - [wide]"r"(_gray_info.width), - [rows]"r"(_gray_info.bheight - shift), - [addr]"a"(_gray_info.plane_data + _gray_info.plane_size - blockshift), - [cnt] "d"(count) - : /* clobbers */ - "a0", "a1", "d0", "d1", "d2", "d3", "d4" - ); -#endif - } -} - -/* Scroll down */ -void gray_ub_scroll_down(int count) -{ - int shift; - long blockshift = 0; - unsigned char *ptr, *ptr_end1, *ptr_end2; - - if ((unsigned) count >= (unsigned) _gray_info.height) - return; - - shift = count >> 3; - count &= 7; - - if (shift) - { - blockshift = _GRAY_MULUQ(_gray_info.width, shift); - ptr_end2 = _gray_info.plane_data; - ptr_end1 = ptr_end2 + blockshift; - ptr = ptr_end2 + _gray_info.plane_size; - /* Scroll row by row to minimize flicker (pixel block rows) */ - do - { - unsigned char *ptr_row, *row_end; - - ptr -= _gray_info.width; - ptr_row = ptr; - row_end = ptr_row + _GRAY_MULUQ(_gray_info.plane_size, _gray_info.depth); - - if (ptr >= ptr_end1) - { - do - { - _gray_rb->memcpy(ptr_row, ptr_row - blockshift, - _gray_info.width); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - else - { - do - { - _gray_rb->memset(ptr_row, 0, _gray_info.width); - ptr_row += _gray_info.plane_size; - } - while (ptr_row < row_end); - } - } - while (ptr > ptr_end2); - } - if (count) - { -#if CONFIG_CPU == SH7034 - /* scroll column by column to minimize flicker */ - asm ( - "mov #0,r6 \n" /* x = 0 */ - "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */ - "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */ - "bra .sd_cloop \n" /* skip table */ - "add r0,%[cnt] \n" - - ".align 2 \n" - ".sd_shifttbl: \n" /* shift jump offset table */ - ".byte .sd_shift0 - .sd_shifttbl \n" - ".byte .sd_shift1 - .sd_shifttbl \n" - ".byte .sd_shift2 - .sd_shifttbl \n" - ".byte .sd_shift3 - .sd_shifttbl \n" - ".byte .sd_shift4 - .sd_shifttbl \n" - ".byte .sd_shift5 - .sd_shifttbl \n" - ".byte .sd_shift6 - .sd_shifttbl \n" - ".byte .sd_shift7 - .sd_shifttbl \n" - - ".sd_cloop: \n" /* repeat for every column */ - "mov %[addr],r2 \n" /* get start address */ - "mov #0,r3 \n" /* current_plane = 0 */ - - ".sd_oloop: \n" /* repeat for every bitplane */ - "mov r2,r4 \n" /* get start address */ - "mov #0,r5 \n" /* current_row = 0 */ - "mov #0,r1 \n" /* fill with zero */ - - ".sd_iloop: \n" /* repeat for all rows */ - "shlr8 r1 \n" /* shift right to get residue */ - "mov.b @r4,r0 \n" /* get data byte */ - "jmp @%[cnt] \n" /* jump into shift "path" */ - "extu.b r0,r0 \n" /* extend unsigned */ - - ".sd_shift6: \n" /* shift left by 0..7 bits */ - "shll8 r0 \n" - "bra .sd_shift0 \n" - "shlr2 r0 \n" - ".sd_shift4: \n" - "shll2 r0 \n" - ".sd_shift2: \n" - "bra .sd_shift0 \n" - "shll2 r0 \n" - ".sd_shift7: \n" - "shll2 r0 \n" - ".sd_shift5: \n" - "shll2 r0 \n" - ".sd_shift3: \n" - "shll2 r0 \n" - ".sd_shift1: \n" - "shll r0 \n" - ".sd_shift0: \n" - - "or r0,r1 \n" /* combine with last residue */ - "mov.b r1,@r4 \n" /* store data */ - "add %[wide],r4 \n" /* address += width */ - "add #1,r5 \n" /* current_row++ */ - "cmp/hi r5,%[rows] \n" /* current_row < bheight - shift ? */ - "bt .sd_iloop \n" - - "add %[psiz],r2 \n" /* start_address += plane_size */ - "add #1,r3 \n" /* current_plane++ */ - "cmp/hi r3,%[dpth] \n" /* current_plane < depth ? */ - "bt .sd_oloop \n" - - "add #1,%[addr] \n" /* start_address++ */ - "add #1,r6 \n" /* x++ */ - "cmp/hi r6,%[wide] \n" /* x < width ? */ - "bt .sd_cloop \n" - : /* outputs */ - : /* inputs */ - [dpth]"r"(_gray_info.depth), - [addr]"r"(_gray_info.plane_data + blockshift), - [wide]"r"(_gray_info.width), - [rows]"r"(_gray_info.bheight - shift), - [psiz]"r"(_gray_info.plane_size), - [cnt] "r"(count) - : /* clobbers */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6" - ); -#elif defined(CPU_COLDFIRE) - /* scroll column by column to minimize flicker */ - asm ( - "move.l %[wide],%%d4\n" /* columns = width */ - - ".sd_cloop: \n" /* repeat for every column */ - "move.l %[addr],%%a0\n" /* get start address */ - "move.l %[dpth],%%d2\n" /* planes = depth */ - - ".sd_oloop: \n" /* repeat for every bitplane */ - "move.l %%a0,%%a1 \n" /* get start address */ - "move.l %[rows],%%d3\n" /* rows = row_count */ - "clr.l %%d1 \n" /* fill with zero */ - - ".sd_iloop: \n" /* repeat for all rows */ - "lsr.l #8,%%d1 \n" /* shift right to get residue */ - "clr.l %%d0 \n" - "move.b (%%a1),%%d0 \n" /* get data byte */ - "lsl.l %[cnt],%%d0 \n" - "or.l %%d0,%%d1 \n" /* combine with last residue */ - "move.b %%d1,(%%a1) \n" /* store data */ - - "add.l %[wide],%%a1\n" /* address += width */ - "subq.l #1,%%d3 \n" /* rows-- */ - "bne.b .sd_iloop \n" - - "add.l %[psiz],%%a0\n" /* start_address += plane_size */ - "subq.l #1,%%d2 \n" /* planes-- */ - "bne.b .sd_oloop \n" - - "addq.l #1,%[addr] \n" /* start_address++ */ - "subq.l #1,%%d4 \n" /* columns-- */ - "bne.b .sd_cloop \n" - : /* outputs */ - : /* inputs */ - [dpth]"r"(_gray_info.depth), - [wide]"r"(_gray_info.width), - [rows]"r"(_gray_info.bheight - shift), - [psiz]"r"(_gray_info.plane_size), - [addr]"a"(_gray_info.plane_data + blockshift), - [cnt] "d"(count) - : /* clobbers */ - "a0", "a1", "d0", "d1", "d2", "d3", "d4" - ); -#endif - } -} -#endif /* LCD_PIXELFORMAT */ - -#endif /* !SIMULATOR */ - -#endif /* HAVE_LCD_BITMAP */