blob: 684d6ac4695fde4205d67a7ac0d39c85a64d4349 [file] [log] [blame]
Kuang-che Wudb9c20b2014-04-17 16:14:18 +08001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Kuang-che Wudb9c20b2014-04-17 16:14:18 +08004#include <alloca.h>
Kuang-che Wuca2bd582014-07-22 18:24:45 +08005#include <errno.h>
6#include <fcntl.h>
7#include <stdio.h>
8#include <stdlib.h>
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +09009#include <string.h>
Kuang-che Wuca2bd582014-07-22 18:24:45 +080010#include <unistd.h>
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080011
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080012#include <va/va.h>
Kuang-che Wuca2bd582014-07-22 18:24:45 +080013#include <va/va_drm.h>
Jeffrey Kardatzke819314a2021-03-01 17:10:32 -080014#include <va/va_prot.h>
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080015
16#include "label_detect.h"
17
18/* Returns true if given VA profile |va_profile| has |entrypoint| and the entry
19 * point supports given raw |format|.
20 */
Tom Hughes0e816952020-08-24 18:04:24 -070021static bool has_vaapi_entrypoint(VADisplay va_display,
22 VAProfile va_profile,
23 VAEntrypoint entrypoint,
24 unsigned int format) {
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080025 VAStatus va_res;
26 VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0};
Tom Hughes0e816952020-08-24 18:04:24 -070027 va_res =
28 vaGetConfigAttributes(va_display, va_profile, entrypoint, &attrib, 1);
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080029 if (va_res != VA_STATUS_SUCCESS) {
30 TRACE("vaGetConfigAttributes failed (%d)\n", va_res);
31 return false;
32 }
33
34 return attrib.value & format;
35}
36
37/* Returns true if the current platform supports at least one of the
38 * |required_profiles| and |entrypoint| for that profile supports given raw
39 * |format|.
40 */
41static bool match_vaapi_capabilities(VADisplay va_display,
Tom Hughes0e816952020-08-24 18:04:24 -070042 const VAProfile* required_profiles,
43 VAEntrypoint entrypoint,
44 unsigned int format) {
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080045 int i;
Kuang-che Wu6505c562014-06-23 20:18:10 +080046 bool found = false;
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080047 int num_supported_profiles;
48 VAStatus va_res;
49 VAProfile* profiles;
50 int max_profiles = vaMaxNumProfiles(va_display);
Sudarshan S758b32a2020-02-10 13:24:54 +053051 /* If no profiles are supported do not proceed further */
52 if (max_profiles <= 0) {
Tom Hughes0e816952020-08-24 18:04:24 -070053 TRACE("vaMaxNumProfiles returns %d \n ", max_profiles);
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080054 return false;
55 }
56
Tom Hughes0e816952020-08-24 18:04:24 -070057 profiles = (VAProfile*)alloca(sizeof(VAProfile) * max_profiles);
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080058 if (!profiles) {
59 TRACE("alloca failed\n");
60 return false;
61 }
62 va_res = vaQueryConfigProfiles(va_display, profiles, &num_supported_profiles);
63 if (va_res != VA_STATUS_SUCCESS) {
64 TRACE("vaQueryConfigProfiles failed (%d)\n", va_res);
65 return false;
66 }
67 for (i = 0; i < num_supported_profiles; i++) {
68 int j;
69 VAProfile profile = profiles[i];
70 TRACE("supported profile: %d\n", profile);
71 for (j = 0; required_profiles[j] != VAProfileNone; j++) {
72 if (required_profiles[j] == profile &&
73 has_vaapi_entrypoint(va_display, profile, entrypoint, format)) {
74 found = true;
75 /* continue the loop in order to output all supported profiles */
76 }
77 }
78 }
79 return found;
80}
81
82/* Returns true if libva supports any given profiles. And that profile has said
83 * entrypoint with format.
84 */
Tom Hughes0e816952020-08-24 18:04:24 -070085bool is_vaapi_support_formats(int fd,
86 const VAProfile* profiles,
87 VAEntrypoint entrypoint,
88 unsigned int format) {
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080089 bool found = false;
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080090 VAStatus va_res;
91 VADisplay va_display;
92 int major_version, minor_version;
93
Kuang-che Wuca2bd582014-07-22 18:24:45 +080094 va_display = vaGetDisplayDRM(fd);
Kuang-che Wudb9c20b2014-04-17 16:14:18 +080095 if (!vaDisplayIsValid(va_display)) {
96 TRACE("vaGetDisplay returns invalid display\n");
97 return false;
98 }
99
100 va_res = vaInitialize(va_display, &major_version, &minor_version);
101 if (va_res != VA_STATUS_SUCCESS) {
102 TRACE("vaInitialize failed\n");
103 return false;
104 }
105
106 if (match_vaapi_capabilities(va_display, profiles, entrypoint, format))
107 found = true;
108
109 vaTerminate(va_display);
Kuang-che Wudb9c20b2014-04-17 16:14:18 +0800110
111 return found;
112}
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900113
114/* Returns true if |entrypoint| is supported. */
Tom Hughes0e816952020-08-24 18:04:24 -0700115static bool is_entrypoint_supported(VADisplay va_display,
116 VAProfile va_profile,
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900117 VAEntrypoint entrypoint) {
118 bool result = false;
119 int max_entrypoints = vaMaxNumEntrypoints(va_display);
120 VAEntrypoint* supported_entrypoints =
121 malloc(max_entrypoints * sizeof(VAEntrypoint));
122 int num_supported_entrypoints;
Tom Hughes0e816952020-08-24 18:04:24 -0700123 VAStatus va_res =
124 vaQueryConfigEntrypoints(va_display, va_profile, supported_entrypoints,
125 &num_supported_entrypoints);
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900126
127 if (va_res != VA_STATUS_SUCCESS) {
128 TRACE("vaQueryConfigEntrypoints failed (%d)\n", va_res);
129 goto finish;
130 }
131 if (num_supported_entrypoints < 0 ||
132 num_supported_entrypoints > max_entrypoints) {
133 TRACE("vaQueryConfigEntrypoints returned: %d\n", num_supported_entrypoints);
134 goto finish;
135 }
136
137 for (int i = 0; i < num_supported_entrypoints; i++) {
138 if (supported_entrypoints[i] == entrypoint) {
139 result = true;
140 break;
141 }
142 }
143
Tom Hughes0e816952020-08-24 18:04:24 -0700144finish:
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900145 free(supported_entrypoints);
146 return result;
147}
148
149/* Returns true if |required_attribs| are supported. */
Tom Hughes0e816952020-08-24 18:04:24 -0700150static bool are_attribs_supported(VADisplay va_display,
151 VAProfile va_profile,
152 VAEntrypoint entrypoint,
Jeffrey Kardatzke819314a2021-03-01 17:10:32 -0800153 const VAConfigAttrib* required_attribs,
Tom Hughes0e816952020-08-24 18:04:24 -0700154 int num_required_attribs) {
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900155 bool result = false;
156 VAConfigAttrib* attribs =
157 malloc(sizeof(VAConfigAttrib) * num_required_attribs);
George Burgess IV00ee1c52019-05-01 16:45:25 -0700158 memcpy(attribs, required_attribs, sizeof(*attribs) * num_required_attribs);
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900159 for (int i = 0; i < num_required_attribs; i++) {
160 attribs[i].value = 0;
161 }
162
163 VAStatus va_res = vaGetConfigAttributes(va_display, va_profile, entrypoint,
164 attribs, num_required_attribs);
165 if (va_res != VA_STATUS_SUCCESS) {
166 TRACE("vaGetConfigAttributes failed (%d)\n", va_res);
167 goto finish;
168 }
169
170 for (int i = 0; i < num_required_attribs; i++) {
171 if (attribs[i].type != required_attribs[i].type ||
172 (attribs[i].value & required_attribs[i].value) !=
173 required_attribs[i].value) {
174 // Unsupported value.
175 goto finish;
176 }
177 }
178 result = true;
179
Tom Hughes0e816952020-08-24 18:04:24 -0700180finish:
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900181 free(attribs);
182 return result;
183}
184
Jeffrey Kardatzke819314a2021-03-01 17:10:32 -0800185/* Returns true if |required_attribs| are supported. */
186bool are_vaapi_attribs_supported(int fd,
187 VAProfile va_profile,
188 VAEntrypoint entrypoint,
189 const VAConfigAttrib* required_attribs,
190 int num_required_attribs) {
191 VAStatus va_res;
192 VADisplay va_display;
193 int major_version, minor_version;
194
195 va_display = vaGetDisplayDRM(fd);
196 if (!vaDisplayIsValid(va_display)) {
197 TRACE("vaGetDisplay returns invalid display\n");
198 return false;
199 }
200
201 va_res = vaInitialize(va_display, &major_version, &minor_version);
202 if (va_res != VA_STATUS_SUCCESS) {
203 TRACE("vaInitialize failed\n");
204 return false;
205 }
206
207 bool res = are_attribs_supported(va_display, va_profile, entrypoint,
208 required_attribs, num_required_attribs);
209
210 vaTerminate(va_display);
211 return res;
212}
213
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900214/* Returns success or failure of getting resolution. The maximum resolution
215 * of a passed profile is returned through arguments. */
Tom Hughes0e816952020-08-24 18:04:24 -0700216static bool get_max_resolution(VADisplay va_display,
217 VAProfile va_profile,
218 VAEntrypoint entrypoint,
219 VAConfigAttrib* required_attribs,
220 int num_required_attribs,
221 int32_t* width,
222 int32_t* height) {
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900223 VAStatus va_res;
224 VAConfigID va_config_id;
Tom Hughes0e816952020-08-24 18:04:24 -0700225 VASurfaceAttrib* attrib_list;
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900226 unsigned int num_attribs = 0;
227 *width = 0;
228 *height = 0;
229
Tom Hughes0e816952020-08-24 18:04:24 -0700230 va_res = vaCreateConfig(va_display, va_profile, entrypoint, required_attribs,
231 num_attribs, &va_config_id);
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900232 if (va_res != VA_STATUS_SUCCESS) {
233 TRACE("vaQueryConfigProfiles failed (%d)\n", va_res);
234 return false;
235 }
236 // Calls vaQuerySurfaceAttributes twice. The first time is to get the number
237 // of attributes to prepare the space and the second time is to get all
238 // attributes.
239 va_res =
240 vaQuerySurfaceAttributes(va_display, va_config_id, NULL, &num_attribs);
241 if (va_res != VA_STATUS_SUCCESS) {
242 TRACE("vaQuerySurfaceAttributes failed (%d)\n", va_res);
243 return false;
244 }
245 if (!num_attribs) {
246 return false;
247 }
248
249 attrib_list = malloc(num_attribs * sizeof(VASurfaceAttrib));
Tom Hughes0e816952020-08-24 18:04:24 -0700250 va_res = vaQuerySurfaceAttributes(va_display, va_config_id, attrib_list,
251 &num_attribs);
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900252 if (va_res != VA_STATUS_SUCCESS) {
253 TRACE("vaQuerySurfaceAttributes failed (%d)\n", va_res);
254 free(attrib_list);
255 return false;
256 }
257 for (unsigned int j = 0; j < num_attribs; j++) {
258 VASurfaceAttrib attrib = attrib_list[j];
259 if (attrib.type == VASurfaceAttribMaxWidth) {
260 *width = attrib.value.value.i;
261 } else if (attrib.type == VASurfaceAttribMaxHeight) {
262 *height = attrib.value.value.i;
263 }
264 }
265 free(attrib_list);
266 return *width > 0 && *height > 0;
267}
268
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900269/* Returns success or failure of getting resolution. The maximum resolution
270 * among passed profiles is returned through arguments. */
Tom Hughes0e816952020-08-24 18:04:24 -0700271bool get_vaapi_max_resolution(int fd,
272 const VAProfile* profiles,
273 VAEntrypoint entrypoint,
Steve Cho79784862021-01-22 13:59:00 -0800274 unsigned int format,
Tom Hughes0e816952020-08-24 18:04:24 -0700275 int32_t* const resolution_width,
276 int32_t* const resolution_height) {
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900277 *resolution_width = 0;
278 *resolution_height = 0;
279
Steve Cho79784862021-01-22 13:59:00 -0800280 VAConfigAttrib required_attribs = {VAConfigAttribRTFormat, format};
281
Hirokazu Hondad92e9ac2017-09-20 11:33:59 +0900282 VAStatus va_res;
283 VADisplay va_display = vaGetDisplayDRM(fd);
284 int major_version, minor_version;
285 if (!vaDisplayIsValid(va_display)) {
286 TRACE("vaGetDisplay returns invalid display\n");
287 return false;
288 }
289 va_res = vaInitialize(va_display, &major_version, &minor_version);
290 if (va_res != VA_STATUS_SUCCESS) {
291 TRACE("vaInitialize failed\n");
292 return false;
293 }
294
295 for (size_t i = 0; profiles[i] != VAProfileNone; i++) {
296 VAProfile va_profile = profiles[i];
297 int32_t width = 0;
298 int32_t height = 0;
299 if (!is_entrypoint_supported(va_display, va_profile, entrypoint)) {
300 continue;
301 }
302
303 if (!are_attribs_supported(va_display, va_profile, entrypoint,
304 &required_attribs, 1)) {
305 continue;
306 }
307
308 if (!get_max_resolution(va_display, va_profile, entrypoint,
309 &required_attribs, 1, &width, &height)) {
310 TRACE("GetMaxResolution failed for va_profile %d and entrypoint %u\n",
311 va_profile, entrypoint);
312 continue;
313 }
314
315 if (*resolution_width <= width && *resolution_height <= height) {
316 *resolution_width = width;
317 *resolution_height = height;
318 }
319 }
320 vaTerminate(va_display);
321 return *resolution_width > 0 && *resolution_height > 0;
322}