/*
 * Copyright (C) 2012 Google 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 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 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.
 */

#include "platform/graphics/Canvas2DLayerBridge.h"

#include "base/memory/ptr_util.h"
#include "cc/resources/single_release_callback.h"
#include "cc/resources/texture_mailbox.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "platform/Histogram.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/WebTaskRunner.h"
#include "platform/graphics/CanvasMetrics.h"
#include "platform/graphics/ExpensiveCanvasHeuristicParameters.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/gpu/SharedContextRateLimiter.h"
#include "platform/graphics/paint/PaintCanvas.h"
#include "platform/graphics/paint/PaintSurface.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebGraphicsContext3DProvider.h"
#include "public/platform/WebScheduler.h"
#include "public/platform/WebTraceLocation.h"
#include "skia/ext/texture_handle.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
#include "wtf/PtrUtil.h"
#include <memory>

namespace {
enum {
  InvalidMailboxIndex = -1,
  MaxCanvasAnimationBacklog = 2,  // Make sure the the GPU is never more than
                                  // two animation frames behind.
};
}  // namespace

namespace blink {

#if USE_IOSURFACE_FOR_2D_CANVAS
struct Canvas2DLayerBridge::ImageInfo : public RefCounted<ImageInfo> {
  ImageInfo(std::unique_ptr<gfx::GpuMemoryBuffer>,
            GLuint imageId,
            GLuint textureId);
  ~ImageInfo();

  // The backing buffer.
  std::unique_ptr<gfx::GpuMemoryBuffer> m_gpuMemoryBuffer;

  // The id of the CHROMIUM image.
  const GLuint m_imageId;

  // The id of the texture bound to the CHROMIUM image.
  const GLuint m_textureId;
};
#endif  // USE_IOSURFACE_FOR_2D_CANVAS

static sk_sp<PaintSurface> createSkSurface(GrContext* gr,
                                           const IntSize& size,
                                           int msaaSampleCount,
                                           OpacityMode opacityMode,
                                           sk_sp<SkColorSpace> colorSpace,
                                           SkColorType colorType,
                                           bool* surfaceIsAccelerated) {
  if (gr)
    gr->resetContext();

  SkAlphaType alphaType =
      (Opaque == opacityMode) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
  SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType,
                                       alphaType, colorSpace);
  SkSurfaceProps disableLCDProps(0, kUnknown_SkPixelGeometry);
  sk_sp<PaintSurface> surface;

  if (gr) {
    *surfaceIsAccelerated = true;
    surface = PaintSurface::MakeRenderTarget(
        gr, SkBudgeted::kNo, info, msaaSampleCount,
        Opaque == opacityMode ? 0 : &disableLCDProps);
  }

  if (!surface) {
    *surfaceIsAccelerated = false;
    surface = PaintSurface::MakeRaster(
        info, Opaque == opacityMode ? 0 : &disableLCDProps);
  }

  if (surface) {
    if (opacityMode == Opaque) {
      surface->getCanvas()->clear(SK_ColorBLACK);
    } else {
      surface->getCanvas()->clear(SK_ColorTRANSPARENT);
    }
  }
  return surface;
}

Canvas2DLayerBridge::Canvas2DLayerBridge(
    std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
    const IntSize& size,
    int msaaSampleCount,
    OpacityMode opacityMode,
    AccelerationMode accelerationMode,
    const gfx::ColorSpace& colorSpace,
    bool skSurfacesUseColorSpace,
    SkColorType colorType)
    : m_contextProvider(std::move(contextProvider)),
      m_logger(WTF::wrapUnique(new Logger)),
      m_weakPtrFactory(this),
      m_imageBuffer(0),
      m_msaaSampleCount(msaaSampleCount),
      m_bytesAllocated(0),
      m_haveRecordedDrawCommands(false),
      m_destructionInProgress(false),
      m_filterQuality(kLow_SkFilterQuality),
      m_isHidden(false),
      m_isDeferralEnabled(true),
      m_softwareRenderingWhileHidden(false),
      m_lastImageId(0),
      m_lastFilter(GL_LINEAR),
      m_accelerationMode(accelerationMode),
      m_opacityMode(opacityMode),
      m_size(size),
      m_colorSpace(colorSpace),
      m_skSurfacesUseColorSpace(skSurfacesUseColorSpace),
      m_colorType(colorType) {
  DCHECK(m_contextProvider);
  DCHECK(!m_contextProvider->isSoftwareRendering());
  DCHECK(m_colorSpace.IsValid());
  // Used by browser tests to detect the use of a Canvas2DLayerBridge.
  TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation",
                       TRACE_EVENT_SCOPE_GLOBAL);
  startRecording();
}

Canvas2DLayerBridge::~Canvas2DLayerBridge() {
  DCHECK(m_destructionInProgress);
#if USE_IOSURFACE_FOR_2D_CANVAS
  clearCHROMIUMImageCache();
#endif  // USE_IOSURFACE_FOR_2D_CANVAS

  m_layer.reset();
  DCHECK_EQ(0u, m_mailboxes.size());
}

