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 94ceafd2ebb701aa817650d53e00f63d5d0b7b4c..4ef5957976e4acaecab6dabd719989cde6e04c0c 100644 |
--- a/content/browser/compositor/software_output_device_win.cc |
+++ b/content/browser/compositor/software_output_device_win.cc |
@@ -4,6 +4,8 @@ |
#include "content/browser/compositor/software_output_device_win.h" |
+#include "base/memory/shared_memory.h" |
+#include "base/memory/singleton.h" |
#include "content/public/browser/browser_thread.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "third_party/skia/include/core/SkDevice.h" |
@@ -15,6 +17,73 @@ |
namespace content { |
+namespace { |
+ |
+class SharedMemoryBacking { |
+ public: |
+ static SharedMemoryBacking* GetInstance() { |
piman
2015/05/11 23:20:56
nit: could the SharedMemoryBacking be owned by the
|
+ return Singleton<SharedMemoryBacking>::get(); |
+ } |
+ |
+ void 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 RegisterOutputDevice(SoftwareOutputDeviceWin* device) { |
+ devices_.push_back(device); |
+ } |
+ |
+ void UnregisterOutputDevice(SoftwareOutputDeviceWin* device) { |
+ auto it = std::find(devices_.begin(), devices_.end(), device); |
+ DCHECK(it != devices_.end()); |
+ devices_.erase(it); |
+ Resized(); |
+ } |
+ |
+ base::SharedMemory* GetSharedMemory() { |
+ if (backing_) |
+ return backing_.get(); |
+ created_byte_size_ = GetMaxByteSize(); |
+ |
+ backing_.reset(new base::SharedMemory); |
+ CHECK(backing_->CreateAnonymous(created_byte_size_)); |
+ return backing_.get(); |
+ } |
+ |
+ private: |
+ SharedMemoryBacking() : created_byte_size_(0) {} |
+ |
+ ~SharedMemoryBacking() { |
+ DCHECK(devices_.empty()); |
+ } |
+ |
+ size_t 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; |
+ } |
+ |
+ std::vector<SoftwareOutputDeviceWin*> devices_; |
+ scoped_ptr<base::SharedMemory> backing_; |
+ size_t created_byte_size_; |
+ friend struct DefaultSingletonTraits<SharedMemoryBacking>; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SharedMemoryBacking); |
+}; |
+ |
+} // namespace |
+ |
SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(ui::Compositor* compositor) |
: hwnd_(compositor->widget()), |
is_hwnd_composited_(false) { |
@@ -23,10 +92,14 @@ SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(ui::Compositor* compositor) |
LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE); |
is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED); |
+ if (!is_hwnd_composited_) |
+ SharedMemoryBacking::GetInstance()->RegisterOutputDevice(this); |
} |
SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ if (!is_hwnd_composited_) |
+ SharedMemoryBacking::GetInstance()->UnregisterOutputDevice(this); |
} |
void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size, |
@@ -39,19 +112,27 @@ 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 (!is_hwnd_composited_) |
+ SharedMemoryBacking::GetInstance()->Resized(); |
+ contents_.reset(); |
} |
SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- DCHECK(contents_); |
+ if (!contents_) { |
+ HANDLE shared_section = NULL; |
+ // Layered windows must be completely updated every time, so they can't |
+ // share contents with other windows. |
+ if (!is_hwnd_composited_) |
piman
2015/05/11 23:20:56
nit: needs {}
|
+ shared_section = |
+ SharedMemoryBacking::GetInstance()->GetSharedMemory()->handle(); |
+ contents_.reset(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; |
+ return contents_.get(); |
} |
void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
@@ -59,9 +140,6 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { |
DCHECK(contents_); |
DCHECK(frame_data); |
- if (!contents_) |
- return; |
- |
SoftwareOutputDevice::EndPaint(frame_data); |
gfx::Rect rect = damage_rect_; |
@@ -69,8 +147,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); |
@@ -84,16 +160,21 @@ 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() { |
piman
2015/05/11 23:20:56
nit: any way to DCHECK we're not between BeginPain
|
+ contents_.release(); |
+} |
+ |
} // namespace content |