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