void Canvas2DLayerBridge::startRecording() {
  DCHECK(m_isDeferralEnabled);
  m_recorder = WTF::wrapUnique(new PaintRecorder);
  PaintCanvas* canvas =
      m_recorder->beginRecording(m_size.width(), m_size.height(), nullptr);
  // Always save an initial frame, to support resetting the top level matrix
  // and clip.
  canvas->save();

  if (m_imageBuffer) {
    m_imageBuffer->resetCanvas(canvas);
  }
  m_recordingPixelCount = 0;
}

void Canvas2DLayerBridge::setLoggerForTesting(std::unique_ptr<Logger> logger) {
  m_logger = std::move(logger);
}

bool Canvas2DLayerBridge::shouldAccelerate(AccelerationHint hint) const {
  bool accelerate;
  if (m_softwareRenderingWhileHidden)
    accelerate = false;
  else if (m_accelerationMode == ForceAccelerationForTesting)
    accelerate = true;
  else if (m_accelerationMode == DisableAcceleration)
    accelerate = false;
  else
    accelerate = hint == PreferAcceleration ||
                 hint == PreferAccelerationAfterVisibilityChange;

  if (accelerate &&
      (!m_contextProvider ||
       m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() !=
           GL_NO_ERROR))
    accelerate = false;
  return accelerate;
}

bool Canvas2DLayerBridge::isAccelerated() const {
  if (m_accelerationMode == DisableAcceleration)
    return false;
  if (isHibernating())
    return false;
  if (m_softwareRenderingWhileHidden)
    return false;
  if (m_layer) {
    // We don't check |m_surface|, so this returns true if context was lost
    // (|m_surface| is null) with restoration pending.
    return true;
  }
  if (m_surface)  // && !m_layer is implied
    return false;

  // Whether or not to accelerate is not yet resolved. Determine whether
  // immediate presentation of the canvas would result in the canvas being
  // accelerated. Presentation is assumed to be a 'PreferAcceleration'
  // operation.
  return shouldAccelerate(PreferAcceleration);
}

GLenum Canvas2DLayerBridge::getGLFilter() {
  return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
}

#if USE_IOSURFACE_FOR_2D_CANVAS
bool Canvas2DLayerBridge::prepareIOSurfaceMailboxFromImage(
    SkImage* image,
    cc::TextureMailbox* outMailbox) {
  // Need to flush skia's internal queue, because the texture is about to be
  // accessed directly.
  GrContext* grContext = m_contextProvider->grContext();
  grContext->flush();

  RefPtr<ImageInfo> imageInfo = createIOSurfaceBackedTexture();
  if (!imageInfo)
    return false;

  gpu::gles2::GLES2Interface* gl = contextGL();
  if (!gl)
    return false;

  GLuint imageTexture =
      skia::GrBackendObjectToGrGLTextureInfo(image->getTextureHandle(true))
          ->fID;
  GLenum textureTarget = GC3D_TEXTURE_RECTANGLE_ARB;
  gl->CopySubTextureCHROMIUM(
      imageTexture, 0, textureTarget, imageInfo->m_textureId, 0, 0, 0, 0, 0,
      m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE);

  MailboxInfo& info = m_mailboxes.first();
  gpu::Mailbox mailbox;
  gl->GenMailboxCHROMIUM(mailbox.name);
  gl->ProduceTextureDirectCHROMIUM(imageInfo->m_textureId, textureTarget,
                                   mailbox.name);

  const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM();
  gl->Flush();
  gpu::SyncToken syncToken;
  gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData());

  info.m_imageInfo = imageInfo;
  bool isOverlayCandidate = true;
  bool secureOutputOnly = false;
  info.m_mailbox = mailbox;

  *outMailbox =
      cc::TextureMailbox(mailbox, syncToken, textureTarget, gfx::Size(m_size),
                         isOverlayCandidate, secureOutputOnly);
  if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) {
    outMailbox->set_color_space(m_colorSpace);
    imageInfo->m_gpuMemoryBuffer->SetColorSpaceForScanout(m_colorSpace);
  }

  gl->BindTexture(GC3D_TEXTURE_RECTANGLE_ARB, 0);

  // Because we are changing the texture binding without going through skia,
  // we must dirty the context.
  grContext->resetContext(kTextureBinding_GrGLBackendState);

  return true;
}

