// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/pepper/pepper_graphics_2d_host.h"

#include <stddef.h>
#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/numerics/checked_math.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/paint/paint_flags.h"
#include "cc/resources/cross_thread_shared_bitmap.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "components/viz/common/resources/shared_bitmap.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/pepper/gfx_conversion.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_instance_throttler_impl.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "ppapi/thunk/enter.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkSwizzle.h"
#include "ui/gfx/blit.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "ui/gfx/skia_util.h"

#if defined(OS_MACOSX)
#include "base/mac/scoped_cftyperef.h"
#endif

using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_ImageData_API;

namespace content {

namespace {

const int64_t kOffscreenCallbackDelayMs = 1000 / 30;  // 30 fps

// Converts a rect inside an image of the given dimensions. The rect may be
// NULL to indicate it should be the entire image. If the rect is outside of
// the image, this will do nothing and return false.
bool ValidateAndConvertRect(const PP_Rect* rect,
                            int image_width,
                            int image_height,
                            gfx::Rect* dest) {
  if (!rect) {
    // Use the entire image area.
    *dest = gfx::Rect(0, 0, image_width, image_height);
  } else {
    // Validate the passed-in area.
    if (rect->point.x < 0 || rect->point.y < 0 || rect->size.width <= 0 ||
        rect->size.height <= 0)
      return false;

    // Check the max bounds, being careful of overflow.
    if (static_cast<int64_t>(rect->point.x) +
            static_cast<int64_t>(rect->size.width) >
        static_cast<int64_t>(image_width))
      return false;
    if (static_cast<int64_t>(rect->point.y) +
            static_cast<int64_t>(rect->size.height) >
        static_cast<int64_t>(image_height))
      return false;

    *dest = gfx::Rect(
        rect->point.x, rect->point.y, rect->size.width, rect->size.height);
  }
  return true;
}

// Converts ImageData from PP_IMAGEDATAFORMAT_BGRA_PREMUL to
// PP_IMAGEDATAFORMAT_RGBA_PREMUL, or reverse. It's assumed that the
// destination image is always mapped (so will have non-NULL data).
void ConvertImageData(PPB_ImageData_Impl* src_image,
                      const SkIRect& src_rect,
                      PPB_ImageData_Impl* dest_image,
                      const SkRect& dest_rect) {
  ImageDataAutoMapper auto_mapper(src_image);

  DCHECK(src_image->format() != dest_image->format());
  DCHECK(PPB_ImageData_Impl::IsImageDataFormatSupported(src_image->format()));
  DCHECK(PPB_ImageData_Impl::IsImageDataFormatSupported(dest_image->format()));

  SkBitmap src_bitmap(src_image->GetMappedBitmap());
  SkBitmap dest_bitmap(dest_image->GetMappedBitmap());
  if (src_rect.width() == src_image->width() &&
      dest_rect.width() == dest_image->width()) {
    // Fast path if the full frame can be converted at once.
    SkSwapRB(
        dest_bitmap.getAddr32(static_cast<int>(dest_rect.fLeft),
                              static_cast<int>(dest_rect.fTop)),
        src_bitmap.getAddr32(static_cast<int>(src_rect.fLeft),
                             static_cast<int>(src_rect.fTop)),
        src_rect.width() * src_rect.height());
  } else {
    // Slow path where we convert line by line.
    for (int y = 0; y < src_rect.height(); y++) {
      SkSwapRB(
          dest_bitmap.getAddr32(static_cast<int>(dest_rect.fLeft),
                                static_cast<int>(dest_rect.fTop + y)),
          src_bitmap.getAddr32(static_cast<int>(src_rect.fLeft),
                               static_cast<int>(src_rect.fTop + y)),
          src_rect.width());
    }
  }
}

}  // namespace

struct PepperGraphics2DHost::QueuedOperation {
  enum Type { PAINT, SCROLL, REPLACE, TRANSFORM };

  QueuedOperation(Type t)
      : type(t), paint_x(0), paint_y(0), scroll_dx(0), scroll_dy(0) {}

  Type type;

  // Valid when type == PAINT.
  scoped_refptr<PPB_ImageData_Impl> paint_image;
  int paint_x, paint_y;
  gfx::Rect paint_src_rect;

  // Valid when type == SCROLL.
  gfx::Rect scroll_clip_rect;
  int scroll_dx, scroll_dy;

  // Valid when type == REPLACE.
  scoped_refptr<PPB_ImageData_Impl> replace_image;

