diff options
Diffstat (limited to 'minui/graphics.cpp')
-rw-r--r-- | minui/graphics.cpp | 196 |
1 files changed, 169 insertions, 27 deletions
diff --git a/minui/graphics.cpp b/minui/graphics.cpp index c0eea9e38..93b70da25 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -31,7 +31,12 @@ #include <time.h> +#ifdef BOARD_USE_CUSTOM_RECOVERY_FONT +#include BOARD_USE_CUSTOM_RECOVERY_FONT +#else #include "font_10x18.h" +#endif + #include "minui.h" #include "graphics.h" @@ -52,6 +57,10 @@ static unsigned char gr_current_r = 255; static unsigned char gr_current_g = 255; static unsigned char gr_current_b = 255; static unsigned char gr_current_a = 255; +static unsigned char rgb_555[2]; +static unsigned char gr_current_r5 = 31; +static unsigned char gr_current_g5 = 63; +static unsigned char gr_current_b5 = 31; static GRSurface* gr_draw = NULL; @@ -71,6 +80,30 @@ void gr_font_size(int *x, int *y) *y = gr_font->cheight; } +void blend_16bpp(unsigned char* px, unsigned r5, unsigned g5, unsigned b5, unsigned char a) +{ + unsigned char orig[2]; + orig[0] = px[0]; + orig[1] = px[1]; + + /* This code is a little easier to read + unsigned oldred = (orig[1] >> 3); + unsigned oldgreen = (((orig[0] >> 5) << 3) + (orig[1] & 0x7)); + unsigned oldblue = (orig[0] & 0x1F); + + unsigned newred = (oldred * (255-a) + r5 * a) / 255; + unsigned newgreen = (oldgreen * (255-a) + g5 * a) / 255; + unsigned newblue = (oldblue * (255-a) + b5 * a) / 255; + */ + + unsigned newred = ((orig[1] >> 3) * (255-a) + r5 * a) / 255; + unsigned newgreen = ((((orig[0] >> 5) << 3) + (orig[1] & 0x7)) * (255-a) + g5 * a) / 255; + unsigned newblue = ((orig[0] & 0x1F) * (255-a) + b5 * a) / 255; + + *px++ = (newgreen << 5) + (newblue); + *px++ = (newred << 3) + (newgreen >> 3); +} + static void text_blend(unsigned char* src_p, int src_row_bytes, unsigned char* dst_p, int dst_row_bytes, int width, int height) @@ -82,20 +115,30 @@ static void text_blend(unsigned char* src_p, int src_row_bytes, unsigned char a = *sx++; if (gr_current_a < 255) a = ((int)a * gr_current_a) / 255; if (a == 255) { - *px++ = gr_current_r; - *px++ = gr_current_g; - *px++ = gr_current_b; - px++; + if (gr_draw->pixel_bytes == 2) { + *px++ = rgb_555[0]; + *px++ = rgb_555[1]; + } else { + *px++ = gr_current_r; + *px++ = gr_current_g; + *px++ = gr_current_b; + px++; + } } else if (a > 0) { - *px = (*px * (255-a) + gr_current_r * a) / 255; - ++px; - *px = (*px * (255-a) + gr_current_g * a) / 255; - ++px; - *px = (*px * (255-a) + gr_current_b * a) / 255; - ++px; - ++px; + if (gr_draw->pixel_bytes == 2) { + blend_16bpp(px, gr_current_r5, gr_current_g5, gr_current_b5, a); + px += gr_draw->pixel_bytes; + } else { + *px = (*px * (255-a) + gr_current_r * a) / 255; + ++px; + *px = (*px * (255-a) + gr_current_g * a) / 255; + ++px; + *px = (*px * (255-a) + gr_current_b * a) / 255; + ++px; + ++px; + } } else { - px += 4; + px += gr_draw->pixel_bytes; } } src_p += src_row_bytes; @@ -155,6 +198,16 @@ void gr_texticon(int x, int y, GRSurface* icon) { icon->width, icon->height); } +void gr_convert_rgb_555() +{ + gr_current_r5 = (((gr_current_r & 0xFF) * 0x1F) + 0x7F) / 0xFF; + gr_current_g5 = (((gr_current_g & 0xFF) * 0x3F) + 0x7F) / 0xFF; + gr_current_b5 = (((gr_current_b & 0xFF) * 0x1F) + 0x7F) / 0xFF; + + rgb_555[0] = (gr_current_g5 << 5) + (gr_current_b5); + rgb_555[1] = (gr_current_r5 << 3) + (gr_current_g5 >> 3); +} + void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { #if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) @@ -168,10 +221,19 @@ void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a gr_current_b = b; gr_current_a = a; #endif + if (gr_draw->pixel_bytes == 2) { + gr_convert_rgb_555(); + } } void gr_clear() { + if (gr_draw->pixel_bytes == 2) { + gr_fill(0, 0, gr_fb_width(), gr_fb_height()); + return; + } + + // This code only works on 32bpp devices if (gr_current_r == gr_current_g && gr_current_r == gr_current_b) { memset(gr_draw->data, gr_current_r, gr_draw->height * gr_draw->row_bytes); } else { @@ -204,10 +266,15 @@ void gr_fill(int x1, int y1, int x2, int y2) for (y = y1; y < y2; ++y) { unsigned char* px = p; for (x = x1; x < x2; ++x) { - *px++ = gr_current_r; - *px++ = gr_current_g; - *px++ = gr_current_b; - px++; + if (gr_draw->pixel_bytes == 2) { + *px++ = rgb_555[0]; + *px++ = rgb_555[1]; + } else { + *px++ = gr_current_r; + *px++ = gr_current_g; + *px++ = gr_current_b; + px++; + } } p += gr_draw->row_bytes; } @@ -216,25 +283,74 @@ void gr_fill(int x1, int y1, int x2, int y2) for (y = y1; y < y2; ++y) { unsigned char* px = p; for (x = x1; x < x2; ++x) { - *px = (*px * (255-gr_current_a) + gr_current_r * gr_current_a) / 255; - ++px; - *px = (*px * (255-gr_current_a) + gr_current_g * gr_current_a) / 255; - ++px; - *px = (*px * (255-gr_current_a) + gr_current_b * gr_current_a) / 255; - ++px; - ++px; + if (gr_draw->pixel_bytes == 2) { + blend_16bpp(px, gr_current_r5, gr_current_g5, gr_current_b5, gr_current_a); + px += gr_draw->row_bytes; + } else { + *px = (*px * (255-gr_current_a) + gr_current_r * gr_current_a) / 255; + ++px; + *px = (*px * (255-gr_current_a) + gr_current_g * gr_current_a) / 255; + ++px; + *px = (*px * (255-gr_current_a) + gr_current_b * gr_current_a) / 255; + ++px; + ++px; + } } p += gr_draw->row_bytes; } } } +void gr_blit_32to16(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) { + dx += overscan_offset_x; + dy += overscan_offset_y; + + if (outside(dx, dy) || outside(dx+w-1, dy+h-1)) return; + + unsigned char* src_p = source->data + sy*source->row_bytes + sx*source->pixel_bytes; + unsigned char* dst_p = gr_draw->data + dy*gr_draw->row_bytes + dx*gr_draw->pixel_bytes; + + int i, j; + for (i = 0; i < h; ++i) { + unsigned char* spx = src_p; + unsigned char* dpx = dst_p; + + for (j = 0; j < w; ++j) { + unsigned a = spx[3]; + + if (a == 0) { + spx += source->pixel_bytes; + dpx += gr_draw->pixel_bytes; + } else { + unsigned r5 = (((*spx++ & 0xFF) * 0x1F) + 0x7F) / 0xFF; + unsigned g5 = (((*spx++ & 0xFF) * 0x3F) + 0x7F) / 0xFF; + unsigned b5 = (((*spx++ & 0xFF) * 0x1F) + 0x7F) / 0xFF; + spx++; + if (a == 255) { + *dpx++ = (g5 << 5) + (b5); + *dpx++ = (r5 << 3) + (g5 >> 3); + } else { + blend_16bpp(dpx, r5, g5, b5, a); + spx += source->pixel_bytes; + } + } + } + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) { if (source == NULL) return; if (gr_draw->pixel_bytes != source->pixel_bytes) { - printf("gr_blit: source has wrong format\n"); - return; + if (gr_draw->pixel_bytes == 2 && source->pixel_bytes == 4) { + gr_blit_32to16(source, sx, sy, w, h, dx, dy); + return; + } else { + printf("gr_blit: source has wrong format\n"); + return; + } } dx += overscan_offset_x; @@ -359,18 +475,37 @@ void gr_flip() { int gr_init(void) { gr_init_font(); + gr_draw = NULL; - gr_backend = open_adf(); + gr_backend = open_overlay(); if (gr_backend) { gr_draw = gr_backend->init(gr_backend); if (!gr_draw) { gr_backend->exit(gr_backend); + } else + printf("Using overlay graphics.\n"); + } + +#ifndef MSM_BSP + if (!gr_draw) { + gr_backend = open_adf(); + if (gr_backend) { + gr_draw = gr_backend->init(gr_backend); + if (!gr_draw) { + gr_backend->exit(gr_backend); + } else + printf("Using adf graphics.\n"); } } +#else + printf("Skipping adf graphics because TW_TARGET_USES_QCOM_BSP := true\n"); +#endif if (!gr_draw) { gr_backend = open_drm(); gr_draw = gr_backend->init(gr_backend); + if (gr_draw) + printf("Using drm graphics.\n"); } if (!gr_draw) { @@ -378,7 +513,8 @@ int gr_init(void) gr_draw = gr_backend->init(gr_backend); if (gr_draw == NULL) { return -1; - } + } else + printf("Using fbdev graphics.\n"); } overscan_offset_x = gr_draw->width * overscan_percent / 100; @@ -409,3 +545,9 @@ void gr_fb_blank(bool blank) { gr_backend->blank(gr_backend, blank); } + +void gr_set_font(__attribute__ ((unused))const char* name) { + //this cm function is made to change font. Don't care, just init the font: + gr_init_font(); + return; +} |