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 */