  // Valid when type == TRANSFORM
  float scale;
  gfx::PointF translation;
};

// static
PepperGraphics2DHost* PepperGraphics2DHost::Create(
    RendererPpapiHost* host,
    PP_Instance instance,
    PP_Resource resource,
    const PP_Size& size,
    PP_Bool is_always_opaque,
    scoped_refptr<PPB_ImageData_Impl> backing_store) {
  PepperGraphics2DHost* resource_host =
      new PepperGraphics2DHost(host, instance, resource);
  if (!resource_host->Init(size.width,
                           size.height,
                           PP_ToBool(is_always_opaque),
                           backing_store)) {
    delete resource_host;
    return nullptr;
  }
  return resource_host;
}

PepperGraphics2DHost::PepperGraphics2DHost(RendererPpapiHost* host,
                                           PP_Instance instance,
                                           PP_Resource resource)
    : ResourceHost(host->GetPpapiHost(), instance, resource),
      renderer_ppapi_host_(host),
      bound_instance_(nullptr),
      need_flush_ack_(false),
      offscreen_flush_pending_(false),
      is_always_opaque_(false),
      scale_(1.0f),
      is_running_in_process_(host->IsRunningInProcess()) {}

PepperGraphics2DHost::~PepperGraphics2DHost() {
  // Delete textures owned by PepperGraphics2DHost, but not those sent to the
  // compositor, since those will be deleted by ReleaseTextureCallback() when it
  // runs.
  while (main_thread_context_ && !recycled_shared_images_.empty()) {
    const auto& shared_image_info = recycled_shared_images_.back();
    main_thread_context_->SharedImageInterface()->DestroySharedImage(
        shared_image_info.sync_token, shared_image_info.mailbox);
    recycled_shared_images_.pop_back();
  }

  // Unbind from the instance when destroyed if we're still bound.
  if (bound_instance_)
    bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0);
}

bool PepperGraphics2DHost::Init(
    int width,
    int height,
    bool is_always_opaque,
    scoped_refptr<PPB_ImageData_Impl> backing_store) {
  // The underlying PPB_ImageData_Impl will validate the dimensions.
  image_data_ = backing_store;
  if (!image_data_->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
                         width,
                         height,
                         true) ||
      !image_data_->Map()) {
    image_data_ = nullptr;
    return false;
  }
  is_always_opaque_ = is_always_opaque;
  scale_ = 1.0f;

  return true;
}

int32_t PepperGraphics2DHost::OnResourceMessageReceived(
    const IPC::Message& msg,
    ppapi::host::HostMessageContext* context) {
  PPAPI_BEGIN_MESSAGE_MAP(PepperGraphics2DHost, msg)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Graphics2D_PaintImageData,
                                      OnHostMsgPaintImageData)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Graphics2D_Scroll,
                                      OnHostMsgScroll)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Graphics2D_ReplaceContents,
                                      OnHostMsgReplaceContents)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Graphics2D_Flush,
                                        OnHostMsgFlush)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Graphics2D_SetScale,
                                      OnHostMsgSetScale)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Graphics2D_SetLayerTransform,
                                      OnHostMsgSetLayerTransform)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Graphics2D_ReadImageData,
                                      OnHostMsgReadImageData)
  PPAPI_END_MESSAGE_MAP()
  return PP_ERROR_FAILED;
}

bool PepperGraphics2DHost::IsGraphics2DHost() { return true; }

bool PepperGraphics2DHost::ReadImageData(PP_Resource image,
                                         const PP_Point* top_left) {
  // Get and validate the image object to paint into.
  EnterResourceNoLock<PPB_ImageData_API> enter(image, true);
  if (enter.failed())
    return false;
  PPB_ImageData_Impl* image_resource =
      static_cast<PPB_ImageData_Impl*>(enter.object());
  if (!PPB_ImageData_Impl::IsImageDataFormatSupported(image_resource->format()))
    return false;  // Must be in the right format.

  // Validate the bitmap position.
  int x = top_left->x;
  if (x < 0 ||
      static_cast<int64_t>(x) + static_cast<int64_t>(image_resource->width()) >
          image_data_->width())
    return false;
  int y = top_left->y;
  if (y < 0 ||
      static_cast<int64_t>(y) + static_cast<int64_t>(image_resource->height()) >
          image_data_->height())
    return false;

  ImageDataAutoMapper auto_mapper(image_resource);
  if (!auto_mapper.is_valid())
    return false;

  SkIRect src_irect = {x, y, x + image_resource->width(),
                       y + image_resource->height()};
  SkRect dest_rect = {SkIntToScalar(0), SkIntToScalar(0),
                      SkIntToScalar(image_resource->width()),
                      SkIntToScalar(image_resource->height())};

  if (image_resource->format() != image_data_->format()) {
    // Convert the image data if the format does not match.
    ConvertImageData(image_data_.get(), src_irect, image_resource, dest_rect);
  } else {
    SkCanvas* dest_canvas = image_resource->GetCanvas();

    // We want to replace the contents of the bitmap rather than blend.
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);
    dest_canvas->drawBitmapRect(
        image_data_->GetMappedBitmap(), src_irect, dest_rect, &paint);
  }
  return true;
}

