OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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. |
| 4 |
| 5 #include "remoting/host/capturer_gdi.h" |
| 6 |
| 7 #include "gfx/rect.h" |
| 8 |
| 9 namespace remoting { |
| 10 |
| 11 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. |
| 12 static const int kPixelsPerMeter = 3780; |
| 13 // 24 bit RGB is 3 bytes per pixel. |
| 14 static const int kBytesPerPixel = 3; |
| 15 |
| 16 CapturerGdi::CapturerGdi() |
| 17 : initialized_(false) { |
| 18 } |
| 19 |
| 20 CapturerGdi::~CapturerGdi() { |
| 21 if (initialized_) { |
| 22 for (int i = kNumBuffers - 1; i >= 0; i--) { |
| 23 DeleteObject(target_bitmap_[i]); |
| 24 } |
| 25 } |
| 26 } |
| 27 |
| 28 void CapturerGdi::CaptureFullScreen(Task* done_task) { |
| 29 dirty_rects_.clear(); |
| 30 |
| 31 CaptureImage(); |
| 32 dirty_rects_.push_back(gfx::Rect(width_, height_)); |
| 33 |
| 34 FinishCapture(done_task); |
| 35 } |
| 36 |
| 37 void CapturerGdi::CaptureDirtyRects(Task* done_task) { |
| 38 dirty_rects_.clear(); |
| 39 |
| 40 CaptureImage(); |
| 41 // TODO(garykac): Diff old/new images and generate |dirty_rects_|. |
| 42 // Currently, this just marks the entire screen as dirty. |
| 43 dirty_rects_.push_back(gfx::Rect(width_, height_)); |
| 44 |
| 45 FinishCapture(done_task); |
| 46 } |
| 47 |
| 48 void CapturerGdi::CaptureRect(const gfx::Rect& rect, Task* done_task) { |
| 49 dirty_rects_.clear(); |
| 50 |
| 51 CaptureImage(); |
| 52 dirty_rects_.push_back(rect); |
| 53 |
| 54 FinishCapture(done_task); |
| 55 } |
| 56 |
| 57 void CapturerGdi::GetData(const uint8* planes[]) const { |
| 58 planes[0] = static_cast<const uint8*>(buffers_[current_buffer_]); |
| 59 planes[1] = planes[2] = NULL; |
| 60 } |
| 61 |
| 62 void CapturerGdi::GetDataStride(int strides[]) const { |
| 63 // Only the first plane has data. |
| 64 strides[0] = bytes_per_row_; |
| 65 strides[1] = strides[2] = 0; |
| 66 } |
| 67 |
| 68 int CapturerGdi::GetWidth() const { |
| 69 if (!width_) |
| 70 width_ = GetSystemMetrics(SM_CXSCREEN); |
| 71 return width_; |
| 72 } |
| 73 |
| 74 int CapturerGdi::GetHeight() const { |
| 75 if (!height_) |
| 76 height_ = GetSystemMetrics(SM_CYSCREEN); |
| 77 return height_; |
| 78 } |
| 79 |
| 80 // TODO(fbarchard): handle error cases. |
| 81 void CapturerGdi::InitializeBuffers() { |
| 82 desktop_dc_ = GetDC(GetDesktopWindow()); |
| 83 memory_dc_ = CreateCompatibleDC(desktop_dc_); |
| 84 |
| 85 // Create a bitmap to keep the desktop image. |
| 86 width_ = GetSystemMetrics(SM_CXSCREEN); |
| 87 height_ = GetSystemMetrics(SM_CYSCREEN); |
| 88 int rounded_width = (width_ + 3) & (~3); |
| 89 |
| 90 // Dimensions of screen. |
| 91 pixel_format_ = chromotocol_pb::PixelFormatRgb24; |
| 92 bytes_per_pixel_ = kBytesPerPixel; |
| 93 bytes_per_row_ = rounded_width * bytes_per_pixel_; |
| 94 |
| 95 // Create a device independant bitmap (DIB) that is the same size. |
| 96 BITMAPINFO bmi; |
| 97 memset(&bmi, 0, sizeof(bmi)); |
| 98 bmi.bmiHeader.biHeight = height_; |
| 99 bmi.bmiHeader.biWidth = width_; |
| 100 bmi.bmiHeader.biPlanes = 1; |
| 101 bmi.bmiHeader.biBitCount = bytes_per_pixel_ * 8; |
| 102 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); |
| 103 bmi.bmiHeader.biSizeImage = bytes_per_row_ * height_; |
| 104 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter; |
| 105 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter; |
| 106 |
| 107 // Create memory for the buffers. |
| 108 for (int i = 0; i < kNumBuffers; i++) { |
| 109 target_bitmap_[i] = CreateDIBSection(desktop_dc_, &bmi, DIB_RGB_COLORS, |
| 110 static_cast<void**>(&buffers_[i]), |
| 111 NULL, 0); |
| 112 } |
| 113 initialized_ = true; |
| 114 } |
| 115 |
| 116 void CapturerGdi::CaptureImage() { |
| 117 if (initialized_ == false) { |
| 118 InitializeBuffers(); |
| 119 } |
| 120 // Selection the target bitmap into the memory dc. |
| 121 SelectObject(memory_dc_, target_bitmap_[current_buffer_]); |
| 122 |
| 123 // And then copy the rect from desktop to memory. |
| 124 BitBlt(memory_dc_, 0, 0, width_, height_, desktop_dc_, 0, 0, |
| 125 SRCCOPY | CAPTUREBLT); |
| 126 } |
| 127 |
| 128 } // namespace remoting |
OLD | NEW |