diff --git a/dom/canvas/OffscreenCanvasDisplayHelper.cpp b/dom/canvas/OffscreenCanvasDisplayHelper.cpp index 0d0701ad4eab..8d75cff2f7a5 100644 --- a/dom/canvas/OffscreenCanvasDisplayHelper.cpp +++ b/dom/canvas/OffscreenCanvasDisplayHelper.cpp @@ -252,14 +252,12 @@ OffscreenCanvasDisplayHelper::GetSurfaceSnapshot() { Maybe childId; HTMLCanvasElement* canvasElement; RefPtr surface; - layers::CompositableHandle handle; { MutexAutoLock lock(mMutex); hasAlpha = !mData.mIsOpaque; isAlphaPremult = mData.mIsAlphaPremult; originPos = mData.mOriginPos; - handle = mData.mHandle; managerId = mContextManagerId; childId = mContextChildId; canvasElement = mCanvasElement; @@ -313,9 +311,7 @@ OffscreenCanvasDisplayHelper::GetSurfaceSnapshot() { // We don't have a usable surface, and the context lives in the compositor // process. return gfx::CanvasManagerChild::Get()->GetSnapshot( - managerId.value(), childId.value(), handle, - hasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8, - hasAlpha && !isAlphaPremult, originPos == gl::OriginPos::BottomLeft); + managerId.value(), childId.value(), hasAlpha); } // If we don't have any protocol IDs, or an existing surface, it is possible diff --git a/dom/canvas/nsICanvasRenderingContextInternal.cpp b/dom/canvas/nsICanvasRenderingContextInternal.cpp index ffa24289a46b..103de14ce6b6 100644 --- a/dom/canvas/nsICanvasRenderingContextInternal.cpp +++ b/dom/canvas/nsICanvasRenderingContextInternal.cpp @@ -9,7 +9,6 @@ #include "mozilla/dom/Document.h" #include "mozilla/PresShell.h" #include "nsRefreshDriver.h" -#include "ImageContainer.h" nsICanvasRenderingContextInternal::nsICanvasRenderingContextInternal() = default; @@ -73,12 +72,3 @@ void nsICanvasRenderingContextInternal::DoSecurityCheck( mOffscreenCanvas->SetWriteOnly(); } } - -already_AddRefed -nsICanvasRenderingContextInternal::GetAsImage() { - RefPtr snapshot = GetFrontBufferSnapshot(true); - if (!snapshot) { - return nullptr; - } - return mozilla::MakeAndAddRef(snapshot); -} diff --git a/dom/canvas/nsICanvasRenderingContextInternal.h b/dom/canvas/nsICanvasRenderingContextInternal.h index 6c4bbcdef663..f284f44b672e 100644 --- a/dom/canvas/nsICanvasRenderingContextInternal.h +++ b/dom/canvas/nsICanvasRenderingContextInternal.h @@ -146,7 +146,9 @@ class nsICanvasRenderingContextInternal : public nsISupports, // for possibly reinitializing with SetDimensions/InitializeWithSurface. NS_IMETHOD Reset() = 0; - virtual already_AddRefed GetAsImage(); + virtual already_AddRefed GetAsImage() { + return nullptr; + } virtual bool UpdateWebRenderCanvasData( mozilla::nsDisplayListBuilder* aBuilder, diff --git a/dom/media/test/reftest/color_quads/reftest.list b/dom/media/test/reftest/color_quads/reftest.list index 0813d6407af2..e7154455d010 100644 --- a/dom/media/test/reftest/color_quads/reftest.list +++ b/dom/media/test/reftest/color_quads/reftest.list @@ -33,10 +33,10 @@ skip-if(Android) skip-if(!(winWidget&&swgl)) fuzzy(0-31,0-8240) == ../reftest_vi # yuv420p10 skip-if(Android) fuzzy(33-49,2263-2579) fuzzy-if(swgl,34-52,180421-270528) fuzzy-if(useDrawSnapshot,16-16,183840-183840) fuzzy-if(OSX,60-74,270329-271024) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm ../reftest_img.html?src=color_quads/720p.png -skip-if(Android) fuzzy-if(OSX,12-36,187246-273726) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.vp9.webm ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm +skip-if(Android) fuzzy-if(OSX,12-36,187246-273730) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.vp9.webm ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm skip-if(Android) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm #[2] skip-if(Android) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.h264.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm -skip-if(Android) fuzzy-if(OSX,12-36,187246-273726) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.vp9.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm +skip-if(Android) fuzzy-if(OSX,12-36,187246-273730) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.vp9.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p10.av1.webm skip-if(Android) fuzzy(33-49,174699-270059) fuzzy-if(swgl&&!winWidget,36-52,11553-11555) fuzzy-if(swgl&&winWidget,40-52,11555-187200) fuzzy-if(swgl&&OSX,34-50,11465-270059) fuzzy-if(useDrawSnapshot,20-20,186800-186800) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.pc.yuv420p10.av1.webm ../reftest_img.html?src=color_quads/720p.png skip-if(Android) fuzzy-if(OSX,12-27,267487-273726) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.pc.yuv420p10.vp9.webm ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.pc.yuv420p10.av1.webm diff --git a/dom/webgpu/CanvasContext.cpp b/dom/webgpu/CanvasContext.cpp index 676188ca4859..d4b4689faad9 100644 --- a/dom/webgpu/CanvasContext.cpp +++ b/dom/webgpu/CanvasContext.cpp @@ -5,11 +5,9 @@ #include "mozilla/dom/WebGPUBinding.h" #include "CanvasContext.h" -#include "gfxUtils.h" -#include "LayerUserData.h" #include "nsDisplayList.h" +#include "LayerUserData.h" #include "mozilla/dom/HTMLCanvasElement.h" -#include "mozilla/gfx/CanvasManagerChild.h" #include "mozilla/layers/CompositableInProcessManager.h" #include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/LayersSurfaces.h" @@ -80,7 +78,6 @@ void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aDesc) { } else if (mOffscreenCanvas) { dom::OffscreenCanvasDisplayData data; data.mSize = {mWidth, mHeight}; - data.mIsOpaque = false; data.mHandle = mHandle; mOffscreenCanvas->UpdateDisplayData(data); } @@ -126,51 +123,5 @@ void CanvasContext::SwapChainPresent() { } } -mozilla::UniquePtr CanvasContext::GetImageBuffer(int32_t* aFormat) { - gfxAlphaType any; - RefPtr snapshot = GetSurfaceSnapshot(&any); - if (!snapshot) { - *aFormat = 0; - return nullptr; - } - - RefPtr dataSurface = snapshot->GetDataSurface(); - return gfxUtils::GetImageBuffer(dataSurface, /* aIsAlphaPremultiplied */ true, - aFormat); -} - -NS_IMETHODIMP CanvasContext::GetInputStream(const char* aMimeType, - const nsAString& aEncoderOptions, - nsIInputStream** aStream) { - gfxAlphaType any; - RefPtr snapshot = GetSurfaceSnapshot(&any); - if (!snapshot) { - return NS_ERROR_FAILURE; - } - - RefPtr dataSurface = snapshot->GetDataSurface(); - return gfxUtils::GetInputStream(dataSurface, /* aIsAlphaPremultiplied */ true, - aMimeType, aEncoderOptions, aStream); -} - -already_AddRefed CanvasContext::GetSurfaceSnapshot( - gfxAlphaType* aOutAlphaType) { - if (aOutAlphaType) { - *aOutAlphaType = gfxAlphaType::Premult; - } - - auto* const cm = gfx::CanvasManagerChild::Get(); - if (!cm) { - return nullptr; - } - - if (!mBridge || !mBridge->IsOpen() || !mHandle) { - return nullptr; - } - - return cm->GetSnapshot(cm->Id(), mBridge->Id(), mHandle, mGfxFormat, - /* aPremultiply */ false, /* aYFlip */ false); -} - } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/CanvasContext.h b/dom/webgpu/CanvasContext.h index 2ef574000201..05aca8caf58f 100644 --- a/dom/webgpu/CanvasContext.h +++ b/dom/webgpu/CanvasContext.h @@ -54,12 +54,20 @@ class CanvasContext final : public nsICanvasRenderingContextInternal, return NS_OK; } - mozilla::UniquePtr GetImageBuffer(int32_t* aFormat) override; + mozilla::UniquePtr GetImageBuffer(int32_t* aFormat) override { + MOZ_CRASH("todo"); + } NS_IMETHOD GetInputStream(const char* aMimeType, const nsAString& aEncoderOptions, - nsIInputStream** aStream) override; + nsIInputStream** aStream) override { + *aStream = nullptr; + return NS_ERROR_NOT_IMPLEMENTED; + } + already_AddRefed GetSurfaceSnapshot( - gfxAlphaType* aOutAlphaType) override; + gfxAlphaType* aOutAlphaType) override { + return nullptr; + } void SetOpaqueValueFromOpaqueAttr(bool aOpaqueAttrValue) override {} bool GetIsOpaque() override { return true; } diff --git a/dom/webgpu/Device.cpp b/dom/webgpu/Device.cpp index 9c5a243670c3..3b5ee70bf4c6 100644 --- a/dom/webgpu/Device.cpp +++ b/dom/webgpu/Device.cpp @@ -360,8 +360,8 @@ already_AddRefed Device::PopErrorScope(ErrorResult& aRv) { if (aMaybeError->validationMessage.IsEmpty()) { error.SetAsGPUOutOfMemoryError(); } else { - error.SetAsGPUValidationError() = - new ValidationError(self, aMaybeError->validationMessage); + error.SetAsGPUValidationError() = new ValidationError( + self->GetParentObject(), aMaybeError->validationMessage); } promise->MaybeResolve(std::move(error)); } diff --git a/dom/webgpu/ValidationError.cpp b/dom/webgpu/ValidationError.cpp index 287326dab052..119156713cf0 100644 --- a/dom/webgpu/ValidationError.cpp +++ b/dom/webgpu/ValidationError.cpp @@ -4,28 +4,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ValidationError.h" -#include "Device.h" #include "mozilla/dom/WebGPUBinding.h" +#include "mozilla/ErrorResult.h" +#include "nsIGlobalObject.h" +#include "nsReadableUtils.h" -namespace mozilla { -namespace webgpu { +namespace mozilla::webgpu { -GPU_IMPL_CYCLE_COLLECTION(ValidationError, mParent) +GPU_IMPL_CYCLE_COLLECTION(ValidationError, mGlobal) GPU_IMPL_JS_WRAP(ValidationError) -ValidationError::ValidationError(Device* aParent, const nsACString& aMessage) - : ChildOf(aParent), mMessage(aMessage) {} +ValidationError::ValidationError(nsIGlobalObject* aGlobal, + const nsACString& aMessage) + : mGlobal(aGlobal) { + CopyUTF8toUTF16(aMessage, mMessage); +} + +ValidationError::ValidationError(nsIGlobalObject* aGlobal, + const nsAString& aMessage) + : mGlobal(aGlobal), mMessage(aMessage) {} ValidationError::~ValidationError() = default; already_AddRefed ValidationError::Constructor( - const dom::GlobalObject& aGlobal, const nsAString& aString) { - MOZ_CRASH("TODO"); + const dom::GlobalObject& aGlobal, const nsAString& aString, + ErrorResult& aRv) { + nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); + if (!global) { + aRv.ThrowInvalidStateError("aGlobal is not nsIGlobalObject"); + return nullptr; + } + + return MakeAndAddRef(global, aString); } -void ValidationError::GetMessage(nsAString& aMessage) const { - CopyUTF8toUTF16(mMessage, aMessage); -} - -} // namespace webgpu -} // namespace mozilla +} // namespace mozilla::webgpu diff --git a/dom/webgpu/ValidationError.h b/dom/webgpu/ValidationError.h index a46c39a2bf4d..bdbc1ce2eba9 100644 --- a/dom/webgpu/ValidationError.h +++ b/dom/webgpu/ValidationError.h @@ -6,23 +6,28 @@ #ifndef GPU_ValidationError_H_ #define GPU_ValidationError_H_ +#include "nsCOMPtr.h" +#include "nsString.h" #include "nsWrapperCache.h" #include "ObjectModel.h" namespace mozilla { +class ErrorResult; + namespace dom { class GlobalObject; } // namespace dom namespace webgpu { -class Device; -class ValidationError final : public nsWrapperCache, public ChildOf { - nsCString mMessage; +class ValidationError final : public nsWrapperCache { + nsCOMPtr mGlobal; + nsString mMessage; public: GPU_DECL_CYCLE_COLLECTION(ValidationError) GPU_DECL_JS_WRAP(ValidationError) - ValidationError(Device* aParent, const nsACString& aMessage); + ValidationError(nsIGlobalObject* aGlobal, const nsACString& aMessage); + ValidationError(nsIGlobalObject* aGlobal, const nsAString& aMessage); private: virtual ~ValidationError(); @@ -30,8 +35,10 @@ class ValidationError final : public nsWrapperCache, public ChildOf { public: static already_AddRefed Constructor( - const dom::GlobalObject& aGlobal, const nsAString& aString); - void GetMessage(nsAString& aMessage) const; + const dom::GlobalObject& aGlobal, const nsAString& aString, + ErrorResult& aRv); + void GetMessage(nsAString& aMessage) const { aMessage = mMessage; } + nsIGlobalObject* GetParentObject() const { return mGlobal; } }; } // namespace webgpu diff --git a/dom/webgpu/ipc/WebGPUChild.cpp b/dom/webgpu/ipc/WebGPUChild.cpp index 5a8f1f593738..155718755209 100644 --- a/dom/webgpu/ipc/WebGPUChild.cpp +++ b/dom/webgpu/ipc/WebGPUChild.cpp @@ -998,7 +998,7 @@ ipc::IPCResult WebGPUChild::RecvDeviceUncapturedError( dom::GPUUncapturedErrorEventInit init; init.mError.SetAsGPUValidationError() = - new ValidationError(target, aMessage); + new ValidationError(target->GetParentObject(), aMessage); RefPtr event = dom::GPUUncapturedErrorEvent::Constructor( target, u"uncapturederror"_ns, init); diff --git a/dom/webgpu/ipc/WebGPUParent.cpp b/dom/webgpu/ipc/WebGPUParent.cpp index 2a8cc73f73e6..d23f84132f28 100644 --- a/dom/webgpu/ipc/WebGPUParent.cpp +++ b/dom/webgpu/ipc/WebGPUParent.cpp @@ -640,36 +640,6 @@ static void PresentCallback(ffi::WGPUBufferMapAsyncStatus status, delete req; } -ipc::IPCResult WebGPUParent::GetFrontBufferSnapshot( - IProtocol* aProtocol, const CompositableHandle& aHandle, - Maybe& aShmem, gfx::IntSize& aSize) { - const auto& lookup = mCanvasMap.find(aHandle.Value()); - if (lookup == mCanvasMap.end()) { - return IPC_OK(); - } - - RefPtr data = lookup->second.get(); - aSize = data->mTextureHost->GetSize(); - uint32_t stride = - aSize.width * BytesPerPixel(data->mTextureHost->GetFormat()); - uint32_t len = data->mRowCount * stride; - Shmem shmem; - if (!AllocShmem(len, ipc::Shmem::SharedMemory::TYPE_BASIC, &shmem)) { - return IPC_OK(); - } - - uint8_t* dst = shmem.get(); - uint8_t* src = data->mTextureHost->GetBuffer(); - for (uint32_t row = 0; row < data->mRowCount; ++row) { - memcpy(dst, src, stride); - src += data->mTargetPitch; - dst += stride; - } - - aShmem.emplace(std::move(shmem)); - return IPC_OK(); -} - ipc::IPCResult WebGPUParent::RecvSwapChainPresent( const CompositableHandle& aHandle, RawId aTextureId, RawId aCommandEncoderId) { diff --git a/dom/webgpu/ipc/WebGPUParent.h b/dom/webgpu/ipc/WebGPUParent.h index f4591d52f885..0bee6a34cc1e 100644 --- a/dom/webgpu/ipc/WebGPUParent.h +++ b/dom/webgpu/ipc/WebGPUParent.h @@ -11,7 +11,8 @@ #include "WebGPUTypes.h" #include "base/timer.h" -namespace mozilla::webgpu { +namespace mozilla { +namespace webgpu { class ErrorBuffer; class PresentationData; @@ -89,11 +90,6 @@ class WebGPUParent final : public PWebGPUParent { ipc::IPCResult RecvDevicePopErrorScope( RawId aSelfId, DevicePopErrorScopeResolver&& aResolver); - ipc::IPCResult GetFrontBufferSnapshot(IProtocol* aProtocol, - const CompositableHandle& aHandle, - Maybe& aShmem, - gfx::IntSize& aSize); - void ActorDestroy(ActorDestroyReason aWhy) override; private: @@ -113,6 +109,7 @@ class WebGPUParent final : public PWebGPUParent { std::unordered_map mErrorScopeMap; }; -} // namespace mozilla::webgpu +} // namespace webgpu +} // namespace mozilla #endif // WEBGPU_PARENT_H_ diff --git a/dom/webidl/WebGPU.webidl b/dom/webidl/WebGPU.webidl index 2c04644a2a8e..de49682fe07e 100644 --- a/dom/webidl/WebGPU.webidl +++ b/dom/webidl/WebGPU.webidl @@ -208,6 +208,7 @@ interface GPUOutOfMemoryError { [Pref="dom.webgpu.enabled", Exposed=(Window,DedicatedWorker)] interface GPUValidationError { + [Throws] constructor(DOMString message); readonly attribute DOMString message; }; diff --git a/gfx/ipc/CanvasManagerChild.cpp b/gfx/ipc/CanvasManagerChild.cpp index 76e46b98b40b..e4dd68696160 100644 --- a/gfx/ipc/CanvasManagerChild.cpp +++ b/gfx/ipc/CanvasManagerChild.cpp @@ -144,15 +144,13 @@ RefPtr CanvasManagerChild::GetWebGPUChild() { } already_AddRefed CanvasManagerChild::GetSnapshot( - uint32_t aManagerId, int32_t aProtocolId, - const layers::CompositableHandle& aHandle, SurfaceFormat aFormat, - bool aPremultiply, bool aYFlip) { + uint32_t aManagerId, int32_t aProtocolId, bool aHasAlpha) { if (!CanSend()) { return nullptr; } webgl::FrontBufferSnapshotIpc res; - if (!SendGetSnapshot(aManagerId, aProtocolId, aHandle, &res)) { + if (!SendGetSnapshot(aManagerId, aProtocolId, &res)) { return nullptr; } @@ -180,7 +178,7 @@ already_AddRefed CanvasManagerChild::GetSnapshot( } SurfaceFormat format = - IsOpaque(aFormat) ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8; + aHasAlpha ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8; RefPtr surface = Factory::CreateDataSourceSurfaceWithStride(size, format, stride.value(), /* aZero */ false); @@ -194,32 +192,21 @@ already_AddRefed CanvasManagerChild::GetSnapshot( return nullptr; } - // The buffer we may readback from the canvas could be R8G8B8A8, not - // premultiplied, and/or has its rows iverted. For the general case, we want - // surfaces represented as premultiplied B8G8R8A8, with its rows ordered top - // to bottom. Given this path is used for screenshots/SurfaceFromElement, - // that's the representation we need. - if (aYFlip) { - if (aPremultiply) { - if (!PremultiplyYFlipData(res.shmem->get(), stride.value(), - aFormat, map.GetData(), map.GetStride(), format, - size)) { - return nullptr; - } - } else { - if (!SwizzleYFlipData(res.shmem->get(), stride.value(), aFormat, - map.GetData(), map.GetStride(), format, size)) { - return nullptr; - } - } - } else if (aPremultiply) { - if (!PremultiplyData(res.shmem->get(), stride.value(), aFormat, - map.GetData(), map.GetStride(), format, size)) { + // The buffer we read back from WebGL is R8G8B8A8, not premultiplied and has + // its rows inverted. For the general case, we want surfaces represented as + // premultiplied B8G8R8A8, with its rows ordered top to bottom. Given this + // path is used for screenshots/SurfaceFromElement, that's the representation + // we need. + if (aHasAlpha) { + if (!PremultiplyYFlipData(res.shmem->get(), stride.value(), + SurfaceFormat::R8G8B8A8, map.GetData(), + map.GetStride(), format, size)) { return nullptr; } } else { - if (!SwizzleData(res.shmem->get(), stride.value(), aFormat, - map.GetData(), map.GetStride(), format, size)) { + if (!SwizzleYFlipData(res.shmem->get(), stride.value(), + SurfaceFormat::R8G8B8X8, map.GetData(), + map.GetStride(), format, size)) { return nullptr; } } diff --git a/gfx/ipc/CanvasManagerChild.h b/gfx/ipc/CanvasManagerChild.h index f5d1dac2bcae..2538e3c17bca 100644 --- a/gfx/ipc/CanvasManagerChild.h +++ b/gfx/ipc/CanvasManagerChild.h @@ -8,7 +8,6 @@ #include "mozilla/Atomics.h" #include "mozilla/gfx/PCanvasManagerChild.h" -#include "mozilla/gfx/Types.h" #include "mozilla/ThreadLocal.h" namespace mozilla { @@ -30,10 +29,9 @@ class CanvasManagerChild final : public PCanvasManagerChild { explicit CanvasManagerChild(uint32_t aId); uint32_t Id() const { return mId; } - already_AddRefed GetSnapshot( - uint32_t aManagerId, int32_t aProtocolId, - const layers::CompositableHandle& aHandle, SurfaceFormat aFormat, - bool aPremultiply, bool aYFlip); + already_AddRefed GetSnapshot(uint32_t aManagerId, + int32_t aProtocolId, + bool aHasAlpha); void ActorDestroy(ActorDestroyReason aReason) override; static CanvasManagerChild* Get(); diff --git a/gfx/ipc/CanvasManagerParent.cpp b/gfx/ipc/CanvasManagerParent.cpp index 076b2ce4fc01..65fd4d6c632f 100644 --- a/gfx/ipc/CanvasManagerParent.cpp +++ b/gfx/ipc/CanvasManagerParent.cpp @@ -111,7 +111,7 @@ mozilla::ipc::IPCResult CanvasManagerParent::RecvInitialize( mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot( const uint32_t& aManagerId, const int32_t& aProtocolId, - const CompositableHandle& aHandle, webgl::FrontBufferSnapshotIpc* aResult) { + webgl::FrontBufferSnapshotIpc* aResult) { if (!aManagerId) { return IPC_FAIL(this, "invalid id"); } @@ -129,33 +129,16 @@ mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot( return IPC_FAIL(this, "invalid actor"); } - if (actor->GetSide() != mozilla::ipc::Side::ParentSide) { + if (actor->GetProtocolId() != ProtocolId::PWebGLMsgStart || + actor->GetSide() != mozilla::ipc::Side::ParentSide) { return IPC_FAIL(this, "unsupported actor"); } + RefPtr webgl = static_cast(actor); webgl::FrontBufferSnapshotIpc buffer; - switch (actor->GetProtocolId()) { - case ProtocolId::PWebGLMsgStart: { - RefPtr webgl = static_cast(actor); - mozilla::ipc::IPCResult rv = webgl->GetFrontBufferSnapshot(&buffer, this); - if (!rv) { - return rv; - } - } break; - case ProtocolId::PWebGPUMsgStart: { - RefPtr webgpu = - static_cast(actor); - IntSize size; - mozilla::ipc::IPCResult rv = - webgpu->GetFrontBufferSnapshot(this, aHandle, buffer.shmem, size); - if (!rv) { - return rv; - } - buffer.surfSize.x = static_cast(size.width); - buffer.surfSize.y = static_cast(size.height); - } break; - default: - return IPC_FAIL(this, "unsupported protocol"); + mozilla::ipc::IPCResult rv = webgl->GetFrontBufferSnapshot(&buffer, this); + if (!rv) { + return rv; } *aResult = std::move(buffer); diff --git a/gfx/ipc/CanvasManagerParent.h b/gfx/ipc/CanvasManagerParent.h index c652dd670283..6cf0e7138be1 100644 --- a/gfx/ipc/CanvasManagerParent.h +++ b/gfx/ipc/CanvasManagerParent.h @@ -30,7 +30,6 @@ class CanvasManagerParent final : public PCanvasManagerParent { mozilla::ipc::IPCResult RecvInitialize(const uint32_t& aId); mozilla::ipc::IPCResult RecvGetSnapshot( const uint32_t& aManagerId, const int32_t& aProtocolId, - const CompositableHandle& aHandle, webgl::FrontBufferSnapshotIpc* aResult); private: diff --git a/gfx/ipc/PCanvasManager.ipdl b/gfx/ipc/PCanvasManager.ipdl index d625b4c5e7ef..8bea31a7a8bd 100644 --- a/gfx/ipc/PCanvasManager.ipdl +++ b/gfx/ipc/PCanvasManager.ipdl @@ -5,11 +5,9 @@ * 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 "mozilla/layers/LayersMessageUtils.h"; include protocol PWebGL; include protocol PWebGPU; -using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h"; using mozilla::webgl::FrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h"; namespace mozilla { @@ -41,7 +39,7 @@ parent: // intended to be used by the main thread in the content process to block // reading without having to block on the worker thread that owns the context // instance. - sync GetSnapshot(uint32_t aManagerId, int32_t aProtocolId, CompositableHandle aHandle) returns (FrontBufferSnapshotIpc ret); + sync GetSnapshot(uint32_t aManagerId, int32_t aProtocolId) returns (FrontBufferSnapshotIpc ret); }; } // gfx diff --git a/gfx/wr/swgl/src/composite.h b/gfx/wr/swgl/src/composite.h index 4caf80446b4e..8a5c3a6d14e3 100644 --- a/gfx/wr/swgl/src/composite.h +++ b/gfx/wr/swgl/src/composite.h @@ -534,7 +534,8 @@ struct YUVMatrix { // [ yScale, g_from_u, g_from_v ] x ([cb] - ycbcr_bias ) // [ yScale, b_from_u, 0 ] ([cr] ) static YUVMatrix From(const vec3_scalar& ycbcr_bias, - const mat3_scalar& rgb_from_debiased_ycbcr) { + const mat3_scalar& rgb_from_debiased_ycbcr, + int rescale_factor = 0) { assert(ycbcr_bias.z == ycbcr_bias.y); const auto rgb_from_y = rgb_from_debiased_ycbcr[0].y; @@ -544,14 +545,14 @@ struct YUVMatrix { if (rgb_from_debiased_ycbcr[0].x == 0.0) { // gbr-identity matrix? assert(rgb_from_debiased_ycbcr[0].x == 0); - assert(rgb_from_debiased_ycbcr[0].y == 1); + assert(rgb_from_debiased_ycbcr[0].y >= 1); assert(rgb_from_debiased_ycbcr[0].z == 0); assert(rgb_from_debiased_ycbcr[1].x == 0); assert(rgb_from_debiased_ycbcr[1].y == 0); - assert(rgb_from_debiased_ycbcr[1].z == 1); + assert(rgb_from_debiased_ycbcr[1].z >= 1); - assert(rgb_from_debiased_ycbcr[2].x == 1); + assert(rgb_from_debiased_ycbcr[2].x >= 1); assert(rgb_from_debiased_ycbcr[2].y == 0); assert(rgb_from_debiased_ycbcr[2].z == 0); @@ -573,24 +574,30 @@ struct YUVMatrix { assert(rgb_from_debiased_ycbcr[2].z == 0.0); return YUVMatrix({ycbcr_bias.x, ycbcr_bias.y}, rgb_from_y, br_from_y_mask, - r_from_v, g_from_u, g_from_v, b_from_u); + r_from_v, g_from_u, g_from_v, b_from_u, rescale_factor); } - // Convert matrix coefficients to fixed-point representation. + // Convert matrix coefficients to fixed-point representation. If the matrix + // has a rescaling applied to it, then we need to take care to undo the + // scaling so that we can convert the coefficients to fixed-point range. The + // bias still requires shifting to apply the rescaling. The rescaling will be + // applied to the actual YCbCr sample data later by manually shifting it + // before applying this matrix. YUVMatrix(vec2_scalar yuv_bias, double yCoeff, int16_t br_yMask_, double rv, - double gu, double gv, double bu) - : br_uvCoeffs(zip(I16(int16_t(bu * (1 << 6) + 0.5)), - I16(int16_t(rv * (1 << 6) + 0.5)))), - gg_uvCoeffs(zip(I16(-int16_t(-gu * (1 << 6) + - 0.5)), // These are negative coeffs, so - // round them away from zero - I16(-int16_t(-gv * (1 << 6) + 0.5)))), - yCoeffs(uint16_t(yCoeff * (1 << (6 + 1)) + 0.5)), + double gu, double gv, double bu, int rescale_factor = 0) + : br_uvCoeffs(zip(I16(int16_t(bu * (1 << (6 - rescale_factor)) + 0.5)), + I16(int16_t(rv * (1 << (6 - rescale_factor)) + 0.5)))), + gg_uvCoeffs( + zip(I16(-int16_t(-gu * (1 << (6 - rescale_factor)) + + 0.5)), // These are negative coeffs, so + // round them away from zero + I16(-int16_t(-gv * (1 << (6 - rescale_factor)) + 0.5)))), + yCoeffs(uint16_t(yCoeff * (1 << (6 + 1 - rescale_factor)) + 0.5)), // We have a +0.5 fudge-factor for -ybias. // Without this, we get white=254 not 255. // This approximates rounding rather than truncation during `gg >>= 6`. - yBias(int16_t( ((yuv_bias.x * 255 * yCoeff) - 0.5 ) * (1<<6) )), - uvBias(int16_t(yuv_bias.y * 255 + 0.5)), + yBias(int16_t(((yuv_bias.x * 255 * yCoeff) - 0.5) * (1 << 6))), + uvBias(int16_t(yuv_bias.y * (255 << rescale_factor) + 0.5)), br_yMask(br_yMask_) { assert(yuv_bias.x >= 0); assert(yuv_bias.y >= 0); @@ -600,6 +607,7 @@ struct YUVMatrix { assert(rv > 0); assert(gu <= 0); assert(gv <= 0); + assert(rescale_factor <= 6); } ALWAYS_INLINE PackedRGBA8 convert(V8 yy, V8 uv) const { @@ -881,11 +889,15 @@ static void linear_row_yuv(uint32_t* dest, int span, sampler2DRect samplerY, // If the source row has less than 2 pixels, it's not safe to use a linear // filter because it may overread the row. Just convert the single pixel // with nearest filtering and fill the row with it. - I16 yuv = CONVERT( - round_pixel((Float){texelFetch(samplerY, ivec2(srcUV)).x.x, - texelFetch(samplerU, ivec2(chromaUV)).x.x, - texelFetch(samplerV, ivec2(chromaUV)).x.x, 1.0f}), - I16); + Float yuvF = {texelFetch(samplerY, ivec2(srcUV)).x.x, + texelFetch(samplerU, ivec2(chromaUV)).x.x, + texelFetch(samplerV, ivec2(chromaUV)).x.x, 1.0f}; + // If this is an HDR LSB format, we need to renormalize the result. + if (colorDepth > 8) { + int rescaleFactor = 16 - colorDepth; + yuvF *= float(1 << rescaleFactor); + } + I16 yuv = CONVERT(round_pixel(yuvF), I16); commit_solid_span( dest, unpack(colorSpace.convert(V8(yuv.x), diff --git a/gfx/wr/swgl/src/swgl_ext.h b/gfx/wr/swgl/src/swgl_ext.h index 462ba24c0d38..0eb750564951 100644 --- a/gfx/wr/swgl/src/swgl_ext.h +++ b/gfx/wr/swgl/src/swgl_ext.h @@ -1029,7 +1029,7 @@ static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0, } LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0); const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); auto c = packColor(buf, color); auto* end = buf + span; for (; buf < end; buf += swgl_StepSize, uv0 += uv_step0) { @@ -1095,7 +1095,7 @@ static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0, LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0); LINEAR_QUANTIZE_UV(sampler1, uv1, uv_step1, uv_rect1, min_uv1, max_uv1); const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); auto c = packColor(buf, color); auto* end = buf + span; for (; buf < end; buf += swgl_StepSize, uv0 += uv_step0, uv1 += uv_step1) { @@ -1157,7 +1157,7 @@ static void blendYUVFallback(P* buf, int span, S0 sampler0, vec2 uv0, const mat3_scalar& rgb_from_debiased_ycbcr, int rescaleFactor, C color) { const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); for (auto* end = buf + span; buf < end; buf += swgl_StepSize, uv0 += uv_step0, uv1 += uv_step1, uv2 += uv_step2) { commit_blend_span( @@ -1255,7 +1255,7 @@ static int blendYUV(uint32_t* buf, int span, sampler2DRect sampler0, vec2 uv0, (sampler0->format == TextureFormat::R16 ? 16 : 8) - rescaleFactor; // Finally, call the inner loop of CompositeYUV. const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); linear_row_yuv( buf, inside * swgl_StepSize, sampler0, force_scalar(uv0), uv_step0.x / swgl_StepSize, sampler1, sampler2, force_scalar(uv1), diff --git a/gfx/wr/webrender/res/brush_yuv_image.glsl b/gfx/wr/webrender/res/brush_yuv_image.glsl index eb41ecb490fb..28abcab66f8d 100644 --- a/gfx/wr/webrender/res/brush_yuv_image.glsl +++ b/gfx/wr/webrender/res/brush_yuv_image.glsl @@ -60,9 +60,6 @@ void brush_vs( if (prim.channel_bit_depth > 8 && prim.yuv_format != YUV_FORMAT_P010) { vRescaleFactor = 16 - prim.channel_bit_depth; } - // Since SWGL rescales filtered YUV values to 8bpc before yuv->rgb - // conversion, don't embed a 10bpc channel multiplier into the yuv matrix. - prim.channel_bit_depth = 8; #endif YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim); diff --git a/gfx/wr/webrender/res/composite.glsl b/gfx/wr/webrender/res/composite.glsl index 576199fe5c46..4c52f36de178 100644 --- a/gfx/wr/webrender/res/composite.glsl +++ b/gfx/wr/webrender/res/composite.glsl @@ -97,9 +97,6 @@ void main(void) { if (prim.channel_bit_depth > 8 && prim.yuv_format != YUV_FORMAT_P010) { vRescaleFactor = 16 - prim.channel_bit_depth; } - // Since SWGL rescales filtered YUV values to 8bpc before yuv->rgb - // conversion, don't embed a 10bpc channel multiplier into the yuv matrix. - prim.channel_bit_depth = 8; #endif YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim); diff --git a/layout/base/nsFrameTraversal.cpp b/layout/base/nsFrameTraversal.cpp index 2f86fe55d44f..64280e10d33b 100644 --- a/layout/base/nsFrameTraversal.cpp +++ b/layout/base/nsFrameTraversal.cpp @@ -256,16 +256,17 @@ void nsFrameIterator::Next() { result = parent; } break; - } else { - result = GetParentFrameNotPopup(parent); - if (!result || IsRootFrame(result) || - (mLockScroll && result->IsScrollFrame())) { - result = nullptr; - break; - } - if (mType == ePostOrder) break; - parent = result; } + result = GetParentFrameNotPopup(parent); + if (!result || IsRootFrame(result) || + (mLockScroll && result->IsScrollFrame())) { + result = nullptr; + break; + } + if (mType == ePostOrder) { + break; + } + parent = result; } } @@ -313,7 +314,9 @@ void nsFrameIterator::Prev() { result = nullptr; break; } - if (mType == ePreOrder) break; + if (mType == ePreOrder) { + break; + } parent = result; } }