bool PepperGraphics2DHost::BindToInstance(
    PepperPluginInstanceImpl* new_instance) {
  if (new_instance && new_instance->pp_instance() != pp_instance())
    return false;  // Can't bind other instance's contexts.
  if (bound_instance_ == new_instance)
    return true;  // Rebinding the same device, nothing to do.
  if (bound_instance_ && new_instance)
    return false;  // Can't change a bound device.

  if (!new_instance) {
    // When the device is detached, we'll not get any more paint callbacks so
    // we need to clear the list, but we still want to issue any pending
    // callbacks to the plugin.
    if (need_flush_ack_)
      ScheduleOffscreenFlushAck();
  } else {
    // Devices being replaced, redraw the plugin.
    new_instance->InvalidateRect(gfx::Rect());
  }

  cached_bitmap_ = nullptr;
  cached_bitmap_registration_ = cc::SharedBitmapIdRegistration();
  composited_output_modified_ = true;

  bound_instance_ = new_instance;
  return true;
}

// The |backing_bitmap| must be clipped to the |plugin_rect| to avoid painting
// outside the plugin area. This can happen if the plugin has been resized since
// PaintImageData verified the image is within the plugin size.
void PepperGraphics2DHost::Paint(cc::PaintCanvas* canvas,
                                 const gfx::Rect& plugin_rect,
                                 const gfx::Rect& paint_rect) {
  TRACE_EVENT0("pepper", "PepperGraphics2DHost::Paint");
  ImageDataAutoMapper auto_mapper(image_data_.get());
  SkBitmap backing_bitmap = image_data_->GetMappedBitmap();

  gfx::Rect invalidate_rect = plugin_rect;
  invalidate_rect.Intersect(paint_rect);
  SkRect sk_invalidate_rect = gfx::RectToSkRect(invalidate_rect);
  cc::PaintCanvasAutoRestore auto_restore(canvas, true);
  canvas->clipRect(sk_invalidate_rect);
  gfx::Size pixel_image_size(image_data_->width(), image_data_->height());
  gfx::Size image_size = gfx::ScaleToFlooredSize(pixel_image_size, scale_);

  PepperPluginInstance* plugin_instance =
      renderer_ppapi_host_->GetPluginInstance(pp_instance());
  if (!plugin_instance)
    return;
  if (plugin_instance->IsFullPagePlugin()) {
    // When we're resizing a window with a full-frame plugin, the plugin may
    // not yet have bound a new device, which will leave parts of the
    // background exposed if the window is getting larger. We want this to
    // show white (typically less jarring) rather than black or uninitialized.
    // We don't do this for non-full-frame plugins since we specifically want
    // the page background to show through.
    cc::PaintCanvasAutoRestore full_page_auto_restore(canvas, true);
    SkRect image_data_rect =
        gfx::RectToSkRect(gfx::Rect(plugin_rect.origin(), image_size));
    canvas->clipRect(image_data_rect, SkClipOp::kDifference);

    cc::PaintFlags flags;
    flags.setBlendMode(SkBlendMode::kSrc);
    flags.setColor(SK_ColorWHITE);
    canvas->drawRect(sk_invalidate_rect, flags);
  }

  cc::PaintFlags flags;
  if (is_always_opaque_) {
    // When we know the device is opaque, we can disable blending for slightly
    // more optimized painting.
    flags.setBlendMode(SkBlendMode::kSrc);
  }

  SkPoint pixel_origin(PointToSkPoint(plugin_rect.origin()));
  if (scale_ != 1.0f && scale_ > 0.0f) {
    canvas->scale(scale_, scale_);
    pixel_origin.scale(1.0f / scale_);
  }
  // TODO(khushalsagar): Can this be cached on image_data_, and invalidated when
  // the bitmap changes?
  canvas->drawImage(cc::PaintImage::CreateFromBitmap(std::move(backing_bitmap)),
                    pixel_origin.x(), pixel_origin.y(), &flags);
}

void PepperGraphics2DHost::ViewInitiatedPaint() {
  TRACE_EVENT0("pepper", "PepperGraphics2DHost::ViewInitiatedPaint");
  if (need_flush_ack_) {
    SendFlushAck();
    need_flush_ack_ = false;
  }
}

float PepperGraphics2DHost::GetScale() const { return scale_; }

bool PepperGraphics2DHost::IsAlwaysOpaque() const { return is_always_opaque_; }

gfx::Size PepperGraphics2DHost::Size() const {
  if (!image_data_.get())
    return gfx::Size();
  return gfx::Size(image_data_->width(), image_data_->height());
}

void PepperGraphics2DHost::ClearCache() {
  cached_bitmap_ = nullptr;
  cached_bitmap_registration_ = cc::SharedBitmapIdRegistration();
}

