Revision 229241a2c767c7f741b51f486502ec456c0ab329 authored by Bob Owen on 06 March 2020, 22:10:52 UTC, committed by Bob Owen on 06 March 2020, 22:10:52 UTC
When we are running from a network drive the new feature in part 1 doesn't work.
So this uses DuplicateHandle instead of OpenThread to get the thread handle used
by the profiler.
It also removes a DuplicateHandle THREAD_ALL_ACCESS call that also fails and a
DuplicateHandle to get a real process handle, which only seems to have been to
fix something on Windows XP.
The handle passed in is always the profiler one, so already has the necessary
permissions. If no thread handle is passed then the pseudo handle is used.
1 parent 40f9041
Raw File
WebRenderTypes.h
/* -*- 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 GFX_WEBRENDERTYPES_H
#define GFX_WEBRENDERTYPES_H

#include "ImageTypes.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/EnumSet.h"
#include "mozilla/Maybe.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Range.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Variant.h"
#include "Units.h"
#include "nsStyleConsts.h"

namespace mozilla {

namespace ipc {
class ByteBuf;
}  // namespace ipc

namespace wr {

// Using uintptr_t in C++ code for "size" types seems weird, so let's use a
// better-sounding typedef. The name comes from the fact that we generally
// have to deal with uintptr_t because that's what rust's usize maps to.
typedef uintptr_t usize;

typedef wr::WrWindowId WindowId;
typedef wr::WrPipelineId PipelineId;
typedef wr::WrDocumentId DocumentId;
typedef wr::WrRemovedPipeline RemovedPipeline;
typedef wr::WrImageKey ImageKey;
typedef wr::WrFontKey FontKey;
typedef wr::WrFontInstanceKey FontInstanceKey;
typedef wr::WrEpoch Epoch;
typedef wr::WrExternalImageId ExternalImageId;

typedef mozilla::Maybe<mozilla::wr::IdNamespace> MaybeIdNamespace;
typedef mozilla::Maybe<mozilla::wr::ImageMask> MaybeImageMask;
typedef Maybe<ExternalImageId> MaybeExternalImageId;

typedef Maybe<FontInstanceOptions> MaybeFontInstanceOptions;
typedef Maybe<FontInstancePlatformOptions> MaybeFontInstancePlatformOptions;

struct ExternalImageKeyPair {
  ImageKey key;
  ExternalImageId id;
};

/* Generate a brand new window id and return it. */
WindowId NewWindowId();

MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
    RenderRoot, uint8_t,
    (
        // The default render root - within the parent process, this refers
        // to everything within the top chrome area (urlbar, tab strip, etc.).
        // Within the content process, this refers to the content area. Any
        // system that multiplexes data streams from different processes is
        // responsible for converting RenderRoot::Default into
        // RenderRoot::Content (or whatever value is appropriate)
        Default,

        // Everything below the chrome - even if it is not coming from a content
        // process. For example. the devtools, sidebars, and status panel are
        // traditionally part of the "chrome," but are assigned a renderroot of
        // RenderRoot::Content because they occupy screen space in the "content"
        // area of the browser (visually situated below the "chrome" area).
        Content));

typedef EnumSet<RenderRoot, uint8_t> RenderRootSet;

// For simple iteration of all render roots
const Array<RenderRoot, kRenderRootCount> kRenderRoots(RenderRoot::Default,
                                                       RenderRoot::Content);

const Array<RenderRoot, kRenderRootCount - 1> kNonDefaultRenderRoots(
    RenderRoot::Content);

template <typename T>
class RenderRootArray : public Array<T, kRenderRootCount> {
  typedef Array<T, kRenderRootCount> Super;

 public:
  RenderRootArray() {
    if (IsPod<T>::value) {
      // Ensure primitive types get initialized to 0/false.
      PodArrayZero(*this);
    }  // else C++ will default-initialize the array elements for us
  }

  T& operator[](wr::RenderRoot aIndex) {
    return (*(Super*)this)[(size_t)aIndex];
  }

  const T& operator[](wr::RenderRoot aIndex) const {
    return (*(Super*)this)[(size_t)aIndex];
  }

