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

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

Issue 10699046: Support remoting of all monitors on multi-monitor Windows systems (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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 | « no previous file | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/file_path.h" 9 #include "base/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 void UpdateBufferCapture(const SkISize& size); 81 void UpdateBufferCapture(const SkISize& size);
82 82
83 // Allocate memory for a buffer of a given size, freeing any memory previously 83 // Allocate memory for a buffer of a given size, freeing any memory previously
84 // allocated for that buffer. 84 // allocated for that buffer.
85 void ReallocateBuffer(int buffer_index, const SkISize& size); 85 void ReallocateBuffer(int buffer_index, const SkISize& size);
86 86
87 void CalculateInvalidRegion(); 87 void CalculateInvalidRegion();
88 void CaptureRegion(const SkRegion& region, 88 void CaptureRegion(const SkRegion& region,
89 const CaptureCompletedCallback& callback); 89 const CaptureCompletedCallback& callback);
90 90
91 void ReleaseBuffers(); 91 // Release all GDI resources, including bitmaps and device contexts.
92 void ReleaseGdiResources();
93
92 // Generates an image in the current buffer. 94 // Generates an image in the current buffer.
93 void CaptureImage(); 95 void CaptureImage();
94 96
95 // Expand the cursor shape to add a white outline for visibility against 97 // Expand the cursor shape to add a white outline for visibility against
96 // dark backgrounds. 98 // dark backgrounds.
97 void AddCursorOutline(int width, int height, uint32* dst); 99 void AddCursorOutline(int width, int height, uint32* dst);
98 100
99 // Capture the current cursor shape. 101 // Capture the current cursor shape.
100 void CaptureCursor(); 102 void CaptureCursor();
101 103
(...skipping 12 matching lines...) Expand all
114 // message when the shape has changed. 116 // message when the shape has changed.
115 scoped_array<uint8> last_cursor_; 117 scoped_array<uint8> last_cursor_;
116 SkISize last_cursor_size_; 118 SkISize last_cursor_size_;
117 119
118 // There are two buffers for the screen images, as required by Capturer. 120 // There are two buffers for the screen images, as required by Capturer.
119 static const int kNumBuffers = 2; 121 static const int kNumBuffers = 2;
120 VideoFrameBuffer buffers_[kNumBuffers]; 122 VideoFrameBuffer buffers_[kNumBuffers];
121 123
122 ScopedThreadDesktopWin desktop_; 124 ScopedThreadDesktopWin desktop_;
123 125
124 // Gdi specific information about screen. 126 // GDI resources used for screen capture.
125 HWND desktop_window_;
126 HDC desktop_dc_; 127 HDC desktop_dc_;
alexeypa (please no reviews) 2012/07/02 15:50:11 nit: There are ScopedGetDC and ScopedCreateDC avai
Wez 2012/07/03 20:56:26 Done.
127 HDC memory_dc_; 128 HDC memory_dc_;
128 HBITMAP target_bitmap_[kNumBuffers]; 129 HBITMAP target_bitmap_[kNumBuffers];
alexeypa (please no reviews) 2012/07/02 15:50:11 nit: ScopedBitmap can be used here.
Wez 2012/07/03 20:56:26 Done.
129 130
130 // The screen size attached to the device contexts through which the screen 131 // The screen size attached to the device contexts through which the screen
131 // is captured. 132 // is captured.
132 SkISize dc_size_; 133 SkISize dc_size_;
133 134
134 // The current buffer with valid data for reading. 135 // The current buffer with valid data for reading.
135 int current_buffer_; 136 int current_buffer_;
136 137
137 // Format of pixels returned in buffer. 138 // Format of pixels returned in buffer.
138 media::VideoFrame::Format pixel_format_; 139 media::VideoFrame::Format pixel_format_;
139 140
140 // Class to calculate the difference between two screen bitmaps. 141 // Class to calculate the difference between two screen bitmaps.
141 scoped_ptr<Differ> differ_; 142 scoped_ptr<Differ> differ_;
142 143
143 base::ScopedNativeLibrary dwmapi_library_; 144 base::ScopedNativeLibrary dwmapi_library_;
144 DwmEnableCompositionFunc composition_func_; 145 DwmEnableCompositionFunc composition_func_;
145 146
146 DISALLOW_COPY_AND_ASSIGN(CapturerGdi); 147 DISALLOW_COPY_AND_ASSIGN(CapturerGdi);
147 }; 148 };
148 149
149 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. 150 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors.
150 static const int kPixelsPerMeter = 3780; 151 static const int kPixelsPerMeter = 3780;
151 // 32 bit RGBA is 4 bytes per pixel. 152 // 32 bit RGBA is 4 bytes per pixel.
152 static const int kBytesPerPixel = 4; 153 static const int kBytesPerPixel = 4;
153 154
154 CapturerGdi::CapturerGdi() 155 CapturerGdi::CapturerGdi()
155 : last_cursor_size_(SkISize::Make(0, 0)), 156 : last_cursor_size_(SkISize::Make(0, 0)),
156 desktop_window_(NULL),
157 desktop_dc_(NULL), 157 desktop_dc_(NULL),
158 memory_dc_(NULL), 158 memory_dc_(NULL),
159 dc_size_(SkISize::Make(0, 0)), 159 dc_size_(SkISize::Make(0, 0)),
160 current_buffer_(0), 160 current_buffer_(0),
161 pixel_format_(media::VideoFrame::RGB32), 161 pixel_format_(media::VideoFrame::RGB32),
162 composition_func_(NULL) { 162 composition_func_(NULL) {
163 memset(target_bitmap_, 0, sizeof(target_bitmap_)); 163 memset(target_bitmap_, 0, sizeof(target_bitmap_));
164 memset(buffers_, 0, sizeof(buffers_)); 164 memset(buffers_, 0, sizeof(buffers_));
165 ScreenConfigurationChanged(); 165 ScreenConfigurationChanged();
166 } 166 }
167 167
168 CapturerGdi::~CapturerGdi() { 168 CapturerGdi::~CapturerGdi() {
169 ReleaseBuffers(); 169 ReleaseGdiResources();
170 } 170 }
171 171
172 media::VideoFrame::Format CapturerGdi::pixel_format() const { 172 media::VideoFrame::Format CapturerGdi::pixel_format() const {
173 return pixel_format_; 173 return pixel_format_;
174 } 174 }
175 175
176 void CapturerGdi::ClearInvalidRegion() { 176 void CapturerGdi::ClearInvalidRegion() {
177 helper_.ClearInvalidRegion(); 177 helper_.ClearInvalidRegion();
178 } 178 }
179 179
(...skipping 21 matching lines...) Expand all
201 CaptureRegion(invalid_region, callback); 201 CaptureRegion(invalid_region, callback);
202 202
203 // Check for cursor shape update. 203 // Check for cursor shape update.
204 CaptureCursor(); 204 CaptureCursor();
205 } 205 }
206 206
207 const SkISize& CapturerGdi::size_most_recent() const { 207 const SkISize& CapturerGdi::size_most_recent() const {
208 return helper_.size_most_recent(); 208 return helper_.size_most_recent();
209 } 209 }
210 210
211 void CapturerGdi::ReleaseBuffers() { 211 void CapturerGdi::ReleaseGdiResources() {
212 for (int i = kNumBuffers - 1; i >= 0; i--) { 212 for (int i = kNumBuffers - 1; i >= 0; i--) {
213 if (target_bitmap_[i]) { 213 if (target_bitmap_[i]) {
214 DeleteObject(target_bitmap_[i]); 214 DeleteObject(target_bitmap_[i]);
215 target_bitmap_[i] = NULL; 215 target_bitmap_[i] = NULL;
216 } 216 }
217 if (buffers_[i].data) { 217 if (buffers_[i].data) {
218 DeleteObject(buffers_[i].data); 218 DeleteObject(buffers_[i].data);
219 buffers_[i].data = NULL; 219 buffers_[i].data = NULL;
220 } 220 }
221 } 221 }
222 222
223 if (desktop_dc_) { 223 if (desktop_dc_) {
224 ReleaseDC(desktop_window_, desktop_dc_); 224 ReleaseDC(NULL, desktop_dc_);
225 desktop_window_ = NULL;
226 desktop_dc_ = NULL; 225 desktop_dc_ = NULL;
227 } 226 }
228 227
229 if (memory_dc_) { 228 if (memory_dc_) {
230 DeleteDC(memory_dc_); 229 DeleteDC(memory_dc_);
231 memory_dc_ = NULL; 230 memory_dc_ = NULL;
232 } 231 }
233 } 232 }
234 233
235 void CapturerGdi::Start( 234 void CapturerGdi::Start(
(...skipping 29 matching lines...) Expand all
265 void CapturerGdi::ScreenConfigurationChanged() { 264 void CapturerGdi::ScreenConfigurationChanged() {
266 // We poll for screen configuration changes, so ignore notifications. 265 // We poll for screen configuration changes, so ignore notifications.
267 } 266 }
268 267
269 void CapturerGdi::UpdateBufferCapture(const SkISize& size) { 268 void CapturerGdi::UpdateBufferCapture(const SkISize& size) {
270 // Switch to the desktop receiving user input if different from the current 269 // Switch to the desktop receiving user input if different from the current
271 // one. 270 // one.
272 scoped_ptr<DesktopWin> input_desktop = DesktopWin::GetInputDesktop(); 271 scoped_ptr<DesktopWin> input_desktop = DesktopWin::GetInputDesktop();
273 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 272 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
274 // Release GDI resources otherwise SetThreadDesktop will fail. 273 // Release GDI resources otherwise SetThreadDesktop will fail.
275 if (desktop_dc_) { 274 ReleaseGdiResources();
276 ReleaseDC(desktop_window_, desktop_dc_);
277 desktop_window_ = NULL;
278 desktop_dc_ = NULL;
279 }
280
281 if (memory_dc_) {
282 DeleteDC(memory_dc_);
283 memory_dc_ = NULL;
284 }
285
286 ReleaseBuffers();
287 275
288 // If SetThreadDesktop() fails, the thread is still assigned a desktop. 276 // If SetThreadDesktop() fails, the thread is still assigned a desktop.
289 // So we can continue capture screen bits, just from a diffented desktop. 277 // So we can continue capture screen bits, just from a diffented desktop.
290 desktop_.SetThreadDesktop(input_desktop.Pass()); 278 desktop_.SetThreadDesktop(input_desktop.Pass());
291 } 279 }
292 280
293 // Make sure the DCs have the correct dimensions. 281 // If the display dimensions have changed then recreate GDI resources.
294 if (size != dc_size_) { 282 if (size != dc_size_) {
295 // TODO(simonmorris): screen dimensions changing isn't equivalent to needing 283 ReleaseGdiResources();
296 // a new DC, but it's good enough for now.
297 if (desktop_dc_) {
298 ReleaseDC(desktop_window_, desktop_dc_);
299 desktop_window_ = NULL;
300 desktop_dc_ = NULL;
301 }
302
303 if (memory_dc_) {
304 DeleteDC(memory_dc_);
305 memory_dc_ = NULL;
306 }
307 } 284 }
308 285
286 // Create GDI device contexts to capture from the desktop into memory.
309 if (desktop_dc_ == NULL) { 287 if (desktop_dc_ == NULL) {
310 DCHECK(desktop_window_ == NULL);
311 DCHECK(memory_dc_ == NULL); 288 DCHECK(memory_dc_ == NULL);
289 DCHECK(target_bitmap_[0] == NULL);
290 DCHECK(buffers_[0].data == NULL);
312 291
313 desktop_window_ = GetDesktopWindow(); 292 desktop_dc_ = GetDC(NULL);
314 desktop_dc_ = GetDC(desktop_window_);
315 memory_dc_ = CreateCompatibleDC(desktop_dc_); 293 memory_dc_ = CreateCompatibleDC(desktop_dc_);
316 dc_size_ = size; 294 dc_size_ = size;
317 } 295 }
318 296
319 // Make sure the current bitmap has the correct dimensions. 297 // Make sure the current bitmap has the correct dimensions.
320 if (buffers_[current_buffer_].data == NULL || 298 if (buffers_[current_buffer_].data == NULL ||
321 size != buffers_[current_buffer_].size) { 299 size != buffers_[current_buffer_].size) {
322 ReallocateBuffer(current_buffer_, size); 300 ReallocateBuffer(current_buffer_, size);
alexeypa (please no reviews) 2012/07/02 15:50:11 nit: We could separate allocation and deletion of
Wez 2012/07/03 20:56:26 As discussed, we can't just tear down the buffers
323 InvalidateFullScreen(); 301 InvalidateFullScreen();
324 } 302 }
325 } 303 }
326 304
327 void CapturerGdi::ReallocateBuffer(int buffer_index, const SkISize& size) { 305 void CapturerGdi::ReallocateBuffer(int buffer_index, const SkISize& size) {
328 // Delete any previously constructed bitmap. 306 // Delete any previously constructed bitmap.
329 if (target_bitmap_[buffer_index]) { 307 if (target_bitmap_[buffer_index]) {
330 DeleteObject(target_bitmap_[buffer_index]); 308 DeleteObject(target_bitmap_[buffer_index]);
331 target_bitmap_[buffer_index] = NULL; 309 target_bitmap_[buffer_index] = NULL;
332 } 310 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 402
425 void CapturerGdi::CaptureImage() { 403 void CapturerGdi::CaptureImage() {
426 // Make sure the structures we use to capture the image have the correct size. 404 // Make sure the structures we use to capture the image have the correct size.
427 UpdateBufferCapture(GetScreenSize()); 405 UpdateBufferCapture(GetScreenSize());
428 406
429 // Select the target bitmap into the memory dc. 407 // Select the target bitmap into the memory dc.
430 SelectObject(memory_dc_, target_bitmap_[current_buffer_]); 408 SelectObject(memory_dc_, target_bitmap_[current_buffer_]);
431 409
432 // And then copy the rect from desktop to memory. 410 // And then copy the rect from desktop to memory.
433 BitBlt(memory_dc_, 0, 0, buffers_[current_buffer_].size.width(), 411 BitBlt(memory_dc_, 0, 0, buffers_[current_buffer_].size.width(),
434 buffers_[current_buffer_].size.height(), desktop_dc_, 0, 0, 412 buffers_[current_buffer_].size.height(), desktop_dc_,
413 GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
alexeypa (please no reviews) 2012/07/02 15:50:11 There is a race between this code and CapturerGdi:
Wez 2012/07/03 20:56:26 There's no race as such, since the width & height
435 SRCCOPY | CAPTUREBLT); 414 SRCCOPY | CAPTUREBLT);
436 } 415 }
437 416
438 void CapturerGdi::AddCursorOutline(int width, int height, uint32* dst) { 417 void CapturerGdi::AddCursorOutline(int width, int height, uint32* dst) {
439 for (int y = 0; y < height; y++) { 418 for (int y = 0; y < height; y++) {
440 for (int x = 0; x < width; x++) { 419 for (int x = 0; x < width; x++) {
441 // If this is a transparent pixel (bgr == 0 and alpha = 0), check the 420 // If this is a transparent pixel (bgr == 0 and alpha = 0), check the
442 // neighbor pixels to see if this should be changed to an outline pixel. 421 // neighbor pixels to see if this should be changed to an outline pixel.
443 if (*dst == kPixelBgraTransparent) { 422 if (*dst == kPixelBgraTransparent) {
444 // Change to white pixel if any neighbors (top, bottom, left, right) 423 // Change to white pixel if any neighbors (top, bottom, left, right)
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 581
603 // Record the last cursor image that we sent to the client. 582 // Record the last cursor image that we sent to the client.
604 last_cursor_.reset(new uint8[data_size]); 583 last_cursor_.reset(new uint8[data_size]);
605 memcpy(last_cursor_.get(), cursor_dst_data, data_size); 584 memcpy(last_cursor_.get(), cursor_dst_data, data_size);
606 last_cursor_size_ = SkISize::Make(width, height); 585 last_cursor_size_ = SkISize::Make(width, height);
607 586
608 cursor_shape_changed_callback_.Run(cursor_proto.Pass()); 587 cursor_shape_changed_callback_.Run(cursor_proto.Pass());
609 } 588 }
610 589
611 SkISize CapturerGdi::GetScreenSize() { 590 SkISize CapturerGdi::GetScreenSize() {
612 return SkISize::Make(GetSystemMetrics(SM_CXSCREEN), 591 return SkISize::Make(GetSystemMetrics(SM_CXVIRTUALSCREEN),
613 GetSystemMetrics(SM_CYSCREEN)); 592 GetSystemMetrics(SM_CYVIRTUALSCREEN));
614 } 593 }
615 594
616 } // namespace 595 } // namespace
617 596
618 // static 597 // static
619 Capturer* Capturer::Create() { 598 Capturer* Capturer::Create() {
620 return new CapturerGdi(); 599 return new CapturerGdi();
621 } 600 }
622 601
623 } // namespace remoting 602 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698