int32_t PepperGraphics2DHost::OnHostMsgPaintImageData(
    ppapi::host::HostMessageContext* context,
    const ppapi::HostResource& image_data,
    const PP_Point& top_left,
    bool src_rect_specified,
    const PP_Rect& src_rect) {
  EnterResourceNoLock<PPB_ImageData_API> enter(image_data.host_resource(),
                                               true);
  if (enter.failed())
    return PP_ERROR_BADRESOURCE;
  PPB_ImageData_Impl* image_resource =
      static_cast<PPB_ImageData_Impl*>(enter.object());

  QueuedOperation operation(QueuedOperation::PAINT);
  operation.paint_image = image_resource;
  if (!ValidateAndConvertRect(src_rect_specified ? &src_rect : nullptr,
                              image_resource->width(), image_resource->height(),
                              &operation.paint_src_rect))
    return PP_ERROR_BADARGUMENT;

  // Validate the bitmap position using the previously-validated rect, there
  // should be no painted area outside of the image.
  int64_t x64 = static_cast<int64_t>(top_left.x);
  int64_t y64 = static_cast<int64_t>(top_left.y);
  if (x64 + static_cast<int64_t>(operation.paint_src_rect.x()) < 0 ||
      x64 + static_cast<int64_t>(operation.paint_src_rect.right()) >
          image_data_->width())
    return PP_ERROR_BADARGUMENT;
  if (y64 + static_cast<int64_t>(operation.paint_src_rect.y()) < 0 ||
      y64 + static_cast<int64_t>(operation.paint_src_rect.bottom()) >
          image_data_->height())
    return PP_ERROR_BADARGUMENT;
  operation.paint_x = top_left.x;
  operation.paint_y = top_left.y;

  queued_operations_.push_back(operation);
  return PP_OK;
}

int32_t PepperGraphics2DHost::OnHostMsgScroll(
    ppapi::host::HostMessageContext* context,
    bool clip_specified,
    const PP_Rect& clip,
    const PP_Point& amount) {
  QueuedOperation operation(QueuedOperation::SCROLL);
  if (!ValidateAndConvertRect(clip_specified ? &clip : nullptr,
                              image_data_->width(), image_data_->height(),
                              &operation.scroll_clip_rect))
    return PP_ERROR_BADARGUMENT;

  // If we're being asked to scroll by more than the clip rect size, just
  // ignore this scroll command and say it worked.
  int32_t dx = amount.x;
  int32_t dy = amount.y;
  if (dx <= -image_data_->width() || dx >= image_data_->width() ||
      dy <= -image_data_->height() || dy >= image_data_->height())
    return PP_ERROR_BADARGUMENT;

  operation.scroll_dx = dx;
  operation.scroll_dy = dy;

  queued_operations_.push_back(operation);
  return PP_OK;
}

int32_t PepperGraphics2DHost::OnHostMsgReplaceContents(
    ppapi::host::HostMessageContext* context,
    const ppapi::HostResource& image_data) {
  EnterResourceNoLock<PPB_ImageData_API> enter(image_data.host_resource(),
                                               true);
  if (enter.failed())
    return PP_ERROR_BADRESOURCE;
  PPB_ImageData_Impl* image_resource =
      static_cast<PPB_ImageData_Impl*>(enter.object());

  if (!PPB_ImageData_Impl::IsImageDataFormatSupported(image_resource->format()))
    return PP_ERROR_BADARGUMENT;

  if (image_resource->width() != image_data_->width() ||
      image_resource->height() != image_data_->height())
    return PP_ERROR_BADARGUMENT;

  QueuedOperation operation(QueuedOperation::REPLACE);
  operation.replace_image = image_resource;
  queued_operations_.push_back(operation);
  return PP_OK;
}

int32_t PepperGraphics2DHost::OnHostMsgFlush(
    ppapi::host::HostMessageContext* context) {
  // Don't allow more than one pending flush at a time.
  if (HasPendingFlush())
    return PP_ERROR_INPROGRESS;

  PP_Resource old_image_data = 0;
  flush_reply_context_ = context->MakeReplyMessageContext();
  if (is_running_in_process_)
    return Flush(nullptr);

  // Reuse image data when running out of process.
  int32_t result = Flush(&old_image_data);

  if (old_image_data) {
    // If the Graphics2D has an old image data it's not using any more, send
    // it back to the plugin for possible re-use. See ppb_image_data_proxy.cc
    // for a description how this process works.
    ppapi::HostResource old_image_data_host_resource;
    old_image_data_host_resource.SetHostResource(pp_instance(), old_image_data);
    host()->Send(new PpapiMsg_PPBImageData_NotifyUnusedImageData(
        ppapi::API_ID_PPB_IMAGE_DATA, old_image_data_host_resource));
  }

  return result;
}