RefPtr<Canvas2DLayerBridge::ImageInfo>
Canvas2DLayerBridge::createIOSurfaceBackedTexture() {
  if (!m_imageInfoCache.isEmpty()) {
    RefPtr<Canvas2DLayerBridge::ImageInfo> info = m_imageInfoCache.back();
    m_imageInfoCache.pop_back();
    return info;
  }

  gpu::gles2::GLES2Interface* gl = contextGL();
  if (!gl)
    return nullptr;

  gpu::GpuMemoryBufferManager* gpuMemoryBufferManager =
      Platform::current()->getGpuMemoryBufferManager();
  if (!gpuMemoryBufferManager)
    return nullptr;

  std::unique_ptr<gfx::GpuMemoryBuffer> gpuMemoryBuffer =
      gpuMemoryBufferManager->CreateGpuMemoryBuffer(
          gfx::Size(m_size), gfx::BufferFormat::RGBA_8888,
          gfx::BufferUsage::SCANOUT, gpu::kNullSurfaceHandle);
  if (!gpuMemoryBuffer)
    return nullptr;

  GLuint imageId =
      gl->CreateImageCHROMIUM(gpuMemoryBuffer->AsClientBuffer(), m_size.width(),
                              m_size.height(), GL_RGBA);
  if (!imageId)
    return nullptr;

  GLuint textureId;
  gl->GenTextures(1, &textureId);
  GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
  gl->BindTexture(target, textureId);
  gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, getGLFilter());
  gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, getGLFilter());
  gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  gl->BindTexImage2DCHROMIUM(target, imageId);

  return adoptRef(new Canvas2DLayerBridge::ImageInfo(std::move(gpuMemoryBuffer),
                                                     imageId, textureId));
}

void Canvas2DLayerBridge::deleteCHROMIUMImage(RefPtr<ImageInfo> info) {
  gpu::gles2::GLES2Interface* gl = contextGL();
  if (!gl)
    return;

  GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
  gl->BindTexture(target, info->m_textureId);
  gl->ReleaseTexImage2DCHROMIUM(target, info->m_imageId);
  gl->DestroyImageCHROMIUM(info->m_imageId);
  gl->DeleteTextures(1, &info->m_textureId);
  gl->BindTexture(target, 0);
  info->m_gpuMemoryBuffer.reset();

  resetSkiaTextureBinding();
}

void Canvas2DLayerBridge::clearCHROMIUMImageCache() {
  for (const auto& it : m_imageInfoCache) {
    deleteCHROMIUMImage(it);
  }
  m_imageInfoCache.clear();
}
#endif  // USE_IOSURFACE_FOR_2D_CANVAS

void Canvas2DLayerBridge::createMailboxInfo() {
  MailboxInfo tmp;
  tmp.m_parentLayerBridge = this;
  m_mailboxes.prepend(tmp);
}

bool Canvas2DLayerBridge::prepareMailboxFromImage(
    sk_sp<SkImage> image,
    cc::TextureMailbox* outMailbox) {
  createMailboxInfo();
  MailboxInfo& mailboxInfo = m_mailboxes.first();

  GrContext* grContext = m_contextProvider->grContext();
  if (!grContext) {
    mailboxInfo.m_image = std::move(image);
    // For testing, skip GL stuff when using a mock graphics context.
    return true;
  }

#if USE_IOSURFACE_FOR_2D_CANVAS
  if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) {
    if (prepareIOSurfaceMailboxFromImage(image.get(), outMailbox))
      return true;
    // Note: if IOSurface backed texture creation failed we fall back to the
    // non-IOSurface path.
  }
#endif  // USE_IOSURFACE_FOR_2D_CANVAS

  mailboxInfo.m_image = std::move(image);

  if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled())
    m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);

  // Need to flush skia's internal queue, because the texture is about to be
  // accessed directly.
  grContext->flush();

  // Because of texture sharing with the compositor, we must invalidate
  // the state cached in skia so that the deferred copy on write
  // in SkSurface_Gpu does not make any false assumptions.
  mailboxInfo.m_image->getTexture()->textureParamsModified();

  gpu::gles2::GLES2Interface* gl = contextGL();
  if (!gl)
    return false;

  GLuint textureID = skia::GrBackendObjectToGrGLTextureInfo(
                         mailboxInfo.m_image->getTextureHandle(true))
                         ->fID;
  gl->BindTexture(GL_TEXTURE_2D, textureID);
  gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter());
  gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter());
  gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  gpu::Mailbox mailbox;
  gl->GenMailboxCHROMIUM(mailbox.name);
  gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);

  gpu::SyncToken syncToken;
  if (isHidden()) {
    // With hidden canvases, we release the SkImage immediately because
    // there is no need for animations to be double buffered.
    mailboxInfo.m_image.reset();
  } else {
    // FIXME: We'd rather insert a syncpoint than perform a flush here,
    // but currently the canvas will flicker if we don't flush here.
    const GLuint64 fenceSync = gl->InsertFenceSyncCHROMIUM();
    gl->Flush();
    gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData());
  }
  mailboxInfo.m_mailbox = mailbox;
  *outMailbox = cc::TextureMailbox(mailbox, syncToken, GL_TEXTURE_2D);

  gl->BindTexture(GL_TEXTURE_2D, 0);
  // Because we are changing the texture binding without going through skia,
  // we must dirty the context.
  grContext->resetContext(kTextureBinding_GrGLBackendState);
  return true;
}

void Canvas2DLayerBridge::resetSkiaTextureBinding() {
  GrContext* grContext = m_contextProvider->grContext();
  if (grContext)
    grContext->resetContext(kTextureBinding_GrGLBackendState);
}

