Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / gpu / compositor_software_output_device.cc
blobc7470753c3f0fe4feb0329e222adccdd154c31ba
1 // Copyright (c) 2013 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.
5 #include "content/renderer/gpu/compositor_software_output_device.h"
7 #include "base/logging.h"
8 #include "cc/output/software_frame_data.h"
9 #include "content/child/child_shared_bitmap_manager.h"
10 #include "content/renderer/render_process.h"
11 #include "content/renderer/render_thread_impl.h"
12 #include "third_party/skia/include/core/SkBitmapDevice.h"
13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "third_party/skia/include/core/SkPixelRef.h"
15 #include "third_party/skia/include/core/SkRegion.h"
16 #include "ui/gfx/skia_util.h"
18 namespace {
20 const size_t kInvalidIndex = static_cast<size_t>(-1);
22 } // namespace
24 namespace content {
26 CompositorSoftwareOutputDevice::Buffer::Buffer(
27 unsigned id,
28 scoped_ptr<cc::SharedBitmap> bitmap)
29 : id_(id), shared_bitmap_(bitmap.Pass()), free_(true), parent_(NULL) {}
31 CompositorSoftwareOutputDevice::Buffer::~Buffer() {
34 void CompositorSoftwareOutputDevice::Buffer::SetParent(
35 Buffer* parent, const gfx::Rect& damage) {
36 parent_ = parent;
37 damage_ = damage;
40 bool CompositorSoftwareOutputDevice::Buffer::FindDamageDifferenceFrom(
41 Buffer* buffer, SkRegion* result) const {
42 if (!buffer)
43 return false;
45 if (buffer == this) {
46 *result = SkRegion();
47 return true;
50 SkRegion damage;
51 const Buffer* current = this;
52 while (current->parent_) {
53 damage.op(RectToSkIRect(current->damage_), SkRegion::kUnion_Op);
54 if (current->parent_ == buffer) {
55 *result = damage;
56 return true;
58 current = current->parent_;
61 return false;
64 CompositorSoftwareOutputDevice::CompositorSoftwareOutputDevice()
65 : current_index_(kInvalidIndex),
66 next_buffer_id_(1),
67 shared_bitmap_manager_(
68 RenderThreadImpl::current()->shared_bitmap_manager()) {
69 DetachFromThread();
72 CompositorSoftwareOutputDevice::~CompositorSoftwareOutputDevice() {
73 DCHECK(CalledOnValidThread());
76 unsigned CompositorSoftwareOutputDevice::GetNextId() {
77 unsigned id = next_buffer_id_++;
78 // Zero is reserved to label invalid frame id.
79 if (id == 0)
80 id = next_buffer_id_++;
81 return id;
84 CompositorSoftwareOutputDevice::Buffer*
85 CompositorSoftwareOutputDevice::CreateBuffer() {
86 scoped_ptr<cc::SharedBitmap> shared_bitmap =
87 shared_bitmap_manager_->AllocateSharedBitmap(viewport_pixel_size_);
88 CHECK(shared_bitmap);
89 return new Buffer(GetNextId(), shared_bitmap.Pass());
92 size_t CompositorSoftwareOutputDevice::FindFreeBuffer(size_t hint) {
93 for (size_t i = 0; i < buffers_.size(); ++i) {
94 size_t index = (hint + i) % buffers_.size();
95 if (buffers_[index]->free())
96 return index;
99 buffers_.push_back(CreateBuffer());
100 return buffers_.size() - 1;
103 void CompositorSoftwareOutputDevice::Resize(
104 const gfx::Size& viewport_pixel_size,
105 float scale_factor) {
106 DCHECK(CalledOnValidThread());
108 scale_factor_ = scale_factor;
110 if (viewport_pixel_size_ == viewport_pixel_size)
111 return;
113 // Keep non-ACKed buffers in awaiting_ack_ until they get acknowledged.
114 for (size_t i = 0; i < buffers_.size(); ++i) {
115 if (!buffers_[i]->free()) {
116 awaiting_ack_.push_back(buffers_[i]);
117 buffers_[i] = NULL;
121 buffers_.clear();
122 current_index_ = kInvalidIndex;
123 viewport_pixel_size_ = viewport_pixel_size;
126 void CompositorSoftwareOutputDevice::DiscardBackbuffer() {
127 // Keep non-ACKed buffers in awaiting_ack_ until they get acknowledged.
128 for (size_t i = 0; i < buffers_.size(); ++i) {
129 if (!buffers_[i]->free()) {
130 awaiting_ack_.push_back(buffers_[i]);
131 buffers_[i] = NULL;
134 buffers_.clear();
135 current_index_ = kInvalidIndex;
138 void CompositorSoftwareOutputDevice::EnsureBackbuffer() {
141 SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
142 const gfx::Rect& damage_rect) {
143 DCHECK(CalledOnValidThread());
145 Buffer* previous = NULL;
146 if (current_index_ != kInvalidIndex)
147 previous = buffers_[current_index_];
148 current_index_ = FindFreeBuffer(current_index_ + 1);
149 Buffer* current = buffers_[current_index_];
150 DCHECK(current->free());
151 current->SetFree(false);
153 // Set up a canvas for the current front buffer.
154 SkImageInfo info = SkImageInfo::MakeN32Premul(viewport_pixel_size_.width(),
155 viewport_pixel_size_.height());
156 SkBitmap bitmap;
157 bitmap.installPixels(info, current->memory(), info.minRowBytes());
158 canvas_ = skia::AdoptRef(new SkCanvas(bitmap));
160 if (!previous) {
161 DCHECK(damage_rect == gfx::Rect(viewport_pixel_size_));
162 } else {
163 // Find the smallest damage region that needs
164 // to be copied from the |previous| buffer.
165 SkRegion region;
166 bool found =
167 current->FindDamageDifferenceFrom(previous, &region) ||
168 previous->FindDamageDifferenceFrom(current, &region);
169 if (!found)
170 region = SkRegion(RectToSkIRect(gfx::Rect(viewport_pixel_size_)));
171 region.op(RectToSkIRect(damage_rect), SkRegion::kDifference_Op);
173 // Copy over the damage region.
174 if (!region.isEmpty()) {
175 SkImageInfo info = SkImageInfo::MakeN32Premul(
176 viewport_pixel_size_.width(), viewport_pixel_size_.height());
177 SkBitmap back_bitmap;
178 back_bitmap.installPixels(info, previous->memory(), info.minRowBytes());
180 for (SkRegion::Iterator it(region); !it.done(); it.next()) {
181 const SkIRect& src_rect = it.rect();
182 SkRect dst_rect = SkRect::Make(src_rect);
183 canvas_->drawBitmapRect(back_bitmap, &src_rect, dst_rect, NULL);
188 // Make |current| child of |previous| and orphan all of |current|'s children.
189 current->SetParent(previous, damage_rect);
190 for (size_t i = 0; i < buffers_.size(); ++i) {
191 Buffer* buffer = buffers_[i];
192 if (buffer->parent() == current)
193 buffer->SetParent(NULL, gfx::Rect(viewport_pixel_size_));
195 damage_rect_ = damage_rect;
197 return canvas_.get();
200 void CompositorSoftwareOutputDevice::EndPaint(
201 cc::SoftwareFrameData* frame_data) {
202 DCHECK(CalledOnValidThread());
203 DCHECK(frame_data);
205 Buffer* buffer = buffers_[current_index_];
206 frame_data->id = buffer->id();
207 frame_data->size = viewport_pixel_size_;
208 frame_data->damage_rect = damage_rect_;
209 frame_data->bitmap_id = buffer->shared_bitmap_id();
212 void CompositorSoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
213 DCHECK(CalledOnValidThread());
215 if (!id)
216 return;
218 // The reclaimed buffer id might not be among the currently
219 // active buffers if we got a resize event in the mean time.
220 ScopedVector<Buffer>::iterator it =
221 std::find_if(buffers_.begin(), buffers_.end(), CompareById(id));
222 if (it != buffers_.end()) {
223 DCHECK(!(*it)->free());
224 (*it)->SetFree(true);
225 return;
226 } else {
227 it = std::find_if(awaiting_ack_.begin(), awaiting_ack_.end(),
228 CompareById(id));
229 DCHECK(it != awaiting_ack_.end());
230 awaiting_ack_.erase(it);
234 } // namespace content