  T& operator[](size_t aIndex) = delete;
  const T& operator[](size_t aIndex) const = delete;
};

template <typename T>
class NonDefaultRenderRootArray : public Array<T, kRenderRootCount - 1> {
  typedef Array<T, kRenderRootCount - 1> Super;

 public:
  NonDefaultRenderRootArray() {
    // See RenderRootArray constructor
    if (IsPod<T>::value) {
      PodArrayZero(*this);
    }
  }

  T& operator[](wr::RenderRoot aIndex) {
    return (*(Super*)this)[(size_t)aIndex - 1];
  }

  const T& operator[](wr::RenderRoot aIndex) const {
    return (*(Super*)this)[(size_t)aIndex - 1];
  }

  T& operator[](size_t aIndex) = delete;
  const T& operator[](size_t aIndex) const = delete;
};

RenderRoot RenderRootFromId(DocumentId id);

inline DebugFlags NewDebugFlags(uint32_t aFlags) { return {aFlags}; }

inline Maybe<wr::ImageFormat> SurfaceFormatToImageFormat(
    gfx::SurfaceFormat aFormat) {
  switch (aFormat) {
    case gfx::SurfaceFormat::R8G8B8X8:
      // WebRender not support RGBX8. Assert here.
      MOZ_ASSERT(false);
      return Nothing();
    case gfx::SurfaceFormat::R8G8B8A8:
      return Some(wr::ImageFormat::RGBA8);
    case gfx::SurfaceFormat::B8G8R8X8:
      // TODO: WebRender will have a BGRA + opaque flag for this but does not
      // have it yet (cf. issue #732).
    case gfx::SurfaceFormat::B8G8R8A8:
      return Some(wr::ImageFormat::BGRA8);
    case gfx::SurfaceFormat::A8:
      return Some(wr::ImageFormat::R8);
    case gfx::SurfaceFormat::A16:
      return Some(wr::ImageFormat::R16);
    case gfx::SurfaceFormat::R8G8:
      return Some(wr::ImageFormat::RG8);
    case gfx::SurfaceFormat::R16G16:
      return Some(wr::ImageFormat::RG16);
    case gfx::SurfaceFormat::UNKNOWN:
    default:
      return Nothing();
  }
}

inline gfx::SurfaceFormat ImageFormatToSurfaceFormat(ImageFormat aFormat) {
  switch (aFormat) {
    case ImageFormat::BGRA8:
      return gfx::SurfaceFormat::B8G8R8A8;
    case ImageFormat::R8:
      return gfx::SurfaceFormat::A8;
    case ImageFormat::R16:
      return gfx::SurfaceFormat::A16;
    default:
      return gfx::SurfaceFormat::UNKNOWN;
  }
}

struct ImageDescriptor : public wr::WrImageDescriptor {
  // We need a default constructor for ipdl serialization.
  ImageDescriptor() {
    format = (ImageFormat)0;
    width = 0;
    height = 0;
    stride = 0;
    opacity = OpacityType::HasAlphaChannel;
  }

  ImageDescriptor(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat) {
    format = wr::SurfaceFormatToImageFormat(aFormat).value();
    width = aSize.width;
    height = aSize.height;
    stride = 0;
    opacity = gfx::IsOpaque(aFormat) ? OpacityType::Opaque
                                     : OpacityType::HasAlphaChannel;
  }

  ImageDescriptor(const gfx::IntSize& aSize, uint32_t aByteStride,
                  gfx::SurfaceFormat aFormat) {
    format = wr::SurfaceFormatToImageFormat(aFormat).value();
    width = aSize.width;
    height = aSize.height;
    stride = aByteStride;
    opacity = gfx::IsOpaque(aFormat) ? OpacityType::Opaque
                                     : OpacityType::HasAlphaChannel;
  }

  ImageDescriptor(const gfx::IntSize& aSize, uint32_t aByteStride,
                  gfx::SurfaceFormat aFormat, OpacityType aOpacity) {
    format = wr::SurfaceFormatToImageFormat(aFormat).value();
    width = aSize.width;
    height = aSize.height;
    stride = aByteStride;
    opacity = aOpacity;
  }
};

