// 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.

#import <Cocoa/Cocoa.h>

#include "content/browser/renderer_host/backing_store_mac.h"

#include <cmath>

#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/render_widget_host_view.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/scoped_cg_context_save_gstate_mac.h"
#include "ui/surface/transport_dib.h"

namespace content {

// Mac Backing Stores:
//
// Since backing stores are only ever written to or drawn into windows, we keep
// our backing store in a CGLayer that can get cached in GPU memory.  This
// allows acclerated drawing into the layer and lets scrolling and such happen
// all or mostly on the GPU, which is good for performance.

BackingStoreMac::BackingStoreMac(RenderWidgetHost* widget,
                                 const gfx::Size& size,
                                 float device_scale_factor)
    : BackingStore(widget, size), device_scale_factor_(device_scale_factor) {
  cg_layer_.reset(CreateCGLayer());
  if (!cg_layer_) {
    // The view isn't in a window yet.  Use a CGBitmapContext for now.
    cg_bitmap_.reset(CreateCGBitmapContext());
    CGContextScaleCTM(cg_bitmap_, device_scale_factor_, device_scale_factor_);
  }
}

BackingStoreMac::~BackingStoreMac() {
}

void BackingStoreMac::ScaleFactorChanged(float device_scale_factor) {
  if (device_scale_factor == device_scale_factor_)
    return;

  device_scale_factor_ = device_scale_factor;

  base::ScopedCFTypeRef<CGLayerRef> new_layer(CreateCGLayer());
  // If we have a layer, copy the old contents. A pixelated flash is better
  // than a white flash.
  if (new_layer && cg_layer_) {
    CGContextRef layer = CGLayerGetContext(new_layer);
    CGContextDrawLayerAtPoint(layer, CGPointMake(0, 0), cg_layer_);
  }

  cg_layer_.swap(new_layer);
  if (!cg_layer_) {
    // The view isn't in a window yet.  Use a CGBitmapContext for now.
    cg_bitmap_.reset(CreateCGBitmapContext());
    CGContextScaleCTM(cg_bitmap_, device_scale_factor_, device_scale_factor_);
  }
}

size_t BackingStoreMac::MemorySize() {
  return gfx::ToFlooredSize(
      gfx::ScaleSize(size(), device_scale_factor_)).GetArea() * 4;
}

void BackingStoreMac::PaintToBackingStore(
    RenderProcessHost* process,
    TransportDIB::Id bitmap,
    const gfx::Rect& bitmap_rect,
    const std::vector<gfx::Rect>& copy_rects,
    float scale_factor,
    const base::Closure& completion_callback,
    bool* scheduled_completion_callback) {
  *scheduled_completion_callback = false;
  DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));

  TransportDIB* dib = process->GetTransportDIB(bitmap);
  if (!dib)
    return;

  gfx::Size pixel_size = gfx::ToFlooredSize(
      gfx::ScaleSize(size(), device_scale_factor_));
  gfx::Rect pixel_bitmap_rect = ToFlooredRectDeprecated(
      gfx::ScaleRect(bitmap_rect, scale_factor));

  size_t bitmap_byte_count =
      pixel_bitmap_rect.width() * pixel_bitmap_rect.height() * 4;
  DCHECK_GE(dib->size(), bitmap_byte_count);

  base::ScopedCFTypeRef<CGDataProviderRef> data_provider(
      CGDataProviderCreateWithData(
          NULL, dib->memory(), bitmap_byte_count, NULL));

  base::ScopedCFTypeRef<CGImageRef> bitmap_image(
      CGImageCreate(pixel_bitmap_rect.width(),
                    pixel_bitmap_rect.height(),
                    8,
                    32,
                    4 * pixel_bitmap_rect.width(),
                    base::mac::GetSystemColorSpace(),
                    kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
                    data_provider,
                    NULL,
                    false,
                    kCGRenderingIntentDefault));

  for (size_t i = 0; i < copy_rects.size(); i++) {
    const gfx::Rect& copy_rect = copy_rects[i];
    gfx::Rect pixel_copy_rect = ToFlooredRectDeprecated(
        gfx::ScaleRect(copy_rect, scale_factor));

    // Only the subpixels given by copy_rect have pixels to copy.
    base::ScopedCFTypeRef<CGImageRef> image(CGImageCreateWithImageInRect(
        bitmap_image,
        CGRectMake(pixel_copy_rect.x() - pixel_bitmap_rect.x(),
                   pixel_copy_rect.y() - pixel_bitmap_rect.y(),
                   pixel_copy_rect.width(),
                   pixel_copy_rect.height())));

    if (!cg_layer()) {
      // The view may have moved to a window.  Try to get a CGLayer.
      cg_layer_.reset(CreateCGLayer());
      if (cg_layer()) {
        // Now that we have a layer, copy the cached image into it.
        base::ScopedCFTypeRef<CGImageRef> bitmap_image(
            CGBitmapContextCreateImage(cg_bitmap_));
        CGContextDrawImage(CGLayerGetContext(cg_layer()),
                           CGRectMake(0, 0, size().width(), size().height()),
                           bitmap_image);
        // Discard the cache bitmap, since we no longer need it.
        cg_bitmap_.reset(NULL);
      }
    }

    DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));

    if (cg_layer()) {
      // The CGLayer's origin is in the lower left, but flipping the CTM would
      // cause the image to get drawn upside down.  So we move the rectangle
      // to the right position before drawing the image.
      CGContextRef layer = CGLayerGetContext(cg_layer());
      gfx::Rect paint_rect = copy_rect;
      paint_rect.set_y(size().height() - copy_rect.bottom());
      CGContextDrawImage(layer, paint_rect.ToCGRect(), image);
    } else {
      // The layer hasn't been created yet, so draw into the cache bitmap.
      gfx::Rect paint_rect = copy_rect;
      paint_rect.set_y(size().height() - copy_rect.bottom());
      CGContextDrawImage(cg_bitmap_, paint_rect.ToCGRect(), image);
    }
  }
}

