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 <stdio.h>
29 
30 #include "pipe/p_video_codec.h"
31 
32 #include "util/u_video.h"
33 
34 #include "si_pipe.h"
35 #include "radeon_vcn_enc.h"
36 
37 #define RENCODE_FW_INTERFACE_MAJOR_VERSION   1
38 #define RENCODE_FW_INTERFACE_MINOR_VERSION   0
39 
radeon_enc_sq_begin(struct radeon_encoder *enc)40 static void radeon_enc_sq_begin(struct radeon_encoder *enc)
41 {
42    rvcn_sq_header(&enc->cs, &enc->sq, true);
43    enc->mq_begin(enc);
44    rvcn_sq_tail(&enc->cs, &enc->sq);
45 }
46 
radeon_enc_sq_encode(struct radeon_encoder *enc)47 static void radeon_enc_sq_encode(struct radeon_encoder *enc)
48 {
49    rvcn_sq_header(&enc->cs, &enc->sq, true);
50    enc->mq_encode(enc);
51    rvcn_sq_tail(&enc->cs, &enc->sq);
52 }
53 
radeon_enc_sq_destroy(struct radeon_encoder *enc)54 static void radeon_enc_sq_destroy(struct radeon_encoder *enc)
55 {
56    rvcn_sq_header(&enc->cs, &enc->sq, true);
57    enc->mq_destroy(enc);
58    rvcn_sq_tail(&enc->cs, &enc->sq);
59 }
60 
radeon_enc_session_init(struct radeon_encoder *enc)61 static void radeon_enc_session_init(struct radeon_encoder *enc)
62 {
63    if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
64       enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264;
65       enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16);
66    } else if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) {
67       enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC;
68       enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64);
69    }
70    enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16);
71    enc->enc_pic.session_init.padding_width =
72       enc->enc_pic.session_init.aligned_picture_width - enc->base.width;
73    enc->enc_pic.session_init.padding_height =
74       enc->enc_pic.session_init.aligned_picture_height - enc->base.height;
75    enc->enc_pic.session_init.pre_encode_mode = RENCODE_PREENCODE_MODE_NONE;
76    enc->enc_pic.session_init.pre_encode_chroma_enabled = false;
77    enc->enc_pic.session_init.slice_output_enabled = false;
78    enc->enc_pic.session_init.display_remote = 0;
79 
80    RADEON_ENC_BEGIN(enc->cmd.session_init);
81    RADEON_ENC_CS(enc->enc_pic.session_init.encode_standard);
82    RADEON_ENC_CS(enc->enc_pic.session_init.aligned_picture_width);
83    RADEON_ENC_CS(enc->enc_pic.session_init.aligned_picture_height);
84    RADEON_ENC_CS(enc->enc_pic.session_init.padding_width);
85    RADEON_ENC_CS(enc->enc_pic.session_init.padding_height);
86    RADEON_ENC_CS(enc->enc_pic.session_init.pre_encode_mode);
87    RADEON_ENC_CS(enc->enc_pic.session_init.pre_encode_chroma_enabled);
88    RADEON_ENC_CS(enc->enc_pic.session_init.slice_output_enabled);
89    RADEON_ENC_CS(enc->enc_pic.session_init.display_remote);
90    RADEON_ENC_END();
91 }
92 
radeon_enc_ctx(struct radeon_encoder *enc)93 static void radeon_enc_ctx(struct radeon_encoder *enc)
94 {
95    enc->enc_pic.ctx_buf.swizzle_mode = 0;
96    enc->enc_pic.ctx_buf.two_pass_search_center_map_offset = 0;
97    enc->enc_pic.ctx_buf.colloc_buffer_offset = enc->dpb_size;
98 
99    uint32_t aligned_width = enc->enc_pic.session_init.aligned_picture_width;
100    uint32_t aligned_height = enc->enc_pic.session_init.aligned_picture_height;
101 
102    enc->enc_pic.ctx_buf.rec_luma_pitch = align(aligned_width, enc->alignment);
103    enc->enc_pic.ctx_buf.rec_chroma_pitch = align(aligned_width, enc->alignment);
104 
105    int luma_size = enc->enc_pic.ctx_buf.rec_luma_pitch * align(aligned_height, enc->alignment);
106    if (enc->enc_pic.bit_depth_luma_minus8 == 2)
107       luma_size *= 2;
108    int chroma_size = align(luma_size / 2, enc->alignment);
109    int offset = 0;
110 
111    for (int i = 0; i < enc->enc_pic.ctx_buf.num_reconstructed_pictures; i++) {
112       offset += luma_size;
113       offset += chroma_size;
114    }
115 
116    assert(offset == enc->dpb_size);
117 
118    RADEON_ENC_BEGIN(enc->cmd.ctx);
119    RADEON_ENC_READWRITE(enc->cpb.res->buf, enc->cpb.res->domains, 0);
120    RADEON_ENC_CS(enc->enc_pic.ctx_buf.swizzle_mode);
121    RADEON_ENC_CS(enc->enc_pic.ctx_buf.rec_luma_pitch);
122    RADEON_ENC_CS(enc->enc_pic.ctx_buf.rec_chroma_pitch);
123    RADEON_ENC_CS(enc->enc_pic.ctx_buf.num_reconstructed_pictures);
124 
125    for (int i = 0; i < RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES; i++) {
126       RADEON_ENC_CS(enc->enc_pic.ctx_buf.reconstructed_pictures_v4_0[i].luma_offset);
127       RADEON_ENC_CS(enc->enc_pic.ctx_buf.reconstructed_pictures_v4_0[i].chroma_offset);
128       RADEON_ENC_CS(enc->enc_pic.ctx_buf.reconstructed_pictures_v4_0[i].unused.unused_offset1);
129       RADEON_ENC_CS(enc->enc_pic.ctx_buf.reconstructed_pictures_v4_0[i].unused.unused_offset2);
130    }
131 
132    //  2: 1 pre encode pitch * 2 (luma + chroma)
133    // 136: 34 pre encode reconstructed pics * 4 (luma + chroma offsets + unused union)
134    //  3: 1 pre encode input pic * 3 (r,g,b offset union)
135    //----
136    // 141
137 
138    for (int i = 0; i < 141; i++)
139       RADEON_ENC_CS(0x00000000);
140 
141    RADEON_ENC_CS(enc->enc_pic.ctx_buf.two_pass_search_center_map_offset);
142    RADEON_ENC_CS(enc->enc_pic.ctx_buf.colloc_buffer_offset);
143    RADEON_ENC_END();
144 }
145 
radeon_enc_4_0_init(struct radeon_encoder *enc)146 void radeon_enc_4_0_init(struct radeon_encoder *enc)
147 {
148    radeon_enc_3_0_init(enc);
149 
150    enc->session_init = radeon_enc_session_init;
151    enc->ctx = radeon_enc_ctx;
152    enc->mq_begin = enc->begin;
153    enc->mq_encode = enc->encode;
154    enc->mq_destroy = enc->destroy;
155    enc->begin = radeon_enc_sq_begin;
156    enc->encode = radeon_enc_sq_encode;
157    enc->destroy = radeon_enc_sq_destroy;
158 
159    enc->enc_pic.session_info.interface_version =
160       ((RENCODE_FW_INTERFACE_MAJOR_VERSION << RENCODE_IF_MAJOR_VERSION_SHIFT) |
161       (RENCODE_FW_INTERFACE_MINOR_VERSION << RENCODE_IF_MINOR_VERSION_SHIFT));
162 }
163