// Whenever possible, use wr::WindowId instead of manipulating uint64_t.
inline uint64_t AsUint64(const WindowId& aId) {
  return static_cast<uint64_t>(aId.mHandle);
}

// Whenever possible, use wr::ImageKey instead of manipulating uint64_t.
inline uint64_t AsUint64(const ImageKey& aId) {
  return (static_cast<uint64_t>(aId.mNamespace.mHandle) << 32) +
         static_cast<uint64_t>(aId.mHandle);
}

inline ImageKey AsImageKey(const uint64_t& aId) {
  ImageKey imageKey;
  imageKey.mNamespace.mHandle = aId >> 32;
  imageKey.mHandle = aId;
  return imageKey;
}

// Whenever possible, use wr::FontKey instead of manipulating uint64_t.
inline uint64_t AsUint64(const FontKey& aId) {
  return (static_cast<uint64_t>(aId.mNamespace.mHandle) << 32) +
         static_cast<uint64_t>(aId.mHandle);
}

inline FontKey AsFontKey(const uint64_t& aId) {
  FontKey fontKey;
  fontKey.mNamespace.mHandle = aId >> 32;
  fontKey.mHandle = aId;
  return fontKey;
}

// Whenever possible, use wr::FontInstanceKey instead of manipulating uint64_t.
inline uint64_t AsUint64(const FontInstanceKey& aId) {
  return (static_cast<uint64_t>(aId.mNamespace.mHandle) << 32) +
         static_cast<uint64_t>(aId.mHandle);
}

inline FontInstanceKey AsFontInstanceKey(const uint64_t& aId) {
  FontInstanceKey instanceKey;
  instanceKey.mNamespace.mHandle = aId >> 32;
  instanceKey.mHandle = aId;
  return instanceKey;
}

// Whenever possible, use wr::PipelineId instead of manipulating uint64_t.
inline uint64_t AsUint64(const PipelineId& aId) {
  return (static_cast<uint64_t>(aId.mNamespace) << 32) +
         static_cast<uint64_t>(aId.mHandle);
}

inline PipelineId AsPipelineId(const uint64_t& aId) {
  PipelineId pipeline;
  pipeline.mNamespace = aId >> 32;
  pipeline.mHandle = aId;
  return pipeline;
}

inline mozilla::layers::LayersId AsLayersId(const PipelineId& aId) {
  return mozilla::layers::LayersId{AsUint64(aId)};
}

inline PipelineId AsPipelineId(const mozilla::layers::LayersId& aId) {
  return AsPipelineId(uint64_t(aId));
}

inline ImageRendering ToImageRendering(gfx::SamplingFilter aFilter) {
  return aFilter == gfx::SamplingFilter::POINT ? ImageRendering::Pixelated
                                               : ImageRendering::Auto;
}

static inline FontRenderMode ToFontRenderMode(gfx::AntialiasMode aMode,
                                              bool aPermitSubpixelAA = true) {
  switch (aMode) {
    case gfx::AntialiasMode::NONE:
      return FontRenderMode::Mono;
    case gfx::AntialiasMode::GRAY:
      return FontRenderMode::Alpha;
    case gfx::AntialiasMode::SUBPIXEL:
    default:
      return aPermitSubpixelAA ? FontRenderMode::Subpixel
                               : FontRenderMode::Alpha;
  }
}

static inline MixBlendMode ToMixBlendMode(gfx::CompositionOp compositionOp) {
  switch (compositionOp) {
    case gfx::CompositionOp::OP_MULTIPLY:
      return MixBlendMode::Multiply;
    case gfx::CompositionOp::OP_SCREEN:
      return MixBlendMode::Screen;
    case gfx::CompositionOp::OP_OVERLAY:
      return MixBlendMode::Overlay;
    case gfx::CompositionOp::OP_DARKEN:
      return MixBlendMode::Darken;
    case gfx::CompositionOp::OP_LIGHTEN:
      return MixBlendMode::Lighten;
    case gfx::CompositionOp::OP_COLOR_DODGE:
      return MixBlendMode::ColorDodge;
    case gfx::CompositionOp::OP_COLOR_BURN:
      return MixBlendMode::ColorBurn;
    case gfx::CompositionOp::OP_HARD_LIGHT:
      return MixBlendMode::HardLight;
    case gfx::CompositionOp::OP_SOFT_LIGHT:
      return MixBlendMode::SoftLight;
    case gfx::CompositionOp::OP_DIFFERENCE:
      return MixBlendMode::Difference;
    case gfx::CompositionOp::OP_EXCLUSION:
      return MixBlendMode::Exclusion;
    case gfx::CompositionOp::OP_HUE:
      return MixBlendMode::Hue;
    case gfx::CompositionOp::OP_SATURATION:
      return MixBlendMode::Saturation;
    case gfx::CompositionOp::OP_COLOR:
      return MixBlendMode::Color;
    case gfx::CompositionOp::OP_LUMINOSITY:
      return MixBlendMode::Luminosity;
    default:
      return MixBlendMode::Normal;
  }
}