int32_t PepperGraphics2DHost::OnHostMsgSetScale(
    ppapi::host::HostMessageContext* context,
    float scale) {
  if (scale > 0.0f) {
    scale_ = scale;
    return PP_OK;
  }
  return PP_ERROR_BADARGUMENT;
}

int32_t PepperGraphics2DHost::OnHostMsgSetLayerTransform(
            ppapi::host::HostMessageContext* context,
            float scale,
            const PP_FloatPoint& translation) {
  if (scale < 0.0f)
    return PP_ERROR_BADARGUMENT;

  QueuedOperation operation(QueuedOperation::TRANSFORM);
  operation.scale = scale;
  operation.translation = gfx::PointF(translation.x, translation.y);
  queued_operations_.push_back(operation);
  return PP_OK;
}


int32_t PepperGraphics2DHost::OnHostMsgReadImageData(
    ppapi::host::HostMessageContext* context,
    PP_Resource image,
    const PP_Point& top_left) {
  context->reply_msg = PpapiPluginMsg_Graphics2D_ReadImageDataAck();
  return ReadImageData(image, &top_left) ? PP_OK : PP_ERROR_FAILED;
}

void PepperGraphics2DHost::ReleaseSoftwareCallback(
    scoped_refptr<cc::CrossThreadSharedBitmap> bitmap,
    cc::SharedBitmapIdRegistration registration,
    const gpu::SyncToken& sync_token,
    bool lost_resource) {
  cached_bitmap_ = nullptr;
  cached_bitmap_registration_ = cc::SharedBitmapIdRegistration();
  // Only keep around a cached bitmap if the plugin is currently drawing (has
  // need_flush_ack_ set).
  if (need_flush_ack_ && bound_instance_) {
    cached_bitmap_ = std::move(bitmap);
    cached_bitmap_registration_ = std::move(registration);
  }
}

// static
void PepperGraphics2DHost::ReleaseTextureCallback(
    base::WeakPtr<PepperGraphics2DHost> host,
    scoped_refptr<viz::ContextProvider> context,
    const gfx::Size& size,
    const gpu::Mailbox& mailbox,
    const gpu::SyncToken& sync_token,
    bool lost) {
  // Only recycle shared images from the same context, otherwise they may be
  // lost.
  if (host && !lost && context == host->main_thread_context_) {
    host->recycled_shared_images_.emplace_back(sync_token, mailbox, size);
    return;
  }

  context->SharedImageInterface()->DestroySharedImage(sync_token, mailbox);
}

