23d9812273
struct plugin_api *rb is declared in PLUGIN_HEADER, and pointed to by __header.api the loader uses this pointer to initialize rb before calling entry_point entry_point is no longer passed a pointer to the plugin API all plugins, and pluginlib functions, are modified to refer to the global rb pluginlib functions which only served to copy the API pointer are removed git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19776 a1c6a512-1295-4272-9138-f99709370657
382 lines
14 KiB
C
382 lines
14 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Additional LCD routines not present in the rockbox core
|
|
* Drawing functions
|
|
*
|
|
* Copyright (C) 2005 Jens Arnold
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* 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 "xlcd.h"
|
|
|
|
/* sort the given coordinates by increasing x value */
|
|
static void sort_points_by_increasing_x(int* x1, int* y1,
|
|
int* x2, int* y2,
|
|
int* x3, int* y3)
|
|
{
|
|
int x, y;
|
|
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 */
|
|
}
|
|
}
|
|
|
|
#define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
|
|
sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
|
|
|
|
/* draw a filled triangle, using horizontal lines for speed */
|
|
static void xlcd_filltriangle_horizontal(struct screen* display,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
int x3, int y3)
|
|
{
|
|
long fp_x1, fp_x2, fp_dx1, fp_dx2;
|
|
int y;
|
|
sort_points_by_increasing_y(&x1, &y1, &x2, &y2, &x3, &y3);
|
|
|
|
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++)
|
|
{
|
|
display->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++)
|
|
{
|
|
display->hline(fp_x1 >> 16, fp_x2 >> 16, y);
|
|
fp_x1 += fp_dx1;
|
|
fp_x2 += fp_dx2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw a filled triangle, using vertical lines for speed */
|
|
static void xlcd_filltriangle_vertical(struct screen* display,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
int x3, int y3)
|
|
{
|
|
long fp_y1, fp_y2, fp_dy1, fp_dy2;
|
|
int x;
|
|
sort_points_by_increasing_x(&x1, &y1, &x2, &y2, &x3, &y3);
|
|
|
|
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++)
|
|
{
|
|
display->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++)
|
|
{
|
|
display->vline(x, fp_y1 >> 16, fp_y2 >> 16);
|
|
fp_y1 += fp_dy1;
|
|
fp_y2 += fp_dy2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void xlcd_filltriangle(int x1, int y1,
|
|
int x2, int y2,
|
|
int x3, int y3)
|
|
{
|
|
/* default is main screen */
|
|
xlcd_filltriangle_screen(rb->screens[SCREEN_MAIN],
|
|
x1, y1, x2, y2, x3, y3);
|
|
}
|
|
|
|
void xlcd_filltriangle_screen(struct screen* display,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
int x3, int y3)
|
|
{
|
|
if(display->pixel_format==HORIZONTAL_PACKING || display->depth>=8)
|
|
xlcd_filltriangle_horizontal(display, x1, y1, x2, y2, x3, y3);
|
|
else
|
|
xlcd_filltriangle_vertical(display, x1, y1, x2, y2, x3, y3);
|
|
}
|
|
|
|
#if LCD_DEPTH >= 8
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
static const fb_data graylut[256] = {
|
|
#if LCD_PIXELFORMAT == RGB565
|
|
0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841,
|
|
0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082,
|
|
0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3,
|
|
0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104,
|
|
0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945,
|
|
0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186,
|
|
0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7,
|
|
0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208,
|
|
0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49,
|
|
0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a,
|
|
0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab,
|
|
0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec,
|
|
0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d,
|
|
0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d,
|
|
0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae,
|
|
0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef,
|
|
0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430,
|
|
0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71,
|
|
0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2,
|
|
0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3,
|
|
0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534,
|
|
0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75,
|
|
0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6,
|
|
0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7,
|
|
0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638,
|
|
0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79,
|
|
0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba,
|
|
0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb,
|
|
0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c,
|
|
0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d,
|
|
0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be,
|
|
0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff
|
|
#elif LCD_PIXELFORMAT == RGB565SWAPPED
|
|
0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108,
|
|
0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210,
|
|
0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318,
|
|
0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421,
|
|
0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529,
|
|
0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631,
|
|
0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739,
|
|
0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842,
|
|
0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a,
|
|
0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52,
|
|
0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a,
|
|
0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62,
|
|
0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b,
|
|
0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b,
|
|
0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73,
|
|
0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b,
|
|
0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084,
|
|
0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c,
|
|
0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294,
|
|
0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c,
|
|
0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5,
|
|
0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad,
|
|
0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5,
|
|
0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd,
|
|
0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6,
|
|
0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce,
|
|
0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6,
|
|
0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde,
|
|
0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7,
|
|
0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def,
|
|
0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7,
|
|
0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff
|
|
#endif /* LCD_PIXELFORMAT */
|
|
};
|
|
#endif /* HAVE_LCD_COLOR */
|
|
|
|
/* Draw a partial greyscale bitmap, canonical 8 bit format */
|
|
void xlcd_gray_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;
|
|
fb_data *dst;
|
|
|
|
/* nothing to draw? */
|
|
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_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 > LCD_WIDTH)
|
|
width = LCD_WIDTH - x;
|
|
if (y + height > LCD_HEIGHT)
|
|
height = LCD_HEIGHT - y;
|
|
|
|
src += stride * src_y + src_x; /* move starting point */
|
|
src_end = src + stride * height;
|
|
dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
|
|
|
|
do
|
|
{
|
|
const unsigned char *src_row = src;
|
|
const unsigned char *row_end = src_row + width;
|
|
fb_data *dst_row = dst;
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
do
|
|
*dst_row++ = graylut[*src_row++];
|
|
while (src_row < row_end);
|
|
#endif
|
|
|
|
src += stride;
|
|
dst += LCD_WIDTH;
|
|
}
|
|
while (src < src_end);
|
|
}
|
|
|
|
/* Draw a full greyscale bitmap, canonical 8 bit format */
|
|
void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width,
|
|
int height)
|
|
{
|
|
xlcd_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
|
|
}
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
/* Draw a partial colour bitmap, canonical 24 bit RGB format */
|
|
void xlcd_color_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;
|
|
fb_data *dst;
|
|
|
|
/* nothing to draw? */
|
|
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_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 > LCD_WIDTH)
|
|
width = LCD_WIDTH - x;
|
|
if (y + height > LCD_HEIGHT)
|
|
height = LCD_HEIGHT - y;
|
|
|
|
src += 3 * (stride * src_y + src_x); /* move starting point */
|
|
src_end = src + 3 * stride * height;
|
|
dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
|
|
|
|
do
|
|
{
|
|
const unsigned char *src_row = src;
|
|
const unsigned char *row_end = src_row + 3 * width;
|
|
fb_data *dst_row = dst;
|
|
|
|
do
|
|
{ /* only RGB565 and RGB565SWAPPED so far */
|
|
unsigned red = 31 * (*src_row++) + 127;
|
|
unsigned green = 63 * (*src_row++) + 127;
|
|
unsigned blue = 31 * (*src_row++) + 127;
|
|
|
|
red = (red + (red >> 8)) >> 8; /* approx red /= 255: */
|
|
green = (green + (green >> 8)) >> 8; /* approx green /= 255: */
|
|
blue = (blue + (blue >> 8)) >> 8; /* approx blue /= 255: */
|
|
|
|
#if LCD_PIXELFORMAT == RGB565
|
|
*dst_row++ = (red << 11) | (green << 5) | blue;
|
|
#elif LCD_PIXELFORMAT == RGB565SWAPPED
|
|
*dst_row++ = swap16((red << 11) | (green << 5) | blue);
|
|
#endif
|
|
}
|
|
while (src_row < row_end);
|
|
|
|
src += 3 * stride;
|
|
dst += LCD_WIDTH;
|
|
}
|
|
while (src < src_end);
|
|
}
|
|
|
|
/* Draw a full colour bitmap, canonical 24 bit RGB format */
|
|
void xlcd_color_bitmap(const unsigned char *src, int x, int y, int width,
|
|
int height)
|
|
{
|
|
xlcd_color_bitmap_part(src, 0, 0, width, x, y, width, height);
|
|
}
|
|
#endif /* HAVE_LCD_COLOR */
|
|
|
|
#endif /* LCD_DEPTH >= 8 */
|
|
|
|
#endif /* HAVE_LCD_BITMAP */
|
|
|