Bug 1910520 - Add Metal SharedEvent handling around WebRender for compositing IOSurface of WebGPU r=gfx-reviewers,lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D228946
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "ExternalTexture.h"
|
||||
|
||||
#include "mozilla/webgpu/WebGPUParent.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/webgpu/ExternalTextureD3D11.h"
|
||||
#endif
|
||||
@@ -21,19 +23,22 @@ namespace mozilla::webgpu {
|
||||
|
||||
// static
|
||||
UniquePtr<ExternalTexture> ExternalTexture::Create(
|
||||
const ffi::WGPUGlobal* aContext, const ffi::WGPUDeviceId aDeviceId,
|
||||
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
|
||||
const uint32_t aWidth, const uint32_t aHeight,
|
||||
const struct ffi::WGPUTextureFormat aFormat,
|
||||
const ffi::WGPUTextureUsages aUsage) {
|
||||
MOZ_ASSERT(aParent);
|
||||
|
||||
UniquePtr<ExternalTexture> texture;
|
||||
#ifdef XP_WIN
|
||||
texture = ExternalTextureD3D11::Create(aWidth, aHeight, aFormat, aUsage);
|
||||
#elif defined(MOZ_WIDGET_GTK)
|
||||
texture = ExternalTextureDMABuf::Create(aContext, aDeviceId, aWidth, aHeight,
|
||||
auto* context = aParent->GetContext();
|
||||
texture = ExternalTextureDMABuf::Create(context, aDeviceId, aWidth, aHeight,
|
||||
aFormat, aUsage);
|
||||
#elif defined(XP_MACOSX)
|
||||
texture =
|
||||
ExternalTextureMacIOSurface::Create(aWidth, aHeight, aFormat, aUsage);
|
||||
texture = ExternalTextureMacIOSurface::Create(aParent, aDeviceId, aWidth,
|
||||
aHeight, aFormat, aUsage);
|
||||
#endif
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "mozilla/webgpu/ffi/wgpu.h"
|
||||
#include "mozilla/webgpu/WebGPUTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -20,13 +21,14 @@ namespace webgpu {
|
||||
|
||||
class ExternalTextureDMABuf;
|
||||
class ExternalTextureMacIOSurface;
|
||||
class WebGPUParent;
|
||||
|
||||
// A texture that can be used by the WebGPU implementation but is created and
|
||||
// owned by Gecko
|
||||
class ExternalTexture {
|
||||
public:
|
||||
static UniquePtr<ExternalTexture> Create(
|
||||
const ffi::WGPUGlobal* aContext, const ffi::WGPUDeviceId aDeviceId,
|
||||
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
|
||||
const uint32_t aWidth, const uint32_t aHeight,
|
||||
const struct ffi::WGPUTextureFormat aFormat,
|
||||
const ffi::WGPUTextureUsages aUsage);
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/MacIOSurface.h"
|
||||
#include "mozilla/layers/GpuFenceMTLSharedEvent.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/webgpu/WebGPUParent.h"
|
||||
|
||||
namespace mozilla::webgpu {
|
||||
|
||||
// static
|
||||
UniquePtr<ExternalTextureMacIOSurface> ExternalTextureMacIOSurface::Create(
|
||||
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
|
||||
const uint32_t aWidth, const uint32_t aHeight,
|
||||
const struct ffi::WGPUTextureFormat aFormat,
|
||||
const ffi::WGPUTextureUsages aUsage) {
|
||||
@@ -24,18 +27,23 @@ UniquePtr<ExternalTextureMacIOSurface> ExternalTextureMacIOSurface::Create(
|
||||
RefPtr<MacIOSurface> surface =
|
||||
MacIOSurface::CreateIOSurface(aWidth, aHeight, true);
|
||||
if (!surface) {
|
||||
gfxCriticalNoteOnce << "Failed to create MacIOSurface: (" << aWidth << ", "
|
||||
<< aHeight << ")";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return MakeUnique<ExternalTextureMacIOSurface>(aWidth, aHeight, aFormat,
|
||||
aUsage, std::move(surface));
|
||||
return MakeUnique<ExternalTextureMacIOSurface>(
|
||||
aParent, aDeviceId, aWidth, aHeight, aFormat, aUsage, std::move(surface));
|
||||
}
|
||||
|
||||
ExternalTextureMacIOSurface::ExternalTextureMacIOSurface(
|
||||
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
|
||||
const uint32_t aWidth, const uint32_t aHeight,
|
||||
const struct ffi::WGPUTextureFormat aFormat,
|
||||
const ffi::WGPUTextureUsages aUsage, RefPtr<MacIOSurface>&& aSurface)
|
||||
: ExternalTexture(aWidth, aHeight, aFormat, aUsage),
|
||||
mParent(aParent),
|
||||
mDeviceId(aDeviceId),
|
||||
mSurface(std::move(aSurface)) {}
|
||||
|
||||
ExternalTextureMacIOSurface::~ExternalTextureMacIOSurface() {}
|
||||
@@ -51,9 +59,22 @@ uint32_t ExternalTextureMacIOSurface::GetIOSurfaceId() {
|
||||
Maybe<layers::SurfaceDescriptor>
|
||||
ExternalTextureMacIOSurface::ToSurfaceDescriptor(
|
||||
Maybe<gfx::FenceInfo>& aFenceInfo) {
|
||||
MOZ_ASSERT(mSubmissionIndex > 0);
|
||||
|
||||
RefPtr<layers::GpuFence> gpuFence;
|
||||
UniquePtr<ffi::WGPUMetalSharedEventHandle> eventHandle(
|
||||
wgpu_server_get_device_fence_metal_shared_event(mParent->GetContext(),
|
||||
mDeviceId));
|
||||
if (eventHandle) {
|
||||
gpuFence = layers::GpuFenceMTLSharedEvent::Create(std::move(eventHandle),
|
||||
mSubmissionIndex);
|
||||
} else {
|
||||
gfxCriticalNoteOnce << "Failed to get MetalSharedEventHandle";
|
||||
}
|
||||
|
||||
return Some(layers::SurfaceDescriptorMacIOSurface(
|
||||
mSurface->GetIOSurfaceID(), !mSurface->HasAlpha(),
|
||||
mSurface->GetYUVColorSpace()));
|
||||
mSurface->GetYUVColorSpace(), std::move(gpuFence)));
|
||||
}
|
||||
|
||||
void ExternalTextureMacIOSurface::GetSnapshot(const ipc::Shmem& aDestShmem,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define GPU_ExternalTextureMacIOSurface_H_
|
||||
|
||||
#include "mozilla/gfx/FileHandleWrapper.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/webgpu/ExternalTexture.h"
|
||||
|
||||
class MacIOSurface;
|
||||
@@ -18,11 +19,14 @@ namespace webgpu {
|
||||
class ExternalTextureMacIOSurface final : public ExternalTexture {
|
||||
public:
|
||||
static UniquePtr<ExternalTextureMacIOSurface> Create(
|
||||
WebGPUParent* aParent, const ffi::WGPUDeviceId aDeviceId,
|
||||
const uint32_t aWidth, const uint32_t aHeight,
|
||||
const struct ffi::WGPUTextureFormat aFormat,
|
||||
const ffi::WGPUTextureUsages aUsage);
|
||||
|
||||
ExternalTextureMacIOSurface(const uint32_t aWidth, const uint32_t aHeight,
|
||||
ExternalTextureMacIOSurface(WebGPUParent* aParent,
|
||||
const ffi::WGPUDeviceId aDeviceId,
|
||||
const uint32_t aWidth, const uint32_t aHeight,
|
||||
const struct ffi::WGPUTextureFormat aFormat,
|
||||
const ffi::WGPUTextureUsages aUsage,
|
||||
RefPtr<MacIOSurface>&& aSurface);
|
||||
@@ -43,6 +47,8 @@ class ExternalTextureMacIOSurface final : public ExternalTexture {
|
||||
uint32_t GetIOSurfaceId();
|
||||
|
||||
protected:
|
||||
const WeakPtr<WebGPUParent> mParent;
|
||||
const RawId mDeviceId;
|
||||
const RefPtr<MacIOSurface> mSurface;
|
||||
};
|
||||
|
||||
|
||||
@@ -1635,7 +1635,7 @@ std::shared_ptr<ExternalTexture> WebGPUParent::CreateExternalTexture(
|
||||
mExternalTextures.end());
|
||||
|
||||
UniquePtr<ExternalTexture> texture = ExternalTexture::Create(
|
||||
mContext.get(), aDeviceId, aWidth, aHeight, aFormat, aUsage);
|
||||
this, aDeviceId, aWidth, aHeight, aFormat, aUsage);
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -178,6 +178,8 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
|
||||
return ForwardError(Some(aDeviceId), aError);
|
||||
}
|
||||
|
||||
ffi::WGPUGlobal* GetContext() const { return mContext.get(); }
|
||||
|
||||
private:
|
||||
static void MapCallback(uint8_t* aUserData,
|
||||
ffi::WGPUBufferMapAsyncStatus aStatus);
|
||||
|
||||
@@ -95,7 +95,8 @@ Maybe<layers::SurfaceDescriptor>
|
||||
SharedSurface_IOSurface::ToSurfaceDescriptor() {
|
||||
const bool isOpaque = false; // RGBA
|
||||
return Some(layers::SurfaceDescriptorMacIOSurface(
|
||||
mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace()));
|
||||
mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace(),
|
||||
(layers::GpuFence*)nullptr));
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
29
gfx/layers/GpuFence.h
Normal file
29
gfx/layers/GpuFence.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_GpuFence_H
|
||||
#define MOZILLA_GFX_GpuFence_H
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class GpuFence {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GpuFence);
|
||||
|
||||
virtual bool HasCompleted() = 0;
|
||||
|
||||
protected:
|
||||
GpuFence() = default;
|
||||
virtual ~GpuFence() = default;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZILLA_GFX_GpuFence_H */
|
||||
38
gfx/layers/GpuFenceMTLSharedEvent.cpp
Normal file
38
gfx/layers/GpuFenceMTLSharedEvent.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GpuFenceMTLSharedEvent.h"
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/* static */
|
||||
RefPtr<GpuFenceMTLSharedEvent> GpuFenceMTLSharedEvent::Create(
|
||||
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
|
||||
const uint64_t aFenceValue) {
|
||||
if (!aSharedEventHandle) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return nullptr;
|
||||
}
|
||||
return new GpuFenceMTLSharedEvent(std::move(aSharedEventHandle), aFenceValue);
|
||||
}
|
||||
|
||||
GpuFenceMTLSharedEvent::GpuFenceMTLSharedEvent(
|
||||
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
|
||||
const uint64_t aFenceValue)
|
||||
: mSharedEventHandle(std::move(aSharedEventHandle)),
|
||||
mFenceValue(aFenceValue) {}
|
||||
|
||||
bool GpuFenceMTLSharedEvent::HasCompleted() {
|
||||
auto value =
|
||||
wgpu_server_metal_shared_event_signaled_value(mSharedEventHandle.get());
|
||||
return value >= mFenceValue;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
46
gfx/layers/GpuFenceMTLSharedEvent.h
Normal file
46
gfx/layers/GpuFenceMTLSharedEvent.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_GpuFenceMTLSharedEvent_H
|
||||
#define MOZILLA_GFX_GpuFenceMTLSharedEvent_H
|
||||
|
||||
#include "mozilla/layers/GpuFence.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/webgpu/ffi/wgpu.h"
|
||||
#include "mozilla/webgpu/WebGPUTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace webgpu {
|
||||
namespace ffi {
|
||||
struct WGPUMetalSharedEventHandle;
|
||||
}
|
||||
} // namespace webgpu
|
||||
|
||||
namespace layers {
|
||||
|
||||
class GpuFenceMTLSharedEvent : public GpuFence {
|
||||
public:
|
||||
static RefPtr<GpuFenceMTLSharedEvent> Create(
|
||||
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
|
||||
const uint64_t aFenceValue);
|
||||
|
||||
bool HasCompleted() override;
|
||||
|
||||
protected:
|
||||
GpuFenceMTLSharedEvent(
|
||||
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle>&& aSharedEventHandle,
|
||||
const uint64_t aFenceValue);
|
||||
virtual ~GpuFenceMTLSharedEvent() = default;
|
||||
|
||||
UniquePtr<webgpu::ffi::WGPUMetalSharedEventHandle> mSharedEventHandle;
|
||||
const uint64_t mFenceValue;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZILLA_GFX_GpuFenceMTLSharedEvent_H */
|
||||
@@ -28,6 +28,7 @@ class RenderTextureHost;
|
||||
|
||||
namespace layers {
|
||||
|
||||
class GpuFence;
|
||||
class NativeLayer;
|
||||
class NativeLayerCA;
|
||||
class NativeLayerWayland;
|
||||
@@ -235,6 +236,8 @@ class NativeLayer {
|
||||
|
||||
virtual void AttachExternalImage(wr::RenderTextureHost* aExternalImage) = 0;
|
||||
|
||||
virtual GpuFence* GetGpuFence() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~NativeLayer() = default;
|
||||
};
|
||||
|
||||
@@ -268,6 +268,7 @@ class NativeLayerCA : public NativeLayer {
|
||||
void DumpLayer(std::ostream& aOutputStream);
|
||||
|
||||
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
|
||||
GpuFence* GetGpuFence() override;
|
||||
|
||||
void SetRootWindowIsFullscreen(bool aFullscreen);
|
||||
|
||||
|
||||
@@ -937,6 +937,22 @@ void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
|
||||
});
|
||||
}
|
||||
|
||||
GpuFence* NativeLayerCA::GetGpuFence() {
|
||||
if (!mTextureHost) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wr::RenderMacIOSurfaceTextureHost* texture =
|
||||
mTextureHost->AsRenderMacIOSurfaceTextureHost();
|
||||
if (!texture) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
gfxCriticalNoteOnce << "ExternalImage is not RenderMacIOSurfaceTextureHost";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return texture->GetGpuFence();
|
||||
}
|
||||
|
||||
bool NativeLayerCA::IsVideo(const MutexAutoLock& aProofOfLock) {
|
||||
// If we have a texture host, we've checked to see if it's providing video.
|
||||
// And if we don't have a texture host, it isn't video, so we just check
|
||||
|
||||
@@ -125,6 +125,7 @@ class NativeLayerWayland final : public NativeLayer {
|
||||
bool SurfaceIsFlipped() override;
|
||||
|
||||
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
|
||||
GpuFence* GetGpuFence() override { return nullptr; }
|
||||
|
||||
void Commit();
|
||||
void Unmap();
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "mozilla/layers/FocusTarget.h"
|
||||
#include "mozilla/layers/GeckoContentControllerTypes.h"
|
||||
#include "mozilla/layers/GpuFence.h"
|
||||
#include "mozilla/layers/KeyboardMap.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/MatrixMessage.h"
|
||||
@@ -1172,6 +1173,39 @@ struct ParamTraits<mozilla::layers::DoubleTapToZoomMetrics> {
|
||||
|
||||
} /* namespace IPC */
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<layers::GpuFence*> {
|
||||
static void Write(IPC::MessageWriter* aWriter, IProtocol* aActor,
|
||||
layers::GpuFence* aParam) {
|
||||
if (aParam) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
}
|
||||
WriteIPDLParam(aWriter, aActor, false);
|
||||
}
|
||||
|
||||
static bool Read(IPC::MessageReader* aReader, IProtocol* aActor,
|
||||
RefPtr<layers::GpuFence>* aResult) {
|
||||
*aResult = nullptr;
|
||||
bool notnull = false;
|
||||
if (!ReadIPDLParam(aReader, aActor, ¬null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!notnull) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#define DEFINE_SERVO_PARAMTRAITS(ty_) \
|
||||
MOZ_DEFINE_RUST_PARAMTRAITS(mozilla::ty_, Servo_##ty_##_Serialize, \
|
||||
Servo_##ty_##_Deserialize)
|
||||
|
||||
@@ -29,6 +29,7 @@ using gfxImageFormat from "gfxTypes.h";
|
||||
using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
|
||||
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
|
||||
[RefCounted] using mozilla::layers::GpuFence from "mozilla/layers/GpuFence.h";
|
||||
using mozilla::layers::GpuProcessTextureId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::GpuProcessQueryId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
|
||||
@@ -67,6 +68,7 @@ namespace layers {
|
||||
uint32_t surfaceId;
|
||||
bool isOpaque;
|
||||
YUVColorSpace yUVColorSpace;
|
||||
nullable GpuFence gpuFence;
|
||||
};
|
||||
|
||||
[Comparable] struct SurfaceDescriptorDMABuf {
|
||||
|
||||
@@ -145,6 +145,7 @@ EXPORTS.mozilla.layers += [
|
||||
"D3D11ZeroCopyTextureImage.h",
|
||||
"DirectionUtils.h",
|
||||
"Effects.h",
|
||||
"GpuFence.h",
|
||||
"ImageDataSerializer.h",
|
||||
"ipc/ActiveResource.h",
|
||||
"ipc/APZChild.h",
|
||||
@@ -263,6 +264,7 @@ if CONFIG["MOZ_WAYLAND"]:
|
||||
|
||||
if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
|
||||
EXPORTS.mozilla.layers += [
|
||||
"GpuFenceMTLSharedEvent.h",
|
||||
"NativeLayerCA.h",
|
||||
"SurfacePoolCA.h",
|
||||
]
|
||||
@@ -275,6 +277,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
|
||||
"SurfacePoolCA.mm",
|
||||
]
|
||||
SOURCES += [
|
||||
"GpuFenceMTLSharedEvent.cpp",
|
||||
"MacIOSurfaceHelpers.cpp",
|
||||
"MacIOSurfaceImage.cpp",
|
||||
]
|
||||
|
||||
@@ -50,17 +50,19 @@ MacIOSurfaceTextureData* MacIOSurfaceTextureData::Create(const IntSize& aSize,
|
||||
}
|
||||
|
||||
bool MacIOSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
||||
aOutDescriptor = SurfaceDescriptorMacIOSurface(mSurface->GetIOSurfaceID(),
|
||||
!mSurface->HasAlpha(),
|
||||
mSurface->GetYUVColorSpace());
|
||||
RefPtr<layers::GpuFence> gpuFence;
|
||||
aOutDescriptor = SurfaceDescriptorMacIOSurface(
|
||||
mSurface->GetIOSurfaceID(), !mSurface->HasAlpha(),
|
||||
mSurface->GetYUVColorSpace(), std::move(gpuFence));
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacIOSurfaceTextureData::GetSubDescriptor(
|
||||
RemoteDecoderVideoSubDescriptor* const aOutDesc) {
|
||||
*aOutDesc = SurfaceDescriptorMacIOSurface(mSurface->GetIOSurfaceID(),
|
||||
!mSurface->HasAlpha(),
|
||||
mSurface->GetYUVColorSpace());
|
||||
RefPtr<layers::GpuFence> gpuFence;
|
||||
*aOutDesc = SurfaceDescriptorMacIOSurface(
|
||||
mSurface->GetIOSurfaceID(), !mSurface->HasAlpha(),
|
||||
mSurface->GetYUVColorSpace(), std::move(gpuFence));
|
||||
}
|
||||
|
||||
void MacIOSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "MacIOSurfaceTextureHostOGL.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/MacIOSurface.h"
|
||||
#include "mozilla/layers/GpuFence.h"
|
||||
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
@@ -24,6 +25,7 @@ MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(
|
||||
if (!mSurface) {
|
||||
gfxCriticalNote << "Failed to look up MacIOSurface";
|
||||
}
|
||||
mGpuFence = aDescriptor.gpuFence();
|
||||
}
|
||||
|
||||
MacIOSurfaceTextureHostOGL::~MacIOSurfaceTextureHostOGL() {
|
||||
@@ -74,7 +76,7 @@ void MacIOSurfaceTextureHostOGL::CreateRenderTexture(
|
||||
MOZ_ASSERT(mExternalImageId.isSome());
|
||||
|
||||
RefPtr<wr::RenderTextureHost> texture =
|
||||
new wr::RenderMacIOSurfaceTextureHost(GetMacIOSurface());
|
||||
new wr::RenderMacIOSurfaceTextureHost(GetMacIOSurface(), mGpuFence);
|
||||
|
||||
bool isDRM = (bool)(mFlags & TextureFlags::DRM_SOURCE);
|
||||
texture->SetIsFromDRMSource(isDRM);
|
||||
|
||||
@@ -17,6 +17,8 @@ class MacIOSurface;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class GpuFence;
|
||||
|
||||
/**
|
||||
* A TextureHost for shared MacIOSurface
|
||||
*
|
||||
@@ -77,6 +79,7 @@ class MacIOSurfaceTextureHostOGL : public TextureHost {
|
||||
protected:
|
||||
RefPtr<GLTextureSource> mTextureSource;
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
RefPtr<GpuFence> mGpuFence;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/CompositionRecorder.h"
|
||||
#include "mozilla/layers/GpuFence.h"
|
||||
#include "mozilla/layers/NativeLayer.h"
|
||||
#include "mozilla/layers/SurfacePool.h"
|
||||
#include "mozilla/StaticPrefs_gfx.h"
|
||||
@@ -88,6 +89,8 @@ RenderedFrameId RenderCompositorNative::EndFrame(
|
||||
|
||||
DoSwap();
|
||||
|
||||
MOZ_ASSERT(mPendingGpuFeces.empty());
|
||||
|
||||
if (mNativeLayerForEntireWindow) {
|
||||
mNativeLayerForEntireWindow->NotifySurfaceReady();
|
||||
mNativeLayerRoot->CommitToScreen();
|
||||
@@ -431,6 +434,13 @@ void RenderCompositorNative::AddSurface(
|
||||
layer->SetSamplingFilter(ToSamplingFilter(aImageRendering));
|
||||
mAddedLayers.AppendElement(layer);
|
||||
|
||||
if (surface.mIsExternal) {
|
||||
RefPtr<layers::GpuFence> fence = layer->GetGpuFence();
|
||||
if (fence && BackendType() == layers::WebRenderBackend::HARDWARE) {
|
||||
mPendingGpuFeces.emplace_back(fence);
|
||||
}
|
||||
}
|
||||
|
||||
if (!surface.mIsExternal) {
|
||||
mAddedTilePixelCount += layerSize.width * layerSize.height;
|
||||
}
|
||||
@@ -471,16 +481,16 @@ RenderCompositorNativeOGL::~RenderCompositorNativeOGL() {
|
||||
gfxCriticalNote
|
||||
<< "Failed to make render context current during destroying.";
|
||||
// Leak resources!
|
||||
mPreviousFrameDoneSync = nullptr;
|
||||
mThisFrameDoneSync = nullptr;
|
||||
mPreviousFrameDoneFences = nullptr;
|
||||
mThisFrameDoneFences = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPreviousFrameDoneSync) {
|
||||
mGL->fDeleteSync(mPreviousFrameDoneSync);
|
||||
if (mPreviousFrameDoneFences && mPreviousFrameDoneFences->mSync) {
|
||||
mGL->fDeleteSync(mPreviousFrameDoneFences->mSync);
|
||||
}
|
||||
if (mThisFrameDoneSync) {
|
||||
mGL->fDeleteSync(mThisFrameDoneSync);
|
||||
if (mThisFrameDoneFences && mThisFrameDoneFences->mSync) {
|
||||
mGL->fDeleteSync(mThisFrameDoneFences->mSync);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,23 +522,43 @@ void RenderCompositorNativeOGL::InsertFrameDoneSync() {
|
||||
#ifdef XP_DARWIN
|
||||
// Only do this on macOS.
|
||||
// On other platforms, SwapBuffers automatically applies back-pressure.
|
||||
if (mThisFrameDoneSync) {
|
||||
mGL->fDeleteSync(mThisFrameDoneSync);
|
||||
if (mThisFrameDoneFences && mThisFrameDoneFences->mSync) {
|
||||
mGL->fDeleteSync(mThisFrameDoneFences->mSync);
|
||||
}
|
||||
mThisFrameDoneSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
mThisFrameDoneFences =
|
||||
MakeUnique<BackPressureFences>(std::move(mPendingGpuFeces));
|
||||
mThisFrameDoneFences->mSync =
|
||||
mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RenderCompositorNativeOGL::WaitForGPU() {
|
||||
if (mPreviousFrameDoneSync) {
|
||||
AUTO_PROFILER_LABEL("Waiting for GPU to finish previous frame", GRAPHICS);
|
||||
mGL->fClientWaitSync(mPreviousFrameDoneSync,
|
||||
LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT,
|
||||
LOCAL_GL_TIMEOUT_IGNORED);
|
||||
mGL->fDeleteSync(mPreviousFrameDoneSync);
|
||||
if (mPreviousFrameDoneFences) {
|
||||
bool complete = false;
|
||||
while (!complete) {
|
||||
complete = true;
|
||||
for (const auto& fence : mPreviousFrameDoneFences->mGpuFeces) {
|
||||
if (!fence->HasCompleted()) {
|
||||
complete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!complete) {
|
||||
PR_Sleep(PR_MillisecondsToInterval(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (mPreviousFrameDoneFences->mSync) {
|
||||
AUTO_PROFILER_LABEL("Waiting for GPU to finish previous frame", GRAPHICS);
|
||||
mGL->fClientWaitSync(mPreviousFrameDoneFences->mSync,
|
||||
LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT,
|
||||
LOCAL_GL_TIMEOUT_IGNORED);
|
||||
mGL->fDeleteSync(mPreviousFrameDoneFences->mSync);
|
||||
}
|
||||
}
|
||||
mPreviousFrameDoneSync = mThisFrameDoneSync;
|
||||
mThisFrameDoneSync = nullptr;
|
||||
mPreviousFrameDoneFences = std::move(mThisFrameDoneFences);
|
||||
MOZ_ASSERT(!mThisFrameDoneFences);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef MOZILLA_GFX_RENDERCOMPOSITOR_NATIVE_H
|
||||
#define MOZILLA_GFX_RENDERCOMPOSITOR_NATIVE_H
|
||||
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "GLTypes.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
class GpuFence;
|
||||
class NativeLayerRootSnapshotter;
|
||||
class NativeLayerRoot;
|
||||
class NativeLayer;
|
||||
@@ -140,6 +142,7 @@ class RenderCompositorNative : public RenderCompositor {
|
||||
gfx::IntRect mVisibleBounds;
|
||||
std::unordered_map<wr::NativeSurfaceId, Surface, SurfaceIdHashFn> mSurfaces;
|
||||
TimeStamp mBeginFrameTimeStamp;
|
||||
std::deque<RefPtr<layers::GpuFence>> mPendingGpuFeces;
|
||||
};
|
||||
|
||||
static inline bool operator==(const RenderCompositorNative::TileKey& a0,
|
||||
@@ -176,9 +179,18 @@ class RenderCompositorNativeOGL : public RenderCompositorNative {
|
||||
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
|
||||
struct BackPressureFences {
|
||||
explicit BackPressureFences(
|
||||
std::deque<RefPtr<layers::GpuFence>>&& aGpuFeces)
|
||||
: mGpuFeces(std::move(aGpuFeces)) {}
|
||||
|
||||
GLsync mSync = nullptr;
|
||||
std::deque<RefPtr<layers::GpuFence>> mGpuFeces;
|
||||
};
|
||||
|
||||
// Used to apply back-pressure in WaitForGPU().
|
||||
GLsync mPreviousFrameDoneSync = nullptr;
|
||||
GLsync mThisFrameDoneSync = nullptr;
|
||||
UniquePtr<BackPressureFences> mPreviousFrameDoneFences;
|
||||
UniquePtr<BackPressureFences> mThisFrameDoneFences;
|
||||
};
|
||||
|
||||
// RenderCompositorNativeSWGL is a NativeLayer compositor that only
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#endif
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/GpuFence.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
|
||||
namespace mozilla {
|
||||
@@ -41,8 +42,8 @@ static bool CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL,
|
||||
}
|
||||
|
||||
RenderMacIOSurfaceTextureHost::RenderMacIOSurfaceTextureHost(
|
||||
MacIOSurface* aSurface)
|
||||
: mSurface(aSurface), mTextureHandles{0, 0, 0} {
|
||||
MacIOSurface* aSurface, layers::GpuFence* aGpuFence)
|
||||
: mSurface(aSurface), mGpuFence(aGpuFence), mTextureHandles{0, 0, 0} {
|
||||
MOZ_COUNT_CTOR_INHERITED(RenderMacIOSurfaceTextureHost, RenderTextureHost);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,16 @@
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
class GpuFence;
|
||||
class SurfaceDescriptorMacIOSurface;
|
||||
}
|
||||
} // namespace layers
|
||||
|
||||
namespace wr {
|
||||
|
||||
class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL {
|
||||
public:
|
||||
explicit RenderMacIOSurfaceTextureHost(MacIOSurface* aSurface);
|
||||
explicit RenderMacIOSurfaceTextureHost(MacIOSurface* aSurface,
|
||||
layers::GpuFence* aGpuFence);
|
||||
|
||||
wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL) override;
|
||||
void Unlock() override;
|
||||
@@ -46,11 +48,14 @@ class RenderMacIOSurfaceTextureHost final : public RenderTextureHostSWGL {
|
||||
PlaneInfo& aPlaneInfo) override;
|
||||
void UnmapPlanes() override;
|
||||
|
||||
layers::GpuFence* GetGpuFence() { return mGpuFence; }
|
||||
|
||||
private:
|
||||
virtual ~RenderMacIOSurfaceTextureHost();
|
||||
void DeleteTextureHandle();
|
||||
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
RefPtr<layers::GpuFence> mGpuFence;
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
GLuint mTextureHandles[3];
|
||||
};
|
||||
|
||||
@@ -1270,6 +1270,62 @@ pub extern "C" fn wgpu_vkimage_get_dma_buf_info(handle: &VkImageHandle) -> DMABu
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub struct MetalSharedEventHandle(metal::SharedEvent);
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub struct MetalSharedEventHandle;
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(unreachable_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub extern "C" fn wgpu_server_get_device_fence_metal_shared_event(
|
||||
global: &Global,
|
||||
device_id: id::DeviceId,
|
||||
) -> *mut MetalSharedEventHandle {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let shared_event = unsafe {
|
||||
global.device_fence_as_hal::<wgc::api::Metal, _, Option<metal::SharedEvent>>(
|
||||
device_id,
|
||||
|hal_fence| hal_fence.map(|fence| fence.raw_shared_event().unwrap().clone()),
|
||||
)
|
||||
};
|
||||
let shared_event = match shared_event {
|
||||
Some(shared_event) => shared_event,
|
||||
None => {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
};
|
||||
return Box::into_raw(Box::new(MetalSharedEventHandle(shared_event)));
|
||||
}
|
||||
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(unreachable_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub extern "C" fn wgpu_server_metal_shared_event_signaled_value(
|
||||
shared_event: &mut MetalSharedEventHandle,
|
||||
) -> u64 {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
return shared_event.0.signaled_value();
|
||||
}
|
||||
|
||||
u64::MAX
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(unreachable_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub extern "C" fn wgpu_server_delete_metal_shared_event(shared_event: *mut MetalSharedEventHandle) {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let _ = unsafe { Box::from_raw(shared_event) };
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[allow(dead_code)]
|
||||
fn gfx_critical_note(msg: *const c_char);
|
||||
|
||||
@@ -68,6 +68,14 @@ class DefaultDelete<webgpu::ffi::WGPUVkImageHandle> {
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
class DefaultDelete<webgpu::ffi::WGPUMetalSharedEventHandle> {
|
||||
public:
|
||||
void operator()(webgpu::ffi::WGPUMetalSharedEventHandle* aPtr) const {
|
||||
webgpu::ffi::wgpu_server_delete_metal_shared_event(aPtr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // WGPU_h
|
||||
|
||||
Reference in New Issue
Block a user