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