Hey all, I had an idea which I mentioned in IRC which would allow the skin engine (or anything) to draw (using the existing lcd api) into a different lcd framebuffer which could then be used as the backdrop image for text/whatever which is finally drawn to the LCD. The problem is though that every lcd driver currently uses a static array as the lcd_framebuffer instead of a nice pointer which can be changed.
http://www.rockbox.org/tracker/task/11615 started working on changing this to allow dynamic screen sizes (for RaaA) and attached is a stripped down copy of that which changes sdl,android and the ipod video drivers to use a pointer (which currently just points to the array anyway) as a proof-of-concept/base. That patch only changes lcd_framebuffer for targets with HAVE_DYNAMIC_LCD_SIZE but for my plan to work I need all drivers to change. That patch will then be able to build on this quite easily. Now, is this something which people would object to? Jonathan P.S Being able to use different images for viewport backdrops has been requests quite a few times, and now we can draw images semi transparent I think having the AA image as a backdrop would look sweet (or at least be interesting!)
diff --git a/apps/plugin.c b/apps/plugin.c index b9c2e7c..abc03c0 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -145,7 +145,7 @@ static int close_wrapper(int fd); static int creat_wrapper(const char *pathname, mode_t mode); #endif -static const struct plugin_api rockbox_api = { +static struct plugin_api rockbox_api = { /* FIXME! */ /* lcd */ #ifdef HAVE_LCD_CONTRAST @@ -170,7 +170,7 @@ static const struct plugin_api rockbox_api = { lcd_icon, lcd_double_height, #else - &lcd_framebuffer[0][0], + NULL, lcd_update_rect, lcd_set_drawmode, lcd_get_drawmode, @@ -863,6 +863,7 @@ int plugin_load(const char* plugin, const void* parameter) plugin_size = 0; #endif + rockbox_api.lcd_framebuffer = lcd_framebuffer; *(p_hdr->api) = &rockbox_api; lcd_clear_display(); diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 28c3285..60d8b57 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -46,9 +46,9 @@ enum fill_opt { }; /*** globals ***/ -fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] - IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); - +fb_data _lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] +IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); +fb_data *lcd_framebuffer = _lcd_framebuffer; static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; @@ -203,7 +203,7 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) /*** low-level drawing functions ***/ -#define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) +#define LCDADDR(x, y) (lcd_framebuffer + y * LCD_WIDTH + x) static void ICODE_ATTR setpixel(fb_data *address) { @@ -247,7 +247,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (long)backdrop - (long)&lcd_framebuffer[0][0]; + lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop; } else diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 76b8b09..8d50eb6 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -408,7 +408,7 @@ static inline unsigned lcd_color_to_native(unsigned color) #define LCD_FBHEIGHT LCD_HEIGHT #endif /* The actual framebuffer */ -extern fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; +extern fb_data *lcd_framebuffer; /** Port-specific functions. Enable in port config file. **/ #ifdef HAVE_REMOTE_LCD_AS_MAIN diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h index 0fe6fe4..df8f6b0 100644 --- a/firmware/export/scroll_engine.h +++ b/firmware/export/scroll_engine.h @@ -68,9 +68,12 @@ struct scrollinfo struct scroll_screen_info { - struct scrollinfo * const scroll; + struct scrollinfo * scroll; const int num_scroll; /* number of scrollable lines (also number of scroll structs) */ int lines; /* Number of currently scrolling lines */ +#ifdef HAVE_DYNAMIC_LCD_SIZE + int line_size; /* max chars storable on each scroll line */ +#endif long ticks; /* # of ticks between updates*/ long delay; /* ticks delay before start */ int bidir_limit; /* percent */ diff --git a/firmware/screendump.c b/firmware/screendump.c index 30b9539..c886459 100644 --- a/firmware/screendump.c +++ b/firmware/screendump.c @@ -53,25 +53,44 @@ #define BMP_DATASIZE (DUMP_BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES)) #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE) -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+LCD_SPLIT_LINES), /* Height in pixels */ - 0x01, 0x00, /* Number of planes (always 1) */ - LE16_CONST(DUMP_BMP_BPP), /* Bits per pixel 1/4/8/16/24 */ - LE32_CONST(BMP_COMPRESSION),/* Compression mode */ - 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 */ - +#define ASSIGN_LE32(dst, x) memcpy((dst), (unsigned char[4]){LE32_CONST(x)}, 4); + +static struct { + const unsigned char header[2]; + unsigned char file_size[4]; + const unsigned char reserved[4]; + unsigned char header_size[4]; + const unsigned char second_header_size[4]; + unsigned char lcd_width[4]; + unsigned char lcd_height[4]; + const unsigned char nr_planes[2]; + const unsigned char bpp[2]; + const unsigned char compression[4]; + unsigned char data_size[4]; + const unsigned char horizontal_resolution[4]; + const unsigned char vertical_resolution[4]; + const unsigned char nr_used_colors[4]; + const unsigned char nr_important_colors[4]; + const unsigned char colors[BMP_NUMCOLORS*4]; +} __attribute__((__packed__)) bmpheader = { + {0x42, 0x4d}, /* 'BM' */ + {}, /* Total file size */ + {0x00, 0x00, 0x00, 0x00}, /* Reserved */ + {}, /* Offset to start of pixel data */ + + {0x28, 0x00, 0x00, 0x00}, /* Size of (2nd) header */ + {}, /* Width in pixels */ + {}, /* Height in pixels */ + {0x01, 0x00}, /* Number of planes (always 1) */ + {LE16_CONST(DUMP_BMP_BPP)}, /* Bits per pixel 1/4/8/16/24 */ + {LE32_CONST(BMP_COMPRESSION)},/* Compression mode */ + {}, /* 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 */ + + { #if LCD_DEPTH == 1 #ifdef HAVE_NEGATIVE_LCD BMP_COLOR(LCD_BL_DARKCOLOR), @@ -94,6 +113,7 @@ static const unsigned char bmpheader[] = 0xe0, 0x07, 0x00, 0x00, /* green bitfield mask */ 0x1f, 0x00, 0x00, 0x00, /* blue bitfield mask */ #endif + } }; static void (*screen_dump_hook)(int fh) = NULL; @@ -136,7 +156,12 @@ void screen_dump(void) } else { - write(fd, bmpheader, sizeof(bmpheader)); + ASSIGN_LE32(bmpheader.file_size, BMP_TOTALSIZE); + ASSIGN_LE32(bmpheader.header_size, BMP_HEADERSIZE); + ASSIGN_LE32(bmpheader.lcd_width, LCD_WIDTH); + ASSIGN_LE32(bmpheader.lcd_height, LCD_HEIGHT+LCD_SPLIT_LINES); + ASSIGN_LE32(bmpheader.data_size, BMP_DATASIZE); + write(fd, &bmpheader, sizeof(bmpheader)); /* BMP image goes bottom up */ for (y = LCD_HEIGHT - 1; y >= 0; y--) @@ -214,8 +239,7 @@ void screen_dump(void) #endif #elif LCD_DEPTH == 16 dst_end = dst + LCD_WIDTH; - src = lcd_framebuffer[y]; - + src = &lcd_framebuffer[y]; do { #if (LCD_PIXELFORMAT == RGB565SWAPPED) diff --git a/firmware/target/arm/ipod/video/lcd-video.c b/firmware/target/arm/ipod/video/lcd-video.c index c499e9f..db7f35e 100644 --- a/firmware/target/arm/ipod/video/lcd-video.c +++ b/firmware/target/arm/ipod/video/lcd-video.c @@ -410,7 +410,7 @@ void lcd_update_rect(int x, int y, int width, int height) /* Prevent the tick from triggering BCM updates while we're writing. */ lcd_block_tick(); - addr = &lcd_framebuffer[y][x]; + addr = (lcd_framebuffer + y * LCD_WIDTH + x); bcmaddr = BCMA_CMDPARAM + (LCD_WIDTH*2) * y + (x << 1); if (width == LCD_WIDTH) diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c index abde721..64597ce 100644 --- a/firmware/target/hosted/android/lcd-android.c +++ b/firmware/target/hosted/android/lcd-android.c @@ -87,6 +87,19 @@ void connect_with_java(JNIEnv* env, jobject fb_instance) */ void lcd_init_device(void) { +#ifdef HAVE_DYNAMIC_LCD_SIZE + jmethodID getResolution = (*env_ptr)->GetMethodID(env_ptr, RockboxService_class, "getResolution", "()[I"); + jintArray resolution = (jintArray) (*env_ptr)->CallObjectMethod(env_ptr, RockboxService_instance, getResolution); + jint *resolutionElements = (*env_ptr)->GetIntArrayElements(env_ptr, resolution, NULL); + + lcd_width = resolutionElements[0]; + lcd_height = resolutionElements[1]; + (*env_ptr)->ReleaseIntArrayElements(env_ptr, resolution, resolutionElements, 0); +#else + lcd_height = LCD_HEIGHT; + lcd_width = LCD_WIDTH; +#endif + lcd_framebuffer = malloc(sizeof(fb_data) * lcd_width * lcd_height); } void lcd_update(void) @@ -190,6 +203,8 @@ void lcd_yuv_set_options(unsigned options) (void)options; } +#define LCDADDR(x, y) (lcd_framebuffer + y * LCD_WIDTH + x) + /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv in the core */ void lcd_blit_yuv(unsigned char * const src[3], @@ -205,13 +220,13 @@ void lcd_blit_yuv(unsigned char * const src[3], width &= ~1; linecounter = height >> 1; -#if LCD_WIDTH >= LCD_HEIGHT - dst = &lcd_framebuffer[y][x]; - row_end = dst + width; -#else - dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1]; + if (LCD_WIDTH >= LCD_HEIGHT) { + dst = LCDADDR(y, x); + row_end = dst + width; + } else { + dst = LCDADDR(x, LCD_WIDTH - y - 1); row_end = dst + LCD_WIDTH * width; -#endif + } z = stride * src_y; ysrc = src[0] + z + src_x; @@ -250,11 +265,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; y = YFAC*(*ysrc++ - 16); r = y + rv; @@ -270,11 +284,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; } while (dst < row_end); @@ -282,13 +295,13 @@ void lcd_blit_yuv(unsigned char * const src[3], usrc -= width >> 1; vsrc -= width >> 1; -#if LCD_WIDTH >= LCD_HEIGHT - row_end += LCD_WIDTH; - dst += LCD_WIDTH - width; -#else - row_end -= 1; - dst -= LCD_WIDTH*width + 1; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) { + row_end += LCD_WIDTH; + dst += LCD_WIDTH - width; + } else { + row_end -= 1; + dst -= LCD_WIDTH*width + 1; + } do { @@ -315,11 +328,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; y = YFAC*(*ysrc++ - 16); r = y + rv; @@ -335,11 +347,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; } while (dst < row_end); @@ -347,19 +358,18 @@ void lcd_blit_yuv(unsigned char * const src[3], usrc += stride >> 1; vsrc += stride >> 1; -#if LCD_WIDTH >= LCD_HEIGHT - row_end += LCD_WIDTH; - dst += LCD_WIDTH - width; -#else - row_end -= 1; - dst -= LCD_WIDTH*width + 1; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) { + row_end += LCD_WIDTH; + dst += LCD_WIDTH - width; + } else { + row_end -= 1; + dst -= LCD_WIDTH*width + 1; + } } while (--linecounter > 0); -#if LCD_WIDTH >= LCD_HEIGHT - lcd_update_rect(x, y, width, height); -#else - lcd_update_rect(LCD_WIDTH - y - height, x, height, width); -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + lcd_update_rect(x, y, width, height); + else + lcd_update_rect(LCD_WIDTH - y - height, x, height, width); } diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c index 4c29692..06d6522 100644 --- a/firmware/target/hosted/sdl/lcd-bitmap.c +++ b/firmware/target/hosted/sdl/lcd-bitmap.c @@ -88,6 +88,8 @@ unsigned long (*lcd_ex_getpixel)(int, int) = NULL; static const unsigned char colorindex[4] = {128, 85, 43, 0}; #endif +#define LCD_PIXEL(x, y) (lcd_framebuffer + y * LCD_WIDTH + x) + static unsigned long get_lcd_pixel(int x, int y) { #if LCD_DEPTH == 1 @@ -113,7 +115,7 @@ static unsigned long get_lcd_pixel(int x, int y) #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE return *(&lcd_framebuffer[0][0]+LCD_HEIGHT*x+y); #else - return lcd_framebuffer[y][x]; + return *LCD_PIXEL(x, y); #endif #endif #endif @@ -176,6 +178,8 @@ void sim_backlight(int value) /* initialise simulator lcd driver */ void lcd_init_device(void) { + lcd_framebuffer = malloc(LCD_HEIGHT * LCD_WIDTH * sizeof(fb_data)); + #if LCD_DEPTH == 16 lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, SIM_LCD_WIDTH * display_zoom, @@ -269,13 +273,16 @@ void lcd_blit_yuv(unsigned char * const src[3], width &= ~1; linecounter = height >> 1; -#if LCD_WIDTH >= LCD_HEIGHT - dst = &lcd_framebuffer[y][x]; - row_end = dst + width; -#else - dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1]; - row_end = dst + LCD_WIDTH * width; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + { + dst = LCD_PIXEL(x, y); + row_end = dst + width; + } + else + { + dst = LCD_PIXEL(x, LCD_WIDTH - y - 1); + row_end = dst + LCD_WIDTH * width; + } z = stride * src_y; ysrc = src[0] + z + src_x; @@ -314,11 +321,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; y = YFAC*(*ysrc++ - 16); r = y + rv; @@ -334,11 +340,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; } while (dst < row_end); @@ -346,13 +351,16 @@ void lcd_blit_yuv(unsigned char * const src[3], usrc -= width >> 1; vsrc -= width >> 1; -#if LCD_WIDTH >= LCD_HEIGHT - row_end += LCD_WIDTH; - dst += LCD_WIDTH - width; -#else - row_end -= 1; - dst -= LCD_WIDTH*width + 1; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + { + row_end += LCD_WIDTH; + dst += LCD_WIDTH - width; + } + else + { + row_end -= 1; + dst -= LCD_WIDTH*width + 1; + } do { @@ -379,11 +387,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; y = YFAC*(*ysrc++ - 16); r = y + rv; @@ -399,11 +406,10 @@ void lcd_blit_yuv(unsigned char * const src[3], *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9); -#if LCD_WIDTH >= LCD_HEIGHT - dst++; -#else - dst += LCD_WIDTH; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + dst++; + else + dst += LCD_WIDTH; } while (dst < row_end); @@ -411,20 +417,22 @@ void lcd_blit_yuv(unsigned char * const src[3], usrc += stride >> 1; vsrc += stride >> 1; -#if LCD_WIDTH >= LCD_HEIGHT - row_end += LCD_WIDTH; - dst += LCD_WIDTH - width; -#else - row_end -= 1; - dst -= LCD_WIDTH*width + 1; -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + { + row_end += LCD_WIDTH; + dst += LCD_WIDTH - width; + } + else + { + row_end -= 1; + dst -= LCD_WIDTH*width + 1; + } } while (--linecounter > 0); -#if LCD_WIDTH >= LCD_HEIGHT - lcd_update_rect(x, y, width, height); -#else - lcd_update_rect(LCD_WIDTH - y - height, x, height, width); -#endif + if (LCD_WIDTH >= LCD_HEIGHT) + lcd_update_rect(x, y, width, height); + else + lcd_update_rect(LCD_WIDTH - y - height, x, height, width); } #endif /* HAVE_LCD_COLOR */