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