Bug 1933572 - Be more stringent about which SurfaceDescriptors we serialize for moz2d recording IPC. r=tnikkel a=pascalc

Original Revision: https://phabricator.services.mozilla.com/D244105

Differential Revision: https://phabricator.services.mozilla.com/D254904
This commit is contained in:
unknown
2025-08-08 23:50:11 +00:00
committed by rvandermeulen@mozilla.com
parent 2debf439a3
commit 2ea89a3cf2
5 changed files with 93 additions and 39 deletions

View File

@@ -5501,6 +5501,52 @@ static Matrix ComputeRotationMatrix(gfxFloat aRotatedWidth,
.PostTranslate(shiftLeftTopToOrigin); .PostTranslate(shiftLeftTopToOrigin);
} }
// -
Maybe<layers::SurfaceDescriptor> ValidSurfaceDescriptorForRemoteCanvas2d(
const layers::SurfaceDescriptor& sdConst) {
auto sd = sdConst; // Copy, so we can mutate it.
if (sd.type() != layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo) {
return Nothing();
}
auto& sdv = sd.get_SurfaceDescriptorGPUVideo();
if (sdv.type() !=
layers::SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder) {
return Nothing();
}
auto& sdrd = sdv.get_SurfaceDescriptorRemoteDecoder();
auto& subdesc = sdrd.subdesc();
switch (subdesc.type()) {
case layers::RemoteDecoderVideoSubDescriptor::Tnull_t:
break;
#ifdef XP_MACOSX
case layers::RemoteDecoderVideoSubDescriptor::
TSurfaceDescriptorMacIOSurface: {
const auto& ssd = subdesc.get_SurfaceDescriptorMacIOSurface();
if (ssd.gpuFence()) {
return Nothing();
}
break;
}
#endif
#ifdef XP_WIN
case layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorD3D10: {
if (!StaticPrefs::gfx_canvas_remote_use_draw_image_fast_path_d3d()) {
return Nothing();
}
auto& ssd = subdesc.get_SurfaceDescriptorD3D10();
ssd.handle() =
nullptr; // Not IPC-able, but it's just an optimization to have this.
break;
}
#endif
default:
return Nothing();
}
return Some(sd);
}
static Maybe<layers::SurfaceDescriptor> static Maybe<layers::SurfaceDescriptor>
MaybeGetSurfaceDescriptorForRemoteCanvas( MaybeGetSurfaceDescriptorForRemoteCanvas(
const SurfaceFromElementResult& aResult) { const SurfaceFromElementResult& aResult) {
@@ -5512,43 +5558,9 @@ MaybeGetSurfaceDescriptorForRemoteCanvas(
return Nothing(); return Nothing();
} }
Maybe<layers::SurfaceDescriptor> sd; const auto sd = aResult.mLayersImage->GetDesc();
sd = aResult.mLayersImage->GetDesc(); if (!sd) return Nothing();
if (sd.isNothing() || return ValidSurfaceDescriptorForRemoteCanvas2d(*sd);
sd.ref().type() !=
layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo) {
return Nothing();
}
auto& sdv = sd.ref().get_SurfaceDescriptorGPUVideo();
const auto& sdvType = sdv.type();
if (sdvType ==
layers::SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder) {
auto& sdrd = sdv.get_SurfaceDescriptorRemoteDecoder();
auto& subdesc = sdrd.subdesc();
const auto& subdescType = subdesc.type();
if (subdescType == layers::RemoteDecoderVideoSubDescriptor::Tnull_t) {
return sd;
}
if (subdescType == layers::RemoteDecoderVideoSubDescriptor::
TSurfaceDescriptorMacIOSurface) {
return sd;
}
if (subdescType ==
layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorD3D10 &&
StaticPrefs::gfx_canvas_remote_use_draw_image_fast_path_d3d()) {
auto& descD3D10 = subdesc.get_SurfaceDescriptorD3D10();
// Clear FileHandleWrapper, since FileHandleWrapper::mHandle could not be
// cross process delivered by using Shmem. Cross-process delivery of
// FileHandleWrapper::mHandle is not possible simply by using shmen. When
// it is tried, parent side process just causes crash during destroying
// FileHandleWrapper.
descD3D10.handle() = nullptr;
return sd;
}
}
return Nothing();
} }
// drawImage(in HTMLImageElement image, in float dx, in float dy); // drawImage(in HTMLImageElement image, in float dx, in float dy);

View File

