• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params->debug);
196    si_vpe_populate_callback_modules(&params->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