| 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..bb22e90acd3393d430f5c9a1a82e7e46fc0f1fa0 100644
|
| --- a/content/browser/compositor/software_output_device_win.cc
|
| +++ b/content/browser/compositor/software_output_device_win.cc
|
| @@ -4,33 +4,97 @@
|
|
|
| #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) {
|
| - // TODO(skaslev) Remove this when crbug.com/180702 is fixed.
|
| + is_hwnd_composited_(false),
|
| + backing_(backing),
|
| + in_paint_(false) {
|
| 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 +102,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 +138,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 +151,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
|
|
|