static inline wr::ColorF ToColorF(const gfx::Color& color) {
  wr::ColorF c;
  c.r = color.r;
  c.g = color.g;
  c.b = color.b;
  c.a = color.a;
  return c;
}

static inline wr::ColorU ToColorU(const gfx::Color& color) {
  wr::ColorU c;
  c.r = uint8_t(color.r * 255.0f);
  c.g = uint8_t(color.g * 255.0f);
  c.b = uint8_t(color.b * 255.0f);
  c.a = uint8_t(color.a * 255.0f);
  return c;
}

static inline wr::LayoutPoint ToLayoutPoint(
    const mozilla::LayoutDevicePoint& point) {
  wr::LayoutPoint p;
  p.x = point.x;
  p.y = point.y;
  return p;
}

static inline wr::LayoutPoint ToLayoutPoint(
    const mozilla::LayoutDeviceIntPoint& point) {
  return ToLayoutPoint(LayoutDevicePoint(point));
}

static inline wr::LayoutPoint ToRoundedLayoutPoint(
    const mozilla::LayoutDevicePoint& point) {
  mozilla::LayoutDevicePoint rounded = point;
  rounded.Round();
  return ToLayoutPoint(rounded);
}

static inline wr::WorldPoint ToWorldPoint(const mozilla::ScreenPoint& point) {
  wr::WorldPoint p;
  p.x = point.x;
  p.y = point.y;
  return p;
}

static inline wr::LayoutVector2D ToLayoutVector2D(
    const mozilla::LayoutDevicePoint& point) {
  wr::LayoutVector2D p;
  p.x = point.x;
  p.y = point.y;
  return p;
}

static inline wr::LayoutVector2D ToLayoutVector2D(
    const mozilla::LayoutDeviceIntPoint& point) {
  return ToLayoutVector2D(LayoutDevicePoint(point));
}

static inline wr::LayoutRect ToLayoutRect(
    const mozilla::LayoutDeviceRect& rect) {
  wr::LayoutRect r;
  r.origin.x = rect.X();
  r.origin.y = rect.Y();
  r.size.width = rect.Width();
  r.size.height = rect.Height();
  return r;
}

static inline wr::LayoutRect ToLayoutRect(const gfx::Rect& rect) {
  wr::LayoutRect r;
  r.origin.x = rect.X();
  r.origin.y = rect.Y();
  r.size.width = rect.Width();
  r.size.height = rect.Height();
  return r;
}

static inline wr::DeviceIntRect ToDeviceIntRect(
    const mozilla::ImageIntRect& rect) {
  wr::DeviceIntRect r;
  r.origin.x = rect.X();
  r.origin.y = rect.Y();
  r.size.width = rect.Width();
  r.size.height = rect.Height();
  return r;
}

// TODO: should be const LayoutDeviceIntRect instead of ImageIntRect
static inline wr::LayoutIntRect ToLayoutIntRect(
    const mozilla::ImageIntRect& rect) {
  wr::LayoutIntRect r;
  r.origin.x = rect.X();
  r.origin.y = rect.Y();
  r.size.width = rect.Width();
  r.size.height = rect.Height();
  return r;
}

static inline wr::LayoutRect ToLayoutRect(
    const mozilla::LayoutDeviceIntRect& rect) {
  return ToLayoutRect(IntRectToRect(rect));
}

