summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Stransky <stransky@redhat.com>2022-06-07 11:19:41 +0200
committerMartin Stransky <stransky@redhat.com>2022-06-07 11:19:41 +0200
commit61879d2c53a0473a24b4a9a69fcedd1af8f74fdf (patch)
treed12a4530b17d4c7e0cde6ecb74aa5e47e5120477
parentUpdated cbindgen to 0.23.0 (diff)
downloadlibrewolf-fedora-ff-61879d2c53a0473a24b4a9a69fcedd1af8f74fdf.tar.gz
librewolf-fedora-ff-61879d2c53a0473a24b4a9a69fcedd1af8f74fdf.tar.bz2
librewolf-fedora-ff-61879d2c53a0473a24b4a9a69fcedd1af8f74fdf.zip
Enabled VA-API by default (+ added VA-API fixes from upstream), Fixed WebGL performance on NVIDIA drivers (mzbz#1735929)
-rw-r--r--D144284.diff77
-rw-r--r--D145725.diff132
-rw-r--r--D145871.diff140
-rw-r--r--D145966.diff20
-rw-r--r--D146084.diff17
-rw-r--r--D146085.diff205
-rw-r--r--D146086.diff65
-rw-r--r--D146087.diff19
-rw-r--r--D147420.diff179
-rw-r--r--D147635.diff125
-rw-r--r--D147636.diff278
-rw-r--r--D147637.diff113
-rw-r--r--D147720.diff73
-rw-r--r--D147874.diff64
-rw-r--r--firefox.spec44
15 files changed, 1550 insertions, 1 deletions
diff --git a/D144284.diff b/D144284.diff
new file mode 100644
index 0000000..d838254
--- /dev/null
+++ b/D144284.diff
@@ -0,0 +1,77 @@
+diff --git a/gfx/layers/DMABUFSurfaceImage.cpp b/gfx/layers/DMABUFSurfaceImage.cpp
+--- a/gfx/layers/DMABUFSurfaceImage.cpp
++++ b/gfx/layers/DMABUFSurfaceImage.cpp
+@@ -39,20 +39,20 @@
+
+ StaticRefPtr<GLContext> sSnapshotContext;
+ static StaticMutex sSnapshotContextMutex MOZ_UNANNOTATED;
+
+ already_AddRefed<gfx::SourceSurface> DMABUFSurfaceImage::GetAsSourceSurface() {
++ StaticMutexAutoLock lock(sSnapshotContextMutex);
+ if (!sSnapshotContext) {
+ nsCString discardFailureId;
+ sSnapshotContext = GLContextProvider::CreateHeadless({}, &discardFailureId);
+ if (!sSnapshotContext) {
+ gfxCriticalError() << "Failed to create snapshot GLContext.";
+ return nullptr;
+ }
+ }
+
+- StaticMutexAutoLock lock(sSnapshotContextMutex);
+ sSnapshotContext->MakeCurrent();
+
+ auto releaseTextures =
+ mozilla::MakeScopeExit([&] { mSurface->ReleaseTextures(); });
+
+diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp
+--- a/widget/gtk/DMABufSurface.cpp
++++ b/widget/gtk/DMABufSurface.cpp
+@@ -53,24 +53,13 @@
+ using namespace mozilla::layers;
+
+ #define BUFFER_FLAGS 0
+
+ static RefPtr<GLContext> sSnapshotContext;
++static StaticMutex sSnapshotContextMutex MOZ_UNANNOTATED;
+ static Atomic<int> gNewSurfaceUID(1);
+
+-bool EnsureSnapshotGLContext() {
+- if (!sSnapshotContext) {
+- nsCString discardFailureId;
+- sSnapshotContext = GLContextProvider::CreateHeadless({}, &discardFailureId);
+- if (!sSnapshotContext) {
+- NS_WARNING("Failed to create snapshot GLContext");
+- return false;
+- }
+- }
+- return true;
+-}
+-
+ bool DMABufSurface::IsGlobalRefSet() const {
+ if (!mGlobalRefCountFd) {
+ return false;
+ }
+ struct pollfd pfd;
+@@ -1263,13 +1252,18 @@
+ }
+
+ bool DMABufSurfaceYUV::VerifyTextureCreation() {
+ LOGDMABUF(("DMABufSurfaceYUV::VerifyTextureCreation() UID %d", mUID));
+
+- if (!EnsureSnapshotGLContext()) {
+- LOGDMABUF((" failed to create GL context!"));
+- return false;
++ StaticMutexAutoLock lock(sSnapshotContextMutex);
++ if (!sSnapshotContext) {
++ nsCString discardFailureId;
++ sSnapshotContext = GLContextProvider::CreateHeadless({}, &discardFailureId);
++ if (!sSnapshotContext) {
++ NS_WARNING("Failed to create snapshot GLContext");
++ return false;
++ }
+ }
+
+ auto release = MakeScopeExit([&] { ReleaseEGLImages(sSnapshotContext); });
+
+ for (int i = 0; i < mBufferPlaneCount; i++) {
+
diff --git a/D145725.diff b/D145725.diff
new file mode 100644
index 0000000..1c28b10
--- /dev/null
+++ b/D145725.diff
@@ -0,0 +1,132 @@
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+@@ -106,10 +106,11 @@
+ bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
+ bool IsHardwareAccelerated() const {
+ nsAutoCString dummy;
+ return IsHardwareAccelerated(dummy);
+ }
++ void UpdateDecodeTimes(TimeStamp aDecodeStart);
+
+ #if LIBAVCODEC_VERSION_MAJOR >= 57 && LIBAVUTIL_VERSION_MAJOR >= 56
+ layers::TextureClient* AllocateTextureClientForImage(
+ struct AVCodecContext* aCodecContext, layers::PlanarYCbCrImage* aImage);
+
+@@ -142,10 +143,15 @@
+ static nsTArray<AVCodecID> mAcceleratedFormats;
+ #endif
+ RefPtr<KnowsCompositor> mImageAllocator;
+ RefPtr<ImageContainer> mImageContainer;
+ VideoInfo mInfo;
++ int mDecodedFrames;
++#if LIBAVCODEC_VERSION_MAJOR >= 58
++ int mDecodedFramesLate;
++#endif
++ float mAverangeDecodeTime;
+
+ class PtsCorrectionContext {
+ public:
+ PtsCorrectionContext();
+ int64_t GuessCorrectPts(int64_t aPts, int64_t aDts);
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+@@ -383,10 +383,15 @@
+ mDisplay(nullptr),
+ #endif
+ mImageAllocator(aAllocator),
+ mImageContainer(aImageContainer),
+ mInfo(aConfig),
++ mDecodedFrames(0),
++#if LIBAVCODEC_VERSION_MAJOR >= 58
++ mDecodedFramesLate(0),
++#endif
++ mAverangeDecodeTime(0),
+ mLowLatency(aLowLatency) {
+ FFMPEG_LOG("FFmpegVideoDecoder::FFmpegVideoDecoder MIME %s Codec ID %d",
+ aConfig.mMimeType.get(), mCodecID);
+ // Use a new MediaByteBuffer as the object will be modified during
+ // initialization.
+@@ -769,17 +774,41 @@
+ #else
+ return aFrame->pkt_pts;
+ #endif
+ }
+
++void FFmpegVideoDecoder<LIBAV_VER>::UpdateDecodeTimes(TimeStamp aDecodeStart) {
++ mDecodedFrames++;
++ float decodeTime = (TimeStamp::Now() - aDecodeStart).ToMilliseconds();
++ mAverangeDecodeTime =
++ (mAverangeDecodeTime * (mDecodedFrames - 1) + decodeTime) /
++ mDecodedFrames;
++ FFMPEG_LOG(" averange frame decode time %.2f ms decoded frames %d\n",
++ mAverangeDecodeTime, mDecodedFrames);
++#if LIBAVCODEC_VERSION_MAJOR >= 58
++ int frameDuration = mFrame->pkt_duration;
++ if (frameDuration > 0 && frameDuration / 1000.0 < decodeTime) {
++ mDecodedFramesLate++;
++ FFMPEG_LOG(
++ " slow decode: failed to decode in time, frame duration %.2f ms, "
++ "decode time %.2f\n",
++ frameDuration / 1000.0, decodeTime);
++ FFMPEG_LOG(" all decoded frames / late decoded frames %d/%d\n",
++ mDecodedFrames, mDecodedFramesLate);
++ }
++#endif
++}
++
+ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
+ MediaRawData* aSample, uint8_t* aData, int aSize, bool* aGotFrame,
+ MediaDataDecoder::DecodedData& aResults) {
+ MOZ_ASSERT(mTaskQueue->IsOnCurrentThread());
+ AVPacket packet;
+ mLib->av_init_packet(&packet);
+
++ TimeStamp decodeStart = TimeStamp::Now();
++
+ packet.data = aData;
+ packet.size = aSize;
+ packet.dts = aSample->mTimecode.ToMicroseconds();
+ packet.pts = aSample->mTime.ToMicroseconds();
+ packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0;
+@@ -794,11 +823,10 @@
+ // at a time, and we immediately call avcodec_receive_frame right after.
+ FFMPEG_LOG("avcodec_send_packet error: %d", res);
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("avcodec_send_packet error: %d", res));
+ }
+-
+ if (aGotFrame) {
+ *aGotFrame = false;
+ }
+ do {
+ if (!PrepareFrame()) {
+@@ -831,10 +859,13 @@
+ FFMPEG_LOG(" avcodec_receive_frame error: %d", res);
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("avcodec_receive_frame error: %d", res));
+ }
+
++ UpdateDecodeTimes(decodeStart);
++ decodeStart = TimeStamp::Now();
++
+ MediaResult rv;
+ # ifdef MOZ_WAYLAND_USE_VAAPI
+ if (IsHardwareAccelerated()) {
+ rv = CreateImageVAAPI(mFrame->pkt_pos, GetFramePts(mFrame),
+ mFrame->pkt_duration, aResults);
+@@ -898,10 +929,12 @@
+ *aGotFrame = false;
+ }
+ return NS_OK;
+ }
+
++ UpdateDecodeTimes(decodeStart);
++
+ // If we've decoded a frame then we need to output it
+ int64_t pts =
+ mPtsContext.GuessCorrectPts(GetFramePts(mFrame), mFrame->pkt_dts);
+ // Retrieve duration from dts.
+ // We use the first entry found matching this dts (this is done to
+
diff --git a/D145871.diff b/D145871.diff
new file mode 100644
index 0000000..33a2e61
--- /dev/null
+++ b/D145871.diff
@@ -0,0 +1,140 @@
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+@@ -146,10 +146,15 @@
+ RefPtr<ImageContainer> mImageContainer;
+ VideoInfo mInfo;
+ int mDecodedFrames;
+ #if LIBAVCODEC_VERSION_MAJOR >= 58
+ int mDecodedFramesLate;
++ // Tracks when decode time of recent frame and averange decode time of
++ // previous frames is bigger than frame interval,
++ // i.e. we fail to decode in time.
++ // We switch to SW decode when we hit HW_DECODE_LATE_FRAMES treshold.
++ int mMissedDecodeInAverangeTime;
+ #endif
+ float mAverangeDecodeTime;
+
+ class PtsCorrectionContext {
+ public:
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+@@ -14,10 +14,13 @@
+ #include "VPXDecoder.h"
+ #include "mozilla/layers/KnowsCompositor.h"
+ #if LIBAVCODEC_VERSION_MAJOR >= 57
+ # include "mozilla/layers/TextureClient.h"
+ #endif
++#if LIBAVCODEC_VERSION_MAJOR >= 58
++# include "mozilla/ProfilerMarkers.h"
++#endif
+ #ifdef MOZ_WAYLAND_USE_VAAPI
+ # include "H264.h"
+ # include "mozilla/layers/DMABUFSurfaceImage.h"
+ # include "mozilla/widget/DMABufLibWrapper.h"
+ # include "FFmpegVideoFramePool.h"
+@@ -56,13 +59,14 @@
+ typedef int VAStatus;
+ # define VA_EXPORT_SURFACE_READ_ONLY 0x0001
+ # define VA_EXPORT_SURFACE_SEPARATE_LAYERS 0x0004
+ # define VA_STATUS_SUCCESS 0x00000000
+ #endif
+-
+ // Use some extra HW frames for potential rendering lags.
+ #define EXTRA_HW_FRAMES 6
++// Defines number of delayed frames until we switch back to SW decode.
++#define HW_DECODE_LATE_FRAMES 15
+
+ #if LIBAVCODEC_VERSION_MAJOR >= 57 && LIBAVUTIL_VERSION_MAJOR >= 56
+ # define CUSTOMIZED_BUFFER_ALLOCATION 1
+ #endif
+
+@@ -386,10 +390,11 @@
+ mImageContainer(aImageContainer),
+ mInfo(aConfig),
+ mDecodedFrames(0),
+ #if LIBAVCODEC_VERSION_MAJOR >= 58
+ mDecodedFramesLate(0),
++ mMissedDecodeInAverangeTime(0),
+ #endif
+ mAverangeDecodeTime(0),
+ mLowLatency(aLowLatency) {
+ FFMPEG_LOG("FFmpegVideoDecoder::FFmpegVideoDecoder MIME %s Codec ID %d",
+ aConfig.mMimeType.get(), mCodecID);
+@@ -781,22 +786,32 @@
+ float decodeTime = (TimeStamp::Now() - aDecodeStart).ToMilliseconds();
+ mAverangeDecodeTime =
+ (mAverangeDecodeTime * (mDecodedFrames - 1) + decodeTime) /
+ mDecodedFrames;
+ FFMPEG_LOG(
+- " decode time %.2f ms averange decode time %.2f ms decoded frames %d\n",
++ "Frame decode finished, time %.2f ms averange decode time %.2f ms "
++ "decoded %d frames\n",
+ decodeTime, mAverangeDecodeTime, mDecodedFrames);
+ #if LIBAVCODEC_VERSION_MAJOR >= 58
+- int frameDuration = mFrame->pkt_duration;
+- if (frameDuration > 0 && frameDuration / 1000.0 < decodeTime) {
+- mDecodedFramesLate++;
+- FFMPEG_LOG(
+- " slow decode: failed to decode in time, frame duration %.2f ms, "
+- "decode time %.2f\n",
+- frameDuration / 1000.0, decodeTime);
+- FFMPEG_LOG(" all decoded frames / late decoded frames %d/%d\n",
+- mDecodedFrames, mDecodedFramesLate);
++ if (mFrame->pkt_duration > 0) {
++ // Switch frame duration to ms
++ float frameDuration = mFrame->pkt_duration / 1000.0f;
++ if (frameDuration < decodeTime) {
++ PROFILER_MARKER_TEXT("FFmpegVideoDecoder::DoDecode", MEDIA_PLAYBACK, {},
++ "frame decode takes too long");
++ mDecodedFramesLate++;
++ if (frameDuration < mAverangeDecodeTime) {
++ mMissedDecodeInAverangeTime++;
++ }
++ FFMPEG_LOG(
++ " slow decode: failed to decode in time, frame duration %.2f ms, "
++ "decode time %.2f\n",
++ frameDuration, decodeTime);
++ FFMPEG_LOG(" frames: all decoded %d late decoded %d over averange %d\n",
++ mDecodedFrames, mDecodedFramesLate,
++ mMissedDecodeInAverangeTime);
++ }
+ }
+ #endif
+ }
+
+ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
+@@ -866,10 +881,18 @@
+ decodeStart = TimeStamp::Now();
+
+ MediaResult rv;
+ # ifdef MOZ_WAYLAND_USE_VAAPI
+ if (IsHardwareAccelerated()) {
++ if (mMissedDecodeInAverangeTime > HW_DECODE_LATE_FRAMES) {
++ PROFILER_MARKER_TEXT("FFmpegVideoDecoder::DoDecode", MEDIA_PLAYBACK, {},
++ "Fallback to SW decode");
++ FFMPEG_LOG(" HW decoding is slow, switch back to SW decode");
++ return MediaResult(
++ NS_ERROR_DOM_MEDIA_DECODE_ERR,
++ RESULT_DETAIL("HW decoding is slow, switch back to SW decode"));
++ }
+ rv = CreateImageVAAPI(mFrame->pkt_pos, GetFramePts(mFrame),
+ mFrame->pkt_duration, aResults);
+ // If VA-API playback failed, just quit. Decoder is going to be restarted
+ // without VA-API.
+ if (NS_FAILED(rv)) {
+@@ -1129,11 +1152,11 @@
+ }
+
+ MediaResult FFmpegVideoDecoder<LIBAV_VER>::CreateImageVAAPI(
+ int64_t aOffset, int64_t aPts, int64_t aDuration,
+ MediaDataDecoder::DecodedData& aResults) {
+- FFMPEG_LOG("VA-API Got one frame output with pts=%" PRId64 "dts=%" PRId64
++ FFMPEG_LOG("VA-API Got one frame output with pts=%" PRId64 " dts=%" PRId64
+ " duration=%" PRId64 " opaque=%" PRId64,
+ aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque);
+
+ VADRMPRIMESurfaceDescriptor vaDesc;
+ if (!GetVAAPISurfaceDescriptor(&vaDesc)) {
+
diff --git a/D145966.diff b/D145966.diff
new file mode 100644
index 0000000..2ecfaec
--- /dev/null
+++ b/D145966.diff
@@ -0,0 +1,20 @@
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+@@ -780,12 +780,13 @@
+ mDecodedFrames++;
+ float decodeTime = (TimeStamp::Now() - aDecodeStart).ToMilliseconds();
+ mAverangeDecodeTime =
+ (mAverangeDecodeTime * (mDecodedFrames - 1) + decodeTime) /
+ mDecodedFrames;
+- FFMPEG_LOG(" averange frame decode time %.2f ms decoded frames %d\n",
+- mAverangeDecodeTime, mDecodedFrames);
++ FFMPEG_LOG(
++ " decode time %.2f ms averange decode time %.2f ms decoded frames %d\n",
++ decodeTime, mAverangeDecodeTime, mDecodedFrames);
+ #if LIBAVCODEC_VERSION_MAJOR >= 58
+ int frameDuration = mFrame->pkt_duration;
+ if (frameDuration > 0 && frameDuration / 1000.0 < decodeTime) {
+ mDecodedFramesLate++;
+ FFMPEG_LOG(
+
diff --git a/D146084.diff b/D146084.diff
new file mode 100644
index 0000000..8ed2c28
--- /dev/null
+++ b/D146084.diff
@@ -0,0 +1,17 @@
+diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh
+--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
++++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
+@@ -57,10 +57,12 @@
+ uint64_t[] modifier;
+ uint32_t flags;
+ FileDescriptor[] fds;
+ uint32_t[] width;
+ uint32_t[] height;
++ uint32_t[] widthAligned;
++ uint32_t[] heightAligned;
+ uint32_t[] format;
+ uint32_t[] strides;
+ uint32_t[] offsets;
+ YUVColorSpace yUVColorSpace;
+ ColorRange colorRange;
+
diff --git a/D146085.diff b/D146085.diff
new file mode 100644
index 0000000..6b037f6
--- /dev/null
+++ b/D146085.diff
@@ -0,0 +1,205 @@
+diff --git a/widget/gtk/DMABufSurface.h b/widget/gtk/DMABufSurface.h
+--- a/widget/gtk/DMABufSurface.h
++++ b/widget/gtk/DMABufSurface.h
+@@ -275,11 +275,11 @@
+ static already_AddRefed<DMABufSurfaceYUV> CreateYUVSurface(
+ int aWidth, int aHeight, void** aPixelData = nullptr,
+ int* aLineSizes = nullptr);
+
+ static already_AddRefed<DMABufSurfaceYUV> CreateYUVSurface(
+- const VADRMPRIMESurfaceDescriptor& aDesc);
++ const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight);
+
+ bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor);
+
+ DMABufSurfaceYUV* GetAsDMABufSurfaceYUV() { return this; };
+
+@@ -304,11 +304,12 @@
+ mozilla::gfx::YUVColorSpace GetYUVColorSpace() { return mColorSpace; }
+
+ DMABufSurfaceYUV();
+
+ bool UpdateYUVData(void** aPixelData, int* aLineSizes);
+- bool UpdateYUVData(const VADRMPRIMESurfaceDescriptor& aDesc);
++ bool UpdateYUVData(const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth,
++ int aHeight);
+
+ bool VerifyTextureCreation();
+
+ private:
+ ~DMABufSurfaceYUV();
+@@ -329,10 +330,15 @@
+ bool CreateEGLImage(mozilla::gl::GLContext* aGLContext, int aPlane);
+ void ReleaseEGLImages(mozilla::gl::GLContext* aGLContext);
+
+ int mWidth[DMABUF_BUFFER_PLANES];
+ int mHeight[DMABUF_BUFFER_PLANES];
++ // Aligned size of the surface imported from VADRMPRIMESurfaceDescriptor.
++ // It's used only internally to create EGLImage as some GL drivers
++ // needs that (Bug 1724385).
++ int mWidthAligned[DMABUF_BUFFER_PLANES];
++ int mHeightAligned[DMABUF_BUFFER_PLANES];
+ EGLImageKHR mEGLImage[DMABUF_BUFFER_PLANES];
+ GLuint mTexture[DMABUF_BUFFER_PLANES];
+ mozilla::gfx::YUVColorSpace mColorSpace =
+ mozilla::gfx::YUVColorSpace::Default;
+ };
+diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp
+--- a/widget/gtk/DMABufSurface.cpp
++++ b/widget/gtk/DMABufSurface.cpp
+@@ -479,13 +479,13 @@
+ if (mGlobalRefCountFd) {
+ refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCountFd));
+ }
+
+ aOutDescriptor = SurfaceDescriptorDMABuf(
+- mSurfaceType, modifiers, mGbmBufferFlags, fds, width, height, format,
+- strides, offsets, GetYUVColorSpace(), mColorRange, fenceFDs, mUID,
+- refCountFDs);
++ mSurfaceType, modifiers, mGbmBufferFlags, fds, width, height, width,
++ height, format, strides, offsets, GetYUVColorSpace(), mColorRange,
++ fenceFDs, mUID, refCountFDs);
+ return true;
+ }
+
+ bool DMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext, int aPlane) {
+ MOZ_ASSERT(!mEGLImage && !mTexture, "EGLImage is already created!");
+@@ -807,15 +807,15 @@
+ }
+ return surf.forget();
+ }
+
+ already_AddRefed<DMABufSurfaceYUV> DMABufSurfaceYUV::CreateYUVSurface(
+- const VADRMPRIMESurfaceDescriptor& aDesc) {
++ const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) {
+ RefPtr<DMABufSurfaceYUV> surf = new DMABufSurfaceYUV();
+ LOGDMABUF(("DMABufSurfaceYUV::CreateYUVSurface() UID %d from desc\n",
+ surf->GetUID()));
+- if (!surf->UpdateYUVData(aDesc)) {
++ if (!surf->UpdateYUVData(aDesc, aWidth, aHeight)) {
+ return nullptr;
+ }
+ return surf.forget();
+ }
+
+@@ -829,11 +829,16 @@
+ }
+ return surf.forget();
+ }
+
+ DMABufSurfaceYUV::DMABufSurfaceYUV()
+- : DMABufSurface(SURFACE_NV12), mWidth(), mHeight(), mTexture() {
++ : DMABufSurface(SURFACE_NV12),
++ mWidth(),
++ mHeight(),
++ mWidthAligned(),
++ mHeightAligned(),
++ mTexture() {
+ for (int i = 0; i < DMABUF_BUFFER_PLANES; i++) {
+ mEGLImage[i] = LOCAL_EGL_NO_IMAGE;
+ }
+ }
+
+@@ -870,11 +875,12 @@
+ close(mDmabufFds[aPlane]);
+ mDmabufFds[aPlane] = -1;
+ }
+ }
+
+-bool DMABufSurfaceYUV::UpdateYUVData(const VADRMPRIMESurfaceDescriptor& aDesc) {
++bool DMABufSurfaceYUV::UpdateYUVData(const VADRMPRIMESurfaceDescriptor& aDesc,
++ int aWidth, int aHeight) {
+ if (aDesc.num_layers > DMABUF_BUFFER_PLANES ||
+ aDesc.num_objects > DMABUF_BUFFER_PLANES) {
+ return false;
+ }
+
+@@ -907,12 +913,14 @@
+
+ mBufferModifiers[i] = aDesc.objects[object].drm_format_modifier;
+ mDrmFormats[i] = aDesc.layers[i].drm_format;
+ mOffsets[i] = aDesc.layers[i].offset[0];
+ mStrides[i] = aDesc.layers[i].pitch[0];
+- mWidth[i] = aDesc.width >> i;
+- mHeight[i] = aDesc.height >> i;
++ mWidthAligned[i] = aDesc.width >> i;
++ mHeightAligned[i] = aDesc.height >> i;
++ mWidth[i] = aWidth >> i;
++ mHeight[i] = aHeight >> i;
+
+ LOGDMABUF((" plane %d size %d x %d format %x", i, mWidth[i], mHeight[i],
+ mDrmFormats[i]));
+ }
+
+@@ -1044,10 +1052,12 @@
+ strerror(errno)));
+ return false;
+ }
+ mWidth[i] = aDesc.width()[i];
+ mHeight[i] = aDesc.height()[i];
++ mWidthAligned[i] = aDesc.widthAligned()[i];
++ mHeightAligned[i] = aDesc.heightAligned()[i];
+ mDrmFormats[i] = aDesc.format()[i];
+ mStrides[i] = aDesc.strides()[i];
+ mOffsets[i] = aDesc.offsets()[i];
+ mBufferModifiers[i] = aDesc.modifier()[i];
+ LOGDMABUF((" plane %d fd %d size %d x %d format %x", i, mDmabufFds[i],
+@@ -1072,10 +1082,12 @@
+
+ bool DMABufSurfaceYUV::Serialize(
+ mozilla::layers::SurfaceDescriptor& aOutDescriptor) {
+ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> width;
+ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> height;
++ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> widthBytes;
++ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> heightBytes;
+ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> format;
+ AutoTArray<ipc::FileDescriptor, DMABUF_BUFFER_PLANES> fds;
+ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> strides;
+ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> offsets;
+ AutoTArray<uint64_t, DMABUF_BUFFER_PLANES> modifiers;
+@@ -1090,10 +1102,12 @@
+ }
+
+ for (int i = 0; i < mBufferPlaneCount; i++) {
+ width.AppendElement(mWidth[i]);
+ height.AppendElement(mHeight[i]);
++ widthBytes.AppendElement(mWidthAligned[i]);
++ heightBytes.AppendElement(mHeightAligned[i]);
+ format.AppendElement(mDrmFormats[i]);
+ fds.AppendElement(ipc::FileDescriptor(mDmabufFds[i]));
+ strides.AppendElement(mStrides[i]);
+ offsets.AppendElement(mOffsets[i]);
+ modifiers.AppendElement(mBufferModifiers[i]);
+@@ -1108,12 +1122,13 @@
+ if (mGlobalRefCountFd) {
+ refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCountFd));
+ }
+
+ aOutDescriptor = SurfaceDescriptorDMABuf(
+- mSurfaceType, modifiers, 0, fds, width, height, format, strides, offsets,
+- GetYUVColorSpace(), mColorRange, fenceFDs, mUID, refCountFDs);
++ mSurfaceType, modifiers, 0, fds, width, height, widthBytes, heightBytes,
++ format, strides, offsets, GetYUVColorSpace(), mColorRange, fenceFDs, mUID,
++ refCountFDs);
+ return true;
+ }
+
+ bool DMABufSurfaceYUV::CreateEGLImage(GLContext* aGLContext, int aPlane) {
+ LOGDMABUF(
+@@ -1131,13 +1146,13 @@
+ return false;
+ }
+
+ nsTArray<EGLint> attribs;
+ attribs.AppendElement(LOCAL_EGL_WIDTH);
+- attribs.AppendElement(mWidth[aPlane]);
++ attribs.AppendElement(mWidthAligned[aPlane]);
+ attribs.AppendElement(LOCAL_EGL_HEIGHT);
+- attribs.AppendElement(mHeight[aPlane]);
++ attribs.AppendElement(mHeightAligned[aPlane]);
+ attribs.AppendElement(LOCAL_EGL_LINUX_DRM_FOURCC_EXT);
+ attribs.AppendElement(mDrmFormats[aPlane]);
+ #define ADD_PLANE_ATTRIBS_NV12(plane_idx) \
+ attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_FD_EXT); \
+ attribs.AppendElement(mDmabufFds[aPlane]); \
+
diff --git a/D146086.diff b/D146086.diff
new file mode 100644
index 0000000..c6790ad
--- /dev/null
+++ b/D146086.diff
@@ -0,0 +1,65 @@
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h
+@@ -112,12 +112,13 @@
+ public:
+ VideoFramePool();
+ ~VideoFramePool();
+
+ RefPtr<VideoFrameSurface<LIBAV_VER>> GetVideoFrameSurface(
+- VADRMPRIMESurfaceDescriptor& aVaDesc, AVCodecContext* aAVCodecContext,
+- AVFrame* aAVFrame, FFmpegLibWrapper* aLib);
++ VADRMPRIMESurfaceDescriptor& aVaDesc, int aWidth, int aHeight,
++ AVCodecContext* aAVCodecContext, AVFrame* aAVFrame,
++ FFmpegLibWrapper* aLib);
+ void ReleaseUnusedVAAPIFrames();
+
+ private:
+ RefPtr<VideoFrameSurface<LIBAV_VER>> GetFreeVideoFrameSurface();
+
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp
+@@ -111,12 +111,13 @@
+ return nullptr;
+ }
+
+ RefPtr<VideoFrameSurface<LIBAV_VER>>
+ VideoFramePool<LIBAV_VER>::GetVideoFrameSurface(
+- VADRMPRIMESurfaceDescriptor& aVaDesc, AVCodecContext* aAVCodecContext,
+- AVFrame* aAVFrame, FFmpegLibWrapper* aLib) {
++ VADRMPRIMESurfaceDescriptor& aVaDesc, int aWidth, int aHeight,
++ AVCodecContext* aAVCodecContext, AVFrame* aAVFrame,
++ FFmpegLibWrapper* aLib) {
+ if (aVaDesc.fourcc != VA_FOURCC_NV12 && aVaDesc.fourcc != VA_FOURCC_YV12 &&
+ aVaDesc.fourcc != VA_FOURCC_P010) {
+ FFMPEG_LOG("Unsupported VA-API surface format %d", aVaDesc.fourcc);
+ return nullptr;
+ }
+@@ -124,11 +125,11 @@
+ MutexAutoLock lock(mSurfaceLock);
+ RefPtr<VideoFrameSurface<LIBAV_VER>> videoSurface =
+ GetFreeVideoFrameSurface();
+ if (!videoSurface) {
+ RefPtr<DMABufSurfaceYUV> surface =
+- DMABufSurfaceYUV::CreateYUVSurface(aVaDesc);
++ DMABufSurfaceYUV::CreateYUVSurface(aVaDesc, aWidth, aHeight);
+ if (!surface) {
+ return nullptr;
+ }
+ FFMPEG_LOG("Created new VA-API DMABufSurface UID = %d", surface->GetUID());
+ RefPtr<VideoFrameSurface<LIBAV_VER>> surf =
+@@ -142,11 +143,11 @@
+ }
+ videoSurface = surf;
+ mDMABufSurfaces.AppendElement(std::move(surf));
+ } else {
+ RefPtr<DMABufSurfaceYUV> surface = videoSurface->GetDMABufSurface();
+- if (!surface->UpdateYUVData(aVaDesc)) {
++ if (!surface->UpdateYUVData(aVaDesc, aWidth, aHeight)) {
+ return nullptr;
+ }
+ FFMPEG_LOG("Reusing VA-API DMABufSurface UID = %d", surface->GetUID());
+ }
+ videoSurface->LockVAAPIData(aAVCodecContext, aAVFrame, aLib);
+
diff --git a/D146087.diff b/D146087.diff
new file mode 100644
index 0000000..d5dcf9d
--- /dev/null
+++ b/D146087.diff
@@ -0,0 +1,19 @@
+diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
++++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+@@ -1164,12 +1164,12 @@
+ NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("Unable to get frame by vaExportSurfaceHandle()"));
+ }
+
+ MOZ_ASSERT(mTaskQueue->IsOnCurrentThread());
+- auto surface = mVideoFramePool->GetVideoFrameSurface(vaDesc, mCodecContext,
+- mFrame, mLib);
++ auto surface = mVideoFramePool->GetVideoFrameSurface(
++ vaDesc, mFrame->width, mFrame->height, mCodecContext, mFrame, mLib);
+ if (!surface) {
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("VAAPI dmabuf allocation error"));
+ }
+ surface->SetYUVColorSpace(GetFrameColorSpace());
+
diff --git a/D147420.diff b/D147420.diff
new file mode 100644
index 0000000..1ee3af1
--- /dev/null
+++ b/D147420.diff
@@ -0,0 +1,179 @@
+diff -up firefox-101.0/gfx/gl/GLContextEGL.h.D147420.diff firefox-101.0/gfx/gl/GLContextEGL.h
+--- firefox-101.0/gfx/gl/GLContextEGL.h.D147420.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/gl/GLContextEGL.h 2022-06-07 09:01:17.487787806 +0200
+@@ -106,6 +106,9 @@ class GLContextEGL final : public GLCont
+ static RefPtr<GLContextEGL> CreateEGLPBufferOffscreenContextImpl(
+ std::shared_ptr<EglDisplay>, const GLContextCreateDesc&,
+ const gfx::IntSize& size, bool aUseGles, nsACString* const out_FailureId);
++ static RefPtr<GLContextEGL> CreateEGLSurfacelessContext(
++ const std::shared_ptr<EglDisplay> display,
++ const GLContextCreateDesc& desc, nsACString* const out_failureId);
+
+ static EGLSurface CreateEGLSurfaceForCompositorWidget(
+ widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig);
+diff -up firefox-101.0/gfx/gl/GLContextProviderEGL.cpp.D147420.diff firefox-101.0/gfx/gl/GLContextProviderEGL.cpp
+--- firefox-101.0/gfx/gl/GLContextProviderEGL.cpp.D147420.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/gl/GLContextProviderEGL.cpp 2022-06-07 09:01:17.487787806 +0200
+@@ -1190,16 +1190,42 @@ RefPtr<GLContextEGL> GLContextEGL::Creat
+ }
+
+ /*static*/
++RefPtr<GLContextEGL> GLContextEGL::CreateEGLSurfacelessContext(
++ const std::shared_ptr<EglDisplay> display, const GLContextCreateDesc& desc,
++ nsACString* const out_failureId) {
++ const EGLConfig config = {};
++ auto fullDesc = GLContextDesc{desc};
++ fullDesc.isOffscreen = true;
++ RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(
++ display, fullDesc, config, EGL_NO_SURFACE, false, out_failureId);
++ if (!gl) {
++ NS_WARNING("Failed to create surfaceless GL context");
++ return nullptr;
++ }
++ return gl;
++}
++
++/*static*/
+ already_AddRefed<GLContext> GLContextProviderEGL::CreateHeadless(
+ const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+ const auto display = DefaultEglDisplay(out_failureId);
+ if (!display) {
+ return nullptr;
+ }
+- mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
+- auto ret = GLContextEGL::CreateEGLPBufferOffscreenContext(
+- display, desc, dummySize, out_failureId);
+- return ret.forget();
++ RefPtr<GLContextEGL> gl;
++#ifdef MOZ_WAYLAND
++ if (!gdk_display_get_default() &&
++ display->IsExtensionSupported(EGLExtension::MESA_platform_surfaceless)) {
++ gl =
++ GLContextEGL::CreateEGLSurfacelessContext(display, desc, out_failureId);
++ } else
++#endif
++ {
++ mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
++ gl = GLContextEGL::CreateEGLPBufferOffscreenContext(
++ display, desc, dummySize, out_failureId);
++ }
++ return gl.forget();
+ }
+
+ // Don't want a global context on Android as 1) share groups across 2 threads
+diff -up firefox-101.0/gfx/gl/GLDefs.h.D147420.diff firefox-101.0/gfx/gl/GLDefs.h
+--- firefox-101.0/gfx/gl/GLDefs.h.D147420.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/gl/GLDefs.h 2022-06-07 09:01:17.487787806 +0200
+@@ -104,6 +104,9 @@ bool CheckContextLost(const GLContext* g
+ // EGL_ANGLE_image_d3d11_texture
+ #define LOCAL_EGL_D3D11_TEXTURE_ANGLE 0x3484
+
++// EGL_MESA_platform_surfaceless
++#define LOCAL_EGL_PLATFORM_SURFACELESS_MESA 0x31DD
++
+ // clang-format on
+
+ #endif
+diff -up firefox-101.0/gfx/gl/GLLibraryEGL.cpp.D147420.diff firefox-101.0/gfx/gl/GLLibraryEGL.cpp
+--- firefox-101.0/gfx/gl/GLLibraryEGL.cpp.D147420.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/gl/GLLibraryEGL.cpp 2022-06-07 09:03:04.077349997 +0200
+@@ -82,7 +82,8 @@ static const char* sEGLExtensionNames[]
+ "EGL_KHR_swap_buffers_with_damage",
+ "EGL_EXT_buffer_age",
+ "EGL_KHR_partial_update",
+- "EGL_NV_robustness_video_memory_purge"};
++ "EGL_NV_robustness_video_memory_purge",
++ "EGL_MESA_platform_surfaceless"};
+
+ PRLibrary* LoadApitraceLibrary() {
+ const char* path = nullptr;
+@@ -151,6 +152,19 @@ static std::shared_ptr<EglDisplay> GetAn
+ return EglDisplay::Create(egl, display, false, aProofOfLock);
+ }
+
++#ifdef MOZ_WAYLAND
++static std::shared_ptr<EglDisplay> GetAndInitSurfacelessDisplay(
++ GLLibraryEGL& egl, const StaticMutexAutoLock& aProofOfLock) {
++ const EGLAttrib attrib_list[] = {LOCAL_EGL_NONE};
++ const EGLDisplay display = egl.fGetPlatformDisplay(
++ LOCAL_EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, attrib_list);
++ if (display == EGL_NO_DISPLAY) {
++ return nullptr;
++ }
++ return EglDisplay::Create(egl, display, true, aProofOfLock);
++}
++#endif
++
+ static std::shared_ptr<EglDisplay> GetAndInitWARPDisplay(
+ GLLibraryEGL& egl, void* displayType,
+ const StaticMutexAutoLock& aProofOfLock) {
+@@ -629,6 +643,11 @@ bool GLLibraryEGL::Init(nsACString* cons
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
++ {
++ const SymLoadStruct symbols[] = {SYMBOL(GetPlatformDisplay),
++ END_OF_SYMBOLS};
++ (void)fnLoadSymbols(symbols);
++ }
+
+ return true;
+ }
+@@ -806,7 +825,9 @@ std::shared_ptr<EglDisplay> GLLibraryEGL
+ #ifdef MOZ_WAYLAND
+ // Some drivers doesn't support EGL_DEFAULT_DISPLAY
+ GdkDisplay* gdkDisplay = gdk_display_get_default();
+- if (widget::GdkIsWaylandDisplay(gdkDisplay)) {
++ if (!gdkDisplay) {
++ ret = GetAndInitSurfacelessDisplay(*this, aProofOfLock);
++ } else if (widget::GdkIsWaylandDisplay(gdkDisplay)) {
+ nativeDisplay = widget::WaylandDisplayGetWLDisplay(gdkDisplay);
+ if (!nativeDisplay) {
+ NS_WARNING("Failed to get wl_display.");
+@@ -814,7 +835,9 @@ std::shared_ptr<EglDisplay> GLLibraryEGL
+ }
+ }
+ #endif
+- ret = GetAndInitDisplay(*this, nativeDisplay, aProofOfLock);
++ if (!ret) {
++ ret = GetAndInitDisplay(*this, nativeDisplay, aProofOfLock);
++ }
+ }
+
+ if (!ret) {
+diff -up firefox-101.0/gfx/gl/GLLibraryEGL.h.D147420.diff firefox-101.0/gfx/gl/GLLibraryEGL.h
+--- firefox-101.0/gfx/gl/GLLibraryEGL.h.D147420.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/gl/GLLibraryEGL.h 2022-06-07 09:01:17.487787806 +0200
+@@ -107,6 +107,7 @@ enum class EGLExtension {
+ EXT_buffer_age,
+ KHR_partial_update,
+ NV_robustness_video_memory_purge,
++ MESA_platform_surfaceless,
+ Max
+ };
+
+diff -up firefox-101.0/widget/gtk/DMABufSurface.cpp.D147420.diff firefox-101.0/widget/gtk/DMABufSurface.cpp
+--- firefox-101.0/widget/gtk/DMABufSurface.cpp.D147420.diff 2022-06-07 09:01:17.486787773 +0200
++++ firefox-101.0/widget/gtk/DMABufSurface.cpp 2022-06-07 09:01:17.487787806 +0200
+@@ -1259,7 +1259,7 @@ bool DMABufSurfaceYUV::VerifyTextureCrea
+ nsCString discardFailureId;
+ sSnapshotContext = GLContextProvider::CreateHeadless({}, &discardFailureId);
+ if (!sSnapshotContext) {
+- NS_WARNING("Failed to create snapshot GLContext");
++ LOGDMABUF((" failed to create snapshot GLContext"));
+ return false;
+ }
+ }
+@@ -1268,10 +1268,12 @@ bool DMABufSurfaceYUV::VerifyTextureCrea
+
+ for (int i = 0; i < mBufferPlaneCount; i++) {
+ if (!CreateEGLImage(sSnapshotContext, i)) {
++ LOGDMABUF((" failed to create EGL image!"));
+ return false;
+ }
+ }
+
++ LOGDMABUF((" success"));
+ return true;
+ }
+
diff --git a/D147635.diff b/D147635.diff
new file mode 100644
index 0000000..1d4bb58
--- /dev/null
+++ b/D147635.diff
@@ -0,0 +1,125 @@
+diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h
+--- a/gfx/gl/GLLibraryEGL.h
++++ b/gfx/gl/GLLibraryEGL.h
+@@ -106,10 +106,13 @@
+ KHR_swap_buffers_with_damage,
+ EXT_buffer_age,
+ KHR_partial_update,
+ NV_robustness_video_memory_purge,
+ MESA_platform_surfaceless,
++ EXT_image_dma_buf_import,
++ EXT_image_dma_buf_import_modifiers,
++ MESA_image_dma_buf_export,
+ Max
+ };
+
+ // -
+
+@@ -461,10 +464,23 @@
+ // EGL_KHR_partial_update
+ EGLBoolean fSetDamageRegion(EGLDisplay dpy, EGLSurface surface,
+ const EGLint* rects, EGLint n_rects) {
+ WRAP(fSetDamageRegion(dpy, surface, rects, n_rects));
+ }
++ // EGL_MESA_image_dma_buf_export
++ EGLBoolean fExportDMABUFImageQuery(EGLDisplay dpy, EGLImage image,
++ int* fourcc, int* num_planes,
++ uint64_t* modifiers) {
++ WRAP(
++ fExportDMABUFImageQueryMESA(dpy, image, fourcc, num_planes, modifiers));
++ }
++ EGLBoolean fExportDMABUFImage(EGLDisplay dpy, EGLImage image, int* fds,
++ EGLint* strides, EGLint* offsets) {
++ WRAP(fExportDMABUFImageMESA(dpy, image, fds, strides, offsets));
++ }
++
++#undef WRAP
+
+ #undef WRAP
+ #undef PROFILE_CALL
+ #undef BEFORE_CALL
+ #undef AFTER_CALL
+@@ -593,10 +609,22 @@
+ EGLBoolean(GLAPIENTRY* fSetDamageRegion)(EGLDisplay dpy, EGLSurface surface,
+ const EGLint* rects,
+ EGLint n_rects);
+ EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)(
+ const struct AHardwareBuffer* buffer);
++
++ // EGL_MESA_image_dma_buf_export
++ EGLBoolean(GLAPIENTRY* fExportDMABUFImageQueryMESA)(EGLDisplay dpy,
++ EGLImage image,
++ int* fourcc,
++ int* num_planes,
++ uint64_t* modifiers);
++ EGLBoolean(GLAPIENTRY* fExportDMABUFImageMESA)(EGLDisplay dpy,
++ EGLImage image, int* fds,
++ EGLint* strides,
++ EGLint* offsets);
++
+ } mSymbols = {};
+ };
+
+ class EglDisplay final {
+ public:
+@@ -852,10 +880,23 @@
+ EGLBoolean fSetDamageRegion(EGLSurface surface, const EGLint* rects,
+ EGLint n_rects) {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update));
+ return mLib->fSetDamageRegion(mDisplay, surface, rects, n_rects);
+ }
++
++ EGLBoolean fExportDMABUFImageQuery(EGLImage image, int* fourcc,
++ int* num_planes,
++ uint64_t* modifiers) const {
++ MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export));
++ return mLib->fExportDMABUFImageQuery(mDisplay, image, fourcc, num_planes,
++ modifiers);
++ }
++ EGLBoolean fExportDMABUFImage(EGLImage image, int* fds, EGLint* strides,
++ EGLint* offsets) const {
++ MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export));
++ return mLib->fExportDMABUFImage(mDisplay, image, fds, strides, offsets);
++ }
+ };
+
+ } /* namespace gl */
+ } /* namespace mozilla */
+
+diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp
+--- a/gfx/gl/GLLibraryEGL.cpp
++++ b/gfx/gl/GLLibraryEGL.cpp
+@@ -82,11 +82,14 @@
+ "EGL_EXT_swap_buffers_with_damage",
+ "EGL_KHR_swap_buffers_with_damage",
+ "EGL_EXT_buffer_age",
+ "EGL_KHR_partial_update",
+ "EGL_NV_robustness_video_memory_purge",
+- "EGL_MESA_platform_surfaceless"};
++ "EGL_MESA_platform_surfaceless",
++ "EGL_EXT_image_dma_buf_import",
++ "EGL_EXT_image_dma_buf_import_modifiers",
++ "EGL_MESA_image_dma_buf_export"};
+
+ PRLibrary* LoadApitraceLibrary() {
+ const char* path = nullptr;
+
+ #ifdef ANDROID
+@@ -647,10 +650,16 @@
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(GetPlatformDisplay),
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
++ {
++ const SymLoadStruct symbols[] = {SYMBOL(ExportDMABUFImageQueryMESA),
++ SYMBOL(ExportDMABUFImageMESA),
++ END_OF_SYMBOLS};
++ (void)fnLoadSymbols(symbols);
++ }
+
+ return true;
+ }
+
+ // -
+
diff --git a/D147636.diff b/D147636.diff
new file mode 100644
index 0000000..52462f2
--- /dev/null
+++ b/D147636.diff
@@ -0,0 +1,278 @@
+diff --git a/widget/gtk/DMABufSurface.h b/widget/gtk/DMABufSurface.h
+--- a/widget/gtk/DMABufSurface.h
++++ b/widget/gtk/DMABufSurface.h
+@@ -173,13 +173,13 @@
+ SurfaceType mSurfaceType;
+ uint64_t mBufferModifiers[DMABUF_BUFFER_PLANES];
+
+ int mBufferPlaneCount;
+ int mDmabufFds[DMABUF_BUFFER_PLANES];
+- uint32_t mDrmFormats[DMABUF_BUFFER_PLANES];
+- uint32_t mStrides[DMABUF_BUFFER_PLANES];
+- uint32_t mOffsets[DMABUF_BUFFER_PLANES];
++ int32_t mDrmFormats[DMABUF_BUFFER_PLANES];
++ int32_t mStrides[DMABUF_BUFFER_PLANES];
++ int32_t mOffsets[DMABUF_BUFFER_PLANES];
+
+ struct gbm_bo* mGbmBufferObject[DMABUF_BUFFER_PLANES];
+ void* mMappedRegion[DMABUF_BUFFER_PLANES];
+ void* mMappedRegionData[DMABUF_BUFFER_PLANES];
+ uint32_t mMappedRegionStride[DMABUF_BUFFER_PLANES];
+@@ -198,10 +198,14 @@
+ class DMABufSurfaceRGBA : public DMABufSurface {
+ public:
+ static already_AddRefed<DMABufSurfaceRGBA> CreateDMABufSurface(
+ int aWidth, int aHeight, int aDMABufSurfaceFlags);
+
++ static already_AddRefed<DMABufSurface> CreateDMABufSurface(
++ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage,
++ int aWidth, int aHeight);
++
+ bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor);
+
+ DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() { return this; }
+
+ void Clear();
+@@ -247,10 +251,12 @@
+ private:
+ ~DMABufSurfaceRGBA();
+
+ bool Create(int aWidth, int aHeight, int aDMABufSurfaceFlags);
+ bool Create(const mozilla::layers::SurfaceDescriptor& aDesc);
++ bool Create(mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage,
++ int aWidth, int aHeight);
+
+ bool ImportSurfaceDescriptor(const mozilla::layers::SurfaceDescriptor& aDesc);
+
+ bool OpenFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock,
+ int aPlane);
+diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp
+--- a/widget/gtk/DMABufSurface.cpp
++++ b/widget/gtk/DMABufSurface.cpp
+@@ -204,10 +204,12 @@
+ }
+ }
+
+ void DMABufSurface::FenceSet() {
+ if (!mGL || !mGL->MakeCurrent()) {
++ MOZ_DIAGNOSTIC_ASSERT(mGL,
++ "DMABufSurface::FenceSet(): missing GL context!");
+ return;
+ }
+ const auto& gle = gl::GLContextEGL::Cast(mGL);
+ const auto& egl = gle->mEgl;
+
+@@ -228,21 +230,23 @@
+ mGL->fFinish();
+ }
+
+ void DMABufSurface::FenceWait() {
+ if (!mGL || mSyncFd < 0) {
++ MOZ_DIAGNOSTIC_ASSERT(mGL,
++ "DMABufSurface::FenceWait() missing GL context!");
+ return;
+ }
+
+ const auto& gle = gl::GLContextEGL::Cast(mGL);
+ const auto& egl = gle->mEgl;
+
+ const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, mSyncFd,
+ LOCAL_EGL_NONE};
+ EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+ if (!sync) {
+- MOZ_ASSERT(false, "Failed to create GLFence!");
++ MOZ_ASSERT(false, "DMABufSurface::FenceWait(): Failed to create GLFence!");
+ // We failed to create GLFence so clear mSyncFd to avoid another try.
+ close(mSyncFd);
+ mSyncFd = -1;
+ return;
+ }
+@@ -338,17 +342,18 @@
+ mGmbFormat = GetDMABufDevice()->GetGbmFormat(mSurfaceFlags & DMABUF_ALPHA);
+ if (!mGmbFormat) {
+ // Requested DRM format is not supported.
+ return false;
+ }
++ mDrmFormats[0] = mGmbFormat->mFormat;
+
+ bool useModifiers = (aDMABufSurfaceFlags & DMABUF_USE_MODIFIERS) &&
+ mGmbFormat->mModifiersCount > 0;
+ if (useModifiers) {
+ LOGDMABUF((" Creating with modifiers\n"));
+ mGbmBufferObject[0] = nsGbmLib::CreateWithModifiers(
+- GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, mGmbFormat->mFormat,
++ GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, mDrmFormats[0],
+ mGmbFormat->mModifiers, mGmbFormat->mModifiersCount);
+ if (mGbmBufferObject[0]) {
+ mBufferModifiers[0] = nsGbmLib::GetModifier(mGbmBufferObject[0]);
+ }
+ }
+@@ -356,11 +361,11 @@
+ if (!mGbmBufferObject[0]) {
+ LOGDMABUF((" Creating without modifiers\n"));
+ mGbmBufferFlags = GBM_BO_USE_LINEAR;
+ mGbmBufferObject[0] =
+ nsGbmLib::Create(GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight,
+- mGmbFormat->mFormat, mGbmBufferFlags);
++ mDrmFormats[0], mGbmBufferFlags);
+ mBufferModifiers[0] = DRM_FORMAT_MOD_INVALID;
+ }
+
+ if (!mGbmBufferObject[0]) {
+ LOGDMABUF((" Failed to create GbmBufferObject\n"));
+@@ -386,22 +391,51 @@
+
+ LOGDMABUF((" Success\n"));
+ return true;
+ }
+
++bool DMABufSurfaceRGBA::Create(mozilla::gl::GLContext* aGLContext,
++ const EGLImageKHR aEGLImage, int aWidth,
++ int aHeight) {
++ LOGDMABUF(("DMABufSurfaceRGBA::Create() from EGLImage UID = %d\n", mUID));
++ if (!aGLContext) {
++ return false;
++ }
++ const auto& gle = gl::GLContextEGL::Cast(aGLContext);
++ const auto& egl = gle->mEgl;
++
++ mGL = aGLContext;
++ mWidth = aWidth;
++ mHeight = aHeight;
++ mEGLImage = aEGLImage;
++ if (!egl->fExportDMABUFImageQuery(mEGLImage, mDrmFormats, &mBufferPlaneCount,
++ mBufferModifiers)) {
++ LOGDMABUF((" ExportDMABUFImageQueryMESA failed, quit\n"));
++ return false;
++ }
++ if (mBufferPlaneCount > DMABUF_BUFFER_PLANES) {
++ LOGDMABUF((" wrong plane count %d, quit\n", mBufferPlaneCount));
++ return false;
++ }
++ if (!egl->fExportDMABUFImage(mEGLImage, mDmabufFds, mStrides, mOffsets)) {
++ LOGDMABUF((" ExportDMABUFImageMESA failed, quit\n"));
++ return false;
++ }
++
++ LOGDMABUF((" imported size %d x %d format %x planes %d", mWidth, mHeight,
++ mDrmFormats[0], mBufferPlaneCount));
++ return true;
++}
++
+ bool DMABufSurfaceRGBA::ImportSurfaceDescriptor(
+ const SurfaceDescriptor& aDesc) {
+ const SurfaceDescriptorDMABuf& desc = aDesc.get_SurfaceDescriptorDMABuf();
+
+ mWidth = desc.width()[0];
+ mHeight = desc.height()[0];
+ mBufferModifiers[0] = desc.modifier()[0];
+- if (mBufferModifiers[0] != DRM_FORMAT_MOD_INVALID) {
+- mGmbFormat = GetDMABufDevice()->GetExactGbmFormat(desc.format()[0]);
+- } else {
+- mDrmFormats[0] = desc.format()[0];
+- }
++ mDrmFormats[0] = desc.format()[0];
+ mBufferPlaneCount = desc.fds().Length();
+ mGbmBufferFlags = desc.flags();
+ MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES);
+ mUID = desc.uid();
+
+@@ -431,10 +465,12 @@
+
+ if (desc.refCount().Length() > 0) {
+ GlobalRefCountImport(desc.refCount()[0].ClonePlatformHandle().release());
+ }
+
++ LOGDMABUF((" imported size %d x %d format %x planes %d", mWidth, mHeight,
++ mDrmFormats[0], mBufferPlaneCount));
+ return true;
+ }
+
+ bool DMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) {
+ return ImportSurfaceDescriptor(aDesc);
+@@ -460,11 +496,11 @@
+ return false;
+ }
+
+ width.AppendElement(mWidth);
+ height.AppendElement(mHeight);
+- format.AppendElement(mGmbFormat->mFormat);
++ format.AppendElement(mDrmFormats[0]);
+ modifiers.AppendElement(mBufferModifiers[0]);
+ for (int i = 0; i < mBufferPlaneCount; i++) {
+ fds.AppendElement(ipc::FileDescriptor(mDmabufFds[i]));
+ strides.AppendElement(mStrides[i]);
+ offsets.AppendElement(mOffsets[i]);
+@@ -486,23 +522,20 @@
+ fenceFDs, mUID, refCountFDs);
+ return true;
+ }
+
+ bool DMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext, int aPlane) {
++ LOGDMABUF(("DMABufSurfaceRGBA::CreateTexture() UID %d\n", mUID));
+ MOZ_ASSERT(!mEGLImage && !mTexture, "EGLImage is already created!");
+
+ nsTArray<EGLint> attribs;
+ attribs.AppendElement(LOCAL_EGL_WIDTH);
+ attribs.AppendElement(mWidth);
+ attribs.AppendElement(LOCAL_EGL_HEIGHT);
+ attribs.AppendElement(mHeight);
+ attribs.AppendElement(LOCAL_EGL_LINUX_DRM_FOURCC_EXT);
+- if (mGmbFormat) {
+- attribs.AppendElement(mGmbFormat->mFormat);
+- } else {
+- attribs.AppendElement(mDrmFormats[0]);
+- }
++ attribs.AppendElement(mDrmFormats[0]);
+ #define ADD_PLANE_ATTRIBS(plane_idx) \
+ { \
+ attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_FD_EXT); \
+ attribs.AppendElement(mDmabufFds[plane_idx]); \
+ attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_OFFSET_EXT); \
+@@ -560,10 +593,11 @@
+
+ return true;
+ }
+
+ void DMABufSurfaceRGBA::ReleaseTextures() {
++ LOGDMABUF(("DMABufSurfaceRGBA::ReleaseTextures() UID %d\n", mUID));
+ FenceDelete();
+
+ if (!mTexture) {
+ return;
+ }
+@@ -618,11 +652,11 @@
+ zwp_linux_buffer_params_v1_add(params, mDmabufFds[0], 0, mOffsets[0],
+ mStrides[0], mBufferModifiers[0] >> 32,
+ mBufferModifiers[0] & 0xffffffff);
+
+ mWlBuffer = zwp_linux_buffer_params_v1_create_immed(
+- params, GetWidth(), GetHeight(), mGmbFormat->mFormat, 0);
++ params, GetWidth(), GetHeight(), mDrmFormats[0], 0);
+
+ CloseFileDescriptors(lockFD);
+
+ return mWlBuffer != nullptr;
+ }
+@@ -806,10 +840,20 @@
+ return nullptr;
+ }
+ return surf.forget();
+ }
+
++already_AddRefed<DMABufSurface> DMABufSurfaceRGBA::CreateDMABufSurface(
++ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, int aWidth,
++ int aHeight) {
++ RefPtr<DMABufSurfaceRGBA> surf = new DMABufSurfaceRGBA();
++ if (!surf->Create(aGLContext, aEGLImage, aWidth, aHeight)) {
++ return nullptr;
++ }
++ return surf.forget();
++}
++
+ already_AddRefed<DMABufSurfaceYUV> DMABufSurfaceYUV::CreateYUVSurface(
+ const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) {
+ RefPtr<DMABufSurfaceYUV> surf = new DMABufSurfaceYUV();
+ LOGDMABUF(("DMABufSurfaceYUV::CreateYUVSurface() UID %d from desc\n",
+ surf->GetUID()));
+
diff --git a/D147637.diff b/D147637.diff
new file mode 100644
index 0000000..0a84b25
--- /dev/null
+++ b/D147637.diff
@@ -0,0 +1,113 @@
+diff -up firefox-101.0/gfx/gl/SharedSurfaceDMABUF.cpp.D147637.diff firefox-101.0/gfx/gl/SharedSurfaceDMABUF.cpp
+--- firefox-101.0/gfx/gl/SharedSurfaceDMABUF.cpp.D147637.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/gl/SharedSurfaceDMABUF.cpp 2022-06-07 09:37:29.361992695 +0200
+@@ -12,22 +12,37 @@
+
+ namespace mozilla::gl {
+
++static bool HasDmaBufExtensions(const GLContextEGL* gl) {
++ const auto& egl = *(gl->mEgl);
++ return egl.IsExtensionSupported(EGLExtension::EXT_image_dma_buf_import) &&
++ egl.IsExtensionSupported(
++ EGLExtension::EXT_image_dma_buf_import_modifiers) &&
++ egl.IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export);
++}
++
+ /*static*/
+ UniquePtr<SharedSurface_DMABUF> SharedSurface_DMABUF::Create(
+ const SharedSurfaceDesc& desc) {
+- const auto flags = static_cast<DMABufSurfaceFlags>(
+- DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA);
+- const RefPtr<DMABufSurface> surface = DMABufSurfaceRGBA::CreateDMABufSurface(
+- desc.size.width, desc.size.height, flags);
+- if (!surface || !surface->CreateTexture(desc.gl)) {
++ const auto& gle = GLContextEGL::Cast(desc.gl);
++ const auto& context = gle->mContext;
++ const auto& egl = *(gle->mEgl);
++
++ if (!HasDmaBufExtensions(gle)) {
+ return nullptr;
+ }
+
+- const auto tex = surface->GetTexture();
+- auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
+- LOCAL_GL_TEXTURE_2D, tex);
++ auto fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
+ if (!fb) return nullptr;
+
++ const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
++ const auto image =
++ egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
++ if (!image) return nullptr;
++
++ const RefPtr<DMABufSurface> surface = DMABufSurfaceRGBA::CreateDMABufSurface(
++ desc.gl, image, desc.size.width, desc.size.height);
++ if (!surface) return nullptr;
++
+ return AsUnique(new SharedSurface_DMABUF(desc, std::move(fb), surface));
+ }
+
+@@ -61,7 +76,7 @@ UniquePtr<SurfaceFactory_DMABUF> Surface
+ }
+
+ auto dmabufFactory = MakeUnique<SurfaceFactory_DMABUF>(gl);
+- if (dmabufFactory->CanCreateSurface()) {
++ if (dmabufFactory->CanCreateSurface(gl)) {
+ return dmabufFactory;
+ }
+
+@@ -71,8 +86,38 @@ UniquePtr<SurfaceFactory_DMABUF> Surface
+ return nullptr;
+ }
+
++bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) {
++ UniquePtr<SharedSurface> test =
++ CreateShared(gfx::IntSize(1, 1));
++ if (!test) {
++ LOGDMABUF((
++ "SurfaceFactory_DMABUF::CanCreateSurface() failed to create surface."));
++ return false;
++ }
++ auto desc = test->ToSurfaceDescriptor();
++ if (!desc) {
++ LOGDMABUF(
++ ("SurfaceFactory_DMABUF::CanCreateSurface() failed to serialize "
++ "surface."));
++ return false;
++ }
++ RefPtr<DMABufSurface> importedSurface =
++ DMABufSurface::CreateDMABufSurface(*desc);
++ if (!importedSurface) {
++ LOGDMABUF((
++ "SurfaceFactory_DMABUF::CanCreateSurface() failed to import surface."));
++ return false;
++ }
++ if (!importedSurface->CreateTexture(&gl)) {
++ LOGDMABUF(
++ ("SurfaceFactory_DMABUF::CanCreateSurface() failed to create texture "
++ "over surface."));
++ return false;
++ }
++ return true;
++}
++
+ SurfaceFactory_DMABUF::SurfaceFactory_DMABUF(GLContext& gl)
+ : SurfaceFactory({&gl, SharedSurfaceType::EGLSurfaceDMABUF,
+ layers::TextureType::DMABUF, true}) {}
+-
+ } // namespace mozilla::gl
+diff -up firefox-101.0/gfx/gl/SharedSurfaceDMABUF.h.D147637.diff firefox-101.0/gfx/gl/SharedSurfaceDMABUF.h
+--- firefox-101.0/gfx/gl/SharedSurfaceDMABUF.h.D147637.diff 2022-06-07 09:31:23.678228010 +0200
++++ firefox-101.0/gfx/gl/SharedSurfaceDMABUF.h 2022-06-07 09:36:39.691512555 +0200
+@@ -59,10 +59,7 @@ class SurfaceFactory_DMABUF : public Sur
+ return SharedSurface_DMABUF::Create(desc);
+ }
+
+- bool CanCreateSurface() {
+- UniquePtr<SharedSurface> test = CreateShared(gfx::IntSize(1, 1));
+- return test != nullptr;
+- }
++ bool CanCreateSurface(GLContext& gl);
+ };
+
+ } // namespace gl
diff --git a/D147720.diff b/D147720.diff
new file mode 100644
index 0000000..9287f44
--- /dev/null
+++ b/D147720.diff
@@ -0,0 +1,73 @@
+diff --git a/widget/gtk/DMABufSurface.h b/widget/gtk/DMABufSurface.h
+--- a/widget/gtk/DMABufSurface.h
++++ b/widget/gtk/DMABufSurface.h
+@@ -146,11 +146,16 @@
+ DMABufSurface(SurfaceType aSurfaceType);
+
+ protected:
+ virtual bool Create(const mozilla::layers::SurfaceDescriptor& aDesc) = 0;
+
++ // Import global ref count from IPC by file descriptor.
+ void GlobalRefCountImport(int aFd);
++ // Export global ref count by file descriptor. This adds global ref count
++ // reference to the surface.
++ // It's used when dmabuf surface is shared with another process via. IPC.
++ int GlobalRefCountExport();
+ void GlobalRefCountDelete();
+
+ void ReleaseDMABuf();
+
+ void* MapInternal(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight,
+diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp
+--- a/widget/gtk/DMABufSurface.cpp
++++ b/widget/gtk/DMABufSurface.cpp
+@@ -105,11 +105,21 @@
+ }
+
+ void DMABufSurface::GlobalRefCountImport(int aFd) {
+ MOZ_ASSERT(!mGlobalRefCountFd);
+ mGlobalRefCountFd = aFd;
+- GlobalRefAdd();
++ MOZ_DIAGNOSTIC_ASSERT(IsGlobalRefSet(),
++ "We're importing unreferenced surface!");
++}
++
++int DMABufSurface::GlobalRefCountExport() {
++ if (mGlobalRefCountFd) {
++ MOZ_DIAGNOSTIC_ASSERT(IsGlobalRefSet(),
++ "We're exporting unreferenced surface!");
++ GlobalRefAdd();
++ }
++ return mGlobalRefCountFd;
+ }
+
+ void DMABufSurface::GlobalRefCountDelete() {
+ if (mGlobalRefCountFd) {
+ GlobalRefRelease();
+@@ -475,11 +485,11 @@
+ if (mSync) {
+ fenceFDs.AppendElement(ipc::FileDescriptor(mSyncFd));
+ }
+
+ if (mGlobalRefCountFd) {
+- refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCountFd));
++ refCountFDs.AppendElement(ipc::FileDescriptor(GlobalRefCountExport()));
+ }
+
+ aOutDescriptor = SurfaceDescriptorDMABuf(
+ mSurfaceType, modifiers, mGbmBufferFlags, fds, width, height, width,
+ height, format, strides, offsets, GetYUVColorSpace(), mColorRange,
+@@ -1118,11 +1128,11 @@
+ if (mSync) {
+ fenceFDs.AppendElement(ipc::FileDescriptor(mSyncFd));
+ }
+
+ if (mGlobalRefCountFd) {
+- refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCountFd));
++ refCountFDs.AppendElement(ipc::FileDescriptor(GlobalRefCountExport()));
+ }
+
+ aOutDescriptor = SurfaceDescriptorDMABuf(
+ mSurfaceType, modifiers, 0, fds, width, height, widthBytes, heightBytes,
+ format, strides, offsets, GetYUVColorSpace(), mColorRange, fenceFDs, mUID,
+
diff --git a/D147874.diff b/D147874.diff
new file mode 100644
index 0000000..f0c57dd
--- /dev/null
+++ b/D147874.diff
@@ -0,0 +1,64 @@
+diff -up firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp.D147874.diff firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp
+--- firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp.D147874.diff 2022-05-27 01:16:54.000000000 +0200
++++ firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp 2022-06-07 11:16:03.791419558 +0200
+@@ -233,13 +233,7 @@ void gfxPlatformGtk::InitDmabufConfig()
+ void gfxPlatformGtk::InitVAAPIConfig() {
+ FeatureState& feature = gfxConfig::GetFeature(Feature::VAAPI);
+ #ifdef MOZ_WAYLAND
+- feature.DisableByDefault(FeatureStatus::Disabled,
+- "VAAPI is disabled by default",
+- "FEATURE_VAAPI_DISABLED"_ns);
+-
+- if (StaticPrefs::media_ffmpeg_vaapi_enabled()) {
+- feature.UserForceEnable("Force enabled by pref");
+- }
++ feature.EnableByDefault();
+
+ nsCString failureId;
+ int32_t status;
+@@ -253,6 +247,10 @@ void gfxPlatformGtk::InitVAAPIConfig() {
+ failureId);
+ }
+
++ if (StaticPrefs::media_ffmpeg_vaapi_enabled()) {
++ feature.UserForceEnable("Force enabled by pref");
++ }
++
+ if (!gfxVars::UseEGL()) {
+ feature.ForceDisable(FeatureStatus::Unavailable, "Requires EGL",
+ "FEATURE_FAILURE_REQUIRES_EGL"_ns);
+diff -up firefox-101.0/widget/gtk/GfxInfo.cpp.D147874.diff firefox-101.0/widget/gtk/GfxInfo.cpp
+--- firefox-101.0/widget/gtk/GfxInfo.cpp.D147874.diff 2022-05-27 01:17:06.000000000 +0200
++++ firefox-101.0/widget/gtk/GfxInfo.cpp 2022-06-07 09:52:54.416701418 +0200
+@@ -843,6 +843,31 @@ const nsTArray<GfxDriverInfo>& GfxInfo::
+ V(495, 44, 0, 0), "FEATURE_FAILURE_NO_GBM", "495.44.0");
+
+ ////////////////////////////////////
++ // FEATURE_VAAPI
++ APPEND_TO_DRIVER_BLOCKLIST_EXT(
++ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
++ DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
++ DeviceFamily::All, nsIGfxInfo::FEATURE_VAAPI,
++ nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
++ V(21, 0, 0, 0), "FEATURE_ROLLOUT_VAAPI_MESA", "Mesa 21.0.0.0");
++
++ // Disable on all NVIDIA hardware
++ APPEND_TO_DRIVER_BLOCKLIST_EXT(
++ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
++ DesktopEnvironment::All, WindowProtocol::All, DriverVendor::All,
++ DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_VAAPI,
++ nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
++ V(0, 0, 0, 0), "FEATURE_FAILURE_VAAPI_NO_LINUX_NVIDIA", "");
++
++ // Disable on all AMD devices not using Mesa.
++ APPEND_TO_DRIVER_BLOCKLIST_EXT(
++ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
++ DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
++ DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_VAAPI,
++ nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
++ V(0, 0, 0, 0), "FEATURE_FAILURE_VAAPI_NO_LINUX_AMD", "");
++
++ ////////////////////////////////////
+ // FEATURE_WEBRENDER_PARTIAL_PRESENT
+ APPEND_TO_DRIVER_BLOCKLIST_EXT(
+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
diff --git a/firefox.spec b/firefox.spec
index 3206448..4d49292 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -163,7 +163,7 @@ ExcludeArch: aarch64
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 101.0
-Release: 1%{?pre_tag}%{?dist}
+Release: 2%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz
@@ -244,6 +244,24 @@ Patch408: mozilla-1663844.patch
Patch415: mozilla-1670333.patch
Patch418: mozilla-1767946-profilemanagersize.patch
+# VA-API fixes
+Patch420: D144284.diff
+Patch421: D147420.diff
+Patch422: D147720.diff
+Patch423: D147874.diff
+Patch424: D146084.diff
+Patch425: D146085.diff
+Patch426: D146086.diff
+Patch427: D146087.diff
+Patch428: D145725.diff
+Patch429: D145966.diff
+Patch430: D145871.diff
+
+# NVIDIA mzbz#1735929
+Patch440: D147635.diff
+Patch441: D147636.diff
+Patch442: D147637.diff
+
# PGO/LTO patches
Patch600: pgo.patch
Patch602: mozilla-1516803.patch
@@ -485,6 +503,26 @@ This package contains results of tests executed during build.
%patch415 -p1 -b .1670333
%patch418 -p1 -b .mozilla-1767946-profilemanagersize
+# VA-API fixes
+%patch420 -p1 -b .D144284.diff
+%patch421 -p1 -b .D147420.diff
+%patch423 -p1 -b .D147874.diff
+%patch424 -p1 -b .D146084.diff
+%patch425 -p1 -b .D146085.diff
+%patch426 -p1 -b .D146086.diff
+%patch427 -p1 -b .D146087.diff
+%patch428 -p1 -b .D145725.diff
+%patch429 -p1 -b .D145966.diff
+%patch430 -p1 -b .D145871.diff
+
+# NVIDIA mzbz#1735929
+%patch440 -p1 -b .D147635.diff
+%patch441 -p1 -b .D147636.diff
+%patch442 -p1 -b .D147637.diff
+
+# More VA-API fixes
+%patch422 -p1 -b .D147720.diff
+
# PGO patches
%if %{build_with_pgo}
%if !%{build_with_clang}
@@ -1057,6 +1095,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Tue Jun 7 2022 Martin Stransky <stransky@redhat.com>- 101.0-2
+- Enabled VA-API by default (+ added VA-API fixes from upstream)
+- Fixed WebGL performance on NVIDIA drivers (mzbz#1735929)
+
* Mon May 30 2022 Martin Stransky <stransky@redhat.com>- 101.0-1
- Updated to 101.0
bgstack15