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_PRETAG ""
37 #define SI_VPE_LOG_LEVEL_DEFAULT 0
38 #define SI_VPE_LOG_LEVEL_INFO 1
39 #define SI_VPE_LOG_LEVEL_WARNING 2
40 #define SI_VPE_LOG_LEVEL_DEBUG 3
41
42 #define SIVPE_INFO(dblv, fmt, args...) \
43 if ((dblv) >= SI_VPE_LOG_LEVEL_INFO) { \
44 printf("SIVPE INFO: %s: " fmt, __func__, ##args); \
45 }
46
47 #define SIVPE_WARN(dblv, fmt, args...) \
48 if ((dblv) >= SI_VPE_LOG_LEVEL_WARNING) { \
49 printf("SIVPE WARNING: %s: " fmt, __func__, ##args); \
50 }
51
52 #define SIVPE_DBG(dblv, fmt, args...) \
53 if ((dblv) >= SI_VPE_LOG_LEVEL_DEBUG) { \
54 printf("SIVPE DBG: %s: " fmt, __func__, ##args); \
55 }
56
57 #define SIVPE_ERR(fmt, args...) \
58 fprintf(stderr, "SIVPE ERROR %s:%d %s " fmt, __FILE__, __LINE__, __func__, ##args)
59
60 /* Use this enum to help us for accessing the anonymous struct src, dst
61 * in blit_info.
62 */
63 enum {
64 USE_SRC_SURFACE,
65 USE_DST_SURFACE
66 };
67
68
69 static void *
si_vpe_zalloc(void * mem_ctx,size_t size)70 si_vpe_zalloc(void* mem_ctx, size_t size)
71 {
72 /* mem_ctx is optional for now */
73 return CALLOC(1, size);
74 }
75
76
77 static void
si_vpe_free(void * mem_ctx,void * ptr)78 si_vpe_free(void* mem_ctx, void *ptr)
79 {
80 /* mem_ctx is optional for now */
81 if (ptr != NULL) {
82 FREE(ptr);
83 ptr = NULL;
84 }
85 }
86
87
88 static void
si_vpe_log(void * log_ctx,const char * fmt,...)89 si_vpe_log(void* log_ctx, const char* fmt, ...)
90 {
91 /* log_ctx is optional for now */
92 va_list args;
93
94 va_start(args, fmt);
95 vfprintf(stderr, fmt, args);
96 va_end(args);
97 }
98
99
100 static void
si_vpe_populate_debug_options(struct vpe_debug_options * debug)101 si_vpe_populate_debug_options(struct vpe_debug_options* debug)
102 {
103 /* ref: vpe-utils */
104 debug->flags.cm_in_bypass = 0;
105 debug->identity_3dlut = 0;
106 debug->sce_3dlut = 0;
107 debug->disable_reuse_bit = 0;
108 }
109
110
111 static void
si_vpe_populate_callback_modules(struct vpe_callback_funcs * funcs)112 si_vpe_populate_callback_modules(struct vpe_callback_funcs* funcs)
113 {
114 funcs->log = si_vpe_log;
115 funcs->zalloc = si_vpe_zalloc;
116 funcs->free = si_vpe_free;
117 return;
118 }
119
120 static char*
si_vpe_get_cositing_str(enum vpe_chroma_cositing cositing)121 si_vpe_get_cositing_str(enum vpe_chroma_cositing cositing)
122 {
123 switch (cositing) {
124 case VPE_CHROMA_COSITING_NONE:
125 return "NONE";
126 case VPE_CHROMA_COSITING_LEFT:
127 return "LEFT";
128 case VPE_CHROMA_COSITING_TOPLEFT:
129 return "TOPLEFT";
130 case VPE_CHROMA_COSITING_COUNT:
131 default:
132 return "ERROR";
133 }
134 }
135
136 static char*
si_vpe_get_primarie_str(enum vpe_color_primaries primarie)137 si_vpe_get_primarie_str(enum vpe_color_primaries primarie)
138 {
139 switch (primarie) {
140 case VPE_PRIMARIES_BT601:
141 return "BT601";
142 case VPE_PRIMARIES_BT709:
143 return "BT709";
144 case VPE_PRIMARIES_BT2020:
145 return "BT2020";
146 case VPE_PRIMARIES_JFIF:
147 return "JFIF";
148 case VPE_PRIMARIES_COUNT:
149 default:
150 return "ERROR";
151 }
152 }
153
154 static char*
si_vpe_get_tf_str(enum vpe_transfer_function tf)155 si_vpe_get_tf_str(enum vpe_transfer_function tf)
156 {
157 switch (tf) {
158 case VPE_TF_G22:
159 return "G22";
160 case VPE_TF_G24:
161 return "G24";
162 case VPE_TF_G10:
163 return "G10";
164 case VPE_TF_PQ:
165 return "PQ";
166 case VPE_TF_PQ_NORMALIZED:
167 return "PQ_NORMALIZED";
168 case VPE_TF_HLG:
169 return "HLG";
170 case VPE_TF_COUNT:
171 default:
172 return "ERROR";
173 }
174 }
175
176 /* cycle to the next set of buffers */
177 static void
next_buffer(struct vpe_video_processor * vpeproc)178 next_buffer(struct vpe_video_processor *vpeproc)
179 {
180 ++vpeproc->cur_buf;
181 vpeproc->cur_buf %= vpeproc->bufs_num;
182 }
183
184 static enum vpe_status
si_vpe_populate_init_data(struct si_context * sctx,struct vpe_init_data * params,uint8_t log_level)185 si_vpe_populate_init_data(struct si_context *sctx, struct vpe_init_data* params, uint8_t log_level)
186 {
187 if (!sctx || !params) {
188 return VPE_STATUS_ERROR;
189 }
190
191 params->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
192 params->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
193 params->ver_rev = sctx->screen->info.ip[AMD_IP_VPE].ver_rev;
194
195 si_vpe_populate_debug_options(¶ms->debug);
196 si_vpe_populate_callback_modules(¶ms->funcs);
197
198 SIVPE_DBG(log_level, "Get family: %d\n", sctx->family);
199 SIVPE_DBG(log_level, "Get gfx_level: %d\n", sctx->gfx_level);
200 SIVPE_DBG(log_level, "Set ver_major: %d\n", params->ver_major);
201 SIVPE_DBG(log_level, "Set ver_minor: %d\n", params->ver_minor);
202 SIVPE_DBG(log_level, "Set ver_rev: %d\n", params->ver_rev);
203
204 return VPE_STATUS_OK;
205 }
206
207
208 static enum vpe_status
si_vpe_allocate_buffer(struct vpe_build_bufs ** bufs)209 si_vpe_allocate_buffer(struct vpe_build_bufs **bufs)
210 {
211 if (!bufs) {
212 return VPE_STATUS_ERROR;
213 }
214
215 *bufs = (struct vpe_build_bufs *)malloc(sizeof(struct vpe_build_bufs));
216 if (!*bufs) {
217 return VPE_STATUS_NO_MEMORY;
218 }
219
220 (*bufs)->cmd_buf.cpu_va = 0;
221 (*bufs)->emb_buf.cpu_va = 0;
222 (*bufs)->cmd_buf.size = 0;
223 (*bufs)->emb_buf.size = 0;
224
225 return VPE_STATUS_OK;
226 }
227
228 static void
si_vpe_free_buffer(struct vpe_build_bufs * bufs)229 si_vpe_free_buffer(struct vpe_build_bufs *bufs)
230 {
231 if (!bufs) {
232 return;
233 }
234 free(bufs);
235 }
236
237 static enum vpe_surface_pixel_format
si_vpe_format(enum pipe_format format)238 si_vpe_format(enum pipe_format format)
239 {
240 enum vpe_surface_pixel_format ret;
241
242 switch (format) {
243 /* VPE input format: */
244 case PIPE_FORMAT_NV12:
245 ret = VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb;
246 break;
247 case PIPE_FORMAT_NV21:
248 ret = VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr;
249 break;
250 case PIPE_FORMAT_P010:
251 ret = VPE_SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb;
252 break;
253 /* VPE output format: */
254 case PIPE_FORMAT_A8R8G8B8_UNORM:
255 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA8888;
256 break;
257 case PIPE_FORMAT_A8B8G8R8_UNORM:
258 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA8888;
259 break;
260 case PIPE_FORMAT_R8G8B8A8_UNORM:
261 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR8888;
262 break;
263 case PIPE_FORMAT_B8G8R8A8_UNORM:
264 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
265 break;
266 case PIPE_FORMAT_X8R8G8B8_UNORM:
267 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRX8888;
268 break;
269 case PIPE_FORMAT_X8B8G8R8_UNORM:
270 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBX8888;
271 break;
272 case PIPE_FORMAT_R8G8B8X8_UNORM:
273 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_XBGR8888;
274 break;
275 case PIPE_FORMAT_B8G8R8X8_UNORM:
276 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_XRGB8888;
277 break;
278 case PIPE_FORMAT_A2R10G10B10_UNORM:
279 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_BGRA1010102;
280 break;
281 case PIPE_FORMAT_A2B10G10R10_UNORM:
282 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_RGBA1010102;
283 break;
284 case PIPE_FORMAT_B10G10R10A2_UNORM:
285 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010;
286 break;
287 case PIPE_FORMAT_R10G10B10A2_UNORM:
288 ret = VPE_SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010;
289 break;
290 default:
291 ret = VPE_SURFACE_PIXEL_FORMAT_INVALID;
292 break;
293 }
294 return ret;
295 }
296
297 static enum vpe_status
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)298 si_vpe_set_color_space(const struct pipe_vpp_desc *process_properties,
299 struct vpe_color_space *color_space,
300 enum pipe_format format,
301 int which_surface)
302 {
303 enum pipe_video_vpp_color_standard_type colors_standard;
304 enum pipe_video_vpp_color_range color_range;
305 enum pipe_video_vpp_chroma_siting chroma_siting;
306
307 if (which_surface == USE_SRC_SURFACE) {
308 colors_standard = process_properties->in_colors_standard;
309 color_range = process_properties->in_color_range;
310 chroma_siting = process_properties->in_chroma_siting;
311 } else {
312 colors_standard = process_properties->out_colors_standard;
313 color_range = process_properties->out_color_range;
314 chroma_siting = process_properties->out_chroma_siting;
315 }
316
317 switch (colors_standard) {
318 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601:
319 color_space->primaries = VPE_PRIMARIES_BT601;
320 color_space->tf = VPE_TF_G24;
321 break;
322 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709:
323 color_space->primaries = VPE_PRIMARIES_BT709;
324 color_space->tf = VPE_TF_G22;
325 break;
326 case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020:
327 color_space->primaries = VPE_PRIMARIES_BT2020;
328 color_space->tf = VPE_TF_PQ;
329 break;
330 default:
331 color_space->primaries = VPE_PRIMARIES_BT709;
332 color_space->tf = VPE_TF_G22;
333 break;
334 }
335
336 switch (color_range) {
337 case PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED:
338 color_space->range = VPE_COLOR_RANGE_STUDIO;
339 break;
340 case PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL:
341 color_space->range = VPE_COLOR_RANGE_FULL;
342 break;
343 default:
344 color_space->range = VPE_COLOR_RANGE_FULL;
345 break;
346 }
347
348 /* Default use VPE_CHROMA_COSITING_NONE (CENTER | CENTER) */
349 color_space->cositing = VPE_CHROMA_COSITING_NONE;
350 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER){
351 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT)
352 color_space->cositing = VPE_CHROMA_COSITING_LEFT;
353 //else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER)
354 // color_space->cositing = VPE_CHROMA_COSITING_NONE;
355 } else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP) {
356 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT)
357 color_space->cositing = VPE_CHROMA_COSITING_TOPLEFT;
358 //else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER)
359 // color_space->cositing = VPE_CHROMA_COSITING_NONE;
360 } else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM) {
361 if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT)
362 color_space->cositing = VPE_CHROMA_COSITING_LEFT;
363 //else if (chroma_siting & PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER)
364 // color_space->cositing = VPE_CHROMA_COSITING_NONE;
365 }
366
367 /* VPE 1.0 Input format only supports NV12 and NV21 now */
368 switch (format) {
369 case PIPE_FORMAT_NV12:
370 case PIPE_FORMAT_NV21:
371 case PIPE_FORMAT_P010:
372 color_space->encoding = VPE_PIXEL_ENCODING_YCbCr;
373 break;
374 case PIPE_FORMAT_A8R8G8B8_UNORM:
375 case PIPE_FORMAT_A8B8G8R8_UNORM:
376 case PIPE_FORMAT_R8G8B8A8_UNORM:
377 case PIPE_FORMAT_B8G8R8A8_UNORM:
378 case PIPE_FORMAT_X8R8G8B8_UNORM:
379 case PIPE_FORMAT_X8B8G8R8_UNORM:
380 case PIPE_FORMAT_R8G8B8X8_UNORM:
381 case PIPE_FORMAT_B8G8R8X8_UNORM:
382 case PIPE_FORMAT_A2R10G10B10_UNORM:
383 case PIPE_FORMAT_R10G10B10A2_UNORM:
384 case PIPE_FORMAT_A2B10G10R10_UNORM:
385 case PIPE_FORMAT_B10G10R10A2_UNORM:
386 default:
387 color_space->encoding = VPE_PIXEL_ENCODING_RGB;
388 break;
389 }
390 return VPE_STATUS_OK;
391 }
392
393 /* Combine si_vpe_set_plane_address and si_vpe_set_plane_size*/
394 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)395 si_vpe_set_plane_info(struct vpe_video_processor *vpeproc,
396 const struct pipe_vpp_desc *process_properties,
397 struct pipe_surface **surfaces,
398 int which_surface,
399 struct vpe_surface_info *surface_info)
400 {
401 struct vpe_plane_address *plane_address = &surface_info->address;
402 struct vpe_plane_size *plane_size = &surface_info->plane_size;
403 struct si_resource *si_res;
404 uint32_t width, height, pitch, pos_x, pos_y, offset;
405 enum pipe_format format;
406
407 if (which_surface == USE_SRC_SURFACE) {
408 pos_x = process_properties->src_region.x0;
409 pos_y = process_properties->src_region.y0;
410 width = process_properties->src_region.x1 - pos_x;
411 height = process_properties->src_region.y1 - pos_y;
412 format = process_properties->base.input_format;
413 } else {
414 pos_x = process_properties->dst_region.x0;
415 pos_y = process_properties->dst_region.y0;
416 width = process_properties->dst_region.x1 - pos_x;
417 height = process_properties->dst_region.y1 - pos_y;
418 format = process_properties->base.output_format;
419 }
420
421 /* Formate Color Space */
422 surface_info->format = si_vpe_format(format);
423 si_vpe_set_color_space(process_properties, &surface_info->cs, format, which_surface);
424
425 /* Get surface info, such as buffer alignment and offset */
426 if (vpeproc->base.context->screen && vpeproc->base.context->screen->resource_get_info) {
427 vpeproc->base.context->screen->resource_get_info(vpeproc->base.context->screen,
428 surfaces[0]->texture,
429 &pitch,
430 &offset);
431 } else {
432 SIVPE_ERR("Get plane pitch and offset info failed\n");
433 return VPE_STATUS_ERROR;
434 }
435
436 si_res = si_resource(surfaces[0]->texture);
437 plane_address->tmz_surface = false;
438
439 /* here is the SURFACE size, not image rect */
440 plane_size->surface_size.x = 0;
441 plane_size->surface_size.y = 0;
442 plane_size->surface_size.width = surfaces[0]->width;
443 plane_size->surface_size.height = surfaces[0]->height;
444 plane_size->surface_pitch = pitch; // Byte alignment
445
446 switch (format) {
447 case PIPE_FORMAT_NV12:
448 case PIPE_FORMAT_NV21:
449 plane_address->type = VPE_PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
450 plane_address->video_progressive.luma_addr.quad_part = si_res->gpu_address + offset;
451 plane_address->video_progressive.luma_meta_addr.quad_part = 0;
452 plane_address->video_progressive.luma_dcc_const_color.quad_part = 0;
453 //plane_size->surface_pitch /= 1; // Byte alignment to Pixel alignment
454 /* Get 2nd plane buffer info */
455 if (surfaces[1] && vpeproc->base.context->screen && vpeproc->base.context->screen->resource_get_info) {
456 vpeproc->base.context->screen->resource_get_info(vpeproc->base.context->screen,
457 surfaces[1]->texture,
458 &pitch,
459 &offset);
460 } else {
461 SIVPE_ERR("Get 2nd plane pitch and offset info failed\n");
462 return VPE_STATUS_ERROR;
463 }
464 si_res = si_resource(surfaces[1]->texture);
465 plane_address->video_progressive.chroma_addr.quad_part = si_res->gpu_address + offset;
466 plane_address->video_progressive.chroma_meta_addr.quad_part = 0;
467 plane_address->video_progressive.chroma_dcc_const_color.quad_part = 0;
468
469 plane_size->chroma_size.x = pos_x;
470 plane_size->chroma_size.y = pos_y;
471 plane_size->chroma_size.width = (width + 1) / 2; // 2 pixel-width alignment
472 plane_size->chroma_size.height = (height + 1) / 2; // 2 pixel-height alignment
473 plane_size->chroma_pitch = pitch / 2; // Byte alignment to Pixel alignment (NV12/NV21 2nd plane is 16 bits per pixel)
474 break;
475
476 case PIPE_FORMAT_P010:
477 plane_address->type = VPE_PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
478 plane_address->video_progressive.luma_addr.quad_part = si_res->gpu_address + offset;
479 plane_address->video_progressive.luma_meta_addr.quad_part = 0;
480 plane_address->video_progressive.luma_dcc_const_color.quad_part = 0;
481 plane_size->surface_pitch /= 2; // Byte alignment to Pixel alignment (P010 plane is 16 bits per pixel)
482 if (surfaces[1] && vpeproc->base.context->screen && vpeproc->base.context->screen->resource_get_info)
483 vpeproc->base.context->screen->resource_get_info(vpeproc->base.context->screen,
484 surfaces[1]->texture,
485 &pitch,
486 &offset);
487 else {
488 SIVPE_ERR("Get 2nd plane pitch and offset info failed\n");
489 return VPE_STATUS_ERROR;
490 }
491 si_res = si_resource(surfaces[1]->texture);
492 plane_address->video_progressive.chroma_addr.quad_part = si_res->gpu_address + offset;
493 plane_address->video_progressive.chroma_meta_addr.quad_part = 0;
494 plane_address->video_progressive.chroma_dcc_const_color.quad_part = 0;
495
496 plane_size->chroma_size.x = pos_x;
497 plane_size->chroma_size.y = pos_y;
498 plane_size->chroma_size.width = (width + 1) / 2; // 2 pixel-width alignment
499 plane_size->chroma_size.height = (height + 1) / 2; // 2 pixel-height alignment
500 plane_size->chroma_pitch = pitch / 4; // Byte alignment to Pixel alignment (NV12/NV21 2nd plane is 32 bits per pixel)
501 break;
502
503 case PIPE_FORMAT_A8R8G8B8_UNORM:
504 case PIPE_FORMAT_A8B8G8R8_UNORM:
505 case PIPE_FORMAT_R8G8B8A8_UNORM:
506 case PIPE_FORMAT_B8G8R8A8_UNORM:
507 case PIPE_FORMAT_X8R8G8B8_UNORM:
508 case PIPE_FORMAT_X8B8G8R8_UNORM:
509 case PIPE_FORMAT_R8G8B8X8_UNORM:
510 case PIPE_FORMAT_B8G8R8X8_UNORM:
511 plane_address->type = VPE_PLN_ADDR_TYPE_GRAPHICS;
512 plane_address->grph.addr.quad_part = si_res->gpu_address + offset;
513 plane_address->grph.meta_addr.quad_part = 0;
514 plane_address->grph.dcc_const_color.quad_part = 0;
515 plane_size->surface_pitch /= 4; // Byte alignment to Pixel alignment (RGBA plane is 32 bits per pixel)
516
517 plane_size->chroma_size.x = 0;
518 plane_size->chroma_size.y = 0;
519 plane_size->chroma_size.width = 0;
520 plane_size->chroma_size.height = 0;
521 plane_size->chroma_pitch = 0;
522 break;
523
524 case PIPE_FORMAT_A2R10G10B10_UNORM:
525 case PIPE_FORMAT_R10G10B10A2_UNORM:
526 case PIPE_FORMAT_A2B10G10R10_UNORM:
527 case PIPE_FORMAT_B10G10R10A2_UNORM:
528 default:
529 SIVPE_ERR("Un-supported format %d\n", format);
530 }
531 return VPE_STATUS_OK;
532 }
533
534 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)535 si_vpe_set_surface_info(struct vpe_video_processor *vpeproc,
536 const struct pipe_vpp_desc *process_properties,
537 struct pipe_surface **surfaces,
538 int which_surface,
539 struct vpe_surface_info *surface_info)
540 {
541 assert(surface_info);
542
543 /* Set up surface pitch, plane address, color space */
544 si_vpe_set_plane_info(vpeproc, process_properties, surfaces, which_surface, surface_info);
545
546 /* VAAPI does not provide swizzle info right now.
547 * Swizzle mode is strongly releated to hardware DMA design,
548 * intel-vaapi-driver/i965_drv_video.c also does not handle swizzle information,
549 * maybe this is the reason why it is not currently supported.
550 *
551 * Just default to linear or none temporarily.
552 */
553 surface_info->swizzle = VPE_SW_LINEAR;
554
555 struct vpe_plane_dcc_param *dcc_param = &surface_info->dcc;
556 dcc_param->enable = false;
557 dcc_param->meta_pitch = 0;
558 dcc_param->independent_64b_blks = false;
559 dcc_param->dcc_ind_blk = 0;
560 dcc_param->meta_pitch_c = 0;
561 dcc_param->independent_64b_blks_c = false;
562 dcc_param->dcc_ind_blk_c = 0;
563
564 return VPE_STATUS_OK;
565 }
566
567 static enum vpe_status
si_vpe_set_stream(const struct pipe_vpp_desc * process_properties,struct vpe_stream * stream)568 si_vpe_set_stream(const struct pipe_vpp_desc *process_properties,
569 struct vpe_stream *stream)
570 {
571 struct vpe_scaling_info *scaling_info = &stream->scaling_info;
572 scaling_info->src_rect.x = process_properties->src_region.x0;
573 scaling_info->src_rect.y = process_properties->src_region.y0;
574 scaling_info->src_rect.width = process_properties->src_region.x1 - process_properties->src_region.x0;
575 scaling_info->src_rect.height = process_properties->src_region.y1 - process_properties->src_region.y0;
576 scaling_info->dst_rect.x = process_properties->dst_region.x0;
577 scaling_info->dst_rect.y = process_properties->dst_region.y0;
578 scaling_info->dst_rect.width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
579 scaling_info->dst_rect.height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
580 /* Programmable 1 to 8 taps of vertical polyphase filter, and
581 * programmable 1, 2, 4, 6, 8 taps of horizontal polyphase filter.
582 */
583 scaling_info->taps.v_taps = 4;
584 scaling_info->taps.h_taps = 4;
585 scaling_info->taps.v_taps_c = 2;
586 scaling_info->taps.h_taps_c = 2;
587
588 /* Blending is not supported for now */
589 struct vpe_blend_info *blend_info = &stream->blend_info;
590 blend_info->blending = false;
591 blend_info->pre_multiplied_alpha = false;
592 blend_info->global_alpha = false;
593 blend_info->global_alpha_value = 0.0;
594 /* Global Alpha for Background ? */
595 if (process_properties->blend.mode == PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA) {
596 blend_info->global_alpha = true;
597 blend_info->global_alpha_value = process_properties->blend.global_alpha;
598 }
599
600 /* TODO: do ProcAmp in next stage */
601 struct vpe_color_adjust *color_adj = &stream->color_adj;
602 color_adj->brightness = 0.0;
603 color_adj->contrast = 1.0;
604 color_adj->hue = 0.0;
605 color_adj->saturation = 1.0;
606
607 /* TODO: Tone Mapping */
608 //struct vpe_tonemap_params *tm_params = &stream->tm_params;
609
610
611 stream->horizontal_mirror = false;
612 stream->vertical_mirror = false;
613 switch (process_properties->orientation & 0xF) {
614 case PIPE_VIDEO_VPP_ROTATION_90:
615 stream->rotation = VPE_ROTATION_ANGLE_90;
616 break;
617 case PIPE_VIDEO_VPP_ROTATION_180:
618 stream->rotation = VPE_ROTATION_ANGLE_180;
619 break;
620 case PIPE_VIDEO_VPP_ROTATION_270:
621 stream->rotation = VPE_ROTATION_ANGLE_270;
622 break;
623 default:
624 stream->rotation = VPE_ROTATION_ANGLE_0;
625 break;
626 }
627 if (process_properties->orientation & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) {
628 stream->horizontal_mirror = true;
629 }
630 if (process_properties->orientation & PIPE_VIDEO_VPP_FLIP_VERTICAL)
631 stream->vertical_mirror = true;
632
633 stream->enable_luma_key = false;
634 stream->lower_luma_bound = 0.5;
635 stream->upper_luma_bound = 0.5;
636
637 stream->flags.hdr_metadata = 0;
638 stream->flags.reserved = 0;
639
640 /* TODO: hdr_metadata support in next stage */
641 stream->hdr_metadata.redX = 1;
642 stream->hdr_metadata.redY = 1;
643 stream->hdr_metadata.greenX = 1;
644 stream->hdr_metadata.greenY = 1;
645 stream->hdr_metadata.blueX = 1;
646 stream->hdr_metadata.blueY = 1;
647 stream->hdr_metadata.whiteX = 1;
648 stream->hdr_metadata.whiteY = 1;
649
650 stream->hdr_metadata.min_mastering = 1;
651 stream->hdr_metadata.max_mastering = 1;
652 stream->hdr_metadata.max_content = 1;
653 stream->hdr_metadata.avg_content = 1;
654
655 return VPE_STATUS_OK;
656 }
657
658 static void
si_vpe_processor_destroy(struct pipe_video_codec * codec)659 si_vpe_processor_destroy(struct pipe_video_codec *codec)
660 {
661 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
662 unsigned int i;
663 assert(codec);
664
665 if (vpeproc->process_fence) {
666 SIVPE_INFO(vpeproc->log_level, "Wait fence\n");
667 vpeproc->ws->fence_wait(vpeproc->ws, vpeproc->process_fence, PIPE_DEFAULT_DECODER_FEEDBACK_TIMEOUT_NS);
668 }
669 vpeproc->ws->cs_destroy(&vpeproc->cs);
670
671 if (vpeproc->vpe_build_bufs)
672 si_vpe_free_buffer(vpeproc->vpe_build_bufs);
673 if (vpeproc->vpe_handle)
674 vpe_destroy(&vpeproc->vpe_handle);
675 if (vpeproc->vpe_build_param) {
676 if (vpeproc->vpe_build_param->streams)
677 FREE(vpeproc->vpe_build_param->streams);
678 FREE(vpeproc->vpe_build_param);
679 }
680 if (vpeproc->emb_buffers) {
681 for (i = 0; i < vpeproc->bufs_num; i++) {
682 if (vpeproc->emb_buffers[i].res) {
683 vpeproc->ws->buffer_unmap(vpeproc->ws, vpeproc->emb_buffers[i].res->buf);
684 si_vid_destroy_buffer(&vpeproc->emb_buffers[i]);
685 }
686 }
687 FREE(vpeproc->emb_buffers);
688 }
689 if (vpeproc->mapped_cpu_va)
690 FREE(vpeproc->mapped_cpu_va);
691 vpeproc->bufs_num = 0;
692
693 SIVPE_DBG(vpeproc->log_level, "Success\n");
694 FREE(vpeproc);
695 }
696
697 static void
si_vpe_processor_begin_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)698 si_vpe_processor_begin_frame(struct pipe_video_codec *codec,
699 struct pipe_video_buffer *target,
700 struct pipe_picture_desc *picture)
701 {
702 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
703 struct pipe_surface **dst_surfaces;
704 assert(codec);
705
706 dst_surfaces = target->get_surfaces(target);
707 if (!dst_surfaces || !dst_surfaces[0]) {
708 SIVPE_ERR("Get target surface failed\n");
709 return;
710 }
711 vpeproc->dst_surfaces = dst_surfaces;
712 }
713
714 static void
si_vpe_cs_add_surface_buffer(struct vpe_video_processor * vpeproc,struct pipe_surface ** surfaces,unsigned usage)715 si_vpe_cs_add_surface_buffer(struct vpe_video_processor *vpeproc,
716 struct pipe_surface **surfaces,
717 unsigned usage)
718 {
719 struct si_resource *si_res;
720 int i;
721
722 for (i = 0; i < VL_MAX_SURFACES; ++i) {
723 if (!surfaces[i])
724 continue;
725
726 si_res = si_resource(surfaces[i]->texture);
727 vpeproc->ws->cs_add_buffer(&vpeproc->cs, si_res->buf, usage | RADEON_USAGE_SYNCHRONIZED, 0);
728 }
729 }
730
731 static void
si_vpe_processor_process_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * input_texture,const struct pipe_vpp_desc * process_properties)732 si_vpe_processor_process_frame(struct pipe_video_codec *codec,
733 struct pipe_video_buffer *input_texture,
734 const struct pipe_vpp_desc *process_properties)
735 {
736 enum vpe_status result = VPE_STATUS_OK;
737 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
738 struct vpe *vpe_handle = vpeproc->vpe_handle;
739 struct vpe_build_param *build_param = vpeproc->vpe_build_param;
740 struct pipe_surface **src_surfaces;
741 struct vpe_bufs_req bufs_required;
742 struct rvid_buffer *emb_buf;
743 uint64_t *vpe_ptr;
744
745 assert(codec);
746 assert(process_properties);
747 assert(vpeproc->dst_surfaces);
748
749 src_surfaces = input_texture->get_surfaces(input_texture);
750 if (!src_surfaces || !src_surfaces[0]) {
751 SIVPE_ERR("Get source surface failed\n");
752 return;
753 }
754 vpeproc->src_surfaces = src_surfaces;
755
756 /* Following setting is from si_vpe_set_build_param()*/
757 /* VPE 1.0 only support one input */
758 build_param->num_streams = 1;
759 if (build_param->num_streams > VPE_STREAM_MAX_NUM) {
760 SIVPE_ERR("Can only suppport %d stream(s) now\n", VPE_STREAM_MAX_NUM);
761 return;
762 }
763
764 if (!build_param->streams) {
765 SIVPE_ERR("Streams structure is not allocated\n");
766 return;
767 }
768
769 si_vpe_set_surface_info(vpeproc,
770 process_properties,
771 vpeproc->src_surfaces,
772 USE_SRC_SURFACE,
773 &build_param->streams[0].surface_info);
774
775 si_vpe_set_stream(process_properties, &build_param->streams[0]);
776
777 si_vpe_set_surface_info(vpeproc,
778 process_properties,
779 vpeproc->dst_surfaces,
780 USE_DST_SURFACE,
781 &build_param->dst_surface);
782
783 if (process_properties->background_color) {
784 build_param->target_rect.x = 0;
785 build_param->target_rect.y = 0;
786 build_param->target_rect.width = vpeproc->dst_surfaces[0]->width;
787 build_param->target_rect.height = vpeproc->dst_surfaces[0]->height;
788 } else {
789 build_param->target_rect.x = process_properties->dst_region.x0;
790 build_param->target_rect.y = process_properties->dst_region.y0;
791 build_param->target_rect.width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
792 build_param->target_rect.height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
793 }
794
795 /* TODO: background color is not specified in pipe_vpp_desc structure.
796 * Need to add this filed in pipe_vpp_desc.
797 */
798 build_param->bg_color.is_ycbcr = false;
799
800 if (!(process_properties->background_color & 0xFFFFFF) &&
801 (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_STUDIO)) {
802 build_param->bg_color.rgba.a =
803 (float)((process_properties->background_color & 0xFF000000) >> 24) / 255.0;
804 build_param->bg_color.rgba.r = 0.0628;
805 build_param->bg_color.rgba.g = 0.0628;
806 build_param->bg_color.rgba.b = 0.0628;
807 } else if (process_properties->background_color) {
808 build_param->bg_color.rgba.a =
809 (float)((process_properties->background_color & 0xFF000000) >> 24) / 255.0;
810 build_param->bg_color.rgba.r =
811 (float)((process_properties->background_color & 0x00FF0000) >> 16) / 255.0;
812 build_param->bg_color.rgba.g =
813 (float)((process_properties->background_color & 0x0000FF00) >> 8) / 255.0;
814 build_param->bg_color.rgba.b =
815 (float)(process_properties->background_color & 0x000000FF) / 255.0;
816 } else {
817 build_param->bg_color.rgba.r = 0;
818 build_param->bg_color.rgba.g = 0;
819 build_param->bg_color.rgba.b = 0;
820 build_param->bg_color.rgba.a = 0;
821 }
822
823 build_param->alpha_mode = VPE_ALPHA_OPAQUE;
824
825 build_param->flags.hdr_metadata = 0;
826 build_param->flags.reserved = 1;
827
828 /* TODO: hdr_metadata support in next stage */
829 build_param->hdr_metadata.redX = 1;
830 build_param->hdr_metadata.redY = 1;
831 build_param->hdr_metadata.greenX = 1;
832 build_param->hdr_metadata.greenY = 1;
833 build_param->hdr_metadata.blueX = 1;
834 build_param->hdr_metadata.blueY = 1;
835 build_param->hdr_metadata.whiteX = 1;
836 build_param->hdr_metadata.whiteY = 1;
837
838 build_param->hdr_metadata.min_mastering = 1;
839 build_param->hdr_metadata.max_mastering = 1;
840 build_param->hdr_metadata.max_content = 1;
841 build_param->hdr_metadata.avg_content = 1;
842
843
844 /* Setup CmdBuf and EmbBuf address adn size information */
845 vpe_ptr = (uint64_t *)vpeproc->cs.current.buf;
846 vpeproc->vpe_build_bufs->cmd_buf.cpu_va = (uintptr_t)vpe_ptr;
847 vpeproc->vpe_build_bufs->cmd_buf.gpu_va = 0;
848 vpeproc->vpe_build_bufs->cmd_buf.size = vpeproc->cs.current.max_dw;
849 vpeproc->vpe_build_bufs->cmd_buf.tmz = false;
850
851 emb_buf = &vpeproc->emb_buffers[vpeproc->cur_buf];
852 vpeproc->vpe_build_bufs->emb_buf.cpu_va = (uintptr_t)vpeproc->mapped_cpu_va[vpeproc->cur_buf];
853 vpeproc->vpe_build_bufs->emb_buf.gpu_va = vpeproc->ws->buffer_get_virtual_address(emb_buf->res->buf);
854 vpeproc->vpe_build_bufs->emb_buf.size = VPE_EMBBUF_SIZE;
855 vpeproc->vpe_build_bufs->emb_buf.tmz = false;
856
857
858 if (vpeproc->log_level >= SI_VPE_LOG_LEVEL_DEBUG) {
859 SIVPE_DBG(vpeproc->log_level, "src surface format(%d) rect (%d, %d, %d, %d)\n",
860 build_param->streams[0].surface_info.format,
861 build_param->streams[0].surface_info.plane_size.surface_size.x,
862 build_param->streams[0].surface_info.plane_size.surface_size.y,
863 build_param->streams[0].surface_info.plane_size.surface_size.width,
864 build_param->streams[0].surface_info.plane_size.surface_size.height);
865
866 SIVPE_DBG(vpeproc->log_level, "src surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
867 si_vpe_get_cositing_str(build_param->streams[0].surface_info.cs.cositing),
868 si_vpe_get_primarie_str(build_param->streams[0].surface_info.cs.primaries),
869 si_vpe_get_tf_str(build_param->streams[0].surface_info.cs.tf),
870 (build_param->streams[0].surface_info.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
871
872 SIVPE_DBG(vpeproc->log_level, "dst surface format(%d) rect (%d, %d, %d, %d)\n",
873 build_param->dst_surface.format,
874 build_param->dst_surface.plane_size.surface_size.x,
875 build_param->dst_surface.plane_size.surface_size.y,
876 build_param->dst_surface.plane_size.surface_size.width,
877 build_param->dst_surface.plane_size.surface_size.height);
878
879 SIVPE_DBG(vpeproc->log_level, "dst surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
880 si_vpe_get_cositing_str(build_param->dst_surface.cs.cositing),
881 si_vpe_get_primarie_str(build_param->dst_surface.cs.primaries),
882 si_vpe_get_tf_str(build_param->dst_surface.cs.tf),
883 (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
884
885 SIVPE_DBG(vpeproc->log_level, "Source surface pitch(%d), chroma pitch(%d), dst-surface pitch(%d), chroma pitch(%d)\n",
886 build_param->streams[0].surface_info.plane_size.surface_pitch,
887 build_param->streams[0].surface_info.plane_size.chroma_pitch,
888 build_param->dst_surface.plane_size.surface_pitch,
889 build_param->dst_surface.plane_size.chroma_pitch);
890
891 SIVPE_DBG(vpeproc->log_level, "background color RGBA(%0.3f, %0.3f, %0.3f, %0.3f)\n",
892 build_param->bg_color.rgba.r,
893 build_param->bg_color.rgba.g,
894 build_param->bg_color.rgba.b,
895 build_param->bg_color.rgba.a);
896
897 SIVPE_DBG(vpeproc->log_level, "target_rect(%d, %d, %d, %d)\n",
898 build_param->target_rect.x,
899 build_param->target_rect.y,
900 build_param->target_rect.width,
901 build_param->target_rect.height);
902
903 SIVPE_DBG(vpeproc->log_level, "rotation(%d) horizontal_mirror(%d) vertical_mirror(%d)\n",
904 build_param->streams[0].rotation,
905 build_param->streams[0].horizontal_mirror,
906 build_param->streams[0].vertical_mirror);
907
908 SIVPE_DBG(vpeproc->log_level, "scaling_src_rect(%d, %d, %d, %d)\n",
909 build_param->streams[0].scaling_info.src_rect.x,
910 build_param->streams[0].scaling_info.src_rect.y,
911 build_param->streams[0].scaling_info.src_rect.width,
912 build_param->streams[0].scaling_info.src_rect.height);
913
914 SIVPE_DBG(vpeproc->log_level, "scaling_dst_rect(%d, %d, %d, %d)\n",
915 build_param->streams[0].scaling_info.dst_rect.x,
916 build_param->streams[0].scaling_info.dst_rect.y,
917 build_param->streams[0].scaling_info.dst_rect.width,
918 build_param->streams[0].scaling_info.dst_rect.height);
919
920 SIVPE_DBG(vpeproc->log_level, "scaling_taps h_taps(%d) v_taps(%d) h_taps_c(%d) v_taps_c(%d)\n",
921 build_param->streams[0].scaling_info.taps.h_taps,
922 build_param->streams[0].scaling_info.taps.v_taps,
923 build_param->streams[0].scaling_info.taps.h_taps_c,
924 build_param->streams[0].scaling_info.taps.v_taps_c);
925
926 SIVPE_DBG(vpeproc->log_level, "blend global_alpha(%d): %0.3f\n",
927 build_param->streams[0].blend_info.global_alpha,
928 build_param->streams[0].blend_info.global_alpha_value);
929
930 SIVPE_DBG(vpeproc->log_level, "ToneMapping shaper_tf(%d) lut_out_tf(%d) lut_in_gamut(%d) lut_out_gamut(%d)\n",
931 build_param->streams[0].tm_params.shaper_tf,
932 build_param->streams[0].tm_params.lut_out_tf,
933 build_param->streams[0].tm_params.lut_in_gamut,
934 build_param->streams[0].tm_params.lut_out_gamut);
935
936 //SIVPE_DBG(vpeproc->log_level, "ToneMapping update_3dlut(%d) enable_3dlut(%d)\n",
937 // build_param->streams[0].tm_params.update_3dlut,
938 // build_param->streams[0].tm_params.enable_3dlut);
939 }
940
941 if(vpe_handle->level == VPE_IP_LEVEL_1_1) {
942 build_param->num_instances = 2;
943 build_param->collaboration_mode = true;
944 } else {
945 build_param->num_instances = 1;
946 build_param->collaboration_mode = false;
947 }
948
949 result = vpe_check_support(vpe_handle, build_param, &bufs_required);
950 if (VPE_STATUS_OK != result) {
951 SIVPE_ERR("Check support failed with result: %d\n", result);
952 goto fail;
953 }
954
955 result = vpe_build_commands(vpe_handle, build_param, vpeproc->vpe_build_bufs);
956 if (VPE_STATUS_OK != result) {
957 SIVPE_ERR("Build commands failed with result: %d\n", result);
958 goto fail;
959 }
960
961 /* Check buffer size */
962 if (vpeproc->vpe_build_bufs->cmd_buf.size == 0 || vpeproc->vpe_build_bufs->cmd_buf.size == vpeproc->cs.current.max_dw) {
963 SIVPE_ERR("Cmdbuf size wrong\n");
964 goto fail;
965 }
966 if (vpeproc->vpe_build_bufs->emb_buf.size == 0 || vpeproc->vpe_build_bufs->emb_buf.size == VPE_EMBBUF_SIZE) {
967 SIVPE_ERR("Embbuf size wrong\n");
968 goto fail;
969 }
970 SIVPE_INFO(vpeproc->log_level, "Used buf size: %" PRIu64 ", %" PRIu64 "\n",
971 vpeproc->vpe_build_bufs->cmd_buf.size, vpeproc->vpe_build_bufs->emb_buf.size);
972
973 /* Have to tell Command Submission context the command length wrote by libvpe */
974 vpeproc->cs.current.cdw += (vpeproc->vpe_build_bufs->cmd_buf.size / 4);
975
976 /* Add embbuf into bo_handle list */
977 vpeproc->ws->cs_add_buffer(&vpeproc->cs, emb_buf->res->buf, RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_GTT);
978
979 si_vpe_cs_add_surface_buffer(vpeproc, vpeproc->src_surfaces, RADEON_USAGE_READ);
980 si_vpe_cs_add_surface_buffer(vpeproc, vpeproc->dst_surfaces, RADEON_USAGE_WRITE);
981
982 SIVPE_DBG(vpeproc->log_level, "Success\n");
983 return;
984
985 fail:
986 vpeproc->ws->buffer_unmap(vpeproc->ws, emb_buf->res->buf);
987 SIVPE_ERR("Failed\n");
988 return;
989 }
990
991 static int
si_vpe_processor_end_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)992 si_vpe_processor_end_frame(struct pipe_video_codec *codec,
993 struct pipe_video_buffer *target,
994 struct pipe_picture_desc *picture)
995 {
996 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
997 struct pipe_fence_handle *process_fence = NULL;
998 assert(codec);
999
1000 vpeproc->ws->cs_flush(&vpeproc->cs, picture->flush_flags, &process_fence);
1001 next_buffer(vpeproc);
1002
1003 if (picture->fence && process_fence) {
1004 *picture->fence = process_fence;
1005 SIVPE_INFO(vpeproc->log_level, "Assign process fence\n");
1006 } else
1007 SIVPE_WARN(vpeproc->log_level, "Fence may have problem!\n");
1008
1009 SIVPE_INFO(vpeproc->log_level, "Success\n");
1010 return 0;
1011 }
1012
1013 static void
si_vpe_processor_flush(struct pipe_video_codec * codec)1014 si_vpe_processor_flush(struct pipe_video_codec *codec)
1015 {
1016 //struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1017 //assert(codec);
1018
1019 //SIVPE_DBG(vpeproc->log_level, "Success\n");
1020 return;
1021 }
1022
si_vpe_processor_get_processor_fence(struct pipe_video_codec * codec,struct pipe_fence_handle * fence,uint64_t timeout)1023 static int si_vpe_processor_get_processor_fence(struct pipe_video_codec *codec,
1024 struct pipe_fence_handle *fence,
1025 uint64_t timeout)
1026 {
1027 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1028 assert(codec);
1029
1030 SIVPE_INFO(vpeproc->log_level, "Wait processor fence\n");
1031 if (!vpeproc->ws->fence_wait(vpeproc->ws, fence, timeout)) {
1032 SIVPE_DBG(vpeproc->log_level, "Wait processor fence fail\n");
1033 return 0;
1034 }
1035 SIVPE_INFO(vpeproc->log_level, "Wait processor fence success\n");
1036 return 1;
1037 }
1038
1039 struct pipe_video_codec*
si_vpe_create_processor(struct pipe_context * context,const struct pipe_video_codec * templ)1040 si_vpe_create_processor(struct pipe_context *context, const struct pipe_video_codec *templ)
1041 {
1042 struct si_context *sctx = (struct si_context *)context;
1043 struct radeon_winsys *ws = sctx->ws;
1044 struct vpe_video_processor *vpeproc;
1045 struct vpe_init_data *init_data;
1046 const char *str = getenv("AMDGPU_SIVPE_LOG_LEVEL");
1047 unsigned int i;
1048
1049 vpeproc = CALLOC_STRUCT(vpe_video_processor);
1050 if (!vpeproc) {
1051 SIVPE_ERR("Allocate struct failed\n");
1052 return NULL;
1053 }
1054
1055 /* get SI_VPE debug log level */
1056 if (str == NULL)
1057 vpeproc->log_level = SI_VPE_LOG_LEVEL_DEFAULT;
1058 else
1059 vpeproc->log_level = atoi(str);
1060
1061 vpeproc->base = *templ;
1062 vpeproc->base.context = context;
1063 vpeproc->base.width = templ->width;
1064 vpeproc->base.height = templ->height;
1065
1066 vpeproc->base.destroy = si_vpe_processor_destroy;
1067 vpeproc->base.begin_frame = si_vpe_processor_begin_frame;
1068 vpeproc->base.process_frame = si_vpe_processor_process_frame;
1069 vpeproc->base.end_frame = si_vpe_processor_end_frame;
1070 vpeproc->base.flush = si_vpe_processor_flush;
1071 vpeproc->base.get_processor_fence = si_vpe_processor_get_processor_fence;
1072
1073 vpeproc->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
1074 vpeproc->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
1075
1076 vpeproc->screen = context->screen;
1077 vpeproc->ws = ws;
1078 vpeproc->process_fence = NULL;
1079
1080 init_data = &vpeproc->vpe_data;
1081 if (VPE_STATUS_OK != si_vpe_populate_init_data(sctx, init_data, vpeproc->log_level)){
1082 SIVPE_ERR("Init VPE populate data failed\n");
1083 goto fail;
1084 }
1085
1086 vpeproc->vpe_handle = vpe_create(init_data);
1087 if (!vpeproc->vpe_handle) {
1088 SIVPE_ERR("Create VPE handle failed\n");
1089 goto fail;
1090 }
1091
1092 if (VPE_STATUS_OK != si_vpe_allocate_buffer(&vpeproc->vpe_build_bufs)) {
1093 SIVPE_ERR("Allocate VPE buffers failed\n");
1094 goto fail;
1095 }
1096
1097 /* Create Command Submission context.
1098 * The cmdbuf (Vpe Descriptor) will be stored in cs.current.buf
1099 * there is no needs to allocate another buffer handle for cmdbuf.
1100 */
1101 if (!ws->cs_create(&vpeproc->cs, sctx->ctx, AMD_IP_VPE, NULL, NULL)) {
1102 SIVPE_ERR("Get command submission context failed.\n");
1103 goto fail;
1104 }
1105
1106 /* Allocate Vpblit Descriptor buffers
1107 * Descriptor buffer is used to store plane config and VPEP commands
1108 */
1109 vpeproc->bufs_num = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_BUF_NUM", VPE_BUFFERS_NUM);
1110 vpeproc->cur_buf = 0;
1111 vpeproc->emb_buffers = (struct rvid_buffer *)CALLOC(vpeproc->bufs_num, sizeof(struct rvid_buffer));
1112 if (!vpeproc->emb_buffers) {
1113 SIVPE_ERR("Allocate command buffer list failed\n");
1114 goto fail;
1115 } else
1116 SIVPE_INFO(vpeproc->log_level, "Number of emb_buf is %d\n", vpeproc->bufs_num);
1117
1118 vpeproc->mapped_cpu_va = (void **)CALLOC(vpeproc->bufs_num, sizeof(void *));
1119 if (!vpeproc->mapped_cpu_va) {
1120 SIVPE_ERR("Can't allocated mapped_cpu_va for emb_buf buffers.\n");
1121 goto fail;
1122 }
1123
1124 for (i = 0; i < vpeproc->bufs_num; i++) {
1125 if (!si_vid_create_buffer(vpeproc->screen, &vpeproc->emb_buffers[i], VPE_EMBBUF_SIZE, PIPE_USAGE_DEFAULT)) {
1126 SIVPE_ERR("Can't allocated emb_buf buffers.\n");
1127 goto fail;
1128 }
1129 si_vid_clear_buffer(context, &vpeproc->emb_buffers[i]);
1130
1131 vpeproc->mapped_cpu_va[i] = vpeproc->ws->buffer_map(vpeproc->ws, vpeproc->emb_buffers[i].res->buf,
1132 &vpeproc->cs, PIPE_MAP_WRITE);
1133 if (!vpeproc->mapped_cpu_va[i])
1134 goto fail;
1135 }
1136
1137 /* Create VPE parameters structure */
1138 vpeproc->vpe_build_param = CALLOC_STRUCT(vpe_build_param);
1139 if (!vpeproc->vpe_build_param) {
1140 SIVPE_ERR("Allocate build-paramaters sturcture failed\n");
1141 goto fail;
1142 }
1143
1144 /* Pre-allocate the streams */
1145 vpeproc->vpe_build_param->streams = (struct vpe_stream *)CALLOC(VPE_STREAM_MAX_NUM, sizeof(struct vpe_stream));
1146 if (!vpeproc->vpe_build_param->streams) {
1147 SIVPE_ERR("Allocate streams sturcture failed\n");
1148 goto fail;
1149 }
1150
1151 return &vpeproc->base;
1152
1153 fail:
1154 SIVPE_ERR("Failed\n");
1155 if (vpeproc) {
1156 si_vpe_processor_destroy(&vpeproc->base);
1157 }
1158 return NULL;
1159 }
1160