1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "VAAPIUtils.h"
11 #include "mozilla/ScopeExit.h"
12 #include "DMABufLibWrapper.h"
14 namespace mozilla::widget
{
16 static constexpr struct {
18 nsLiteralCString mName
;
19 } kVAAPiProfileName
[] = {
21 { VAProfile##v, nsLiteralCString(#v) }
22 MAP(H264ConstrainedBaseline
),
33 static const char* VAProfileName(VAProfile aVAProfile
) {
34 for (const auto& profile
: kVAAPiProfileName
) {
35 if (profile
.mVAProfile
== aVAProfile
) {
36 return profile
.mName
.get();
42 static nsTArray
<VAProfile
> VAAPIGetAcceleratedProfilesInternal() {
43 LOGDMABUF(("VAAPIGetAcceleratedProfiles()"));
44 VAProfile
* profiles
= nullptr;
45 VAEntrypoint
* entryPoints
= nullptr;
46 PRLibrary
* libDrm
= nullptr;
47 VADisplay display
= nullptr;
48 nsTArray
<VAProfile
> supportedProfiles
;
50 auto autoRelease
= mozilla::MakeScopeExit([&] {
57 PR_UnloadLibrary(libDrm
);
62 lspec
.type
= PR_LibSpec_Pathname
;
63 const char* libName
= "libva-drm.so.2";
64 lspec
.value
.pathname
= libName
;
65 libDrm
= PR_LoadLibraryWithFlags(lspec
, PR_LD_NOW
| PR_LD_LOCAL
);
67 LOGDMABUF((" Missing or old %s library.", libName
));
68 return supportedProfiles
;
71 static auto sVaGetDisplayDRM
=
72 (void* (*)(int fd
))PR_FindSymbol(libDrm
, "vaGetDisplayDRM");
73 if (!sVaGetDisplayDRM
) {
74 LOGDMABUF((" Missing vaGetDisplayDRM()"));
75 return supportedProfiles
;
77 display
= sVaGetDisplayDRM(widget::GetDMABufDevice()->GetDRMFd());
79 LOGDMABUF((" Failed to get vaGetDisplayDRM()"));
80 return supportedProfiles
;
84 VAStatus status
= vaInitialize(display
, &major
, &minor
);
85 if (status
!= VA_STATUS_SUCCESS
) {
87 (" Failed to initialise VAAPI connection: %s.", vaErrorStr(status
)));
88 return supportedProfiles
;
90 LOGDMABUF((" Initialised VAAPI connection: version %d.%d", major
, minor
));
92 int maxProfiles
= vaMaxNumProfiles(display
);
93 int maxEntryPoints
= vaMaxNumEntrypoints(display
);
94 if (MOZ_UNLIKELY(maxProfiles
<= 0 || maxEntryPoints
<= 0)) {
95 LOGDMABUF((" Wrong profiles/entry point nums."));
96 return supportedProfiles
;
99 profiles
= new VAProfile
[maxProfiles
];
101 status
= vaQueryConfigProfiles(display
, profiles
, &numProfiles
);
102 if (status
!= VA_STATUS_SUCCESS
) {
103 LOGDMABUF((" vaQueryConfigProfiles() failed %s", vaErrorStr(status
)));
104 return supportedProfiles
;
106 numProfiles
= std::min(numProfiles
, maxProfiles
);
108 entryPoints
= new VAEntrypoint
[maxEntryPoints
];
109 for (int p
= 0; p
< numProfiles
; p
++) {
110 VAProfile profile
= profiles
[p
];
112 // Check only supported profiles
113 if (!VAProfileName(profile
)) {
117 int numEntryPoints
= 0;
118 status
= vaQueryConfigEntrypoints(display
, profile
, entryPoints
,
120 if (status
!= VA_STATUS_SUCCESS
) {
121 LOGDMABUF((" vaQueryConfigEntrypoints() failed: '%s' for profile %d",
122 vaErrorStr(status
), (int)profile
));
125 numEntryPoints
= std::min(numEntryPoints
, maxEntryPoints
);
127 for (int entry
= 0; entry
< numEntryPoints
; entry
++) {
128 if (entryPoints
[entry
] != VAEntrypointVLD
) {
131 VAConfigID config
= VA_INVALID_ID
;
132 status
= vaCreateConfig(display
, profile
, entryPoints
[entry
], nullptr, 0,
134 if (status
== VA_STATUS_SUCCESS
) {
135 LOGDMABUF((" Supported profile %s:", VAProfileName(profile
)));
136 supportedProfiles
.AppendElement(profile
);
137 vaDestroyConfig(display
, config
);
142 return supportedProfiles
;
145 static const nsTArray
<VAProfile
>& VAAPIGetAcceleratedProfiles() {
146 static const nsTArray
<VAProfile
> profiles
=
147 VAAPIGetAcceleratedProfilesInternal();
151 bool VAAPIIsSupported() { return !VAAPIGetAcceleratedProfiles().IsEmpty(); }
153 } // namespace mozilla::widget