<commit_before>// Copyright (c) 2006-2008 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 "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"

#include "base/logging.h"
#include "base/mac_util.h"
#include "chrome/common/transport_dib.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"

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

BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
    : render_widget_host_(widget),
      size_(size),
      cg_layer_(NULL) {
  // We want our CGLayer to be optimized for drawing into our containing
  // window, so extract a CGContext corresponding to that window that we can
  // pass to CGLayerCreateWithContext.
  NSWindow* containing_window = [widget->view()->GetNativeView() window];
  if (!containing_window) {
    // If we are not in a containing window yet, create a CGBitmapContext
    // to use as a stand-in for the layer.
    cg_bitmap_.reset(CGBitmapContextCreate(NULL, size.width(), size.height(),
        8, size.width() * 4, mac_util::GetSystemColorSpace(),
        kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
  } else {
    CGContextRef context = static_cast<CGContextRef>(
        [[containing_window graphicsContext] graphicsPort]);
    CGLayerRef layer = CGLayerCreateWithContext(context, size.ToCGSize(), NULL);
    cg_layer_.reset(layer);
  }
}

BackingStore::~BackingStore() {
}

size_t BackingStore::MemorySize() {
  // Estimate memory usage as 4 bytes per pixel.
  return size_.GetArea() * 4;
}

// Paint the contents of a TransportDIB into a rectangle of our CGLayer
void BackingStore::PaintRect(base::ProcessHandle process,
                             TransportDIB* bitmap,
                             const gfx::Rect& bitmap_rect) {
  scoped_cftyperef<CGDataProviderRef> data_provider(
      CGDataProviderCreateWithData(NULL, bitmap->memory(),
      bitmap_rect.width() * bitmap_rect.height() * 4, NULL));
  scoped_cftyperef<CGImageRef> image(
      CGImageCreate(bitmap_rect.width(), bitmap_rect.height(), 8, 32,
          4 * bitmap_rect.width(), mac_util::GetSystemColorSpace(),
          kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
          data_provider, NULL, false, kCGRenderingIntentDefault));

  if (!cg_layer()) {
    // we don't have a CGLayer yet, so see if we can create one.
    NSWindow* containing_window =
        [render_widget_host()->view()->GetNativeView() window];
    if (containing_window) {
      CGContextRef context = static_cast<CGContextRef>(
          [[containing_window graphicsContext] graphicsPort]);
      CGLayerRef layer =
          CGLayerCreateWithContext(context, size().ToCGSize(), NULL);
      cg_layer_.reset(layer);
      // now that we have a layer, copy the cached image into it
      scoped_cftyperef<CGImageRef> bitmap_image(
          CGBitmapContextCreateImage(cg_bitmap_));
      CGContextDrawImage(CGLayerGetContext(layer),
                         CGRectMake(0, 0, size().width(), size().height()),
                         bitmap_image);
      // Discard the cache bitmap, since we no longer need it.
      cg_bitmap_.reset(NULL);
    }
  }

  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 = bitmap_rect;
    paint_rect.set_y(size_.height() - bitmap_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 = bitmap_rect;
    paint_rect.set_y(size_.height() - bitmap_rect.bottom());
    CGContextDrawImage(cg_bitmap_, paint_rect.ToCGRect(), image);
  }
}

// Scroll the contents of our CGLayer
void BackingStore::ScrollRect(base::ProcessHandle process,
                              TransportDIB* bitmap,
                              const gfx::Rect& bitmap_rect,
                              int dx, int dy,
                              const gfx::Rect& clip_rect,
                              const gfx::Size& view_size) {
  // "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.
  CGSize layer_size = CGLayerGetSize(cg_layer());
  DCHECK(clip_rect.bottom() <= layer_size.height);
  DCHECK(clip_rect.right() <= layer_size.width);

  if ((dx && abs(dx) < layer_size.width) ||
      (dy && abs(dy) < layer_size.height)) {
    if (cg_layer()) {
      CGContextRef context = CGLayerGetContext(cg_layer());
      scoped_cftyperef<CGLayerRef> new_layer(
          CGLayerCreateWithContext(context, layer_size, NULL));
      CGContextRef layer = CGLayerGetContext(new_layer);
      CGContextDrawLayerAtPoint(layer, CGPointMake(0, 0), cg_layer());
      CGContextSaveGState(layer);<commit_msg>BackingStoreMac scrolling update and DCHECKs.<commit_after>// Copyright (c) 2006-2008 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 "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"

#include "base/logging.h"
#include "base/mac_util.h"
#include "chrome/common/transport_dib.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"

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

BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
    : render_widget_host_(widget),
      size_(size),
      cg_layer_(NULL) {
  // We want our CGLayer to be optimized for drawing into our containing
  // window, so extract a CGContext corresponding to that window that we can
  // pass to CGLayerCreateWithContext.
  NSWindow* containing_window = [widget->view()->GetNativeView() window];
  if (!containing_window) {
    // If we are not in a containing window yet, create a CGBitmapContext
    // to use as a stand-in for the layer.
    cg_bitmap_.reset(CGBitmapContextCreate(NULL, size.width(), size.height(),
        8, size.width() * 4, mac_util::GetSystemColorSpace(),
        kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
  } else {
    CGContextRef context = static_cast<CGContextRef>(
        [[containing_window graphicsContext] graphicsPort]);
    CGLayerRef layer = CGLayerCreateWithContext(context, size.ToCGSize(), NULL);
    cg_layer_.reset(layer);
  }
}

BackingStore::~BackingStore() {
}

size_t BackingStore::MemorySize() {
  // Estimate memory usage as 4 bytes per pixel.
  return size_.GetArea() * 4;
}

// Paint the contents of a TransportDIB into a rectangle of our CGLayer
void BackingStore::PaintRect(base::ProcessHandle process,
                             TransportDIB* bitmap,
                             const gfx::Rect& bitmap_rect) {
  DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));

  scoped_cftyperef<CGDataProviderRef> data_provider(
      CGDataProviderCreateWithData(NULL, bitmap->memory(),
      bitmap_rect.width() * bitmap_rect.height() * 4, NULL));
  scoped_cftyperef<CGImageRef> image(
      CGImageCreate(bitmap_rect.width(), bitmap_rect.height(), 8, 32,
          4 * bitmap_rect.width(), mac_util::GetSystemColorSpace(),
          kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
          data_provider, NULL, false, kCGRenderingIntentDefault));

  if (!cg_layer()) {
    // we don't have a CGLayer yet, so see if we can create one.
    NSWindow* containing_window =
        [render_widget_host()->view()->GetNativeView() window];
    if (containing_window) {
      CGContextRef context = static_cast<CGContextRef>(
          [[containing_window graphicsContext] graphicsPort]);
      CGLayerRef layer =
          CGLayerCreateWithContext(context, size().ToCGSize(), NULL);
      cg_layer_.reset(layer);
      // now that we have a layer, copy the cached image into it
      scoped_cftyperef<CGImageRef> bitmap_image(
          CGBitmapContextCreateImage(cg_bitmap_));
      CGContextDrawImage(CGLayerGetContext(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 = bitmap_rect;
    paint_rect.set_y(size_.height() - bitmap_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 = bitmap_rect;
    paint_rect.set_y(size_.height() - bitmap_rect.bottom());
    CGContextDrawImage(cg_bitmap_, paint_rect.ToCGRect(), image);
  }
}

// Scroll the contents of our CGLayer
void BackingStore::ScrollRect(base::ProcessHandle process,
                              TransportDIB* bitmap,
                              const gfx::Rect& bitmap_rect,
                              int dx, int dy,
                              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 ((dx || dy) && abs(dx) < size_.width() && abs(dy) < size_.height()) {
    if (cg_layer()) {
      CGContextRef context = CGLayerGetContext(cg_layer());
      scoped_cftyperef<CGLayerRef> new_layer(
          CGLayerCreateWithContext(context, size_.ToCGSize(), NULL));
      CGContextRef layer = CGLayerGetContext(new_layer);
      CGContextDrawLayerAtPoint(layer, CGPointMake(0, 0), cg_layer());
      CGContextSaveGState(layer);
{'fraction_non_alphanumeric': 0.10357583230579531, 'fraction_numerical': 0.004110152075626798, 'mean_word_length': 3.3203125, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5318652', 'n_tokens_mistral': 3690, 'n_tokens_neox': 3573, 'n_words': 1050}