Bug 1751217 Part 3: Make HDR-capable macOS screens report 30 pixelDepth. r=mstange
[gecko.git] / widget / gtk / VAAPIUtils.cpp
blobbf24abbd6a0e49fd2637ac295dc86ace7d24c690
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"
9 #include "va/va.h"
10 #include "prlink.h"
11 #include "mozilla/ScopeExit.h"
12 #include "DMABufLibWrapper.h"
14 namespace mozilla::widget {
16 static constexpr struct {
17 VAProfile mVAProfile;
18 nsLiteralCString mName;
19 } kVAAPiProfileName[] = {
20 #define MAP(v) \
21 { VAProfile##v, nsLiteralCString(#v) }
22 MAP(H264ConstrainedBaseline),
23 MAP(H264Main),
24 MAP(H264High),
25 MAP(VP8Version0_3),
26 MAP(VP9Profile0),
27 MAP(VP9Profile2),
28 MAP(AV1Profile0),
29 MAP(AV1Profile1),
30 #undef MAP
33 static const char* VAProfileName(VAProfile aVAProfile) {
34 for (const auto& profile : kVAAPiProfileName) {
35 if (profile.mVAProfile == aVAProfile) {
36 return profile.mName.get();
39 return nullptr;
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([&] {
51 delete[] profiles;
52 delete[] entryPoints;
53 if (display) {
54 vaTerminate(display);
56 if (libDrm) {
57 PR_UnloadLibrary(libDrm);
59 });
61 PRLibSpec lspec;
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);
66 if (!libDrm) {
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());
78 if (!display) {
79 LOGDMABUF((" Failed to get vaGetDisplayDRM()"));
80 return supportedProfiles;
83 int major, minor;
84 VAStatus status = vaInitialize(display, &major, &minor);
85 if (status != VA_STATUS_SUCCESS) {
86 LOGDMABUF(
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];
100 int numProfiles = 0;
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)) {
114 continue;
117 int numEntryPoints = 0;
118 status = vaQueryConfigEntrypoints(display, profile, entryPoints,
119 &numEntryPoints);
120 if (status != VA_STATUS_SUCCESS) {
121 LOGDMABUF((" vaQueryConfigEntrypoints() failed: '%s' for profile %d",
122 vaErrorStr(status), (int)profile));
123 continue;
125 numEntryPoints = std::min(numEntryPoints, maxEntryPoints);
127 for (int entry = 0; entry < numEntryPoints; entry++) {
128 if (entryPoints[entry] != VAEntrypointVLD) {
129 continue;
131 VAConfigID config = VA_INVALID_ID;
132 status = vaCreateConfig(display, profile, entryPoints[entry], nullptr, 0,
133 &config);
134 if (status == VA_STATUS_SUCCESS) {
135 LOGDMABUF((" Supported profile %s:", VAProfileName(profile)));
136 supportedProfiles.AppendElement(profile);
137 vaDestroyConfig(display, config);
138 break;
142 return supportedProfiles;
145 static const nsTArray<VAProfile>& VAAPIGetAcceleratedProfiles() {
146 static const nsTArray<VAProfile> profiles =
147 VAAPIGetAcceleratedProfilesInternal();
148 return profiles;
151 bool VAAPIIsSupported() { return !VAAPIGetAcceleratedProfiles().IsEmpty(); }
153 } // namespace mozilla::widget