static inline wr::LayoutRect ToRoundedLayoutRect(
    const mozilla::LayoutDeviceRect& aRect) {
  auto rect = aRect;
  rect.Round();
  return wr::ToLayoutRect(rect);
}

static inline wr::LayoutRect IntersectLayoutRect(const wr::LayoutRect& aRect,
                                                 const wr::LayoutRect& aOther) {
  wr::LayoutRect r;
  r.origin.x = std::max(aRect.origin.x, aOther.origin.x);
  r.origin.y = std::max(aRect.origin.y, aOther.origin.y);
  r.size.width = std::min(aRect.origin.x + aRect.size.width,
                          aOther.origin.x + aOther.size.width) -
                 r.origin.x;
  r.size.height = std::min(aRect.origin.y + aRect.size.height,
                           aOther.origin.y + aOther.size.height) -
                  r.origin.y;
  if (r.size.width < 0 || r.size.height < 0) {
    r.size.width = 0;
    r.size.height = 0;
  }
  return r;
}

static inline wr::LayoutSize ToLayoutSize(
    const mozilla::LayoutDeviceSize& size) {
  wr::LayoutSize ls;
  ls.width = size.width;
  ls.height = size.height;
  return ls;
}

static inline wr::ComplexClipRegion ToComplexClipRegion(
    const gfx::RoundedRect& rect) {
  wr::ComplexClipRegion ret;
  ret.rect = ToLayoutRect(rect.rect);
  ret.radii.top_left = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
      rect.corners.radii[mozilla::eCornerTopLeft]));
  ret.radii.top_right = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
      rect.corners.radii[mozilla::eCornerTopRight]));
  ret.radii.bottom_left = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
      rect.corners.radii[mozilla::eCornerBottomLeft]));
  ret.radii.bottom_right = ToLayoutSize(LayoutDeviceSize::FromUnknownSize(
      rect.corners.radii[mozilla::eCornerBottomRight]));
  ret.mode = wr::ClipMode::Clip;
  return ret;
}

static inline wr::ComplexClipRegion SimpleRadii(const wr::LayoutRect& aRect,
                                                float aRadii) {
  wr::ComplexClipRegion ret;
  wr::LayoutSize radii{aRadii, aRadii};
  ret.rect = aRect;
  ret.radii.top_left = radii;
  ret.radii.top_right = radii;
  ret.radii.bottom_left = radii;
  ret.radii.bottom_right = radii;
  ret.mode = wr::ClipMode::Clip;
  return ret;
}

static inline wr::LayoutSize ToLayoutSize(
    const mozilla::LayoutDeviceIntSize& size) {
  return ToLayoutSize(LayoutDeviceSize(size));
}

template <class S, class T>
static inline wr::LayoutTransform ToLayoutTransform(
    const gfx::Matrix4x4Typed<S, T>& m) {
  wr::LayoutTransform transform;
  transform.m11 = m._11;
  transform.m12 = m._12;
  transform.m13 = m._13;
  transform.m14 = m._14;
  transform.m21 = m._21;
  transform.m22 = m._22;
  transform.m23 = m._23;
  transform.m24 = m._24;
  transform.m31 = m._31;
  transform.m32 = m._32;
  transform.m33 = m._33;
  transform.m34 = m._34;
  transform.m41 = m._41;
  transform.m42 = m._42;
  transform.m43 = m._43;
  transform.m44 = m._44;
  return transform;
}

static inline wr::BorderStyle ToBorderStyle(const StyleBorderStyle& style) {
  switch (style) {
    case StyleBorderStyle::None:
      return wr::BorderStyle::None;
    case StyleBorderStyle::Solid:
      return wr::BorderStyle::Solid;
    case StyleBorderStyle::Double:
      return wr::BorderStyle::Double;
    case StyleBorderStyle::Dotted:
      return wr::BorderStyle::Dotted;
    case StyleBorderStyle::Dashed:
      return wr::BorderStyle::Dashed;
    case StyleBorderStyle::Hidden:
      return wr::BorderStyle::Hidden;
    case StyleBorderStyle::Groove:
      return wr::BorderStyle::Groove;
    case StyleBorderStyle::Ridge:
      return wr::BorderStyle::Ridge;
    case StyleBorderStyle::Inset:
      return wr::BorderStyle::Inset;
    case StyleBorderStyle::Outset:
      return wr::BorderStyle::Outset;
    default:
      MOZ_ASSERT(false);
  }
  return wr::BorderStyle::None;
}