bool PepperGraphics2DHost::PrepareTransferableResource(
    cc::SharedBitmapIdRegistrar* bitmap_registrar,
    viz::TransferableResource* transferable_resource,
    std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
  // Reuse the |main_thread_context_| if it is not lost. If it is lost, we can't
  // reuse the shared images, they are invalid. If the compositing mode changed,
  // the context will be lost also, so we get both together.
  if (!main_thread_context_ ||
      main_thread_context_->ContextGL()->GetGraphicsResetStatusKHR() !=
          GL_NO_ERROR) {
    recycled_shared_images_.clear();
    main_thread_context_ = nullptr;

    if (!is_gpu_compositing_disabled_) {
      RenderThreadImpl* rti = RenderThreadImpl::current();
      is_gpu_compositing_disabled_ = rti->IsGpuCompositingDisabled();
      if (!is_gpu_compositing_disabled_) {
        // Using gpu compositing.
        main_thread_context_ = rti->SharedMainThreadContextProvider();
      }

      // The last transferable resource is invalid, either coming from a lost
      // context or because we switched to software compositing. Force us to
      // send the frame to the compositor again even if not changed.
      composited_output_modified_ = true;
    }
  }

  if (!composited_output_modified_)
    return false;

  // Context creation failed, so we're unable to give this frame to the
  // compositor. Try again next time.
  if (!is_gpu_compositing_disabled_ && !main_thread_context_)
    return false;

  // When gpu compositing, the compositor expects gpu resources, so we copy the
  // |image_data_| into a texture.
  if (main_thread_context_) {
    auto* gl = main_thread_context_->ContextGL();
    auto* sii = main_thread_context_->SharedImageInterface();

    // The bitmap in |image_data_| uses the skia N32 byte order.
    constexpr bool bitmap_is_bgra = kN32_SkColorType == kBGRA_8888_SkColorType;
    const bool texture_can_be_bgra =
        main_thread_context_->ContextCapabilities().texture_format_bgra8888;
    const bool upload_bgra = bitmap_is_bgra && texture_can_be_bgra;
    const viz::ResourceFormat format =
        upload_bgra ? viz::BGRA_8888 : viz::RGBA_8888;

    RenderThreadImpl* rti = RenderThreadImpl::current();
    bool overlays_supported =
        rti->IsGpuMemoryBufferCompositorResourcesEnabled() &&
        main_thread_context_->ContextCapabilities().texture_storage_image;
    uint32_t texture_target = GL_TEXTURE_2D;
    if (overlays_supported) {
      texture_target = gpu::GetBufferTextureTarget(
          gfx::BufferUsage::SCANOUT, viz::BufferFormat(format),
          main_thread_context_->ContextCapabilities());
    }

    const gfx::Size size(image_data_->width(), image_data_->height());

    gpu::Mailbox gpu_mailbox;
    gpu::SyncToken in_sync_token;
    while (!recycled_shared_images_.empty()) {
      const auto& shared_image_info = recycled_shared_images_.back();
      if (shared_image_info.size == size) {
        in_sync_token = shared_image_info.sync_token;
        gpu_mailbox = shared_image_info.mailbox;
        recycled_shared_images_.pop_back();
        break;
      }
      sii->DestroySharedImage(shared_image_info.sync_token,
                              shared_image_info.mailbox);
      recycled_shared_images_.pop_back();
    }
    if (gpu_mailbox.IsZero()) {
      uint32_t usage =
          gpu::SHARED_IMAGE_USAGE_GLES2 | gpu::SHARED_IMAGE_USAGE_DISPLAY;
      if (overlays_supported)
        usage |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
      gpu_mailbox =
          sii->CreateSharedImage(format, size, gfx::ColorSpace(), usage);
      in_sync_token = sii->GenUnverifiedSyncToken();
    }

    void* src = image_data_->Map();

    // Convert to RGBA if we can't upload BGRA. This is slow sad times.
    std::unique_ptr<uint32_t[]> swizzled;
    if (bitmap_is_bgra != upload_bgra) {
      size_t num_pixels = (base::CheckedNumeric<size_t>(image_data_->width()) *
                           image_data_->height())
                              .ValueOrDie();
      swizzled = std::make_unique<uint32_t[]>(num_pixels);
      SkSwapRB(swizzled.get(), static_cast<uint32_t*>(src), num_pixels);
      src = swizzled.get();
    }

    gl->WaitSyncTokenCHROMIUM(in_sync_token.GetConstData());
    GLuint texture_id =
        gl->CreateAndTexStorage2DSharedImageCHROMIUM(gpu_mailbox.name);
    gl->BeginSharedImageAccessDirectCHROMIUM(
        texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
    gl->BindTexture(texture_target, texture_id);
    gl->TexSubImage2D(texture_target, 0, 0, 0, size.width(), size.height(),
                      viz::GLDataFormat(format), viz::GLDataType(format), src);
    gl->BindTexture(texture_target, 0);
    gl->EndSharedImageAccessDirectCHROMIUM(texture_id);
    gl->DeleteTextures(1, &texture_id);
    gpu::SyncToken out_sync_token;
    gl->GenUnverifiedSyncTokenCHROMIUM(out_sync_token.GetData());

    image_data_->Unmap();
    swizzled.reset();

    *release_callback = viz::SingleReleaseCallback::Create(
        base::BindOnce(&ReleaseTextureCallback, this->AsWeakPtr(),
                       main_thread_context_, size, gpu_mailbox));
    *transferable_resource = viz::TransferableResource::MakeGL(
        std::move(gpu_mailbox), GL_LINEAR, texture_target,
        std::move(out_sync_token), size, overlays_supported);
    transferable_resource->format = format;
    composited_output_modified_ = false;
    return true;
  }

  gfx::Size pixel_image_size(image_data_->width(), image_data_->height());
  scoped_refptr<cc::CrossThreadSharedBitmap> shared_bitmap;
  cc::SharedBitmapIdRegistration registration;
  if (cached_bitmap_) {
    if (cached_bitmap_->size() == pixel_image_size) {
      shared_bitmap = std::move(cached_bitmap_);
      registration = std::move(cached_bitmap_registration_);
    } else {
      cached_bitmap_ = nullptr;
      cached_bitmap_registration_ = cc::SharedBitmapIdRegistration();
    }
  }
  if (!shared_bitmap) {
    viz::SharedBitmapId id = viz::SharedBitmap::GenerateId();
    base::MappedReadOnlyRegion shm =
        viz::bitmap_allocation::AllocateSharedBitmap(pixel_image_size,
                                                     viz::RGBA_8888);
    shared_bitmap = base::MakeRefCounted<cc::CrossThreadSharedBitmap>(
        id, std::move(shm), pixel_image_size, viz::RGBA_8888);
    registration = bitmap_registrar->RegisterSharedBitmapId(id, shared_bitmap);
  }
  void* src = image_data_->Map();
  memcpy(shared_bitmap->memory(), src,
         viz::ResourceSizes::CheckedSizeInBytes<size_t>(pixel_image_size,
                                                        viz::RGBA_8888));
  image_data_->Unmap();

  *transferable_resource = viz::TransferableResource::MakeSoftware(
      shared_bitmap->id(), pixel_image_size, viz::RGBA_8888);
  *release_callback = viz::SingleReleaseCallback::Create(base::BindOnce(
      &PepperGraphics2DHost::ReleaseSoftwareCallback, this->AsWeakPtr(),
      std::move(shared_bitmap), std::move(registration)));
  composited_output_modified_ = false;
  return true;
}

void PepperGraphics2DHost::AttachedToNewLayer() {
  composited_output_modified_ = true;
}

int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) {
  bool done_replace_contents = false;
  bool no_update_visible = true;
  bool is_plugin_visible = true;

  for (size_t i = 0; i < queued_operations_.size(); i++) {
    QueuedOperation& operation = queued_operations_[i];
    gfx::Rect op_rect;
    switch (operation.type) {
      case QueuedOperation::TRANSFORM:
        ExecuteTransform(operation.scale, operation.translation, &op_rect);
        break;
      case QueuedOperation::PAINT:
        ExecutePaintImageData(operation.paint_image.get(),
                              operation.paint_x,
                              operation.paint_y,
                              operation.paint_src_rect,
                              &op_rect);
        break;
      case QueuedOperation::SCROLL:
        ExecuteScroll(operation.scroll_clip_rect,
                      operation.scroll_dx,
                      operation.scroll_dy,
                      &op_rect);
        break;
      case QueuedOperation::REPLACE:
        // Since the out parameter |old_image_data| takes ownership of the
        // reference, if there are more than one ReplaceContents calls queued
        // the first |old_image_data| will get overwritten and leaked. So we
        // only supply this for the first call.
        ExecuteReplaceContents(
            operation.replace_image.get(), &op_rect,
            done_replace_contents ? nullptr : old_image_data);
        done_replace_contents = true;
        break;
    }

    // For correctness with accelerated compositing, we must issue an invalidate
    // on the full op_rect even if it is partially or completely off-screen.
    // However, if we issue an invalidate for a clipped-out region, WebKit will
    // do nothing and we won't get any ViewFlushedPaint calls, leaving our
    // callback stranded. So we still need to check whether the repainted area
    // is visible to determine how to deal with the callback.
    if (bound_instance_ && !op_rect.IsEmpty()) {
      gfx::Point scroll_delta(operation.scroll_dx, operation.scroll_dy);
      // In use-zoom-for-dsf mode, the viewport (thus cc) uses native
      // pixels, so the damage and rects have to be scaled.
      gfx::Rect op_rect_in_viewport = op_rect;
      ConvertToLogicalPixels(scale_, &op_rect, nullptr);
      if (!ConvertToLogicalPixels(scale_ / viewport_to_dip_scale_,
                                  &op_rect_in_viewport,
                                  operation.type == QueuedOperation::SCROLL
                                      ? &scroll_delta
                                      : nullptr)) {
        // Conversion requires falling back to InvalidateRect.
        operation.type = QueuedOperation::PAINT;
      }

      gfx::Rect clip = PP_ToGfxRect(bound_instance_->view_data().clip_rect);
      is_plugin_visible = !clip.IsEmpty();

      // Set |no_update_visible| to false if the change overlaps the visible
      // area.
      if (!gfx::IntersectRects(clip, op_rect).IsEmpty()) {
        no_update_visible = false;
      }

      if (!op_rect_in_viewport.IsEmpty())
        bound_instance_->InvalidateRect(op_rect_in_viewport);
      composited_output_modified_ = true;
    }
  }
  queued_operations_.clear();

  if (!bound_instance_) {
    // As promised in the API, we always schedule callback when unbound.
    ScheduleOffscreenFlushAck();
  } else if (no_update_visible && is_plugin_visible &&
             bound_instance_->view_data().is_page_visible) {
    // There's nothing visible to invalidate so just schedule the callback to
    // execute in the next round of the message loop.
    ScheduleOffscreenFlushAck();
  } else {
    need_flush_ack_ = true;
  }

  if (bound_instance_ && bound_instance_->throttler() &&
      bound_instance_->throttler()->needs_representative_keyframe()) {
    bound_instance_->throttler()->OnImageFlush(image_data_->GetMappedBitmap());
  }

  return PP_OK_COMPLETIONPENDING;
}

