• 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    if (vpeproc->geometric_scaling_ratios)
716       FREE(vpeproc->geometric_scaling_ratios);
717 
718    if (vpeproc->geometric_buf[0])
719       vpeproc->geometric_buf[0]->destroy(vpeproc->geometric_buf[0]);
720 
721    if (vpeproc->geometric_buf[1])
722       vpeproc->geometric_buf[1]->destroy(vpeproc->geometric_buf[1]);
723 
724    vpeproc->bufs_num = 0;
725    vpeproc->ws->cs_destroy(&vpeproc->cs);
726    SIVPE_DBG(vpeproc->log_level, "Success\n");
727    FREE(vpeproc);
728 }
729 
730 static void
si_vpe_processor_begin_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)731 si_vpe_processor_begin_frame(struct pipe_video_codec *codec,
732                              struct pipe_video_buffer *target,
733                              struct pipe_picture_desc *picture)
734 {
735    struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
736    struct pipe_surface **dst_surfaces;
737    assert(codec);
738 
739    dst_surfaces = target->get_surfaces(target);
740    if (!dst_surfaces || !dst_surfaces[0]) {
741       SIVPE_ERR("Get target surface failed\n");
742       return;
743    }
744    vpeproc->dst_surfaces = dst_surfaces;
745 }
746 
747 static void
si_vpe_cs_add_surface_buffer(struct vpe_video_processor * vpeproc,struct pipe_surface ** surfaces,unsigned usage)748 si_vpe_cs_add_surface_buffer(struct vpe_video_processor *vpeproc,
749                              struct pipe_surface **surfaces,
750                              unsigned usage)
751 {
752    struct si_resource *si_res;
753    int i;
754 
755    for (i = 0; i < VL_MAX_SURFACES; ++i) {
756       if (!surfaces[i])
757          continue;
758 
759       si_res = si_resource(surfaces[i]->texture);
760       vpeproc->ws->cs_add_buffer(&vpeproc->cs, si_res->buf, usage | RADEON_USAGE_SYNCHRONIZED, 0);
761    }
762 }
763 
764 static void
si_vpe_show_process_settings(struct vpe_video_processor * vpeproc,struct vpe_build_param * build_param)765 si_vpe_show_process_settings(struct vpe_video_processor *vpeproc,
766                              struct vpe_build_param *build_param)
767 {
768    if (vpeproc->log_level >= SI_VPE_LOG_LEVEL_DEBUG) {
769       SIVPE_PRINT("src surface format(%d) rect (%d, %d, %d, %d)\n",
770                build_param->streams[0].surface_info.format,
771                build_param->streams[0].surface_info.plane_size.surface_size.x,
772                build_param->streams[0].surface_info.plane_size.surface_size.y,
773                build_param->streams[0].surface_info.plane_size.surface_size.width,
774                build_param->streams[0].surface_info.plane_size.surface_size.height);
775 
776       SIVPE_PRINT("src surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
777                si_vpe_get_cositing_str(build_param->streams[0].surface_info.cs.cositing),
778                si_vpe_get_primarie_str(build_param->streams[0].surface_info.cs.primaries),
779                si_vpe_get_tf_str(build_param->streams[0].surface_info.cs.tf),
780                (build_param->streams[0].surface_info.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
781 
782       SIVPE_PRINT("dst surface format(%d) rect (%d, %d, %d, %d)\n",
783                build_param->dst_surface.format,
784                build_param->dst_surface.plane_size.surface_size.x,
785                build_param->dst_surface.plane_size.surface_size.y,
786                build_param->dst_surface.plane_size.surface_size.width,
787                build_param->dst_surface.plane_size.surface_size.height);
788 
789       SIVPE_PRINT("dst surface Cositing(%s), primaries(%s), tf(%s), range(%s)\n",
790                si_vpe_get_cositing_str(build_param->dst_surface.cs.cositing),
791                si_vpe_get_primarie_str(build_param->dst_surface.cs.primaries),
792                si_vpe_get_tf_str(build_param->dst_surface.cs.tf),
793                (build_param->dst_surface.cs.range == VPE_COLOR_RANGE_FULL)?"FULL":"STUDIO");
794 
795       SIVPE_PRINT("Source surface pitch(%d), chroma pitch(%d), dst-surface pitch(%d), chroma pitch(%d)\n",
796                build_param->streams[0].surface_info.plane_size.surface_pitch,
797                build_param->streams[0].surface_info.plane_size.chroma_pitch,
798                build_param->dst_surface.plane_size.surface_pitch,
799                build_param->dst_surface.plane_size.chroma_pitch);
800 
801       SIVPE_PRINT("background color RGBA(%0.3f, %0.3f, %0.3f, %0.3f)\n",
802                build_param->bg_color.rgba.r,
803                build_param->bg_color.rgba.g,
804                build_param->bg_color.rgba.b,
805                build_param->bg_color.rgba.a);
806 
807       SIVPE_PRINT("target_rect(%d, %d, %d, %d)\n",
808                build_param->target_rect.x,
809                build_param->target_rect.y,
810                build_param->target_rect.width,
811                build_param->target_rect.height);
812 
813       SIVPE_PRINT("rotation(%d) horizontal_mirror(%d) vertical_mirror(%d)\n",
814                build_param->streams[0].rotation,
815                build_param->streams[0].horizontal_mirror,
816                build_param->streams[0].vertical_mirror);
817 
818       SIVPE_PRINT("scaling_src_rect(%d, %d, %d, %d)\n",
819                build_param->streams[0].scaling_info.src_rect.x,
820                build_param->streams[0].scaling_info.src_rect.y,
821                build_param->streams[0].scaling_info.src_rect.width,
822                build_param->streams[0].scaling_info.src_rect.height);
823 
824       SIVPE_PRINT("scaling_dst_rect(%d, %d, %d, %d)\n",
825                build_param->streams[0].scaling_info.dst_rect.x,
826                build_param->streams[0].scaling_info.dst_rect.y,
827                build_param->streams[0].scaling_info.dst_rect.width,
828                build_param->streams[0].scaling_info.dst_rect.height);
829 
830       SIVPE_PRINT("scaling_taps h_taps(%d) v_taps(%d) h_taps_c(%d) v_taps_c(%d)\n",
831                build_param->streams[0].scaling_info.taps.h_taps,
832                build_param->streams[0].scaling_info.taps.v_taps,
833                build_param->streams[0].scaling_info.taps.h_taps_c,
834                build_param->streams[0].scaling_info.taps.v_taps_c);
835 
836       SIVPE_PRINT("blend global_alpha(%d): %0.3f\n",
837                build_param->streams[0].blend_info.global_alpha,
838                build_param->streams[0].blend_info.global_alpha_value);
839 
840       SIVPE_PRINT("ToneMapping shaper_tf(%d) lut_out_tf(%d) lut_in_gamut(%d) lut_out_gamut(%d)\n",
841                build_param->streams[0].tm_params.shaper_tf,
842                build_param->streams[0].tm_params.lut_out_tf,
843                build_param->streams[0].tm_params.lut_in_gamut,
844                build_param->streams[0].tm_params.lut_out_gamut);
845    }
846 }
847 
848 static enum vpe_status
si_vpe_processor_check_and_build_settins(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct pipe_surface ** src_surfaces,struct pipe_surface ** dst_surfaces)849 si_vpe_processor_check_and_build_settins(struct vpe_video_processor *vpeproc,
850                                          const struct pipe_vpp_desc *process_properties,
851                                          struct pipe_surface **src_surfaces,
852                                          struct pipe_surface **dst_surfaces)
853 {
854    enum vpe_status result = VPE_STATUS_OK;
855    struct vpe *vpe_handle = vpeproc->vpe_handle;
856    struct vpe_build_param *build_param = vpeproc->vpe_build_param;
857    struct vpe_bufs_req bufs_required;
858 
859    /* Mesa only sends one input frame at one time (one stream pipe).
860     * If there is more than one pipe need to be handled, it have to re-locate memory.
861     * But now we only focuse on handling one stream pipe.
862     */
863    build_param->num_streams = 1;
864    memset(build_param->streams, 0, sizeof(struct vpe_stream) * build_param->num_streams);
865 
866    /* Init input surface setting */
867    result = si_vpe_set_surface_info(vpeproc,
868                                     process_properties,
869                                     src_surfaces,
870                                     USE_SRC_SURFACE,
871                                     &build_param->streams[0].surface_info);
872    if (VPE_STATUS_OK != result) {
873       SIVPE_ERR("Set Src surface failed with result: %d\n", result);
874       return result;
875    }
876 
877    /* Init input stream setting */
878    si_vpe_set_stream_in_param(
879                vpeproc,
880                process_properties,
881                &build_param->streams[0]);
882 
883    /* Init output surface setting */
884    result = si_vpe_set_surface_info(vpeproc,
885                                     process_properties,
886                                     dst_surfaces,
887                                     USE_DST_SURFACE,
888                                     &build_param->dst_surface);
889    if (VPE_STATUS_OK != result) {
890       SIVPE_ERR("Set Dst surface failed with result: %d\n", result);
891       return result;
892    }
893 
894    /* Init output stream setting */
895    si_vpe_set_stream_out_param(
896                vpeproc,
897                process_properties,
898                build_param);
899 
900    /* Shows details of current processing. */
901    si_vpe_show_process_settings(vpeproc, build_param);
902 
903    if(vpe_handle->level == VPE_IP_LEVEL_1_1) {
904       build_param->num_instances = 2;
905       build_param->collaboration_mode = true;
906    } else {
907       build_param->num_instances = 1;
908       build_param->collaboration_mode = false;
909    }
910 
911    result = vpe_check_support(vpe_handle, build_param, &bufs_required);
912    if (VPE_STATUS_OK != result) {
913       SIVPE_WARN(vpeproc->log_level, "Check support failed with result: %d\n", result);
914       return result;
915    }
916 
917    if (VPE_EMBBUF_SIZE < bufs_required.emb_buf_size) {
918       SIVPE_ERR("Required Buffer size is out of allocated: %" PRIu64 "\n", bufs_required.emb_buf_size);
919       return VPE_STATUS_NO_MEMORY;
920    }
921 
922    return result;
923 }
924 
925 static enum vpe_status
si_vpe_construct_blt(struct vpe_video_processor * vpeproc,const struct pipe_vpp_desc * process_properties,struct pipe_surface ** src_surfaces,struct pipe_surface ** dst_surfaces)926 si_vpe_construct_blt(struct vpe_video_processor *vpeproc,
927                      const struct pipe_vpp_desc *process_properties,
928                      struct pipe_surface **src_surfaces,
929                      struct pipe_surface **dst_surfaces)
930 {
931    enum vpe_status result = VPE_STATUS_OK;
932    struct vpe *vpe_handle = vpeproc->vpe_handle;
933    struct vpe_build_param *build_param = vpeproc->vpe_build_param;
934    struct vpe_build_bufs *build_bufs = vpeproc->vpe_build_bufs;
935    struct rvid_buffer *emb_buf;
936    uint64_t *vpe_ptr;
937 
938    assert(process_properties);
939    assert(src_surfaces);
940    assert(dst_surfaces);
941 
942    /* Check if the blt operation is supported and build related settings.
943     * Command settings will be is stored in vpeproc->vpe_build_param.
944     */
945    result = si_vpe_processor_check_and_build_settins(vpeproc, process_properties, src_surfaces, dst_surfaces);
946    if (VPE_STATUS_OK != result) {
947       SIVPE_ERR("Failed in checking process operation and build settings(%d)\n", result);
948       return result;
949    }
950 
951    /* Prepare cmd_bud and emb_buf for building commands from settings */
952    /* Init CmdBuf address and size information */
953    vpe_ptr = (uint64_t *)vpeproc->cs.current.buf;
954    build_bufs->cmd_buf.cpu_va = (uintptr_t)vpe_ptr;
955    build_bufs->cmd_buf.gpu_va = 0;
956    build_bufs->cmd_buf.size = vpeproc->cs.current.max_dw;
957    build_bufs->cmd_buf.tmz = false;
958 
959    /* Init EmbBuf address and size information */
960    emb_buf = &vpeproc->emb_buffers[vpeproc->cur_buf];
961    /* Map EmbBuf for CPU access */
962    vpe_ptr = (uint64_t *)vpeproc->ws->buffer_map(vpeproc->ws,
963                                                  emb_buf->res->buf,
964                                                  &vpeproc->cs,
965                                                  PIPE_MAP_WRITE | RADEON_MAP_TEMPORARY);
966    if (!vpe_ptr) {
967       SIVPE_ERR("Mapping Embbuf failed\n");
968       return 1;
969    }
970    build_bufs->emb_buf.cpu_va = (uintptr_t)vpe_ptr;
971    build_bufs->emb_buf.gpu_va = vpeproc->ws->buffer_get_virtual_address(emb_buf->res->buf);
972    build_bufs->emb_buf.size = VPE_EMBBUF_SIZE;
973    build_bufs->emb_buf.tmz = false;
974 
975    result = vpe_build_commands(vpe_handle, build_param, build_bufs);
976 
977    /* Un-map Emb_buf */
978    vpeproc->ws->buffer_unmap(vpeproc->ws, emb_buf->res->buf);
979 
980    if (VPE_STATUS_OK != result) {
981       SIVPE_ERR("Build commands failed with result: %d\n", result);
982       return VPE_STATUS_NO_MEMORY;
983    }
984 
985 
986    /* Check buffer size */
987    if (vpeproc->vpe_build_bufs->cmd_buf.size == 0 || vpeproc->vpe_build_bufs->cmd_buf.size == vpeproc->cs.current.max_dw) {
988       SIVPE_ERR("Cmdbuf size wrong\n");
989       return VPE_STATUS_NO_MEMORY;
990    }
991    if (vpeproc->vpe_build_bufs->emb_buf.size == 0 || vpeproc->vpe_build_bufs->emb_buf.size == VPE_EMBBUF_SIZE) {
992       SIVPE_ERR("Embbuf size wrong\n");
993       return VPE_STATUS_NO_MEMORY;
994    }
995    SIVPE_DBG(vpeproc->log_level, "Used buf size: %" PRIu64 ", %" PRIu64 "\n",
996               vpeproc->vpe_build_bufs->cmd_buf.size, vpeproc->vpe_build_bufs->emb_buf.size);
997 
998    /* Have to tell Command Submission context the command length */
999    vpeproc->cs.current.cdw += (vpeproc->vpe_build_bufs->cmd_buf.size / 4);
1000 
1001    /* Add embbuf into bo_handle list */
1002    vpeproc->ws->cs_add_buffer(&vpeproc->cs, emb_buf->res->buf, RADEON_USAGE_READ | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_GTT);
1003 
1004    /* Add surface buffers into bo_handle list */
1005    si_vpe_cs_add_surface_buffer(vpeproc, src_surfaces, RADEON_USAGE_READ);
1006    si_vpe_cs_add_surface_buffer(vpeproc, dst_surfaces, RADEON_USAGE_WRITE);
1007 
1008    return VPE_STATUS_OK;
1009 }
1010 
1011 static void
si_vpe_find_substage_scal_ratios(float * p_scale_ratios,float scaling_ratio,float max_scale,uint32_t num_stages)1012 si_vpe_find_substage_scal_ratios(float *p_scale_ratios,
1013                                  float scaling_ratio,
1014                                  float max_scale,
1015                                  uint32_t num_stages)
1016 {
1017    uint32_t i;
1018 
1019    for (i = 0; i < num_stages; i++) {
1020       if (i == num_stages - 1)
1021          p_scale_ratios[i] = scaling_ratio/(float)(pow(max_scale, num_stages - 1));
1022       else
1023          p_scale_ratios[i] = max_scale;
1024    }
1025 }
1026 
1027 static enum vpe_status
si_vpe_decide_substage_scal_ratios(struct vpe_video_processor * vpeproc,float * p_target_ratios)1028 si_vpe_decide_substage_scal_ratios(struct vpe_video_processor *vpeproc,
1029                                    float *p_target_ratios)
1030 {
1031    uint8_t no_horizontal_passes, no_vertical_passes, no_of_passes;
1032    float *pHrSr, *pVtSr;
1033    uint32_t idx;
1034 
1035    /* The scaling ratios are the same as pre-processing */
1036    if (vpeproc->geometric_scaling_ratios &&
1037        vpeproc->scaling_ratios[0] == p_target_ratios[0] &&
1038        vpeproc->scaling_ratios[1] == p_target_ratios[1])
1039       return VPE_STATUS_OK;
1040 
1041    if (vpeproc->geometric_scaling_ratios) {
1042       FREE(vpeproc->geometric_scaling_ratios);
1043       vpeproc->geometric_scaling_ratios = NULL;
1044    }
1045 
1046    /* How many passes we need */
1047    no_horizontal_passes = (p_target_ratios[0] > VPE_MAX_GEOMETRIC_DOWNSCALE) ?
1048          (uint8_t)(ceil(log(p_target_ratios[0]) / log(VPE_MAX_GEOMETRIC_DOWNSCALE))) : 1;
1049    no_vertical_passes   = (p_target_ratios[1] > VPE_MAX_GEOMETRIC_DOWNSCALE) ?
1050          (uint8_t)(ceil(log(p_target_ratios[1]) / log(VPE_MAX_GEOMETRIC_DOWNSCALE))) : 1;
1051    no_of_passes = MAX2(no_horizontal_passes, no_vertical_passes);
1052 
1053    /* Allocate ratio array depends on no_of_passes */
1054    pHrSr = (float *)CALLOC(2 * no_of_passes, sizeof(float));
1055    if (NULL == pHrSr) {
1056       SIVPE_ERR("no_of_passes times float of array memory allocation failed\n");
1057       return VPE_STATUS_NO_MEMORY;
1058    }
1059    pVtSr = pHrSr + no_of_passes;
1060    for (idx = 0; idx < no_of_passes; idx++) {
1061       pHrSr[idx] = 1.0f;
1062       pVtSr[idx] = 1.0f;
1063    }
1064 
1065    /* Calculate scaling ratios of every pass */
1066    if (no_horizontal_passes > 1)
1067       si_vpe_find_substage_scal_ratios(pHrSr, p_target_ratios[0], VPE_MAX_GEOMETRIC_DOWNSCALE, no_horizontal_passes);
1068    else
1069       pHrSr[0] = p_target_ratios[0];
1070 
1071    if (no_vertical_passes > 1)
1072       si_vpe_find_substage_scal_ratios(pVtSr, p_target_ratios[1], VPE_MAX_GEOMETRIC_DOWNSCALE, no_vertical_passes);
1073    else
1074       pVtSr[0] = p_target_ratios[1];
1075 
1076    if (no_vertical_passes < no_horizontal_passes) {
1077       pVtSr[no_horizontal_passes - 1] = pVtSr[no_vertical_passes - 1];
1078       pVtSr[no_vertical_passes - 1]   = 1.0f;
1079    } else if (no_vertical_passes > no_horizontal_passes) {
1080       pHrSr[no_vertical_passes - 1]   = pHrSr[no_horizontal_passes - 1];
1081       pHrSr[no_horizontal_passes - 1] = 1.0f;
1082    }
1083 
1084    /* Store the ratio information in vpeproc */
1085    vpeproc->scaling_ratios[0] = p_target_ratios[0];
1086    vpeproc->scaling_ratios[1] = p_target_ratios[1];
1087    vpeproc->geometric_scaling_ratios = pHrSr;
1088    vpeproc->geometric_passes = no_of_passes;
1089 
1090    return VPE_STATUS_OK;
1091 }
1092 
1093 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)1094 si_vpe_processor_process_frame(struct pipe_video_codec *codec,
1095                                struct pipe_video_buffer *input_texture,
1096                                const struct pipe_vpp_desc *process_properties)
1097 {
1098    struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1099    uint32_t src_rect_width, src_rect_height, dst_rect_width, dst_rect_height;
1100    float scaling_ratio[2];
1101 
1102    /* Get input surface */
1103    vpeproc->src_surfaces = input_texture->get_surfaces(input_texture);
1104    if (!vpeproc->src_surfaces || !vpeproc->src_surfaces[0]) {
1105       SIVPE_ERR("Get source surface failed\n");
1106       return 1;
1107    }
1108 
1109    /* Get scaling ratio info */
1110    src_rect_width  = process_properties->src_region.x1 - process_properties->src_region.x0;
1111    src_rect_height = process_properties->src_region.y1 - process_properties->src_region.y0;
1112    dst_rect_width  = process_properties->dst_region.x1 - process_properties->dst_region.x0;
1113    dst_rect_height = process_properties->dst_region.y1 - process_properties->dst_region.y0;
1114 
1115    scaling_ratio[0] = src_rect_width  / dst_rect_width;
1116    scaling_ratio[1] = src_rect_height / dst_rect_height;
1117 
1118    /* Check if the reduction ratio is within capability */
1119    if ((scaling_ratio[0] <= VPE_MAX_GEOMETRIC_DOWNSCALE) && (scaling_ratio[1] <= VPE_MAX_GEOMETRIC_DOWNSCALE))
1120       return si_vpe_construct_blt(vpeproc, process_properties, vpeproc->src_surfaces, vpeproc->dst_surfaces);
1121 
1122    return 1;
1123 }
1124 
1125 static int
si_vpe_processor_end_frame(struct pipe_video_codec * codec,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)1126 si_vpe_processor_end_frame(struct pipe_video_codec *codec,
1127                            struct pipe_video_buffer *target,
1128                            struct pipe_picture_desc *picture)
1129 {
1130    struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1131    assert(codec);
1132 
1133    vpeproc->ws->cs_flush(&vpeproc->cs, picture->flush_flags, picture->fence);
1134    next_buffer(vpeproc);
1135 
1136    return 0;
1137 }
1138 
1139 static void
si_vpe_processor_flush(struct pipe_video_codec * codec)1140 si_vpe_processor_flush(struct pipe_video_codec *codec)
1141 {
1142    /* Commands will be flushed when end_frame() is called */
1143    return;
1144 }
1145 
si_vpe_processor_fence_wait(struct pipe_video_codec * codec,struct pipe_fence_handle * fence,uint64_t timeout)1146 static int si_vpe_processor_fence_wait(struct pipe_video_codec *codec,
1147                                        struct pipe_fence_handle *fence,
1148                                        uint64_t timeout)
1149 {
1150    struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1151    assert(codec);
1152 
1153    if (!vpeproc->ws->fence_wait(vpeproc->ws, fence, timeout)) {
1154       SIVPE_DBG(vpeproc->log_level, "Wait processor fence fail\n");
1155       return 0;
1156    }
1157    return 1;
1158 }
1159 
si_vpe_processor_destroy_fence(struct pipe_video_codec * codec,struct pipe_fence_handle * fence)1160 static void si_vpe_processor_destroy_fence(struct pipe_video_codec *codec,
1161                                            struct pipe_fence_handle *fence)
1162 {
1163    struct vpe_video_processor *vpeproc = (struct vpe_video_processor *)codec;
1164    assert(codec);
1165 
1166    vpeproc->ws->fence_reference(vpeproc->ws, &fence, NULL);
1167 }
1168 
1169 struct pipe_video_codec*
si_vpe_create_processor(struct pipe_context * context,const struct pipe_video_codec * templ)1170 si_vpe_create_processor(struct pipe_context *context, const struct pipe_video_codec *templ)
1171 {
1172    struct si_context *sctx = (struct si_context *)context;
1173    struct radeon_winsys *ws = sctx->ws;
1174    struct vpe_video_processor *vpeproc;
1175    struct vpe_init_data *init_data;
1176    unsigned int i;
1177 
1178    vpeproc = CALLOC_STRUCT(vpe_video_processor);
1179    if (!vpeproc) {
1180       SIVPE_ERR("Allocate struct failed\n");
1181       return NULL;
1182    }
1183 
1184    /* SI_VPE debug log level
1185     * Default level(0) only shows error messages
1186     */
1187    vpeproc->log_level = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_LOG_LEVEL", SI_VPE_LOG_LEVEL_DEFAULT);
1188 
1189    vpeproc->base = *templ;
1190    vpeproc->base.context = context;
1191    vpeproc->base.width = templ->width;
1192    vpeproc->base.height = templ->height;
1193 
1194    vpeproc->base.destroy = si_vpe_processor_destroy;
1195    vpeproc->base.begin_frame = si_vpe_processor_begin_frame;
1196    vpeproc->base.process_frame = si_vpe_processor_process_frame;
1197    vpeproc->base.end_frame = si_vpe_processor_end_frame;
1198    vpeproc->base.flush = si_vpe_processor_flush;
1199    vpeproc->base.fence_wait = si_vpe_processor_fence_wait;
1200    vpeproc->base.destroy_fence = si_vpe_processor_destroy_fence;
1201 
1202    vpeproc->ver_major = sctx->screen->info.ip[AMD_IP_VPE].ver_major;
1203    vpeproc->ver_minor = sctx->screen->info.ip[AMD_IP_VPE].ver_minor;
1204 
1205    vpeproc->screen = context->screen;
1206    vpeproc->ws = ws;
1207 
1208    init_data = &vpeproc->vpe_data;
1209    if (VPE_STATUS_OK != si_vpe_populate_init_data(sctx, init_data, vpeproc->log_level)){
1210       SIVPE_ERR("Init VPE populate data failed\n");
1211       goto fail;
1212    }
1213 
1214    vpeproc->vpe_handle = vpe_create(init_data);
1215    if (!vpeproc->vpe_handle) {
1216       SIVPE_ERR("Create VPE handle failed\n");
1217       goto fail;
1218    }
1219 
1220    if (VPE_STATUS_OK != si_vpe_allocate_buffer(&vpeproc->vpe_build_bufs)) {
1221       SIVPE_ERR("Allocate VPE buffers failed\n");
1222       goto fail;
1223    }
1224 
1225    /* Create Command Submission context.
1226     * The cmdbuf (Vpe Descriptor) will be stored in cs.current.buf
1227     * there is no needs to allocate another buffer handle for cmdbuf.
1228     */
1229    if (!ws->cs_create(&vpeproc->cs, sctx->ctx, AMD_IP_VPE, NULL, NULL)) {
1230       SIVPE_ERR("Get command submission context failed.\n");
1231       goto fail;
1232    }
1233 
1234    /* Allocate Vpblit Descriptor buffers
1235     * Descriptor buffer is used to store plane config and VPEP commands
1236     */
1237    vpeproc->bufs_num = (uint8_t)debug_get_num_option("AMDGPU_SIVPE_BUF_NUM", VPE_BUFFERS_NUM);
1238    vpeproc->cur_buf = 0;
1239    vpeproc->emb_buffers = (struct rvid_buffer *)CALLOC(vpeproc->bufs_num, sizeof(struct rvid_buffer));
1240    if (!vpeproc->emb_buffers) {
1241       SIVPE_ERR("Allocate command buffer list failed\n");
1242       goto fail;
1243    } else
1244       SIVPE_INFO(vpeproc->log_level, "Number of emb_buf is %d\n", vpeproc->bufs_num);
1245 
1246    for (i = 0; i < vpeproc->bufs_num; i++) {
1247       if (!si_vid_create_buffer(vpeproc->screen, &vpeproc->emb_buffers[i], VPE_EMBBUF_SIZE, PIPE_USAGE_DEFAULT)) {
1248           SIVPE_ERR("Can't allocated emb_buf buffers.\n");
1249           goto fail;
1250       }
1251       si_vid_clear_buffer(context, &vpeproc->emb_buffers[i]);
1252    }
1253 
1254    /* Create VPE parameters structure */
1255    vpeproc->vpe_build_param = CALLOC_STRUCT(vpe_build_param);
1256    if (!vpeproc->vpe_build_param) {
1257       SIVPE_ERR("Allocate build-paramaters sturcture failed\n");
1258       goto fail;
1259    }
1260 
1261    /* Only one input frame is passed in for processing at a time (one stream pipe).
1262     * Only needs to handle one stream processing.
1263     */
1264    vpeproc->vpe_build_param->streams = (struct vpe_stream *)CALLOC(VPE_STREAM_MAX_NUM, sizeof(struct vpe_stream));
1265    if (!vpeproc->vpe_build_param->streams) {
1266       SIVPE_ERR("Allocate streams sturcture failed\n");
1267       goto fail;
1268    }
1269 
1270    return &vpeproc->base;
1271 
1272 fail:
1273    SIVPE_ERR("Failed\n");
1274    if (vpeproc) {
1275       si_vpe_processor_destroy(&vpeproc->base);
1276    }
1277    return NULL;
1278 }
1279