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 vpeproc->bufs_num = 0;
716 vpeproc->ws->cs_destroy(&vpeproc->cs);
717 SIVPE_DBG(vpeproc->log_level, "Success\n");
718 FREE(vpeproc);
719 }
720
721 static void
si_vpe_processor_begin_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)722 si_vpe_processor_begin_frame(struct pipe_video_codec *codec,
723 struct pipe_video_buffer *target,
724 struct pipe_picture_desc *picture)
725 {
726 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
727 struct pipe_surface **dst_surfaces;
728 assert(codec);
729
730 dst_surfaces = target->get_surfaces(target);
731 if (!dst_surfaces || !dst_surfaces[0]) {
732 SIVPE_ERR("Get target surface failed\n");
733 return;
734 }
735 vpeproc->dst_surfaces = dst_surfaces;
736 }
737
738 static void
si_vpe_cs_add_surface_buffer(struct vpe_video_processor * vpeproc,struct pipe_surface ** surfaces,unsigned usage)739 si_vpe_cs_add_surface_buffer(struct vpe_video_processor *vpeproc,
740 struct pipe_surface **surfaces,
741 unsigned usage)
742 {
743 struct si_resource *si_res;
744 int i;
745
746 for (i = 0; i < VL_MAX_SURFACES; ++i) {
747 if (!surfaces[i])
748 continue;
749
750 si_res = si_resource(surfaces[i]->texture);
751 vpeproc->ws->cs_add_buffer(&vpeproc->cs, si_res->buf, usage | RADEON_USAGE_SYNCHRONIZED, 0);
752 }
753 }
754
755 static void
si_vpe_show_process_settings(struct vpe_video_processor * vpeproc,struct vpe_build_param * build_param)756 si_vpe_show_process_settings(struct vpe_video_processor *vpeproc,
757 struct vpe_build_param *build_param)
758 {
759 if (vpeproc->log_level >= SI_VPE_LOG_LEVEL_DEBUG) {
760 SIVPE_PRINT("src surface format(%d) rect (%d, %d, %d, %d)\n",
761 build_param->streams[0].surface_info.format,
762 build_param->streams[0].surface_info.plane_size.surface_size.x,
763 build_param->streams[0].surface_info.plane_size.surface_size.y,
764 build_param->streams[0].surface_info.plane_size.surface_size.width,
765 build_param->streams[0].surface_info.plane_size.surface_size.height);
766
767 SIVPE_PRINT("src surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
768 si_vpe_get_cositing_str(build_param->streams[0].surface_info.cs.cositing),
769 si_vpe_get_primarie_str(build_param->streams[0].surface_info.cs.primaries),
770 si_vpe_get_tf_str(build_param->streams[0].surface_info.cs.tf),
771 (build_param->streams[0].surface_info.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
772
773 SIVPE_PRINT("dst surface format(%d) rect (%d, %d, %d, %d)\n",
774 build_param->dst_surface.format,
775 build_param->dst_surface.plane_size.surface_size.x,
776 build_param->dst_surface.plane_size.surface_size.y,
777 build_param->dst_surface.plane_size.surface_size.width,
778 build_param->dst_surface.plane_size.surface_size.height);
779
780 SIVPE_PRINT("dst surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
781 si_vpe_get_cositing_str(build_param->dst_surface.cs.cositing),
782 si_vpe_get_primarie_str(build_param->dst_surface.cs.primaries),
783 si_vpe_get_tf_str(build_param->dst_surface.cs.tf),
784 (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
785
786 SIVPE_PRINT("Source surface pitch(%d), chroma pitch(%d), dst-surface pitch(%d), chroma pitch(%d)\n",
787 build_param->streams[0].surface_info.plane_size.surface_pitch,
788 build_param->streams[0].surface_info.plane_size.chroma_pitch,
789 build_param->dst_surface.plane_size.surface_pitch,
790 build_param->dst_surface.plane_size.chroma_pitch);
791
792 SIVPE_PRINT("background color RGBA(%0.3f, %0.3f, %0.3f, %0.3f)\n",
793 build_param->bg_color.rgba.r,
794 build_param->bg_color.rgba.g,
795 build_param->bg_color.rgba.b,
796 build_param->bg_color.rgba.a);
797
798 SIVPE_PRINT("target_rect(%d, %d, %d, %d)\n",
799 build_param->target_rect.x,
800 build_param->target_rect.y,
801 build_param->target_rect.width,
802 build_param->target_rect.height);
803
804 SIVPE_PRINT("rotation(%d) horizontal_mirror(%d) vertical_mirror(%d)\n",
805 build_param->streams[0].rotation,
806 build_param->streams[0].horizontal_mirror,
807 build_param->streams[0].vertical_mirror);
808
809 SIVPE_PRINT("scaling_src_rect(%d, %d, %d, %d)\n",
810 build_param->streams[0].scaling_info.src_rect.x,
811 build_param->streams[0].scaling_info.src_rect.y,
812 build_param->streams[0].scaling_info.src_rect.width,
813 build_param->streams[0].scaling_info.src_rect.height);
814
815 SIVPE_PRINT("scaling_dst_rect(%d, %d, %d, %d)\n",
816 build_param->streams[0].scaling_info.dst_rect.x,
817 build_param->streams[0].scaling_info.dst_rect.y,
818 build_param->streams[0].scaling_info.dst_rect.width,
819 build_param->streams[0].scaling_info.dst_rect.height);
820
821 SIVPE_PRINT("scaling_taps h_taps(%d) v_taps(%d) h_taps_c(%d) v_taps_c(%d)\n",
822 build_param->streams[0].scaling_info.taps.h_taps,
823 build_param->streams[0].scaling_info.taps.v_taps,
824 build_param->streams[0].scaling_info.taps.h_taps_c,
825 build_param->streams[0].scaling_info.taps.v_taps_c);
826
827 SIVPE_PRINT("blend global_alpha(%d): %0.3f\n",
828 build_param->streams[0].blend_info.global_alpha,
829 build_param->streams[0].blend_info.global_alpha_value);
830
831 SIVPE_PRINT("ToneMapping shaper_tf(%d) lut_out_tf(%d) lut_in_gamut(%d) lut_out_gamut(%d)\n",
832 build_param->streams[0].tm_params.shaper_tf,
833 build_param->streams[0].tm_params.lut_out_tf,
834 build_param->streams[0].tm_params.lut_in_gamut,
835 build_param->streams[0].tm_params.lut_out_gamut);
836 }
837 }
838
839 static int
si_vpe_processor_is_process_supported(struct pipe_video_codec * codec,struct pipe_video_buffer * input_texture,const struct pipe_vpp_desc * process_properties)840 si_vpe_processor_is_process_supported(struct pipe_video_codec *codec,
841 struct pipe_video_buffer *input_texture,
842 const struct pipe_vpp_desc *process_properties)
843 {
844 enum vpe_status result = VPE_STATUS_OK;
845 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
846 struct vpe *vpe_handle = vpeproc->vpe_handle;
847 struct vpe_build_param *build_param = vpeproc->vpe_build_param;
848 struct pipe_surface **src_surfaces;
849 struct vpe_bufs_req bufs_required;
850
851 assert(codec);
852 assert(process_properties);
853 assert(vpeproc->dst_surfaces);
854
855 /* Get input surface */
856 src_surfaces = input_texture->get_surfaces(input_texture);
857 if (!src_surfaces || !src_surfaces[0]) {
858 SIVPE_ERR("Get source surface failed\n");
859 return 1;
860 }
861 vpeproc->src_surfaces = src_surfaces;
862
863 /* Mesa only sends one input frame at one time (one stream pipe).
864 * If there is more than one pipe need to be handled, it have to re-locate memory.
865 * But now we only focuse on handling one stream pipe.
866 */
867 build_param->num_streams = 1;
868 memset(build_param->streams, 0, sizeof(struct vpe_stream) * build_param->num_streams);
869
870 /* Init input surface setting */
871 result = si_vpe_set_surface_info(vpeproc,
872 process_properties,
873 vpeproc->src_surfaces,
874 USE_SRC_SURFACE,
875 &build_param->streams[0].surface_info);
876 if (VPE_STATUS_OK != result) {
877 SIVPE_ERR("Set Src surface failed with result: %d\n", result);
878 return 1;
879 }
880
881 /* Init input stream setting */
882 si_vpe_set_stream_in_param(
883 vpeproc,
884 process_properties,
885 &build_param->streams[0]);
886
887 /* Init output surface setting */
888 result = si_vpe_set_surface_info(vpeproc,
889 process_properties,
890 vpeproc->dst_surfaces,
891 USE_DST_SURFACE,
892 &build_param->dst_surface);
893 if (VPE_STATUS_OK != result) {
894 SIVPE_ERR("Set Dst surface failed with result: %d\n", result);
895 return 1;
896 }
897
898 /* Init output stream setting */
899 si_vpe_set_stream_out_param(
900 vpeproc,
901 process_properties,
902 build_param);
903
904 /* Shows details of current processing. */
905 si_vpe_show_process_settings(vpeproc, build_param);
906
907 if(vpe_handle->level == VPE_IP_LEVEL_1_1) {
908 build_param->num_instances = 2;
909 build_param->collaboration_mode = true;
910 } else {
911 build_param->num_instances = 1;
912 build_param->collaboration_mode = false;
913 }
914
915 result = vpe_check_support(vpe_handle, build_param, &bufs_required);
916 if (VPE_STATUS_OK != result) {
917 SIVPE_WARN(vpeproc->log_level, "Check support failed with result: %d\n", result);
918 return 1;
919 }
920
921 if (VPE_EMBBUF_SIZE < bufs_required.emb_buf_size) {
922 SIVPE_ERR("Required Buffer size is out of allocated: %" PRIu64 "\n", bufs_required.emb_buf_size);
923 return 1;
924 }
925
926 return 0;
927 }
928
929 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)930 si_vpe_processor_process_frame(struct pipe_video_codec *codec,
931 struct pipe_video_buffer *input_texture,
932 const struct pipe_vpp_desc *process_properties)
933 {
934 enum vpe_status result = VPE_STATUS_OK;
935 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
936 struct vpe *vpe_handle = vpeproc->vpe_handle;
937 struct vpe_build_param *build_param = vpeproc->vpe_build_param;
938 struct rvid_buffer *emb_buf;
939 uint64_t *vpe_ptr;
940
941 /* Check if the required options are supported */
942 if(si_vpe_processor_is_process_supported(codec, input_texture, process_properties))
943 return 1;
944
945 /* Init CmdBuf address and size information */
946 vpe_ptr = (uint64_t *)vpeproc->cs.current.buf;
947 vpeproc->vpe_build_bufs->cmd_buf.cpu_va = (uintptr_t)vpe_ptr;
948 vpeproc->vpe_build_bufs->cmd_buf.gpu_va = 0;
949 vpeproc->vpe_build_bufs->cmd_buf.size = vpeproc->cs.current.max_dw;
950 vpeproc->vpe_build_bufs->cmd_buf.tmz = false;
951
952 /* Init EmbBuf address and size information */
953 emb_buf = &vpeproc->emb_buffers[vpeproc->cur_buf];
954 /* Map EmbBuf for CPU access */
955 vpe_ptr = (uint64_t *)vpeproc->ws->buffer_map(vpeproc->ws,
956 emb_buf->res->buf,
957 &vpeproc->cs,
958 PIPE_MAP_WRITE | RADEON_MAP_TEMPORARY);
959 if (!vpe_ptr) {
960 SIVPE_ERR("Mapping Embbuf failed\n");
961 return 1;
962 }
963 vpeproc->vpe_build_bufs->emb_buf.cpu_va = (uintptr_t)vpe_ptr;
964 vpeproc->vpe_build_bufs->emb_buf.gpu_va = vpeproc->ws->buffer_get_virtual_address(emb_buf->res->buf);
965 vpeproc->vpe_build_bufs->emb_buf.size = VPE_EMBBUF_SIZE;
966 vpeproc->vpe_build_bufs->emb_buf.tmz = false;
967
968 result = vpe_build_commands(vpe_handle, build_param, vpeproc->vpe_build_bufs);
969 if (VPE_STATUS_OK != result) {
970 SIVPE_ERR("Build commands failed with result: %d\n", result);
971 goto fail;
972 }
973
974 /* Un-map Emb_buf */
975 vpeproc->ws->buffer_unmap(vpeproc->ws, emb_buf->res->buf);
976
977 /* Check buffer size */
978 if (vpeproc->vpe_build_bufs->cmd_buf.size == 0 || vpeproc->vpe_build_bufs->cmd_buf.size == vpeproc->cs.current.max_dw) {
979 SIVPE_ERR("Cmdbuf size wrong\n");
980 goto fail;
981 }
982 if (vpeproc->vpe_build_bufs->emb_buf.size == 0 || vpeproc->vpe_build_bufs->emb_buf.size == VPE_EMBBUF_SIZE) {
983 SIVPE_ERR("Embbuf size wrong\n");
984 goto fail;
985 }
986 SIVPE_DBG(vpeproc->log_level, "Used buf size: %" PRIu64 ", %" PRIu64 "\n",
987 vpeproc->vpe_build_bufs->cmd_buf.size, vpeproc->vpe_build_bufs->emb_buf.size);
988
989 /* Have to tell Command Submission context the command length */
990 vpeproc->cs.current.cdw += (vpeproc->vpe_build_bufs->cmd_buf.size / 4);
991
992 /* Add embbuf into bo_handle list */
993 vpeproc->ws->cs_add_buffer(&vpeproc->cs, emb_buf->res->buf, RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_GTT);
994
995 /* Add surface buffers into bo_handle list */
996 si_vpe_cs_add_surface_buffer(vpeproc, vpeproc->src_surfaces, RADEON_USAGE_READ);
997 si_vpe_cs_add_surface_buffer(vpeproc, vpeproc->dst_surfaces, RADEON_USAGE_WRITE);
998
999 return 0;
1000
1001 fail:
1002 vpeproc->ws->buffer_unmap(vpeproc->ws, emb_buf->res->buf);
1003 SIVPE_ERR("Process frame failed\n");
1004 return 1;
1005 }
1006
1007 static int
si_vpe_processor_end_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)1008 si_vpe_processor_end_frame(struct pipe_video_codec *codec,
1009 struct pipe_video_buffer *target,
1010 struct pipe_picture_desc *picture)
1011 {
1012 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1013 assert(codec);
1014
1015 vpeproc->ws->cs_flush(&vpeproc->cs, picture->flush_flags, picture->fence);
1016 next_buffer(vpeproc);
1017
1018 return 0;
1019 }
1020
1021 static void
si_vpe_processor_flush(struct pipe_video_codec * codec)1022 si_vpe_processor_flush(struct pipe_video_codec *codec)
1023 {
1024 /* Commands will be flushed when end_frame() is called */
1025 return;
1026 }
1027
si_vpe_processor_fence_wait(struct pipe_video_codec * codec,struct pipe_fence_handle * fence,uint64_t timeout)1028 static int si_vpe_processor_fence_wait(struct pipe_video_codec *codec,
1029 struct pipe_fence_handle *fence,
1030 uint64_t timeout)
1031 {
1032 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1033 assert(codec);
1034
1035 if (!vpeproc->ws->fence_wait(vpeproc->ws, fence, timeout)) {
1036 SIVPE_DBG(vpeproc->log_level, "Wait processor fence fail\n");
1037 return 0;
1038 }
1039 return 1;
1040 }
1041
si_vpe_processor_destroy_fence(struct pipe_video_codec * codec,struct pipe_fence_handle * fence)1042 static void si_vpe_processor_destroy_fence(struct pipe_video_codec *codec,
1043 struct pipe_fence_handle *fence)
1044 {
1045 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1046 assert(codec);
1047
1048 vpeproc->ws->fence_reference(vpeproc->ws, &fence, NULL);
1049 }
1050
1051 struct pipe_video_codec*
si_vpe_create_processor(struct pipe_context * context,const struct pipe_video_codec * templ)1052 si_vpe_create_processor(struct pipe_context *context, const struct pipe_video_codec *templ)
1053 {
1054 struct si_context *sctx = (struct si_context *)context;
1055 struct radeon_winsys *ws = sctx->ws;
1056 struct vpe_video_processor *vpeproc;
1057 struct vpe_init_data *init_data;
1058 unsigned int i;
1059
1060 vpeproc = CALLOC_STRUCT(vpe_video_processor);
1061 if (!vpeproc) {
1062 SIVPE_ERR("Allocate struct failed\n");
1063 return NULL;
1064 }
1065
1066 /* SI_VPE debug log level
1067 * Default level(0) only shows error messages
1068 */
1069 vpeproc->log_level = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_LOG_LEVEL", SI_VPE_LOG_LEVEL_DEFAULT);
1070
1071 vpeproc->base = *templ;
1072 vpeproc->base.context = context;
1073 vpeproc->base.width = templ->width;
1074 vpeproc->base.height = templ->height;
1075
1076 vpeproc->base.destroy = si_vpe_processor_destroy;
1077 vpeproc->base.begin_frame = si_vpe_processor_begin_frame;
1078 vpeproc->base.process_frame = si_vpe_processor_process_frame;
1079 vpeproc->base.end_frame = si_vpe_processor_end_frame;
1080 vpeproc->base.flush = si_vpe_processor_flush;
1081 vpeproc->base.fence_wait = si_vpe_processor_fence_wait;
1082 vpeproc->base.destroy_fence = si_vpe_processor_destroy_fence;
1083
1084 vpeproc->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
1085 vpeproc->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
1086
1087 vpeproc->screen = context->screen;
1088 vpeproc->ws = ws;
1089
1090 init_data = &vpeproc->vpe_data;
1091 if (VPE_STATUS_OK != si_vpe_populate_init_data(sctx, init_data, vpeproc->log_level)){
1092 SIVPE_ERR("Init VPE populate data failed\n");
1093 goto fail;
1094 }
1095
1096 vpeproc->vpe_handle = vpe_create(init_data);
1097 if (!vpeproc->vpe_handle) {
1098 SIVPE_ERR("Create VPE handle failed\n");
1099 goto fail;
1100 }
1101
1102 if (VPE_STATUS_OK != si_vpe_allocate_buffer(&vpeproc->vpe_build_bufs)) {
1103 SIVPE_ERR("Allocate VPE buffers failed\n");
1104 goto fail;
1105 }
1106
1107 /* Create Command Submission context.
1108 * The cmdbuf (Vpe Descriptor) will be stored in cs.current.buf
1109 * there is no needs to allocate another buffer handle for cmdbuf.
1110 */
1111 if (!ws->cs_create(&vpeproc->cs, sctx->ctx, AMD_IP_VPE, NULL, NULL)) {
1112 SIVPE_ERR("Get command submission context failed.\n");
1113 goto fail;
1114 }
1115
1116 /* Allocate Vpblit Descriptor buffers
1117 * Descriptor buffer is used to store plane config and VPEP commands
1118 */
1119 vpeproc->bufs_num = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_BUF_NUM", VPE_BUFFERS_NUM);
1120 vpeproc->cur_buf = 0;
1121 vpeproc->emb_buffers = (struct rvid_buffer *)CALLOC(vpeproc->bufs_num, sizeof(struct rvid_buffer));
1122 if (!vpeproc->emb_buffers) {
1123 SIVPE_ERR("Allocate command buffer list failed\n");
1124 goto fail;
1125 } else
1126 SIVPE_INFO(vpeproc->log_level, "Number of emb_buf is %d\n", vpeproc->bufs_num);
1127
1128 for (i = 0; i < vpeproc->bufs_num; i++) {
1129 if (!si_vid_create_buffer(vpeproc->screen, &vpeproc->emb_buffers[i], VPE_EMBBUF_SIZE, PIPE_USAGE_DEFAULT)) {
1130 SIVPE_ERR("Can't allocated emb_buf buffers.\n");
1131 goto fail;
1132 }
1133 si_vid_clear_buffer(context, &vpeproc->emb_buffers[i]);
1134 }
1135
1136 /* Create VPE parameters structure */
1137 vpeproc->vpe_build_param = CALLOC_STRUCT(vpe_build_param);
1138 if (!vpeproc->vpe_build_param) {
1139 SIVPE_ERR("Allocate build-paramaters sturcture failed\n");
1140 goto fail;
1141 }
1142
1143 /* Only one input frame is passed in for processing at a time (one stream pipe).
1144 * Only needs to handle one stream processing.
1145 */
1146 vpeproc->vpe_build_param->streams = (struct vpe_stream *)CALLOC(VPE_STREAM_MAX_NUM, sizeof(struct vpe_stream));
1147 if (!vpeproc->vpe_build_param->streams) {
1148 SIVPE_ERR("Allocate streams sturcture failed\n");
1149 goto fail;
1150 }
1151
1152 return &vpeproc->base;
1153
1154 fail:
1155 SIVPE_ERR("Failed\n");
1156 if (vpeproc) {
1157 si_vpe_processor_destroy(&vpeproc->base);
1158 }
1159 return NULL;
1160 }
1161