void PepperGraphics2DHost::ExecuteTransform(const float& scale,
                                            const gfx::PointF& translate,
                                            gfx::Rect* invalidated_rect) {
  if (bound_instance_) {
    bound_instance_->SetGraphics2DTransform(scale, translate);
    *invalidated_rect =
        gfx::Rect(0, 0, image_data_->width(), image_data_->height());
  }
}

void PepperGraphics2DHost::ExecutePaintImageData(PPB_ImageData_Impl* image,
                                                 int x,
                                                 int y,
                                                 const gfx::Rect& src_rect,
                                                 gfx::Rect* invalidated_rect) {
  // Ensure the source image is mapped to read from it.
  ImageDataAutoMapper auto_mapper(image);
  if (!auto_mapper.is_valid())
    return;

  // Portion within the source image to cut out.
  SkIRect src_irect = {src_rect.x(), src_rect.y(), src_rect.right(),
                       src_rect.bottom()};

  // Location within the backing store to copy to.
  *invalidated_rect = src_rect;
  invalidated_rect->Offset(x, y);
  SkRect dest_rect = {SkIntToScalar(invalidated_rect->x()),
                      SkIntToScalar(invalidated_rect->y()),
                      SkIntToScalar(invalidated_rect->right()),
                      SkIntToScalar(invalidated_rect->bottom())};

  if (image->format() != image_data_->format()) {
    // Convert the image data if the format does not match.
    ConvertImageData(image, src_irect, image_data_.get(), dest_rect);
  } else {
    // We're guaranteed to have a mapped canvas since we mapped it in Init().
    SkCanvas* backing_canvas = image_data_->GetCanvas();

    // We want to replace the contents of the bitmap rather than blend.
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);
    backing_canvas->drawBitmapRect(
        image->GetMappedBitmap(), src_irect, dest_rect, &paint);
  }
}