static inline wr::BorderSide ToBorderSide(const gfx::Color& color,
                                          const StyleBorderStyle& style) {
  wr::BorderSide bs;
  bs.color = ToColorF(color);
  bs.style = ToBorderStyle(style);
  return bs;
}

static inline wr::BorderRadius EmptyBorderRadius() {
  wr::BorderRadius br;
  PodZero(&br);
  return br;
}

static inline wr::BorderRadius ToBorderRadius(
    const mozilla::LayoutDeviceSize& topLeft,
    const mozilla::LayoutDeviceSize& topRight,
    const mozilla::LayoutDeviceSize& bottomLeft,
    const mozilla::LayoutDeviceSize& bottomRight) {
  wr::BorderRadius br;
  br.top_left = ToLayoutSize(topLeft);
  br.top_right = ToLayoutSize(topRight);
  br.bottom_left = ToLayoutSize(bottomLeft);
  br.bottom_right = ToLayoutSize(bottomRight);
  return br;
}

static inline wr::ComplexClipRegion ToComplexClipRegion(
    const nsRect& aRect, const nscoord* aRadii, int32_t aAppUnitsPerDevPixel) {
  wr::ComplexClipRegion ret;
  ret.rect = ToRoundedLayoutRect(
      LayoutDeviceRect::FromAppUnits(aRect, aAppUnitsPerDevPixel));
  ret.radii = ToBorderRadius(
      LayoutDeviceSize::FromAppUnits(
          nsSize(aRadii[eCornerTopLeftX], aRadii[eCornerTopLeftY]),
          aAppUnitsPerDevPixel),
      LayoutDeviceSize::FromAppUnits(
          nsSize(aRadii[eCornerTopRightX], aRadii[eCornerTopRightY]),
          aAppUnitsPerDevPixel),
      LayoutDeviceSize::FromAppUnits(
          nsSize(aRadii[eCornerBottomLeftX], aRadii[eCornerBottomLeftY]),
          aAppUnitsPerDevPixel),
      LayoutDeviceSize::FromAppUnits(
          nsSize(aRadii[eCornerBottomRightX], aRadii[eCornerBottomRightY]),
          aAppUnitsPerDevPixel));
  ret.mode = ClipMode::Clip;
  return ret;
}

static inline wr::LayoutSideOffsets ToBorderWidths(float top, float right,
                                                   float bottom, float left) {
  wr::LayoutSideOffsets bw;
  bw.top = top;
  bw.right = right;
  bw.bottom = bottom;
  bw.left = left;
  return bw;
}

static inline wr::SideOffsets2D<int32_t> ToSideOffsets2D_i32(int32_t top,
                                                             int32_t right,
                                                             int32_t bottom,
                                                             int32_t left) {
  SideOffsets2D<int32_t> offset;
  offset.top = top;
  offset.right = right;
  offset.bottom = bottom;
  offset.left = left;
  return offset;
}

static inline wr::SideOffsets2D<float> ToSideOffsets2D_f32(float top,
                                                           float right,
                                                           float bottom,
                                                           float left) {
  SideOffsets2D<float> offset;
  offset.top = top;
  offset.right = right;
  offset.bottom = bottom;
  offset.left = left;
  return offset;
}

static inline wr::RepeatMode ToRepeatMode(
    mozilla::StyleBorderImageRepeat repeatMode) {
  switch (repeatMode) {
    case mozilla::StyleBorderImageRepeat::Stretch:
      return wr::RepeatMode::Stretch;
    case mozilla::StyleBorderImageRepeat::Repeat:
      return wr::RepeatMode::Repeat;
    case mozilla::StyleBorderImageRepeat::Round:
      return wr::RepeatMode::Round;
    case mozilla::StyleBorderImageRepeat::Space:
      return wr::RepeatMode::Space;
    default:
      MOZ_ASSERT(false);
  }

  return wr::RepeatMode::Stretch;
}