static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge,
                             double /*idleDeadline*/) {
  if (bridge) {
    bridge->hibernate();
  } else {
    Canvas2DLayerBridge::Logger localLogger;
    localLogger.reportHibernationEvent(
        Canvas2DLayerBridge::
            HibernationAbortedDueToDestructionWhileHibernatePending);
  }
}

static void hibernateWrapperForTesting(WeakPtr<Canvas2DLayerBridge> bridge) {
  hibernateWrapper(bridge, 0);
}

void Canvas2DLayerBridge::hibernate() {
  DCHECK(!isHibernating());
  DCHECK(m_hibernationScheduled);

  m_hibernationScheduled = false;

  if (m_destructionInProgress) {
    m_logger->reportHibernationEvent(HibernationAbortedDueToPendingDestruction);
    return;
  }

  if (!m_surface) {
    m_logger->reportHibernationEvent(HibernationAbortedBecauseNoSurface);
    return;
  }

  if (!isHidden()) {
    m_logger->reportHibernationEvent(HibernationAbortedDueToVisibilityChange);
    return;
  }

  if (!checkSurfaceValid()) {
    m_logger->reportHibernationEvent(HibernationAbortedDueGpuContextLoss);
    return;
  }

  if (!isAccelerated()) {
    m_logger->reportHibernationEvent(
        HibernationAbortedDueToSwitchToUnacceleratedRendering);
    return;
  }

  TRACE_EVENT0("blink", "Canvas2DLayerBridge::hibernate");
  sk_sp<PaintSurface> tempHibernationSurface =
      PaintSurface::MakeRasterN32Premul(m_size.width(), m_size.height());
  if (!tempHibernationSurface) {
    m_logger->reportHibernationEvent(HibernationAbortedDueToAllocationFailure);
    return;
  }
  // No HibernationEvent reported on success. This is on purppose to avoid
  // non-complementary stats. Each HibernationScheduled event is paired with
  // exactly one failure or exit event.
  flushRecordingOnly();
  // The following checks that the flush succeeded, which should always be the
  // case because flushRecordingOnly should only fail it it fails to allocate
  // a surface, and we have an early exit at the top of this function for when
  // 'this' does not already have a surface.
  DCHECK(!m_haveRecordedDrawCommands);
  PaintFlags copyPaint;
  copyPaint.setBlendMode(SkBlendMode::kSrc);
  m_surface->draw(tempHibernationSurface->getCanvas(), 0, 0,
                  &copyPaint);  // GPU readback
  m_hibernationImage = tempHibernationSurface->makeImageSnapshot();
  m_surface.reset();  // destroy the GPU-backed buffer
  m_layer->clearTexture();
#if USE_IOSURFACE_FOR_2D_CANVAS
  clearCHROMIUMImageCache();
#endif  // USE_IOSURFACE_FOR_2D_CANVAS
  m_logger->didStartHibernating();
}

sk_sp<SkColorSpace> Canvas2DLayerBridge::skSurfaceColorSpace() const {
  if (m_skSurfacesUseColorSpace)
    return m_colorSpace.ToSkColorSpace();
  return nullptr;
}

void Canvas2DLayerBridge::reportSurfaceCreationFailure() {
  if (!m_surfaceCreationFailedAtLeastOnce) {
    // Only count the failure once per instance so that the histogram may
    // reflect the proportion of Canvas2DLayerBridge instances with surface
    // allocation failures.
    CanvasMetrics::countCanvasContextUsage(
        CanvasMetrics::GPUAccelerated2DCanvasSurfaceCreationFailed);
    m_surfaceCreationFailedAtLeastOnce = true;
  }
}

PaintSurface* Canvas2DLayerBridge::getOrCreateSurface(AccelerationHint hint) {
  if (m_surface)
    return m_surface.get();

  if (m_layer && !isHibernating() && hint == PreferAcceleration &&
      m_accelerationMode != DisableAcceleration) {
    return nullptr;  // re-creation will happen through restore()
  }

  bool wantAcceleration = shouldAccelerate(hint);
  if (CANVAS2D_BACKGROUND_RENDER_SWITCH_TO_CPU && isHidden() &&
      wantAcceleration) {
    wantAcceleration = false;
    m_softwareRenderingWhileHidden = true;
  }

  bool surfaceIsAccelerated;
  m_surface = createSkSurface(
      wantAcceleration ? m_contextProvider->grContext() : nullptr, m_size,
      m_msaaSampleCount, m_opacityMode, skSurfaceColorSpace(), m_colorType,
      &surfaceIsAccelerated);

  if (m_surface) {
    // Always save an initial frame, to support resetting the top level matrix
    // and clip.
    m_surface->getCanvas()->save();
  } else {
    reportSurfaceCreationFailure();
  }

  if (m_surface && surfaceIsAccelerated && !m_layer) {
    m_layer =
        Platform::current()->compositorSupport()->createExternalTextureLayer(
            this);
    m_layer->setOpaque(m_opacityMode == Opaque);
    m_layer->setBlendBackgroundColor(m_opacityMode != Opaque);
    GraphicsLayer::registerContentsLayer(m_layer->layer());
    m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
  }

  if (m_surface && isHibernating()) {
    if (surfaceIsAccelerated) {
      m_logger->reportHibernationEvent(HibernationEndedNormally);
    } else {
      if (isHidden())
        m_logger->reportHibernationEvent(
            HibernationEndedWithSwitchToBackgroundRendering);
      else
        m_logger->reportHibernationEvent(HibernationEndedWithFallbackToSW);
    }

    PaintFlags copyPaint;
    copyPaint.setBlendMode(SkBlendMode::kSrc);
    m_surface->getCanvas()->drawImage(m_hibernationImage.get(), 0, 0,
                                      &copyPaint);
    m_hibernationImage.reset();

    if (m_imageBuffer)
      m_imageBuffer->updateGPUMemoryUsage();

    if (m_imageBuffer && !m_isDeferralEnabled)
      m_imageBuffer->resetCanvas(m_surface->getCanvas());
  }

  return m_surface.get();
}

