1 /*
2 * Copyright (C) 2020 Samsung Electronics Co. Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #if __has_include(<video/mfc_macros.h>)
20 #include <video/mfc_macros.h>
21 #else
22 #include "mfc_macros_local.h"
23 #endif
24
25 #define PLANE_SIZE(w, h) ((w) * (h))
26 #define S2B_PLANE_SIZE(w, h) (GRALLOC_ALIGN((w) / 4, 16) * (GRALLOC_ALIGN(h, 16)))
27
28 /*
29 * Compute SBWC buffer geometry for a buffer containing packed SBWC YUV data
30 * with bits per pixel bpp, width w, and height h.
31 * Returns a pair of { luma size, chroma size }.
32 */
33 template <int bpp>
sbwc_sizes(int w,int h)34 static std::pair<size_t, size_t> sbwc_sizes(int w, int h) {
35 static_assert(bpp == 8 || bpp == 10, "Unexpected bit width");
36
37 const size_t luma_body_size = (bpp == 8) ?
38 SBWC_8B_Y_SIZE(w, h) : SBWC_10B_Y_SIZE(w, h);
39 const size_t luma_header_size = (bpp == 8) ?
40 SBWC_8B_Y_HEADER_SIZE(w, h) : SBWC_10B_Y_HEADER_SIZE(w, h);
41
42 const size_t chroma_body_size = (bpp == 8) ?
43 SBWC_8B_CBCR_SIZE(w, h) : SBWC_10B_CBCR_SIZE(w, h);
44 const size_t chroma_header_size = (bpp == 8) ?
45 SBWC_8B_CBCR_HEADER_SIZE(w, h) : SBWC_10B_CBCR_HEADER_SIZE(w, h);
46
47 MALI_GRALLOC_LOGV("SBWC luma body size 0x%zx, header size 0x%zx", luma_body_size, luma_header_size);
48 MALI_GRALLOC_LOGV("SBWC chroma body size 0x%zx, header size 0x%zx", chroma_body_size, chroma_header_size);
49
50 return { luma_body_size + luma_header_size,
51 chroma_body_size + chroma_header_size };
52 }
53
54 /*
55 * All setup_<format> function will returns the plane_count
56 */
57
58 /* Sets up 8-bit SBWC semi planar and returns the plane count */
setup_sbwc_420_sp(int w,int h,int fd_count,plane_info_t * plane)59 int setup_sbwc_420_sp(int w, int h, int fd_count, plane_info_t *plane)
60 {
61 std::tie(plane[0].size, plane[1].size) = sbwc_sizes<8>(w, h);
62
63 plane[0].alloc_width = GRALLOC_ALIGN(w, 32);
64 plane[0].alloc_height = __ALIGN_UP(h, 16);
65 plane[0].byte_stride = SBWC_8B_STRIDE(w);
66 plane[0].fd_idx = 0;
67
68 plane[1].alloc_width = GRALLOC_ALIGN(w, 32);
69 plane[1].alloc_height = __ALIGN_UP(h, 16) / 2;
70 plane[1].byte_stride = SBWC_8B_STRIDE(w);
71
72 if (fd_count > 1)
73 {
74 plane[1].fd_idx = 1;
75 }
76 else
77 {
78 plane[1].fd_idx = 0;
79 plane[1].offset = plane[0].size;
80 }
81
82 return 2;
83 }
84
85 /* Sets up 10-bit SBWC semi planar and returns the plane count */
setup_sbwc_420_sp_10bit(int w,int h,int fd_count,plane_info_t * plane)86 int setup_sbwc_420_sp_10bit(int w, int h, int fd_count, plane_info_t *plane)
87 {
88 std::tie(plane[0].size, plane[1].size) = sbwc_sizes<10>(w, h);
89
90 plane[0].alloc_width = GRALLOC_ALIGN(w, 32);
91 plane[0].alloc_height = __ALIGN_UP(h, 16);
92 plane[0].byte_stride = SBWC_10B_STRIDE(w);
93 plane[0].fd_idx = 0;
94
95 plane[1].alloc_width = GRALLOC_ALIGN(w, 32);
96 plane[1].alloc_height = __ALIGN_UP(h, 16) / 2;
97 plane[1].byte_stride = SBWC_10B_STRIDE(w);
98
99 if (fd_count > 1)
100 {
101 plane[1].fd_idx = 1;
102 }
103 else
104 {
105 plane[1].fd_idx = 0;
106 plane[1].offset = plane[0].size;
107 }
108
109 return 2;
110 }
111
112 /* Sets up 8-bit Lossy SBWC semi planar and returns the plane count */
setup_sbwc_420_sp_lossy(int width,int height,int rate,int fd_count,plane_info_t * plane)113 int setup_sbwc_420_sp_lossy(int width, int height, int rate, int fd_count, plane_info_t *plane)
114 {
115 plane[0].size = SBWCL_8B_Y_SIZE(width, height, rate);
116 plane[0].alloc_width = GRALLOC_ALIGN(width, 32);
117 plane[0].alloc_height = __ALIGN_UP(height, 8);
118 plane[0].byte_stride = SBWCL_8B_STRIDE(width, rate);
119 plane[0].fd_idx = 0;
120
121 plane[1].size = SBWCL_8B_CBCR_SIZE(width, height, rate);
122 plane[1].alloc_width = GRALLOC_ALIGN(width, 32);
123 plane[1].alloc_height = __ALIGN_UP(height, 8) / 2;
124 plane[1].byte_stride = SBWCL_8B_STRIDE(width, rate);
125
126 if (fd_count > 1)
127 {
128 plane[1].fd_idx = 1;
129 }
130 else
131 {
132 plane[1].fd_idx = 0;
133 plane[1].offset = plane[0].size;
134 }
135
136 return 2;
137 }
138
139
140 /* Sets up 10-bit Lossy SBWC semi planar and returns the plane count */
setup_sbwc_420_sp_10bit_lossy(int width,int height,int rate,int fd_count,plane_info_t * plane)141 int setup_sbwc_420_sp_10bit_lossy(int width, int height, int rate, int fd_count, plane_info_t *plane)
142 {
143 plane[0].size = SBWCL_10B_Y_SIZE(width, height, rate);
144 plane[0].alloc_width = GRALLOC_ALIGN(width, 32);
145 plane[0].alloc_height = __ALIGN_UP(height, 8);
146 plane[0].byte_stride = SBWCL_10B_STRIDE(width, rate);
147 plane[0].fd_idx = 0;
148
149 plane[1].size = SBWCL_10B_CBCR_SIZE(width, height, rate);
150 plane[1].alloc_width = GRALLOC_ALIGN(width, 32);
151 plane[1].alloc_height = __ALIGN_UP(height, 8) / 2;
152 plane[1].byte_stride = SBWCL_10B_STRIDE(width, rate);
153
154 if (fd_count > 1)
155 {
156 plane[1].fd_idx = 1;
157 }
158 else
159 {
160 plane[1].fd_idx = 0;
161 plane[1].offset = plane[0].size;
162 }
163
164 return 2;
165 }
166
setup_420_sp(int width,int height,int fd_count,plane_info_t * plane)167 int setup_420_sp(int width, int height, int fd_count, plane_info_t *plane)
168 {
169 /* TODO: make this into an assert instead ? */
170 height = GRALLOC_ALIGN(height, 2);
171
172 plane[0].size = PLANE_SIZE(width, height);
173 plane[0].alloc_width = width;
174 plane[0].alloc_height = height;
175 plane[0].byte_stride = width;
176 plane[0].fd_idx = 0;
177
178 int chroma_width = width;
179 int chroma_height = height / 2;
180
181 plane[1].size = PLANE_SIZE(chroma_width, chroma_height);
182 plane[1].alloc_width = chroma_width;
183 plane[1].alloc_height = chroma_height;
184 plane[1].byte_stride = chroma_width;
185
186 if (fd_count > 1)
187 {
188 plane[1].fd_idx = 1;
189 }
190 else
191 {
192 plane[1].fd_idx = 0;
193 plane[1].offset = plane[0].size;
194 }
195
196 return 2;
197 }
198
setup_420_sp_s10b(int width,int height,int fd_count,plane_info_t * plane)199 int setup_420_sp_s10b(int width, int height, int fd_count, plane_info_t *plane)
200 {
201 /* TODO: make this into an assert instead ? */
202 /* TODO: assert height aligned to 16 ? */
203 height = GRALLOC_ALIGN(height, 2);
204
205 int mscl_ext = 256;
206
207 /* HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B have special padding requirement */
208 if (fd_count == 1)
209 {
210 mscl_ext = 64;
211 }
212
213 plane[0].size = PLANE_SIZE(width, height) + S2B_PLANE_SIZE(width, height) + mscl_ext;
214 plane[0].alloc_width = width;
215 plane[0].alloc_height = height;
216 plane[0].byte_stride = width;
217 plane[0].fd_idx = 0;
218
219 int chroma_width = width;
220 int chroma_height = height / 2;
221
222 plane[1].size = PLANE_SIZE(chroma_width, chroma_height)
223 + S2B_PLANE_SIZE(chroma_width, chroma_height) + mscl_ext;
224 plane[1].alloc_width = chroma_width;
225 plane[1].alloc_height = chroma_height;
226 plane[1].byte_stride = chroma_width;
227
228 if (fd_count > 1)
229 {
230 plane[1].fd_idx = 1;
231 }
232 else
233 {
234 plane[1].fd_idx = 0;
235 plane[1].offset = plane[0].size;
236 }
237
238 return 2;
239 }
240
setup_p010_sp(int width,int height,int fd_count,plane_info_t * plane)241 int setup_p010_sp(int width, int height, int fd_count, plane_info_t *plane)
242 {
243 /* TODO: make this into an assert instead ? */
244 height = GRALLOC_ALIGN(height, 2);
245
246 plane[0].size = PLANE_SIZE(width * 2, height);
247 plane[0].alloc_width = width;
248 plane[0].alloc_height = height;
249 plane[0].byte_stride = width * 2;
250 plane[0].fd_idx = 0;
251
252 int chroma_width = width;
253 int chroma_height = height / 2;
254
255 plane[1].size = PLANE_SIZE(chroma_width * 2, chroma_height);
256 plane[1].alloc_width = chroma_width;
257 plane[1].alloc_height = chroma_height;
258 plane[1].byte_stride = chroma_width * 2;
259
260 if (fd_count > 1)
261 {
262 plane[1].fd_idx = 1;
263 }
264 else
265 {
266 plane[1].fd_idx = 0;
267 plane[1].offset = plane[0].size;
268 }
269
270 return 2;
271 }
272
setup_420_p(int width,int height,int fd_count,plane_info_t * plane)273 int setup_420_p(int width, int height, int fd_count, plane_info_t *plane)
274 {
275 /* TODO: make this into an assert instead ? */
276 width = GRALLOC_ALIGN(width, 2);
277 height = GRALLOC_ALIGN(height, 2);
278
279 plane[0].size = PLANE_SIZE(width, height);
280 plane[0].alloc_width = width;
281 plane[0].alloc_height = height;
282 plane[0].byte_stride = width;
283 plane[0].fd_idx = 0;
284
285 int chroma_width = GRALLOC_ALIGN(width / 2, 16);
286 int chroma_height = height / 2;
287
288 plane[1].size = PLANE_SIZE(chroma_width, chroma_height);
289 plane[1].alloc_width = chroma_width;
290 plane[1].alloc_height = chroma_height;
291 plane[1].byte_stride = chroma_width;
292
293 plane[2].size = PLANE_SIZE(chroma_width, chroma_height);
294 plane[2].alloc_width = chroma_width;
295 plane[2].alloc_height = chroma_height;
296 plane[2].byte_stride = chroma_width;
297
298 if (fd_count > 1)
299 {
300 plane[1].fd_idx = 1;
301 plane[2].fd_idx = 2;
302 }
303 else
304 {
305 plane[1].fd_idx = 0;
306 plane[2].fd_idx = 0;
307 plane[1].offset = plane[0].size;
308 plane[2].offset = plane[0].size + plane[1].size;
309 }
310
311 return 3;
312 }
313
setup_420_sp_tiled(int width,int height,int fd_count,plane_info_t * plane)314 int setup_420_sp_tiled(int width, int height, int fd_count, plane_info_t *plane)
315 {
316 /* TODO: make this into an assert instead ? */
317 width = GRALLOC_ALIGN(width, 2);
318 height = GRALLOC_ALIGN(height, 2);
319
320 plane[0].size = PLANE_SIZE(width, height);
321 plane[0].alloc_width = width;
322 plane[0].alloc_height = height;
323 plane[0].byte_stride = width * 16;
324 plane[0].fd_idx = 0;
325
326 int chroma_width = width;
327 int chroma_height = GRALLOC_ALIGN(height / 2, 32);
328
329 plane[1].size = PLANE_SIZE(chroma_width, chroma_height);
330 plane[1].alloc_width = chroma_width;
331 plane[1].alloc_height = chroma_height;
332 plane[1].byte_stride = chroma_width * 16;
333
334 if (fd_count > 1)
335 {
336 plane[1].fd_idx = 1;
337 }
338 else
339 {
340 plane[1].fd_idx = 0;
341 plane[1].offset = plane[0].size;
342 }
343
344 return 3;
345 }
346