Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: remoting/host/capturer_win.cc

Issue 7491070: Switch over to using SkRegions to calculate dirty areas. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed up shared lib compile Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/capturer_mac_unittest.cc ('k') | remoting/host/differ.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "remoting/host/capturer.h" 5 #include "remoting/host/capturer.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "remoting/host/capturer_helper.h" 10 #include "remoting/host/capturer_helper.h"
11 #include "remoting/host/differ.h" 11 #include "remoting/host/differ.h"
12 #include "ui/gfx/rect.h"
13 12
14 namespace remoting { 13 namespace remoting {
15 14
16 namespace { 15 namespace {
17 16
18 // CapturerGdi captures 32bit RGB using GDI. 17 // CapturerGdi captures 32bit RGB using GDI.
19 // 18 //
20 // CapturerGdi is double-buffered as required by Capturer. See 19 // CapturerGdi is double-buffered as required by Capturer. See
21 // remoting/host/capturer.h. 20 // remoting/host/capturer.h.
22 class CapturerGdi : public Capturer { 21 class CapturerGdi : public Capturer {
23 public: 22 public:
24 CapturerGdi(); 23 CapturerGdi();
25 virtual ~CapturerGdi(); 24 virtual ~CapturerGdi();
26 25
27 // Capturer interface. 26 // Capturer interface.
28 virtual void ScreenConfigurationChanged() OVERRIDE; 27 virtual void ScreenConfigurationChanged() OVERRIDE;
29 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; 28 virtual media::VideoFrame::Format pixel_format() const OVERRIDE;
30 virtual void ClearInvalidRects() OVERRIDE; 29 virtual void ClearInvalidRegion() OVERRIDE;
31 virtual void InvalidateRects(const InvalidRects& inval_rects) OVERRIDE; 30 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE;
32 virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; 31 virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE;
33 virtual void InvalidateFullScreen() OVERRIDE; 32 virtual void InvalidateFullScreen() OVERRIDE;
34 virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) OVERRIDE; 33 virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback)
34 OVERRIDE;
35 virtual const gfx::Size& size_most_recent() const OVERRIDE; 35 virtual const gfx::Size& size_most_recent() const OVERRIDE;
36 36
37 private: 37 private:
38 struct VideoFrameBuffer { 38 struct VideoFrameBuffer {
39 VideoFrameBuffer(void* data, const gfx::Size& size, int bytes_per_pixel, 39 VideoFrameBuffer(void* data, const gfx::Size& size, int bytes_per_pixel,
40 int bytes_per_row) 40 int bytes_per_row)
41 : data(data), size(size), bytes_per_pixel(bytes_per_pixel), 41 : data(data), size(size), bytes_per_pixel(bytes_per_pixel),
42 bytes_per_row(bytes_per_row) { 42 bytes_per_row(bytes_per_row) {
43 } 43 }
44 VideoFrameBuffer() { 44 VideoFrameBuffer() {
45 data = 0; 45 data = 0;
46 size = gfx::Size(0, 0); 46 size = gfx::Size(0, 0);
47 bytes_per_pixel = 0; 47 bytes_per_pixel = 0;
48 bytes_per_row = 0; 48 bytes_per_row = 0;
49 } 49 }
50 void* data; 50 void* data;
51 gfx::Size size; 51 gfx::Size size;
52 int bytes_per_pixel; 52 int bytes_per_pixel;
53 int bytes_per_row; 53 int bytes_per_row;
54 }; 54 };
55 55
56 // Make sure that the current buffer has the same size as the screen. 56 // Make sure that the current buffer has the same size as the screen.
57 void UpdateBufferCapture(const gfx::Size& size); 57 void UpdateBufferCapture(const gfx::Size& size);
58 58
59 // Allocate memory for a buffer of a given size, freeing any memory previously 59 // Allocate memory for a buffer of a given size, freeing any memory previously
60 // allocated for that buffer. 60 // allocated for that buffer.
61 void ReallocateBuffer(int buffer_index, const gfx::Size& size); 61 void ReallocateBuffer(int buffer_index, const gfx::Size& size);
62 62
63 void CalculateInvalidRects(); 63 void CalculateInvalidRegion();
64 void CaptureRects(const InvalidRects& rects, 64 void CaptureRegion(const SkRegion& region,
65 CaptureCompletedCallback* callback); 65 CaptureCompletedCallback* callback);
66 66
67 void ReleaseBuffers(); 67 void ReleaseBuffers();
68 // Generates an image in the current buffer. 68 // Generates an image in the current buffer.
69 void CaptureImage(); 69 void CaptureImage();
70 70
71 // Gets the current screen size and calls ScreenConfigurationChanged 71 // Gets the current screen size and calls ScreenConfigurationChanged
72 // if the screen size has changed. 72 // if the screen size has changed.
73 void MaybeChangeScreenConfiguration(); 73 void MaybeChangeScreenConfiguration();
74 74
75 // Gets the screen size. 75 // Gets the screen size.
76 gfx::Size GetScreenSize(); 76 gfx::Size GetScreenSize();
77 77
78 // A thread-safe list of invalid rectangles, and the size of the most 78 // A thread-safe list of invalid rectangles, and the size of the most
79 // recently captured screen. 79 // recently captured screen.
80 CapturerHelper helper; 80 CapturerHelper helper_;
81 81
82 // There are two buffers for the screen images, as required by Capturer. 82 // There are two buffers for the screen images, as required by Capturer.
83 static const int kNumBuffers = 2; 83 static const int kNumBuffers = 2;
84 VideoFrameBuffer buffers_[kNumBuffers]; 84 VideoFrameBuffer buffers_[kNumBuffers];
85 85
86 // Gdi specific information about screen. 86 // Gdi specific information about screen.
87 HDC desktop_dc_; 87 HDC desktop_dc_;
88 HDC memory_dc_; 88 HDC memory_dc_;
89 HBITMAP target_bitmap_[kNumBuffers]; 89 HBITMAP target_bitmap_[kNumBuffers];
90 90
91 // The screen size attached to the device contexts through which the screen 91 // The screen size attached to the device contexts through which the screen
92 // is captured. 92 // is captured.
93 gfx::Size dc_size_; 93 gfx::Size dc_size_;
94 94
95 // The current buffer with valid data for reading. 95 // The current buffer with valid data for reading.
96 int current_buffer_; 96 int current_buffer_;
97 97
98 // Format of pixels returned in buffer. 98 // Format of pixels returned in buffer.
99 media::VideoFrame::Format pixel_format_; 99 media::VideoFrame::Format pixel_format_;
100 100
101 // Class to calculate the difference between two screen bitmaps. 101 // Class to calculate the difference between two screen bitmaps.
102 scoped_ptr<Differ> differ_; 102 scoped_ptr<Differ> differ_;
103 103
104 // True if we should force a fullscreen capture.
105 bool capture_fullscreen_;
106
107 DISALLOW_COPY_AND_ASSIGN(CapturerGdi); 104 DISALLOW_COPY_AND_ASSIGN(CapturerGdi);
108 }; 105 };
109 106
110 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. 107 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors.
111 static const int kPixelsPerMeter = 3780; 108 static const int kPixelsPerMeter = 3780;
112 // 32 bit RGBA is 4 bytes per pixel. 109 // 32 bit RGBA is 4 bytes per pixel.
113 static const int kBytesPerPixel = 4; 110 static const int kBytesPerPixel = 4;
114 111
115 CapturerGdi::CapturerGdi() 112 CapturerGdi::CapturerGdi()
116 : desktop_dc_(NULL), 113 : desktop_dc_(NULL),
117 memory_dc_(NULL), 114 memory_dc_(NULL),
118 dc_size_(0, 0), 115 dc_size_(0, 0),
119 current_buffer_(0), 116 current_buffer_(0),
120 pixel_format_(media::VideoFrame::RGB32), 117 pixel_format_(media::VideoFrame::RGB32) {
121 capture_fullscreen_(true) {
122 memset(target_bitmap_, 0, sizeof(target_bitmap_)); 118 memset(target_bitmap_, 0, sizeof(target_bitmap_));
123 memset(buffers_, 0, sizeof(buffers_)); 119 memset(buffers_, 0, sizeof(buffers_));
124 ScreenConfigurationChanged(); 120 ScreenConfigurationChanged();
125 } 121 }
126 122
127 CapturerGdi::~CapturerGdi() { 123 CapturerGdi::~CapturerGdi() {
128 ReleaseBuffers(); 124 ReleaseBuffers();
129 } 125 }
130 126
131 media::VideoFrame::Format CapturerGdi::pixel_format() const { 127 media::VideoFrame::Format CapturerGdi::pixel_format() const {
132 return pixel_format_; 128 return pixel_format_;
133 } 129 }
134 130
135 void CapturerGdi::ClearInvalidRects() { 131 void CapturerGdi::ClearInvalidRegion() {
136 helper.ClearInvalidRects(); 132 helper_.ClearInvalidRegion();
137 } 133 }
138 134
139 void CapturerGdi::InvalidateRects(const InvalidRects& inval_rects) { 135 void CapturerGdi::InvalidateRegion(const SkRegion& invalid_region) {
140 helper.InvalidateRects(inval_rects); 136 helper_.InvalidateRegion(invalid_region);
141 } 137 }
142 138
143 void CapturerGdi::InvalidateScreen(const gfx::Size& size) { 139 void CapturerGdi::InvalidateScreen(const gfx::Size& size) {
144 helper.InvalidateScreen(size); 140 helper_.InvalidateScreen(size);
145 } 141 }
146 142
147 void CapturerGdi::InvalidateFullScreen() { 143 void CapturerGdi::InvalidateFullScreen() {
148 helper.InvalidateFullScreen(); 144 helper_.InvalidateFullScreen();
149 } 145 }
150 146
151 void CapturerGdi::CaptureInvalidRects(CaptureCompletedCallback* callback) { 147 void CapturerGdi::CaptureInvalidRegion(CaptureCompletedCallback* callback) {
152 CalculateInvalidRects(); 148 CalculateInvalidRegion();
153 InvalidRects inval_rects; 149 SkRegion invalid_region;
154 helper.SwapInvalidRects(inval_rects); 150 helper_.SwapInvalidRegion(&invalid_region);
155 CaptureRects(inval_rects, callback); 151 CaptureRegion(invalid_region, callback);
156 } 152 }
157 153
158 const gfx::Size& CapturerGdi::size_most_recent() const { 154 const gfx::Size& CapturerGdi::size_most_recent() const {
159 return helper.size_most_recent(); 155 return helper_.size_most_recent();
160 } 156 }
161 157
162 void CapturerGdi::ReleaseBuffers() { 158 void CapturerGdi::ReleaseBuffers() {
163 for (int i = kNumBuffers - 1; i >= 0; i--) { 159 for (int i = kNumBuffers - 1; i >= 0; i--) {
164 if (target_bitmap_[i]) { 160 if (target_bitmap_[i]) {
165 DeleteObject(target_bitmap_[i]); 161 DeleteObject(target_bitmap_[i]);
166 target_bitmap_[i] = NULL; 162 target_bitmap_[i] = NULL;
167 } 163 }
168 if (buffers_[i].data) { 164 if (buffers_[i].data) {
169 DeleteObject(buffers_[i].data); 165 DeleteObject(buffers_[i].data);
(...skipping 20 matching lines...) Expand all
190 desktop_dc_ = GetDC(GetDesktopWindow()); 186 desktop_dc_ = GetDC(GetDesktopWindow());
191 if (memory_dc_) 187 if (memory_dc_)
192 DeleteDC(memory_dc_); 188 DeleteDC(memory_dc_);
193 memory_dc_ = CreateCompatibleDC(desktop_dc_); 189 memory_dc_ = CreateCompatibleDC(desktop_dc_);
194 dc_size_ = size; 190 dc_size_ = size;
195 } 191 }
196 192
197 // Make sure the current bitmap has the correct dimensions. 193 // Make sure the current bitmap has the correct dimensions.
198 if (size != buffers_[current_buffer_].size) { 194 if (size != buffers_[current_buffer_].size) {
199 ReallocateBuffer(current_buffer_, size); 195 ReallocateBuffer(current_buffer_, size);
200 capture_fullscreen_ = true; 196 InvalidateFullScreen();
201 } 197 }
202 } 198 }
203 199
204 void CapturerGdi::ReallocateBuffer(int buffer_index, const gfx::Size& size) { 200 void CapturerGdi::ReallocateBuffer(int buffer_index, const gfx::Size& size) {
205 // Delete any previously constructed bitmap. 201 // Delete any previously constructed bitmap.
206 if (target_bitmap_[buffer_index]) { 202 if (target_bitmap_[buffer_index]) {
207 DeleteObject(target_bitmap_[buffer_index]); 203 DeleteObject(target_bitmap_[buffer_index]);
208 target_bitmap_[buffer_index] = NULL; 204 target_bitmap_[buffer_index] = NULL;
209 } 205 }
210 if (buffers_[buffer_index].data) { 206 if (buffers_[buffer_index].data) {
(...skipping 25 matching lines...) Expand all
236 CreateDIBSection(desktop_dc_, &bmi, DIB_RGB_COLORS, 232 CreateDIBSection(desktop_dc_, &bmi, DIB_RGB_COLORS,
237 static_cast<void**>(&buffers_[buffer_index].data), 233 static_cast<void**>(&buffers_[buffer_index].data),
238 NULL, 0); 234 NULL, 0);
239 buffers_[buffer_index].size = gfx::Size(bmi.bmiHeader.biWidth, 235 buffers_[buffer_index].size = gfx::Size(bmi.bmiHeader.biWidth,
240 std::abs(bmi.bmiHeader.biHeight)); 236 std::abs(bmi.bmiHeader.biHeight));
241 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8; 237 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8;
242 buffers_[buffer_index].bytes_per_row = 238 buffers_[buffer_index].bytes_per_row =
243 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight); 239 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight);
244 } 240 }
245 241
246 void CapturerGdi::CalculateInvalidRects() { 242 void CapturerGdi::CalculateInvalidRegion() {
247 CaptureImage(); 243 CaptureImage();
248 244
249 const VideoFrameBuffer& current = buffers_[current_buffer_]; 245 const VideoFrameBuffer& current = buffers_[current_buffer_];
250 if (helper.IsCaptureFullScreen(current.size))
251 capture_fullscreen_ = true;
252
253 if (capture_fullscreen_) {
254 InvalidateScreen(current.size);
255 capture_fullscreen_ = false;
256 return;
257 }
258 246
259 // Find the previous and current screens. 247 // Find the previous and current screens.
260 int prev_buffer_id = current_buffer_ - 1; 248 int prev_buffer_id = current_buffer_ - 1;
261 if (prev_buffer_id < 0) { 249 if (prev_buffer_id < 0) {
262 prev_buffer_id = kNumBuffers - 1; 250 prev_buffer_id = kNumBuffers - 1;
263 } 251 }
264 const VideoFrameBuffer& prev = buffers_[prev_buffer_id]; 252 const VideoFrameBuffer& prev = buffers_[prev_buffer_id];
265 253
266 // Maybe the previous and current screens can't be differenced. 254 // Maybe the previous and current screens can't be differenced.
267 if ((current.size != prev.size) || 255 if ((current.size != prev.size) ||
268 (current.bytes_per_pixel != prev.bytes_per_pixel) || 256 (current.bytes_per_pixel != prev.bytes_per_pixel) ||
269 (current.bytes_per_row != prev.bytes_per_row)) { 257 (current.bytes_per_row != prev.bytes_per_row)) {
270 InvalidateScreen(current.size); 258 InvalidateScreen(current.size);
271 return; 259 return;
272 } 260 }
273 261
274 // Make sure the differencer is set up correctly for these previous and 262 // Make sure the differencer is set up correctly for these previous and
275 // current screens. 263 // current screens.
276 if (!differ_.get() || 264 if (!differ_.get() ||
277 (differ_->width() != current.size.width()) || 265 (differ_->width() != current.size.width()) ||
278 (differ_->height() != current.size.height()) || 266 (differ_->height() != current.size.height()) ||
279 (differ_->bytes_per_pixel() != current.bytes_per_pixel) || 267 (differ_->bytes_per_pixel() != current.bytes_per_pixel) ||
280 (differ_->bytes_per_row() != current.bytes_per_row)) { 268 (differ_->bytes_per_row() != current.bytes_per_row)) {
281 differ_.reset(new Differ(current.size.width(), current.size.height(), 269 differ_.reset(new Differ(current.size.width(), current.size.height(),
282 current.bytes_per_pixel, current.bytes_per_row)); 270 current.bytes_per_pixel, current.bytes_per_row));
283 } 271 }
284 272
285 InvalidRects rects; 273 SkRegion region;
286 differ_->CalcDirtyRects(prev.data, current.data, &rects); 274 differ_->CalcDirtyRegion(prev.data, current.data, &region);
287 275
288 InvalidateRects(rects); 276 InvalidateRegion(region);
289 } 277 }
290 278
291 void CapturerGdi::CaptureRects(const InvalidRects& rects, 279 void CapturerGdi::CaptureRegion(const SkRegion& region,
292 CaptureCompletedCallback* callback) { 280 CaptureCompletedCallback* callback) {
293 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); 281 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback);
294 282
295 const VideoFrameBuffer& buffer = buffers_[current_buffer_]; 283 const VideoFrameBuffer& buffer = buffers_[current_buffer_];
296 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; 284 current_buffer_ = (current_buffer_ + 1) % kNumBuffers;
297 285
298 DataPlanes planes; 286 DataPlanes planes;
299 planes.data[0] = static_cast<uint8*>(buffer.data); 287 planes.data[0] = static_cast<uint8*>(buffer.data);
300 planes.strides[0] = buffer.bytes_per_row; 288 planes.strides[0] = buffer.bytes_per_row;
301 289
302 scoped_refptr<CaptureData> data(new CaptureData(planes, 290 scoped_refptr<CaptureData> data(new CaptureData(planes,
303 buffer.size, 291 buffer.size,
304 pixel_format_)); 292 pixel_format_));
305 data->mutable_dirty_rects() = rects; 293 data->mutable_dirty_region() = region;
306 294
307 helper.set_size_most_recent(data->size()); 295 helper_.set_size_most_recent(data->size());
308 296
309 callback->Run(data); 297 callback->Run(data);
310 } 298 }
311 299
312 void CapturerGdi::CaptureImage() { 300 void CapturerGdi::CaptureImage() {
313 // Make sure the structures we use to capture the image have the correct size. 301 // Make sure the structures we use to capture the image have the correct size.
314 UpdateBufferCapture(GetScreenSize()); 302 UpdateBufferCapture(GetScreenSize());
315 303
316 // Select the target bitmap into the memory dc. 304 // Select the target bitmap into the memory dc.
317 SelectObject(memory_dc_, target_bitmap_[current_buffer_]); 305 SelectObject(memory_dc_, target_bitmap_[current_buffer_]);
(...skipping 10 matching lines...) Expand all
328 } 316 }
329 317
330 } // namespace 318 } // namespace
331 319
332 // static 320 // static
333 Capturer* Capturer::Create() { 321 Capturer* Capturer::Create() {
334 return new CapturerGdi(); 322 return new CapturerGdi();
335 } 323 }
336 324
337 } // namespace remoting 325 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/capturer_mac_unittest.cc ('k') | remoting/host/differ.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698