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 */

Reply via email to