| Index: third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
 | 
| diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
 | 
| index 00bc234084636803e37c5bb5c78fd852dc77e77b..849575cb4960b16ddd153878da7052ca9bc5eca2 100644
 | 
| --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
 | 
| +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
 | 
| @@ -42,6 +42,7 @@
 | 
|  #include "platform/graphics/LinkHighlight.h"
 | 
|  #include "platform/graphics/paint/DrawingRecorder.h"
 | 
|  #include "platform/graphics/paint/PaintController.h"
 | 
| +#include "platform/graphics/paint/RasterInvalidationTracking.h"
 | 
|  #include "platform/json/JSONValues.h"
 | 
|  #include "platform/scroll/ScrollableArea.h"
 | 
|  #include "platform/text/TextStream.h"
 | 
| @@ -70,36 +71,11 @@
 | 
|  
 | 
|  namespace blink {
 | 
|  
 | 
| -struct PaintInvalidationInfo {
 | 
| -  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
 | 
| -  // This is for comparison only. Don't dereference because the client may have died.
 | 
| -  const DisplayItemClient* client;
 | 
| -  String clientDebugName;
 | 
| -  IntRect rect;
 | 
| -  PaintInvalidationReason reason;
 | 
| -};
 | 
| -
 | 
| -struct UnderPaintInvalidation {
 | 
| -  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
 | 
| -  int x;
 | 
| -  int y;
 | 
| -  SkColor oldPixel;
 | 
| -  SkColor newPixel;
 | 
| -};
 | 
| -
 | 
| -struct PaintInvalidationTracking {
 | 
| -  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
 | 
| -  Vector<PaintInvalidationInfo> trackedPaintInvalidations;
 | 
| -  sk_sp<SkPicture> lastPaintedPicture;
 | 
| -  IntRect lastInterestRect;
 | 
| -  Region paintInvalidationRegionSinceLastPaint;
 | 
| -  Vector<UnderPaintInvalidation> underPaintInvalidations;
 | 
| -};
 | 
| -
 | 
| -typedef HashMap<const GraphicsLayer*, PaintInvalidationTracking>
 | 
| -    PaintInvalidationTrackingMap;
 | 
| -static PaintInvalidationTrackingMap& paintInvalidationTrackingMap() {
 | 
| -  DEFINE_STATIC_LOCAL(PaintInvalidationTrackingMap, map, ());
 | 
| +template class RasterInvalidationTrackingMap<const GraphicsLayer>;
 | 
| +static RasterInvalidationTrackingMap<const GraphicsLayer>&
 | 
| +rasterInvalidationTrackingMap() {
 | 
| +  DEFINE_STATIC_LOCAL(RasterInvalidationTrackingMap<const GraphicsLayer>, map,
 | 
| +                      ());
 | 
|    return map;
 | 
|  }
 | 
|  
 | 
| @@ -123,8 +99,8 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
 | 
|        m_hasScrollParent(false),
 | 
|        m_hasClipParent(false),
 | 
|        m_painted(false),
 | 
| -      m_isTrackingPaintInvalidations(client &&
 | 
| -                                     client->isTrackingPaintInvalidations()),
 | 
| +      m_isTrackingRasterInvalidations(client &&
 | 
| +                                      client->isTrackingRasterInvalidations()),
 | 
|        m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip),
 | 
|        m_parent(0),
 | 
|        m_maskLayer(0),
 | 
| @@ -160,7 +136,7 @@ GraphicsLayer::~GraphicsLayer() {
 | 
|    removeAllChildren();
 | 
|    removeFromParent();
 | 
|  
 | 
| -  paintInvalidationTrackingMap().remove(this);
 | 
| +  rasterInvalidationTrackingMap().remove(this);
 | 
|    ASSERT(!m_parent);
 | 
|  }
 | 
|  
 | 
| @@ -304,13 +280,11 @@ void GraphicsLayer::paint(const IntRect* interestRect,
 | 
|      if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
 | 
|        sk_sp<SkPicture> newPicture = capturePicture();
 | 
|        checkPaintUnderInvalidations(*newPicture);
 | 
| -      PaintInvalidationTracking& tracking =
 | 
| -          paintInvalidationTrackingMap()
 | 
| -              .add(this, PaintInvalidationTracking())
 | 
| -              .storedValue->value;
 | 
| +      RasterInvalidationTracking& tracking =
 | 
| +          rasterInvalidationTrackingMap().add(this);
 | 
|        tracking.lastPaintedPicture = std::move(newPicture);
 | 
|        tracking.lastInterestRect = m_previousInterestRect;
 | 
| -      tracking.paintInvalidationRegionSinceLastPaint = Region();
 | 
| +      tracking.rasterInvalidationRegionSinceLastPaint = Region();
 | 
|      }
 | 
|    }
 | 