@@ -19,6 +19,10 @@ namespace mozilla {
class ErrorResult; class ErrorResult;
namespace layers {
class SurfaceDescriptor;
} // namespace layers
namespace dom { namespace dom {
class BlobCallback; class BlobCallback;
@@ -89,6 +93,9 @@ class CanvasRenderingContextHelper {
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext; nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
}; };
Maybe<layers::SurfaceDescriptor> ValidSurfaceDescriptorForRemoteCanvas2d(
const layers::SurfaceDescriptor&);
} // namespace dom } // namespace dom
namespace CanvasUtils { namespace CanvasUtils {
bool GetCanvasContextType(const nsAString&, dom::CanvasContextType* const); bool GetCanvasContextType(const nsAString&, dom::CanvasContextType* const);

View File

@@ -17,6 +17,9 @@
#include "ScaledFontBase.h" #include "ScaledFontBase.h"
#include "SFNTData.h" #include "SFNTData.h"
#include "mozilla/dom/CanvasRenderingContextHelper.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/layers/BuildConstants.h"
#include "mozilla/layers/LayersSurfaces.h" #include "mozilla/layers/LayersSurfaces.h"
namespace mozilla { namespace mozilla {
@@ -3247,6 +3250,35 @@ inline bool RecordedDrawSurfaceDescriptor::PlayEvent(
return true; return true;
} }
template <class S>
struct ElementStreamFormat<S, layers::SurfaceDescriptor> {
using T = layers::SurfaceDescriptor;
static void Write(S& s, const T& t) {
// More rigorous version is coming soon! -Kelsey
const auto valid = dom::ValidSurfaceDescriptorForRemoteCanvas2d(t);
MOZ_RELEASE_ASSERT(valid && *valid == t);
if (kIsDebug) {
// We better be able to memcpy and destroy this if we're going to send it
// over IPC!
constexpr int A_COUPLE_TIMES = 3;
for (const auto i : IntegerRange(A_COUPLE_TIMES)) {
(void)i;
auto copy = T{};
memcpy(&copy, &t, sizeof(T));
}
}
const auto& tValid = *valid;
s.write(reinterpret_cast<const char*>(&tValid), sizeof(T));
}
static void Read(S& s, T& t) {
s.read(reinterpret_cast<char*>(&t), sizeof(T));
const auto valid = dom::ValidSurfaceDescriptorForRemoteCanvas2d(t);
MOZ_RELEASE_ASSERT(valid && *valid == t);
t = *valid;
}
};
template <class S> template <class S>
void RecordedDrawSurfaceDescriptor::Record(S& aStream) const { void RecordedDrawSurfaceDescriptor::Record(S& aStream) const {
WriteElement(aStream, mDesc); WriteElement(aStream, mDesc);

View File

@@ -7,7 +7,7 @@
#ifndef MOZILLA_GFX_RECORDINGTYPES_H_ #ifndef MOZILLA_GFX_RECORDINGTYPES_H_
#define MOZILLA_GFX_RECORDINGTYPES_H_ #define MOZILLA_GFX_RECORDINGTYPES_H_
#include <ostream> #include <type_traits>
#include <vector> #include <vector>
#include "Logging.h" #include "Logging.h"
@@ -18,12 +18,15 @@ namespace gfx {
template <class S, class T> template <class S, class T>
struct ElementStreamFormat { struct ElementStreamFormat {
static void Write(S& aStream, const T& aElement) { static void Write(S& aStream, const T& aElement) {
static_assert(std::is_trivially_copyable_v<T>);
aStream.write(reinterpret_cast<const char*>(&aElement), sizeof(T)); aStream.write(reinterpret_cast<const char*>(&aElement), sizeof(T));
} }
static void Read(S& aStream, T& aElement) { static void Read(S& aStream, T& aElement) {
static_assert(std::is_trivially_copyable_v<T>);
aStream.read(reinterpret_cast<char*>(&aElement), sizeof(T)); aStream.read(reinterpret_cast<char*>(&aElement), sizeof(T));
} }
}; };
template <class S> template <class S>
struct ElementStreamFormat<S, bool> { struct ElementStreamFormat<S, bool> {
static void Write(S& aStream, const bool& aElement) { static void Write(S& aStream, const bool& aElement) {

View File

@@ -1960,7 +1960,7 @@ inline auto MaybeFind(C& container, const K& key)
std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex( std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex(
const ColorLutKey& request) const { const ColorLutKey& request) const {
if (const auto found = MaybeFind(mColorLutTexMap, request)) { if (const auto found = gl::MaybeFind(mColorLutTexMap, request)) {
return *found; // Might be *Some(nullptr) -> nullptr! return *found; // Might be *Some(nullptr) -> nullptr!
} }