PaintCanvas* Canvas2DLayerBridge::canvas() {
  if (!m_isDeferralEnabled) {
    PaintSurface* s = getOrCreateSurface();
    return s ? s->getCanvas() : nullptr;
  }
  return m_recorder->getRecordingCanvas();
}

void Canvas2DLayerBridge::disableDeferral(DisableDeferralReason reason) {
  // Disabling deferral is permanent: once triggered by disableDeferral()
  // we stay in immediate mode indefinitely. This is a performance heuristic
  // that significantly helps a number of use cases. The rationale is that if
  // immediate rendering was needed once, it is likely to be needed at least
  // once per frame, which eliminates the possibility for inter-frame
  // overdraw optimization. Furthermore, in cases where immediate mode is
  // required multiple times per frame, the repeated flushing of deferred
  // commands would cause significant overhead, so it is better to just stop
  // trying to defer altogether.
  if (!m_isDeferralEnabled)
    return;

  DEFINE_STATIC_LOCAL(EnumerationHistogram, gpuDisabledHistogram,
                      ("Canvas.GPUAccelerated2DCanvasDisableDeferralReason",
                       DisableDeferralReasonCount));
  gpuDisabledHistogram.count(reason);
  CanvasMetrics::countCanvasContextUsage(
      CanvasMetrics::GPUAccelerated2DCanvasDeferralDisabled);
  flushRecordingOnly();
  // Because we will be discarding the recorder, if the flush failed
  // content will be lost -> force m_haveRecordedDrawCommands to false
  m_haveRecordedDrawCommands = false;

  m_isDeferralEnabled = false;
  m_recorder.reset();
  // install the current matrix/clip stack onto the immediate canvas
  PaintSurface* surface = getOrCreateSurface();
  if (m_imageBuffer && surface)
    m_imageBuffer->resetCanvas(surface->getCanvas());
}

void Canvas2DLayerBridge::setImageBuffer(ImageBuffer* imageBuffer) {
  m_imageBuffer = imageBuffer;
  if (m_imageBuffer && m_isDeferralEnabled) {
    m_imageBuffer->resetCanvas(m_recorder->getRecordingCanvas());
  }
}

void Canvas2DLayerBridge::beginDestruction() {
  if (m_destructionInProgress)
    return;
  if (isHibernating())
    m_logger->reportHibernationEvent(HibernationEndedWithTeardown);
  m_hibernationImage.reset();
  m_recorder.reset();
  m_imageBuffer = nullptr;
  m_destructionInProgress = true;
  setIsHidden(true);
  m_surface.reset();

  if (m_layer && m_accelerationMode != DisableAcceleration) {
    GraphicsLayer::unregisterContentsLayer(m_layer->layer());
    m_layer->clearTexture();
    // Orphaning the layer is required to trigger the recration of a new layer
    // in the case where destruction is caused by a canvas resize. Test:
    // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
    m_layer->layer()->removeFromParent();
  }

  DCHECK(!m_bytesAllocated);
}

void Canvas2DLayerBridge::setFilterQuality(SkFilterQuality filterQuality) {
  DCHECK(!m_destructionInProgress);
  m_filterQuality = filterQuality;
  if (m_layer)
    m_layer->setNearestNeighbor(m_filterQuality == kNone_SkFilterQuality);
}

