xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/radeonsi/si_vpe.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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_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