bool BackingStoreMac::CopyFromBackingStore(const gfx::Rect& rect,
                                           skia::PlatformBitmap* output) {
  // TODO(thakis): Make sure this works with HiDPI backing stores.
  if (!output->Allocate(rect.width(), rect.height(), true))
    return false;

  CGContextRef temp_context = output->GetSurface();
  gfx::ScopedCGContextSaveGState save_gstate(temp_context);
  CGContextTranslateCTM(temp_context, 0.0, size().height());
  CGContextScaleCTM(temp_context, 1.0, -1.0);
  if (cg_layer()) {
    CGContextDrawLayerAtPoint(temp_context, CGPointMake(-rect.x(), -rect.y()),
                              cg_layer());
  } else {
    base::ScopedCFTypeRef<CGImageRef> bitmap_image(
        CGBitmapContextCreateImage(cg_bitmap_));
    CGContextDrawImage(
        temp_context,
        CGRectMake(-rect.x(), -rect.y(), rect.width(), rect.height()),
        bitmap_image);
  }

  return true;
}

// Scroll the contents of our CGLayer
void BackingStoreMac::ScrollBackingStore(const gfx::Vector2d& delta,
                                         const gfx::Rect& clip_rect,
                                         const gfx::Size& view_size) {
  DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));

  // "Scroll" the contents of the layer by creating a new CGLayer,
  // copying the contents of the old one into the new one offset by the scroll
  // amount, swapping in the new CGLayer, and then painting in the new data.
  //
  // The Windows code always sets the whole backing store as the source of the
  // scroll. Thus, we only have to worry about pixels which will end up inside
  // the clipping rectangle. (Note that the clipping rectangle is not
  // translated by the scroll.)

  // We assume |clip_rect| is contained within the backing store.
  DCHECK(clip_rect.bottom() <= size().height());
  DCHECK(clip_rect.right() <= size().width());

  if ((delta.x() || delta.y()) &&
       abs(delta.x()) < size().width() && abs(delta.y()) < size().height()) {
    if (cg_layer()) {
      CGContextRef layer = CGLayerGetContext(cg_layer());
      gfx::ScopedCGContextSaveGState save_gstate(layer);
      CGContextClipToRect(layer,
                          CGRectMake(clip_rect.x(),
                                     size().height() - clip_rect.bottom(),
                                     clip_rect.width(),
                                     clip_rect.height()));
      CGContextDrawLayerAtPoint(layer,
                                CGPointMake(delta.x(), -delta.y()), cg_layer());
    } else {
      // We don't have a layer, so scroll the contents of the CGBitmapContext.
      base::ScopedCFTypeRef<CGImageRef> bitmap_image(
          CGBitmapContextCreateImage(cg_bitmap_));
      gfx::ScopedCGContextSaveGState save_gstate(cg_bitmap_);
      CGContextClipToRect(cg_bitmap_,
                          CGRectMake(clip_rect.x(),
                                     size().height() - clip_rect.bottom(),
                                     clip_rect.width(),
                                     clip_rect.height()));
      CGContextDrawImage(cg_bitmap_,
                         CGRectMake(delta.x(), -delta.y(),
                                    size().width(), size().height()),
                         bitmap_image);
    }
  }
}

void BackingStoreMac::CopyFromBackingStoreToCGContext(const CGRect& dest_rect,
                                                      CGContextRef context) {
  gfx::ScopedCGContextSaveGState save_gstate(context);
  CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
  if (cg_layer_) {
    CGContextDrawLayerInRect(context, dest_rect, cg_layer_);
  } else {
    base::ScopedCFTypeRef<CGImageRef> image(
        CGBitmapContextCreateImage(cg_bitmap_));
    CGContextDrawImage(context, dest_rect, image);
  }
}

CGLayerRef BackingStoreMac::CreateCGLayer() {
  // The CGLayer should be optimized for drawing into the containing window,
  // so extract a CGContext corresponding to the window to be passed to
  // CGLayerCreateWithContext.
  NSWindow* window = [render_widget_host()->GetView()->GetNativeView() window];
  if ([window windowNumber] <= 0) {
    // This catches a nil |window|, as well as windows that exist but that
    // aren't yet connected to WindowServer.
    return NULL;
  }

  NSGraphicsContext* ns_context = [window graphicsContext];
  DCHECK(ns_context);

  CGContextRef cg_context = static_cast<CGContextRef>(
      [ns_context graphicsPort]);
  DCHECK(cg_context);

  // Note: This takes the backingScaleFactor of cg_context into account. The
  // bitmap backing |layer| will be size() * 2 in HiDPI mode automatically.
  CGLayerRef layer = CGLayerCreateWithContext(cg_context,
                                              size().ToCGSize(),
                                              NULL);
  DCHECK(layer);

  return layer;
}

CGContextRef BackingStoreMac::CreateCGBitmapContext() {
  gfx::Size pixel_size = gfx::ToFlooredSize(
      gfx::ScaleSize(size(), device_scale_factor_));
  // A CGBitmapContext serves as a stand-in for the layer before the view is
  // in a containing window.
  CGContextRef context = CGBitmapContextCreate(NULL,
                                               pixel_size.width(),
                                               pixel_size.height(),
                                               8, pixel_size.width() * 4,
                                               base::mac::GetSystemColorSpace(),
                                               kCGImageAlphaPremultipliedFirst |
                                                   kCGBitmapByteOrder32Host);
  DCHECK(context);

  return context;
}

}  // namespace content
