raster_cache.cc 3.1 KB
Newer Older
1 2 3 4
// Copyright 2016 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.

A
Adam Barth 已提交
5
#include "flow/raster_cache.h"
6 7

#include "base/logging.h"
8
#include "base/trace_event/trace_event.h"
A
Adam Barth 已提交
9
#include "third_party/skia/include/core/SkCanvas.h"
10
#include "third_party/skia/include/core/SkImage.h"
11
#include "third_party/skia/include/core/SkPicture.h"
A
Adam Barth 已提交
12
#include "third_party/skia/include/core/SkSurface.h"
13

A
Adam Barth 已提交
14
#define ENABLE_RASTER_CACHE 1
15

A
Adam Barth 已提交
16
namespace flow {
17

18 19
#if ENABLE_RASTER_CACHE

20 21 22 23 24 25 26 27
static const int kRasterThreshold = 3;

static bool isWorthRasterizing(SkPicture* picture) {
  // TODO(abarth): We should find a better heuristic here that lets us avoid
  // wasting memory on trivial layers that are easy to re-rasterize every frame.
  return picture->approximateOpCount() > 10 || picture->hasText();
}

28 29
#endif

30 31 32 33 34 35 36 37 38 39 40 41 42
RasterCache::RasterCache() {
}

RasterCache::~RasterCache() {
}

RasterCache::Entry::Entry() {
  physical_size.setEmpty();
}

RasterCache::Entry::~Entry() {
}

43 44 45
skia::RefPtr<SkImage> RasterCache::GetPrerolledImage(GrContext* context,
                                                     SkPicture* picture,
                                                     const SkMatrix& ctm) {
46
#if ENABLE_RASTER_CACHE
47 48 49 50 51 52 53 54
  SkScalar scaleX = ctm.getScaleX();
  SkScalar scaleY = ctm.getScaleY();

  SkRect rect = picture->cullRect();

  SkISize physical_size = SkISize::Make(rect.width() * scaleX,
                                        rect.height() * scaleY);

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  if (physical_size.isEmpty())
    return nullptr;

  Entry& entry = cache_[picture->uniqueID()];

  const bool size_matched = entry.physical_size == physical_size;

  entry.used_this_frame = true;
  entry.physical_size = physical_size;

  if (!size_matched) {
    entry.access_count = 1;
    entry.image = nullptr;
    return nullptr;
  }

  entry.access_count++;

  if (entry.access_count >= kRasterThreshold) {
    // Saturate at the threshhold.
    entry.access_count = kRasterThreshold;

    if (!entry.image && isWorthRasterizing(picture)) {
78 79 80
      TRACE_EVENT2("flutter", "Rasterize picture layer",
                   "width", physical_size.width(),
                   "height", physical_size.height());
A
Adam Barth 已提交
81
      SkImageInfo info = SkImageInfo::MakeN32Premul(physical_size);
82
      skia::RefPtr<SkSurface> surface = skia::AdoptRef(
A
Adam Barth 已提交
83
          SkSurface::NewRenderTarget(context, SkBudgeted::kYes, info));
A
Adam Barth 已提交
84 85 86
      if (surface) {
        SkCanvas* canvas = surface->getCanvas();
        canvas->clear(SK_ColorTRANSPARENT);
87
        canvas->scale(scaleX, scaleY);
A
Adam Barth 已提交
88
        canvas->translate(-rect.left(), -rect.top());
89
        canvas->drawPicture(picture);
90
        entry.image = skia::AdoptRef(surface->newImageSnapshot());
A
Adam Barth 已提交
91
      }
92 93 94 95
    }
  }

  return entry.image;
96 97 98
#else
  return nullptr;
#endif
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
}

void RasterCache::SweepAfterFrame() {
  std::vector<Cache::iterator> dead;

  for (auto it = cache_.begin(); it != cache_.end(); ++it) {
    Entry& entry = it->second;
    if (!entry.used_this_frame)
      dead.push_back(it);
    entry.used_this_frame = false;
  }

  for (auto it : dead)
    cache_.erase(it);
}

115 116 117 118
void RasterCache::Clear() {
  cache_.clear();
}

A
Adam Barth 已提交
119
}  // namespace flow