1 /**************************************************************************
2 *
3 * Copyright 2022 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <pipe/p_state.h>
33 #include <si_pipe.h>
34 #include "si_vpe.h"
35
36 #define SI_VPE_LOG_LEVEL_DEFAULT 0
37 #define SI_VPE_LOG_LEVEL_INFO 1
38 #define SI_VPE_LOG_LEVEL_WARNING 2
39 #define SI_VPE_LOG_LEVEL_DEBUG 3
40
41 #define SIVPE_INFO(dblv, fmt, args...) \
42 if ((dblv) >= SI_VPE_LOG_LEVEL_INFO) { \
43 printf("SIVPE INFO: %s: " fmt, __func__, ##args); \
44 }
45
46 #define SIVPE_WARN(dblv, fmt, args...) \
47 if ((dblv) >= SI_VPE_LOG_LEVEL_WARNING) { \
48 printf("SIVPE WARNING: %s: " fmt, __func__, ##args); \
49 }
50
51 #define SIVPE_DBG(dblv, fmt, args...) \
52 if ((dblv) >= SI_VPE_LOG_LEVEL_DEBUG) { \
53 printf("SIVPE DBG: %s: " fmt, __func__, ##args); \
54 }
55
56 #define SIVPE_ERR(fmt, args...) \
57 fprintf(stderr, "SIVPE ERROR %s:%d %s " fmt, __FILE__, __LINE__, __func__, ##args)
58
59 #define SIVPE_PRINT(fmt, args...) \
60 printf("SIVPE %s: " fmt, __func__, ##args);
61
62 /* Pre-defined color primaries of BT601, BT709, BT2020 */
63 static struct vpe_hdr_metadata Color_Parimaries[] = {
64 /* RedX RedY GreenX GreenY BlueX BlueY WhiteX WhiteY minlum maxlum maxlig avglig*/
65 [VPE_PRIMARIES_BT601] = {31500, 17000, 15500, 29750, 7750, 3500, 15635, 16450, 10, 270, 1, 1},
66 [VPE_PRIMARIES_BT709] = {32000, 16500, 15000, 30000, 7500, 3000, 15635, 16450, 10, 270, 1, 1},
67 [VPE_PRIMARIES_BT2020] = {34000, 16000, 13249, 34500, 7500, 3000, 15635, 16450, 10, 1100, 1, 1},
68 };
69
70 /* Use this enum to help us for accessing the anonymous struct src, dst
71 * in blit_info.
72 */
73 enum {
74 USE_SRC_SURFACE,
75 USE_DST_SURFACE
76 };
77
78 static void *
si_vpe_zalloc(void * mem_ctx,size_t size)79 si_vpe_zalloc(void* mem_ctx, size_t size)
80 {
81 /* mem_ctx is optional for now */
82 return CALLOC(1, size);
83 }
84
85 static void
si_vpe_free(void * mem_ctx,void * ptr)86 si_vpe_free(void* mem_ctx, void *ptr)
87 {
88 /* mem_ctx is optional for now */
89 if (ptr != NULL) {
90 FREE(ptr);
91 ptr = NULL;
92 }
93 }
94
95 static void
si_vpe_log(void * log_ctx,const char * fmt,...)96 si_vpe_log(void* log_ctx, const char* fmt, ...)
97 {
98 /* log_ctx is optional for now */
99 va_list args;
100
101 va_start(args, fmt);
102 vfprintf(stderr, fmt, args);
103 va_end(args);
104 }
105
106 static void
si_vpe_log_silent(void * log_ctx,const char * fmt,...)107 si_vpe_log_silent(void* log_ctx, const char* fmt, ...)
108 {
109 }
110
111 static void
si_vpe_populate_debug_options(struct vpe_debug_options * debug)112 si_vpe_populate_debug_options(struct vpe_debug_options* debug)
113 {
114 /* Enable debug options here if needed */
115 }
116
117 static void
si_vpe_populate_callback_modules(struct vpe_callback_funcs * funcs,uint8_t log_level)118 si_vpe_populate_callback_modules(struct vpe_callback_funcs* funcs, uint8_t log_level)
119 {
120 funcs->log = log_level ? si_vpe_log : si_vpe_log_silent;
121 funcs->zalloc = si_vpe_zalloc;
122 funcs->free = si_vpe_free;
123 }
124
125 static char*
si_vpe_get_cositing_str(enum vpe_chroma_cositing cositing)126 si_vpe_get_cositing_str(enum vpe_chroma_cositing cositing)
127 {
128 switch (cositing) {
129 case VPE_CHROMA_COSITING_NONE:
130 return "NONE";
131 case VPE_CHROMA_COSITING_LEFT:
132 return "LEFT";
133 case VPE_CHROMA_COSITING_TOPLEFT:
134 return "TOPLEFT";
135 case VPE_CHROMA_COSITING_COUNT:
136 default:
137 return "ERROR";
138 }
139 }
140
141 static char*
si_vpe_get_primarie_str(enum vpe_color_primaries primarie)142 si_vpe_get_primarie_str(enum vpe_color_primaries primarie)
143 {
144 switch (primarie) {
145 case VPE_PRIMARIES_BT601:
146 return "BT601";
147 case VPE_PRIMARIES_BT709:
148 return "BT709";
149 case VPE_PRIMARIES_BT2020:
150 return "BT2020";
151 case VPE_PRIMARIES_JFIF:
152 return "JFIF";
153 case VPE_PRIMARIES_COUNT:
154 default:
155 return "ERROR";
156 }
157 }
158
159 static char*
si_vpe_get_tf_str(enum vpe_transfer_function tf)160 si_vpe_get_tf_str(enum vpe_transfer_function tf)
161 {
162 switch (tf) {
163 case VPE_TF_G22:
164 return "G22";
165 case VPE_TF_G24:
166 return "G24";
167 case VPE_TF_G10:
168 return "G10";
169 case VPE_TF_PQ:
170 return "PQ";
171 case VPE_TF_PQ_NORMALIZED:
172 return "PQ_NORMALIZED";
173 case VPE_TF_HLG:
174 return "HLG";
175 case VPE_TF_SRGB:
176 return "SRGB";
177 case VPE_TF_BT709:
178 return "BT709";
179 case VPE_TF_COUNT:
180 default:
181 return "ERROR";
182 }
183 }
184
185 /* cycle to the next set of buffers */
186 static void
next_buffer(struct vpe_video_processor * vpeproc)187 next_buffer(struct vpe_video_processor *vpeproc)
188 {
189 ++vpeproc->cur_buf;
190 vpeproc->cur_buf %= vpeproc->bufs_num;
191 }
192
193 static enum vpe_status
si_vpe_populate_init_data(struct si_context * sctx,struct vpe_init_data * params,uint8_t log_level)194 si_vpe_populate_init_data(struct si_context *sctx, struct vpe_init_data* params, uint8_t log_level)
195 {
196 if (!sctx || !params)
197 return VPE_STATUS_ERROR;
198
199 params->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
200 params->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
201 params->ver_rev = sctx->screen->info.ip[AMD_IP_VPE].ver_rev;
202
203 memset(¶ms->debug, 0, sizeof(struct vpe_debug_options));
204 si_vpe_populate_debug_options(¶ms->debug);
205 si_vpe_populate_callback_modules(¶ms->funcs, log_level);
206
207 SIVPE_DBG(log_level, "Get family: %d\n", sctx->family);
208 SIVPE_DBG(log_level, "Get gfx_level: %d\n", sctx->gfx_level);
209 SIVPE_DBG(log_level, "Set ver_major: %d\n", params->ver_major);
210 SIVPE_DBG(log_level, "Set ver_minor: %d\n", params->ver_minor);
211 SIVPE_DBG(log_level, "Set ver_rev: %d\n", params->ver_rev);
212
213 return VPE_STATUS_OK;
214 }
215
216
217 static enum vpe_status
si_vpe_allocate_buffer(struct vpe_build_bufs ** bufs)218 si_vpe_allocate_buffer(struct vpe_build_bufs **bufs)
219 {
220 if (!bufs)
221 return VPE_STATUS_ERROR;
222
223 *bufs = (struct vpe_build_bufs *)MALLOC(sizeof(struct vpe_build_bufs));
224 if (!*bufs)
225 return VPE_STATUS_NO_MEMORY;
226
227 (*bufs)->cmd_buf.cpu_va = 0;
228 (*bufs)->emb_buf.cpu_va = 0;
229 (*bufs)->cmd_buf.size = 0;
230 (*bufs)->emb_buf.size = 0;
231
232 return VPE_STATUS_OK;
233 }
234
235 static void
si_vpe_free_buffer(struct vpe_build_bufs * bufs)236 si_vpe_free_buffer(struct vpe_build_bufs *bufs)
237 {
238 if (!bufs)
239 return;
240
241 free(bufs);
242 }
243
244 static enum vpe_surface_pixel_format
si_vpe_pipe_map_to_vpe_format(enum pipe_format format)245 si_vpe_pipe_map_to_vpe_format(enum pipe_format format)
246 {
247 enum vpe_surface_pixel_format ret;
248
249 switch (format) {
250 /* YUV format: */
251 case PIPE_FORMAT_NV12:
252 ret = VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb;
253 break;
254 case PIPE_FORMAT_NV21:
255 ret = VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr;
256 break;
257 case PIPE_FORMAT_P010:
258 ret = VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb;
259 break;
260 /* RGB format: */
261 case PIPE_FORMAT_A8R8G8B8_UNORM:
262 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA8888;
263 break;
264 case PIPE_FORMAT_A8B8G8R8_UNORM:
265 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA8888;
266 break;
267 case PIPE_FORMAT_R8G8B8A8_UNORM:
268 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR8888;
269 break;
270 case PIPE_FORMAT_B8G8R8A8_UNORM:
271 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
272 break;
273 case PIPE_FORMAT_X8R8G8B8_UNORM:
274 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRX8888;
275 break;
276 case PIPE_FORMAT_X8B8G8R8_UNORM:
277 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBX8888;
278 break;
279 case PIPE_FORMAT_R8G8B8X8_UNORM:
280 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_XBGR8888;
281 break;
282 case PIPE_FORMAT_B8G8R8X8_UNORM:
283 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_XRGB8888;
284 break;
285 /* ARGB 2-10-10-10 formats are not supported in Mesa VA-frontend
286 * but they are defined in Mesa already.
287 */
288 case PIPE_FORMAT_A2R10G10B10_UNORM:
289 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA1010102;
290 break;
291 case PIPE_FORMAT_A2B10G10R10_UNORM:
292 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA1010102;
293 break;
294 case PIPE_FORMAT_B10G10R10A2_UNORM:
295 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010;
296 break;
297 case PIPE_FORMAT_R10G10B10A2_UNORM:
298 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010;
299 break;
300 default:
301 ret = VPE_SURFACE_PIXEL_FORMAT_INVALID;
302 break;
303 }
304 return ret;
305 }
306
307 static enum vpe_color_primaries
si_vpe_maps_vpp_to_vpe_primaries(enum pipe_video_vpp_color_primaries colour_primaries)308 si_vpe_maps_vpp_to_vpe_primaries(enum pipe_video_vpp_color_primaries colour_primaries)
309 {
310 if (colour_primaries == PIPE_VIDEO_VPP_PRI_BT470BG || colour_primaries == PIPE_VIDEO_VPP_PRI_SMPTE170M)
311 return VPE_PRIMARIES_BT601;
312
313 else if (colour_primaries == PIPE_VIDEO_VPP_PRI_BT709)
314 return VPE_PRIMARIES_BT709;
315
316 else if (colour_primaries == PIPE_VIDEO_VPP_PRI_BT2020)
317 return VPE_PRIMARIES_BT2020;
318
319 SIVPE_PRINT("WARNING: map VA-API primaries(%d) to BT709\n", colour_primaries);
320 return VPE_PRIMARIES_BT709;
321 }
322
323 static enum vpe_transfer_function
si_vpe_maps_vpp_to_vpe_transfer_function(enum pipe_video_vpp_transfer_characteristic transfer_characteristics,enum pipe_video_vpp_matrix_coefficients matrix_coefficients)324 si_vpe_maps_vpp_to_vpe_transfer_function(
325 enum pipe_video_vpp_transfer_characteristic transfer_characteristics,
326 enum pipe_video_vpp_matrix_coefficients matrix_coefficients)
327 {
328 if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_BT709)
329 return (matrix_coefficients == PIPE_VIDEO_VPP_MCF_RGB)? VPE_TF_SRGB : VPE_TF_BT709;
330
331 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_GAMMA22)
332 return VPE_TF_G22;
333
334 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_SMPTEST2084)
335 return VPE_TF_PQ;
336
337 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_LINEAR)
338 return VPE_TF_G10;
339
340 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_ARIB_STD_B67)
341 return VPE_TF_HLG;
342
343 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_BT2020_10)
344 return VPE_TF_G10;
345
346 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_SMPTEST428_1)
347 return VPE_TF_G24;
348
349 else if (transfer_characteristics == PIPE_VIDEO_VPP_TRC_BT2020_12)
350 return (matrix_coefficients == PIPE_VIDEO_VPP_MCF_RGB)? VPE_TF_SRGB : VPE_TF_BT709;
351
352 SIVPE_PRINT("WARNING: map VA-API transfer_characteristics(%d) to BT709/SRGB\n", transfer_characteristics);
353 return (matrix_coefficients == PIPE_VIDEO_VPP_MCF_RGB)? VPE_TF_SRGB : VPE_TF_BT709;
354 }
355
356 static void
si_vpe_load_default_primaries(struct vpe_hdr_metadata * vpe_hdr,enum vpe_color_primaries primaries)357 si_vpe_load_default_primaries(struct vpe_hdr_metadata* vpe_hdr, enum vpe_color_primaries primaries)
358 {
359 enum vpe_color_primaries pri_idx = (primaries < VPE_PRIMARIES_COUNT)?
360 primaries : VPE_PRIMARIES_BT709;
361
362 vpe_hdr->redX = Color_Parimaries[pri_idx].redX;
363 vpe_hdr->redY = Color_Parimaries[pri_idx].redY;
364 vpe_hdr->greenX = Color_Parimaries[pri_idx].greenX;
365 vpe_hdr->greenY = Color_Parimaries[pri_idx].greenY;
366 vpe_hdr->blueX = Color_Parimaries[pri_idx].blueX;
367 vpe_hdr->blueY = Color_Parimaries[pri_idx].blueY;
368 vpe_hdr->whiteX = Color_Parimaries[pri_idx].whiteX;
369 vpe_hdr->whiteY = Color_Parimaries[pri_idx].whiteY;
370 vpe_hdr->min_mastering = Color_Parimaries[pri_idx].min_mastering;
371 vpe_hdr->max_mastering = Color_Parimaries[pri_idx].max_mastering;
372 vpe_hdr->max_content = Color_Parimaries[pri_idx].max_content;
373 vpe_hdr->avg_content = Color_Parimaries[pri_idx].avg_content;
374 }
375
376 static void
si_vpe_set_color_space(const struct pipe_vpp_desc * process_properties,struct vpe_color_space * color_space,enum pipe_format format,int which_surface)377 si_vpe_set_color_space(const struct pipe_vpp_desc *process_properties,
378 struct vpe_color_space *color_space,
379 enum pipe_format format,
380 int which_surface)
381 {
382 enum pipe_video_vpp_color_standard_type colors_standard;
383 enum pipe_video_vpp_color_range color_range;
384 enum pipe_video_vpp_chroma_siting chroma_siting;
385 enum pipe_video_vpp_color_primaries colour_primaries;
386 enum pipe_video_vpp_transfer_characteristic transfer_characteristics;
387 enum pipe_video_vpp_matrix_coefficients matrix_coefficients;
388
389 if (which_surface == USE_SRC_SURFACE) {
390 colors_standard = process_properties->in_colors_standard;
391 color_range = process_properties->in_color_range;
392 chroma_siting = process_properties->in_chroma_siting;
393 colour_primaries = process_properties->in_color_primaries;
394 transfer_characteristics = process_properties->in_transfer_characteristics;
395 matrix_coefficients = process_properties->in_matrix_coefficients;
396 } else {
397 colors_standard = process_properties->out_colors_standard;
398 color_range = process_properties->out_color_range;
399 chroma_siting = process_properties->out_chroma_siting;
400 colour_primaries = process_properties->out_color_primaries;
401 transfer_characteristics = process_properties->out_transfer_characteristics;
402 matrix_coefficients = process_properties->out_matrix_coefficients;
403 }
404
405 switch (colors_standard) {
406 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_EXPLICIT:
407 /* use original settings from user application */
408 break;
409
410 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601:
411 colour_primaries = PIPE_VIDEO_VPP_PRI_SMPTE170M;
412 transfer_characteristics = PIPE_VIDEO_VPP_TRC_SMPTE170M;
413 matrix_coefficients = PIPE_VIDEO_VPP_MCF_SMPTE170M;
414 break;
415
416 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020:
417 colour_primaries = PIPE_VIDEO_VPP_PRI_BT2020;
418 transfer_characteristics = PIPE_VIDEO_VPP_TRC_BT2020_10;
419 matrix_coefficients = PIPE_VIDEO_VPP_MCF_BT2020_NCL;
420 break;
421
422 default:
423 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709:
424 colour_primaries = PIPE_VIDEO_VPP_PRI_BT709;
425 transfer_characteristics = PIPE_VIDEO_VPP_TRC_BT709;
426 matrix_coefficients = PIPE_VIDEO_VPP_MCF_BT709;
427 break;
428 }
429
430 switch (format) {
431 case PIPE_FORMAT_NV12:
432 case PIPE_FORMAT_NV21:
433 case PIPE_FORMAT_P010:
434 color_space->encoding = VPE_PIXEL_ENCODING_YCbCr;
435 break;
436 case PIPE_FORMAT_A8R8G8B8_UNORM:
437 case PIPE_FORMAT_A8B8G8R8_UNORM:
438 case PIPE_FORMAT_R8G8B8A8_UNORM:
439 case PIPE_FORMAT_B8G8R8A8_UNORM:
440 case PIPE_FORMAT_X8R8G8B8_UNORM:
441 case PIPE_FORMAT_X8B8G8R8_UNORM:
442 case PIPE_FORMAT_R8G8B8X8_UNORM:
443 case PIPE_FORMAT_B8G8R8X8_UNORM:
444 case PIPE_FORMAT_A2R10G10B10_UNORM:
445 case PIPE_FORMAT_R10G10B10A2_UNORM:
446 case PIPE_FORMAT_A2B10G10R10_UNORM:
447 case PIPE_FORMAT_B10G10R10A2_UNORM:
448 default:
449 matrix_coefficients = PIPE_VIDEO_VPP_MCF_RGB;
450 color_space->encoding = VPE_PIXEL_ENCODING_RGB;
451 break;
452 }
453
454 switch (color_range) {
455 case PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED:
456 color_space->range = VPE_COLOR_RANGE_STUDIO;
457 break;
458 default:
459 case PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL:
460 color_space->range = VPE_COLOR_RANGE_FULL;
461 break;
462 }
463
464 /* Force RGB output range is Full to have better color performance */
465 /* TO-DO: Should Mesa have to know the display console is TV or PC Monitor? */
466 if (!util_format_is_yuv(format) && (which_surface == USE_DST_SURFACE))
467 color_space->range = VPE_COLOR_RANGE_FULL;
468
469 /* Default use VPE_CHROMA_COSITING_NONE (CENTER | CENTER) */
470 color_space->cositing = VPE_CHROMA_COSITING_NONE;
471 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER){
472 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT)
473 color_space->cositing = VPE_CHROMA_COSITING_LEFT;
474 } else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP) {
475 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT)
476 color_space->cositing = VPE_CHROMA_COSITING_TOPLEFT;
477 } else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM) {
478 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT)
479 color_space->cositing = VPE_CHROMA_COSITING_LEFT;
480 }
481
482 color_space->primaries = si_vpe_maps_vpp_to_vpe_primaries(colour_primaries);
483 color_space->tf = si_vpe_maps_vpp_to_vpe_transfer_function(transfer_characteristics, matrix_coefficients);
484 }
485
486 static enum vpe_status
si_vpe_set_plane_info(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct pipe_surface ** surfaces,int which_surface,struct vpe_surface_info * surface_info)487 si_vpe_set_plane_info(struct vpe_video_processor *vpeproc,
488 const struct pipe_vpp_desc *process_properties,
489 struct pipe_surface **surfaces,
490 int which_surface,
491 struct vpe_surface_info *surface_info)
492 {
493 struct vpe_plane_address *plane_address = &surface_info->address;
494 struct vpe_plane_size *plane_size = &surface_info->plane_size;
495 struct si_texture *si_tex_0;
496 struct si_texture *si_tex_1;
497 enum pipe_format format;
498
499 if (which_surface == USE_SRC_SURFACE)
500 format = process_properties->base.input_format;
501 else
502 format = process_properties->base.output_format;
503
504 /* Trusted memory not supported now */
505 plane_address->tmz_surface = false;
506
507 /* Only support 1 plane for RGB formats, and 2 plane format for YUV formats */
508 if (util_format_is_yuv(format) && util_format_get_num_planes(format) == 2) {
509 si_tex_0 = (struct si_texture *)surfaces[0]->texture;
510 si_tex_1 = (struct si_texture *)surfaces[1]->texture;
511 plane_address->type = VPE_PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
512 plane_address->video_progressive.luma_addr.quad_part = si_tex_0->buffer.gpu_address + si_tex_0->surface.u.gfx9.surf_offset;
513 plane_address->video_progressive.chroma_addr.quad_part = si_tex_1->buffer.gpu_address + si_tex_1->surface.u.gfx9.surf_offset;
514 } else if (!util_format_is_yuv(format) && util_format_get_num_planes(format) == 1){
515 si_tex_0 = (struct si_texture *)surfaces[0]->texture;
516 si_tex_1 = NULL;
517 plane_address->type = VPE_PLN_ADDR_TYPE_GRAPHICS;
518 plane_address->grph.addr.quad_part = si_tex_0->buffer.gpu_address + si_tex_0->surface.u.gfx9.surf_offset;
519 } else
520 return VPE_STATUS_NOT_SUPPORTED;
521
522 /* 1st plane ret setting */
523 plane_size->surface_size.x = 0;
524 plane_size->surface_size.y = 0;
525 plane_size->surface_size.width = surfaces[0]->width;
526 plane_size->surface_size.height = surfaces[0]->height;
527 plane_size->surface_pitch = si_tex_0->surface.u.gfx9.surf_pitch;
528 plane_size->surface_aligned_height = surfaces[0]->height;
529
530 /* YUV 2nd plane ret setting */
531 if (util_format_get_num_planes(format) == 2) {
532 plane_size->chroma_size.x = 0;
533 plane_size->chroma_size.y = 0;
534 plane_size->chroma_size.width = surfaces[1]->width;
535 plane_size->chroma_size.height = surfaces[1]->height;
536 plane_size->chroma_pitch = si_tex_1->surface.u.gfx9.surf_pitch;
537 plane_size->chrome_aligned_height = surfaces[1]->height;
538 }
539
540 /* Color space setting */
541 surface_info->format = si_vpe_pipe_map_to_vpe_format(format);
542 si_vpe_set_color_space(process_properties, &surface_info->cs, format, which_surface);
543 return VPE_STATUS_OK;
544 }
545
546 static enum vpe_status
si_vpe_set_surface_info(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct pipe_surface ** surfaces,int which_surface,struct vpe_surface_info * surface_info)547 si_vpe_set_surface_info(struct vpe_video_processor *vpeproc,
548 const struct pipe_vpp_desc *process_properties,
549 struct pipe_surface **surfaces,
550 int which_surface,
551 struct vpe_surface_info *surface_info)
552 {
553 assert(surface_info);
554
555 /* Set up surface pitch, plane address, color space */
556 if (VPE_STATUS_OK != si_vpe_set_plane_info(vpeproc, process_properties, surfaces, which_surface, surface_info))
557 return VPE_STATUS_NOT_SUPPORTED;
558
559 struct si_texture *tex = (struct si_texture *)surfaces[0]->texture;
560 surface_info->swizzle = tex->surface.u.gfx9.swizzle_mode;
561
562 /* DCC not supported */
563 if (tex->surface.meta_offset)
564 return VPE_STATUS_NOT_SUPPORTED;
565
566 struct vpe_plane_dcc_param *dcc_param = &surface_info->dcc;
567 dcc_param->enable = false;
568 dcc_param->meta_pitch = 0;
569 dcc_param->independent_64b_blks = false;
570 dcc_param->dcc_ind_blk = 0;
571 dcc_param->meta_pitch_c = 0;
572 dcc_param->independent_64b_blks_c = false;
573 dcc_param->dcc_ind_blk_c = 0;
574
575 return VPE_STATUS_OK;
576 }
577
578 static void
si_vpe_set_stream_in_param(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct vpe_stream * stream)579 si_vpe_set_stream_in_param(struct vpe_video_processor *vpeproc,
580 const struct pipe_vpp_desc *process_properties,
581 struct vpe_stream *stream)
582 {
583 struct vpe *vpe_handle = vpeproc->vpe_handle;
584 struct vpe_scaling_info *scaling_info = &stream->scaling_info;
585 struct vpe_blend_info *blend_info = &stream->blend_info;
586 struct vpe_color_adjust *color_adj = &stream->color_adj;
587
588 /* Init: scaling_info */
589 scaling_info->src_rect.x = process_properties->src_region.x0;
590 scaling_info->src_rect.y = process_properties->src_region.y0;
591 scaling_info->src_rect.width = process_properties->src_region.x1 - process_properties->src_region.x0;
592 scaling_info->src_rect.height = process_properties->src_region.y1 - process_properties->src_region.y0;
593 scaling_info->dst_rect.x = process_properties->dst_region.x0;
594 scaling_info->dst_rect.y = process_properties->dst_region.y0;
595 scaling_info->dst_rect.width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
596 scaling_info->dst_rect.height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
597 scaling_info->taps.v_taps = 0;
598 scaling_info->taps.h_taps = 0;
599 scaling_info->taps.v_taps_c = 2;
600 scaling_info->taps.h_taps_c = 2;
601
602 vpe_get_optimal_num_of_taps(vpe_handle, scaling_info);
603
604 blend_info->blending = false;
605 blend_info->pre_multiplied_alpha = false;
606 blend_info->global_alpha = blend_info->blending;
607 blend_info->global_alpha_value = 1.0;
608
609 /* Global Alpha for Background ? */
610 if (process_properties->blend.mode == PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA) {
611 //blend_info->global_alpha = true;
612 blend_info->global_alpha_value = process_properties->blend.global_alpha;
613 }
614
615 /* TO-DO: do ProcAmp in next stage */
616 color_adj->brightness = 0.0;
617 color_adj->contrast = 1.0;
618 color_adj->hue = 0.0;
619 color_adj->saturation = 1.0;
620
621 switch (process_properties->orientation & 0xF) {
622 case PIPE_VIDEO_VPP_ROTATION_90:
623 stream->rotation = VPE_ROTATION_ANGLE_90;
624 break;
625 case PIPE_VIDEO_VPP_ROTATION_180:
626 stream->rotation = VPE_ROTATION_ANGLE_180;
627 break;
628 case PIPE_VIDEO_VPP_ROTATION_270:
629 stream->rotation = VPE_ROTATION_ANGLE_270;
630 break;
631 default:
632 stream->rotation = VPE_ROTATION_ANGLE_0;
633 break;
634 }
635
636 stream->horizontal_mirror = (process_properties->orientation & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? true : false;
637 stream->vertical_mirror = (process_properties->orientation & PIPE_VIDEO_VPP_FLIP_VERTICAL) ? true : false;
638
639 stream->enable_luma_key = false;
640 stream->lower_luma_bound = 0.5;
641 stream->upper_luma_bound = 0.5;
642
643 stream->flags.reserved = 0;
644 stream->flags.geometric_scaling = 0;
645 stream->flags.hdr_metadata = 0;
646
647 /* TO-DO: support HDR10 Metadata */
648 si_vpe_load_default_primaries(&stream->hdr_metadata, stream->surface_info.cs.primaries);
649 }
650
651 static void
si_vpe_set_stream_out_param(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct vpe_build_param * build_param)652 si_vpe_set_stream_out_param(struct vpe_video_processor *vpeproc,
653 const struct pipe_vpp_desc *process_properties,
654 struct vpe_build_param *build_param)
655 {
656 uint32_t background_color = process_properties->background_color;
657
658 build_param->target_rect.x = process_properties->dst_region.x0;
659 build_param->target_rect.y = process_properties->dst_region.y0;
660 build_param->target_rect.width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
661 build_param->target_rect.height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
662
663 build_param->bg_color.is_ycbcr = false;
664 build_param->bg_color.rgba.r = 0;
665 build_param->bg_color.rgba.g = 0;
666 build_param->bg_color.rgba.b = 0;
667 build_param->bg_color.rgba.a = 0;
668
669 /* Studio color range not start from 0 */
670 if (!(background_color & 0xFFFFFF) && (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_STUDIO)) {
671 build_param->bg_color.rgba.a = (float)((background_color & 0xFF000000) >> 24) / 255.0;
672 build_param->bg_color.rgba.r = 0.0628;
673 build_param->bg_color.rgba.g = 0.0628;
674 build_param->bg_color.rgba.b = 0.0628;
675 } else if (process_properties->background_color) {
676 build_param->bg_color.rgba.a = (float)((background_color & 0xFF000000) >> 24) / 255.0;
677 build_param->bg_color.rgba.r = (float)((background_color & 0x00FF0000) >> 16) / 255.0;
678 build_param->bg_color.rgba.g = (float)((background_color & 0x0000FF00) >> 8) / 255.0;
679 build_param->bg_color.rgba.b = (float)(background_color & 0x000000FF) / 255.0;
680 }
681
682 build_param->alpha_mode = VPE_ALPHA_OPAQUE;
683 build_param->flags.hdr_metadata = 1;
684
685 /* TODO: Should support HDR10 Metadata */
686 si_vpe_load_default_primaries(&build_param->hdr_metadata, build_param->dst_surface.cs.primaries);
687 }
688
689 static void
si_vpe_processor_destroy(struct pipe_video_codec * codec)690 si_vpe_processor_destroy(struct pipe_video_codec *codec)
691 {
692 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
693 unsigned int i;
694 assert(codec);
695
696 if (vpeproc->vpe_build_bufs)
697 si_vpe_free_buffer(vpeproc->vpe_build_bufs);
698
699 if (vpeproc->vpe_handle)
700 vpe_destroy(&vpeproc->vpe_handle);
701
702 if (vpeproc->vpe_build_param) {
703 if (vpeproc->vpe_build_param->streams)
704 FREE(vpeproc->vpe_build_param->streams);
705 FREE(vpeproc->vpe_build_param);
706 }
707
708 if (vpeproc->emb_buffers) {
709 for (i = 0; i < vpeproc->bufs_num; i++)
710 if (vpeproc->emb_buffers[i].res)
711 si_vid_destroy_buffer(&vpeproc->emb_buffers[i]);
712 FREE(vpeproc->emb_buffers);
713 }
714
715 if (vpeproc->geometric_scaling_ratios)
716 FREE(vpeproc->geometric_scaling_ratios);
717
718 if (vpeproc->geometric_buf[0])
719 vpeproc->geometric_buf[0]->destroy(vpeproc->geometric_buf[0]);
720
721 if (vpeproc->geometric_buf[1])
722 vpeproc->geometric_buf[1]->destroy(vpeproc->geometric_buf[1]);
723
724 vpeproc->bufs_num = 0;
725 vpeproc->ws->cs_destroy(&vpeproc->cs);
726 SIVPE_DBG(vpeproc->log_level, "Success\n");
727 FREE(vpeproc);
728 }
729
730 static void
si_vpe_processor_begin_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)731 si_vpe_processor_begin_frame(struct pipe_video_codec *codec,
732 struct pipe_video_buffer *target,
733 struct pipe_picture_desc *picture)
734 {
735 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
736 struct pipe_surface **dst_surfaces;
737 assert(codec);
738
739 dst_surfaces = target->get_surfaces(target);
740 if (!dst_surfaces || !dst_surfaces[0]) {
741 SIVPE_ERR("Get target surface failed\n");
742 return;
743 }
744 vpeproc->dst_surfaces = dst_surfaces;
745 }
746
747 static void
si_vpe_cs_add_surface_buffer(struct vpe_video_processor * vpeproc,struct pipe_surface ** surfaces,unsigned usage)748 si_vpe_cs_add_surface_buffer(struct vpe_video_processor *vpeproc,
749 struct pipe_surface **surfaces,
750 unsigned usage)
751 {
752 struct si_resource *si_res;
753 int i;
754
755 for (i = 0; i < VL_MAX_SURFACES; ++i) {
756 if (!surfaces[i])
757 continue;
758
759 si_res = si_resource(surfaces[i]->texture);
760 vpeproc->ws->cs_add_buffer(&vpeproc->cs, si_res->buf, usage | RADEON_USAGE_SYNCHRONIZED, 0);
761 }
762 }
763
764 static void
si_vpe_show_process_settings(struct vpe_video_processor * vpeproc,struct vpe_build_param * build_param)765 si_vpe_show_process_settings(struct vpe_video_processor *vpeproc,
766 struct vpe_build_param *build_param)
767 {
768 if (vpeproc->log_level >= SI_VPE_LOG_LEVEL_DEBUG) {
769 SIVPE_PRINT("src surface format(%d) rect (%d, %d, %d, %d)\n",
770 build_param->streams[0].surface_info.format,
771 build_param->streams[0].surface_info.plane_size.surface_size.x,
772 build_param->streams[0].surface_info.plane_size.surface_size.y,
773 build_param->streams[0].surface_info.plane_size.surface_size.width,
774 build_param->streams[0].surface_info.plane_size.surface_size.height);
775
776 SIVPE_PRINT("src surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
777 si_vpe_get_cositing_str(build_param->streams[0].surface_info.cs.cositing),
778 si_vpe_get_primarie_str(build_param->streams[0].surface_info.cs.primaries),
779 si_vpe_get_tf_str(build_param->streams[0].surface_info.cs.tf),
780 (build_param->streams[0].surface_info.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
781
782 SIVPE_PRINT("dst surface format(%d) rect (%d, %d, %d, %d)\n",
783 build_param->dst_surface.format,
784 build_param->dst_surface.plane_size.surface_size.x,
785 build_param->dst_surface.plane_size.surface_size.y,
786 build_param->dst_surface.plane_size.surface_size.width,
787 build_param->dst_surface.plane_size.surface_size.height);
788
789 SIVPE_PRINT("dst surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
790 si_vpe_get_cositing_str(build_param->dst_surface.cs.cositing),
791 si_vpe_get_primarie_str(build_param->dst_surface.cs.primaries),
792 si_vpe_get_tf_str(build_param->dst_surface.cs.tf),
793 (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
794
795 SIVPE_PRINT("Source surface pitch(%d), chroma pitch(%d), dst-surface pitch(%d), chroma pitch(%d)\n",
796 build_param->streams[0].surface_info.plane_size.surface_pitch,
797 build_param->streams[0].surface_info.plane_size.chroma_pitch,
798 build_param->dst_surface.plane_size.surface_pitch,
799 build_param->dst_surface.plane_size.chroma_pitch);
800
801 SIVPE_PRINT("background color RGBA(%0.3f, %0.3f, %0.3f, %0.3f)\n",
802 build_param->bg_color.rgba.r,
803 build_param->bg_color.rgba.g,
804 build_param->bg_color.rgba.b,
805 build_param->bg_color.rgba.a);
806
807 SIVPE_PRINT("target_rect(%d, %d, %d, %d)\n",
808 build_param->target_rect.x,
809 build_param->target_rect.y,
810 build_param->target_rect.width,
811 build_param->target_rect.height);
812
813 SIVPE_PRINT("rotation(%d) horizontal_mirror(%d) vertical_mirror(%d)\n",
814 build_param->streams[0].rotation,
815 build_param->streams[0].horizontal_mirror,
816 build_param->streams[0].vertical_mirror);
817
818 SIVPE_PRINT("scaling_src_rect(%d, %d, %d, %d)\n",
819 build_param->streams[0].scaling_info.src_rect.x,
820 build_param->streams[0].scaling_info.src_rect.y,
821 build_param->streams[0].scaling_info.src_rect.width,
822 build_param->streams[0].scaling_info.src_rect.height);
823
824 SIVPE_PRINT("scaling_dst_rect(%d, %d, %d, %d)\n",
825 build_param->streams[0].scaling_info.dst_rect.x,
826 build_param->streams[0].scaling_info.dst_rect.y,
827 build_param->streams[0].scaling_info.dst_rect.width,
828 build_param->streams[0].scaling_info.dst_rect.height);
829
830 SIVPE_PRINT("scaling_taps h_taps(%d) v_taps(%d) h_taps_c(%d) v_taps_c(%d)\n",
831 build_param->streams[0].scaling_info.taps.h_taps,
832 build_param->streams[0].scaling_info.taps.v_taps,
833 build_param->streams[0].scaling_info.taps.h_taps_c,
834 build_param->streams[0].scaling_info.taps.v_taps_c);
835
836 SIVPE_PRINT("blend global_alpha(%d): %0.3f\n",
837 build_param->streams[0].blend_info.global_alpha,
838 build_param->streams[0].blend_info.global_alpha_value);
839
840 SIVPE_PRINT("ToneMapping shaper_tf(%d) lut_out_tf(%d) lut_in_gamut(%d) lut_out_gamut(%d)\n",
841 build_param->streams[0].tm_params.shaper_tf,
842 build_param->streams[0].tm_params.lut_out_tf,
843 build_param->streams[0].tm_params.lut_in_gamut,
844 build_param->streams[0].tm_params.lut_out_gamut);
845 }
846 }
847
848 static enum vpe_status
si_vpe_processor_check_and_build_settins(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct pipe_surface ** src_surfaces,struct pipe_surface ** dst_surfaces)849 si_vpe_processor_check_and_build_settins(struct vpe_video_processor *vpeproc,
850 const struct pipe_vpp_desc *process_properties,
851 struct pipe_surface **src_surfaces,
852 struct pipe_surface **dst_surfaces)
853 {
854 enum vpe_status result = VPE_STATUS_OK;
855 struct vpe *vpe_handle = vpeproc->vpe_handle;
856 struct vpe_build_param *build_param = vpeproc->vpe_build_param;
857 struct vpe_bufs_req bufs_required;
858
859 /* Mesa only sends one input frame at one time (one stream pipe).
860 * If there is more than one pipe need to be handled, it have to re-locate memory.
861 * But now we only focuse on handling one stream pipe.
862 */
863 build_param->num_streams = 1;
864 memset(build_param->streams, 0, sizeof(struct vpe_stream) * build_param->num_streams);
865
866 /* Init input surface setting */
867 result = si_vpe_set_surface_info(vpeproc,
868 process_properties,
869 src_surfaces,
870 USE_SRC_SURFACE,
871 &build_param->streams[0].surface_info);
872 if (VPE_STATUS_OK != result) {
873 SIVPE_ERR("Set Src surface failed with result: %d\n", result);
874 return result;
875 }
876
877 /* Init input stream setting */
878 si_vpe_set_stream_in_param(
879 vpeproc,
880 process_properties,
881 &build_param->streams[0]);
882
883 /* Init output surface setting */
884 result = si_vpe_set_surface_info(vpeproc,
885 process_properties,
886 dst_surfaces,
887 USE_DST_SURFACE,
888 &build_param->dst_surface);
889 if (VPE_STATUS_OK != result) {
890 SIVPE_ERR("Set Dst surface failed with result: %d\n", result);
891 return result;
892 }
893
894 /* Init output stream setting */
895 si_vpe_set_stream_out_param(
896 vpeproc,
897 process_properties,
898 build_param);
899
900 /* Shows details of current processing. */
901 si_vpe_show_process_settings(vpeproc, build_param);
902
903 if(vpe_handle->level == VPE_IP_LEVEL_1_1) {
904 build_param->num_instances = 2;
905 build_param->collaboration_mode = true;
906 } else {
907 build_param->num_instances = 1;
908 build_param->collaboration_mode = false;
909 }
910
911 result = vpe_check_support(vpe_handle, build_param, &bufs_required);
912 if (VPE_STATUS_OK != result) {
913 SIVPE_WARN(vpeproc->log_level, "Check support failed with result: %d\n", result);
914 return result;
915 }
916
917 if (VPE_EMBBUF_SIZE < bufs_required.emb_buf_size) {
918 SIVPE_ERR("Required Buffer size is out of allocated: %" PRIu64 "\n", bufs_required.emb_buf_size);
919 return VPE_STATUS_NO_MEMORY;
920 }
921
922 return result;
923 }
924
925 static enum vpe_status
si_vpe_construct_blt(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct pipe_surface ** src_surfaces,struct pipe_surface ** dst_surfaces)926 si_vpe_construct_blt(struct vpe_video_processor *vpeproc,
927 const struct pipe_vpp_desc *process_properties,
928 struct pipe_surface **src_surfaces,
929 struct pipe_surface **dst_surfaces)
930 {
931 enum vpe_status result = VPE_STATUS_OK;
932 struct vpe *vpe_handle = vpeproc->vpe_handle;
933 struct vpe_build_param *build_param = vpeproc->vpe_build_param;
934 struct vpe_build_bufs *build_bufs = vpeproc->vpe_build_bufs;
935 struct rvid_buffer *emb_buf;
936 uint64_t *vpe_ptr;
937
938 assert(process_properties);
939 assert(src_surfaces);
940 assert(dst_surfaces);
941
942 /* Check if the blt operation is supported and build related settings.
943 * Command settings will be is stored in vpeproc->vpe_build_param.
944 */
945 result = si_vpe_processor_check_and_build_settins(vpeproc, process_properties, src_surfaces, dst_surfaces);
946 if (VPE_STATUS_OK != result) {
947 SIVPE_ERR("Failed in checking process operation and build settings(%d)\n", result);
948 return result;
949 }
950
951 /* Prepare cmd_bud and emb_buf for building commands from settings */
952 /* Init CmdBuf address and size information */
953 vpe_ptr = (uint64_t *)vpeproc->cs.current.buf;
954 build_bufs->cmd_buf.cpu_va = (uintptr_t)vpe_ptr;
955 build_bufs->cmd_buf.gpu_va = 0;
956 build_bufs->cmd_buf.size = vpeproc->cs.current.max_dw;
957 build_bufs->cmd_buf.tmz = false;
958
959 /* Init EmbBuf address and size information */
960 emb_buf = &vpeproc->emb_buffers[vpeproc->cur_buf];
961 /* Map EmbBuf for CPU access */
962 vpe_ptr = (uint64_t *)vpeproc->ws->buffer_map(vpeproc->ws,
963 emb_buf->res->buf,
964 &vpeproc->cs,
965 PIPE_MAP_WRITE | RADEON_MAP_TEMPORARY);
966 if (!vpe_ptr) {
967 SIVPE_ERR("Mapping Embbuf failed\n");
968 return 1;
969 }
970 build_bufs->emb_buf.cpu_va = (uintptr_t)vpe_ptr;
971 build_bufs->emb_buf.gpu_va = vpeproc->ws->buffer_get_virtual_address(emb_buf->res->buf);
972 build_bufs->emb_buf.size = VPE_EMBBUF_SIZE;
973 build_bufs->emb_buf.tmz = false;
974
975 result = vpe_build_commands(vpe_handle, build_param, build_bufs);
976
977 /* Un-map Emb_buf */
978 vpeproc->ws->buffer_unmap(vpeproc->ws, emb_buf->res->buf);
979
980 if (VPE_STATUS_OK != result) {
981 SIVPE_ERR("Build commands failed with result: %d\n", result);
982 return VPE_STATUS_NO_MEMORY;
983 }
984
985
986 /* Check buffer size */
987 if (vpeproc->vpe_build_bufs->cmd_buf.size == 0 || vpeproc->vpe_build_bufs->cmd_buf.size == vpeproc->cs.current.max_dw) {
988 SIVPE_ERR("Cmdbuf size wrong\n");
989 return VPE_STATUS_NO_MEMORY;
990 }
991 if (vpeproc->vpe_build_bufs->emb_buf.size == 0 || vpeproc->vpe_build_bufs->emb_buf.size == VPE_EMBBUF_SIZE) {
992 SIVPE_ERR("Embbuf size wrong\n");
993 return VPE_STATUS_NO_MEMORY;
994 }
995 SIVPE_DBG(vpeproc->log_level, "Used buf size: %" PRIu64 ", %" PRIu64 "\n",
996 vpeproc->vpe_build_bufs->cmd_buf.size, vpeproc->vpe_build_bufs->emb_buf.size);
997
998 /* Have to tell Command Submission context the command length */
999 vpeproc->cs.current.cdw += (vpeproc->vpe_build_bufs->cmd_buf.size / 4);
1000
1001 /* Add embbuf into bo_handle list */
1002 vpeproc->ws->cs_add_buffer(&vpeproc->cs, emb_buf->res->buf, RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_GTT);
1003
1004 /* Add surface buffers into bo_handle list */
1005 si_vpe_cs_add_surface_buffer(vpeproc, src_surfaces, RADEON_USAGE_READ);
1006 si_vpe_cs_add_surface_buffer(vpeproc, dst_surfaces, RADEON_USAGE_WRITE);
1007
1008 return VPE_STATUS_OK;
1009 }
1010
1011 static void
si_vpe_find_substage_scal_ratios(float * p_scale_ratios,float scaling_ratio,float max_scale,uint32_t num_stages)1012 si_vpe_find_substage_scal_ratios(float *p_scale_ratios,
1013 float scaling_ratio,
1014 float max_scale,
1015 uint32_t num_stages)
1016 {
1017 uint32_t i;
1018
1019 for (i = 0; i < num_stages; i++) {
1020 if (i == num_stages - 1)
1021 p_scale_ratios[i] = scaling_ratio/(float)(pow(max_scale, num_stages - 1));
1022 else
1023 p_scale_ratios[i] = max_scale;
1024 }
1025 }
1026
1027 static enum vpe_status
si_vpe_decide_substage_scal_ratios(struct vpe_video_processor * vpeproc,float * p_target_ratios)1028 si_vpe_decide_substage_scal_ratios(struct vpe_video_processor *vpeproc,
1029 float *p_target_ratios)
1030 {
1031 uint8_t no_horizontal_passes, no_vertical_passes, no_of_passes;
1032 float *pHrSr, *pVtSr;
1033 uint32_t idx;
1034
1035 /* The scaling ratios are the same as pre-processing */
1036 if (vpeproc->geometric_scaling_ratios &&
1037 vpeproc->scaling_ratios[0] == p_target_ratios[0] &&
1038 vpeproc->scaling_ratios[1] == p_target_ratios[1])
1039 return VPE_STATUS_OK;
1040
1041 if (vpeproc->geometric_scaling_ratios) {
1042 FREE(vpeproc->geometric_scaling_ratios);
1043 vpeproc->geometric_scaling_ratios = NULL;
1044 }
1045
1046 /* How many passes we need */
1047 no_horizontal_passes = (p_target_ratios[0] > VPE_MAX_GEOMETRIC_DOWNSCALE) ?
1048 (uint8_t)(ceil(log(p_target_ratios[0]) / log(VPE_MAX_GEOMETRIC_DOWNSCALE))) : 1;
1049 no_vertical_passes = (p_target_ratios[1] > VPE_MAX_GEOMETRIC_DOWNSCALE) ?
1050 (uint8_t)(ceil(log(p_target_ratios[1]) / log(VPE_MAX_GEOMETRIC_DOWNSCALE))) : 1;
1051 no_of_passes = MAX2(no_horizontal_passes, no_vertical_passes);
1052
1053 /* Allocate ratio array depends on no_of_passes */
1054 pHrSr = (float *)CALLOC(2 * no_of_passes, sizeof(float));
1055 if (NULL == pHrSr) {
1056 SIVPE_ERR("no_of_passes times float of array memory allocation failed\n");
1057 return VPE_STATUS_NO_MEMORY;
1058 }
1059 pVtSr = pHrSr + no_of_passes;
1060 for (idx = 0; idx < no_of_passes; idx++) {
1061 pHrSr[idx] = 1.0f;
1062 pVtSr[idx] = 1.0f;
1063 }
1064
1065 /* Calculate scaling ratios of every pass */
1066 if (no_horizontal_passes > 1)
1067 si_vpe_find_substage_scal_ratios(pHrSr, p_target_ratios[0], VPE_MAX_GEOMETRIC_DOWNSCALE, no_horizontal_passes);
1068 else
1069 pHrSr[0] = p_target_ratios[0];
1070
1071 if (no_vertical_passes > 1)
1072 si_vpe_find_substage_scal_ratios(pVtSr, p_target_ratios[1], VPE_MAX_GEOMETRIC_DOWNSCALE, no_vertical_passes);
1073 else
1074 pVtSr[0] = p_target_ratios[1];
1075
1076 if (no_vertical_passes < no_horizontal_passes) {
1077 pVtSr[no_horizontal_passes - 1] = pVtSr[no_vertical_passes - 1];
1078 pVtSr[no_vertical_passes - 1] = 1.0f;
1079 } else if (no_vertical_passes > no_horizontal_passes) {
1080 pHrSr[no_vertical_passes - 1] = pHrSr[no_horizontal_passes - 1];
1081 pHrSr[no_horizontal_passes - 1] = 1.0f;
1082 }
1083
1084 /* Store the ratio information in vpeproc */
1085 vpeproc->scaling_ratios[0] = p_target_ratios[0];
1086 vpeproc->scaling_ratios[1] = p_target_ratios[1];
1087 vpeproc->geometric_scaling_ratios = pHrSr;
1088 vpeproc->geometric_passes = no_of_passes;
1089
1090 return VPE_STATUS_OK;
1091 }
1092
1093 static int
si_vpe_processor_process_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * input_texture,const struct pipe_vpp_desc * process_properties)1094 si_vpe_processor_process_frame(struct pipe_video_codec *codec,
1095 struct pipe_video_buffer *input_texture,
1096 const struct pipe_vpp_desc *process_properties)
1097 {
1098 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1099 uint32_t src_rect_width, src_rect_height, dst_rect_width, dst_rect_height;
1100 float scaling_ratio[2];
1101
1102 /* Get input surface */
1103 vpeproc->src_surfaces = input_texture->get_surfaces(input_texture);
1104 if (!vpeproc->src_surfaces || !vpeproc->src_surfaces[0]) {
1105 SIVPE_ERR("Get source surface failed\n");
1106 return 1;
1107 }
1108
1109 /* Get scaling ratio info */
1110 src_rect_width = process_properties->src_region.x1 - process_properties->src_region.x0;
1111 src_rect_height = process_properties->src_region.y1 - process_properties->src_region.y0;
1112 dst_rect_width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
1113 dst_rect_height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
1114
1115 scaling_ratio[0] = src_rect_width / dst_rect_width;
1116 scaling_ratio[1] = src_rect_height / dst_rect_height;
1117
1118 /* Check if the reduction ratio is within capability */
1119 if ((scaling_ratio[0] <= VPE_MAX_GEOMETRIC_DOWNSCALE) && (scaling_ratio[1] <= VPE_MAX_GEOMETRIC_DOWNSCALE))
1120 return si_vpe_construct_blt(vpeproc, process_properties, vpeproc->src_surfaces, vpeproc->dst_surfaces);
1121
1122 return 1;
1123 }
1124
1125 static int
si_vpe_processor_end_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)1126 si_vpe_processor_end_frame(struct pipe_video_codec *codec,
1127 struct pipe_video_buffer *target,
1128 struct pipe_picture_desc *picture)
1129 {
1130 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1131 assert(codec);
1132
1133 vpeproc->ws->cs_flush(&vpeproc->cs, picture->flush_flags, picture->fence);
1134 next_buffer(vpeproc);
1135
1136 return 0;
1137 }
1138
1139 static void
si_vpe_processor_flush(struct pipe_video_codec * codec)1140 si_vpe_processor_flush(struct pipe_video_codec *codec)
1141 {
1142 /* Commands will be flushed when end_frame() is called */
1143 return;
1144 }
1145
si_vpe_processor_fence_wait(struct pipe_video_codec * codec,struct pipe_fence_handle * fence,uint64_t timeout)1146 static int si_vpe_processor_fence_wait(struct pipe_video_codec *codec,
1147 struct pipe_fence_handle *fence,
1148 uint64_t timeout)
1149 {
1150 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1151 assert(codec);
1152
1153 if (!vpeproc->ws->fence_wait(vpeproc->ws, fence, timeout)) {
1154 SIVPE_DBG(vpeproc->log_level, "Wait processor fence fail\n");
1155 return 0;
1156 }
1157 return 1;
1158 }
1159
si_vpe_processor_destroy_fence(struct pipe_video_codec * codec,struct pipe_fence_handle * fence)1160 static void si_vpe_processor_destroy_fence(struct pipe_video_codec *codec,
1161 struct pipe_fence_handle *fence)
1162 {
1163 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1164 assert(codec);
1165
1166 vpeproc->ws->fence_reference(vpeproc->ws, &fence, NULL);
1167 }
1168
1169 struct pipe_video_codec*
si_vpe_create_processor(struct pipe_context * context,const struct pipe_video_codec * templ)1170 si_vpe_create_processor(struct pipe_context *context, const struct pipe_video_codec *templ)
1171 {
1172 struct si_context *sctx = (struct si_context *)context;
1173 struct radeon_winsys *ws = sctx->ws;
1174 struct vpe_video_processor *vpeproc;
1175 struct vpe_init_data *init_data;
1176 unsigned int i;
1177
1178 vpeproc = CALLOC_STRUCT(vpe_video_processor);
1179 if (!vpeproc) {
1180 SIVPE_ERR("Allocate struct failed\n");
1181 return NULL;
1182 }
1183
1184 /* SI_VPE debug log level
1185 * Default level(0) only shows error messages
1186 */
1187 vpeproc->log_level = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_LOG_LEVEL", SI_VPE_LOG_LEVEL_DEFAULT);
1188
1189 vpeproc->base = *templ;
1190 vpeproc->base.context = context;
1191 vpeproc->base.width = templ->width;
1192 vpeproc->base.height = templ->height;
1193
1194 vpeproc->base.destroy = si_vpe_processor_destroy;
1195 vpeproc->base.begin_frame = si_vpe_processor_begin_frame;
1196 vpeproc->base.process_frame = si_vpe_processor_process_frame;
1197 vpeproc->base.end_frame = si_vpe_processor_end_frame;
1198 vpeproc->base.flush = si_vpe_processor_flush;
1199 vpeproc->base.fence_wait = si_vpe_processor_fence_wait;
1200 vpeproc->base.destroy_fence = si_vpe_processor_destroy_fence;
1201
1202 vpeproc->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
1203 vpeproc->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
1204
1205 vpeproc->screen = context->screen;
1206 vpeproc->ws = ws;
1207
1208 init_data = &vpeproc->vpe_data;
1209 if (VPE_STATUS_OK != si_vpe_populate_init_data(sctx, init_data, vpeproc->log_level)){
1210 SIVPE_ERR("Init VPE populate data failed\n");
1211 goto fail;
1212 }
1213
1214 vpeproc->vpe_handle = vpe_create(init_data);
1215 if (!vpeproc->vpe_handle) {
1216 SIVPE_ERR("Create VPE handle failed\n");
1217 goto fail;
1218 }
1219
1220 if (VPE_STATUS_OK != si_vpe_allocate_buffer(&vpeproc->vpe_build_bufs)) {
1221 SIVPE_ERR("Allocate VPE buffers failed\n");
1222 goto fail;
1223 }
1224
1225 /* Create Command Submission context.
1226 * The cmdbuf (Vpe Descriptor) will be stored in cs.current.buf
1227 * there is no needs to allocate another buffer handle for cmdbuf.
1228 */
1229 if (!ws->cs_create(&vpeproc->cs, sctx->ctx, AMD_IP_VPE, NULL, NULL)) {
1230 SIVPE_ERR("Get command submission context failed.\n");
1231 goto fail;
1232 }
1233
1234 /* Allocate Vpblit Descriptor buffers
1235 * Descriptor buffer is used to store plane config and VPEP commands
1236 */
1237 vpeproc->bufs_num = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_BUF_NUM", VPE_BUFFERS_NUM);
1238 vpeproc->cur_buf = 0;
1239 vpeproc->emb_buffers = (struct rvid_buffer *)CALLOC(vpeproc->bufs_num, sizeof(struct rvid_buffer));
1240 if (!vpeproc->emb_buffers) {
1241 SIVPE_ERR("Allocate command buffer list failed\n");
1242 goto fail;
1243 } else
1244 SIVPE_INFO(vpeproc->log_level, "Number of emb_buf is %d\n", vpeproc->bufs_num);
1245
1246 for (i = 0; i < vpeproc->bufs_num; i++) {
1247 if (!si_vid_create_buffer(vpeproc->screen, &vpeproc->emb_buffers[i], VPE_EMBBUF_SIZE, PIPE_USAGE_DEFAULT)) {
1248 SIVPE_ERR("Can't allocated emb_buf buffers.\n");
1249 goto fail;
1250 }
1251 si_vid_clear_buffer(context, &vpeproc->emb_buffers[i]);
1252 }
1253
1254 /* Create VPE parameters structure */
1255 vpeproc->vpe_build_param = CALLOC_STRUCT(vpe_build_param);
1256 if (!vpeproc->vpe_build_param) {
1257 SIVPE_ERR("Allocate build-paramaters sturcture failed\n");
1258 goto fail;
1259 }
1260
1261 /* Only one input frame is passed in for processing at a time (one stream pipe).
1262 * Only needs to handle one stream processing.
1263 */
1264 vpeproc->vpe_build_param->streams = (struct vpe_stream *)CALLOC(VPE_STREAM_MAX_NUM, sizeof(struct vpe_stream));
1265 if (!vpeproc->vpe_build_param->streams) {
1266 SIVPE_ERR("Allocate streams sturcture failed\n");
1267 goto fail;
1268 }
1269
1270 return &vpeproc->base;
1271
1272 fail:
1273 SIVPE_ERR("Failed\n");
1274 if (vpeproc) {
1275 si_vpe_processor_destroy(&vpeproc->base);
1276 }
1277 return NULL;
1278 }
1279