OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/gpu/compositor_software_output_device.h" | 5 #include "content/renderer/gpu/compositor_software_output_device.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "cc/output/software_frame_data.h" | 8 #include "cc/output/software_frame_data.h" |
9 #include "third_party/skia/include/core/SkCanvas.h" | 9 #include "third_party/skia/include/core/SkCanvas.h" |
10 #include "third_party/skia/include/core/SkDevice.h" | 10 #include "third_party/skia/include/core/SkDevice.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 return dib->id() == id_; | 25 return dib->id() == id_; |
26 } | 26 } |
27 | 27 |
28 private: | 28 private: |
29 TransportDIB::Id id_; | 29 TransportDIB::Id id_; |
30 }; | 30 }; |
31 | 31 |
32 } // namespace | 32 } // namespace |
33 | 33 |
34 CompositorSoftwareOutputDevice::CompositorSoftwareOutputDevice() | 34 CompositorSoftwareOutputDevice::CompositorSoftwareOutputDevice() |
35 : front_buffer_(0), | 35 : front_buffer_(-1), |
36 last_buffer_(-1), | |
37 num_free_buffers_(0), | 36 num_free_buffers_(0), |
38 sequence_num_(0) { | 37 sequence_num_(0) { |
39 DetachFromThread(); | 38 DetachFromThread(); |
40 } | 39 } |
41 | 40 |
42 CompositorSoftwareOutputDevice::~CompositorSoftwareOutputDevice() { | 41 CompositorSoftwareOutputDevice::~CompositorSoftwareOutputDevice() { |
43 DCHECK(CalledOnValidThread()); | 42 DCHECK(CalledOnValidThread()); |
44 } | 43 } |
45 | 44 |
46 TransportDIB* CompositorSoftwareOutputDevice::CreateDIB() { | 45 TransportDIB* CompositorSoftwareOutputDevice::CreateDIB() { |
47 const size_t size = 4 * viewport_size_.GetArea(); | 46 const size_t size = 4 * viewport_size_.GetArea(); |
48 TransportDIB* dib = TransportDIB::Create(size, sequence_num_++); | 47 TransportDIB* dib = TransportDIB::Create(size, sequence_num_++); |
49 CHECK(dib); | 48 CHECK(dib); |
50 bool success = dib->Map(); | 49 bool success = dib->Map(); |
51 CHECK(success); | 50 CHECK(success); |
52 return dib; | 51 return dib; |
53 } | 52 } |
54 | 53 |
55 void CompositorSoftwareOutputDevice::Resize(gfx::Size viewport_size) { | 54 void CompositorSoftwareOutputDevice::Resize(gfx::Size viewport_size) { |
56 DCHECK(CalledOnValidThread()); | 55 DCHECK(CalledOnValidThread()); |
57 | 56 |
58 // Reset last_buffer_ so that we don't copy over old damage. | |
59 last_buffer_ = -1; | |
60 | |
61 if (viewport_size_ == viewport_size) | 57 if (viewport_size_ == viewport_size) |
62 return; | 58 return; |
63 viewport_size_ = viewport_size; | |
64 | 59 |
65 // Keep non-acked dibs open. | 60 // Keep non-ACKed dibs open. |
66 for (size_t i = 0; i < dibs_.size() - num_free_buffers_; ++i) { | 61 int first_non_free = front_buffer_ + num_free_buffers_ + 1; |
67 size_t index = (front_buffer_ + num_free_buffers_ + i) % dibs_.size(); | 62 int num_non_free = dibs_.size() - num_free_buffers_; |
| 63 for (int i = 0; i < num_non_free; ++i) { |
| 64 int index = (first_non_free + i) % dibs_.size(); |
68 awaiting_ack_.push_back(dibs_[index]); | 65 awaiting_ack_.push_back(dibs_[index]); |
69 dibs_[index] = NULL; | 66 dibs_[index] = NULL; |
70 } | 67 } |
71 | 68 |
72 dibs_.clear(); | 69 dibs_.clear(); |
73 front_buffer_ = 0; | 70 front_buffer_ = -1; |
74 num_free_buffers_ = 0; | 71 num_free_buffers_ = 0; |
| 72 viewport_size_ = viewport_size; |
75 } | 73 } |
76 | 74 |
77 SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(gfx::Rect damage_rect) { | 75 SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(gfx::Rect damage_rect) { |
78 DCHECK(CalledOnValidThread()); | 76 DCHECK(CalledOnValidThread()); |
79 | 77 |
| 78 gfx::Rect last_damage_rect = damage_rect_; |
| 79 damage_rect_ = damage_rect; |
| 80 |
| 81 int last_buffer = front_buffer_; |
80 if (num_free_buffers_ == 0) { | 82 if (num_free_buffers_ == 0) { |
81 dibs_.insert(dibs_.begin() + front_buffer_, CreateDIB()); | 83 dibs_.insert(dibs_.begin() + (front_buffer_ + 1), CreateDIB()); |
82 num_free_buffers_++; | 84 last_damage_rect = gfx::Rect(viewport_size_); |
| 85 } else { |
| 86 --num_free_buffers_; |
83 } | 87 } |
| 88 front_buffer_ = (front_buffer_ + 1) % dibs_.size(); |
84 | 89 |
85 TransportDIB* front_dib = dibs_[front_buffer_]; | 90 TransportDIB* front_dib = dibs_[front_buffer_]; |
86 DCHECK(front_dib); | 91 DCHECK(front_dib); |
87 DCHECK(front_dib->memory()); | 92 DCHECK(front_dib->memory()); |
88 | 93 |
89 // Set up a canvas for the front_dib. | 94 // Set up a canvas for the current front buffer. |
90 bitmap_.setConfig(SkBitmap::kARGB_8888_Config, | 95 bitmap_.setConfig(SkBitmap::kARGB_8888_Config, |
91 viewport_size_.width(), | 96 viewport_size_.width(), |
92 viewport_size_.height()); | 97 viewport_size_.height()); |
93 bitmap_.setPixels(front_dib->memory()); | 98 bitmap_.setPixels(front_dib->memory()); |
94 device_ = skia::AdoptRef(new SkDevice(bitmap_)); | 99 device_ = skia::AdoptRef(new SkDevice(bitmap_)); |
95 canvas_ = skia::AdoptRef(new SkCanvas(device_.get())); | 100 canvas_ = skia::AdoptRef(new SkCanvas(device_.get())); |
96 | 101 |
97 // Copy damage_rect_ from last_buffer_ to front_buffer_. | 102 // Copy over previous damage. |
98 if (last_buffer_ != -1 && !damage_rect.Contains(damage_rect_)) { | 103 if (last_buffer != -1) { |
99 TransportDIB* last_dib = dibs_[last_buffer_]; | 104 TransportDIB* last_dib = dibs_[last_buffer]; |
100 SkBitmap back_bitmap; | 105 SkBitmap back_bitmap; |
101 back_bitmap.setConfig(SkBitmap::kARGB_8888_Config, | 106 back_bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
102 viewport_size_.width(), | 107 viewport_size_.width(), |
103 viewport_size_.height()); | 108 viewport_size_.height()); |
104 back_bitmap.setPixels(last_dib->memory()); | 109 back_bitmap.setPixels(last_dib->memory()); |
105 | 110 |
106 SkRect last_damage = gfx::RectToSkRect(damage_rect_); | 111 SkRegion region(RectToSkIRect(last_damage_rect)); |
107 canvas_->drawBitmapRectToRect(back_bitmap, &last_damage, last_damage, NULL); | 112 region.op(RectToSkIRect(damage_rect), SkRegion::kDifference_Op); |
| 113 for (SkRegion::Iterator it(region); !it.done(); it.next()) { |
| 114 const SkIRect& src_rect = it.rect(); |
| 115 SkRect dst_rect = SkRect::Make(src_rect); |
| 116 canvas_->drawBitmapRect(back_bitmap, &src_rect, dst_rect, NULL); |
| 117 } |
108 } | 118 } |
109 damage_rect_ = damage_rect; | |
110 | 119 |
111 return canvas_.get(); | 120 return canvas_.get(); |
112 } | 121 } |
113 | 122 |
114 void CompositorSoftwareOutputDevice::EndPaint( | 123 void CompositorSoftwareOutputDevice::EndPaint( |
115 cc::SoftwareFrameData* frame_data) { | 124 cc::SoftwareFrameData* frame_data) { |
116 DCHECK(CalledOnValidThread()); | 125 DCHECK(CalledOnValidThread()); |
117 | 126 |
118 if (frame_data) { | 127 if (frame_data) { |
119 frame_data->size = viewport_size_; | 128 frame_data->size = viewport_size_; |
120 frame_data->damage_rect = damage_rect_; | 129 frame_data->damage_rect = damage_rect_; |
121 frame_data->dib_id = dibs_[front_buffer_]->id(); | 130 frame_data->dib_id = dibs_[front_buffer_]->id(); |
122 } | 131 } |
123 | |
124 last_buffer_ = front_buffer_; | |
125 front_buffer_ = (front_buffer_ + 1) % dibs_.size(); | |
126 --num_free_buffers_; | |
127 DCHECK_GE(num_free_buffers_, 0); | |
128 } | 132 } |
129 | 133 |
130 void CompositorSoftwareOutputDevice::ReclaimDIB(const TransportDIB::Id& id) { | 134 void CompositorSoftwareOutputDevice::ReclaimDIB(const TransportDIB::Id& id) { |
131 DCHECK(CalledOnValidThread()); | 135 DCHECK(CalledOnValidThread()); |
132 | 136 |
133 // The reclaimed handle might not be among the currently | 137 if (!TransportDIB::is_valid_id(id)) |
| 138 return; |
| 139 |
| 140 // The reclaimed dib id might not be among the currently |
134 // active dibs if we got a resize event in the mean time. | 141 // active dibs if we got a resize event in the mean time. |
135 ScopedVector<TransportDIB>::iterator it = | 142 ScopedVector<TransportDIB>::iterator it = |
136 std::find_if(dibs_.begin(), dibs_.end(), CompareById(id)); | 143 std::find_if(dibs_.begin(), dibs_.end(), CompareById(id)); |
137 if (it != dibs_.end()) { | 144 if (it != dibs_.end()) { |
138 ++num_free_buffers_; | 145 ++num_free_buffers_; |
| 146 DCHECK_LE(static_cast<size_t>(num_free_buffers_), dibs_.size()); |
| 147 return; |
139 } else { | 148 } else { |
140 it = std::find_if(awaiting_ack_.begin(), | 149 it = std::find_if(awaiting_ack_.begin(), awaiting_ack_.end(), |
141 awaiting_ack_.end(), | |
142 CompareById(id)); | 150 CompareById(id)); |
| 151 DCHECK(it != awaiting_ack_.end()); |
143 awaiting_ack_.erase(it); | 152 awaiting_ack_.erase(it); |
144 } | 153 } |
145 | |
146 DCHECK_LE(static_cast<size_t>(num_free_buffers_), dibs_.size()); | |
147 } | 154 } |
148 | 155 |
149 } // namespace content | 156 } // namespace content |
OLD | NEW |