Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/backing_store_aura.h"
      6 
      7 #include "content/browser/renderer_host/dip_util.h"
      8 #include "content/browser/renderer_host/render_process_host_impl.h"
      9 #include "content/public/browser/render_widget_host.h"
     10 #include "skia/ext/platform_canvas.h"
     11 #include "third_party/skia/include/core/SkCanvas.h"
     12 #include "ui/gfx/canvas.h"
     13 #include "ui/gfx/image/image_skia.h"
     14 #include "ui/gfx/rect.h"
     15 #include "ui/gfx/rect_conversions.h"
     16 #include "ui/gfx/size_conversions.h"
     17 #include "ui/gfx/vector2d_conversions.h"
     18 
     19 namespace {
     20 
     21 gfx::Size ToPixelSize(gfx::Size dipSize, float scale) {
     22   return gfx::ToCeiledSize(gfx::ScaleSize(dipSize, scale));
     23 }
     24 
     25 }  // namespace
     26 
     27 
     28 namespace content {
     29 
     30 // Assume that somewhere along the line, someone will do width * height * 4
     31 // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 =
     32 // 2**29 and floor(sqrt(2**29)) = 23170.
     33 
     34 // Max height and width for layers
     35 static const int kMaxVideoLayerSize = 23170;
     36 
     37 BackingStoreAura::BackingStoreAura(RenderWidgetHost* widget,
     38                                    const gfx::Size& size)
     39     : BackingStore(widget, size) {
     40   device_scale_factor_ =
     41       ui::GetImageScale(GetScaleFactorForView(widget->GetView()));
     42   gfx::Size pixel_size = ToPixelSize(size, device_scale_factor_);
     43   bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
     44       pixel_size.width(), pixel_size.height());
     45   bitmap_.allocPixels();
     46   canvas_.reset(new SkCanvas(bitmap_));
     47 }
     48 
     49 BackingStoreAura::~BackingStoreAura() {
     50 }
     51 
     52 void BackingStoreAura::SkiaShowRect(const gfx::Point& point,
     53                                     gfx::Canvas* canvas) {
     54   gfx::ImageSkia image = gfx::ImageSkia(gfx::ImageSkiaRep(bitmap_,
     55       device_scale_factor_));
     56   canvas->DrawImageInt(image, point.x(), point.y());
     57 }
     58 
     59 void BackingStoreAura::ScaleFactorChanged(float device_scale_factor) {
     60   if (device_scale_factor == device_scale_factor_)
     61     return;
     62 
     63   gfx::Size old_pixel_size = ToPixelSize(size(), device_scale_factor_);
     64   device_scale_factor_ = device_scale_factor;
     65 
     66   gfx::Size pixel_size = ToPixelSize(size(), device_scale_factor_);
     67   SkBitmap new_bitmap;
     68   new_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
     69       pixel_size.width(), pixel_size.height());
     70   new_bitmap.allocPixels();
     71   scoped_ptr<SkCanvas> new_canvas(new SkCanvas(new_bitmap));
     72 
     73   // Copy old contents; a low-res flash is better than a black flash.
     74   SkPaint copy_paint;
     75   copy_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
     76   SkIRect src_rect = SkIRect::MakeWH(old_pixel_size.width(),
     77                                      old_pixel_size.height());
     78   SkRect dst_rect = SkRect::MakeWH(pixel_size.width(), pixel_size.height());
     79   new_canvas.get()->drawBitmapRect(bitmap_, &src_rect, dst_rect, &copy_paint);
     80 
     81   canvas_.swap(new_canvas);
     82   bitmap_ = new_bitmap;
     83 }
     84 
     85 size_t BackingStoreAura::MemorySize() {
     86   // NOTE: The computation may be different when the canvas is a subrectangle of
     87   // a larger bitmap.
     88   return ToPixelSize(size(), device_scale_factor_).GetArea() * 4;
     89 }
     90 
     91 void BackingStoreAura::PaintToBackingStore(
     92     RenderProcessHost* process,
     93     TransportDIB::Id bitmap,
     94     const gfx::Rect& bitmap_rect,
     95     const std::vector<gfx::Rect>& copy_rects,
     96     float scale_factor,
     97     const base::Closure& completion_callback,
     98     bool* scheduled_completion_callback) {
     99   *scheduled_completion_callback = false;
    100   if (bitmap_rect.IsEmpty())
    101     return;
    102 
    103   gfx::Rect pixel_bitmap_rect = gfx::ToEnclosingRect(
    104       gfx::ScaleRect(bitmap_rect, scale_factor));
    105 
    106   const int width = pixel_bitmap_rect.width();
    107   const int height = pixel_bitmap_rect.height();
    108 
    109   if (width <= 0 || width > kMaxVideoLayerSize ||
    110       height <= 0 || height > kMaxVideoLayerSize)
    111     return;
    112 
    113   TransportDIB* dib = process->GetTransportDIB(bitmap);
    114   if (!dib)
    115     return;
    116 
    117   SkPaint copy_paint;
    118   copy_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    119 
    120   SkBitmap sk_bitmap;
    121   sk_bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
    122   sk_bitmap.setPixels(dib->memory());
    123   for (size_t i = 0; i < copy_rects.size(); i++) {
    124     const gfx::Rect pixel_copy_rect = gfx::ToEnclosingRect(
    125         gfx::ScaleRect(copy_rects[i], scale_factor));
    126     int x = pixel_copy_rect.x() - pixel_bitmap_rect.x();
    127     int y = pixel_copy_rect.y() - pixel_bitmap_rect.y();
    128     SkIRect srcrect = SkIRect::MakeXYWH(x, y,
    129         pixel_copy_rect.width(),
    130         pixel_copy_rect.height());
    131 
    132     const gfx::Rect pixel_copy_dst_rect = gfx::ToEnclosingRect(
    133         gfx::ScaleRect(copy_rects[i], device_scale_factor_));
    134     SkRect dstrect = SkRect::MakeXYWH(
    135         SkIntToScalar(pixel_copy_dst_rect.x()),
    136         SkIntToScalar(pixel_copy_dst_rect.y()),
    137         SkIntToScalar(pixel_copy_dst_rect.width()),
    138         SkIntToScalar(pixel_copy_dst_rect.height()));
    139     canvas_.get()->drawBitmapRect(sk_bitmap, &srcrect, dstrect, &copy_paint);
    140   }
    141 }
    142 
    143 void BackingStoreAura::ScrollBackingStore(const gfx::Vector2d& delta,
    144                                           const gfx::Rect& clip_rect,
    145                                           const gfx::Size& view_size) {
    146   gfx::Rect pixel_rect = gfx::ToEnclosingRect(
    147       gfx::ScaleRect(clip_rect, device_scale_factor_));
    148   gfx::Vector2d pixel_delta = gfx::ToFlooredVector2d(
    149       gfx::ScaleVector2d(delta, device_scale_factor_));
    150 
    151   int x = std::min(pixel_rect.x(), pixel_rect.x() - pixel_delta.x());
    152   int y = std::min(pixel_rect.y(), pixel_rect.y() - pixel_delta.y());
    153   int w = pixel_rect.width() + abs(pixel_delta.x());
    154   int h = pixel_rect.height() + abs(pixel_delta.y());
    155   SkIRect rect = SkIRect::MakeXYWH(x, y, w, h);
    156   bitmap_.scrollRect(&rect, pixel_delta.x(), pixel_delta.y());
    157 }
    158 
    159 bool BackingStoreAura::CopyFromBackingStore(const gfx::Rect& rect,
    160                                             skia::PlatformBitmap* output) {
    161   const int width =
    162       std::min(size().width(), rect.width()) * device_scale_factor_;
    163   const int height =
    164       std::min(size().height(), rect.height()) * device_scale_factor_;
    165   if (!output->Allocate(width, height, true))
    166     return false;
    167 
    168   SkIRect skrect = SkIRect::MakeXYWH(rect.x(), rect.y(), width, height);
    169   SkBitmap b;
    170   if (!canvas_->readPixels(skrect, &b))
    171     return false;
    172   SkCanvas(output->GetBitmap()).writePixels(b, rect.x(), rect.y());
    173   return true;
    174 }
    175 
    176 }  // namespace content
    177