Chromium Code Reviews| Index: content/browser/compositor/software_output_device_win.cc |
| diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc |
| index 7c6ca0c24fd53a27552363ee3117c8901020d233..06761b816c6f94d9f3da521843e125749af5df27 100644 |
| --- a/content/browser/compositor/software_output_device_win.cc |
| +++ b/content/browser/compositor/software_output_device_win.cc |
| @@ -4,33 +4,98 @@ |
| #include "content/browser/compositor/software_output_device_win.h" |
| +#include "base/memory/shared_memory.h" |
| #include "content/public/browser/browser_thread.h" |
| +#include "skia/ext/platform_canvas.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkDevice.h" |
| #include "ui/compositor/compositor.h" |
| -#include "ui/gfx/canvas.h" |
| #include "ui/gfx/gdi_util.h" |
| #include "ui/gfx/skia_util.h" |
| namespace content { |
| -SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(ui::Compositor* compositor) |
| +OutputDeviceBacking::OutputDeviceBacking() : created_byte_size_(0) { |
| +} |
| + |
| +OutputDeviceBacking::~OutputDeviceBacking() { |
| + DCHECK(devices_.empty()); |
| +} |
| + |
| +void OutputDeviceBacking::Resized() { |
| + size_t new_size = GetMaxByteSize(); |
| + if (new_size == created_byte_size_) |
| + return; |
| + for (SoftwareOutputDeviceWin* device : devices_) { |
| + device->ReleaseContents(); |
| + } |
| + backing_.reset(); |
| + created_byte_size_ = 0; |
| +} |
| + |
| +void OutputDeviceBacking::RegisterOutputDevice( |
| + SoftwareOutputDeviceWin* device) { |
| + devices_.push_back(device); |
| +} |
| + |
| +void OutputDeviceBacking::UnregisterOutputDevice( |
| + SoftwareOutputDeviceWin* device) { |
| + auto it = std::find(devices_.begin(), devices_.end(), device); |
| + DCHECK(it != devices_.end()); |
| + devices_.erase(it); |
| + Resized(); |
| +} |
| + |
| +base::SharedMemory* OutputDeviceBacking::GetSharedMemory() { |
| + if (backing_) |
| + return backing_.get(); |
| + created_byte_size_ = GetMaxByteSize(); |
| + |
| + backing_.reset(new base::SharedMemory); |
| + CHECK(backing_->CreateAnonymous(created_byte_size_)); |
| + return backing_.get(); |
| +} |
| + |
| +size_t OutputDeviceBacking::GetMaxByteSize() { |
| + size_t max_size = 0; |
| + for (const SoftwareOutputDeviceWin* device : devices_) { |
| + max_size = std::max( |
| + max_size, |
| + static_cast<size_t>(device->viewport_pixel_size().GetArea() * 4)); |
| + } |
| + return max_size; |
| +} |
| + |
| +SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(OutputDeviceBacking* backing, |
| + ui::Compositor* compositor) |
| : hwnd_(compositor->widget()), |
| - is_hwnd_composited_(false) { |
| + is_hwnd_composited_(false), |
| + backing_(backing), |
| + in_paint_(false) { |
| // 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
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE); |
| is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED); |
| + // Layered windows must be completely updated every time, so they can't |
| + // share contents with other windows. |
| + if (is_hwnd_composited_) |
| + backing_ = nullptr; |
| + if (backing_) |
| + backing_->RegisterOutputDevice(this); |
| } |
| SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + DCHECK(!in_paint_); |
| + if (backing_) |
| + backing_->UnregisterOutputDevice(this); |
| } |
| void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, |
| float scale_factor) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + DCHECK(!in_paint_); |
| scale_factor_ = scale_factor; |
| @@ -38,29 +103,35 @@ void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, |
| return; |
| viewport_pixel_size_ = viewport_pixel_size; |
| - contents_.reset(new gfx::Canvas(viewport_pixel_size, 1.0f, true)); |
| - memset(&bitmap_info_, 0, sizeof(bitmap_info_)); |
| - gfx::CreateBitmapHeader(viewport_pixel_size_.width(), |
| - viewport_pixel_size_.height(), |
| - &bitmap_info_.bmiHeader); |
| + if (backing_) |
| + backing_->Resized(); |
| + contents_.clear(); |
| } |
| SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - DCHECK(contents_); |
| + DCHECK(!in_paint_); |
| + if (!contents_) { |
| + HANDLE shared_section = NULL; |
| + if (backing_) |
| + shared_section = backing_->GetSharedMemory()->handle(); |
| + contents_ = skia::AdoptRef(skia::CreatePlatformCanvas( |
| + viewport_pixel_size_.width(), viewport_pixel_size_.height(), true, |
| + shared_section, skia::CRASH_ON_FAILURE)); |
| + } |
| damage_rect_ = damage_rect; |
| - return contents_ ? contents_->sk_canvas() : NULL; |
| + in_paint_ = true; |
| + return contents_.get(); |
| } |
| void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| DCHECK(contents_); |
| DCHECK(frame_data); |
| + DCHECK(in_paint_); |
| - if (!contents_) |
| - return; |
| - |
| + in_paint_ = false; |
| SoftwareOutputDevice::EndPaint(frame_data); |
| gfx::Rect rect = damage_rect_; |
| @@ -68,8 +139,6 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
| if (rect.IsEmpty()) |
| return; |
| - SkCanvas* canvas = contents_->sk_canvas(); |
| - DCHECK(canvas); |
| if (is_hwnd_composited_) { |
| RECT wr; |
| GetWindowRect(hwnd_, &wr); |
| @@ -83,16 +152,23 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
| style |= WS_EX_LAYERED; |
| SetWindowLong(hwnd_, GWL_EXSTYLE, style); |
| - HDC dib_dc = skia::BeginPlatformPaint(canvas); |
| + HDC dib_dc = skia::BeginPlatformPaint(contents_.get()); |
| ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero, |
| RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); |
| - skia::EndPlatformPaint(canvas); |
| + skia::EndPlatformPaint(contents_.get()); |
| } else { |
| HDC hdc = ::GetDC(hwnd_); |
| RECT src_rect = rect.ToRECT(); |
| - skia::DrawToNativeContext(canvas, hdc, rect.x(), rect.y(), &src_rect); |
| + skia::DrawToNativeContext(contents_.get(), hdc, rect.x(), rect.y(), |
| + &src_rect); |
| ::ReleaseDC(hwnd_, hdc); |
| } |
| } |
| +void SoftwareOutputDeviceWin::ReleaseContents() { |
| + DCHECK(!contents_ || contents_->unique()); |
| + DCHECK(!in_paint_); |
| + contents_.clear(); |
| +} |
| + |
| } // namespace content |