void Canvas2DLayerBridge::setIsHidden(bool hidden) {
  bool newHiddenValue = hidden || m_destructionInProgress;
  if (m_isHidden == newHiddenValue)
    return;

  m_isHidden = newHiddenValue;
  if (CANVAS2D_HIBERNATION_ENABLED && m_surface && isHidden() &&
      !m_destructionInProgress && !m_hibernationScheduled) {
    if (m_layer)
      m_layer->clearTexture();
    m_logger->reportHibernationEvent(HibernationScheduled);
    m_hibernationScheduled = true;
    if (m_dontUseIdleSchedulingForTesting) {
      Platform::current()->currentThread()->getWebTaskRunner()->postTask(
          BLINK_FROM_HERE, WTF::bind(&hibernateWrapperForTesting,
                                     m_weakPtrFactory.createWeakPtr()));
    } else {
      Platform::current()->currentThread()->scheduler()->postIdleTask(
          BLINK_FROM_HERE,
          WTF::bind(&hibernateWrapper, m_weakPtrFactory.createWeakPtr()));
    }
  }
  if (!isHidden() && m_softwareRenderingWhileHidden) {
    flushRecordingOnly();
    PaintFlags copyPaint;
    copyPaint.setBlendMode(SkBlendMode::kSrc);

    sk_sp<PaintSurface> oldSurface = std::move(m_surface);
    m_surface.reset();

    m_softwareRenderingWhileHidden = false;
    PaintSurface* newSurface =
        getOrCreateSurface(PreferAccelerationAfterVisibilityChange);
    if (newSurface) {
      if (oldSurface)
        oldSurface->draw(newSurface->getCanvas(), 0, 0, &copyPaint);
      if (m_imageBuffer && !m_isDeferralEnabled) {
        m_imageBuffer->resetCanvas(m_surface->getCanvas());
      }
    }
  }
  if (!isHidden() && isHibernating()) {
    getOrCreateSurface();  // Rude awakening
  }
}

bool Canvas2DLayerBridge::writePixels(const SkImageInfo& origInfo,
                                      const void* pixels,
                                      size_t rowBytes,
                                      int x,
                                      int y) {
  if (!getOrCreateSurface())
    return false;
  if (x <= 0 && y <= 0 && x + origInfo.width() >= m_size.width() &&
      y + origInfo.height() >= m_size.height()) {
    skipQueuedDrawCommands();
  } else {
    flush();
  }
  DCHECK(!m_haveRecordedDrawCommands);
  // call write pixels on the surface, not the recording canvas.
  // No need to call beginDirectSurfaceAccessModeIfNeeded() because writePixels
  // ignores the matrix and clip state.
  return getOrCreateSurface()->getCanvas()->writePixels(origInfo, pixels,
                                                        rowBytes, x, y);
}

void Canvas2DLayerBridge::skipQueuedDrawCommands() {
  if (m_haveRecordedDrawCommands) {
    m_recorder->finishRecordingAsPicture();
    startRecording();
    m_haveRecordedDrawCommands = false;
  }

  if (m_isDeferralEnabled) {
    if (m_rateLimiter)
      m_rateLimiter->reset();
  }
}

void Canvas2DLayerBridge::flushRecordingOnly() {
  DCHECK(!m_destructionInProgress);

  if (m_haveRecordedDrawCommands && getOrCreateSurface()) {
    TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecordingOnly");
    m_recorder->finishRecordingAsPicture()->playback(
        getOrCreateSurface()->getCanvas());
    if (m_isDeferralEnabled)
      startRecording();
    m_haveRecordedDrawCommands = false;
  }
}

void Canvas2DLayerBridge::flush() {
  if (!m_didDrawSinceLastFlush)
    return;
  TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
  if (!getOrCreateSurface())
    return;
  flushRecordingOnly();
  getOrCreateSurface()->getCanvas()->flush();
  m_didDrawSinceLastFlush = false;
}

void Canvas2DLayerBridge::flushGpu() {
  flush();
  gpu::gles2::GLES2Interface* gl = contextGL();
  if (isAccelerated() && gl && m_didDrawSinceLastGpuFlush) {
    TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushGpu");
    gl->Flush();
    m_didDrawSinceLastGpuFlush = false;
  }
}

gpu::gles2::GLES2Interface* Canvas2DLayerBridge::contextGL() {
  // Check on m_layer is necessary because contextGL() may be called during
  // the destruction of m_layer
  if (m_layer && m_accelerationMode != DisableAcceleration &&
      !m_destructionInProgress) {
    // Call checkSurfaceValid to ensure the rate limiter is disabled if the
    // context is lost.
    if (!checkSurfaceValid())
      return nullptr;
  }
  return m_contextProvider ? m_contextProvider->contextGL() : nullptr;
}

bool Canvas2DLayerBridge::checkSurfaceValid() {
  DCHECK(!m_destructionInProgress);
  if (m_destructionInProgress)
    return false;
  if (isHibernating())
    return true;
  if (!m_layer || m_accelerationMode == DisableAcceleration)
    return true;
  if (!m_surface)
    return false;
  if (m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() !=
      GL_NO_ERROR) {
    m_surface.reset();
    for (auto mailboxInfo = m_mailboxes.begin();
         mailboxInfo != m_mailboxes.end(); ++mailboxInfo) {
      if (mailboxInfo->m_image)
        mailboxInfo->m_image.reset();
    }
    if (m_imageBuffer)
      m_imageBuffer->notifySurfaceInvalid();
    CanvasMetrics::countCanvasContextUsage(
        CanvasMetrics::Accelerated2DCanvasGPUContextLost);
  }
  return m_surface.get();
}

