| #include "asrfb.h" |
| #include "lcd_fns.h" |
| |
| int get_format_plane(unsigned int format) |
| { |
| int plane = 1; |
| |
| switch (format) { |
| case LCD_FORMAT_RGB565: |
| case LCD_FORMAT_RGB1555: |
| case LCD_FORMAT_RGB888_PACKED: |
| case LCD_FORMAT_RGB888_UNPACKED: |
| case LCD_FORMAT_RGBA888: |
| case LCD_FORMAT_RGB888A: |
| case LCD_FORMAT_YUV422_PACKED: |
| plane = 1; |
| break; |
| case LCD_FORMAT_YUV422_PLANAR: |
| case LCD_FORMAT_YUV420_PLANAR: |
| plane = 3; |
| break; |
| case LCD_FORMAT_YUV420_SEMI: |
| plane = 2; |
| break; |
| } |
| return plane; |
| } |
| |
| int get_format_bpp(unsigned int format) |
| { |
| int bpp = 0; |
| |
| switch (format) { |
| case LCD_FORMAT_RGB565: |
| case LCD_FORMAT_RGB1555: |
| bpp = 16; |
| break; |
| case LCD_FORMAT_RGB888_PACKED: |
| bpp = 24; |
| break; |
| case LCD_FORMAT_RGB888_UNPACKED: |
| case LCD_FORMAT_RGBA888: |
| case LCD_FORMAT_RGB888A: |
| bpp = 32; |
| break; |
| case LCD_FORMAT_YUV422_PACKED: |
| case LCD_FORMAT_YUV422_PLANAR: |
| bpp = 16; |
| break; |
| case LCD_FORMAT_YUV420_PLANAR: |
| case LCD_FORMAT_YUV420_SEMI: |
| bpp = 12; |
| break; |
| } |
| return bpp; |
| } |
| |
| int is_format_yuv(unsigned int format) |
| { |
| int is_yuv = 0; |
| |
| switch (format) { |
| case LCD_FORMAT_RGB565: |
| case LCD_FORMAT_RGB1555: |
| case LCD_FORMAT_RGB888_PACKED: |
| case LCD_FORMAT_RGB888_UNPACKED: |
| case LCD_FORMAT_RGBA888: |
| case LCD_FORMAT_RGB888A: |
| is_yuv = 0; |
| break; |
| case LCD_FORMAT_YUV422_PACKED: |
| case LCD_FORMAT_YUV422_PLANAR: |
| case LCD_FORMAT_YUV420_PLANAR: |
| case LCD_FORMAT_YUV420_SEMI: |
| is_yuv = 1; |
| break; |
| } |
| return is_yuv; |
| } |
| |
| int get_uv_height_dividor(unsigned int format) |
| { |
| int dividor = 0; |
| |
| switch (format) { |
| case LCD_FORMAT_RGB565: |
| case LCD_FORMAT_RGB1555: |
| case LCD_FORMAT_RGB888_PACKED: |
| case LCD_FORMAT_RGB888_UNPACKED: |
| case LCD_FORMAT_RGBA888: |
| case LCD_FORMAT_RGB888A: |
| dividor = 0; |
| break; |
| case LCD_FORMAT_YUV422_PACKED: |
| case LCD_FORMAT_YUV422_PLANAR: |
| dividor = 1; |
| break; |
| case LCD_FORMAT_YUV420_PLANAR: |
| case LCD_FORMAT_YUV420_SEMI: |
| dividor = 2; |
| break; |
| } |
| return dividor; |
| } |
| |
| static int get_layer_rgb_data(int position_x, int position_y, int is_first_layer, |
| struct s_compose_layer_setting *layer, unsigned int *rgb_data, unsigned char *alpha) |
| { |
| unsigned int data; |
| unsigned char al_data; |
| unsigned char *psrc8 = NULL; |
| unsigned int *psrc32 = NULL; |
| |
| if (layer->format == LCD_FORMAT_RGB888_PACKED) { |
| psrc8 = (unsigned char *)(layer->addr + position_y * layer->stride + position_x * 3); |
| data = (*psrc8++) & 0xFF; /*b*/ |
| data = (((*psrc8++) & 0xFF) << 8) | data; /*g*/ |
| data = (((*psrc8++) & 0xFF) << 16) | data; /*r*/ |
| if (1 != is_first_layer) { |
| if (layer->alpha_sel != LCD_ALPHA_LAYER) { |
| printf("%s: Invalid alpha setting!\n", __func__); |
| return -1; |
| } |
| al_data = layer->layer_alpha; |
| } |
| else { |
| al_data = 0; |
| } |
| } |
| else if (layer->format == LCD_FORMAT_RGB888_UNPACKED) { |
| psrc32 = (unsigned int *)(layer->addr + position_y * layer->stride + position_x * 4); |
| data = (*psrc32++) & 0xFFFFFF; |
| if (1 != is_first_layer) { |
| if (layer->alpha_sel != LCD_ALPHA_LAYER) { |
| printf("%s: Invalid alpha setting!\n", __func__); |
| return -1; |
| } |
| al_data = layer->layer_alpha; |
| } |
| else { |
| al_data = 0; |
| } |
| } |
| else if (layer->format == LCD_FORMAT_RGBA888) { |
| psrc32 = (unsigned int *)(layer->addr + position_y * layer->stride + position_x * 4); |
| psrc8 = (unsigned char *)(layer->addr + position_y * layer->stride + position_x * 4 + 3); |
| data = (*psrc32) & 0xFFFFFF; |
| if ((1 != is_first_layer) && (layer->alpha_sel == LCD_ALPHA_LAYER)) { |
| al_data = layer->layer_alpha; |
| } |
| else { |
| al_data = *psrc8; |
| } |
| } |
| else if (layer->format == LCD_FORMAT_RGB888A) { |
| psrc32 = (unsigned int *)(layer->addr + position_y * layer->stride + position_x * 4); |
| psrc8 = (unsigned char *)(layer->addr + position_y * layer->stride + position_x * 4); |
| data = ((*psrc32++) >> 8) & 0xFFFFFF; |
| if ((1 != is_first_layer) && (layer->alpha_sel == LCD_ALPHA_LAYER)) { |
| al_data = layer->layer_alpha; |
| } |
| else { |
| al_data = *psrc8; |
| } |
| } |
| else { |
| printf("%s: Invalid layer format (0x%x)!\n", __func__, layer->format); |
| return -1; |
| } |
| *rgb_data = data; |
| *alpha = al_data; |
| return 0; |
| } |
| |
| static unsigned int do_compose(unsigned int *src1, unsigned int *src2, unsigned char alpha1, |
| unsigned char alpha2, unsigned char alpha_mode, unsigned char dest_format, unsigned int *dest_rgb, |
| unsigned char *dest_alpha, int log) |
| { |
| unsigned int result = 0; |
| unsigned char r1, g1, b1; |
| unsigned char r2, g2, b2; |
| unsigned char r3, g3, b3; |
| unsigned int r3_temp, g3_temp, b3_temp; |
| unsigned int alpha_temp; |
| unsigned char *pbyte; |
| |
| if (1 == log) |
| printf("%s: a1 = %d, a2 = %d\n", __func__, (int)alpha1, (int)alpha2); |
| |
| if (NULL == src2) { |
| *dest_rgb = (*src1) & 0xFFFFFF; |
| if (dest_format == LCD_FORMAT_RGB888_PACKED) { |
| result = (*src1) & 0xFFFFFF; |
| } |
| else if (dest_format == LCD_FORMAT_RGBA888) { |
| result = (alpha1 << 24) | ((*src1) & 0xFFFFFF); |
| } |
| else if (dest_format == LCD_FORMAT_RGB888A) { |
| result = ((*src1 << 8) & 0xFFFFFF00) | alpha1; |
| } |
| else if (dest_format == LCD_FORMAT_RGB888_UNPACKED) { |
| result = (*src1) & 0xFFFFFF; |
| } |
| else { |
| printf("%s: Invalid dest format (0x%x)!\n", __func__, dest_format); |
| } |
| return result; |
| } |
| |
| pbyte = (unsigned char *)src1; |
| b1 = *pbyte++; |
| g1 = *pbyte++; |
| r1 = *pbyte++; |
| |
| pbyte = (unsigned char *)src2; |
| b2 = *pbyte++; |
| g2 = *pbyte++; |
| r2 = *pbyte++; |
| |
| if (1 == log) |
| printf("%s: r1 = %d, g1 = %d, b1 = %d, r2 = %d, g2 = %d, b2 = %d\n", __func__, |
| (int)r1, (int)g1, (int)b1, (int)r2, (int)g2, (int)b2); |
| |
| if (alpha_mode == LCD_ALPHA_MODE_NORMAL) { |
| r3_temp = (r2 * alpha2 + r1 * (255 - alpha2)) / 255; |
| g3_temp = (g2 * alpha2 + g1 * (255 - alpha2)) / 255; |
| b3_temp = (b2 * alpha2 + b1 * (255 - alpha2)) / 255; |
| alpha_temp = alpha1 + alpha2 - alpha1 * alpha2 / 255; |
| } |
| else if (alpha_mode == LCD_ALPHA_MODE_PRE) { |
| r3_temp = (r2 * 255 + r1 * (255 - alpha2)) / 255; |
| g3_temp = (g2 * 255 + g1 * (255 - alpha2)) / 255; |
| b3_temp = (b2 * 255 + b1 * (255 - alpha2)) / 255; |
| alpha_temp = alpha1 + alpha2 - alpha1 * alpha2 / 255; |
| } |
| else { |
| r3_temp = (r2 * 255 + r1 * alpha2) / 255; |
| g3_temp = (g2 * 255 + g1 * alpha2) / 255; |
| b3_temp = (b2 * 255 + b1 * alpha2) / 255; |
| alpha_temp = alpha1 + alpha2 - alpha1 * alpha2 / 255; |
| if (1 == log) { |
| printf("%s: r3_temp = %d, g3_temp = %d, b3_temp = %d\n", __func__, r3_temp, |
| g3_temp, b3_temp); |
| } |
| } |
| r3 = (r3_temp > 255) ? 255 : r3_temp; |
| g3 = (g3_temp > 255) ? 255 : g3_temp; |
| b3 = (b3_temp > 255) ? 255 : b3_temp; |
| *dest_alpha = (alpha_temp > 255) ? 255 : alpha_temp; |
| |
| if (1 == log) { |
| printf("%s: r3 = %d, g3 = %d, b3 = %d, alpha= %d\n", __func__, (int)r3, (int)g3, |
| (int)b3, (int)*dest_alpha); |
| } |
| |
| *dest_rgb = (r3 << 16) | (g3 << 8) | b3; |
| if (dest_format == LCD_FORMAT_RGB888_PACKED) { |
| result = (r3 << 16) | (g3 << 8) | b3; |
| } |
| else if (dest_format == LCD_FORMAT_RGBA888) { |
| result = (*dest_alpha << 24) | (r3 << 16) | (g3 << 8) | b3; |
| } |
| else if (dest_format == LCD_FORMAT_RGB888A) { |
| result = (r3 << 24) | (g3 << 16) | (b3 << 8) | *dest_alpha; |
| } |
| else if (dest_format == LCD_FORMAT_RGB888_UNPACKED) { |
| result = (r3 << 16) | (g3 << 8) | b3; |
| } |
| |
| if (1 == log) { |
| printf("%s: result = 0x%x\n", __func__, result); |
| } |
| return result; |
| } |
| |
| static void dump_compose_setting(struct s_compose_setting *compose_setting) |
| { |
| } |
| |
| static void draw_pure_color(unsigned int addr, unsigned int width, |
| unsigned int height, unsigned int color, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned int *pdata = (unsigned int *)addr; |
| unsigned int porch = 0; |
| unsigned char *pbyte = NULL; |
| |
| *stride = WIDE_ALIGN(width * 4, align); |
| porch = *stride - width * 4; |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| *pdata = color; |
| pdata++; |
| } |
| pbyte = (unsigned char *)pdata; |
| pbyte += porch; |
| pdata = (unsigned int *)pbyte; |
| } |
| } |
| |
| static void draw_hcb(unsigned int addr, unsigned int width, |
| unsigned int height, unsigned int cb_num, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned int *pdata = (unsigned int *)addr; |
| unsigned int data[5] = {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00FFFFFF, 0x00000000}; |
| unsigned int cur_index = 0; |
| unsigned int line_num; |
| unsigned int porch = 0; |
| unsigned char *pbyte = NULL; |
| |
| *stride = WIDE_ALIGN(width * 4, align); |
| porch = *stride - width * 4; |
| |
| line_num = height / cb_num; |
| |
| cur_index = 0; |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| *pdata = data[cur_index]; |
| pdata++; |
| } |
| if ((i + 1) % line_num == 0) { |
| cur_index++; |
| if (cur_index == 5) { |
| cur_index = 0; |
| } |
| } |
| pbyte = (unsigned char *)pdata; |
| pbyte += porch; |
| pdata = (unsigned int *)pbyte; |
| } |
| } |
| |
| static void draw_vcb(unsigned int addr, unsigned int width, |
| unsigned int height, unsigned int cb_num, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned int *pdata = (unsigned int *)addr; |
| unsigned int data[5] = { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00FFFFFF, 0x00000000 }; |
| unsigned int cur_index = 0; |
| unsigned int colum_num; |
| unsigned int porch = 0; |
| unsigned char *pbyte = NULL; |
| |
| *stride = WIDE_ALIGN(width * 4, align); |
| porch = *stride - width * 4; |
| |
| colum_num = width / cb_num; |
| for (i = 0; i < height; i++) { |
| cur_index = 0; |
| for (j = 0; j < width; j++) { |
| *pdata = data[cur_index]; |
| pdata++; |
| if ((j + 1) % colum_num == 0) { |
| cur_index++; |
| if (cur_index == 5) { |
| cur_index = 0; |
| } |
| } |
| } |
| pbyte = (unsigned char *)pdata; |
| pbyte += porch; |
| pdata = (unsigned int *)pbyte; |
| } |
| } |
| |
| static void draw_line(unsigned int addr, unsigned int width, |
| unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned int *pdata = (unsigned int *)addr; |
| unsigned int data[3] = { 0x00FF0000, 0x0000FF00, 0x000000FF }; |
| unsigned int cur_index = 0; |
| unsigned int porch = 0; |
| unsigned char *pbyte = NULL; |
| |
| *stride = WIDE_ALIGN(width * 4, align); |
| porch = *stride - width * 4; |
| cur_index = 0; |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| *pdata = data[cur_index]; |
| pdata++; |
| } |
| cur_index++; |
| cur_index = cur_index % 3; |
| pbyte = (unsigned char *)pdata; |
| pbyte += porch; |
| pdata = (unsigned int *)pbyte; |
| } |
| } |
| |
| static void draw_grey_level(unsigned int addr, unsigned int width, |
| unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned int *pdata = (unsigned int *)addr; |
| unsigned int porch = 0; |
| unsigned char cur_value = 0; |
| unsigned char *pbyte = NULL; |
| |
| *stride = WIDE_ALIGN(width * 4, align); |
| porch = *stride - width * 4; |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| *pdata++ = cur_value | cur_value << 8 | cur_value << 16 /*| (0xFF << 24)*/; |
| } |
| if ((i % 4 == 0) && (i > 0)) { |
| cur_value += 3; |
| cur_value = cur_value % 6; |
| } |
| pbyte = (unsigned char *)pdata; |
| pbyte += porch; |
| pdata = (unsigned int *)pbyte; |
| } |
| } |
| |
| static void prepare_argb8888_image(unsigned int addr, unsigned int pattern, |
| unsigned int width, unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| switch (pattern) { |
| case IMG_PATTERN_RED: |
| draw_pure_color(addr, width, height, 0xFF0000, align, stride); |
| break; |
| case IMG_PATTERN_GREEN: |
| draw_pure_color(addr, width, height, 0xFF00, align, stride); |
| break; |
| case IMG_PATTERN_BLUE: |
| draw_pure_color(addr, width, height, 0xFF, align, stride); |
| break; |
| case IMG_PATTERN_WHITE: |
| draw_pure_color(addr, width, height, 0xFFFFFF, align, stride); |
| break; |
| case IMG_PATTERN_HCB_5: |
| draw_hcb(addr, width, height, 5, align, stride); |
| break; |
| case IMG_PATTERN_HCB_2: |
| draw_hcb(addr, width, height, 2, align, stride); |
| break; |
| case IMG_PATTERN_VCB_5: |
| draw_vcb(addr, width, height, 5, align, stride); |
| break; |
| case IMG_PATTERN_VCB_2: |
| draw_vcb(addr, width, height, 2, align, stride); |
| break; |
| case IMG_PATTERN_LINE: |
| draw_line(addr, width, height, align, stride); |
| break; |
| case IMG_PATTERN_GREY_LEVEL: |
| draw_grey_level(addr, width, height, align, stride); |
| break; |
| } |
| } |
| |
| static void argb8888_to_rgb888(unsigned int src_addr, unsigned int dest_addr, |
| unsigned int width, unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned char *psrc, *pdest; |
| unsigned int porch; |
| |
| *stride = WIDE_ALIGN(width * 3, align); |
| porch = *stride - width * 3; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest = (unsigned char *)dest_addr; |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| *pdest++ = *psrc++; /*b*/ |
| *pdest++ = *psrc++; /*g*/ |
| *pdest++ = *psrc++; /*r*/ |
| psrc++; /*alpha*/ |
| } |
| pdest += porch; |
| } |
| } |
| |
| static void argb8888_to_rgba8888(unsigned int src_addr, unsigned int dest_addr, |
| unsigned int width, unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned char *psrc, *pdest; |
| unsigned int porch; |
| unsigned char r, g, b, a; |
| |
| *stride = WIDE_ALIGN(width * 4, align); |
| porch = *stride - width * 4; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest = (unsigned char *)dest_addr; |
| |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| b = *psrc++; /*b*/ |
| g = *psrc++; /*g*/ |
| r = *psrc++; /*r*/ |
| a = *psrc++; /*alpha*/ |
| *pdest++ = a; |
| *pdest++ = b; |
| *pdest++ = g; |
| *pdest++ = r; |
| } |
| pdest += porch; |
| } |
| } |
| |
| |
| static void argb8888_to_rgb565(unsigned int src_addr, unsigned int dest_addr, |
| unsigned int width, unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned char *psrc; |
| unsigned short *pdest; |
| unsigned char r, g, b; |
| unsigned char nr, ng, nb; |
| unsigned int porch; |
| |
| *stride = WIDE_ALIGN(width * 2, align); |
| porch = *stride - width * 2; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest = (unsigned short *)dest_addr; |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| b = *psrc++; /*b*/ |
| g = *psrc++; /*g*/ |
| r = *psrc++; /*r*/ |
| psrc++; /*alpha*/ |
| |
| nr = r * 31 / 255; |
| ng = g * 63 / 255; |
| nb = b * 31 / 255; |
| *pdest++ = ((nr & 0x1F) << 11) | |
| ((ng & 0x3F) << 5) | (nb & 0x1F); |
| } |
| pdest += (porch >> 1); |
| } |
| } |
| |
| static void argb8888_to_rgb1555(unsigned int src_addr, unsigned int dest_addr, |
| unsigned int width, unsigned int height, unsigned int align, unsigned int *stride) |
| { |
| unsigned int i, j; |
| unsigned char *psrc; |
| unsigned short *pdest; |
| unsigned char r, g, b; |
| unsigned int porch; |
| |
| *stride = WIDE_ALIGN(width * 2, align); |
| porch = *stride - width * 2; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest = (unsigned short *)dest_addr; |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| b = *psrc++; /*b*/ |
| g = *psrc++; /*g*/ |
| r = *psrc++; /*r*/ |
| psrc++; /*alpha*/ |
| |
| *pdest++ = ((r & 0x1F) << 10) | |
| ((g & 0x1F) << 5) | (b & 0x1F); |
| } |
| pdest += (porch >> 1); |
| } |
| } |
| |
| static void argb8888_to_yuv420_p2(unsigned int src_addr, unsigned int dest_addr_p1, |
| unsigned int *dest_addr_p2, unsigned int width, unsigned int height, |
| unsigned int align, unsigned int *stride_p1, unsigned int *stride_p2) |
| { |
| unsigned int i, j; |
| unsigned char *psrc, *pdest_p1, *pdest_p2; |
| unsigned int r, g, b; |
| unsigned char y, u, v; |
| unsigned int porch_p1, porch_p2; |
| unsigned int addr_p2; |
| |
| *stride_p1 = WIDE_ALIGN(width, align); |
| *stride_p2 = WIDE_ALIGN(width, align); |
| porch_p1 = *stride_p1 - width; |
| porch_p2 = *stride_p2 - width; |
| |
| addr_p2 = dest_addr_p1 + (*stride_p1) * height; |
| *dest_addr_p2 = addr_p2; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest_p1 = (unsigned char *)dest_addr_p1; |
| pdest_p2 = (unsigned char *)addr_p2; |
| |
| for (j = 0; j < height; j++) { |
| for (i = 0; i < width; i += 2) { |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = y; |
| if (0 == j % 2) { |
| *pdest_p2++ = u; |
| } |
| |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = y; |
| if (0 == j % 2) { |
| *pdest_p2++ = v; |
| } |
| } |
| pdest_p1 += porch_p1; |
| if (0 == j % 2) { |
| pdest_p2 += porch_p2; |
| } |
| } |
| } |
| |
| static void argb8888_to_yuv420_p3(unsigned int src_addr, unsigned int dest_addr_p1, |
| unsigned int *dest_addr_p2, unsigned int *dest_addr_p3, |
| unsigned int width, unsigned int height, unsigned int align, |
| unsigned int *stride_p1, unsigned int *stride_p2, unsigned int *stride_p3) |
| { |
| unsigned int i, j; |
| unsigned char *psrc, *pdest_p1, *pdest_p2, *pdest_p3; |
| unsigned int r, g, b; |
| unsigned char y, u, v; |
| unsigned int porch_p1, porch_p2, porch_p3; |
| unsigned int addr_p2, addr_p3; |
| |
| *stride_p1 = WIDE_ALIGN(width, align); |
| *stride_p2 = WIDE_ALIGN(width / 2, align); |
| *stride_p3 = WIDE_ALIGN(width / 2, align); |
| porch_p1 = *stride_p1 - width; |
| porch_p2 = *stride_p2 - width / 2; |
| porch_p3 = *stride_p3 - width / 2; |
| |
| addr_p2 = dest_addr_p1 + (*stride_p1) * height; |
| addr_p3 = addr_p2 + (*stride_p2) * height / 2; |
| *dest_addr_p2 = addr_p2; |
| *dest_addr_p3 = addr_p3; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest_p1 = (unsigned char *)dest_addr_p1; |
| pdest_p2 = (unsigned char *)addr_p2; |
| pdest_p3 = (unsigned char *)addr_p3; |
| |
| for (j = 0; j < height; j++) { |
| for (i = 0; i < width; i += 2) { |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = y; |
| if (0 == j % 2) { |
| *pdest_p2++ = u; |
| } |
| |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = y; |
| if (0 == j % 2) { |
| *pdest_p3++ = v; |
| } |
| } |
| pdest_p1 += porch_p1; |
| if (0 == j % 2) { |
| pdest_p2 += porch_p2; |
| pdest_p3 += porch_p3; |
| } |
| } |
| } |
| |
| static void argb8888_to_yuv422_p3(unsigned int src_addr, unsigned int dest_addr_p1, |
| unsigned int *dest_addr_p2, unsigned int *dest_addr_p3, |
| unsigned int width, unsigned int height, unsigned int align, |
| unsigned int *stride_p1, unsigned int *stride_p2, unsigned int *stride_p3) |
| { |
| unsigned int i, j; |
| unsigned char *psrc, *pdest_p1, *pdest_p2, *pdest_p3; |
| unsigned int r, g, b; |
| unsigned char y, u, v; |
| unsigned int porch_p1, porch_p2, porch_p3; |
| unsigned int addr_p2, addr_p3; |
| |
| *stride_p1 = WIDE_ALIGN(width, align); |
| *stride_p2 = WIDE_ALIGN(width / 2, align); |
| *stride_p3 = WIDE_ALIGN(width / 2, align); |
| porch_p1 = *stride_p1 - width; |
| porch_p2 = *stride_p2 - width / 2; |
| porch_p3 = *stride_p3 - width / 2; |
| |
| addr_p2 = dest_addr_p1 + (*stride_p1) * height; |
| addr_p3 = addr_p2 + (*stride_p2) * height; |
| *dest_addr_p2 = addr_p2; |
| *dest_addr_p3 = addr_p3; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest_p1 = (unsigned char *)dest_addr_p1; |
| pdest_p2 = (unsigned char *)addr_p2; |
| pdest_p3 = (unsigned char *)addr_p3; |
| |
| for (j = 0; j < height; j++) { |
| for (i = 0; i < width; i += 2) { |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = y; |
| *pdest_p2++ = u; |
| |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = y; |
| *pdest_p3++ = v; |
| } |
| pdest_p1 += porch_p1; |
| pdest_p2 += porch_p2; |
| pdest_p3 += porch_p3; |
| } |
| } |
| |
| static void argb8888_to_yuv422_p1(unsigned int src_addr, unsigned int dest_addr_p1, |
| unsigned int width, unsigned int height, unsigned int align, |
| unsigned int *stride_p1) |
| { |
| unsigned int i, j; |
| unsigned char *psrc, *pdest_p1; |
| unsigned int r, g, b; |
| unsigned char y, u, v; |
| unsigned int porch_p1; |
| |
| *stride_p1 = WIDE_ALIGN(width * 2, align); |
| porch_p1 = *stride_p1 - width * 2; |
| |
| psrc = (unsigned char *)src_addr; |
| pdest_p1 = (unsigned char *)dest_addr_p1; |
| |
| /*format is UYVY*/ |
| for (j = 0; j < height; j++) { |
| for (i = 0; i < width; i += 2) { |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = u; |
| *pdest_p1++ = y; |
| |
| b = (unsigned int)*psrc++; |
| g = (unsigned int)*psrc++; |
| r = (unsigned int)*psrc++; |
| psrc++; |
| |
| y = (unsigned char)((77 * r + 150 * g + 29 * b) >> 8); |
| u = (unsigned char)(128 + ((128 * b - 43 * r - 85 * g) >> 8)); |
| v = (unsigned char)(128 + ((128 * r - 107 * g - 21 * b) >> 8)); |
| *pdest_p1++ = v; |
| *pdest_p1++ = y; |
| } |
| pdest_p1 += porch_p1; |
| } |
| } |
| |
| int lcd_draw_images(unsigned int addr_p1, unsigned int *addr_p2, unsigned int *addr_p3, |
| unsigned int format, unsigned int pattern, unsigned int width, |
| unsigned int height, unsigned int *stride_p1, unsigned int *stride_p2, |
| unsigned int *stride_p3) |
| { |
| unsigned int stride_temp = 0; |
| unsigned int addr_tmp = 0; |
| |
| if ((LCD_FORMAT_RGBA888 == format) || (LCD_FORMAT_RGB888_UNPACKED == format)) { |
| prepare_argb8888_image(addr_p1, pattern, width, height, STRIDE_ALIGN, stride_p1); |
| return 0; |
| } |
| |
| addr_tmp = (unsigned int)malloc(width * height * 4); |
| if (!addr_tmp) { |
| printf("%s: no mem w: %d, h: %d\n", __func__, width, height); |
| return -1; |
| } |
| |
| prepare_argb8888_image(addr_tmp, pattern, width, height, 1, &stride_temp); |
| switch (format) { |
| case LCD_FORMAT_RGB888_PACKED: |
| argb8888_to_rgb888(addr_tmp, addr_p1, width, height, STRIDE_ALIGN, stride_p1); |
| break; |
| case LCD_FORMAT_RGB565: |
| argb8888_to_rgb565(addr_tmp, addr_p1, width, height, STRIDE_ALIGN, stride_p1); |
| break; |
| case LCD_FORMAT_RGB888A: |
| argb8888_to_rgba8888(addr_tmp, addr_p1, width, height, STRIDE_ALIGN, stride_p1); |
| break; |
| case LCD_FORMAT_YUV420_SEMI: |
| argb8888_to_yuv420_p2(addr_tmp, addr_p1, addr_p2, |
| width, height, STRIDE_ALIGN, stride_p1, stride_p2); |
| break; |
| case LCD_FORMAT_YUV422_PLANAR: |
| argb8888_to_yuv422_p3(addr_tmp, addr_p1, addr_p2, |
| addr_p3, width, height, STRIDE_ALIGN, stride_p1, stride_p2, stride_p3); |
| break; |
| case LCD_FORMAT_YUV420_PLANAR: |
| argb8888_to_yuv420_p3(addr_tmp, addr_p1, addr_p2, |
| addr_p3, width, height, STRIDE_ALIGN, stride_p1, stride_p2, stride_p3); |
| break; |
| case LCD_FORMAT_YUV422_PACKED: |
| argb8888_to_yuv422_p1(addr_tmp, addr_p1, width, height, |
| STRIDE_ALIGN, stride_p1); |
| break; |
| case LCD_FORMAT_RGB1555: |
| argb8888_to_rgb1555(addr_tmp, addr_p1, width, height, |
| STRIDE_ALIGN, stride_p1); |
| break; |
| default: |
| printf("%s: Unsupport formate = %d\n", __func__, format); |
| } |
| |
| free((void *)addr_tmp); |
| return 0; |
| } |
| |
| int lcd_compare_buffers(unsigned int src, unsigned int dest, unsigned int width, |
| unsigned int height, unsigned int stride_src, unsigned int stride_dest, unsigned int format, int log) |
| { |
| unsigned int var1, var2; |
| unsigned int res, i, j; |
| unsigned char *mem_ptr1; |
| unsigned char *mem_ptr2; |
| unsigned int bpp; |
| |
| if ((LCD_FORMAT_RGB565 != format) && (LCD_FORMAT_RGB888_PACKED != format) && |
| (LCD_FORMAT_RGB888A != format) && (LCD_FORMAT_RGBA888 != format)) { |
| printf("%s: only support RGB565 & RGB888_packet & RGB888A (0x%x)\n", __func__, format); |
| return -1; |
| } |
| |
| if ((LCD_FORMAT_RGB565 == format) || |
| (LCD_FORMAT_RGB1555 == format)) { |
| bpp = 2; |
| } |
| else if (LCD_FORMAT_RGB888_PACKED == format) { |
| bpp = 3; |
| } |
| else { |
| bpp = 4; |
| } |
| |
| for (j = 0; j < height; j++) { |
| mem_ptr1 = (unsigned char *)(src + j * stride_src); |
| mem_ptr2 = (unsigned char *)(dest + j * stride_dest); |
| |
| res = memcmp(mem_ptr1, mem_ptr2, width * bpp); |
| if (res != 0) { |
| res = 0; |
| for (i = 0; i < width; i++) { |
| if (4 == bpp) { |
| var1 = *(unsigned int *)mem_ptr1; |
| var2 = *(unsigned int *)mem_ptr2; |
| } |
| else if (3 == bpp) { |
| var1 = (*mem_ptr1 << 16) | (*(mem_ptr1 + 1) << 8) | *(mem_ptr1 + 2); |
| var2 = (*mem_ptr2 << 16) | (*(mem_ptr2 + 1) << 8) | *(mem_ptr2 + 2); |
| } |
| else { |
| var1 = (*mem_ptr1 << 8) | *(mem_ptr1 + 1); |
| var2 = (*mem_ptr2 << 8) | *(mem_ptr2 + 1); |
| } |
| if ((var1 & 0xFFFFFF) != (var2 & 0xFFFFFF)) { |
| if (1 == log) { |
| printf("%s: mismatch: source[0x%08X] = 0x%08X. dest[0x%08X] = 0x%08X.\n", |
| __func__, (unsigned int)mem_ptr1, var1, (unsigned int)mem_ptr2, var2); |
| } |
| res = -1; |
| } |
| mem_ptr1 += bpp; |
| mem_ptr2 += bpp; |
| } |
| if (res != 0) { |
| if (log) { |
| printf("%s: Error during check of bytes from address: 0x%08X.\n", |
| __func__, dest + j * stride_dest); |
| } |
| return -1; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| int lcd_compare_compose_buffer(struct s_compose_setting *compose_setting, int log) |
| { |
| struct s_compose_layer_setting *img_layer = NULL; |
| struct s_compose_layer_setting *osd1_layer = NULL; |
| struct s_compose_layer_setting *osd2_layer = NULL; |
| |
| struct s_compose_layer_setting *first_layer = NULL; |
| struct s_compose_layer_setting *second_layer = NULL; |
| struct s_compose_layer_setting *third_layer = NULL; |
| |
| unsigned int i, j, has_img = 0; |
| int ret, ret1 = 0; |
| unsigned int src1, src2, result, dest_rgb, dest_addr; |
| unsigned char alpha1, alpha2, dest_alpha; |
| unsigned char src_r, src_g, src_b, src_a; |
| unsigned char dest_r, dest_g, dest_b, dest_a; |
| unsigned char *pdest8 = NULL; |
| unsigned int *pdest32 = NULL; |
| unsigned int count = 0; |
| |
| if (NULL == compose_setting) { |
| printf("%s: Invalid paramr\n", __func__); |
| return -1; |
| } |
| |
| dump_compose_setting(compose_setting); |
| img_layer = &compose_setting->layer_setting[LCD_LAYER_IMG]; |
| osd1_layer = &compose_setting->layer_setting[LCD_LAYER_OSD1]; |
| osd2_layer = &compose_setting->layer_setting[LCD_LAYER_OSD2]; |
| |
| has_img = 0; |
| if (1 == img_layer->layer_en) { |
| has_img = 1; |
| first_layer = img_layer; |
| if (1 == osd1_layer->layer_en) { |
| second_layer = osd1_layer; |
| if (1 == osd2_layer->layer_en) { |
| third_layer = osd2_layer; |
| } |
| } |
| else if (1 == osd2_layer->layer_en) { |
| second_layer = osd2_layer; |
| } |
| } |
| else if (1 == osd1_layer->layer_en) { |
| first_layer = osd1_layer; |
| if (1 == osd2_layer->layer_en) { |
| second_layer = osd2_layer; |
| } |
| } |
| else if (1 == osd2_layer->layer_en) { |
| first_layer = osd2_layer; |
| } |
| |
| if (NULL == first_layer) { |
| printf("%s: No layer is enabled!\n", __func__); |
| return -1; |
| } |
| |
| for (i = 0; i < compose_setting->height; i++) { |
| for (j = 0; j < compose_setting->width; j++) { |
| /*get src1 data*/ |
| ret = get_layer_rgb_data(j, i, 1, first_layer, &src1, &alpha1); |
| if (0 != ret) { |
| printf("%s: get_layer_rgb_data fail!\n", __func__); |
| return -1; |
| } |
| else { |
| if (1 == log) { |
| printf("%s: get src1 %d, %d rgb data is 0x%x, A is%d\n", |
| __func__, j, i, src1, alpha1); |
| } |
| } |
| |
| if (NULL == second_layer) { |
| result = do_compose(&src1, NULL, alpha1, 0, compose_setting->alpha_mode, |
| compose_setting->dest_format, &dest_rgb, &dest_alpha, log); |
| goto compare; |
| } |
| |
| /*get src2 data*/ |
| ret = get_layer_rgb_data(j, i, 0, second_layer, &src2, &alpha2); |
| if (0 != ret) { |
| printf("%s: get_layer_rgb_data fail!\n", __func__); |
| return -1; |
| } |
| else { |
| if (1 == log) { |
| printf("%s: get src2 %d, %d rgb data is 0x%x, A is%d\n", |
| __func__, j, i, src2, alpha2); |
| } |
| } |
| if (has_img) { |
| result = do_compose(&src1, &src2, 0, alpha2, compose_setting->alpha_mode, |
| compose_setting->dest_format, &dest_rgb, &dest_alpha, log); |
| } |
| else { |
| result = do_compose(&src1, &src2, alpha1, alpha2, compose_setting->alpha_mode, |
| compose_setting->dest_format, &dest_rgb, &dest_alpha, log); |
| } |
| if (1 == log) { |
| printf("%s: compose 0x%x, 0x%x is 0x%x!\n", __func__, src1, src2, result); |
| } |
| |
| if (NULL == third_layer) { |
| goto compare; |
| } |
| |
| src1 = dest_rgb; |
| alpha1 = dest_alpha; |
| /*get src3 data*/ |
| ret = get_layer_rgb_data(j, i, 0, third_layer, &src2, &alpha2); |
| if (0 != ret) { |
| printf("%s: get_layer_rgb_data fail!\n", __func__); |
| return -1; |
| } |
| else { |
| if (1 == log) { |
| printf("%s: get %d, %d rgb data is 0x%x!\n", __func__, j, i, src2); |
| } |
| } |
| result = do_compose(&src1, &src2, alpha1, alpha2, compose_setting->alpha_mode, |
| compose_setting->dest_format, &dest_rgb, &dest_alpha, log); |
| if (1 == log) { |
| printf("%s: compose 0x%x, 0x%x is 0x%x!\n", __func__, src1, src2, result); |
| } |
| |
| compare: |
| if (compose_setting->dest_format == LCD_FORMAT_RGB888_PACKED) { |
| dest_addr = compose_setting->dest_addr + i * compose_setting->dest_stride |
| + j * 3; |
| pdest8 = (unsigned char *)dest_addr; |
| dest_b = (*pdest8++) & 0xFF; |
| dest_g = (*pdest8++) & 0xFF; |
| dest_r = (*pdest8) & 0xFF; |
| dest_a = 0; |
| dest_rgb = (dest_r << 16) | (dest_g << 8) | dest_b; |
| result = result & 0xFFFFFF; |
| pdest8 = (unsigned char *)&result; |
| src_b = (*pdest8++) & 0xFF; |
| src_g = (*pdest8++) & 0xFF; |
| src_r = (*pdest8) & 0xFF; |
| src_a = 0; |
| } |
| else if (compose_setting->dest_format == LCD_FORMAT_RGB888A) { |
| dest_addr = compose_setting->dest_addr + i * compose_setting->dest_stride |
| + j * 4; |
| pdest32 = (unsigned int *)dest_addr; |
| dest_rgb = *pdest32; |
| if ((compose_setting->alpha_mode != LCD_ALPHA_MODE_PRE) || |
| (NULL == second_layer)) { |
| result = result & 0xFFFFFF00; |
| dest_rgb = dest_rgb & 0xFFFFFF00; |
| } |
| pdest8 = (unsigned char *)&dest_rgb; |
| dest_a = (*pdest8++) & 0xFF; |
| dest_b = (*pdest8++) & 0xFF; |
| dest_g = (*pdest8++) & 0xFF; |
| dest_r = (*pdest8) & 0xFF; |
| pdest8 = (unsigned char *)&result; |
| src_a = (*pdest8++) & 0xFF; |
| src_b = (*pdest8++) & 0xFF; |
| src_g = (*pdest8++) & 0xFF; |
| src_r = (*pdest8) & 0xFF; |
| } |
| else if (compose_setting->dest_format == LCD_FORMAT_RGBA888) { |
| dest_addr = compose_setting->dest_addr + i * compose_setting->dest_stride |
| + j * 4; |
| pdest32 = (unsigned int *)dest_addr; |
| dest_rgb = *pdest32; |
| if ((compose_setting->alpha_mode != LCD_ALPHA_MODE_PRE) || |
| (NULL == second_layer)) { |
| result = result & 0xFFFFFF; |
| dest_rgb = dest_rgb & 0xFFFFFF; |
| } |
| pdest8 = (unsigned char *)&dest_rgb; |
| dest_b = (*pdest8++) & 0xFF; |
| dest_g = (*pdest8++) & 0xFF; |
| dest_r = (*pdest8++) & 0xFF; |
| dest_a = (*pdest8) & 0xFF; |
| pdest8 = (unsigned char *)&result; |
| src_b = (*pdest8++) & 0xFF; |
| src_g = (*pdest8++) & 0xFF; |
| src_r = (*pdest8++) & 0xFF; |
| src_a = (*pdest8) & 0xFF; |
| } |
| else { |
| printf("%s: Unsupported dest format (0x%x)!\n", |
| __func__, compose_setting->dest_format); |
| return -1; |
| } |
| count++; |
| |
| if ((dest_r < (src_r - 1)) || (dest_r > (src_r + 1)) || |
| (dest_g < (src_g - 1)) || (dest_g > (src_g + 1)) || |
| (dest_b < (src_b - 1)) || (dest_b > (src_b + 1)) || |
| (dest_a < (src_a - 1)) || (dest_a > (src_a + 1))) { |
| printf("%s: Compare fail: (w=%d, h=%d) src = 0x%x, dest = 0x%x\n", |
| __func__, j, i, result, dest_rgb); |
| printf("%s: dest_addr = 0x%x\n", __func__, dest_addr); |
| printf("%s: src_r,g,b,a = %d, %d, %d, %d\n", |
| __func__, src_r, src_g, src_b, src_a); |
| printf("%s: dest_r,g,b,a = %d, %d, %d, %d\n", |
| __func__, dest_r, dest_g, dest_b, dest_a); |
| ret1 = -1; |
| return -1; |
| } |
| } |
| } |
| printf("%s: compare %d pixel are same\n", __func__, count); |
| return ret1; |
| } |