tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebRenderTypes.h (28175B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef GFX_WEBRENDERTYPES_H
      8 #define GFX_WEBRENDERTYPES_H
      9 
     10 #include "ImageTypes.h"
     11 #include "mozilla/webrender/webrender_ffi.h"
     12 #include "mozilla/Maybe.h"
     13 #include "mozilla/gfx/Matrix.h"
     14 #include "mozilla/gfx/Types.h"
     15 #include "mozilla/gfx/Tools.h"
     16 #include "mozilla/gfx/Rect.h"
     17 #include "mozilla/layers/LayersTypes.h"
     18 #include "mozilla/PodOperations.h"
     19 #include "mozilla/Range.h"
     20 #include "mozilla/ScrollGeneration.h"
     21 #include "Units.h"
     22 #include "nsIWidgetListener.h"
     23 
     24 #include <tuple>
     25 
     26 namespace mozilla {
     27 
     28 enum class StyleBorderStyle : uint8_t;
     29 enum class StyleBorderImageRepeatKeyword : uint8_t;
     30 enum class StyleImageRendering : uint8_t;
     31 
     32 namespace ipc {
     33 class ByteBuf;
     34 }  // namespace ipc
     35 
     36 namespace wr {
     37 
     38 // Using uintptr_t in C++ code for "size" types seems weird, so let's use a
     39 // better-sounding typedef. The name comes from the fact that we generally
     40 // have to deal with uintptr_t because that's what rust's usize maps to.
     41 typedef uintptr_t usize;
     42 
     43 typedef wr::WrWindowId WindowId;
     44 typedef wr::WrRemovedPipeline RemovedPipeline;
     45 
     46 class RenderedFrameIdType {};
     47 typedef layers::BaseTransactionId<RenderedFrameIdType> RenderedFrameId;
     48 
     49 typedef mozilla::Maybe<mozilla::wr::IdNamespace> MaybeIdNamespace;
     50 typedef mozilla::Maybe<mozilla::wr::ImageMask> MaybeImageMask;
     51 typedef Maybe<ExternalImageId> MaybeExternalImageId;
     52 
     53 typedef Maybe<FontInstanceOptions> MaybeFontInstanceOptions;
     54 typedef Maybe<FontInstancePlatformOptions> MaybeFontInstancePlatformOptions;
     55 
     56 struct ExternalImageKeyPair {
     57  ImageKey key;
     58  ExternalImageId id;
     59 
     60  auto MutTiedFields() { return std::tie(key, id); }
     61 };
     62 
     63 /* Generate a brand new window id and return it. */
     64 WindowId NewWindowId();
     65 
     66 inline bool WindowSizeSanityCheck(int32_t aWidth, int32_t aHeight) {
     67  if (aWidth < 0 || aWidth > wr::MAX_RENDER_TASK_SIZE || aHeight < 0 ||
     68      aHeight > wr::MAX_RENDER_TASK_SIZE) {
     69    return false;
     70  }
     71  return true;
     72 }
     73 
     74 inline DebugFlags NewDebugFlags(uint32_t aFlags) { return {aFlags}; }
     75 
     76 inline Maybe<wr::ImageFormat> SurfaceFormatToImageFormat(
     77    gfx::SurfaceFormat aFormat) {
     78  switch (aFormat) {
     79    case gfx::SurfaceFormat::R8G8B8X8:
     80      // WebRender not support RGBX8. Assert here.
     81      MOZ_ASSERT(false);
     82      return Nothing();
     83    case gfx::SurfaceFormat::R8G8B8A8:
     84      return Some(wr::ImageFormat::RGBA8);
     85    case gfx::SurfaceFormat::B8G8R8X8:
     86      // TODO: WebRender will have a BGRA + opaque flag for this but does not
     87      // have it yet (cf. issue #732).
     88    case gfx::SurfaceFormat::B8G8R8A8:
     89      return Some(wr::ImageFormat::BGRA8);
     90    case gfx::SurfaceFormat::A8:
     91      return Some(wr::ImageFormat::R8);
     92    case gfx::SurfaceFormat::A16:
     93      return Some(wr::ImageFormat::R16);
     94    case gfx::SurfaceFormat::R8G8:
     95      return Some(wr::ImageFormat::RG8);
     96    case gfx::SurfaceFormat::R16G16:
     97      return Some(wr::ImageFormat::RG16);
     98    case gfx::SurfaceFormat::UNKNOWN:
     99    default:
    100      return Nothing();
    101  }
    102 }
    103 
    104 inline gfx::SurfaceFormat ImageFormatToSurfaceFormat(ImageFormat aFormat) {
    105  switch (aFormat) {
    106    case ImageFormat::BGRA8:
    107      return gfx::SurfaceFormat::B8G8R8A8;
    108    case ImageFormat::R8:
    109      return gfx::SurfaceFormat::A8;
    110    case ImageFormat::R16:
    111      return gfx::SurfaceFormat::A16;
    112    default:
    113      return gfx::SurfaceFormat::UNKNOWN;
    114  }
    115 }
    116 
    117 // This extra piece of data is used to differentiate when spatial nodes that are
    118 // created by Gecko that have the same mFrame and PerFrameKey. This currently
    119 // only occurs with sticky display list items that are also zoomable, which
    120 // results in Gecko creating both a sticky spatial node, and then a property
    121 // animated reference frame for APZ
    122 enum class SpatialKeyKind : uint32_t {
    123  Transform,
    124  Perspective,
    125  Scroll,
    126  Sticky,
    127  ImagePipeline,
    128  APZ,
    129  ViewTransition,
    130 };
    131 
    132 // Construct a unique, persistent spatial key based on the frame tree pointer,
    133 // per-frame key and a spatial key kind. For now, this covers all the ways Gecko
    134 // creates spatial nodes. In future, we may need to be more clever with the
    135 // SpatialKeyKind.
    136 inline wr::SpatialTreeItemKey SpatialKey(uint64_t aFrame, uint32_t aPerFrameKey,
    137                                         SpatialKeyKind aKind) {
    138  return wr::SpatialTreeItemKey{
    139      aFrame, uint64_t(aPerFrameKey) | (uint64_t(aKind) << 32)};
    140 }
    141 
    142 struct ImageDescriptor : public wr::WrImageDescriptor {
    143  // We need a default constructor for ipdl serialization.
    144  ImageDescriptor() {
    145    format = (ImageFormat)0;
    146    width = 0;
    147    height = 0;
    148    stride = 0;
    149    opacity = OpacityType::HasAlphaChannel;
    150    prefer_compositor_surface = false;
    151  }
    152 
    153  ImageDescriptor(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
    154                  bool aPreferCompositorSurface = false) {
    155    format = wr::SurfaceFormatToImageFormat(aFormat).valueOr((ImageFormat)0);
    156    width = aSize.width;
    157    height = aSize.height;
    158    stride = 0;
    159    opacity = gfx::IsOpaque(aFormat) ? OpacityType::Opaque
    160                                     : OpacityType::HasAlphaChannel;
    161    prefer_compositor_surface = aPreferCompositorSurface;
    162  }
    163 
    164  ImageDescriptor(const gfx::IntSize& aSize, uint32_t aByteStride,
    165                  gfx::SurfaceFormat aFormat,
    166                  bool aPreferCompositorSurface = false) {
    167    format = wr::SurfaceFormatToImageFormat(aFormat).valueOr((ImageFormat)0);
    168    width = aSize.width;
    169    height = aSize.height;
    170    stride = aByteStride;
    171    opacity = gfx::IsOpaque(aFormat) ? OpacityType::Opaque
    172                                     : OpacityType::HasAlphaChannel;
    173    prefer_compositor_surface = aPreferCompositorSurface;
    174  }
    175 
    176  ImageDescriptor(const gfx::IntSize& aSize, uint32_t aByteStride,
    177                  gfx::SurfaceFormat aFormat, OpacityType aOpacity,
    178                  bool aPreferCompositorSurface = false) {
    179    format = wr::SurfaceFormatToImageFormat(aFormat).valueOr((ImageFormat)0);
    180    width = aSize.width;
    181    height = aSize.height;
    182    stride = aByteStride;
    183    opacity = aOpacity;
    184    prefer_compositor_surface = aPreferCompositorSurface;
    185  }
    186 };
    187 
    188 inline uint64_t AsUint64(const NativeSurfaceId& aId) {
    189  return static_cast<uint64_t>(aId._0);
    190 }
    191 
    192 // Whenever possible, use wr::WindowId instead of manipulating uint64_t.
    193 inline uint64_t AsUint64(const WindowId& aId) {
    194  return static_cast<uint64_t>(aId.mHandle);
    195 }
    196 
    197 // Whenever possible, use wr::ImageKey instead of manipulating uint64_t.
    198 inline uint64_t AsUint64(const ImageKey& aId) {
    199  return (static_cast<uint64_t>(aId.mNamespace.mHandle) << 32) +
    200         static_cast<uint64_t>(aId.mHandle);
    201 }
    202 
    203 inline ImageKey AsImageKey(const uint64_t& aId) {
    204  ImageKey imageKey;
    205  imageKey.mNamespace.mHandle = aId >> 32;
    206  imageKey.mHandle = aId;
    207  return imageKey;
    208 }
    209 
    210 // Whenever possible, use wr::FontKey instead of manipulating uint64_t.
    211 inline uint64_t AsUint64(const FontKey& aId) {
    212  return (static_cast<uint64_t>(aId.mNamespace.mHandle) << 32) +
    213         static_cast<uint64_t>(aId.mHandle);
    214 }
    215 
    216 inline FontKey AsFontKey(const uint64_t& aId) {
    217  FontKey fontKey;
    218  fontKey.mNamespace.mHandle = aId >> 32;
    219  fontKey.mHandle = aId;
    220  return fontKey;
    221 }
    222 
    223 // Whenever possible, use wr::FontInstanceKey instead of manipulating uint64_t.
    224 inline uint64_t AsUint64(const FontInstanceKey& aId) {
    225  return (static_cast<uint64_t>(aId.mNamespace.mHandle) << 32) +
    226         static_cast<uint64_t>(aId.mHandle);
    227 }
    228 
    229 inline FontInstanceKey AsFontInstanceKey(const uint64_t& aId) {
    230  FontInstanceKey instanceKey;
    231  instanceKey.mNamespace.mHandle = aId >> 32;
    232  instanceKey.mHandle = aId;
    233  return instanceKey;
    234 }
    235 
    236 // Whenever possible, use wr::PipelineId instead of manipulating uint64_t.
    237 inline uint64_t AsUint64(const PipelineId& aId) {
    238  return (static_cast<uint64_t>(aId.mNamespace) << 32) +
    239         static_cast<uint64_t>(aId.mHandle);
    240 }
    241 
    242 inline PipelineId AsPipelineId(const uint64_t& aId) {
    243  PipelineId pipeline;
    244  pipeline.mNamespace = aId >> 32;
    245  pipeline.mHandle = aId;
    246  return pipeline;
    247 }
    248 
    249 inline mozilla::layers::LayersId AsLayersId(const PipelineId& aId) {
    250  return mozilla::layers::LayersId{AsUint64(aId)};
    251 }
    252 
    253 inline PipelineId AsPipelineId(const mozilla::layers::LayersId& aId) {
    254  return AsPipelineId(uint64_t(aId));
    255 }
    256 
    257 ImageRendering ToImageRendering(StyleImageRendering);
    258 
    259 static inline FontRenderMode ToFontRenderMode(gfx::AntialiasMode aMode,
    260                                              bool aPermitSubpixelAA = true) {
    261  switch (aMode) {
    262    case gfx::AntialiasMode::NONE:
    263      return FontRenderMode::Mono;
    264    case gfx::AntialiasMode::GRAY:
    265      return FontRenderMode::Alpha;
    266    case gfx::AntialiasMode::SUBPIXEL:
    267    default:
    268      return aPermitSubpixelAA ? FontRenderMode::Subpixel
    269                               : FontRenderMode::Alpha;
    270  }
    271 }
    272 
    273 static inline MixBlendMode ToMixBlendMode(gfx::CompositionOp compositionOp) {
    274  switch (compositionOp) {
    275    case gfx::CompositionOp::OP_MULTIPLY:
    276      return MixBlendMode::Multiply;
    277    case gfx::CompositionOp::OP_SCREEN:
    278      return MixBlendMode::Screen;
    279    case gfx::CompositionOp::OP_OVERLAY:
    280      return MixBlendMode::Overlay;
    281    case gfx::CompositionOp::OP_DARKEN:
    282      return MixBlendMode::Darken;
    283    case gfx::CompositionOp::OP_LIGHTEN:
    284      return MixBlendMode::Lighten;
    285    case gfx::CompositionOp::OP_COLOR_DODGE:
    286      return MixBlendMode::ColorDodge;
    287    case gfx::CompositionOp::OP_COLOR_BURN:
    288      return MixBlendMode::ColorBurn;
    289    case gfx::CompositionOp::OP_HARD_LIGHT:
    290      return MixBlendMode::HardLight;
    291    case gfx::CompositionOp::OP_SOFT_LIGHT:
    292      return MixBlendMode::SoftLight;
    293    case gfx::CompositionOp::OP_DIFFERENCE:
    294      return MixBlendMode::Difference;
    295    case gfx::CompositionOp::OP_EXCLUSION:
    296      return MixBlendMode::Exclusion;
    297    case gfx::CompositionOp::OP_HUE:
    298      return MixBlendMode::Hue;
    299    case gfx::CompositionOp::OP_SATURATION:
    300      return MixBlendMode::Saturation;
    301    case gfx::CompositionOp::OP_COLOR:
    302      return MixBlendMode::Color;
    303    case gfx::CompositionOp::OP_LUMINOSITY:
    304      return MixBlendMode::Luminosity;
    305    case gfx::CompositionOp::OP_ADD:
    306      return MixBlendMode::PlusLighter;
    307    default:
    308      return MixBlendMode::Normal;
    309  }
    310 }
    311 
    312 static inline wr::ColorF ToColorF(const gfx::DeviceColor& color) {
    313  wr::ColorF c;
    314  c.r = color.r;
    315  c.g = color.g;
    316  c.b = color.b;
    317  c.a = color.a;
    318  return c;
    319 }
    320 
    321 static inline wr::LayoutPoint ToLayoutPoint(
    322    const mozilla::LayoutDevicePoint& point) {
    323  wr::LayoutPoint p;
    324  p.x = point.x;
    325  p.y = point.y;
    326  return p;
    327 }
    328 
    329 static inline wr::LayoutPoint ToLayoutPoint(
    330    const mozilla::LayoutDeviceIntPoint& point) {
    331  return ToLayoutPoint(LayoutDevicePoint(point));
    332 }
    333 
    334 static inline wr::WorldPoint ToWorldPoint(const mozilla::ScreenPoint& point) {
    335  wr::WorldPoint p;
    336  p.x = point.x;
    337  p.y = point.y;
    338  return p;
    339 }
    340 
    341 static inline wr::LayoutVector2D ToLayoutVector2D(
    342    const mozilla::LayoutDevicePoint& point) {
    343  wr::LayoutVector2D p;
    344  p.x = point.x;
    345  p.y = point.y;
    346  return p;
    347 }
    348 
    349 static inline wr::LayoutVector2D ToLayoutVector2D(
    350    const mozilla::LayoutDeviceIntPoint& point) {
    351  return ToLayoutVector2D(LayoutDevicePoint(point));
    352 }
    353 
    354 static inline wr::LayoutRect ToLayoutRect(
    355    const mozilla::LayoutDeviceRect& rect) {
    356  wr::LayoutRect r;
    357  r.min.x = rect.X();
    358  r.min.y = rect.Y();
    359  r.max.x = rect.X() + rect.Width();
    360  r.max.y = rect.Y() + rect.Height();
    361  return r;
    362 }
    363 
    364 static inline wr::LayoutRect ToLayoutRect(const gfx::Rect& rect) {
    365  wr::LayoutRect r;
    366  r.min.x = rect.X();
    367  r.min.y = rect.Y();
    368  r.max.x = rect.X() + rect.Width();
    369  r.max.y = rect.Y() + rect.Height();
    370  return r;
    371 }
    372 
    373 static inline wr::DeviceIntRect ToDeviceIntRect(
    374    const mozilla::ImageIntRect& rect) {
    375  wr::DeviceIntRect r;
    376  r.min.x = rect.X();
    377  r.min.y = rect.Y();
    378  r.max.x = rect.X() + rect.Width();
    379  r.max.y = rect.Y() + rect.Height();
    380  return r;
    381 }
    382 
    383 // TODO: should be const LayoutDeviceIntRect instead of ImageIntRect
    384 static inline wr::LayoutIntRect ToLayoutIntRect(
    385    const mozilla::ImageIntRect& rect) {
    386  wr::LayoutIntRect r;
    387  r.min.x = rect.X();
    388  r.min.y = rect.Y();
    389  r.max.x = rect.X() + rect.Width();
    390  r.max.y = rect.Y() + rect.Height();
    391  return r;
    392 }
    393 
    394 static inline wr::LayoutRect ToLayoutRect(
    395    const mozilla::LayoutDeviceIntRect& rect) {
    396  return ToLayoutRect(IntRectToRect(rect));
    397 }
    398 
    399 static inline wr::LayoutRect IntersectLayoutRect(const wr::LayoutRect& aRect,
    400                                                 const wr::LayoutRect& aOther) {
    401  wr::LayoutRect r;
    402  r.min.x = std::max(aRect.min.x, aOther.min.x);
    403  r.min.y = std::max(aRect.min.y, aOther.min.y);
    404  r.max.x = std::min(aRect.max.x, aOther.max.x);
    405  r.max.y = std::min(aRect.max.y, aOther.max.y);
    406 
    407  if (r.max.x < r.min.x || r.max.y < r.min.y) {
    408    r.max.x = r.min.x;
    409    r.max.y = r.min.y;
    410  }
    411  return r;
    412 }
    413 
    414 static inline wr::LayoutSize ToLayoutSize(
    415    const mozilla::LayoutDeviceSize& size) {
    416  wr::LayoutSize ls;
    417  ls.width = size.width;
    418  ls.height = size.height;
    419  return ls;
    420 }
    421 
    422 static inline wr::ComplexClipRegion ToComplexClipRegion(
    423    const gfx::RoundedRect& rect) {
    424  wr::ComplexClipRegion ret;
    425  ret.rect = ToLayoutRect(rect.rect);
    426  ret.radii.top_left = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
    427      rect.corners.radii[mozilla::eCornerTopLeft]));
    428  ret.radii.top_right = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
    429      rect.corners.radii[mozilla::eCornerTopRight]));
    430  ret.radii.bottom_left = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
    431      rect.corners.radii[mozilla::eCornerBottomLeft]));
    432  ret.radii.bottom_right = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
    433      rect.corners.radii[mozilla::eCornerBottomRight]));
    434  ret.mode = wr::ClipMode::Clip;
    435  return ret;
    436 }
    437 
    438 static inline wr::ComplexClipRegion SimpleRadii(const wr::LayoutRect& aRect,
    439                                                float aRadii) {
    440  wr::ComplexClipRegion ret;
    441  wr::LayoutSize radii{aRadii, aRadii};
    442  ret.rect = aRect;
    443  ret.radii.top_left = radii;
    444  ret.radii.top_right = radii;
    445  ret.radii.bottom_left = radii;
    446  ret.radii.bottom_right = radii;
    447  ret.mode = wr::ClipMode::Clip;
    448  return ret;
    449 }
    450 
    451 static inline wr::LayoutSize ToLayoutSize(
    452    const mozilla::LayoutDeviceIntSize& size) {
    453  return ToLayoutSize(LayoutDeviceSize(size));
    454 }
    455 
    456 template <class S, class T>
    457 static inline wr::LayoutTransform ToLayoutTransform(
    458    const gfx::Matrix4x4Typed<S, T>& m) {
    459  wr::LayoutTransform transform;
    460  transform.m11 = m._11;
    461  transform.m12 = m._12;
    462  transform.m13 = m._13;
    463  transform.m14 = m._14;
    464  transform.m21 = m._21;
    465  transform.m22 = m._22;
    466  transform.m23 = m._23;
    467  transform.m24 = m._24;
    468  transform.m31 = m._31;
    469  transform.m32 = m._32;
    470  transform.m33 = m._33;
    471  transform.m34 = m._34;
    472  transform.m41 = m._41;
    473  transform.m42 = m._42;
    474  transform.m43 = m._43;
    475  transform.m44 = m._44;
    476  return transform;
    477 }
    478 
    479 wr::BorderStyle ToBorderStyle(StyleBorderStyle style);
    480 
    481 static inline wr::BorderSide ToBorderSide(const gfx::DeviceColor& color,
    482                                          StyleBorderStyle style) {
    483  wr::BorderSide bs;
    484  bs.color = ToColorF(color);
    485  bs.style = ToBorderStyle(style);
    486  return bs;
    487 }
    488 
    489 static inline wr::BorderRadius EmptyBorderRadius() {
    490  wr::BorderRadius br;
    491  PodZero(&br);
    492  return br;
    493 }
    494 
    495 static inline wr::BorderRadius ToBorderRadius(
    496    const LayoutDeviceSize& topLeft, const LayoutDeviceSize& topRight,
    497    const LayoutDeviceSize& bottomLeft, const LayoutDeviceSize& bottomRight) {
    498  wr::BorderRadius br;
    499  br.top_left = ToLayoutSize(topLeft);
    500  br.top_right = ToLayoutSize(topRight);
    501  br.bottom_left = ToLayoutSize(bottomLeft);
    502  br.bottom_right = ToLayoutSize(bottomRight);
    503  return br;
    504 }
    505 
    506 static inline wr::BorderRadius ToBorderRadius(
    507    const gfx::RectCornerRadii& aRadii) {
    508  return ToBorderRadius(
    509      LayoutDeviceSize::FromUnknownSize(aRadii.TopLeft()),
    510      LayoutDeviceSize::FromUnknownSize(aRadii.TopRight()),
    511      LayoutDeviceSize::FromUnknownSize(aRadii.BottomLeft()),
    512      LayoutDeviceSize::FromUnknownSize(aRadii.BottomRight()));
    513 }
    514 
    515 static inline wr::ComplexClipRegion ToComplexClipRegion(
    516    const nsRect& aRect, const nsRectCornerRadii& aRadii,
    517    int32_t aAppUnitsPerDevPixel) {
    518  wr::ComplexClipRegion ret;
    519  ret.rect =
    520      ToLayoutRect(LayoutDeviceRect::FromAppUnits(aRect, aAppUnitsPerDevPixel));
    521  ret.radii = ToBorderRadius(
    522      LayoutDeviceSize::FromAppUnits(aRadii.TopLeft(), aAppUnitsPerDevPixel),
    523      LayoutDeviceSize::FromAppUnits(aRadii.TopRight(), aAppUnitsPerDevPixel),
    524      LayoutDeviceSize::FromAppUnits(aRadii.BottomLeft(), aAppUnitsPerDevPixel),
    525      LayoutDeviceSize::FromAppUnits(aRadii.BottomRight(),
    526                                     aAppUnitsPerDevPixel));
    527  ret.mode = ClipMode::Clip;
    528  return ret;
    529 }
    530 
    531 static inline wr::DeviceIntSideOffsets ToDeviceIntSideOffsets(int32_t top,
    532                                                              int32_t right,
    533                                                              int32_t bottom,
    534                                                              int32_t left) {
    535  wr::DeviceIntSideOffsets offset;
    536  offset.top = top;
    537  offset.right = right;
    538  offset.bottom = bottom;
    539  offset.left = left;
    540  return offset;
    541 }
    542 
    543 static inline wr::LayoutSideOffsets ToLayoutSideOffsets(float top, float right,
    544                                                        float bottom,
    545                                                        float left) {
    546  wr::LayoutSideOffsets offset;
    547  offset.top = top;
    548  offset.right = right;
    549  offset.bottom = bottom;
    550  offset.left = left;
    551  return offset;
    552 }
    553 
    554 static inline wr::LayoutSideOffsets ToLayoutSideOffsets(
    555    const gfx::Margin& aMargin) {
    556  return ToLayoutSideOffsets(aMargin.top, aMargin.right, aMargin.bottom,
    557                             aMargin.left);
    558 }
    559 
    560 static inline wr::LayoutSideOffsets ToBorderWidths(float top, float right,
    561                                                   float bottom, float left) {
    562  return ToLayoutSideOffsets(top, right, bottom, left);
    563 }
    564 
    565 static inline wr::LayoutSideOffsets ToBorderWidths(const gfx::Margin& aMargin) {
    566  return ToLayoutSideOffsets(aMargin);
    567 }
    568 
    569 wr::RepeatMode ToRepeatMode(StyleBorderImageRepeatKeyword);
    570 
    571 template <class S, class T>
    572 static inline wr::WrTransformProperty ToWrTransformProperty(
    573    uint64_t id, const gfx::Matrix4x4Typed<S, T>& transform) {
    574  wr::WrTransformProperty prop;
    575  prop.id = id;
    576  prop.value = ToLayoutTransform(transform);
    577  return prop;
    578 }
    579 
    580 static inline wr::WrOpacityProperty ToWrOpacityProperty(uint64_t id,
    581                                                        const float opacity) {
    582  wr::WrOpacityProperty prop;
    583  prop.id = id;
    584  prop.value = opacity;
    585  return prop;
    586 }
    587 
    588 static inline wr::WrColorProperty ToWrColorProperty(
    589    uint64_t id, const gfx::DeviceColor& color) {
    590  wr::WrColorProperty prop;
    591  prop.id = id;
    592  prop.value = ToColorF(color);
    593  return prop;
    594 }
    595 
    596 // Whenever possible, use wr::ExternalImageId instead of manipulating uint64_t.
    597 inline uint64_t AsUint64(const ExternalImageId& aId) {
    598  return static_cast<uint64_t>(aId._0);
    599 }
    600 
    601 static inline ExternalImageId ToExternalImageId(uint64_t aID) {
    602  ExternalImageId Id;
    603  Id._0 = aID;
    604  return Id;
    605 }
    606 
    607 static inline wr::WrExternalImage RawDataToWrExternalImage(const uint8_t* aBuff,
    608                                                           size_t size) {
    609  return wr::WrExternalImage{
    610      wr::WrExternalImageType::RawData, 0, 0.0f, 0.0f, 0.0f, 0.0f, aBuff, size};
    611 }
    612 
    613 static inline wr::WrExternalImage NativeTextureToWrExternalImage(
    614    uint32_t aHandle, float u0, float v0, float u1, float v1) {
    615  return wr::WrExternalImage{wr::WrExternalImageType::NativeTexture,
    616                             aHandle,
    617                             u0,
    618                             v0,
    619                             u1,
    620                             v1,
    621                             nullptr,
    622                             0};
    623 }
    624 
    625 static inline wr::WrExternalImage InvalidToWrExternalImage() {
    626  return wr::WrExternalImage{
    627      wr::WrExternalImageType::Invalid, 0, 0, 0, 0, 0, nullptr, 0};
    628 }
    629 
    630 inline wr::ByteSlice RangeToByteSlice(mozilla::Range<uint8_t> aRange) {
    631  return wr::ByteSlice{aRange.begin().get(), aRange.length()};
    632 }
    633 
    634 inline mozilla::Range<const uint8_t> ByteSliceToRange(wr::ByteSlice aWrSlice) {
    635  return mozilla::Range<const uint8_t>(aWrSlice.buffer, aWrSlice.len);
    636 }
    637 
    638 inline mozilla::Range<uint8_t> MutByteSliceToRange(wr::MutByteSlice aWrSlice) {
    639  return mozilla::Range<uint8_t>(aWrSlice.buffer, aWrSlice.len);
    640 }
    641 
    642 void Assign_WrVecU8(wr::WrVecU8& aVec, mozilla::ipc::ByteBuf&& aOther);
    643 
    644 template <typename T>
    645 struct Vec;
    646 
    647 template <>
    648 struct Vec<uint8_t> final {
    649  wr::WrVecU8 inner;
    650  Vec() { SetEmpty(); }
    651  Vec(Vec&) = delete;
    652  Vec(Vec&& src) {
    653    inner = src.inner;
    654    src.SetEmpty();
    655  }
    656 
    657  explicit Vec(mozilla::ipc::ByteBuf&& aSrc) {
    658    Assign_WrVecU8(inner, std::move(aSrc));
    659  }
    660 
    661  Vec& operator=(Vec&& src) {
    662    inner = src.inner;
    663    src.SetEmpty();
    664    return *this;
    665  }
    666 
    667  wr::WrVecU8 Extract() {
    668    wr::WrVecU8 ret = inner;
    669    SetEmpty();
    670    return ret;
    671  }
    672 
    673  void SetEmpty() {
    674    // We need to ensure that (data, capacity, length) always remain valid
    675    // to be passed to Vec::from_raw_parts. In particular, this requires that
    676    // inner.data is always non-null, even for zero-capacity Vecs.
    677 
    678    // Set inner.data to the equivalent of ptr::NonNull::dangling().as_ptr(),
    679    // i.e. a non-null value that is aligned with T's alignment, T being u8
    680    // here.
    681    inner.data = (uint8_t*)1;
    682    inner.capacity = 0;
    683    inner.length = 0;
    684  }
    685 
    686  uint8_t* Data() { return inner.data; }
    687 
    688  size_t Length() { return inner.length; }
    689 
    690  size_t Capacity() { return inner.capacity; }
    691 
    692  Range<uint8_t> GetRange() { return Range<uint8_t>(Data(), Length()); }
    693 
    694  void PushBytes(Range<uint8_t> aBytes) {
    695    wr_vec_u8_push_bytes(&inner, RangeToByteSlice(aBytes));
    696  }
    697 
    698  void Reserve(size_t aLength) { wr_vec_u8_reserve(&inner, aLength); }
    699 
    700  ~Vec() {
    701    if (inner.data) {
    702      wr_vec_u8_free(inner);
    703    }
    704  }
    705 };
    706 
    707 struct ByteBuffer {
    708  ByteBuffer(size_t aLength, uint8_t* aData)
    709      : mLength(aLength), mData(aData), mOwned(false) {}
    710 
    711  // XXX: this is a bit of hack that assumes
    712  // the allocators are the same
    713  explicit ByteBuffer(VecU8&& vec) {
    714    if (vec.inner.capacity) {
    715      mLength = vec.inner.length;
    716      mData = vec.inner.data;
    717      vec.inner.data = nullptr;
    718      vec.inner.capacity = 0;
    719      mOwned = true;
    720    } else {
    721      mOwned = false;
    722      mData = nullptr;
    723      mLength = 0;
    724    }
    725  }
    726 
    727  ByteBuffer(ByteBuffer&& aFrom)
    728      : mLength(aFrom.mLength), mData(aFrom.mData), mOwned(aFrom.mOwned) {
    729    aFrom.mLength = 0;
    730    aFrom.mData = nullptr;
    731    aFrom.mOwned = false;
    732  }
    733 
    734  ByteBuffer(ByteBuffer& aFrom)
    735      : mLength(aFrom.mLength), mData(aFrom.mData), mOwned(aFrom.mOwned) {
    736    aFrom.mLength = 0;
    737    aFrom.mData = nullptr;
    738    aFrom.mOwned = false;
    739  }
    740 
    741  ByteBuffer() : mLength(0), mData(nullptr), mOwned(false) {}
    742 
    743  bool Allocate(size_t aLength) {
    744    MOZ_ASSERT(mData == nullptr);
    745    mData = (uint8_t*)malloc(aLength);
    746    if (!mData) {
    747      return false;
    748    }
    749    mLength = aLength;
    750    mOwned = true;
    751    return true;
    752  }
    753 
    754  ~ByteBuffer() {
    755    if (mData && mOwned) {
    756      free(mData);
    757    }
    758  }
    759 
    760  const Range<uint8_t> AsSlice() const {
    761    return Range<uint8_t>(mData, mLength);
    762  }
    763 
    764  Range<uint8_t> AsSlice() { return Range<uint8_t>(mData, mLength); }
    765 
    766  bool operator==(const ByteBuffer& other) const {
    767    return mLength == other.mLength && !(memcmp(mData, other.mData, mLength));
    768  }
    769 
    770  size_t mLength;
    771  uint8_t* mData;
    772  bool mOwned;
    773 };
    774 
    775 struct BuiltDisplayList {
    776  wr::VecU8 dl_items;
    777  wr::VecU8 dl_cache;
    778  wr::VecU8 dl_spatial_tree;
    779  wr::BuiltDisplayListDescriptor dl_desc;
    780 };
    781 
    782 // Corresponds to a clip id for a clip chain in webrender. Similar to
    783 // WrClipId but a separate struct so we don't get them mixed up in C++.
    784 struct WrClipChainId {
    785  uint64_t id;
    786 
    787  bool operator==(const WrClipChainId& other) const { return id == other.id; }
    788 
    789  static WrClipChainId Empty() {
    790    WrClipChainId id = {0};
    791    return id;
    792  }
    793 };
    794 
    795 WrSpatialId RootScrollNode();
    796 WrSpaceAndClipChain RootScrollNodeWithChain();
    797 WrSpaceAndClipChain InvalidScrollNodeWithChain();
    798 
    799 enum class WebRenderError : int8_t {
    800  INITIALIZE = 0,
    801  MAKE_CURRENT,
    802  RENDER,
    803  NEW_SURFACE,
    804  BEGIN_DRAW,
    805  VIDEO_OVERLAY,
    806  VIDEO_HW_OVERLAY,
    807  VIDEO_SW_OVERLAY,
    808  DCOMP_TEXTURE_OVERLAY,
    809  EXCESSIVE_RESETS,
    810 
    811  Sentinel /* this must be last for serialization purposes. */
    812 };
    813 
    814 static inline wr::WrYuvColorSpace ToWrYuvColorSpace(
    815    gfx::YUVColorSpace aYUVColorSpace) {
    816  switch (aYUVColorSpace) {
    817    case gfx::YUVColorSpace::BT601:
    818      return wr::WrYuvColorSpace::Rec601;
    819    case gfx::YUVColorSpace::BT709:
    820      return wr::WrYuvColorSpace::Rec709;
    821    case gfx::YUVColorSpace::BT2020:
    822      return wr::WrYuvColorSpace::Rec2020;
    823    case gfx::YUVColorSpace::Identity:
    824      return wr::WrYuvColorSpace::Identity;
    825    default:
    826      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid YUVColorSpace.");
    827  }
    828  return wr::WrYuvColorSpace::Rec601;
    829 }
    830 
    831 // TODO: Use YUVRangedColorSpace instead of assuming ColorRange::LIMITED.
    832 static inline wr::YuvRangedColorSpace ToWrYuvRangedColorSpace(
    833    gfx::YUVRangedColorSpace aFrom) {
    834  switch (aFrom) {
    835    case gfx::YUVRangedColorSpace::BT601_Narrow:
    836      return wr::YuvRangedColorSpace::Rec601Narrow;
    837    case gfx::YUVRangedColorSpace::BT601_Full:
    838      return wr::YuvRangedColorSpace::Rec601Full;
    839    case gfx::YUVRangedColorSpace::BT709_Narrow:
    840      return wr::YuvRangedColorSpace::Rec709Narrow;
    841    case gfx::YUVRangedColorSpace::BT709_Full:
    842      return wr::YuvRangedColorSpace::Rec709Full;
    843    case gfx::YUVRangedColorSpace::BT2020_Narrow:
    844      return wr::YuvRangedColorSpace::Rec2020Narrow;
    845    case gfx::YUVRangedColorSpace::BT2020_Full:
    846      return wr::YuvRangedColorSpace::Rec2020Full;
    847    case gfx::YUVRangedColorSpace::GbrIdentity:
    848      break;
    849    default:
    850      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid YUVColorSpace.");
    851      break;
    852  }
    853  return wr::YuvRangedColorSpace::GbrIdentity;
    854 }
    855 
    856 static inline wr::WrColorDepth ToWrColorDepth(gfx::ColorDepth aColorDepth) {
    857  switch (aColorDepth) {
    858    case gfx::ColorDepth::COLOR_8:
    859      return wr::WrColorDepth::Color8;
    860    case gfx::ColorDepth::COLOR_10:
    861      return wr::WrColorDepth::Color10;
    862    case gfx::ColorDepth::COLOR_12:
    863      return wr::WrColorDepth::Color12;
    864    case gfx::ColorDepth::COLOR_16:
    865      return wr::WrColorDepth::Color16;
    866    default:
    867      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid color depth value.");
    868  }
    869  return wr::WrColorDepth::Color8;
    870 }
    871 
    872 static inline wr::WrColorRange ToWrColorRange(gfx::ColorRange aColorRange) {
    873  switch (aColorRange) {
    874    case gfx::ColorRange::LIMITED:
    875      return wr::WrColorRange::Limited;
    876    case gfx::ColorRange::FULL:
    877      return wr::WrColorRange::Full;
    878    default:
    879      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid color range value.");
    880      return wr ::WrColorRange::Limited;
    881  }
    882 }
    883 
    884 static inline wr::SyntheticItalics DegreesToSyntheticItalics(float aDegrees) {
    885  wr::SyntheticItalics synthetic_italics;
    886  synthetic_italics.angle =
    887      int16_t(std::clamp(aDegrees, -89.0f, 89.0f) * 256.0f);
    888  return synthetic_italics;
    889 }
    890 
    891 static inline wr::APZScrollGeneration ToWrAPZScrollGeneration(
    892    const mozilla::APZScrollGeneration& aGeneration) {
    893  return wr::APZScrollGeneration(aGeneration.Raw());
    894 }
    895 
    896 static inline wr::HasScrollLinkedEffect ToWrHasScrollLinkedEffect(
    897    bool aHasScrollLinkedEffect) {
    898  return aHasScrollLinkedEffect ? wr::HasScrollLinkedEffect::Yes
    899                                : wr::HasScrollLinkedEffect::No;
    900 }
    901 
    902 enum class ExternalImageSource : uint8_t { Unknown = 0, SharedSurfaces, Last };
    903 
    904 }  // namespace wr
    905 }  // namespace mozilla
    906 
    907 namespace std {
    908 template <>
    909 struct hash<mozilla::wr::WrSpatialId> {
    910  std::size_t operator()(mozilla::wr::WrSpatialId const& aKey) const noexcept {
    911    return std::hash<size_t>{}(aKey.id);
    912  }
    913 };
    914 }  // namespace std
    915 
    916 #endif /* GFX_WEBRENDERTYPES_H */