bool Canvas2DLayerBridge::restoreSurface() {
  DCHECK(!m_destructionInProgress);
  if (m_destructionInProgress || !isAccelerated())
    return false;
  DCHECK(!m_surface);

  gpu::gles2::GLES2Interface* sharedGL = nullptr;
  m_layer->clearTexture();
  m_contextProvider = WTF::wrapUnique(
      Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
  if (m_contextProvider)
    sharedGL = m_contextProvider->contextGL();

  if (sharedGL && sharedGL->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
    GrContext* grCtx = m_contextProvider->grContext();
    bool surfaceIsAccelerated;
    sk_sp<PaintSurface> surface(createSkSurface(
        grCtx, m_size, m_msaaSampleCount, m_opacityMode, skSurfaceColorSpace(),
        m_colorType, &surfaceIsAccelerated));
    if (!m_surface)
      reportSurfaceCreationFailure();

    // The current paradigm does not support switching from accelerated to
    // non-accelerated, which would be tricky due to changes to the layer tree,
    // which can only happen at specific times during the document lifecycle.
    // Therefore, we can only accept the restored surface if it is accelerated.
    if (surface && surfaceIsAccelerated) {
      m_surface = std::move(surface);
      // FIXME: draw sad canvas picture into new buffer crbug.com/243842
    }
  }
  if (m_imageBuffer)
    m_imageBuffer->updateGPUMemoryUsage();

  return m_surface.get();
}

bool Canvas2DLayerBridge::PrepareTextureMailbox(
    cc::TextureMailbox* outMailbox,
    std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
  if (m_destructionInProgress) {
    // It can be hit in the following sequence.
    // 1. Canvas draws something.
    // 2. The compositor begins the frame.
    // 3. Javascript makes a context be lost.
    // 4. Here.
    return false;
  }

  m_framesSinceLastCommit = 0;
  if (m_rateLimiter) {
    m_rateLimiter->reset();
  }

  // If the context is lost, we don't know if we should be producing GPU or
  // software frames, until we get a new context, since the compositor will
  // be trying to get a new context and may change modes.
  if (!m_contextProvider ||
      m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() !=
          GL_NO_ERROR)
    return false;

  DCHECK(isAccelerated() || isHibernating() || m_softwareRenderingWhileHidden);

  // if hibernating but not hidden, we want to wake up from
  // hibernation
  if ((isHibernating() || m_softwareRenderingWhileHidden) && isHidden())
    return false;

  sk_sp<SkImage> image =
      newImageSnapshot(PreferAcceleration, SnapshotReasonUnknown);
  if (!image || !image->getTexture())
    return false;

  // Early exit if canvas was not drawn to since last prepareMailbox.
  GLenum filter = getGLFilter();
  if (image->uniqueID() == m_lastImageId && filter == m_lastFilter)
    return false;
  m_lastImageId = image->uniqueID();
  m_lastFilter = filter;

  if (!prepareMailboxFromImage(std::move(image), outMailbox))
    return false;
  outMailbox->set_nearest_neighbor(getGLFilter() == GL_NEAREST);
  outMailbox->set_color_space(m_colorSpace);

  auto func =
      WTF::bind(&Canvas2DLayerBridge::mailboxReleased,
                m_weakPtrFactory.createWeakPtr(), outMailbox->mailbox());
  *outReleaseCallback =
      cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func)));
  return true;
}

void Canvas2DLayerBridge::mailboxReleased(const gpu::Mailbox& mailbox,
                                          const gpu::SyncToken& syncToken,
                                          bool lostResource) {
  DCHECK(isAccelerated() || isHibernating());
  bool contextLost =
      !isHibernating() &&
      (!m_surface ||
       m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() !=
           GL_NO_ERROR);
  DCHECK(m_mailboxes.last().m_parentLayerBridge.get() == this);

  // Mailboxes are typically released in FIFO order, so we iterate
  // from the end of m_mailboxes.
  auto releasedMailboxInfo = m_mailboxes.end();
  auto firstMailbox = m_mailboxes.begin();

  while (true) {
    --releasedMailboxInfo;
    if (releasedMailboxInfo->m_mailbox == mailbox)
      break;
    DCHECK(releasedMailboxInfo != firstMailbox);
  }

#if USE_IOSURFACE_FOR_2D_CANVAS
  if (releasedMailboxInfo->m_imageInfo && !lostResource) {
    if (contextLost) {
      deleteCHROMIUMImage(releasedMailboxInfo->m_imageInfo);
    } else {
      m_imageInfoCache.push_back(releasedMailboxInfo->m_imageInfo);
    }
  }
#endif  // USE_IOSURFACE_FOR_2D_CANVAS

  if (!contextLost) {
    // Invalidate texture state in case the compositor altered it since the
    // copy-on-write.
    if (releasedMailboxInfo->m_image) {
#if USE_IOSURFACE_FOR_2D_CANVAS
      DCHECK(!releasedMailboxInfo->m_imageInfo);
#endif  // USE_IOSURFACE_FOR_2D_CANVAS
      if (syncToken.HasData()) {
        contextGL()->WaitSyncTokenCHROMIUM(syncToken.GetConstData());
      }
      GrTexture* texture = releasedMailboxInfo->m_image->getTexture();
      if (texture) {
        if (lostResource) {
          texture->abandon();
        } else {
          texture->textureParamsModified();
          // Break the mailbox association to avoid leaking mailboxes every time
          // skia recycles a texture.
          gpu::gles2::GLES2Interface* gl = contextGL();
          if (gl)
            gl->ProduceTextureDirectCHROMIUM(
                0, GL_TEXTURE_2D, releasedMailboxInfo->m_mailbox.name);
        }
      }
    }
  }

  RefPtr<Canvas2DLayerBridge> selfRef;
  if (m_destructionInProgress) {
    // To avoid memory use after free, take a scoped self-reference
    // to postpone destruction until the end of this function.
    selfRef = this;
  }

  // The destruction of 'releasedMailboxInfo' will:
  // 1) Release the self reference held by the mailboxInfo, which may trigger
  //    the self-destruction of this Canvas2DLayerBridge
  // 2) Release the SkImage, which will return the texture to skia's scratch
  //    texture pool.
  m_mailboxes.remove(releasedMailboxInfo);

  if (m_mailboxes.isEmpty() && m_accelerationMode == DisableAcceleration)
    m_layer.reset();
}

