Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/browser/compositor/software_output_device_win.h" | 5 #include "content/browser/compositor/software_output_device_win.h" |
| 6 | 6 |
| 7 #include "base/memory/shared_memory.h" | |
| 7 #include "content/public/browser/browser_thread.h" | 8 #include "content/public/browser/browser_thread.h" |
| 9 #include "skia/ext/platform_canvas.h" | |
| 8 #include "third_party/skia/include/core/SkBitmap.h" | 10 #include "third_party/skia/include/core/SkBitmap.h" |
| 9 #include "third_party/skia/include/core/SkDevice.h" | 11 #include "third_party/skia/include/core/SkDevice.h" |
| 10 #include "ui/compositor/compositor.h" | 12 #include "ui/compositor/compositor.h" |
| 11 #include "ui/gfx/canvas.h" | |
| 12 #include "ui/gfx/gdi_util.h" | 13 #include "ui/gfx/gdi_util.h" |
| 13 #include "ui/gfx/skia_util.h" | 14 #include "ui/gfx/skia_util.h" |
| 14 | 15 |
| 15 namespace content { | 16 namespace content { |
| 16 | 17 |
| 17 SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(ui::Compositor* compositor) | 18 OutputDeviceBacking::OutputDeviceBacking() : created_byte_size_(0) { |
| 19 } | |
| 20 | |
| 21 OutputDeviceBacking::~OutputDeviceBacking() { | |
| 22 DCHECK(devices_.empty()); | |
| 23 } | |
| 24 | |
| 25 void OutputDeviceBacking::Resized() { | |
| 26 size_t new_size = GetMaxByteSize(); | |
| 27 if (new_size == created_byte_size_) | |
| 28 return; | |
| 29 for (SoftwareOutputDeviceWin* device : devices_) { | |
| 30 device->ReleaseContents(); | |
| 31 } | |
| 32 backing_.reset(); | |
| 33 created_byte_size_ = 0; | |
| 34 } | |
| 35 | |
| 36 void OutputDeviceBacking::RegisterOutputDevice( | |
| 37 SoftwareOutputDeviceWin* device) { | |
| 38 devices_.push_back(device); | |
| 39 } | |
| 40 | |
| 41 void OutputDeviceBacking::UnregisterOutputDevice( | |
| 42 SoftwareOutputDeviceWin* device) { | |
| 43 auto it = std::find(devices_.begin(), devices_.end(), device); | |
| 44 DCHECK(it != devices_.end()); | |
| 45 devices_.erase(it); | |
| 46 Resized(); | |
| 47 } | |
| 48 | |
| 49 base::SharedMemory* OutputDeviceBacking::GetSharedMemory() { | |
| 50 if (backing_) | |
| 51 return backing_.get(); | |
| 52 created_byte_size_ = GetMaxByteSize(); | |
| 53 | |
| 54 backing_.reset(new base::SharedMemory); | |
| 55 CHECK(backing_->CreateAnonymous(created_byte_size_)); | |
| 56 return backing_.get(); | |
| 57 } | |
| 58 | |
| 59 size_t OutputDeviceBacking::GetMaxByteSize() { | |
| 60 size_t max_size = 0; | |
| 61 for (const SoftwareOutputDeviceWin* device : devices_) { | |
| 62 max_size = std::max( | |
| 63 max_size, | |
| 64 static_cast<size_t>(device->viewport_pixel_size().GetArea() * 4)); | |
| 65 } | |
| 66 return max_size; | |
| 67 } | |
| 68 | |
| 69 SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(OutputDeviceBacking* backing, | |
| 70 ui::Compositor* compositor) | |
| 18 : hwnd_(compositor->widget()), | 71 : hwnd_(compositor->widget()), |
| 19 is_hwnd_composited_(false) { | 72 is_hwnd_composited_(false), |
| 73 backing_(backing), | |
| 74 in_paint_(false) { | |
| 20 // TODO(skaslev) Remove this when crbug.com/180702 is fixed. | 75 // TODO(skaslev) Remove this when crbug.com/180702 is fixed. |
|
piman
2015/05/12 03:03:51
nit: BTW you can remove this comment now, since th
| |
| 21 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 76 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 22 | 77 |
| 23 LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE); | 78 LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE); |
| 24 is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED); | 79 is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED); |
| 80 // Layered windows must be completely updated every time, so they can't | |
| 81 // share contents with other windows. | |
| 82 if (is_hwnd_composited_) | |
| 83 backing_ = nullptr; | |
| 84 if (backing_) | |
| 85 backing_->RegisterOutputDevice(this); | |
| 25 } | 86 } |
| 26 | 87 |
| 27 SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { | 88 SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { |
| 28 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 89 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 90 DCHECK(!in_paint_); | |
| 91 if (backing_) | |
| 92 backing_->UnregisterOutputDevice(this); | |
| 29 } | 93 } |
| 30 | 94 |
| 31 void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, | 95 void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, |
| 32 float scale_factor) { | 96 float scale_factor) { |
| 33 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 97 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 98 DCHECK(!in_paint_); | |
| 34 | 99 |
| 35 scale_factor_ = scale_factor; | 100 scale_factor_ = scale_factor; |
| 36 | 101 |
| 37 if (viewport_pixel_size_ == viewport_pixel_size) | 102 if (viewport_pixel_size_ == viewport_pixel_size) |
| 38 return; | 103 return; |
| 39 | 104 |
| 40 viewport_pixel_size_ = viewport_pixel_size; | 105 viewport_pixel_size_ = viewport_pixel_size; |
| 41 contents_.reset(new gfx::Canvas(viewport_pixel_size, 1.0f, true)); | 106 if (backing_) |
| 42 memset(&bitmap_info_, 0, sizeof(bitmap_info_)); | 107 backing_->Resized(); |
| 43 gfx::CreateBitmapHeader(viewport_pixel_size_.width(), | 108 contents_.clear(); |
| 44 viewport_pixel_size_.height(), | |
| 45 &bitmap_info_.bmiHeader); | |
| 46 } | 109 } |
| 47 | 110 |
| 48 SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { | 111 SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { |
| 49 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 112 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 50 DCHECK(contents_); | 113 DCHECK(!in_paint_); |
| 114 if (!contents_) { | |
| 115 HANDLE shared_section = NULL; | |
| 116 if (backing_) | |
| 117 shared_section = backing_->GetSharedMemory()->handle(); | |
| 118 contents_ = skia::AdoptRef(skia::CreatePlatformCanvas( | |
| 119 viewport_pixel_size_.width(), viewport_pixel_size_.height(), true, | |
| 120 shared_section, skia::CRASH_ON_FAILURE)); | |
| 121 } | |
| 51 | 122 |
| 52 damage_rect_ = damage_rect; | 123 damage_rect_ = damage_rect; |
| 53 return contents_ ? contents_->sk_canvas() : NULL; | 124 in_paint_ = true; |
| 125 return contents_.get(); | |
| 54 } | 126 } |
| 55 | 127 |
| 56 void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { | 128 void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
| 57 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 129 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 58 DCHECK(contents_); | 130 DCHECK(contents_); |
| 59 DCHECK(frame_data); | 131 DCHECK(frame_data); |
| 132 DCHECK(in_paint_); | |
| 60 | 133 |
| 61 if (!contents_) | 134 in_paint_ = false; |
| 62 return; | |
| 63 | |
| 64 SoftwareOutputDevice::EndPaint(frame_data); | 135 SoftwareOutputDevice::EndPaint(frame_data); |
| 65 | 136 |
| 66 gfx::Rect rect = damage_rect_; | 137 gfx::Rect rect = damage_rect_; |
| 67 rect.Intersect(gfx::Rect(viewport_pixel_size_)); | 138 rect.Intersect(gfx::Rect(viewport_pixel_size_)); |
| 68 if (rect.IsEmpty()) | 139 if (rect.IsEmpty()) |
| 69 return; | 140 return; |
| 70 | 141 |
| 71 SkCanvas* canvas = contents_->sk_canvas(); | |
| 72 DCHECK(canvas); | |
| 73 if (is_hwnd_composited_) { | 142 if (is_hwnd_composited_) { |
| 74 RECT wr; | 143 RECT wr; |
| 75 GetWindowRect(hwnd_, &wr); | 144 GetWindowRect(hwnd_, &wr); |
| 76 SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; | 145 SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; |
| 77 POINT position = {wr.left, wr.top}; | 146 POINT position = {wr.left, wr.top}; |
| 78 POINT zero = {0, 0}; | 147 POINT zero = {0, 0}; |
| 79 BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA}; | 148 BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA}; |
| 80 | 149 |
| 81 DWORD style = GetWindowLong(hwnd_, GWL_EXSTYLE); | 150 DWORD style = GetWindowLong(hwnd_, GWL_EXSTYLE); |
| 82 style &= ~WS_EX_COMPOSITED; | 151 style &= ~WS_EX_COMPOSITED; |
| 83 style |= WS_EX_LAYERED; | 152 style |= WS_EX_LAYERED; |
| 84 SetWindowLong(hwnd_, GWL_EXSTYLE, style); | 153 SetWindowLong(hwnd_, GWL_EXSTYLE, style); |
| 85 | 154 |
| 86 HDC dib_dc = skia::BeginPlatformPaint(canvas); | 155 HDC dib_dc = skia::BeginPlatformPaint(contents_.get()); |
| 87 ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero, | 156 ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero, |
| 88 RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); | 157 RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); |
| 89 skia::EndPlatformPaint(canvas); | 158 skia::EndPlatformPaint(contents_.get()); |
| 90 } else { | 159 } else { |
| 91 HDC hdc = ::GetDC(hwnd_); | 160 HDC hdc = ::GetDC(hwnd_); |
| 92 RECT src_rect = rect.ToRECT(); | 161 RECT src_rect = rect.ToRECT(); |
| 93 skia::DrawToNativeContext(canvas, hdc, rect.x(), rect.y(), &src_rect); | 162 skia::DrawToNativeContext(contents_.get(), hdc, rect.x(), rect.y(), |
| 163 &src_rect); | |
| 94 ::ReleaseDC(hwnd_, hdc); | 164 ::ReleaseDC(hwnd_, hdc); |
| 95 } | 165 } |
| 96 } | 166 } |
| 97 | 167 |
| 168 void SoftwareOutputDeviceWin::ReleaseContents() { | |
| 169 DCHECK(!contents_ || contents_->unique()); | |
| 170 DCHECK(!in_paint_); | |
| 171 contents_.clear(); | |
| 172 } | |
| 173 | |
| 98 } // namespace content | 174 } // namespace content |
| OLD | NEW |