blob: 97cda8a7e7c6e1e22a66c046ab1451fb41e539bd [file] [log] [blame]
/*
* Copyright (C) 2021-2022 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. ``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
* 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.
*/
#include "config.h"
#include "RemoteDisplayListRecorderProxy.h"
#if ENABLE(GPU_PROCESS)
#include "FilterReference.h"
#include "RemoteDisplayListRecorderMessages.h"
#include "WebCoreArgumentCoders.h"
#include <WebCore/DisplayList.h>
#include <WebCore/DisplayListDrawingContext.h>
#include <WebCore/DisplayListItems.h>
#include <WebCore/GraphicsContext.h>
#include <WebCore/ImageBuffer.h>
#include <WebCore/MediaPlayer.h>
#include <WebCore/NotImplemented.h>
#include <wtf/MathExtras.h>
#include <wtf/text/TextStream.h>
namespace WebKit {
using namespace WebCore;
RemoteDisplayListRecorderProxy::RemoteDisplayListRecorderProxy(ImageBuffer& imageBuffer, RemoteRenderingBackendProxy& renderingBackend, const FloatRect& initialClip, const AffineTransform& initialCTM)
: DisplayList::Recorder({ }, initialClip, initialCTM, DrawGlyphsMode::DeconstructUsingDrawGlyphsCommands)
, m_destinationBufferIdentifier(imageBuffer.renderingResourceIdentifier())
, m_imageBuffer(imageBuffer)
, m_renderingBackend(renderingBackend)
{
}
void RemoteDisplayListRecorderProxy::convertToLuminanceMask()
{
send(Messages::RemoteDisplayListRecorder::ConvertToLuminanceMask());
}
void RemoteDisplayListRecorderProxy::transformToColorSpace(const WebCore::DestinationColorSpace& colorSpace)
{
send(Messages::RemoteDisplayListRecorder::TransformToColorSpace(colorSpace));
}
RenderingMode RemoteDisplayListRecorderProxy::renderingMode() const
{
return m_imageBuffer ? m_imageBuffer->renderingMode() : RenderingMode::Unaccelerated;
}
void RemoteDisplayListRecorderProxy::recordSave()
{
send(Messages::RemoteDisplayListRecorder::Save());
}
void RemoteDisplayListRecorderProxy::recordRestore()
{
send(Messages::RemoteDisplayListRecorder::Restore());
}
void RemoteDisplayListRecorderProxy::recordTranslate(float x, float y)
{
send(Messages::RemoteDisplayListRecorder::Translate(x, y));
}
void RemoteDisplayListRecorderProxy::recordRotate(float angle)
{
send(Messages::RemoteDisplayListRecorder::Rotate(angle));
}
void RemoteDisplayListRecorderProxy::recordScale(const FloatSize& scale)
{
send(Messages::RemoteDisplayListRecorder::Scale(scale));
}
void RemoteDisplayListRecorderProxy::recordSetCTM(const AffineTransform& transform)
{
send(Messages::RemoteDisplayListRecorder::SetCTM(transform));
}
void RemoteDisplayListRecorderProxy::recordConcatenateCTM(const AffineTransform& transform)
{
send(Messages::RemoteDisplayListRecorder::ConcatenateCTM(transform));
}
void RemoteDisplayListRecorderProxy::recordSetInlineFillColor(SRGBA<uint8_t> color)
{
send(Messages::RemoteDisplayListRecorder::SetInlineFillColor(DisplayList::SetInlineFillColor { color }));
}
void RemoteDisplayListRecorderProxy::recordSetInlineStrokeColor(SRGBA<uint8_t> color)
{
send(Messages::RemoteDisplayListRecorder::SetInlineStrokeColor(DisplayList::SetInlineStrokeColor { color }));
}
void RemoteDisplayListRecorderProxy::recordSetStrokeThickness(float thickness)
{
send(Messages::RemoteDisplayListRecorder::SetStrokeThickness(thickness));
}
void RemoteDisplayListRecorderProxy::recordSetState(const GraphicsContextState& state)
{
send(Messages::RemoteDisplayListRecorder::SetState(DisplayList::SetState { state }));
}
void RemoteDisplayListRecorderProxy::recordSetLineCap(LineCap lineCap)
{
send(Messages::RemoteDisplayListRecorder::SetLineCap(lineCap));
}
void RemoteDisplayListRecorderProxy::recordSetLineDash(const DashArray& array, float dashOffset)
{
send(Messages::RemoteDisplayListRecorder::SetLineDash(DisplayList::SetLineDash { array, dashOffset }));
}
void RemoteDisplayListRecorderProxy::recordSetLineJoin(LineJoin lineJoin)
{
send(Messages::RemoteDisplayListRecorder::SetLineJoin(lineJoin));
}
void RemoteDisplayListRecorderProxy::recordSetMiterLimit(float limit)
{
send(Messages::RemoteDisplayListRecorder::SetMiterLimit(limit));
}
void RemoteDisplayListRecorderProxy::recordClearShadow()
{
send(Messages::RemoteDisplayListRecorder::ClearShadow());
}
void RemoteDisplayListRecorderProxy::recordClip(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::Clip(rect));
}
void RemoteDisplayListRecorderProxy::recordClipOut(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::ClipOut(rect));
}
void RemoteDisplayListRecorderProxy::recordClipToImageBuffer(ImageBuffer& imageBuffer, const FloatRect& destinationRect)
{
send(Messages::RemoteDisplayListRecorder::ClipToImageBuffer(imageBuffer.renderingResourceIdentifier(), destinationRect));
}
void RemoteDisplayListRecorderProxy::recordClipOutToPath(const Path& path)
{
send(Messages::RemoteDisplayListRecorder::ClipOutToPath(path));
}
void RemoteDisplayListRecorderProxy::recordClipPath(const Path& path, WindRule rule)
{
send(Messages::RemoteDisplayListRecorder::ClipPath(path, rule));
}
void RemoteDisplayListRecorderProxy::recordDrawFilteredImageBuffer(ImageBuffer* sourceImage, const FloatRect& sourceImageRect, Filter& filter)
{
std::optional<RenderingResourceIdentifier> identifier;
if (sourceImage)
identifier = sourceImage->renderingResourceIdentifier();
send(Messages::RemoteDisplayListRecorder::DrawFilteredImageBuffer(WTFMove(identifier), sourceImageRect, IPC::FilterReference(Ref<Filter> { filter })));
}
void RemoteDisplayListRecorderProxy::recordDrawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned count, const FloatPoint& localAnchor, FontSmoothingMode mode)
{
send(Messages::RemoteDisplayListRecorder::DrawGlyphs(DisplayList::DrawGlyphs { font, glyphs, advances, count, localAnchor, mode }));
}
void RemoteDisplayListRecorderProxy::recordDrawDecomposedGlyphs(const Font& font, const DecomposedGlyphs& decomposedGlyphs)
{
send(Messages::RemoteDisplayListRecorder::DrawDecomposedGlyphs(font.renderingResourceIdentifier(), decomposedGlyphs.renderingResourceIdentifier(), decomposedGlyphs.bounds()));
}
void RemoteDisplayListRecorderProxy::recordDrawImageBuffer(ImageBuffer& imageBuffer, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
send(Messages::RemoteDisplayListRecorder::DrawImageBuffer(imageBuffer.renderingResourceIdentifier(), destRect, srcRect, options));
}
void RemoteDisplayListRecorderProxy::recordDrawNativeImage(RenderingResourceIdentifier imageIdentifier, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
send(Messages::RemoteDisplayListRecorder::DrawNativeImage(imageIdentifier, imageSize, destRect, srcRect, options));
}
void RemoteDisplayListRecorderProxy::recordDrawSystemImage(SystemImage& systemImage, const FloatRect& destinationRect)
{
send(Messages::RemoteDisplayListRecorder::DrawSystemImage(systemImage, destinationRect));
}
void RemoteDisplayListRecorderProxy::recordDrawPattern(RenderingResourceIdentifier imageIdentifier, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options)
{
send(Messages::RemoteDisplayListRecorder::DrawPattern(imageIdentifier, destRect, tileRect, transform, phase, spacing, options));
}
void RemoteDisplayListRecorderProxy::recordBeginTransparencyLayer(float opacity)
{
send(Messages::RemoteDisplayListRecorder::BeginTransparencyLayer(opacity));
}
void RemoteDisplayListRecorderProxy::recordEndTransparencyLayer()
{
send(Messages::RemoteDisplayListRecorder::EndTransparencyLayer());
}
void RemoteDisplayListRecorderProxy::recordDrawRect(const FloatRect& rect, float width)
{
send(Messages::RemoteDisplayListRecorder::DrawRect(rect, width));
}
void RemoteDisplayListRecorderProxy::recordDrawLine(const FloatPoint& point1, const FloatPoint& point2)
{
send(Messages::RemoteDisplayListRecorder::DrawLine(point1, point2));
}
void RemoteDisplayListRecorderProxy::recordDrawLinesForText(const FloatPoint& blockLocation, const FloatSize& localAnchor, float thickness, const DashArray& widths, bool printing, bool doubleLines, StrokeStyle style)
{
send(Messages::RemoteDisplayListRecorder::DrawLinesForText(DisplayList::DrawLinesForText { blockLocation, localAnchor, thickness, widths, printing, doubleLines, style }));
}
void RemoteDisplayListRecorderProxy::recordDrawDotsForDocumentMarker(const FloatRect& rect, const DocumentMarkerLineStyle& style)
{
send(Messages::RemoteDisplayListRecorder::DrawDotsForDocumentMarker(rect, style));
}
void RemoteDisplayListRecorderProxy::recordDrawEllipse(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::DrawEllipse(rect));
}
void RemoteDisplayListRecorderProxy::recordDrawPath(const Path& path)
{
send(Messages::RemoteDisplayListRecorder::DrawPath(path));
}
void RemoteDisplayListRecorderProxy::recordDrawFocusRingPath(const Path& path, float width, float offset, const Color& color)
{
send(Messages::RemoteDisplayListRecorder::DrawFocusRingPath(path, width, offset, color));
}
void RemoteDisplayListRecorderProxy::recordDrawFocusRingRects(const Vector<FloatRect>& rects, float width, float offset, const Color& color)
{
send(Messages::RemoteDisplayListRecorder::DrawFocusRingRects(rects, width, offset, color));
}
void RemoteDisplayListRecorderProxy::recordFillRect(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::FillRect(rect));
}
void RemoteDisplayListRecorderProxy::recordFillRectWithColor(const FloatRect& rect, const Color& color)
{
send(Messages::RemoteDisplayListRecorder::FillRectWithColor(rect, color));
}
void RemoteDisplayListRecorderProxy::recordFillRectWithGradient(const FloatRect& rect, Gradient& gradient)
{
send(Messages::RemoteDisplayListRecorder::FillRectWithGradient(DisplayList::FillRectWithGradient { rect, gradient }));
}
void RemoteDisplayListRecorderProxy::recordFillCompositedRect(const FloatRect& rect, const Color& color, CompositeOperator op, BlendMode mode)
{
send(Messages::RemoteDisplayListRecorder::FillCompositedRect(rect, color, op, mode));
}
void RemoteDisplayListRecorderProxy::recordFillRoundedRect(const FloatRoundedRect& roundedRect, const Color& color, BlendMode mode)
{
send(Messages::RemoteDisplayListRecorder::FillRoundedRect(roundedRect, color, mode));
}
void RemoteDisplayListRecorderProxy::recordFillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedRect, const Color& color)
{
send(Messages::RemoteDisplayListRecorder::FillRectWithRoundedHole(rect, roundedRect, color));
}
#if ENABLE(INLINE_PATH_DATA)
void RemoteDisplayListRecorderProxy::recordFillLine(const LineData& data)
{
send(Messages::RemoteDisplayListRecorder::FillLine(data));
}
void RemoteDisplayListRecorderProxy::recordFillArc(const ArcData& data)
{
send(Messages::RemoteDisplayListRecorder::FillArc(data));
}
void RemoteDisplayListRecorderProxy::recordFillQuadCurve(const QuadCurveData& data)
{
send(Messages::RemoteDisplayListRecorder::FillQuadCurve(data));
}
void RemoteDisplayListRecorderProxy::recordFillBezierCurve(const BezierCurveData& data)
{
send(Messages::RemoteDisplayListRecorder::FillBezierCurve(data));
}
#endif // ENABLE(INLINE_PATH_DATA)
void RemoteDisplayListRecorderProxy::recordFillPath(const Path& path)
{
send(Messages::RemoteDisplayListRecorder::FillPath(path));
}
void RemoteDisplayListRecorderProxy::recordFillEllipse(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::FillEllipse(rect));
}
void RemoteDisplayListRecorderProxy::recordPaintFrameForMedia(MediaPlayer& player, const FloatRect& destination)
{
send(Messages::RemoteDisplayListRecorder::PaintFrameForMedia(player.identifier(), destination));
}
void RemoteDisplayListRecorderProxy::recordStrokeRect(const FloatRect& rect, float width)
{
send(Messages::RemoteDisplayListRecorder::StrokeRect(rect, width));
}
#if ENABLE(INLINE_PATH_DATA)
void RemoteDisplayListRecorderProxy::recordStrokeLine(const LineData& data)
{
send(Messages::RemoteDisplayListRecorder::StrokeLine(data));
}
void RemoteDisplayListRecorderProxy::recordStrokeArc(const ArcData& data)
{
send(Messages::RemoteDisplayListRecorder::StrokeArc(data));
}
void RemoteDisplayListRecorderProxy::recordStrokeQuadCurve(const QuadCurveData& data)
{
send(Messages::RemoteDisplayListRecorder::StrokeQuadCurve(data));
}
void RemoteDisplayListRecorderProxy::recordStrokeBezierCurve(const BezierCurveData& data)
{
send(Messages::RemoteDisplayListRecorder::StrokeBezierCurve(data));
}
#endif // ENABLE(INLINE_PATH_DATA)
void RemoteDisplayListRecorderProxy::recordStrokePath(const Path& path)
{
send(Messages::RemoteDisplayListRecorder::StrokePath(path));
}
void RemoteDisplayListRecorderProxy::recordStrokeEllipse(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::StrokeEllipse(rect));
}
void RemoteDisplayListRecorderProxy::recordClearRect(const FloatRect& rect)
{
send(Messages::RemoteDisplayListRecorder::ClearRect(rect));
}
#if USE(CG)
void RemoteDisplayListRecorderProxy::recordApplyStrokePattern()
{
send(Messages::RemoteDisplayListRecorder::ApplyStrokePattern());
}
void RemoteDisplayListRecorderProxy::recordApplyFillPattern()
{
send(Messages::RemoteDisplayListRecorder::ApplyFillPattern());
}
#endif // USE(CG)
void RemoteDisplayListRecorderProxy::recordApplyDeviceScaleFactor(float scaleFactor)
{
send(Messages::RemoteDisplayListRecorder::ApplyDeviceScaleFactor(scaleFactor));
}
bool RemoteDisplayListRecorderProxy::recordResourceUse(NativeImage& image)
{
if (UNLIKELY(!m_renderingBackend)) {
ASSERT_NOT_REACHED();
return false;
}
m_renderingBackend->remoteResourceCacheProxy().recordNativeImageUse(image);
return true;
}
bool RemoteDisplayListRecorderProxy::recordResourceUse(ImageBuffer& imageBuffer)
{
if (UNLIKELY(!m_renderingBackend)) {
ASSERT_NOT_REACHED();
return false;
}
if (!m_renderingBackend->isCached(imageBuffer))
return false;
m_renderingBackend->remoteResourceCacheProxy().recordImageBufferUse(imageBuffer);
return true;
}
bool RemoteDisplayListRecorderProxy::recordResourceUse(const SourceImage& image)
{
if (auto imageBuffer = image.imageBufferIfExists())
return recordResourceUse(*imageBuffer);
if (auto nativeImage = image.nativeImageIfExists())
return recordResourceUse(*nativeImage);
return true;
}
bool RemoteDisplayListRecorderProxy::recordResourceUse(Font& font)
{
if (UNLIKELY(!m_renderingBackend)) {
ASSERT_NOT_REACHED();
return false;
}
m_renderingBackend->remoteResourceCacheProxy().recordFontUse(font);
return true;
}
bool RemoteDisplayListRecorderProxy::recordResourceUse(DecomposedGlyphs& decomposedGlyphs)
{
if (UNLIKELY(!m_renderingBackend)) {
ASSERT_NOT_REACHED();
return false;
}
m_renderingBackend->remoteResourceCacheProxy().recordDecomposedGlyphsUse(decomposedGlyphs);
return true;
}
void RemoteDisplayListRecorderProxy::flushContext(GraphicsContextFlushIdentifier identifier)
{
send(Messages::RemoteDisplayListRecorder::FlushContext(identifier));
}
RefPtr<ImageBuffer> RemoteDisplayListRecorderProxy::createImageBuffer(const FloatSize& size, float resolutionScale, const DestinationColorSpace& colorSpace, std::optional<RenderingMode> renderingMode, std::optional<RenderingMethod> renderingMethod) const
{
if (UNLIKELY(!m_renderingBackend)) {
ASSERT_NOT_REACHED();
return nullptr;
}
if (renderingMethod)
return Recorder::createImageBuffer(size, resolutionScale, colorSpace, renderingMode, renderingMethod);
// FIXME: Ideally we'd plumb the purpose through for callers of GraphicsContext::createImageBuffer().
RenderingPurpose purpose = m_imageBuffer ? m_imageBuffer->renderingPurpose() : RenderingPurpose::Unspecified;
return m_renderingBackend->createImageBuffer(size, renderingMode.value_or(this->renderingMode()), purpose, resolutionScale, colorSpace, PixelFormat::BGRA8);
}
RefPtr<ImageBuffer> RemoteDisplayListRecorderProxy::createAlignedImageBuffer(const FloatSize& size, const DestinationColorSpace& colorSpace, std::optional<RenderingMethod> renderingMethod) const
{
auto renderingMode = !renderingMethod ? this->renderingMode() : RenderingMode::Unaccelerated;
return GraphicsContext::createScaledImageBuffer(size, scaleFactor(), colorSpace, renderingMode, renderingMethod);
}
RefPtr<ImageBuffer> RemoteDisplayListRecorderProxy::createAlignedImageBuffer(const FloatRect& rect, const DestinationColorSpace& colorSpace, std::optional<RenderingMethod> renderingMethod) const
{
auto renderingMode = !renderingMethod ? this->renderingMode() : RenderingMode::Unaccelerated;
return GraphicsContext::createScaledImageBuffer(rect, scaleFactor(), colorSpace, renderingMode, renderingMethod);
}
} // namespace WebCore
#endif // ENABLE(GPU_PROCESS)