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