template <class S, class T>
static inline wr::WrTransformProperty ToWrTransformProperty(
    uint64_t id, const gfx::Matrix4x4Typed<S, T>& transform) {
  wr::WrTransformProperty prop;
  prop.id = id;
  prop.transform = ToLayoutTransform(transform);
  return prop;
}

static inline wr::WrOpacityProperty ToWrOpacityProperty(uint64_t id,
                                                        const float opacity) {
  wr::WrOpacityProperty prop;
  prop.id = id;
  prop.opacity = opacity;
  return prop;
}

// Whenever possible, use wr::ExternalImageId instead of manipulating uint64_t.
inline uint64_t AsUint64(const ExternalImageId& aId) {
  return static_cast<uint64_t>(aId.mHandle);
}

static inline ExternalImageId ToExternalImageId(uint64_t aID) {
  ExternalImageId Id;
  Id.mHandle = aID;
  return Id;
}

static inline wr::WrExternalImage RawDataToWrExternalImage(const uint8_t* aBuff,
                                                           size_t size) {
  return wr::WrExternalImage{
      wr::WrExternalImageType::RawData, 0, 0.0f, 0.0f, 0.0f, 0.0f, aBuff, size};
}

static inline wr::WrExternalImage NativeTextureToWrExternalImage(
    uint32_t aHandle, float u0, float v0, float u1, float v1) {
  return wr::WrExternalImage{wr::WrExternalImageType::NativeTexture,
                             aHandle,
                             u0,
                             v0,
                             u1,
                             v1,
                             nullptr,
                             0};
}

static inline wr::WrExternalImage InvalidToWrExternalImage() {
  return wr::WrExternalImage{
      wr::WrExternalImageType::Invalid, 0, 0, 0, 0, 0, nullptr, 0};
}

inline wr::ByteSlice RangeToByteSlice(mozilla::Range<uint8_t> aRange) {
  return wr::ByteSlice{aRange.begin().get(), aRange.length()};
}

inline mozilla::Range<const uint8_t> ByteSliceToRange(wr::ByteSlice aWrSlice) {
  return mozilla::Range<const uint8_t>(aWrSlice.buffer, aWrSlice.len);
}

inline mozilla::Range<uint8_t> MutByteSliceToRange(wr::MutByteSlice aWrSlice) {
  return mozilla::Range<uint8_t>(aWrSlice.buffer, aWrSlice.len);
}

void Assign_WrVecU8(wr::WrVecU8& aVec, mozilla::ipc::ByteBuf&& aOther);

template <typename T>
struct Vec;

template <>
struct Vec<uint8_t> final {
  wr::WrVecU8 inner;
  Vec() { SetEmpty(); }
  Vec(Vec&) = delete;
  Vec(Vec&& src) {
    inner = src.inner;
    src.SetEmpty();
  }

  explicit Vec(mozilla::ipc::ByteBuf&& aSrc) {
    Assign_WrVecU8(inner, std::move(aSrc));
  }

  Vec& operator=(Vec&& src) {
    inner = src.inner;
    src.SetEmpty();
    return *this;
  }

  wr::WrVecU8 Extract() {
    wr::WrVecU8 ret = inner;
    SetEmpty();
    return ret;
  }

  void SetEmpty() {
    inner.data = (uint8_t*)1;
    inner.capacity = 0;
    inner.length = 0;
  }

  size_t Length() { return inner.length; }

  void PushBytes(Range<uint8_t> aBytes) {
    wr_vec_u8_push_bytes(&inner, RangeToByteSlice(aBytes));
  }

  ~Vec() {
    if (inner.data) {
      wr_vec_u8_free(inner);
    }
  }
};

struct ByteBuffer {
  ByteBuffer(size_t aLength, uint8_t* aData)
      : mLength(aLength), mData(aData), mOwned(false) {}

  // XXX: this is a bit of hack that assumes
  // the allocators are the same
  explicit ByteBuffer(VecU8&& vec) {
    if (vec.inner.capacity) {
      mLength = vec.inner.length;
      mData = vec.inner.data;
      vec.inner.data = nullptr;
      vec.inner.capacity = 0;
      mOwned = true;
    } else {
      mOwned = false;
      mData = nullptr;
      mLength = 0;
    }
  }

