From b276d982a27c421495582b120b0215ad578b7367 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 4 Nov 2019 11:11:59 +0800 Subject: [PATCH 2/6] Support PIXMAN_nv12 format Signed-off-by: Jeffy Chen --- pixman/pixman-access.c | 86 ++++++++++++++++++++++++++++++++++++++++++ pixman/pixman.c | 3 +- pixman/pixman.h | 6 ++- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 7c5ce78..1e5c0ba 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -192,6 +192,25 @@ ((uint8_t *) ((bits) + offset0 + \ ((stride) >> 1) * ((line) >> 1))) +/* + * NV12 setup and access macros + */ + +#define NV12_SETUP(image) \ + bits_image_t *__bits_image = (bits_image_t *)image; \ + uint32_t *bits = __bits_image->bits; \ + int stride = __bits_image->rowstride; \ + int offset0 = stride < 0 ? \ + (-stride) * ((__bits_image->height - 1) >> 1) - stride : \ + stride * __bits_image->height + +#define NV12_Y(line) \ + ((uint8_t *) ((bits) + (stride) * (line))) + +#define NV12_UV(line) \ + ((uint8_t *) ((bits) + offset0 + \ + (stride) * ((line) >> 1))) + /* Misc. helpers */ static force_inline void @@ -845,6 +864,42 @@ fetch_scanline_yv12 (bits_image_t *image, } } +static void +fetch_scanline_nv12 (bits_image_t *image, + int x, + int line, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + NV12_SETUP (image); + uint8_t *y_line = NV12_Y (line); + uint8_t *uv_line = NV12_UV (line); + int i; + + for (i = 0; i < width; i++) + { + int16_t y, u, v; + int32_t r, g, b; + + y = y_line[x + i] - 16; + u = uv_line[(x + i) & -2] - 128; + v = uv_line[((x + i) & -2) + 1] - 128; + + /* R = 1.164(Y - 16) + 1.596(V - 128) */ + r = 0x012b27 * y + 0x019a2e * v; + /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ + g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; + /* B = 1.164(Y - 16) + 2.018(U - 128) */ + b = 0x012b27 * y + 0x0206a2 * u; + + *buffer++ = 0xff000000 | + (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | + (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | + (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); + } +} + /**************************** Pixel wise fetching *****************************/ #ifndef PIXMAN_FB_ACCESSORS @@ -1036,6 +1091,32 @@ fetch_pixel_yv12 (bits_image_t *image, (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); } +static uint32_t +fetch_pixel_nv12 (bits_image_t *image, + int offset, + int line) +{ + NV12_SETUP (image); + int16_t y = NV12_Y (line)[offset] - 16; + int16_t u = NV12_UV (line)[offset & -2] - 128; + int16_t v = NV12_UV (line)[(offset & -2) + 1] - 128; + int32_t r, g, b; + + /* R = 1.164(Y - 16) + 1.596(V - 128) */ + r = 0x012b27 * y + 0x019a2e * v; + + /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ + g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; + + /* B = 1.164(Y - 16) + 2.018(U - 128) */ + b = 0x012b27 * y + 0x0206a2 * u; + + return 0xff000000 | + (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | + (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | + (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); +} + /*********************************** Store ************************************/ #ifndef PIXMAN_FB_ACCESSORS @@ -1509,6 +1590,11 @@ static const format_info_t accessors[] = fetch_pixel_yv12, fetch_pixel_generic_float, NULL, NULL }, + { PIXMAN_nv12, + fetch_scanline_nv12, fetch_scanline_generic_float, + fetch_pixel_nv12, fetch_pixel_generic_float, + NULL, NULL }, + { PIXMAN_null }, }; diff --git a/pixman/pixman.c b/pixman/pixman.c index c09b528..d8a2d24 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -1070,6 +1070,7 @@ pixman_format_supported_source (pixman_format_code_t format) /* YUV formats */ case PIXMAN_yuy2: case PIXMAN_yv12: + case PIXMAN_nv12: return TRUE; default: @@ -1092,7 +1093,7 @@ PIXMAN_EXPORT pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format) { /* YUV formats cannot be written to at the moment */ - if (format == PIXMAN_yuy2 || format == PIXMAN_yv12) + if (format == PIXMAN_yuy2 || format == PIXMAN_yv12 || format == PIXMAN_nv12) return FALSE; return pixman_format_supported_source (format); diff --git a/pixman/pixman.h b/pixman/pixman.h index 08303b5..3bb2fa5 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -861,6 +861,9 @@ struct pixman_indexed #define PIXMAN_TYPE_ARGB_SRGB 10 #define PIXMAN_TYPE_RGBA_FLOAT 11 +/* HACK: Use maximum value to avoid conflict */ +#define PIXMAN_TYPE_NV12 0x3f + #define PIXMAN_FORMAT_COLOR(f) \ (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \ PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ABGR || \ @@ -941,7 +944,8 @@ typedef enum { /* YUV formats */ PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0), - PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0) + PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0), + PIXMAN_nv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_NV12,0,0,0,0), } pixman_format_code_t; /* Querying supported format values. */ -- 2.20.1