• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2022 Advanced Micro Devices, Inc.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
17  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19  * OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Authors: AMD
22  *
23  */
24 
25 #include <string.h>
26 #include "vpe_types.h"
27 #include "vpe_priv.h"
28 #include "common.h"
29 
vpe_find_color_space_from_table(const struct vpe_color_space * table,int table_size,const struct vpe_color_space * cs)30 bool vpe_find_color_space_from_table(
31     const struct vpe_color_space *table, int table_size, const struct vpe_color_space *cs)
32 {
33     int i;
34     for (i = 0; i < table_size; i++) {
35         if (!memcmp(table, cs, sizeof(struct vpe_color_space)))
36             return true;
37     }
38     return false;
39 }
40 
vpe_is_dual_plane_format(enum vpe_surface_pixel_format format)41 bool vpe_is_dual_plane_format(enum vpe_surface_pixel_format format)
42 {
43     switch (format) {
44         // nv12/21
45     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
46     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
47         // p010
48     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
49     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
50         return true;
51     default:
52         return false;
53     }
54 }
55 
vpe_is_32bit_packed_rgb(enum vpe_surface_pixel_format format)56 bool vpe_is_32bit_packed_rgb(enum vpe_surface_pixel_format format)
57 {
58     switch (format) {
59     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
60     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
61     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA8888:
62     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
63     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBX8888:
64     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRX8888:
65     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XRGB8888:
66     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XBGR8888:
67     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
68     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA1010102:
69     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
70     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA1010102:
71         return true;
72     default:
73         return false;
74     }
75 }
76 
vpe_is_rgb8(enum vpe_surface_pixel_format format)77 bool vpe_is_rgb8(enum vpe_surface_pixel_format format)
78 {
79     switch (format) {
80     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
81     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
82     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA8888:
83     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
84     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBX8888:
85     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRX8888:
86     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XRGB8888:
87     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XBGR8888:
88         return true;
89     default:
90         return false;
91     }
92 }
93 
vpe_is_rgb10(enum vpe_surface_pixel_format format)94 bool vpe_is_rgb10(enum vpe_surface_pixel_format format)
95 {
96     switch (format) {
97     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
98     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA1010102:
99     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
100     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA1010102:
101         return true;
102     default:
103         return false;
104     }
105 }
106 
vpe_is_fp16(enum vpe_surface_pixel_format format)107 bool vpe_is_fp16(enum vpe_surface_pixel_format format)
108 {
109     switch (format) {
110     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
111     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
112     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA16161616F:
113     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA16161616F:
114         return true;
115     default:
116         return false;
117     }
118 }
119 
vpe_is_yuv420_8(enum vpe_surface_pixel_format format)120 bool vpe_is_yuv420_8(enum vpe_surface_pixel_format format)
121 {
122     switch (format) {
123     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
124     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
125         return true;
126     default:
127         return false;
128     }
129 }
130 
vpe_is_yuv420_10(enum vpe_surface_pixel_format format)131 bool vpe_is_yuv420_10(enum vpe_surface_pixel_format format)
132 {
133     switch (format) {
134     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
135     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
136         return true;
137     default:
138         return false;
139     }
140 }
141 
vpe_is_yuv420(enum vpe_surface_pixel_format format)142 bool vpe_is_yuv420(enum vpe_surface_pixel_format format)
143 {
144     return (vpe_is_yuv420_8(format) || vpe_is_yuv420_10(format));
145 }
146 
vpe_is_yuv444_8(enum vpe_surface_pixel_format format)147 bool vpe_is_yuv444_8(enum vpe_surface_pixel_format format)
148 {
149     switch (format) {
150     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
151     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_AYCbCr8888:
152         return true;
153     default:
154         return false;
155     }
156 }
157 
vpe_is_yuv444_10(enum vpe_surface_pixel_format format)158 bool vpe_is_yuv444_10(enum vpe_surface_pixel_format format)
159 {
160     switch (format) {
161     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
162     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
163         return true;
164     default:
165         return false;
166     }
167 }
168 
vpe_get_element_size_in_bytes(enum vpe_surface_pixel_format format,int plane_idx)169 static uint8_t vpe_get_element_size_in_bytes(enum vpe_surface_pixel_format format, int plane_idx)
170 {
171     switch (format) {
172         // nv12/21
173     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
174     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
175         if (plane_idx == 0)
176             return 1;
177         else
178             return 2;
179         // P010
180     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
181     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
182         if (plane_idx == 0)
183             return 2;
184         else
185             return 4;
186         // 64bpp
187     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
188     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
189     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
190     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA16161616F:
191     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA16161616F:
192         return 8;
193     default:
194         break;
195     }
196     // default 32bpp packed format
197     return 4;
198 }
199 
vpe_get_color_depth(enum vpe_surface_pixel_format format)200 enum color_depth vpe_get_color_depth(enum vpe_surface_pixel_format format)
201 {
202     enum color_depth c_depth;
203     switch (format) {
204     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGB565:
205         c_depth = COLOR_DEPTH_666;
206         break;
207     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
208     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
209     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA8888:
210     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
211     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBX8888:
212     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRX8888:
213     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XRGB8888:
214     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XBGR8888:
215     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
216     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
217     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
218     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_AYCbCr8888:
219         c_depth = COLOR_DEPTH_888;
220         break;
221     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
222     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
223     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA1010102:
224     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA1010102:
225     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
226     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
227     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
228     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
229         c_depth = COLOR_DEPTH_101010;
230         break;
231     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
232     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
233     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
234     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA16161616F:
235     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA16161616F:
236         c_depth = COLOR_DEPTH_161616;
237         break;
238     default:
239         c_depth = COLOR_DEPTH_888;
240     }
241 
242     return c_depth;
243 }
244 
vpe_has_per_pixel_alpha(enum vpe_surface_pixel_format format)245 bool vpe_has_per_pixel_alpha(enum vpe_surface_pixel_format format)
246 {
247     bool alpha = true;
248 
249     switch (format) {
250     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
251     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
252     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
253     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA8888:
254     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
255     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
256     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
257     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA1010102:
258     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA1010102:
259     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
260     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
261     case VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
262     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA16161616F:
263     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA16161616F:
264     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
265     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
266     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
267     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
268     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_AYCbCr8888:
269         alpha = true;
270         break;
271     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGB565:
272     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
273     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
274     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
275     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
276     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBE:
277     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
278     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
279     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
280     case VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
281     case VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBX8888:
282     case VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRX8888:
283     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XRGB8888:
284     case VPE_SURFACE_PIXEL_FORMAT_GRPH_XBGR8888:
285     default:
286         alpha = false;
287         break;
288     }
289 
290     return alpha;
291 }
292 
293 // Note there is another function vpe_is_hdr that performs the same function but with the translated
294 // internal VPE enums, not the api enums as done below. C does not support function overloading so
295 // another function is needed here.
is_HDR(enum vpe_transfer_function tf)296 static bool is_HDR(enum vpe_transfer_function tf)
297 {
298     return (tf == VPE_TF_PQ || tf == VPE_TF_G10 || tf == VPE_TF_HLG);
299 }
300 
vpe_check_output_support(struct vpe * vpe,const struct vpe_build_param * param)301 enum vpe_status vpe_check_output_support(struct vpe *vpe, const struct vpe_build_param *param)
302 {
303     struct vpe_priv               *vpe_priv = container_of(vpe, struct vpe_priv, pub);
304     struct vpec                   *vpec;
305     struct dpp                    *dpp;
306     struct cdc                    *cdc;
307     const struct vpe_surface_info *surface_info = &param->dst_surface;
308     struct vpe_dcc_surface_param   input;
309     struct vpe_surface_dcc_cap     output;
310     bool                           support;
311 
312     vpec = &vpe_priv->resource.vpec;
313     dpp  = vpe_priv->resource.dpp[0];
314     cdc  = vpe_priv->resource.cdc[0];
315 
316     // swizzle mode
317     support = vpec->funcs->check_swmode_support(vpec, surface_info->swizzle);
318     if (!support) {
319         vpe_log("output swizzle mode not supported %d\n", surface_info->swizzle);
320         return VPE_STATUS_SWIZZLE_NOT_SUPPORTED;
321     }
322 
323     // pitch
324     if ((surface_info->plane_size.surface_pitch *
325             vpe_get_element_size_in_bytes(surface_info->format, 0) %
326             vpe->caps->plane_caps.pitch_alignment) ||
327         ((uint32_t)(surface_info->plane_size.surface_size.x +
328                     (int32_t)surface_info->plane_size.surface_size.width) >
329             surface_info->plane_size.surface_pitch)) {
330         vpe_log("pitch alignment not supported %lu. %lu\n", surface_info->plane_size.surface_pitch,
331             vpe->caps->plane_caps.pitch_alignment);
332         return VPE_STATUS_PITCH_ALIGNMENT_NOT_SUPPORTED;
333     }
334 
335     // target rect shouldn't exceed width/height
336     if ((param->target_rect.x < surface_info->plane_size.surface_size.x ||
337             param->target_rect.x + (int32_t)param->target_rect.width >
338                 surface_info->plane_size.surface_size.x +
339                     (int32_t)surface_info->plane_size.surface_size.width)) {
340         vpe_log("target rect exceed surface boundary, target x= %d, width = %u, surface x = %d, "
341                 "width = %u\n",
342             param->target_rect.x, param->target_rect.width, surface_info->plane_size.surface_size.x,
343             surface_info->plane_size.surface_size.width);
344         return VPE_STATUS_PARAM_CHECK_ERROR;
345     }
346 
347     if ((param->target_rect.y < surface_info->plane_size.surface_size.y ||
348             param->target_rect.y + (int32_t)param->target_rect.height >
349                 surface_info->plane_size.surface_size.y +
350                     (int32_t)surface_info->plane_size.surface_size.height)) {
351         vpe_log(
352             "target rect exceed surface boundary, y= %d, height = %u, surface x = %d, width = %u\n",
353             param->target_rect.y, param->target_rect.height,
354             surface_info->plane_size.surface_size.y, surface_info->plane_size.surface_size.height);
355         return VPE_STATUS_PARAM_CHECK_ERROR;
356     }
357 
358     if (surface_info->address.type == VPE_PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) {
359         if (((uint32_t)surface_info->plane_size.chroma_pitch *
360                 vpe_get_element_size_in_bytes(surface_info->format, 1) %
361                 vpe->caps->plane_caps.pitch_alignment) ||
362             ((uint32_t)(surface_info->plane_size.chroma_size.x +
363                         (int32_t)surface_info->plane_size.chroma_size.width) >
364                 surface_info->plane_size.chroma_pitch)) {
365             vpe_log("chroma pitch alignment not supported %u. %u\n",
366                 surface_info->plane_size.chroma_pitch, vpe->caps->plane_caps.pitch_alignment);
367             return VPE_STATUS_PITCH_ALIGNMENT_NOT_SUPPORTED;
368         }
369     }
370 
371     // dcc
372     if (surface_info->dcc.enable) {
373         input.surface_size.width  = surface_info->plane_size.surface_size.width;
374         input.surface_size.height = surface_info->plane_size.surface_size.height;
375         input.format              = surface_info->format;
376         input.swizzle_mode        = surface_info->swizzle;
377         input.scan                = VPE_SCAN_DIRECTION_HORIZONTAL;
378 
379         support = vpec->funcs->get_dcc_compression_cap(vpec, &input, &output);
380         if (!support) {
381             vpe_log("output dcc not supported\n");
382             return VPE_STATUS_DCC_NOT_SUPPORTED;
383         }
384     }
385 
386     // pixel format
387     support = cdc->funcs->check_output_format(cdc, surface_info->format);
388     if (!support) {
389         vpe_log("output pixel format not supported %d\n", (int)surface_info->format);
390         return VPE_STATUS_PIXEL_FORMAT_NOT_SUPPORTED;
391     }
392 
393     // color space value
394     support = vpe_priv->resource.check_output_color_space(
395         vpe_priv, surface_info->format, &surface_info->cs);
396     if (!support) {
397         vpe_log("output color space not supported fmt: %d, "
398                 "encoding: %d, cositing: %d, gamma: %d, range: %d, primaries: %d\n",
399             (int)surface_info->format, (int)surface_info->cs.encoding,
400             (int)surface_info->cs.cositing, (int)surface_info->cs.tf, (int)surface_info->cs.range,
401             (int)surface_info->cs.primaries);
402         return VPE_STATUS_COLOR_SPACE_VALUE_NOT_SUPPORTED;
403     }
404 
405     return VPE_STATUS_OK;
406 }
407 
vpe_check_input_support(struct vpe * vpe,const struct vpe_stream * stream)408 enum vpe_status vpe_check_input_support(struct vpe *vpe, const struct vpe_stream *stream)
409 {
410     struct vpe_priv               *vpe_priv = container_of(vpe, struct vpe_priv, pub);
411     struct vpec                   *vpec;
412     struct dpp                    *dpp;
413     struct cdc                    *cdc;
414     const struct vpe_surface_info *surface_info = &stream->surface_info;
415     struct vpe_dcc_surface_param   input;
416     struct vpe_surface_dcc_cap     output;
417     bool                           support;
418     const PHYSICAL_ADDRESS_LOC    *addrloc;
419     bool                           use_adj = vpe_use_csc_adjust(&stream->color_adj);
420 
421     vpec = &vpe_priv->resource.vpec;
422     dpp  = vpe_priv->resource.dpp[0];
423     cdc  = vpe_priv->resource.cdc[0];
424 
425     // swizzle mode
426     support = vpec->funcs->check_swmode_support(vpec, surface_info->swizzle);
427     if (!support) {
428         vpe_log("input swizzle mode not supported %d\n", surface_info->swizzle);
429         return VPE_STATUS_SWIZZLE_NOT_SUPPORTED;
430     }
431 
432     // pitch & address
433     if ((surface_info->plane_size.surface_pitch *
434             vpe_get_element_size_in_bytes(surface_info->format, 0) %
435             vpe->caps->plane_caps.pitch_alignment) ||
436         ((uint32_t)(surface_info->plane_size.surface_size.x +
437                     (int32_t)surface_info->plane_size.surface_size.width) >
438             surface_info->plane_size.surface_pitch)) {
439 
440         vpe_log("pitch alignment not supported %d. %d\n", surface_info->plane_size.surface_pitch,
441             vpe->caps->plane_caps.pitch_alignment);
442         return VPE_STATUS_PITCH_ALIGNMENT_NOT_SUPPORTED;
443     }
444 
445     if (surface_info->address.type == VPE_PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) {
446 
447         addrloc = &surface_info->address.video_progressive.luma_addr;
448         if (addrloc->u.low_part % vpe->caps->plane_caps.addr_alignment) {
449             vpe_log("failed. addr not aligned to 256 bytes\n");
450             return VPE_STATUS_PLANE_ADDR_NOT_SUPPORTED;
451         }
452 
453         if (vpe_is_dual_plane_format(surface_info->format)) {
454             if ((surface_info->plane_size.chroma_pitch *
455                     vpe_get_element_size_in_bytes(surface_info->format, 1) %
456                     vpe->caps->plane_caps.pitch_alignment) ||
457                 ((uint32_t)(surface_info->plane_size.chroma_size.x +
458                             (int32_t)surface_info->plane_size.chroma_size.width) >
459                     surface_info->plane_size.chroma_pitch)) {
460                 vpe_log("chroma pitch alignment not supported %d. %d\n",
461                     surface_info->plane_size.chroma_pitch, vpe->caps->plane_caps.pitch_alignment);
462                 return VPE_STATUS_PITCH_ALIGNMENT_NOT_SUPPORTED;
463             }
464 
465             addrloc = &surface_info->address.video_progressive.chroma_addr;
466             if (addrloc->u.low_part % vpe->caps->plane_caps.addr_alignment) {
467                 vpe_log("failed. addr not aligned to 256 bytes\n");
468                 return VPE_STATUS_PLANE_ADDR_NOT_SUPPORTED;
469             }
470         }
471     } else {
472         addrloc = &surface_info->address.grph.addr;
473         if (addrloc->u.low_part % vpe->caps->plane_caps.addr_alignment) {
474             vpe_log("failed. addr not aligned to 256 bytes\n");
475             return VPE_STATUS_PLANE_ADDR_NOT_SUPPORTED;
476         }
477     }
478 
479     // dcc
480     if (surface_info->dcc.enable) {
481 
482         input.surface_size.width  = surface_info->plane_size.surface_size.width;
483         input.surface_size.height = surface_info->plane_size.surface_size.height;
484         input.format              = surface_info->format;
485         input.swizzle_mode        = surface_info->swizzle;
486 
487         if (stream->rotation == VPE_ROTATION_ANGLE_0 || stream->rotation == VPE_ROTATION_ANGLE_180)
488             input.scan = VPE_SCAN_DIRECTION_HORIZONTAL;
489         else if (stream->rotation == VPE_ROTATION_ANGLE_90 ||
490                  stream->rotation == VPE_ROTATION_ANGLE_270)
491             input.scan = VPE_SCAN_DIRECTION_VERTICAL;
492         else
493             input.scan = VPE_SCAN_DIRECTION_UNKNOWN;
494 
495         support = vpec->funcs->get_dcc_compression_cap(vpec, &input, &output);
496         if (!support) {
497             vpe_log("input dcc not supported\n");
498             return VPE_STATUS_DCC_NOT_SUPPORTED;
499         }
500     }
501 
502     // pixel format
503     support = cdc->funcs->check_input_format(cdc, surface_info->format);
504     if (!support) {
505         vpe_log("input pixel format not supported %d\n", (int)surface_info->format);
506         return VPE_STATUS_PIXEL_FORMAT_NOT_SUPPORTED;
507     }
508 
509     // color space value
510     support = vpe_priv->resource.check_input_color_space(
511         vpe_priv, surface_info->format, &surface_info->cs);
512     if (!support) {
513         vpe_log("input color space not supported fmt: %d, "
514                 "encoding: %d, cositing: %d, gamma: %d, range: %d, primaries: %d\n",
515             (int)surface_info->format, (int)surface_info->cs.encoding,
516             (int)surface_info->cs.cositing, (int)surface_info->cs.tf, (int)surface_info->cs.range,
517             (int)surface_info->cs.primaries);
518         return VPE_STATUS_COLOR_SPACE_VALUE_NOT_SUPPORTED;
519     }
520 
521     // TODO: Add support
522     // adjustments
523     if (surface_info->cs.primaries == VPE_PRIMARIES_BT2020 &&
524         surface_info->cs.encoding == VPE_PIXEL_ENCODING_RGB && use_adj) {
525         // for BT2020 + RGB input with adjustments, it is expected not working.
526         vpe_log("for BT2020 + RGB input with adjustments, it is expected not working\n");
527         return VPE_STATUS_ADJUSTMENT_NOT_SUPPORTED;
528     }
529 
530     // rotation
531     if ((stream->rotation != VPE_ROTATION_ANGLE_0) && !vpe->caps->rotation_support) {
532         vpe_log("output rotation not supported\n");
533         return VPE_STATUS_ROTATION_NOT_SUPPORTED;
534     }
535 
536     // luma keying
537     if (stream->enable_luma_key && !vpe->caps->color_caps.dpp.luma_key) {
538         vpe_log("luma keying not supported\n");
539         return VPE_STATUS_LUMA_KEYING_NOT_SUPPORTED;
540     }
541 
542     if (stream->horizontal_mirror && !vpe->caps->h_mirror_support) {
543         vpe_log("output horizontal mirroring not supported h:%d\n", (int)stream->horizontal_mirror);
544         return VPE_STATUS_MIRROR_NOT_SUPPORTED;
545     }
546 
547     if (stream->vertical_mirror && !vpe->caps->v_mirror_support) {
548         vpe_log("output vertical mirroring not supported v:%d\n", (int)stream->vertical_mirror);
549         return VPE_STATUS_MIRROR_NOT_SUPPORTED;
550     }
551 
552     return VPE_STATUS_OK;
553 }
554 
vpe_cache_tone_map_params(struct stream_ctx * stream_ctx,const struct vpe_stream * stream)555 enum vpe_status vpe_cache_tone_map_params(
556     struct stream_ctx *stream_ctx, const struct vpe_stream *stream)
557 {
558     stream_ctx->update_3dlut = stream_ctx->update_3dlut || stream->tm_params.update_3dlut ||
559             stream->tm_params.UID || (stream_ctx->stream.flags.geometric_scaling != stream->flags.geometric_scaling);
560 
561     return VPE_STATUS_OK;
562 }
563 
vpe_check_tone_map_support(struct vpe * vpe,const struct vpe_stream * stream,const struct vpe_build_param * param)564 enum vpe_status vpe_check_tone_map_support(
565     struct vpe *vpe, const struct vpe_stream *stream, const struct vpe_build_param *param)
566 {
567     enum vpe_status status = VPE_STATUS_OK;
568     bool input_is_hdr = is_HDR(stream->surface_info.cs.tf);
569     bool is_3D_lut_enabled = stream->tm_params.enable_3dlut || stream->tm_params.UID;
570     bool is_hlg = stream->tm_params.shaper_tf == VPE_TF_HLG;
571     bool is_in_lum_greater_than_out_lum = stream->hdr_metadata.max_mastering > param->hdr_metadata.max_mastering;
572 
573     // Check if Tone Mapping parameters are valid
574     if (is_3D_lut_enabled) {
575         if ((stream->tm_params.lut_data == NULL) ||
576             (!input_is_hdr) ||
577             (!is_hlg && !is_in_lum_greater_than_out_lum)) {
578             status = VPE_STATUS_BAD_TONE_MAP_PARAMS;
579         }
580     } else {
581         if (is_hlg ||
582             (input_is_hdr && is_in_lum_greater_than_out_lum)) {
583             status = VPE_STATUS_BAD_TONE_MAP_PARAMS;
584         }
585     }
586 
587     return status;
588 }
589