|  }
 | 
| @@ -508,75 +482,58 @@ WebLayer* GraphicsLayer::contentsLayerIfRegistered() {
 | 
|    return m_contentsLayer;
 | 
|  }
 | 
|  
 | 
| -void GraphicsLayer::setTracksPaintInvalidations(bool tracksPaintInvalidations) {
 | 
| -  resetTrackedPaintInvalidations();
 | 
| -  m_isTrackingPaintInvalidations = tracksPaintInvalidations;
 | 
| +void GraphicsLayer::setTracksRasterInvalidations(
 | 
| +    bool tracksRasterInvalidations) {
 | 
| +  resetTrackedRasterInvalidations();
 | 
| +  m_isTrackingRasterInvalidations = tracksRasterInvalidations;
 | 
|  }
 | 
|  
 | 
| -void GraphicsLayer::resetTrackedPaintInvalidations() {
 | 
| -  auto it = paintInvalidationTrackingMap().find(this);
 | 
| -  if (it == paintInvalidationTrackingMap().end())
 | 
| +void GraphicsLayer::resetTrackedRasterInvalidations() {
 | 
| +  RasterInvalidationTracking* tracking =
 | 
| +      rasterInvalidationTrackingMap().find(this);
 | 
| +  if (!tracking)
 | 
|      return;
 | 
|  
 | 
|    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled())
 | 
| -    it->value.trackedPaintInvalidations.clear();
 | 
| +    tracking->trackedRasterInvalidations.clear();
 | 
|    else
 | 
| -    paintInvalidationTrackingMap().remove(it);
 | 
| +    rasterInvalidationTrackingMap().remove(this);
 | 
|  }
 | 
|  
 | 
| -bool GraphicsLayer::hasTrackedPaintInvalidations() const {
 | 
| -  PaintInvalidationTrackingMap::iterator it =
 | 
| -      paintInvalidationTrackingMap().find(this);
 | 
| -  if (it != paintInvalidationTrackingMap().end())
 | 
| -    return !it->value.trackedPaintInvalidations.isEmpty();
 | 
| +bool GraphicsLayer::hasTrackedRasterInvalidations() const {
 | 
| +  RasterInvalidationTracking* tracking =
 | 
| +      rasterInvalidationTrackingMap().find(this);
 | 
| +  if (tracking)
 | 
| +    return !tracking->trackedRasterInvalidations.isEmpty();
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| -void GraphicsLayer::trackPaintInvalidation(const DisplayItemClient& client,
 | 
| -                                           const IntRect& rect,
 | 
| -                                           PaintInvalidationReason reason) {
 | 
| -  if (!isTrackingOrCheckingPaintInvalidations() || rect.isEmpty())
 | 
| +void GraphicsLayer::trackRasterInvalidation(const DisplayItemClient& client,
 | 
| +                                            const IntRect& rect,
 | 
| +                                            PaintInvalidationReason reason) {
 | 
| +  if (!isTrackingOrCheckingRasterInvalidations() || rect.isEmpty())
 | 
|      return;
 | 
|  
 | 
| -  PaintInvalidationTracking& tracking =
 | 
| -      paintInvalidationTrackingMap()
 | 
| -          .add(this, PaintInvalidationTracking())
 | 
| -          .storedValue->value;
 | 
| +  RasterInvalidationTracking& tracking =
 | 
| +      rasterInvalidationTrackingMap().add(this);
 | 
|  
 | 
| -  if (m_isTrackingPaintInvalidations) {
 | 
| -    PaintInvalidationInfo info = {&client, client.debugName(), rect, reason};
 | 
| -    tracking.trackedPaintInvalidations.append(info);
 | 
| +  if (m_isTrackingRasterInvalidations) {
 | 
| +    RasterInvalidationInfo info;
 | 
| +    info.client = &client;
 | 
| +    info.clientDebugName = client.debugName();
 | 
| +    info.rect = rect;
 | 
| +    info.reason = reason;
 | 
| +    tracking.trackedRasterInvalidations.append(info);
 | 
|    }
 | 
|  
 | 
|    if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
 | 
|      // TODO(crbug.com/496260): Some antialiasing effects overflows the paint invalidation rect.
 | 
|      IntRect r = rect;
 | 
|      r.inflate(1);
 | 
| -    tracking.paintInvalidationRegionSinceLastPaint.unite(r);
 | 
| +    tracking.rasterInvalidationRegionSinceLastPaint.unite(r);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -static bool comparePaintInvalidationInfo(const PaintInvalidationInfo& a,
 | 
| -                                         const PaintInvalidationInfo& b) {
 | 
| -  // Sort by rect first, bigger rects before smaller ones.
 | 
| -  if (a.rect.width() != b.rect.width())
 | 
| -    return a.rect.width() > b.rect.width();
 | 
| -  if (a.rect.height() != b.rect.height())
 | 
| -    return a.rect.height() > b.rect.height();
 | 
| -  if (a.rect.x() != b.rect.x())
 | 
| -    return a.rect.x() > b.rect.x();
 | 
| -  if (a.rect.y() != b.rect.y())
 | 
| -    return a.rect.y() > b.rect.y();
 | 
| -
 | 
| -  // Then compare clientDebugName, in alphabetic order.
 | 
| -  int nameCompareResult =
 | 
| -      codePointCompare(a.clientDebugName, b.clientDebugName);
 | 
| -  if (nameCompareResult != 0)
 | 
| -    return nameCompareResult < 0;
 | 
| -
 | 
| -  return a.reason < b.reason;
 | 
| -}
 | 
| -
 | 
|  template <typename T>
 | 
|  static std::unique_ptr<JSONArray> pointAsJSONArray(const T& point) {
 | 
|    std::unique_ptr<JSONArray> array = JSONArray::create();
 | 
| @@ -593,16 +550,6 @@ static std::unique_ptr<JSONArray> sizeAsJSONArray(const T& size) {
 | 
|    return array;
 | 
|  }
 | 
|  
 | 
| -template <typename T>
 | 
| -static std::unique_ptr<JSONArray> rectAsJSONArray(const T& rect) {
 | 
| -  std::unique_ptr<JSONArray> array = JSONArray::create();
 | 
| -  array->pushDouble(rect.x());
 | 
| -  array->pushDouble(rect.y());
 | 
| -  array->pushDouble(rect.width());
 | 
| -  array->pushDouble(rect.height());
 | 
| -  return array;
 | 
| -}
 | 
| -
 | 
|  static double roundCloseToZero(double number) {
 | 
|    return std::abs(number) < 1e-7 ? 0 : number;
 | 
|  }
 | 
| @@ -726,51 +673,8 @@ std::unique_ptr<JSONObject> GraphicsLayer::layerTreeAsJSONInternal(
 | 
|    if (!m_transform.isIdentity())
 | 
|      json->setArray("transform", transformAsJSONArray(m_transform));
 | 
|  
 | 
| -  PaintInvalidationTrackingMap::iterator it =
 | 
| -      paintInvalidationTrackingMap().find(this);
 | 
| -  if (it != paintInvalidationTrackingMap().end()) {
 | 
| -    if (flags & LayerTreeIncludesPaintInvalidations) {
 | 
| -      Vector<PaintInvalidationInfo>& infos =
 | 
| -          it->value.trackedPaintInvalidations;
 | 
| -      if (!infos.isEmpty()) {
 | 
| -        std::sort(infos.begin(), infos.end(), &comparePaintInvalidationInfo);
 | 
| -        std::unique_ptr<JSONArray> paintInvalidationsJSON = JSONArray::create();
 | 
| -        for (auto& info : infos) {
 | 
| -          std::unique_ptr<JSONObject> infoJSON = JSONObject::create();
 | 
| -          infoJSON->setString("object", info.clientDebugName);
 | 
| -          if (!info.rect.isEmpty())
 | 
| -            infoJSON->setArray("rect", rectAsJSONArray(info.rect));
 | 
| -          infoJSON->setString("reason",
 | 
| -                              paintInvalidationReasonToString(info.reason));
 | 
| -          paintInvalidationsJSON->pushObject(std::move(infoJSON));
 | 
| -        }
 | 
| -        json->setArray("paintInvalidations", std::move(paintInvalidationsJSON));
 | 
| -      }
 | 
| -
 | 
| -      Vector<UnderPaintInvalidation>& underPaintInvalidations =
 | 
| -          it->value.underPaintInvalidations;
 | 
| -      if (!underPaintInvalidations.isEmpty()) {
 | 
| -        std::unique_ptr<JSONArray> underPaintInvalidationsJSON =
 | 
| -            JSONArray::create();
 | 
| -        for (auto& underPaintInvalidation : underPaintInvalidations) {
 | 
| -          std::unique_ptr<JSONObject> underPaintInvalidationJSON =
 | 
| -              JSONObject::create();
 | 
| -          underPaintInvalidationJSON->setDouble("x", underPaintInvalidation.x);
 | 
| -          underPaintInvalidationJSON->setDouble("y", underPaintInvalidation.y);
 | 
| -          underPaintInvalidationJSON->setString(
 | 
| -              "oldPixel",
 | 
| -              Color(underPaintInvalidation.oldPixel).nameForLayoutTreeAsText());
 | 
| -          underPaintInvalidationJSON->setString(
 | 
| -              "newPixel",
 | 
| -              Color(underPaintInvalidation.newPixel).nameForLayoutTreeAsText());
 | 
| -          underPaintInvalidationsJSON->pushObject(
 | 
| -              std::move(underPaintInvalidationJSON));
 | 
| -        }
 | 
| -        json->setArray("underPaintInvalidations",
 | 
| -                       std::move(underPaintInvalidationsJSON));
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| +  if (flags & LayerTreeIncludesPaintInvalidations)
 | 
| +    rasterInvalidationTrackingMap().asJSON(this, json.get());
 | 
|  
 | 
|    if ((flags & LayerTreeIncludesPaintingPhases) && m_paintingPhase) {
 | 
|      std::unique_ptr<JSONArray> paintingPhasesJSON = JSONArray::create();
 | 
| @@ -1044,7 +948,7 @@ void GraphicsLayer::setIsRootForIsolatedGroup(bool isolated) {
 | 
|  void GraphicsLayer::setContentsNeedsDisplay() {
 | 
|    if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
 | 
|      contentsLayer->invalidate();
 | 
| -    trackPaintInvalidation(*this, m_contentsRect, PaintInvalidationFull);
 | 
| +    trackRasterInvalidation(*this, m_contentsRect, PaintInvalidationFull);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -1058,8 +962,8 @@ void GraphicsLayer::setNeedsDisplay() {
 | 
|      m_linkHighlights[i]->invalidate();
 | 
|    getPaintController().invalidateAll();
 | 
|  
 | 
| -  trackPaintInvalidation(*this, IntRect(IntPoint(), expandedIntSize(m_size)),
 | 
| -                         PaintInvalidationFull);
 | 
| +  trackRasterInvalidation(*this, IntRect(IntPoint(), expandedIntSize(m_size)),
 | 
| +                          PaintInvalidationFull);
 | 
|  }
 | 
|  
 | 
|  void GraphicsLayer::setNeedsDisplayInRect(
 | 
| @@ -1075,7 +979,7 @@ void GraphicsLayer::setNeedsDisplayInRect(
 | 
|    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
 | 
|      m_linkHighlights[i]->invalidate();
 | 
|  
 | 
| -  trackPaintInvalidation(client, rect, invalidationReason);
 | 
| +  trackRasterInvalidation(client, rect, invalidationReason);
 | 
|  }
 | 
|  
 | 
|  void GraphicsLayer::setContentsRect(const IntRect& rect) {
 | 
| @@ -1250,14 +1154,15 @@ void GraphicsLayer::checkPaintUnderInvalidations(const SkPicture& newPicture) {
 | 
|    if (!drawsContent())
 | 
|      return;
 | 
|  
 | 
| -  auto it = paintInvalidationTrackingMap().find(this);
 | 
| -  if (it == paintInvalidationTrackingMap().end())
 | 
| +  RasterInvalidationTracking* tracking =
 | 
| +      rasterInvalidationTrackingMap().find(this);
 | 
| +  if (!tracking)
 | 
|      return;
 | 
| -  PaintInvalidationTracking& tracking = it->value;
 | 
| -  if (!tracking.lastPaintedPicture)
 | 
| +
 | 
| +  if (!tracking->lastPaintedPicture)
 | 
|      return;
 | 
|  
 | 
| -  IntRect rect = intersection(tracking.lastInterestRect, interestRect());
 | 
| +  IntRect rect = intersection(tracking->lastInterestRect, interestRect());
 | 
|    if (rect.isEmpty())
 | 
|      return;
 | 
|  
 | 
| @@ -1268,7 +1173,7 @@ void GraphicsLayer::checkPaintUnderInvalidations(const SkPicture& newPicture) {
 | 
|      SkCanvas canvas(oldBitmap);
 | 
|      canvas.clear(SK_ColorTRANSPARENT);
 | 
|      canvas.translate(-rect.x(), -rect.y());
 | 
| -    canvas.drawPicture(tracking.lastPaintedPicture.get());
 | 
| +    canvas.drawPicture(tracking->lastPaintedPicture.get());
 | 
|    }
 | 
|  
 | 
|    SkBitmap newBitmap;
 | 
| @@ -1292,12 +1197,12 @@ void GraphicsLayer::checkPaintUnderInvalidations(const SkPicture& newPicture) {
 | 
|        SkColor oldPixel = oldBitmap.getColor(bitmapX, bitmapY);
 | 
|        SkColor newPixel = newBitmap.getColor(bitmapX, bitmapY);
 | 
|        if (pixelsDiffer(oldPixel, newPixel) &&
 | 
| -          !tracking.paintInvalidationRegionSinceLastPaint.contains(
 | 
| +          !tracking->rasterInvalidationRegionSinceLastPaint.contains(
 | 
|                IntPoint(layerX, layerY))) {
 | 
|          if (mismatchingPixels < maxMismatchesToReport) {
 | 
|            UnderPaintInvalidation underPaintInvalidation = {layerX, layerY,
 | 
|                                                             oldPixel, newPixel};
 | 
| -          tracking.underPaintInvalidations.append(underPaintInvalidation);
 | 
| +          tracking->underPaintInvalidations.append(underPaintInvalidation);
 | 
|            LOG(ERROR) << debugName()
 | 
|                       << " Uninvalidated old/new pixels mismatch at " << layerX
 | 
|                       << "," << layerY << " old:" << std::hex << oldPixel
 | 
| 
 |