hc
2023-02-18 a08c8b75ee83d7f62c9aefc23bfb42082aa4076c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
From c61de7e05eaf00fa7514cbd0f5df6eecdebb15a4 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Mon, 4 Nov 2019 11:11:59 +0800
Subject: [PATCH 3/6] Support PIXMAN_i420 format
 
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 pixman/pixman-access.c | 77 ++++++++++++++++++++++++++++++++++++++++++
 pixman/pixman.c        |  4 ++-
 pixman/pixman.h        |  2 ++
 3 files changed, 82 insertions(+), 1 deletion(-)
 
diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 1e5c0ba..e7f97ea 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -192,6 +192,15 @@
     ((uint8_t *) ((bits) + offset0 +                                    \
                   ((stride) >> 1) * ((line) >> 1)))
 
+/*
+ * I420 setup and access macros
+ */
+
+#define I420_SETUP(image) YV12_SETUP(image)
+#define I420_Y(line) YV12_Y(line)
+#define I420_U(line) YV12_V(line)
+#define I420_V(line) YV12_U(line)
+
 /*
  * NV12 setup and access macros
  */
@@ -864,6 +873,43 @@ fetch_scanline_yv12 (bits_image_t   *image,
     }
 }
 
+static void
+fetch_scanline_i420 (bits_image_t   *image,
+                     int             x,
+                     int             line,
+                     int             width,
+                     uint32_t *      buffer,
+                     const uint32_t *mask)
+{
+    I420_SETUP (image);
+    uint8_t *y_line = I420_Y (line);
+    uint8_t *u_line = I420_U (line);
+    uint8_t *v_line = I420_V (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 = u_line[(x + i) >> 1] - 128;
+    v = v_line[(x + i) >> 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);
+    }
+}
+
 static void
 fetch_scanline_nv12 (bits_image_t   *image,
                      int             x,
@@ -1091,6 +1137,32 @@ fetch_pixel_yv12 (bits_image_t *image,
     (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
 }
 
+static uint32_t
+fetch_pixel_i420 (bits_image_t *image,
+          int           offset,
+          int           line)
+{
+    I420_SETUP (image);
+    int16_t y = I420_Y (line)[offset] - 16;
+    int16_t u = I420_U (line)[offset >> 1] - 128;
+    int16_t v = I420_V (line)[offset >> 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);
+}
+
 static uint32_t
 fetch_pixel_nv12 (bits_image_t *image,
           int           offset,
@@ -1589,6 +1661,11 @@ static const format_info_t accessors[] =
       fetch_scanline_yv12, fetch_scanline_generic_float,
       fetch_pixel_yv12, fetch_pixel_generic_float,
       NULL, NULL },
+
+    { PIXMAN_i420,
+      fetch_scanline_i420, fetch_scanline_generic_float,
+      fetch_pixel_i420, fetch_pixel_generic_float,
+      NULL, NULL },
     
     { PIXMAN_nv12,
       fetch_scanline_nv12, fetch_scanline_generic_float,
diff --git a/pixman/pixman.c b/pixman/pixman.c
index d8a2d24..ac06002 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_i420:
     case PIXMAN_nv12:
     return TRUE;
 
@@ -1093,7 +1094,8 @@ 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 || format == PIXMAN_nv12)
+    if (format == PIXMAN_yuy2 || format == PIXMAN_yv12 ||
+    format == PIXMAN_nv12 || format == PIXMAN_i420)
     return FALSE;
 
     return pixman_format_supported_source (format);
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 3bb2fa5..e8b0a78 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -863,6 +863,7 @@ struct pixman_indexed
 
 /* HACK: Use maximum value to avoid conflict */
 #define PIXMAN_TYPE_NV12    0x3f
+#define PIXMAN_TYPE_I420    0x3e
 
 #define PIXMAN_FORMAT_COLOR(f)                \
     (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB ||    \
@@ -945,6 +946,7 @@ 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_i420 =     PIXMAN_FORMAT(12,PIXMAN_TYPE_I420,0,0,0,0),
     PIXMAN_nv12 =     PIXMAN_FORMAT(12,PIXMAN_TYPE_NV12,0,0,0,0),
 } pixman_format_code_t;
 
-- 
2.20.1