void PepperGraphics2DHost::ExecuteScroll(const gfx::Rect& clip,
                                         int dx,
                                         int dy,
                                         gfx::Rect* invalidated_rect) {
  gfx::ScrollCanvas(image_data_->GetCanvas(), clip, gfx::Vector2d(dx, dy));
  *invalidated_rect = clip;
}

void PepperGraphics2DHost::ExecuteReplaceContents(PPB_ImageData_Impl* image,
                                                  gfx::Rect* invalidated_rect,
                                                  PP_Resource* old_image_data) {
  if (image->format() != image_data_->format()) {
    DCHECK(image->width() == image_data_->width() &&
           image->height() == image_data_->height());
    // Convert the image data if the format does not match.
    SkIRect src_irect = {0, 0, image->width(), image->height()};
    SkRect dest_rect = {SkIntToScalar(0), SkIntToScalar(0),
                        SkIntToScalar(image_data_->width()),
                        SkIntToScalar(image_data_->height())};
    ConvertImageData(image, src_irect, image_data_.get(), dest_rect);
  } else {
    // The passed-in image may not be mapped in our process, and we need to
    // guarantee that the current backing store is always mapped.
    if (!image->Map())
      return;

    if (old_image_data)
      *old_image_data = image_data_->GetReference();
    image_data_ = image;
  }
  *invalidated_rect =
      gfx::Rect(0, 0, image_data_->width(), image_data_->height());
}

void PepperGraphics2DHost::SendFlushAck() {
  host()->SendReply(flush_reply_context_, PpapiPluginMsg_Graphics2D_FlushAck());
}

void PepperGraphics2DHost::SendOffscreenFlushAck() {
  DCHECK(offscreen_flush_pending_);

  // We must clear this flag before issuing the callback. It will be
  // common for the plugin to issue another invalidate in response to a flush
  // callback, and we don't want to think that a callback is already pending.
  offscreen_flush_pending_ = false;
  SendFlushAck();
}

void PepperGraphics2DHost::ScheduleOffscreenFlushAck() {
  offscreen_flush_pending_ = true;
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&PepperGraphics2DHost::SendOffscreenFlushAck, AsWeakPtr()),
      base::TimeDelta::FromMilliseconds(kOffscreenCallbackDelayMs));
}

bool PepperGraphics2DHost::HasPendingFlush() const {
  return need_flush_ack_ || offscreen_flush_pending_;
}

// static
bool PepperGraphics2DHost::ConvertToLogicalPixels(float scale,
                                                  gfx::Rect* op_rect,
                                                  gfx::Point* delta) {
  if (scale == 1.0f || scale <= 0.0f)
    return true;

  gfx::Rect original_rect = *op_rect;
  // Take the enclosing rectangle after scaling so a rectangle scaled down then
  // scaled back up by the inverse scale would fully contain the entire area
  // affected by the original rectangle.
  *op_rect = gfx::ScaleToEnclosingRect(*op_rect, scale);
  if (delta) {
    gfx::Point original_delta = *delta;
    float inverse_scale = 1.0f / scale;
    *delta = gfx::ScaleToFlooredPoint(*delta, scale);

    gfx::Rect inverse_scaled_rect =
        gfx::ScaleToEnclosingRect(*op_rect, inverse_scale);
    if (original_rect != inverse_scaled_rect)
      return false;
    gfx::Point inverse_scaled_point =
        gfx::ScaleToFlooredPoint(*delta, inverse_scale);
    if (original_delta != inverse_scaled_point)
      return false;
  }

  return true;
}

}  // namespace content
