/*
 * Copyright (C) 2013-2021 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.
 */

#import "config.h"
#import "RemoteLayerBackingStore.h"

#import "ArgumentCoders.h"
#import "CGDisplayListImageBufferBackend.h"
#import "MachPort.h"
#import "PlatformCALayerRemote.h"
#import "PlatformRemoteImageBufferProxy.h"
#import "RemoteLayerBackingStoreCollection.h"
#import "RemoteLayerTreeContext.h"
#import "RemoteLayerTreeLayers.h"
#import "ShareableBitmap.h"
#import "WebCoreArgumentCoders.h"
#import "WebProcess.h"
#import <QuartzCore/QuartzCore.h>
#import <WebCore/BifurcatedGraphicsContext.h>
#import <WebCore/GraphicsContextCG.h>
#import <WebCore/IOSurface.h>
#import <WebCore/ImageBuffer.h>
#import <WebCore/Model.h>
#import <WebCore/PlatformCALayerClient.h>
#import <WebCore/WebLayer.h>
#import <mach/mach_port.h>
#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/cocoa/TypeCastsCocoa.h>

#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
#import <WebKitAdditions/CGDisplayListImageBufferAdditions.h>
#endif

namespace WebKit {

RemoteLayerBackingStore::RemoteLayerBackingStore(PlatformCALayerRemote* layer)
    : m_layer(layer)
    , m_isOpaque(false)
    , m_lastDisplayTime(-MonotonicTime::infinity())
{
    if (!m_layer)
        return;
    if (RemoteLayerTreeContext* context = m_layer->context())
        context->backingStoreWasCreated(*this);
}

RemoteLayerBackingStore::~RemoteLayerBackingStore()
{
    clearBackingStore();

    if (!m_layer)
        return;

    if (RemoteLayerTreeContext* context = m_layer->context())
        context->backingStoreWillBeDestroyed(*this);
}

void RemoteLayerBackingStore::ensureBackingStore(Type type, WebCore::FloatSize size, float scale, bool deepColor, bool isOpaque, IncludeDisplayList includeDisplayList)
{
    if (m_type == type && m_size == size && m_scale == scale && m_deepColor == deepColor && m_isOpaque == isOpaque && m_includeDisplayList == includeDisplayList)
        return;

    m_type = type;
    m_size = size;
    m_scale = scale;
    m_deepColor = deepColor;
    m_isOpaque = isOpaque;
    m_includeDisplayList = includeDisplayList;

    if (m_frontBuffer) {
        // If we have a valid backing store, we need to ensure that it gets completely
        // repainted the next time display() is called.
        setNeedsDisplay();
    }

    clearBackingStore();
}

void RemoteLayerBackingStore::clearBackingStore()
{
    m_frontBuffer.discard();
    m_backBuffer.discard();
    m_secondaryBackBuffer.discard();
}

void RemoteLayerBackingStore::encode(IPC::Encoder& encoder) const
{
    encoder << m_type;
    encoder << m_size;
    encoder << m_scale;
    encoder << m_isOpaque;
    encoder << m_includeDisplayList;

    std::optional<ImageBufferBackendHandle> handle;
    if (m_frontBuffer.imageBuffer) {
        switch (m_type) {
        case Type::IOSurface:
            if (m_frontBuffer.imageBuffer->canMapBackingStore())
                handle = static_cast<AcceleratedImageBufferShareableMappedBackend&>(*m_frontBuffer.imageBuffer->ensureBackendCreated()).createImageBufferBackendHandle();
            else
                handle = static_cast<AcceleratedImageBufferShareableBackend&>(*m_frontBuffer.imageBuffer->ensureBackendCreated()).createImageBufferBackendHandle();
            break;
        case Type::Bitmap:
            handle = static_cast<UnacceleratedImageBufferShareableBackend&>(*m_frontBuffer.imageBuffer->ensureBackendCreated()).createImageBufferBackendHandle();
            break;
        }
    }

    encoder << handle;

#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
    std::optional<ImageBufferBackendHandle> displayListHandle;
    if (m_frontBuffer.displayListImageBuffer)
        displayListHandle = static_cast<CGDisplayListImageBufferBackend&>(*m_frontBuffer.displayListImageBuffer->ensureBackendCreated()).createImageBufferBackendHandle();

    encoder << displayListHandle;
#endif
}

bool RemoteLayerBackingStore::decode(IPC::Decoder& decoder, RemoteLayerBackingStore& result)
{
    if (!decoder.decode(result.m_type))
        return false;

    if (!decoder.decode(result.m_size))
        return false;

    if (!decoder.decode(result.m_scale))
        return false;

    if (!decoder.decode(result.m_isOpaque))
        return false;

    if (!decoder.decode(result.m_includeDisplayList))
        return false;

    if (!decoder.decode(result.m_bufferHandle))
        return false;

#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
    if (!decoder.decode(result.m_displayListBufferHandle))
        return false;
#endif

    return true;
}

void RemoteLayerBackingStore::setNeedsDisplay(const WebCore::IntRect rect)
{
    m_dirtyRegion.unite(rect);
}

void RemoteLayerBackingStore::setNeedsDisplay()
{
    setNeedsDisplay(WebCore::IntRect(WebCore::IntPoint(), WebCore::expandedIntSize(m_size)));
}

WebCore::PixelFormat RemoteLayerBackingStore::pixelFormat() const
{
#if HAVE(IOSURFACE_RGB10)
    if (m_type == Type::IOSurface && m_deepColor)
        return m_isOpaque ? WebCore::PixelFormat::RGB10 : WebCore::PixelFormat::RGB10A8;
#endif

    return WebCore::PixelFormat::BGRA8;
}

unsigned RemoteLayerBackingStore::bytesPerPixel() const
{
    switch (pixelFormat()) {
    case WebCore::PixelFormat::RGBA8: return 4;
    case WebCore::PixelFormat::BGRA8: return 4;
    case WebCore::PixelFormat::RGB10: return 4;
    case WebCore::PixelFormat::RGB10A8: return 5;
    }
    return 4;
}

void RemoteLayerBackingStore::swapToValidFrontBuffer()
{
    // Sometimes, we can get two swaps ahead of the render server.
    // If we're using shared IOSurfaces, we must wait to modify
    // a surface until it no longer has outstanding clients.
    if (m_type == Type::IOSurface) {
        if (!m_backBuffer.imageBuffer || m_backBuffer.imageBuffer->isInUse()) {
            std::swap(m_backBuffer, m_secondaryBackBuffer);

            // When pulling the secondary back buffer out of hibernation (to become
            // the new front buffer), if it is somehow still in use (e.g. we got
            // three swaps ahead of the render server), just give up and discard it.
            if (m_backBuffer.imageBuffer && m_backBuffer.imageBuffer->isInUse())
                m_backBuffer.discard();
        }
    }

    std::swap(m_frontBuffer, m_backBuffer);

    if (m_frontBuffer.imageBuffer) {
        setBufferVolatility(BufferType::Front, false);
        return;
    }

    bool shouldUseRemoteRendering = WebProcess::singleton().shouldUseRemoteRenderingFor(WebCore::RenderingPurpose::DOM);

    switch (m_type) {
    case Type::IOSurface:
        if (shouldUseRemoteRendering)
            m_frontBuffer.imageBuffer = m_layer->context()->ensureRemoteRenderingBackendProxy().createImageBuffer(m_size, WebCore::RenderingMode::Accelerated, m_scale, WebCore::DestinationColorSpace::SRGB(), pixelFormat());
        else
            m_frontBuffer.imageBuffer = WebCore::ConcreteImageBuffer<AcceleratedImageBufferShareableMappedBackend>::create(m_size, m_scale, WebCore::DestinationColorSpace::SRGB(), pixelFormat(), nullptr);
        break;
    case Type::Bitmap:
        if (shouldUseRemoteRendering)
            m_frontBuffer.imageBuffer = m_layer->context()->ensureRemoteRenderingBackendProxy().createImageBuffer(m_size, WebCore::RenderingMode::Unaccelerated, m_scale, WebCore::DestinationColorSpace::SRGB(), pixelFormat());
        else
            m_frontBuffer.imageBuffer = WebCore::ConcreteImageBuffer<UnacceleratedImageBufferShareableBackend>::create(m_size, m_scale, WebCore::DestinationColorSpace::SRGB(), pixelFormat(), nullptr);
        break;
    }

#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
    if (m_includeDisplayList == IncludeDisplayList::Yes)
        m_frontBuffer.displayListImageBuffer = WebCore::ConcreteImageBuffer<CGDisplayListImageBufferBackend>::create(m_size, m_scale, WebCore::DestinationColorSpace::SRGB(), pixelFormat(), nullptr);
#endif
}

bool RemoteLayerBackingStore::supportsPartialRepaint()
{
    // FIXME: Find a way to support partial repaint for backing store that
    // includes a display list without allowing unbounded memory growth.
    return m_includeDisplayList == IncludeDisplayList::No;
}

bool RemoteLayerBackingStore::display()
{
    ASSERT(!m_frontBufferFlushers.size());

    m_lastDisplayTime = MonotonicTime::now();

    bool needToEncodeBackingStore = false;
    if (RemoteLayerTreeContext* context = m_layer->context())
        needToEncodeBackingStore = context->backingStoreWillBeDisplayed(*this);

    // Make the previous front buffer non-volatile early, so that we can dirty the whole layer if it comes back empty.
    setBufferVolatility(BufferType::Front, false);

    if (m_dirtyRegion.isEmpty() || m_size.isEmpty())
        return needToEncodeBackingStore;

    WebCore::IntRect layerBounds(WebCore::IntPoint(), WebCore::expandedIntSize(m_size));
    if (!hasFrontBuffer() || !supportsPartialRepaint())
        m_dirtyRegion.unite(layerBounds);

    if (m_layer->owner()->platformCALayerShowRepaintCounter(m_layer)) {
        WebCore::IntRect indicatorRect(0, 0, 52, 27);
        m_dirtyRegion.unite(indicatorRect);
    }

    swapToValidFrontBuffer();
    if (!m_frontBuffer.imageBuffer)
        return true;


    if (m_includeDisplayList == IncludeDisplayList::Yes) {
#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
        auto& displayListContext = m_frontBuffer.displayListImageBuffer->context();

        // FIXME: Remove this when <rdar://problem/80487697> is fixed.
        static std::optional<bool> needsMissingFlipWorkaround;
        WebCore::GraphicsContextStateSaver workaroundStateSaver(displayListContext, false);
        if (!needsMissingFlipWorkaround) {
            id defaultValue = [[NSUserDefaults standardUserDefaults] objectForKey:@"WebKitNeedsWorkaroundFor80487697"];
            needsMissingFlipWorkaround = defaultValue ? [defaultValue boolValue] : true;
        }
        if (needsMissingFlipWorkaround.value()) {
            workaroundStateSaver.save();
            displayListContext.scale(WebCore::FloatSize(1, -1));
            displayListContext.translate(0, -m_size.height());
        }

        WebCore::BifurcatedGraphicsContext context(m_frontBuffer.imageBuffer->context(), displayListContext);
#else
        WebCore::GraphicsContext& context = m_frontBuffer.imageBuffer->context();
#endif
        drawInContext(context);
    } else {
        WebCore::GraphicsContext& context = m_frontBuffer.imageBuffer->context();
        drawInContext(context);    
    }

    m_dirtyRegion = WebCore::Region();
    m_paintingRects.clear();

    m_layer->owner()->platformCALayerLayerDidDisplay(m_layer);

    m_frontBuffer.imageBuffer->flushDrawingContextAsync();

    m_frontBufferFlushers.append(m_frontBuffer.imageBuffer->createFlusher());
#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
    if (m_includeDisplayList == IncludeDisplayList::Yes)
        m_frontBufferFlushers.append(m_frontBuffer.displayListImageBuffer->createFlusher());
#endif

    return true;
}

void RemoteLayerBackingStore::drawInContext(WebCore::GraphicsContext& context)
{
    WebCore::GraphicsContextStateSaver stateSaver(context);

    // If we have less than webLayerMaxRectsToPaint rects to paint and they cover less
    // than webLayerWastedSpaceThreshold of the total dirty area, we'll repaint each rect separately.
    // Otherwise, repaint the entire bounding box of the dirty region.
    WebCore::IntRect dirtyBounds = m_dirtyRegion.bounds();

    auto dirtyRects = m_dirtyRegion.rects();
    if (dirtyRects.size() > WebCore::PlatformCALayer::webLayerMaxRectsToPaint || m_dirtyRegion.totalArea() > WebCore::PlatformCALayer::webLayerWastedSpaceThreshold * dirtyBounds.width() * dirtyBounds.height()) {
        dirtyRects.clear();
        dirtyRects.append(dirtyBounds);
    }

    // FIXME: find a consistent way to scale and snap dirty and CG clip rects.
    for (const auto& rect : dirtyRects) {
        WebCore::FloatRect scaledRect(rect);
        scaledRect.scale(m_scale);
        scaledRect = WebCore::enclosingIntRect(scaledRect);
        scaledRect.scale(1 / m_scale);
        m_paintingRects.append(scaledRect);
    }

    WebCore::IntRect layerBounds(WebCore::IntPoint(), WebCore::expandedIntSize(m_size));
    if (!m_dirtyRegion.contains(layerBounds)) {
        ASSERT(m_backBuffer.imageBuffer);
        context.drawImageBuffer(*m_backBuffer.imageBuffer, { {0, 0}, m_size }, { {0, 0}, m_size }, { WebCore::CompositeOperator::Copy });
    }

    if (m_paintingRects.size() == 1)
        context.clip(m_paintingRects[0]);
    else {
        WebCore::Path clipPath;
        for (auto rect : m_paintingRects)
            clipPath.addRect(rect);
        context.clipPath(clipPath);
    }

    if (!m_isOpaque)
        context.clearRect(layerBounds);

#ifndef NDEBUG
    if (m_isOpaque)
        context.fillRect(layerBounds, WebCore::SRGBA<uint8_t> { 255, 47, 146 });
#endif

    // FIXME: Clarify that WebCore::GraphicsLayerPaintSnapshotting is just about image decoding.
    auto flags = m_layer->context() && m_layer->context()->nextRenderingUpdateRequiresSynchronousImageDecoding() ? WebCore::GraphicsLayerPaintSnapshotting : WebCore::GraphicsLayerPaintNormal;
    
    // FIXME: This should be moved to PlatformCALayerRemote for better layering.
    switch (m_layer->layerType()) {
    case WebCore::PlatformCALayer::LayerTypeSimpleLayer:
    case WebCore::PlatformCALayer::LayerTypeTiledBackingTileLayer:
        m_layer->owner()->platformCALayerPaintContents(m_layer, context, dirtyBounds, flags);
        break;
    case WebCore::PlatformCALayer::LayerTypeWebLayer:
    case WebCore::PlatformCALayer::LayerTypeBackdropLayer:
        WebCore::PlatformCALayer::drawLayerContents(context, m_layer, m_paintingRects, flags);
        break;
    case WebCore::PlatformCALayer::LayerTypeDarkSystemBackdropLayer:
    case WebCore::PlatformCALayer::LayerTypeLightSystemBackdropLayer:
        // FIXME: These have a more complicated layer hierarchy. We need to paint into
        // a child layer in order to see the rendered results.
        WebCore::PlatformCALayer::drawLayerContents(context, m_layer, m_paintingRects, flags);
        break;
    case WebCore::PlatformCALayer::LayerTypeLayer:
    case WebCore::PlatformCALayer::LayerTypeTransformLayer:
    case WebCore::PlatformCALayer::LayerTypeTiledBackingLayer:
    case WebCore::PlatformCALayer::LayerTypePageTiledBackingLayer:
    case WebCore::PlatformCALayer::LayerTypeRootLayer:
    case WebCore::PlatformCALayer::LayerTypeAVPlayerLayer:
    case WebCore::PlatformCALayer::LayerTypeContentsProvidedLayer:
    case WebCore::PlatformCALayer::LayerTypeShapeLayer:
    case WebCore::PlatformCALayer::LayerTypeScrollContainerLayer:
#if ENABLE(MODEL_ELEMENT)
    case WebCore::PlatformCALayer::LayerTypeModelLayer:
#endif
    case WebCore::PlatformCALayer::LayerTypeCustom:
        ASSERT_NOT_REACHED();
        break;
    };
}

void RemoteLayerBackingStore::enumerateRectsBeingDrawn(WebCore::GraphicsContext& context, void (^block)(WebCore::FloatRect))
{
    CGAffineTransform inverseTransform = CGAffineTransformInvert(context.getCTM());

    // We don't want to un-apply the flipping or contentsScale,
    // because they're not applied to repaint rects.
    inverseTransform = CGAffineTransformScale(inverseTransform, m_scale, -m_scale);
    inverseTransform = CGAffineTransformTranslate(inverseTransform, 0, -m_size.height());

    for (const auto& rect : m_paintingRects) {
        CGRect rectToDraw = CGRectApplyAffineTransform(rect, inverseTransform);
        block(rectToDraw);
    }
}

void RemoteLayerBackingStore::applyBackingStoreToLayer(CALayer *layer, LayerContentsType contentsType)
{
    ASSERT(m_bufferHandle);
    layer.contentsOpaque = m_isOpaque;

    RetainPtr<id> contents;
    WTF::switchOn(*m_bufferHandle,
        [&] (ShareableBitmap::Handle& handle) {
            ASSERT(m_type == Type::Bitmap);
            contents = bridge_id_cast(ShareableBitmap::create(handle)->makeCGImageCopy());
        },
        [&] (MachSendRight& machSendRight) {
            ASSERT(m_type == Type::IOSurface);
            switch (contentsType) {
            case RemoteLayerBackingStore::LayerContentsType::IOSurface: {
                auto surface = WebCore::IOSurface::createFromSendRight(WTFMove(machSendRight), WebCore::DestinationColorSpace::SRGB());
                contents = surface ? surface->asLayerContents() : nil;
                break;
            }
            case RemoteLayerBackingStore::LayerContentsType::CAMachPort:
                contents = bridge_id_cast(adoptCF(CAMachPortCreate(machSendRight.leakSendRight())));
                break;
            }
        }
#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
        , [&] (IPC::SharedBufferCopy& buffer) {
            ASSERT_NOT_REACHED();
        }
#endif
    );

#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
    if (m_displayListBufferHandle) {
        ASSERT([layer isKindOfClass:[WKCompositingLayer class]]);
        if (![layer isKindOfClass:[WKCompositingLayer class]])
            return;
        [layer setValue:@1 forKeyPath:WKCGDisplayListEnabledKey];
        [layer setValue:@1 forKeyPath:WKCGDisplayListBifurcationEnabledKey];
        auto data = std::get<IPC::SharedBufferCopy>(*m_displayListBufferHandle).buffer()->createCFData();
        [(WKCompositingLayer *)layer _setWKContents:contents.get() withDisplayList:data.get()];
        return;
    }
#endif

    layer.contents = contents.get();
}

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> RemoteLayerBackingStore::takePendingFlushers()
{
    return std::exchange(m_frontBufferFlushers, { });
}

bool RemoteLayerBackingStore::setBufferVolatility(BufferType bufferType, bool isVolatile)
{
    if (m_type != Type::IOSurface)
        return true;

    // Return value is true if we succeeded in making volatile.
    auto makeVolatile = [] (Buffer& buffer) -> bool {
        if (!buffer.imageBuffer || buffer.isVolatile)
            return true;

        buffer.imageBuffer->releaseGraphicsContext();

        if (!buffer.imageBuffer->isInUse()) {
            buffer.imageBuffer->setVolatile(true);
            buffer.isVolatile = true;
            return true;
        }
    
        return false;
    };

    // Return value is true if we need to repaint.
    auto makeNonVolatile = [] (Buffer& buffer) -> bool {
        if (!buffer.imageBuffer || !buffer.isVolatile)
            return false;

        auto previousState = buffer.imageBuffer->setVolatile(false);
        buffer.isVolatile = false;

        return previousState == WebCore::VolatilityState::Empty;
    };

    switch (bufferType) {
    case BufferType::Front:
        if (isVolatile)
            return makeVolatile(m_frontBuffer);
        
        // Becoming non-volatile and the front buffer was purged, so we need to repaint.
        if (makeNonVolatile(m_frontBuffer))
            setNeedsDisplay();
        break;
    case BufferType::Back:
        if (isVolatile)
            return makeVolatile(m_backBuffer);
    
        makeNonVolatile(m_backBuffer);
        break;
    case BufferType::SecondaryBack:
        if (isVolatile)
            return makeVolatile(m_secondaryBackBuffer);
    
        makeNonVolatile(m_secondaryBackBuffer);
        break;
    }
    return true;
}

void RemoteLayerBackingStore::Buffer::discard()
{
    isVolatile = false;
    if (imageBuffer)
        imageBuffer->releaseBufferToPool();
    imageBuffer = nullptr;
#if ENABLE(CG_DISPLAY_LIST_BACKED_IMAGE_BUFFER)
    displayListImageBuffer = nullptr;
#endif
}

} // namespace WebKit