WebLayer* Canvas2DLayerBridge::layer() const {
  DCHECK(!m_destructionInProgress);
  DCHECK(m_layer);
  return m_layer->layer();
}

void Canvas2DLayerBridge::didDraw(const FloatRect& rect) {
  if (m_isDeferralEnabled) {
    m_haveRecordedDrawCommands = true;
    IntRect pixelBounds = enclosingIntRect(rect);
    m_recordingPixelCount += pixelBounds.width() * pixelBounds.height();
    if (m_recordingPixelCount >=
        (m_size.width() * m_size.height() *
         ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold)) {
      disableDeferral(DisableDeferralReasonExpensiveOverdrawHeuristic);
    }
  }
  m_didDrawSinceLastFlush = true;
  m_didDrawSinceLastGpuFlush = true;
}

void Canvas2DLayerBridge::finalizeFrame() {
  TRACE_EVENT0("blink", "Canvas2DLayerBridge::finalizeFrame");
  DCHECK(!m_destructionInProgress);

  // Make sure surface is ready for painting: fix the rendering mode now
  // because it will be too late during the paint invalidation phase.
  getOrCreateSurface(PreferAcceleration);

  ++m_framesSinceLastCommit;

  if (m_framesSinceLastCommit >= 2) {
    if (isAccelerated()) {
      flushGpu();
      if (!m_rateLimiter) {
        m_rateLimiter =
            SharedContextRateLimiter::create(MaxCanvasAnimationBacklog);
      }
    } else {
      flush();
    }
  }

  if (m_rateLimiter) {
    m_rateLimiter->tick();
  }
}

void Canvas2DLayerBridge::doPaintInvalidation(const FloatRect& dirtyRect) {
  DCHECK(!m_destructionInProgress);
  if (m_layer && m_accelerationMode != DisableAcceleration)
    m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect));
}

sk_sp<SkImage> Canvas2DLayerBridge::newImageSnapshot(AccelerationHint hint,
                                                     SnapshotReason) {
  if (isHibernating())
    return m_hibernationImage;
  if (!checkSurfaceValid())
    return nullptr;
  if (!getOrCreateSurface(hint))
    return nullptr;
  flush();
  // A readback operation may alter the texture parameters, which may affect
  // the compositor's behavior. Therefore, we must trigger copy-on-write
  // even though we are not technically writing to the texture, only to its
  // parameters.
  getOrCreateSurface()->notifyContentWillChange(
      SkSurface::kRetain_ContentChangeMode);
  return m_surface->makeImageSnapshot();
}

void Canvas2DLayerBridge::willOverwriteCanvas() {
  skipQueuedDrawCommands();
}

#if USE_IOSURFACE_FOR_2D_CANVAS
Canvas2DLayerBridge::ImageInfo::ImageInfo(
    std::unique_ptr<gfx::GpuMemoryBuffer> gpuMemoryBuffer,
    GLuint imageId,
    GLuint textureId)
    : m_gpuMemoryBuffer(std::move(gpuMemoryBuffer)),
      m_imageId(imageId),
      m_textureId(textureId) {
  DCHECK(m_gpuMemoryBuffer);
  DCHECK(m_imageId);
  DCHECK(m_textureId);
}

Canvas2DLayerBridge::ImageInfo::~ImageInfo() {}
#endif  // USE_IOSURFACE_FOR_2D_CANVAS

Canvas2DLayerBridge::MailboxInfo::MailboxInfo() = default;
Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) =
    default;

void Canvas2DLayerBridge::Logger::reportHibernationEvent(
    HibernationEvent event) {
  DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram,
                      ("Canvas.HibernationEvents", HibernationEventCount));
  hibernationHistogram.count(event);
}

}  // namespace blink
