RemoteLayerTreeTransaction.mm [plain text]
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "RemoteLayerTreeTransaction.h"
#import "ArgumentCoders.h"
#import "MessageDecoder.h"
#import "MessageEncoder.h"
#import "PlatformCAAnimationRemote.h"
#import "PlatformCALayerRemote.h"
#import "WebCoreArgumentCoders.h"
#import <QuartzCore/QuartzCore.h>
#import <WebCore/LengthFunctions.h>
#import <WebCore/TextStream.h>
#import <WebCore/TimingFunction.h>
#import <wtf/text/CString.h>
#import <wtf/text/StringBuilder.h>
using namespace WebCore;
namespace WebKit {
RemoteLayerTreeTransaction::LayerCreationProperties::LayerCreationProperties()
: layerID(0)
, type(PlatformCALayer::LayerTypeLayer)
, hostingContextID(0)
, hostingDeviceScaleFactor(1)
{
}
void RemoteLayerTreeTransaction::LayerCreationProperties::encode(IPC::ArgumentEncoder& encoder) const
{
encoder << layerID;
encoder.encodeEnum(type);
encoder << hostingContextID;
encoder << hostingDeviceScaleFactor;
}
bool RemoteLayerTreeTransaction::LayerCreationProperties::decode(IPC::ArgumentDecoder& decoder, LayerCreationProperties& result)
{
if (!decoder.decode(result.layerID))
return false;
if (!decoder.decodeEnum(result.type))
return false;
if (!decoder.decode(result.hostingContextID))
return false;
if (!decoder.decode(result.hostingDeviceScaleFactor))
return false;
return true;
}
RemoteLayerTreeTransaction::LayerProperties::LayerProperties()
: changedProperties(NoChange)
, everChangedProperties(NoChange)
, anchorPoint(0.5, 0.5, 0)
, contentsRect(FloatPoint(), FloatSize(1, 1))
, maskLayerID(0)
, clonedLayerID(0)
, timeOffset(0)
, speed(1)
, contentsScale(1)
, borderWidth(0)
, opacity(1)
, backgroundColor(Color::transparent)
, borderColor(Color::black)
, edgeAntialiasingMask(kCALayerLeftEdge | kCALayerRightEdge | kCALayerBottomEdge | kCALayerTopEdge)
, customAppearance(GraphicsLayer::NoCustomAppearance)
, customBehavior(GraphicsLayer::NoCustomBehavior)
, minificationFilter(PlatformCALayer::FilterType::Linear)
, magnificationFilter(PlatformCALayer::FilterType::Linear)
, blendMode(BlendModeNormal)
, hidden(false)
, geometryFlipped(false)
, doubleSided(true)
, masksToBounds(false)
, opaque(false)
{
}
RemoteLayerTreeTransaction::LayerProperties::LayerProperties(const LayerProperties& other)
: changedProperties(other.changedProperties)
, everChangedProperties(other.everChangedProperties)
, name(other.name)
, children(other.children)
, addedAnimations(other.addedAnimations)
, keyPathsOfAnimationsToRemove(other.keyPathsOfAnimationsToRemove)
, position(other.position)
, anchorPoint(other.anchorPoint)
, bounds(other.bounds)
, contentsRect(other.contentsRect)
, maskLayerID(other.maskLayerID)
, clonedLayerID(other.clonedLayerID)
, timeOffset(other.timeOffset)
, speed(other.speed)
, contentsScale(other.contentsScale)
, borderWidth(other.borderWidth)
, opacity(other.opacity)
, backgroundColor(other.backgroundColor)
, borderColor(other.borderColor)
, edgeAntialiasingMask(other.edgeAntialiasingMask)
, customAppearance(other.customAppearance)
, customBehavior(other.customBehavior)
, minificationFilter(other.minificationFilter)
, magnificationFilter(other.magnificationFilter)
, blendMode(other.blendMode)
, hidden(other.hidden)
, geometryFlipped(other.geometryFlipped)
, doubleSided(other.doubleSided)
, masksToBounds(other.masksToBounds)
, opaque(other.opaque)
{
// FIXME: LayerProperties should reference backing store by ID, so that two layers can have the same backing store (for clones).
// FIXME: LayerProperties shouldn't be copyable; PlatformCALayerRemote::clone should copy the relevant properties.
if (other.transform)
transform = std::make_unique<TransformationMatrix>(*other.transform);
if (other.sublayerTransform)
sublayerTransform = std::make_unique<TransformationMatrix>(*other.sublayerTransform);
if (other.filters)
filters = std::make_unique<FilterOperations>(*other.filters);
}
void RemoteLayerTreeTransaction::LayerProperties::encode(IPC::ArgumentEncoder& encoder) const
{
encoder.encodeEnum(changedProperties);
if (changedProperties & NameChanged)
encoder << name;
if (changedProperties & ChildrenChanged)
encoder << children;
if (changedProperties & AnimationsChanged) {
encoder << addedAnimations;
encoder << keyPathsOfAnimationsToRemove;
}
if (changedProperties & PositionChanged)
encoder << position;
if (changedProperties & BoundsChanged)
encoder << bounds;
if (changedProperties & BackgroundColorChanged)
encoder << backgroundColor;
if (changedProperties & AnchorPointChanged)
encoder << anchorPoint;
if (changedProperties & BorderWidthChanged)
encoder << borderWidth;
if (changedProperties & BorderColorChanged)
encoder << borderColor;
if (changedProperties & OpacityChanged)
encoder << opacity;
if (changedProperties & TransformChanged)
encoder << *transform;
if (changedProperties & SublayerTransformChanged)
encoder << *sublayerTransform;
if (changedProperties & HiddenChanged)
encoder << hidden;
if (changedProperties & GeometryFlippedChanged)
encoder << geometryFlipped;
if (changedProperties & DoubleSidedChanged)
encoder << doubleSided;
if (changedProperties & MasksToBoundsChanged)
encoder << masksToBounds;
if (changedProperties & OpaqueChanged)
encoder << opaque;
if (changedProperties & MaskLayerChanged)
encoder << maskLayerID;
if (changedProperties & ClonedContentsChanged)
encoder << clonedLayerID;
if (changedProperties & ContentsRectChanged)
encoder << contentsRect;
if (changedProperties & ContentsScaleChanged)
encoder << contentsScale;
if (changedProperties & MinificationFilterChanged)
encoder.encodeEnum(minificationFilter);
if (changedProperties & MagnificationFilterChanged)
encoder.encodeEnum(magnificationFilter);
if (changedProperties & BlendModeChanged)
encoder.encodeEnum(blendMode);
if (changedProperties & SpeedChanged)
encoder << speed;
if (changedProperties & TimeOffsetChanged)
encoder << timeOffset;
if (changedProperties & BackingStoreChanged) {
bool hasFrontBuffer = backingStore && backingStore->hasFrontBuffer();
encoder << hasFrontBuffer;
if (hasFrontBuffer)
encoder << *backingStore;
}
if (changedProperties & FiltersChanged)
encoder << *filters;
if (changedProperties & EdgeAntialiasingMaskChanged)
encoder << edgeAntialiasingMask;
if (changedProperties & CustomAppearanceChanged)
encoder.encodeEnum(customAppearance);
if (changedProperties & CustomBehaviorChanged)
encoder.encodeEnum(customBehavior);
}
bool RemoteLayerTreeTransaction::LayerProperties::decode(IPC::ArgumentDecoder& decoder, LayerProperties& result)
{
if (!decoder.decodeEnum(result.changedProperties))
return false;
if (result.changedProperties & NameChanged) {
if (!decoder.decode(result.name))
return false;
}
if (result.changedProperties & ChildrenChanged) {
if (!decoder.decode(result.children))
return false;
for (auto& layerID : result.children) {
if (!layerID)
return false;
}
}
if (result.changedProperties & AnimationsChanged) {
if (!decoder.decode(result.addedAnimations))
return false;
if (!decoder.decode(result.keyPathsOfAnimationsToRemove))
return false;
}
if (result.changedProperties & PositionChanged) {
if (!decoder.decode(result.position))
return false;
}
if (result.changedProperties & BoundsChanged) {
if (!decoder.decode(result.bounds))
return false;
}
if (result.changedProperties & BackgroundColorChanged) {
if (!decoder.decode(result.backgroundColor))
return false;
}
if (result.changedProperties & AnchorPointChanged) {
if (!decoder.decode(result.anchorPoint))
return false;
}
if (result.changedProperties & BorderWidthChanged) {
if (!decoder.decode(result.borderWidth))
return false;
}
if (result.changedProperties & BorderColorChanged) {
if (!decoder.decode(result.borderColor))
return false;
}
if (result.changedProperties & OpacityChanged) {
if (!decoder.decode(result.opacity))
return false;
}
if (result.changedProperties & TransformChanged) {
TransformationMatrix transform;
if (!decoder.decode(transform))
return false;
result.transform = std::make_unique<TransformationMatrix>(transform);
}
if (result.changedProperties & SublayerTransformChanged) {
TransformationMatrix transform;
if (!decoder.decode(transform))
return false;
result.sublayerTransform = std::make_unique<TransformationMatrix>(transform);
}
if (result.changedProperties & HiddenChanged) {
if (!decoder.decode(result.hidden))
return false;
}
if (result.changedProperties & GeometryFlippedChanged) {
if (!decoder.decode(result.geometryFlipped))
return false;
}
if (result.changedProperties & DoubleSidedChanged) {
if (!decoder.decode(result.doubleSided))
return false;
}
if (result.changedProperties & MasksToBoundsChanged) {
if (!decoder.decode(result.masksToBounds))
return false;
}
if (result.changedProperties & OpaqueChanged) {
if (!decoder.decode(result.opaque))
return false;
}
if (result.changedProperties & MaskLayerChanged) {
if (!decoder.decode(result.maskLayerID))
return false;
}
if (result.changedProperties & ClonedContentsChanged) {
if (!decoder.decode(result.clonedLayerID))
return false;
}
if (result.changedProperties & ContentsRectChanged) {
if (!decoder.decode(result.contentsRect))
return false;
}
if (result.changedProperties & ContentsScaleChanged) {
if (!decoder.decode(result.contentsScale))
return false;
}
if (result.changedProperties & MinificationFilterChanged) {
if (!decoder.decodeEnum(result.minificationFilter))
return false;
}
if (result.changedProperties & MagnificationFilterChanged) {
if (!decoder.decodeEnum(result.magnificationFilter))
return false;
}
if (result.changedProperties & BlendModeChanged) {
if (!decoder.decodeEnum(result.blendMode))
return false;
}
if (result.changedProperties & SpeedChanged) {
if (!decoder.decode(result.speed))
return false;
}
if (result.changedProperties & TimeOffsetChanged) {
if (!decoder.decode(result.timeOffset))
return false;
}
if (result.changedProperties & BackingStoreChanged) {
bool hasFrontBuffer = false;
if (!decoder.decode(hasFrontBuffer))
return false;
if (hasFrontBuffer) {
std::unique_ptr<RemoteLayerBackingStore> backingStore = std::make_unique<RemoteLayerBackingStore>(nullptr);
if (!decoder.decode(*backingStore))
return false;
result.backingStore = WTF::move(backingStore);
} else
result.backingStore = nullptr;
}
if (result.changedProperties & FiltersChanged) {
std::unique_ptr<FilterOperations> filters = std::make_unique<FilterOperations>();
if (!decoder.decode(*filters))
return false;
result.filters = WTF::move(filters);
}
if (result.changedProperties & EdgeAntialiasingMaskChanged) {
if (!decoder.decode(result.edgeAntialiasingMask))
return false;
}
if (result.changedProperties & CustomAppearanceChanged) {
if (!decoder.decodeEnum(result.customAppearance))
return false;
}
if (result.changedProperties & CustomBehaviorChanged) {
if (!decoder.decodeEnum(result.customBehavior))
return false;
}
return true;
}
RemoteLayerTreeTransaction::RemoteLayerTreeTransaction()
{
}
RemoteLayerTreeTransaction::~RemoteLayerTreeTransaction()
{
}
void RemoteLayerTreeTransaction::encode(IPC::ArgumentEncoder& encoder) const
{
encoder << m_rootLayerID;
encoder << m_createdLayers;
encoder << static_cast<uint64_t>(m_changedLayers.size());
for (RefPtr<PlatformCALayerRemote> layer : m_changedLayers) {
encoder << layer->layerID();
encoder << layer->properties();
}
encoder << m_destroyedLayerIDs;
encoder << m_videoLayerIDsPendingFullscreen;
encoder << m_layerIDsWithNewlyUnreachableBackingStore;
encoder << m_contentsSize;
encoder << m_pageExtendedBackgroundColor;
encoder << m_pageScaleFactor;
encoder << m_minimumScaleFactor;
encoder << m_maximumScaleFactor;
encoder << m_renderTreeSize;
encoder << m_transactionID;
encoder << m_scaleWasSetByUIProcess;
encoder << m_allowsUserScaling;
encoder << m_callbackIDs;
}
bool RemoteLayerTreeTransaction::decode(IPC::ArgumentDecoder& decoder, RemoteLayerTreeTransaction& result)
{
if (!decoder.decode(result.m_rootLayerID))
return false;
if (!result.m_rootLayerID)
return false;
if (!decoder.decode(result.m_createdLayers))
return false;
uint64_t numChangedLayerProperties;
if (!decoder.decode(numChangedLayerProperties))
return false;
for (uint64_t i = 0; i < numChangedLayerProperties; ++i) {
GraphicsLayer::PlatformLayerID layerID;
if (!decoder.decode(layerID))
return false;
std::unique_ptr<LayerProperties> layerProperties = std::make_unique<LayerProperties>();
if (!decoder.decode(*layerProperties))
return false;
result.changedLayerProperties().set(layerID, WTF::move(layerProperties));
}
if (!decoder.decode(result.m_destroyedLayerIDs))
return false;
for (auto& layerID : result.m_destroyedLayerIDs) {
if (!layerID)
return false;
}
if (!decoder.decode(result.m_videoLayerIDsPendingFullscreen))
return false;
if (!decoder.decode(result.m_layerIDsWithNewlyUnreachableBackingStore))
return false;
for (auto& layerID : result.m_layerIDsWithNewlyUnreachableBackingStore) {
if (!layerID)
return false;
}
if (!decoder.decode(result.m_contentsSize))
return false;
if (!decoder.decode(result.m_pageExtendedBackgroundColor))
return false;
if (!decoder.decode(result.m_pageScaleFactor))
return false;
if (!decoder.decode(result.m_minimumScaleFactor))
return false;
if (!decoder.decode(result.m_maximumScaleFactor))
return false;
if (!decoder.decode(result.m_renderTreeSize))
return false;
if (!decoder.decode(result.m_transactionID))
return false;
if (!decoder.decode(result.m_scaleWasSetByUIProcess))
return false;
if (!decoder.decode(result.m_allowsUserScaling))
return false;
if (!decoder.decode(result.m_callbackIDs))
return false;
return true;
}
void RemoteLayerTreeTransaction::setRootLayerID(GraphicsLayer::PlatformLayerID rootLayerID)
{
ASSERT_ARG(rootLayerID, rootLayerID);
m_rootLayerID = rootLayerID;
}
void RemoteLayerTreeTransaction::layerPropertiesChanged(PlatformCALayerRemote& remoteLayer)
{
m_changedLayers.append(&remoteLayer);
}
void RemoteLayerTreeTransaction::setCreatedLayers(Vector<LayerCreationProperties> createdLayers)
{
m_createdLayers = WTF::move(createdLayers);
}
void RemoteLayerTreeTransaction::setDestroyedLayerIDs(Vector<GraphicsLayer::PlatformLayerID> destroyedLayerIDs)
{
m_destroyedLayerIDs = WTF::move(destroyedLayerIDs);
}
void RemoteLayerTreeTransaction::setLayerIDsWithNewlyUnreachableBackingStore(Vector<GraphicsLayer::PlatformLayerID> layerIDsWithNewlyUnreachableBackingStore)
{
m_layerIDsWithNewlyUnreachableBackingStore = WTF::move(layerIDsWithNewlyUnreachableBackingStore);
}
#if !defined(NDEBUG) || !LOG_DISABLED
class RemoteLayerTreeTextStream : public TextStream
{
public:
using TextStream::operator<<;
RemoteLayerTreeTextStream()
: m_indent(0)
{
}
RemoteLayerTreeTextStream& operator<<(const TransformationMatrix&);
RemoteLayerTreeTextStream& operator<<(PlatformCALayer::FilterType);
RemoteLayerTreeTextStream& operator<<(FloatPoint3D);
RemoteLayerTreeTextStream& operator<<(Color);
RemoteLayerTreeTextStream& operator<<(FloatRect);
RemoteLayerTreeTextStream& operator<<(const Vector<WebCore::GraphicsLayer::PlatformLayerID>&);
RemoteLayerTreeTextStream& operator<<(const FilterOperation&);
RemoteLayerTreeTextStream& operator<<(const FilterOperations&);
RemoteLayerTreeTextStream& operator<<(const PlatformCAAnimationRemote::Properties&);
RemoteLayerTreeTextStream& operator<<(const RemoteLayerBackingStore&);
RemoteLayerTreeTextStream& operator<<(BlendMode);
RemoteLayerTreeTextStream& operator<<(PlatformCAAnimation::AnimationType);
RemoteLayerTreeTextStream& operator<<(PlatformCAAnimation::FillModeType);
RemoteLayerTreeTextStream& operator<<(PlatformCAAnimation::ValueFunctionType);
RemoteLayerTreeTextStream& operator<<(const TimingFunction&);
RemoteLayerTreeTextStream& operator<<(const PlatformCAAnimationRemote::KeyframeValue&);
void increaseIndent() { ++m_indent; }
void decreaseIndent() { --m_indent; ASSERT(m_indent >= 0); }
void writeIndent();
private:
int m_indent;
};
template <class T>
static void dumpProperty(RemoteLayerTreeTextStream& ts, String name, T value)
{
ts << "\n";
ts.increaseIndent();
ts.writeIndent();
ts << "(" << name << " ";
ts << value << ")";
ts.decreaseIndent();
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const TransformationMatrix& transform)
{
RemoteLayerTreeTextStream& ts = *this;
ts << "\n";
ts.increaseIndent();
ts.writeIndent();
ts << "[" << transform.m11() << " " << transform.m12() << " " << transform.m13() << " " << transform.m14() << "]\n";
ts.writeIndent();
ts << "[" << transform.m21() << " " << transform.m22() << " " << transform.m23() << " " << transform.m24() << "]\n";
ts.writeIndent();
ts << "[" << transform.m31() << " " << transform.m32() << " " << transform.m33() << " " << transform.m34() << "]\n";
ts.writeIndent();
ts << "[" << transform.m41() << " " << transform.m42() << " " << transform.m43() << " " << transform.m44() << "]";
ts.decreaseIndent();
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(PlatformCALayer::FilterType filterType)
{
RemoteLayerTreeTextStream& ts = *this;
switch (filterType) {
case PlatformCALayer::Linear:
ts << "linear";
break;
case PlatformCALayer::Nearest:
ts << "nearest";
break;
case PlatformCALayer::Trilinear:
ts << "trilinear";
break;
default:
ASSERT_NOT_REACHED();
break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const FilterOperations& filters)
{
RemoteLayerTreeTextStream& ts = *this;
for (size_t i = 0; i < filters.size(); ++i) {
const auto filter = filters.at(i);
if (filter)
ts << *filter;
else
ts << "(null)";
if (i < filters.size() - 1)
ts << " ";
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const FilterOperation& filter)
{
RemoteLayerTreeTextStream& ts = *this;
switch (filter.type()) {
case FilterOperation::REFERENCE:
ts << "reference";
break;
case FilterOperation::GRAYSCALE: {
const BasicColorMatrixFilterOperation& colorMatrixFilter = toBasicColorMatrixFilterOperation(filter);
ts << "grayscale(" << colorMatrixFilter.amount() << ")";
break;
}
case FilterOperation::SEPIA: {
const BasicColorMatrixFilterOperation& colorMatrixFilter = toBasicColorMatrixFilterOperation(filter);
ts << "sepia(" << colorMatrixFilter.amount() << ")";
break;
}
case FilterOperation::SATURATE: {
const BasicColorMatrixFilterOperation& colorMatrixFilter = toBasicColorMatrixFilterOperation(filter);
ts << "saturate(" << colorMatrixFilter.amount() << ")";
break;
}
case FilterOperation::HUE_ROTATE: {
const BasicColorMatrixFilterOperation& colorMatrixFilter = toBasicColorMatrixFilterOperation(filter);
ts << "hue-rotate(" << colorMatrixFilter.amount() << ")";
break;
}
case FilterOperation::INVERT: {
const BasicComponentTransferFilterOperation& componentTransferFilter = toBasicComponentTransferFilterOperation(filter);
ts << "invert(" << componentTransferFilter.amount() << ")";
break;
}
case FilterOperation::OPACITY: {
const BasicComponentTransferFilterOperation& componentTransferFilter = toBasicComponentTransferFilterOperation(filter);
ts << "opacity(" << componentTransferFilter.amount() << ")";
break;
}
case FilterOperation::BRIGHTNESS: {
const BasicComponentTransferFilterOperation& componentTransferFilter = toBasicComponentTransferFilterOperation(filter);
ts << "brightness(" << componentTransferFilter.amount() << ")";
break;
}
case FilterOperation::CONTRAST: {
const BasicComponentTransferFilterOperation& componentTransferFilter = toBasicComponentTransferFilterOperation(filter);
ts << "contrast(" << componentTransferFilter.amount() << ")";
break;
}
case FilterOperation::BLUR: {
const BlurFilterOperation& blurFilter = toBlurFilterOperation(filter);
ts << "blur(" << floatValueForLength(blurFilter.stdDeviation(), 0) << ")";
break;
}
case FilterOperation::DROP_SHADOW: {
const DropShadowFilterOperation& dropShadowFilter = toDropShadowFilterOperation(filter);
ts << "drop-shadow(" << dropShadowFilter.x() << " " << dropShadowFilter.y() << " " << dropShadowFilter.location() << " ";
ts << dropShadowFilter.color() << ")";
break;
}
case FilterOperation::PASSTHROUGH:
ts << "passthrough";
break;
case FilterOperation::DEFAULT: {
const DefaultFilterOperation& defaultFilter = toDefaultFilterOperation(filter);
ts << "default type=" << (int)defaultFilter.representedType();
break;
}
case FilterOperation::NONE:
ts << "none";
break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(BlendMode blendMode)
{
RemoteLayerTreeTextStream& ts = *this;
switch (blendMode) {
case BlendModeNormal: ts << "normal"; break;
case BlendModeMultiply: ts << "multiply"; break;
case BlendModeScreen: ts << "screen"; break;
case BlendModeOverlay: ts << "overlay"; break;
case BlendModeDarken: ts << "darken"; break;
case BlendModeLighten: ts << "lighten"; break;
case BlendModeColorDodge: ts << "color-dodge"; break;
case BlendModeColorBurn: ts << "color-burn"; break;
case BlendModeHardLight: ts << "hard-light"; break;
case BlendModeSoftLight: ts << "soft-light"; break;
case BlendModeDifference: ts << "difference"; break;
case BlendModeExclusion: ts << "exclusion"; break;
case BlendModeHue: ts << "hue"; break;
case BlendModeSaturation: ts << "saturation"; break;
case BlendModeColor: ts << "color"; break;
case BlendModeLuminosity: ts << "luminosity"; break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(PlatformCAAnimation::AnimationType type)
{
RemoteLayerTreeTextStream& ts = *this;
switch (type) {
case PlatformCAAnimation::Basic: ts << "basic"; break;
case PlatformCAAnimation::Keyframe: ts << "keyframe"; break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(PlatformCAAnimation::FillModeType type)
{
RemoteLayerTreeTextStream& ts = *this;
switch (type) {
case PlatformCAAnimation::NoFillMode: ts << "none"; break;
case PlatformCAAnimation::Forwards: ts << "forwards"; break;
case PlatformCAAnimation::Backwards: ts << "backwards"; break;
case PlatformCAAnimation::Both: ts << "both"; break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(PlatformCAAnimation::ValueFunctionType type)
{
RemoteLayerTreeTextStream& ts = *this;
switch (type) {
case PlatformCAAnimation::NoValueFunction: ts << "none"; break;
case PlatformCAAnimation::RotateX: ts << "rotateX"; break;
case PlatformCAAnimation::RotateY: ts << "rotateY"; break;
case PlatformCAAnimation::RotateZ: ts << "rotateX"; break;
case PlatformCAAnimation::ScaleX: ts << "scaleX"; break;
case PlatformCAAnimation::ScaleY: ts << "scaleY"; break;
case PlatformCAAnimation::ScaleZ: ts << "scaleX"; break;
case PlatformCAAnimation::Scale: ts << "scale"; break;
case PlatformCAAnimation::TranslateX: ts << "translateX"; break;
case PlatformCAAnimation::TranslateY: ts << "translateY"; break;
case PlatformCAAnimation::TranslateZ: ts << "translateZ"; break;
case PlatformCAAnimation::Translate: ts << "translate"; break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const PlatformCAAnimationRemote::KeyframeValue& value)
{
RemoteLayerTreeTextStream& ts = *this;
switch (value.keyframeType()) {
case PlatformCAAnimationRemote::KeyframeValue::NumberKeyType:
ts << "number=" << value.numberValue();
break;
case PlatformCAAnimationRemote::KeyframeValue::ColorKeyType:
ts << "color=";
ts << value.colorValue();
break;
case PlatformCAAnimationRemote::KeyframeValue::PointKeyType:
ts << "point=";
ts << value.pointValue();
break;
case PlatformCAAnimationRemote::KeyframeValue::TransformKeyType:
ts << "transform=";
ts << value.transformValue();
break;
case PlatformCAAnimationRemote::KeyframeValue::FilterKeyType:
ts << "filter=";
if (value.filterValue())
ts << *value.filterValue();
else
ts << "null";
break;
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const TimingFunction& timingFunction)
{
RemoteLayerTreeTextStream& ts = *this;
switch (timingFunction.type()) {
case TimingFunction::LinearFunction:
ts << "linear";
break;
case TimingFunction::CubicBezierFunction: {
const CubicBezierTimingFunction& cubicBezierFunction = static_cast<const CubicBezierTimingFunction&>(timingFunction);
ts << "cubic-bezier(" << cubicBezierFunction.x1() << ", " << cubicBezierFunction.y1() << ", " << cubicBezierFunction.x2() << ", " << cubicBezierFunction.y2() << ")";
break;
}
case TimingFunction::StepsFunction: {
const StepsTimingFunction& stepsFunction = static_cast<const StepsTimingFunction&>(timingFunction);
ts << "steps(" << stepsFunction.numberOfSteps() << ", " << (stepsFunction.stepAtStart() ? "start" : "end") << ")";
break;
}
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const PlatformCAAnimationRemote::Properties& animation)
{
RemoteLayerTreeTextStream& ts = *this;
ts << "type=";
ts << animation.animationType;
ts << " keyPath=";
ts << animation.keyPath;
if (animation.beginTime)
dumpProperty(ts, "beginTime", animation.beginTime);
if (animation.duration)
dumpProperty(ts, "duration", animation.duration);
if (animation.timeOffset)
dumpProperty(ts, "timeOffset", animation.timeOffset);
dumpProperty(ts, "repeatCount", animation.repeatCount);
if (animation.speed != 1)
dumpProperty(ts, "speed", animation.speed);
dumpProperty(ts, "fillMode", animation.fillMode);
dumpProperty(ts, "valueFunction", animation.valueFunction);
if (animation.autoReverses)
dumpProperty(ts, "autoReverses", animation.autoReverses);
if (!animation.removedOnCompletion)
dumpProperty(ts, "removedOnCompletion", animation.removedOnCompletion);
if (animation.additive)
dumpProperty(ts, "additive", animation.additive);
if (animation.reverseTimingFunctions)
dumpProperty(ts, "reverseTimingFunctions", animation.reverseTimingFunctions);
if (animation.hasExplicitBeginTime)
dumpProperty(ts, "hasExplicitBeginTime", animation.hasExplicitBeginTime);
ts << "\n";
ts.increaseIndent();
ts.writeIndent();
ts << "(" << "keyframes";
ts.increaseIndent();
size_t maxFrames = std::max(animation.keyValues.size(), animation.keyTimes.size());
maxFrames = std::max(maxFrames, animation.timingFunctions.size());
for (size_t i = 0; i < maxFrames; ++i) {
ts << "\n";
ts.writeIndent();
ts << "(keyframe " << unsigned(i);
if (i < animation.keyTimes.size())
dumpProperty(ts, "time", animation.keyTimes[i]);
if (i < animation.timingFunctions.size() && animation.timingFunctions[i])
dumpProperty<const TimingFunction&>(ts, "timing function", *animation.timingFunctions[i]);
if (i < animation.keyValues.size())
dumpProperty(ts, "value", animation.keyValues[i]);
ts << ")";
}
ts.decreaseIndent();
ts.decreaseIndent();
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(FloatPoint3D point)
{
RemoteLayerTreeTextStream& ts = *this;
ts << point.x() << " " << point.y() << " " << point.z();
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(Color color)
{
RemoteLayerTreeTextStream& ts = *this;
ts << color.serialized();
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(FloatRect rect)
{
RemoteLayerTreeTextStream& ts = *this;
ts << rect.x() << " " << rect.y() << " " << rect.width() << " " << rect.height();
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const Vector<GraphicsLayer::PlatformLayerID>& layers)
{
RemoteLayerTreeTextStream& ts = *this;
for (size_t i = 0; i < layers.size(); ++i) {
if (i)
ts << " ";
ts << layers[i];
}
return ts;
}
RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const RemoteLayerBackingStore& backingStore)
{
RemoteLayerTreeTextStream& ts = *this;
ts << backingStore.size();
ts << " scale=" << backingStore.scale();
if (backingStore.isOpaque())
ts << " opaque";
if (backingStore.acceleratesDrawing())
ts << " accelerated";
return ts;
}
void RemoteLayerTreeTextStream::writeIndent()
{
for (int i = 0; i < m_indent; ++i)
*this << " ";
}
static void dumpChangedLayers(RemoteLayerTreeTextStream& ts, const RemoteLayerTreeTransaction::LayerPropertiesMap& changedLayerProperties)
{
if (changedLayerProperties.isEmpty())
return;
ts << "\n";
ts.writeIndent();
ts << "(changed-layers";
// Dump the layer properties sorted by layer ID.
Vector<GraphicsLayer::PlatformLayerID> layerIDs;
copyKeysToVector(changedLayerProperties, layerIDs);
std::sort(layerIDs.begin(), layerIDs.end());
for (auto& layerID : layerIDs) {
const RemoteLayerTreeTransaction::LayerProperties& layerProperties = *changedLayerProperties.get(layerID);
ts << "\n";
ts.increaseIndent();
ts.writeIndent();
ts << "(layer " << layerID;
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::NameChanged)
dumpProperty(ts, "name", layerProperties.name);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::ChildrenChanged)
dumpProperty<Vector<GraphicsLayer::PlatformLayerID>>(ts, "children", layerProperties.children);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::PositionChanged)
dumpProperty(ts, "position", layerProperties.position);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BoundsChanged)
dumpProperty(ts, "bounds", layerProperties.bounds);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::AnchorPointChanged)
dumpProperty(ts, "anchorPoint", layerProperties.anchorPoint);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BackgroundColorChanged)
dumpProperty(ts, "backgroundColor", layerProperties.backgroundColor);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BorderColorChanged)
dumpProperty(ts, "borderColor", layerProperties.borderColor);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BorderWidthChanged)
dumpProperty(ts, "borderWidth", layerProperties.borderWidth);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::OpacityChanged)
dumpProperty(ts, "opacity", layerProperties.opacity);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::TransformChanged)
dumpProperty(ts, "transform", layerProperties.transform ? *layerProperties.transform : TransformationMatrix());
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::SublayerTransformChanged)
dumpProperty(ts, "sublayerTransform", layerProperties.sublayerTransform ? *layerProperties.sublayerTransform : TransformationMatrix());
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::HiddenChanged)
dumpProperty(ts, "hidden", layerProperties.hidden);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::GeometryFlippedChanged)
dumpProperty(ts, "geometryFlipped", layerProperties.geometryFlipped);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::DoubleSidedChanged)
dumpProperty(ts, "doubleSided", layerProperties.doubleSided);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::MasksToBoundsChanged)
dumpProperty(ts, "masksToBounds", layerProperties.masksToBounds);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::OpaqueChanged)
dumpProperty(ts, "opaque", layerProperties.opaque);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::MaskLayerChanged)
dumpProperty(ts, "maskLayer", layerProperties.maskLayerID);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::ClonedContentsChanged)
dumpProperty(ts, "clonedLayer", layerProperties.clonedLayerID);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::ContentsRectChanged)
dumpProperty(ts, "contentsRect", layerProperties.contentsRect);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::ContentsScaleChanged)
dumpProperty(ts, "contentsScale", layerProperties.contentsScale);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::MinificationFilterChanged)
dumpProperty(ts, "minificationFilter", layerProperties.minificationFilter);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::MagnificationFilterChanged)
dumpProperty(ts, "magnificationFilter", layerProperties.magnificationFilter);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BlendModeChanged)
dumpProperty(ts, "blendMode", layerProperties.blendMode);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::SpeedChanged)
dumpProperty(ts, "speed", layerProperties.speed);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::TimeOffsetChanged)
dumpProperty(ts, "timeOffset", layerProperties.timeOffset);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BackingStoreChanged) {
if (const RemoteLayerBackingStore* backingStore = layerProperties.backingStore.get())
dumpProperty<const RemoteLayerBackingStore&>(ts, "backingStore", *backingStore);
else
dumpProperty(ts, "backingStore", "removed");
}
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::FiltersChanged)
dumpProperty(ts, "filters", layerProperties.filters ? *layerProperties.filters : FilterOperations());
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::AnimationsChanged) {
for (const auto& keyAnimationPair : layerProperties.addedAnimations)
dumpProperty(ts, "animation " + keyAnimationPair.first, keyAnimationPair.second);
for (const auto& name : layerProperties.keyPathsOfAnimationsToRemove)
dumpProperty(ts, "removed animation", name);
}
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::EdgeAntialiasingMaskChanged)
dumpProperty(ts, "edgeAntialiasingMask", layerProperties.edgeAntialiasingMask);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::CustomAppearanceChanged)
dumpProperty(ts, "customAppearance", layerProperties.customAppearance);
if (layerProperties.changedProperties & RemoteLayerTreeTransaction::CustomBehaviorChanged)
dumpProperty(ts, "customBehavior", layerProperties.customBehavior);
ts << ")";
ts.decreaseIndent();
}
ts.decreaseIndent();
}
void RemoteLayerTreeTransaction::dump() const
{
fprintf(stderr, "%s", description().data());
}
CString RemoteLayerTreeTransaction::description() const
{
RemoteLayerTreeTextStream ts;
ts << "(\n";
ts.increaseIndent();
ts.writeIndent();
ts << "(root-layer " << m_rootLayerID << ")";
if (!m_createdLayers.isEmpty()) {
ts << "\n";
ts.writeIndent();
ts << "(created-layers";
ts.increaseIndent();
for (const auto& createdLayer : m_createdLayers) {
ts << "\n";
ts.writeIndent();
ts << "(";
switch (createdLayer.type) {
case PlatformCALayer::LayerTypeLayer:
case PlatformCALayer::LayerTypeWebLayer:
case PlatformCALayer::LayerTypeSimpleLayer:
ts << "layer";
break;
case PlatformCALayer::LayerTypeTransformLayer:
ts << "transform-layer";
break;
case PlatformCALayer::LayerTypeWebTiledLayer:
ts << "tiled-layer";
break;
case PlatformCALayer::LayerTypeTiledBackingLayer:
ts << "tiled-backing-layer";
break;
case PlatformCALayer::LayerTypePageTiledBackingLayer:
ts << "page-tiled-backing-layer";
break;
case PlatformCALayer::LayerTypeTiledBackingTileLayer:
ts << "tiled-backing-tile";
break;
case PlatformCALayer::LayerTypeRootLayer:
ts << "root-layer";
break;
case PlatformCALayer::LayerTypeAVPlayerLayer:
ts << "av-player-layer (context-id " << createdLayer.hostingContextID << ")";
break;
case PlatformCALayer::LayerTypeWebGLLayer:
ts << "web-gl-layer (context-id " << createdLayer.hostingContextID << ")";
break;
case PlatformCALayer::LayerTypeCustom:
ts << "custom-layer (context-id " << createdLayer.hostingContextID << ")";
break;
}
ts << " " << createdLayer.layerID << ")";
}
ts << ")";
ts.decreaseIndent();
}
dumpChangedLayers(ts, m_changedLayerProperties);
if (!m_destroyedLayerIDs.isEmpty())
dumpProperty<Vector<GraphicsLayer::PlatformLayerID>>(ts, "destroyed-layers", m_destroyedLayerIDs);
ts << ")\n";
return ts.release().utf8();
}
#endif // !defined(NDEBUG) || !LOG_DISABLED
} // namespace WebKit