  ByteBuffer(ByteBuffer&& aFrom)
      : mLength(aFrom.mLength), mData(aFrom.mData), mOwned(aFrom.mOwned) {
    aFrom.mLength = 0;
    aFrom.mData = nullptr;
    aFrom.mOwned = false;
  }

  ByteBuffer(ByteBuffer& aFrom)
      : mLength(aFrom.mLength), mData(aFrom.mData), mOwned(aFrom.mOwned) {
    aFrom.mLength = 0;
    aFrom.mData = nullptr;
    aFrom.mOwned = false;
  }

  ByteBuffer() : mLength(0), mData(nullptr), mOwned(false) {}

  bool Allocate(size_t aLength) {
    MOZ_ASSERT(mData == nullptr);
    mData = (uint8_t*)malloc(aLength);
    if (!mData) {
      return false;
    }
    mLength = aLength;
    mOwned = true;
    return true;
  }

  ~ByteBuffer() {
    if (mData && mOwned) {
      free(mData);
    }
  }

  const Range<uint8_t> AsSlice() const {
    return Range<uint8_t>(mData, mLength);
  }

  Range<uint8_t> AsSlice() { return Range<uint8_t>(mData, mLength); }

  bool operator==(const ByteBuffer& other) const {
    return mLength == other.mLength && !(memcmp(mData, other.mData, mLength));
  }

  size_t mLength;
  uint8_t* mData;
  bool mOwned;
};

struct BuiltDisplayList {
  wr::VecU8 dl;
  wr::BuiltDisplayListDescriptor dl_desc;
};

// Corresponds to a clip id for a clip chain in webrender. Similar to
// WrClipId but a separate struct so we don't get them mixed up in C++.
struct WrClipChainId {
  uint64_t id;

  bool operator==(const WrClipChainId& other) const { return id == other.id; }

  static WrClipChainId Empty() {
    WrClipChainId id = {0};
    return id;
  }
};

WrSpaceAndClip RootScrollNode();
WrSpaceAndClipChain RootScrollNodeWithChain();

enum class WebRenderError : int8_t {
  INITIALIZE = 0,
  MAKE_CURRENT,
  RENDER,

  Sentinel /* this must be last for serialization purposes. */
};

static inline wr::WrYuvColorSpace ToWrYuvColorSpace(
    gfx::YUVColorSpace aYUVColorSpace) {
  switch (aYUVColorSpace) {
    case gfx::YUVColorSpace::BT601:
      return wr::WrYuvColorSpace::Rec601;
    case gfx::YUVColorSpace::BT709:
      return wr::WrYuvColorSpace::Rec709;
    case gfx::YUVColorSpace::BT2020:
      return wr::WrYuvColorSpace::Rec2020;
    default:
      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid YUVColorSpace.");
  }
  return wr::WrYuvColorSpace::Rec601;
}

static inline wr::WrColorDepth ToWrColorDepth(gfx::ColorDepth aColorDepth) {
  switch (aColorDepth) {
    case gfx::ColorDepth::COLOR_8:
      return wr::WrColorDepth::Color8;
    case gfx::ColorDepth::COLOR_10:
      return wr::WrColorDepth::Color10;
    case gfx::ColorDepth::COLOR_12:
      return wr::WrColorDepth::Color12;
    case gfx::ColorDepth::COLOR_16:
      return wr::WrColorDepth::Color16;
    default:
      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid color depth value.");
  }
  return wr::WrColorDepth::Color8;
}

static inline wr::SyntheticItalics DegreesToSyntheticItalics(float aDegrees) {
  wr::SyntheticItalics synthetic_italics;
  synthetic_italics.angle =
      int16_t(std::min(std::max(aDegrees, -89.0f), 89.0f) * 256.0f);
  return synthetic_italics;
}

}  // namespace wr
}  // namespace mozilla

namespace std {
template <>
struct hash<mozilla::wr::WrSpatialId> {
  std::size_t operator()(mozilla::wr::WrSpatialId const& aKey) const noexcept {
    return std::hash<size_t>{}(aKey.id);
  }
};
}  // namespace std

#endif /* GFX_WEBRENDERTYPES_H */
back to top