summaryrefslogtreecommitdiffstats
path: root/remoting/host/capturer_helper.cc
blob: 4081e7269a004bbe1a94281dabb50173e0ff892c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// 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.

#include "remoting/host/capturer_helper.h"

#include <algorithm>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"

namespace remoting {

CapturerHelper::CapturerHelper() :
    size_most_recent_(SkISize::Make(0, 0)),
    log_grid_size_(0) {
}

CapturerHelper::~CapturerHelper() {
}

void CapturerHelper::ClearInvalidRegion() {
  base::AutoLock auto_invalid_region_lock(invalid_region_lock_);
  invalid_region_.setEmpty();
}

void CapturerHelper::InvalidateRegion(const SkRegion& invalid_region) {
  base::AutoLock auto_invalid_region_lock(invalid_region_lock_);
  invalid_region_.op(invalid_region, SkRegion::kUnion_Op);
}

void CapturerHelper::InvalidateScreen(const SkISize& size) {
  base::AutoLock auto_invalid_region_lock(invalid_region_lock_);
  invalid_region_.op(SkIRect::MakeWH(size.width(), size.height()),
                     SkRegion::kUnion_Op);
}

void CapturerHelper::InvalidateFullScreen() {
  if (!size_most_recent_.isZero())
    InvalidateScreen(size_most_recent_);
}

void CapturerHelper::SwapInvalidRegion(SkRegion* invalid_region) {
  {
    base::AutoLock auto_invalid_region_lock(invalid_region_lock_);
    invalid_region->swap(invalid_region_);
  }
  if (log_grid_size_ > 0) {
    scoped_ptr<SkRegion> expanded_region(
        ExpandToGrid(*invalid_region, log_grid_size_));
    invalid_region->swap(*expanded_region);
    invalid_region->op(SkRegion(SkIRect::MakeSize(size_most_recent_)),
                       SkRegion::kIntersect_Op);
  }
}

void CapturerHelper::SetLogGridSize(int log_grid_size) {
  log_grid_size_ = log_grid_size;
}

const SkISize& CapturerHelper::size_most_recent() const {
  return size_most_recent_;
}

void CapturerHelper::set_size_most_recent(const SkISize& size) {
  size_most_recent_ = size;
}

// Returns the largest multiple of |n| that is <= |x|.
// |n| must be a power of 2. |nMask| is ~(|n| - 1).
static int DownToMultiple(int x, int nMask) {
  return (x & nMask);
}

// Returns the smallest multiple of |n| that is >= |x|.
// |n| must be a power of 2. |nMask| is ~(|n| - 1).
static int UpToMultiple(int x, int n, int nMask) {
  return ((x + n - 1) & nMask);
}

scoped_ptr<SkRegion> CapturerHelper::ExpandToGrid(const SkRegion& region,
                                                  int log_grid_size) {
  DCHECK(log_grid_size >= 1);
  int grid_size = 1 << log_grid_size;
  int grid_size_mask = ~(grid_size - 1);
  // Count the rects in the region.
  int rectNum = 0;
  SkRegion::Iterator iter(region);
  while (!iter.done()) {
    iter.next();
    ++rectNum;
  }
  // Expand each rect.
  scoped_array<SkIRect> rects(new SkIRect[rectNum]);
  iter.rewind();
  int rectI = 0;
  while (!iter.done()) {
    SkIRect rect = iter.rect();
    iter.next();
    int left = std::min(rect.left(), rect.right());
    int right = std::max(rect.left(), rect.right());
    int top = std::min(rect.top(), rect.bottom());
    int bottom = std::max(rect.top(), rect.bottom());
    left = DownToMultiple(left, grid_size_mask);
    right = UpToMultiple(right, grid_size, grid_size_mask);
    top = DownToMultiple(top, grid_size_mask);
    bottom = UpToMultiple(bottom, grid_size, grid_size_mask);
    rects[rectI++] = SkIRect::MakeLTRB(left, top, right, bottom);
  }
  // Make the union of the expanded rects.
  scoped_ptr<SkRegion> regionNew(new SkRegion());
  regionNew->setRects(rects.get(), rectNum);
  return regionNew.Pass();
}

}  // namespace remoting