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