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), |
20 // TODO(skaslev) Remove this when crbug.com/180702 is fixed. | 73 backing_(backing), |
| 74 in_paint_(false) { |
21 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 75 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
22 | 76 |
23 LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE); | 77 LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE); |
24 is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED); | 78 is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED); |
| 79 // Layered windows must be completely updated every time, so they can't |
| 80 // share contents with other windows. |
| 81 if (is_hwnd_composited_) |
| 82 backing_ = nullptr; |
| 83 if (backing_) |
| 84 backing_->RegisterOutputDevice(this); |
25 } | 85 } |
26 | 86 |
27 SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { | 87 SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { |
28 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 88 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 89 DCHECK(!in_paint_); |
| 90 if (backing_) |
| 91 backing_->UnregisterOutputDevice(this); |
29 } | 92 } |
30 | 93 |
31 void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, | 94 void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, |
32 float scale_factor) { | 95 float scale_factor) { |
33 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 96 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 97 DCHECK(!in_paint_); |
34 | 98 |
35 scale_factor_ = scale_factor; | 99 scale_factor_ = scale_factor; |
36 | 100 |
37 if (viewport_pixel_size_ == viewport_pixel_size) | 101 if (viewport_pixel_size_ == viewport_pixel_size) |
38 return; | 102 return; |
39 | 103 |
40 viewport_pixel_size_ = viewport_pixel_size; | 104 viewport_pixel_size_ = viewport_pixel_size; |
41 contents_.reset(new gfx::Canvas(viewport_pixel_size, 1.0f, true)); | 105 if (backing_) |
42 memset(&bitmap_info_, 0, sizeof(bitmap_info_)); | 106 backing_->Resized(); |
43 gfx::CreateBitmapHeader(viewport_pixel_size_.width(), | 107 contents_.clear(); |
44 viewport_pixel_size_.height(), | |
45 &bitmap_info_.bmiHeader); | |
46 } | 108 } |
47 | 109 |
48 SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { | 110 SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { |
49 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 111 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
50 DCHECK(contents_); | 112 DCHECK(!in_paint_); |
| 113 if (!contents_) { |
| 114 HANDLE shared_section = NULL; |
| 115 if (backing_) |
| 116 shared_section = backing_->GetSharedMemory()->handle(); |
| 117 contents_ = skia::AdoptRef(skia::CreatePlatformCanvas( |
| 118 viewport_pixel_size_.width(), viewport_pixel_size_.height(), true, |
| 119 shared_section, skia::CRASH_ON_FAILURE)); |
| 120 } |
51 | 121 |
52 damage_rect_ = damage_rect; | 122 damage_rect_ = damage_rect; |
53 return contents_ ? contents_->sk_canvas() : NULL; | 123 in_paint_ = true; |
| 124 return contents_.get(); |
54 } | 125 } |
55 | 126 |
56 void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { | 127 void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
57 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 128 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
58 DCHECK(contents_); | 129 DCHECK(contents_); |
59 DCHECK(frame_data); | 130 DCHECK(frame_data); |
| 131 DCHECK(in_paint_); |
60 | 132 |
61 if (!contents_) | 133 in_paint_ = false; |
62 return; | |
63 | |
64 SoftwareOutputDevice::EndPaint(frame_data); | 134 SoftwareOutputDevice::EndPaint(frame_data); |
65 | 135 |
66 gfx::Rect rect = damage_rect_; | 136 gfx::Rect rect = damage_rect_; |
67 rect.Intersect(gfx::Rect(viewport_pixel_size_)); | 137 rect.Intersect(gfx::Rect(viewport_pixel_size_)); |
68 if (rect.IsEmpty()) | 138 if (rect.IsEmpty()) |
69 return; | 139 return; |
70 | 140 |
71 SkCanvas* canvas = contents_->sk_canvas(); | |
72 DCHECK(canvas); | |
73 if (is_hwnd_composited_) { | 141 if (is_hwnd_composited_) { |
74 RECT wr; | 142 RECT wr; |
75 GetWindowRect(hwnd_, &wr); | 143 GetWindowRect(hwnd_, &wr); |
76 SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; | 144 SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; |
77 POINT position = {wr.left, wr.top}; | 145 POINT position = {wr.left, wr.top}; |
78 POINT zero = {0, 0}; | 146 POINT zero = {0, 0}; |
79 BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA}; | 147 BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA}; |
80 | 148 |
81 DWORD style = GetWindowLong(hwnd_, GWL_EXSTYLE); | 149 DWORD style = GetWindowLong(hwnd_, GWL_EXSTYLE); |
82 style &= ~WS_EX_COMPOSITED; | 150 style &= ~WS_EX_COMPOSITED; |
83 style |= WS_EX_LAYERED; | 151 style |= WS_EX_LAYERED; |
84 SetWindowLong(hwnd_, GWL_EXSTYLE, style); | 152 SetWindowLong(hwnd_, GWL_EXSTYLE, style); |
85 | 153 |
86 HDC dib_dc = skia::BeginPlatformPaint(canvas); | 154 HDC dib_dc = skia::BeginPlatformPaint(contents_.get()); |
87 ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero, | 155 ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero, |
88 RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); | 156 RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); |
89 skia::EndPlatformPaint(canvas); | 157 skia::EndPlatformPaint(contents_.get()); |
90 } else { | 158 } else { |
91 HDC hdc = ::GetDC(hwnd_); | 159 HDC hdc = ::GetDC(hwnd_); |
92 RECT src_rect = rect.ToRECT(); | 160 RECT src_rect = rect.ToRECT(); |
93 skia::DrawToNativeContext(canvas, hdc, rect.x(), rect.y(), &src_rect); | 161 skia::DrawToNativeContext(contents_.get(), hdc, rect.x(), rect.y(), |
| 162 &src_rect); |
94 ::ReleaseDC(hwnd_, hdc); | 163 ::ReleaseDC(hwnd_, hdc); |
95 } | 164 } |
96 } | 165 } |
97 | 166 |
| 167 void SoftwareOutputDeviceWin::ReleaseContents() { |
| 168 DCHECK(!contents_ || contents_->unique()); |
| 169 DCHECK(!in_paint_); |
| 170 contents_.clear(); |
| 171 } |
| 172 |
98 } // namespace content | 173 } // namespace content |
OLD | NEW |