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 |