summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbauman <jbauman@chromium.org>2015-05-12 16:02:10 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-12 23:03:30 +0000
commit8fe39ccf33d9f1a2d785c4deebce4cc7afad7d1e (patch)
treeb541b3a22089b7f5b4ff417c5a5692eed1e7bd63
parentb71e399156a93a2ea675c77f1cb98c84dac813eb (diff)
downloadchromium_src-8fe39ccf33d9f1a2d785c4deebce4cc7afad7d1e.zip
chromium_src-8fe39ccf33d9f1a2d785c4deebce4cc7afad7d1e.tar.gz
chromium_src-8fe39ccf33d9f1a2d785c4deebce4cc7afad7d1e.tar.bz2
Share backing canvases between browser compositors.
The software compositor's canvas is only used between BeginPaint and EndPaint. Those happen consecutively for a compositor, so we can share a single buffer to back multiple canvases, one per compositor. This cuts down on memory used to that necessary to contain just the largest window of the process. Review URL: https://codereview.chromium.org/1132133004 Cr-Commit-Position: refs/heads/master@{#329525}
-rw-r--r--content/browser/compositor/gpu_process_transport_factory.cc10
-rw-r--r--content/browser/compositor/gpu_process_transport_factory.h8
-rw-r--r--content/browser/compositor/software_output_device_win.cc113
-rw-r--r--content/browser/compositor/software_output_device_win.h38
4 files changed, 142 insertions, 27 deletions
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 151ba00..4abccc1 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -108,6 +108,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory()
raster_thread_.reset(new RasterThread(task_graph_runner_.get()));
raster_thread_->Start();
}
+#if defined(OS_WIN)
+ software_backing_.reset(new OutputDeviceBacking);
+#endif
}
GpuProcessTransportFactory::~GpuProcessTransportFactory() {
@@ -130,11 +133,12 @@ GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
return CreateContextCommon(gpu_channel_host, 0);
}
-scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
+scoped_ptr<cc::SoftwareOutputDevice>
+GpuProcessTransportFactory::CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
#if defined(OS_WIN)
- return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceWin(
- compositor));
+ return scoped_ptr<cc::SoftwareOutputDevice>(
+ new SoftwareOutputDeviceWin(software_backing_.get(), compositor));
#elif defined(USE_OZONE)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceOzone(
compositor));
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index 54f02ef..171c030 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -22,6 +22,7 @@ class Thread;
}
namespace cc {
+class SoftwareOutputDevice;
class SurfaceManager;
}
@@ -29,6 +30,7 @@ namespace content {
class BrowserCompositorOutputSurface;
class CompositorSwapClient;
class ContextProviderCommandBuffer;
+class OutputDeviceBacking;
class ReflectorImpl;
class WebGraphicsContext3DCommandBufferImpl;
@@ -78,6 +80,8 @@ class GpuProcessTransportFactory
struct PerCompositorData;
PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor);
+ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
+ ui::Compositor* compositor);
void EstablishedGpuChannel(base::WeakPtr<ui::Compositor> compositor,
bool create_gpu_output_surface,
int num_attempts);
@@ -98,6 +102,10 @@ class GpuProcessTransportFactory
scoped_ptr<cc::TaskGraphRunner> task_graph_runner_;
scoped_ptr<base::SimpleThread> raster_thread_;
+#if defined(OS_WIN)
+ scoped_ptr<OutputDeviceBacking> software_backing_;
+#endif
+
// The contents of this map and its methods may only be used on the compositor
// thread.
IDMap<BrowserCompositorOutputSurface> output_surface_map_;
diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc
index 7c6ca0c..bb22e90 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
diff --git a/content/browser/compositor/software_output_device_win.h b/content/browser/compositor/software_output_device_win.h
index 7063f20..8b7fc16 100644
--- a/content/browser/compositor/software_output_device_win.h
+++ b/content/browser/compositor/software_output_device_win.h
@@ -5,13 +5,15 @@
#ifndef CONTENT_BROWSER_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_WIN_H_
#define CONTENT_BROWSER_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_WIN_H_
+#include <vector>
+
#include "base/memory/scoped_ptr.h"
#include "cc/output/software_output_device.h"
#include <windows.h>
-namespace gfx {
-class Canvas;
+namespace base {
+class SharedMemory;
}
namespace ui {
@@ -19,10 +21,32 @@ class Compositor;
}
namespace content {
+class SoftwareOutputDeviceWin;
+
+class OutputDeviceBacking {
+ public:
+ OutputDeviceBacking();
+ ~OutputDeviceBacking();
+
+ void Resized();
+ void RegisterOutputDevice(SoftwareOutputDeviceWin* device);
+ void UnregisterOutputDevice(SoftwareOutputDeviceWin* device);
+ base::SharedMemory* GetSharedMemory();
+
+ private:
+ size_t GetMaxByteSize();
+
+ std::vector<SoftwareOutputDeviceWin*> devices_;
+ scoped_ptr<base::SharedMemory> backing_;
+ size_t created_byte_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(OutputDeviceBacking);
+};
class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
public:
- explicit SoftwareOutputDeviceWin(ui::Compositor* compositor);
+ SoftwareOutputDeviceWin(OutputDeviceBacking* backing,
+ ui::Compositor* compositor);
~SoftwareOutputDeviceWin() override;
void Resize(const gfx::Size& viewport_pixel_size,
@@ -30,11 +54,15 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
void EndPaint(cc::SoftwareFrameData* frame_data) override;
+ gfx::Size viewport_pixel_size() const { return viewport_pixel_size_; }
+ void ReleaseContents();
+
private:
HWND hwnd_;
- BITMAPINFO bitmap_info_;
- scoped_ptr<gfx::Canvas> contents_;
+ skia::RefPtr<SkCanvas> contents_;
bool is_hwnd_composited_;
+ OutputDeviceBacking* backing_;
+ bool in_paint_;
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWin);
};