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_YCbCr;
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
434 si_res = si_resource(surfaces[0]->texture);
435 plane_address->tmz_surface = false;
436
437 /* here is the SURFACE size, not image rect */
438 plane_size->surface_size.x = 0;
439 plane_size->surface_size.y = 0;
440 plane_size->surface_size.width = surfaces[0]->width;
441 plane_size->surface_size.height = surfaces[0]->height;
442 plane_size->surface_pitch = pitch; // Byte alignment
443
444 switch (format) {
445 case PIPE_FORMAT_NV12:
446 case PIPE_FORMAT_NV21:
447 plane_address->type = VPE_PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
448 plane_address->video_progressive.luma_addr.quad_part = si_res->gpu_address + offset;
449 plane_address->video_progressive.luma_meta_addr.quad_part = 0;
450 plane_address->video_progressive.luma_dcc_const_color.quad_part = 0;
451 //plane_size->surface_pitch /= 1; // Byte alignment to Pixel alignment
452 /* Get 2nd plane buffer info */
453 if (surfaces[1] && vpeproc->base.context->screen && vpeproc->base.context->screen->resource_get_info)
454 vpeproc->base.context->screen->resource_get_info(vpeproc->base.context->screen,
455 surfaces[1]->texture,
456 &pitch,
457 &offset);
458 else {
459 SIVPE_ERR("Get 2nd plane pitch and offset info failed\n");
460 return VPE_STATUS_ERROR;
461 }
462 si_res = si_resource(surfaces[1]->texture);
463 plane_address->video_progressive.chroma_addr.quad_part = si_res->gpu_address + offset;
464 plane_address->video_progressive.chroma_meta_addr.quad_part = 0;
465 plane_address->video_progressive.chroma_dcc_const_color.quad_part = 0;
466
467 plane_size->chroma_size.x = pos_x;
468 plane_size->chroma_size.y = pos_y;
469 plane_size->chroma_size.width = (width + 1) / 2; // 2 pixel-width alignment
470 plane_size->chroma_size.height = (height + 1) / 2; // 2 pixel-height alignment
471 plane_size->chroma_pitch = pitch / 2; // Byte alignment to Pixel alignment (NV12/NV21 2nd plane is 16 bits per pixel)
472 break;
473 case PIPE_FORMAT_A8R8G8B8_UNORM:
474 case PIPE_FORMAT_A8B8G8R8_UNORM:
475 case PIPE_FORMAT_R8G8B8A8_UNORM:
476 case PIPE_FORMAT_B8G8R8A8_UNORM:
477 case PIPE_FORMAT_X8R8G8B8_UNORM:
478 case PIPE_FORMAT_X8B8G8R8_UNORM:
479 case PIPE_FORMAT_R8G8B8X8_UNORM:
480 case PIPE_FORMAT_B8G8R8X8_UNORM:
481 case PIPE_FORMAT_A2R10G10B10_UNORM:
482 case PIPE_FORMAT_R10G10B10A2_UNORM:
483 case PIPE_FORMAT_A2B10G10R10_UNORM:
484 case PIPE_FORMAT_B10G10R10A2_UNORM:
485 default:
486 plane_address->type = VPE_PLN_ADDR_TYPE_GRAPHICS;
487 plane_address->grph.addr.quad_part = si_res->gpu_address + offset;
488 plane_address->grph.meta_addr.quad_part = 0;
489 plane_address->grph.dcc_const_color.quad_part = 0;
490 plane_size->surface_pitch /= 4; // Byte alignment to Pixel alignment (RGBA plane is 32 bits per pixel)
491
492 plane_size->chroma_size.x = 0;
493 plane_size->chroma_size.y = 0;
494 plane_size->chroma_size.width = 0;
495 plane_size->chroma_size.height = 0;
496 plane_size->chroma_pitch = 0;
497 break;
498 }
499 return VPE_STATUS_OK;
500 }
501
502 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)503 si_vpe_set_surface_info(struct vpe_video_processor *vpeproc,
504 const struct pipe_vpp_desc *process_properties,
505 struct pipe_surface **surfaces,
506 int which_surface,
507 struct vpe_surface_info *surface_info)
508 {
509 assert(surface_info);
510
511 /* Set up surface pitch, plane address, color space */
512 si_vpe_set_plane_info(vpeproc, process_properties, surfaces, which_surface, surface_info);
513
514 /* VAAPI does not provide swizzle info right now.
515 * Swizzle mode is strongly releated to hardware DMA design,
516 * intel-vaapi-driver/i965_drv_video.c also does not handle swizzle information,
517 * maybe this is the reason why it is not currently supported.
518 *
519 * Just default to linear or none temporarily.
520 */
521 surface_info->swizzle = VPE_SW_LINEAR;
522
523 struct vpe_plane_dcc_param *dcc_param = &surface_info->dcc;
524 dcc_param->enable = false;
525 dcc_param->meta_pitch = 0;
526 dcc_param->independent_64b_blks = false;
527 dcc_param->dcc_ind_blk = 0;
528 dcc_param->meta_pitch_c = 0;
529 dcc_param->independent_64b_blks_c = false;
530 dcc_param->dcc_ind_blk_c = 0;
531
532 return VPE_STATUS_OK;
533 }
534
535 static enum vpe_status
si_vpe_set_stream(const struct pipe_vpp_desc * process_properties,struct vpe_stream * stream)536 si_vpe_set_stream(const struct pipe_vpp_desc *process_properties,
537 struct vpe_stream *stream)
538 {
539 struct vpe_scaling_info *scaling_info = &stream->scaling_info;
540 scaling_info->src_rect.x = process_properties->src_region.x0;
541 scaling_info->src_rect.y = process_properties->src_region.y0;
542 scaling_info->src_rect.width = process_properties->src_region.x1 - process_properties->src_region.x0;
543 scaling_info->src_rect.height = process_properties->src_region.y1 - process_properties->src_region.y0;
544 scaling_info->dst_rect.x = process_properties->dst_region.x0;
545 scaling_info->dst_rect.y = process_properties->dst_region.y0;
546 scaling_info->dst_rect.width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
547 scaling_info->dst_rect.height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
548 /* Programmable 1 to 8 taps of vertical polyphase filter, and
549 * programmable 1, 2, 4, 6, 8 taps of horizontal polyphase filter.
550 */
551 scaling_info->taps.v_taps = 4;
552 scaling_info->taps.h_taps = 4;
553 scaling_info->taps.v_taps_c = 2;
554 scaling_info->taps.h_taps_c = 2;
555
556 /* Blending is not supported for now */
557 struct vpe_blend_info *blend_info = &stream->blend_info;
558 blend_info->blending = false;
559 blend_info->pre_multiplied_alpha = false;
560 blend_info->global_alpha = false;
561 blend_info->global_alpha_value = 0.0;
562 /* Global Alpha for Background ? */
563 if (process_properties->blend.mode == PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA) {
564 blend_info->global_alpha = true;
565 blend_info->global_alpha_value = process_properties->blend.global_alpha;
566 }
567
568 /* TODO: do ProcAmp in next stage */
569 struct vpe_color_adjust *color_adj = &stream->color_adj;
570 color_adj->brightness = 0.0;
571 color_adj->contrast = 1.0;
572 color_adj->hue = 0.0;
573 color_adj->saturation = 1.0;
574
575 /* TODO: Tone Mapping */
576 //struct vpe_tonemap_params *tm_params = &stream->tm_params;
577
578
579 stream->horizontal_mirror = false;
580 stream->vertical_mirror = false;
581 switch (process_properties->orientation & 0xF) {
582 case PIPE_VIDEO_VPP_ROTATION_90:
583 stream->rotation = VPE_ROTATION_ANGLE_90;
584 break;
585 case PIPE_VIDEO_VPP_ROTATION_180:
586 stream->rotation = VPE_ROTATION_ANGLE_180;
587 break;
588 case PIPE_VIDEO_VPP_ROTATION_270:
589 stream->rotation = VPE_ROTATION_ANGLE_270;
590 break;
591 default:
592 stream->rotation = VPE_ROTATION_ANGLE_0;
593 break;
594 }
595 if (process_properties->orientation & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) {
596 stream->horizontal_mirror = true;
597 }
598 if (process_properties->orientation & PIPE_VIDEO_VPP_FLIP_VERTICAL)
599 stream->vertical_mirror = true;
600
601 stream->enable_luma_key = false;
602 stream->lower_luma_bound = 0.5;
603 stream->upper_luma_bound = 0.5;
604
605 stream->flags.hdr_metadata = 0;
606 stream->flags.reserved = 0;
607
608 /* TODO: hdr_metadata support in next stage */
609 stream->hdr_metadata.redX = 1;
610 stream->hdr_metadata.redY = 1;
611 stream->hdr_metadata.greenX = 1;
612 stream->hdr_metadata.greenY = 1;
613 stream->hdr_metadata.blueX = 1;
614 stream->hdr_metadata.blueY = 1;
615 stream->hdr_metadata.whiteX = 1;
616 stream->hdr_metadata.whiteY = 1;
617
618 stream->hdr_metadata.min_mastering = 1;
619 stream->hdr_metadata.max_mastering = 1;
620 stream->hdr_metadata.max_content = 1;
621 stream->hdr_metadata.avg_content = 1;
622
623 return VPE_STATUS_OK;
624 }
625
626 static void
si_vpe_processor_destroy(struct pipe_video_codec * codec)627 si_vpe_processor_destroy(struct pipe_video_codec *codec)
628 {
629 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
630 unsigned int i;
631 assert(codec);
632
633 if (vpeproc->process_fence) {
634 SIVPE_INFO(vpeproc->log_level, "Wait fence\n");
635 vpeproc->ws->fence_wait(vpeproc->ws, vpeproc->process_fence, PIPE_DEFAULT_DECODER_FEEDBACK_TIMEOUT_NS);
636 }
637 vpeproc->ws->cs_destroy(&vpeproc->cs);
638
639 if (vpeproc->vpe_build_bufs)
640 si_vpe_free_buffer(vpeproc->vpe_build_bufs);
641 if (vpeproc->vpe_handle)
642 vpe_destroy(&vpeproc->vpe_handle);
643 if (vpeproc->vpe_build_param) {
644 if (vpeproc->vpe_build_param->streams)
645 FREE(vpeproc->vpe_build_param->streams);
646 FREE(vpeproc->vpe_build_param);
647 }
648 if (vpeproc->emb_buffers) {
649 for (i = 0; i < vpeproc->bufs_num; i++) {
650 if (vpeproc->emb_buffers[i].res) {
651 vpeproc->ws->buffer_unmap(vpeproc->ws, vpeproc->emb_buffers[i].res->buf);
652 si_vid_destroy_buffer(&vpeproc->emb_buffers[i]);
653 }
654 }
655 FREE(vpeproc->emb_buffers);
656 }
657 if (vpeproc->mapped_cpu_va)
658 FREE(vpeproc->mapped_cpu_va);
659 vpeproc->bufs_num = 0;
660
661 SIVPE_DBG(vpeproc->log_level, "Success\n");
662 FREE(vpeproc);
663 }
664
665 static void
si_vpe_processor_begin_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)666 si_vpe_processor_begin_frame(struct pipe_video_codec *codec,
667 struct pipe_video_buffer *target,
668 struct pipe_picture_desc *picture)
669 {
670 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
671 struct pipe_surface **dst_surfaces;
672 assert(codec);
673
674 dst_surfaces = target->get_surfaces(target);
675 if (!dst_surfaces || !dst_surfaces[0]) {
676 SIVPE_ERR("Get target surface failed\n");
677 return;
678 }
679 vpeproc->dst_surfaces = dst_surfaces;
680 }
681
682 static void
si_vpe_cs_add_surface_buffer(struct vpe_video_processor * vpeproc,struct pipe_surface ** surfaces,unsigned usage)683 si_vpe_cs_add_surface_buffer(struct vpe_video_processor *vpeproc,
684 struct pipe_surface **surfaces,
685 unsigned usage)
686 {
687 struct si_resource *si_res;
688 int i;
689
690 for (i = 0; i < VL_MAX_SURFACES; ++i) {
691 if (!surfaces[i])
692 continue;
693
694 si_res = si_resource(surfaces[i]->texture);
695 vpeproc->ws->cs_add_buffer(&vpeproc->cs, si_res->buf, usage | RADEON_USAGE_SYNCHRONIZED, 0);
696 }
697 }
698
699 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)700 si_vpe_processor_process_frame(struct pipe_video_codec *codec,
701 struct pipe_video_buffer *input_texture,
702 const struct pipe_vpp_desc *process_properties)
703 {
704 enum vpe_status result = VPE_STATUS_OK;
705 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
706 struct vpe *vpe_handle = vpeproc->vpe_handle;
707 struct vpe_build_param *build_param = vpeproc->vpe_build_param;
708 struct pipe_surface **src_surfaces;
709 struct vpe_bufs_req bufs_required;
710 struct rvid_buffer *emb_buf;
711 uint64_t *vpe_ptr;
712
713 assert(codec);
714 assert(process_properties);
715 assert(vpeproc->dst_surfaces);
716
717 src_surfaces = input_texture->get_surfaces(input_texture);
718 if (!src_surfaces || !src_surfaces[0]) {
719 SIVPE_ERR("Get source surface failed\n");
720 return;
721 }
722 vpeproc->src_surfaces = src_surfaces;
723
724 /* Following setting is from si_vpe_set_build_param()*/
725 /* VPE 1.0 only support one input */
726 build_param->num_streams = 1;
727 if (build_param->num_streams > VPE_STREAM_MAX_NUM) {
728 SIVPE_ERR("Can only suppport %d stream(s) now\n", VPE_STREAM_MAX_NUM);
729 return;
730 }
731
732 if (!build_param->streams) {
733 SIVPE_ERR("Streams structure is not allocated\n");
734 return;
735 }
736
737 si_vpe_set_surface_info(vpeproc,
738 process_properties,
739 vpeproc->src_surfaces,
740 USE_SRC_SURFACE,
741 &build_param->streams[0].surface_info);
742
743 si_vpe_set_stream(process_properties, &build_param->streams[0]);
744
745 si_vpe_set_surface_info(vpeproc,
746 process_properties,
747 vpeproc->dst_surfaces,
748 USE_DST_SURFACE,
749 &build_param->dst_surface);
750
751 if (process_properties->background_color) {
752 build_param->target_rect.x = 0;
753 build_param->target_rect.y = 0;
754 build_param->target_rect.width = vpeproc->dst_surfaces[0]->width;
755 build_param->target_rect.height = vpeproc->dst_surfaces[0]->height;
756 } else {
757 build_param->target_rect.x = process_properties->dst_region.x0;
758 build_param->target_rect.y = process_properties->dst_region.y0;
759 build_param->target_rect.width = process_properties->dst_region.x1 - process_properties->dst_region.x0;
760 build_param->target_rect.height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
761 }
762
763 /* TODO: background color is not specified in pipe_vpp_desc structure.
764 * Need to add this filed in pipe_vpp_desc.
765 */
766 build_param->bg_color.is_ycbcr = false;
767
768 if (!(process_properties->background_color & 0xFFFFFF) &&
769 (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_STUDIO)) {
770 build_param->bg_color.rgba.a =
771 (float)((process_properties->background_color & 0xFF000000) >> 24) / 255.0;
772 build_param->bg_color.rgba.r = 0.0628;
773 build_param->bg_color.rgba.g = 0.0628;
774 build_param->bg_color.rgba.b = 0.0628;
775 } else if (process_properties->background_color) {
776 build_param->bg_color.rgba.a =
777 (float)((process_properties->background_color & 0xFF000000) >> 24) / 255.0;
778 build_param->bg_color.rgba.r =
779 (float)((process_properties->background_color & 0x00FF0000) >> 16) / 255.0;
780 build_param->bg_color.rgba.g =
781 (float)((process_properties->background_color & 0x0000FF00) >> 8) / 255.0;
782 build_param->bg_color.rgba.b =
783 (float)(process_properties->background_color & 0x000000FF) / 255.0;
784 } else {
785 build_param->bg_color.rgba.r = 0;
786 build_param->bg_color.rgba.g = 0;
787 build_param->bg_color.rgba.b = 0;
788 build_param->bg_color.rgba.a = 0;
789 }
790
791 build_param->alpha_mode = VPE_ALPHA_OPAQUE;
792
793 build_param->flags.hdr_metadata = 0;
794 build_param->flags.reserved = 1;
795
796 /* TODO: hdr_metadata support in next stage */
797 build_param->hdr_metadata.redX = 1;
798 build_param->hdr_metadata.redY = 1;
799 build_param->hdr_metadata.greenX = 1;
800 build_param->hdr_metadata.greenY = 1;
801 build_param->hdr_metadata.blueX = 1;
802 build_param->hdr_metadata.blueY = 1;
803 build_param->hdr_metadata.whiteX = 1;
804 build_param->hdr_metadata.whiteY = 1;
805
806 build_param->hdr_metadata.min_mastering = 1;
807 build_param->hdr_metadata.max_mastering = 1;
808 build_param->hdr_metadata.max_content = 1;
809 build_param->hdr_metadata.avg_content = 1;
810
811
812 /* Setup CmdBuf and EmbBuf address adn size information */
813 vpe_ptr = (uint64_t *)vpeproc->cs.current.buf;
814 vpeproc->vpe_build_bufs->cmd_buf.cpu_va = (uintptr_t)vpe_ptr;
815 vpeproc->vpe_build_bufs->cmd_buf.gpu_va = 0;
816 vpeproc->vpe_build_bufs->cmd_buf.size = vpeproc->cs.current.max_dw;
817 vpeproc->vpe_build_bufs->cmd_buf.tmz = false;
818
819 emb_buf = &vpeproc->emb_buffers[vpeproc->cur_buf];
820 vpeproc->vpe_build_bufs->emb_buf.cpu_va = (uintptr_t)vpeproc->mapped_cpu_va[vpeproc->cur_buf];
821 vpeproc->vpe_build_bufs->emb_buf.gpu_va = vpeproc->ws->buffer_get_virtual_address(emb_buf->res->buf);
822 vpeproc->vpe_build_bufs->emb_buf.size = VPE_EMBBUF_SIZE;
823 vpeproc->vpe_build_bufs->emb_buf.tmz = false;
824
825
826 if (vpeproc->log_level >= SI_VPE_LOG_LEVEL_DEBUG) {
827 SIVPE_DBG(vpeproc->log_level, "src surface format(%d) rect (%d, %d, %d, %d)\n",
828 build_param->streams[0].surface_info.format,
829 build_param->streams[0].surface_info.plane_size.surface_size.x,
830 build_param->streams[0].surface_info.plane_size.surface_size.y,
831 build_param->streams[0].surface_info.plane_size.surface_size.width,
832 build_param->streams[0].surface_info.plane_size.surface_size.height);
833
834 SIVPE_DBG(vpeproc->log_level, "src surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
835 si_vpe_get_cositing_str(build_param->streams[0].surface_info.cs.cositing),
836 si_vpe_get_primarie_str(build_param->streams[0].surface_info.cs.primaries),
837 si_vpe_get_tf_str(build_param->streams[0].surface_info.cs.tf),
838 (build_param->streams[0].surface_info.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
839
840 SIVPE_DBG(vpeproc->log_level, "dst surface format(%d) rect (%d, %d, %d, %d)\n",
841 build_param->dst_surface.format,
842 build_param->dst_surface.plane_size.surface_size.x,
843 build_param->dst_surface.plane_size.surface_size.y,
844 build_param->dst_surface.plane_size.surface_size.width,
845 build_param->dst_surface.plane_size.surface_size.height);
846
847 SIVPE_DBG(vpeproc->log_level, "dst surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
848 si_vpe_get_cositing_str(build_param->dst_surface.cs.cositing),
849 si_vpe_get_primarie_str(build_param->dst_surface.cs.primaries),
850 si_vpe_get_tf_str(build_param->dst_surface.cs.tf),
851 (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
852
853 SIVPE_DBG(vpeproc->log_level, "background color RGBA(%0.3f, %0.3f, %0.3f, %0.3f)\n",
854 build_param->bg_color.rgba.r,
855 build_param->bg_color.rgba.g,
856 build_param->bg_color.rgba.b,
857 build_param->bg_color.rgba.a);
858
859 SIVPE_DBG(vpeproc->log_level, "target_rect(%d, %d, %d, %d)\n",
860 build_param->target_rect.x,
861 build_param->target_rect.y,
862 build_param->target_rect.width,
863 build_param->target_rect.height);
864
865 SIVPE_DBG(vpeproc->log_level, "rotation(%d) horizontal_mirror(%d) vertical_mirror(%d)\n",
866 build_param->streams[0].rotation,
867 build_param->streams[0].horizontal_mirror,
868 build_param->streams[0].vertical_mirror);
869
870 SIVPE_DBG(vpeproc->log_level, "scaling_src_rect(%d, %d, %d, %d)\n",
871 build_param->streams[0].scaling_info.src_rect.x,
872 build_param->streams[0].scaling_info.src_rect.y,
873 build_param->streams[0].scaling_info.src_rect.width,
874 build_param->streams[0].scaling_info.src_rect.height);
875
876 SIVPE_DBG(vpeproc->log_level, "scaling_dst_rect(%d, %d, %d, %d)\n",
877 build_param->streams[0].scaling_info.dst_rect.x,
878 build_param->streams[0].scaling_info.dst_rect.y,
879 build_param->streams[0].scaling_info.dst_rect.width,
880 build_param->streams[0].scaling_info.dst_rect.height);
881
882 SIVPE_DBG(vpeproc->log_level, "scaling_taps h_taps(%d) v_taps(%d) h_taps_c(%d) v_taps_c(%d)\n",
883 build_param->streams[0].scaling_info.taps.h_taps,
884 build_param->streams[0].scaling_info.taps.v_taps,
885 build_param->streams[0].scaling_info.taps.h_taps_c,
886 build_param->streams[0].scaling_info.taps.v_taps_c);
887
888 SIVPE_DBG(vpeproc->log_level, "blend global_alpha(%d): %0.3f\n",
889 build_param->streams[0].blend_info.global_alpha,
890 build_param->streams[0].blend_info.global_alpha_value);
891
892 SIVPE_DBG(vpeproc->log_level, "ToneMapping shaper_tf(%d) lut_out_tf(%d) lut_in_gamut(%d) lut_out_gamut(%d)\n",
893 build_param->streams[0].tm_params.shaper_tf,
894 build_param->streams[0].tm_params.lut_out_tf,
895 build_param->streams[0].tm_params.lut_in_gamut,
896 build_param->streams[0].tm_params.lut_out_gamut);
897
898 //SIVPE_DBG(vpeproc->log_level, "ToneMapping update_3dlut(%d) enable_3dlut(%d)\n",
899 // build_param->streams[0].tm_params.update_3dlut,
900 // build_param->streams[0].tm_params.enable_3dlut);
901 }
902
903 result = vpe_check_support(vpe_handle, build_param, &bufs_required);
904 if (VPE_STATUS_OK != result) {
905 SIVPE_ERR("Check support failed with result: %d\n", result);
906 goto fail;
907 }
908
909 result = vpe_build_commands(vpe_handle, build_param, vpeproc->vpe_build_bufs);
910 if (VPE_STATUS_OK != result) {
911 SIVPE_ERR("Build commands failed with result: %d\n", result);
912 goto fail;
913 }
914
915 /* Check buffer size */
916 if (vpeproc->vpe_build_bufs->cmd_buf.size == 0 || vpeproc->vpe_build_bufs->cmd_buf.size == vpeproc->cs.current.max_dw) {
917 SIVPE_ERR("Cmdbuf size wrong\n");
918 goto fail;
919 }
920 if (vpeproc->vpe_build_bufs->emb_buf.size == 0 || vpeproc->vpe_build_bufs->emb_buf.size == VPE_EMBBUF_SIZE) {
921 SIVPE_ERR("Embbuf size wrong\n");
922 goto fail;
923 }
924 SIVPE_INFO(vpeproc->log_level, "Used buf size: %" PRIu64 ", %" PRIu64 "\n",
925 vpeproc->vpe_build_bufs->cmd_buf.size, vpeproc->vpe_build_bufs->emb_buf.size);
926
927 /* Have to tell Command Submission context the command length wrote by libvpe */
928 vpeproc->cs.current.cdw += (vpeproc->vpe_build_bufs->cmd_buf.size / 4);
929
930 /* Add embbuf into bo_handle list */
931 vpeproc->ws->cs_add_buffer(&vpeproc->cs, emb_buf->res->buf, RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_GTT);
932
933 si_vpe_cs_add_surface_buffer(vpeproc, vpeproc->src_surfaces, RADEON_USAGE_READ);
934 si_vpe_cs_add_surface_buffer(vpeproc, vpeproc->dst_surfaces, RADEON_USAGE_WRITE);
935
936 SIVPE_DBG(vpeproc->log_level, "Success\n");
937 return;
938
939 fail:
940 vpeproc->ws->buffer_unmap(vpeproc->ws, emb_buf->res->buf);
941 SIVPE_ERR("Failed\n");
942 return;
943 }
944
945 static void
si_vpe_processor_end_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)946 si_vpe_processor_end_frame(struct pipe_video_codec *codec,
947 struct pipe_video_buffer *target,
948 struct pipe_picture_desc *picture)
949 {
950 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
951 struct pipe_fence_handle *process_fence = NULL;
952 assert(codec);
953
954 vpeproc->ws->cs_flush(&vpeproc->cs, PIPE_FLUSH_ASYNC, &process_fence);
955 next_buffer(vpeproc);
956
957 if (picture->fence && process_fence) {
958 *picture->fence = process_fence;
959 SIVPE_INFO(vpeproc->log_level, "Assign process fence\n");
960 } else
961 SIVPE_WARN(vpeproc->log_level, "Fence may have problem!\n");
962
963 SIVPE_INFO(vpeproc->log_level, "Success\n");
964 }
965
966 static void
si_vpe_processor_flush(struct pipe_video_codec * codec)967 si_vpe_processor_flush(struct pipe_video_codec *codec)
968 {
969 //struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
970 //assert(codec);
971
972 //SIVPE_DBG(vpeproc->log_level, "Success\n");
973 return;
974 }
975
si_vpe_processor_get_processor_fence(struct pipe_video_codec * codec,struct pipe_fence_handle * fence,uint64_t timeout)976 static int si_vpe_processor_get_processor_fence(struct pipe_video_codec *codec,
977 struct pipe_fence_handle *fence,
978 uint64_t timeout)
979 {
980 struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
981 assert(codec);
982
983 SIVPE_INFO(vpeproc->log_level, "Wait processor fence\n");
984 if (!vpeproc->ws->fence_wait(vpeproc->ws, fence, timeout)) {
985 SIVPE_DBG(vpeproc->log_level, "Wait processor fence fail\n");
986 return 0;
987 }
988 SIVPE_INFO(vpeproc->log_level, "Wait processor fence success\n");
989 return 1;
990 }
991
992 struct pipe_video_codec*
si_vpe_create_processor(struct pipe_context * context,const struct pipe_video_codec * templ)993 si_vpe_create_processor(struct pipe_context *context, const struct pipe_video_codec *templ)
994 {
995 struct si_context *sctx = (struct si_context *)context;
996 struct radeon_winsys *ws = sctx->ws;
997 struct vpe_video_processor *vpeproc;
998 struct vpe_init_data *init_data;
999 const char *str = getenv("AMDGPU_SIVPE_LOG_LEVEL");
1000 unsigned int i;
1001
1002 vpeproc = CALLOC_STRUCT(vpe_video_processor);
1003 if (!vpeproc) {
1004 SIVPE_ERR("Allocate struct failed\n");
1005 return NULL;
1006 }
1007
1008 /* get SI_VPE debug log level */
1009 if (str == NULL)
1010 vpeproc->log_level = SI_VPE_LOG_LEVEL_DEFAULT;
1011 else
1012 vpeproc->log_level = atoi(str);
1013
1014 vpeproc->base = *templ;
1015 vpeproc->base.context = context;
1016 vpeproc->base.width = templ->width;
1017 vpeproc->base.height = templ->height;
1018
1019 vpeproc->base.destroy = si_vpe_processor_destroy;
1020 vpeproc->base.begin_frame = si_vpe_processor_begin_frame;
1021 vpeproc->base.process_frame = si_vpe_processor_process_frame;
1022 vpeproc->base.end_frame = si_vpe_processor_end_frame;
1023 vpeproc->base.flush = si_vpe_processor_flush;
1024 vpeproc->base.get_processor_fence = si_vpe_processor_get_processor_fence;
1025
1026 vpeproc->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
1027 vpeproc->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
1028
1029 vpeproc->screen = context->screen;
1030 vpeproc->ws = ws;
1031 vpeproc->process_fence = NULL;
1032
1033 init_data = &vpeproc->vpe_data;
1034 if (VPE_STATUS_OK != si_vpe_populate_init_data(sctx, init_data, vpeproc->log_level)){
1035 SIVPE_ERR("Init VPE populate data failed\n");
1036 goto fail;
1037 }
1038
1039 vpeproc->vpe_handle = vpe_create(init_data);
1040 if (!vpeproc->vpe_handle) {
1041 SIVPE_ERR("Create VPE handle failed\n");
1042 goto fail;
1043 }
1044
1045 if (VPE_STATUS_OK != si_vpe_allocate_buffer(&vpeproc->vpe_build_bufs)) {
1046 SIVPE_ERR("Allocate VPE buffers failed\n");
1047 goto fail;
1048 }
1049
1050 /* Create Command Submission context.
1051 * The cmdbuf (Vpe Descriptor) will be stored in cs.current.buf
1052 * there is no needs to allocate another buffer handle for cmdbuf.
1053 */
1054 if (!ws->cs_create(&vpeproc->cs, sctx->ctx, AMD_IP_VPE, NULL, NULL)) {
1055 SIVPE_ERR("Get command submission context failed.\n");
1056 goto fail;
1057 }
1058
1059 /* Allocate Vpblit Descriptor buffers
1060 * Descriptor buffer is used to store plane config and VPEP commands
1061 */
1062 vpeproc->bufs_num = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_BUF_NUM", VPE_BUFFERS_NUM);
1063 vpeproc->cur_buf = 0;
1064 vpeproc->emb_buffers = (struct rvid_buffer *)CALLOC(vpeproc->bufs_num, sizeof(struct rvid_buffer));
1065 if (!vpeproc->emb_buffers) {
1066 SIVPE_ERR("Allocate command buffer list failed\n");
1067 goto fail;
1068 } else
1069 SIVPE_INFO(vpeproc->log_level, "Number of emb_buf is %d\n", vpeproc->bufs_num);
1070
1071 vpeproc->mapped_cpu_va = (void **)CALLOC(vpeproc->bufs_num, sizeof(void *));
1072 if (!vpeproc->mapped_cpu_va) {
1073 SIVPE_ERR("Can't allocated mapped_cpu_va for emb_buf buffers.\n");
1074 goto fail;
1075 }
1076
1077 for (i = 0; i < vpeproc->bufs_num; i++) {
1078 if (!si_vid_create_buffer(vpeproc->screen, &vpeproc->emb_buffers[i], VPE_EMBBUF_SIZE, PIPE_USAGE_DEFAULT)) {
1079 SIVPE_ERR("Can't allocated emb_buf buffers.\n");
1080 goto fail;
1081 }
1082 si_vid_clear_buffer(context, &vpeproc->emb_buffers[i]);
1083
1084 vpeproc->mapped_cpu_va[i] = vpeproc->ws->buffer_map(vpeproc->ws, vpeproc->emb_buffers[i].res->buf,
1085 &vpeproc->cs, PIPE_MAP_WRITE);
1086 if (!vpeproc->mapped_cpu_va[i])
1087 goto fail;
1088 }
1089
1090 /* Create VPE parameters structure */
1091 vpeproc->vpe_build_param = CALLOC_STRUCT(vpe_build_param);
1092 if (!vpeproc->vpe_build_param) {
1093 SIVPE_ERR("Allocate build-paramaters sturcture failed\n");
1094 goto fail;
1095 }
1096
1097 /* Pre-allocate the streams */
1098 vpeproc->vpe_build_param->streams = (struct vpe_stream *)CALLOC(VPE_STREAM_MAX_NUM, sizeof(struct vpe_stream));
1099 if (!vpeproc->vpe_build_param->streams) {
1100 SIVPE_ERR("Allocate streams sturcture failed\n");
1101 goto fail;
1102 }
1103
1104 return &vpeproc->base;
1105
1106 fail:
1107 SIVPE_ERR("Failed\n");
1108 if (vpeproc) {
1109 si_vpe_processor_destroy(&vpeproc->base);
1110 }
1111 return NULL;
1112 }
1113