diff options
author | skaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-09 02:51:14 +0000 |
---|---|---|
committer | skaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-09 02:51:14 +0000 |
commit | b4f00168368a7418d9e4109705b3b2f01a0c21eb (patch) | |
tree | 6c64161afd860e4d32e89defba34433e067568a6 /content/browser/renderer_host | |
parent | 478c6c3aa0165dfd120993c5ec0757d594e70fe6 (diff) | |
download | chromium_src-b4f00168368a7418d9e4109705b3b2f01a0c21eb.zip chromium_src-b4f00168368a7418d9e4109705b3b2f01a0c21eb.tar.gz chromium_src-b4f00168368a7418d9e4109705b3b2f01a0c21eb.tar.bz2 |
Implemented browser side software compositing behind the --ui-enable-software-compositing flag.
BUG=124671, 161008
Review URL: https://chromiumcodereview.appspot.com/12542006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187123 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/renderer_host')
6 files changed, 266 insertions, 40 deletions
diff --git a/content/browser/renderer_host/backing_store_win.cc b/content/browser/renderer_host/backing_store_win.cc index 77c0341..5ccafbb 100644 --- a/content/browser/renderer_host/backing_store_win.cc +++ b/content/browser/renderer_host/backing_store_win.cc @@ -48,29 +48,6 @@ HANDLE CreateDIB(HDC dc, int width, int height, int color_depth) { return dib; } -void CallStretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h, - int src_x, int src_y, int src_w, int src_h, void* pixels, - const BITMAPINFO* bitmap_info) { - // When blitting a rectangle that touches the bottom, left corner of the - // bitmap, StretchDIBits looks at it top-down! For more details, see - // http://wiki.allegro.cc/index.php?title=StretchDIBits. - int rv; - int bitmap_h = -bitmap_info->bmiHeader.biHeight; - int bottom_up_src_y = bitmap_h - src_y - src_h; - if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) { - rv = StretchDIBits(hdc, - dest_x, dest_h + dest_y - 1, dest_w, -dest_h, - src_x, bitmap_h - src_y + 1, src_w, -src_h, - pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY); - } else { - rv = StretchDIBits(hdc, - dest_x, dest_y, dest_w, dest_h, - src_x, bottom_up_src_y, src_w, src_h, - pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY); - } - DCHECK(rv != GDI_ERROR); -} - } // namespace BackingStoreWin::BackingStoreWin(RenderWidgetHost* widget, @@ -149,9 +126,11 @@ void BackingStoreWin::PaintToBackingStore( gfx::Rect pixel_bitmap_rect = gfx::ToEnclosingRect( gfx::ScaleRect(bitmap_rect, scale_factor)); - BITMAPINFOHEADER hdr; + BITMAPINFO bitmap_info; + memset(&bitmap_info, 0, sizeof(bitmap_info)); gfx::CreateBitmapHeader(pixel_bitmap_rect.width(), - pixel_bitmap_rect.height(), &hdr); + pixel_bitmap_rect.height(), + &bitmap_info.bmiHeader); // Account for a bitmap_rect that exceeds the bounds of our view. gfx::Rect view_rect(size()); @@ -160,17 +139,17 @@ void BackingStoreWin::PaintToBackingStore( gfx::Rect pixel_copy_rect = gfx::ToEnclosingRect( gfx::ScaleRect(paint_rect, scale_factor)); gfx::Rect target_rect = pixel_copy_rect; - CallStretchDIBits(hdc_, - target_rect.x(), - target_rect.y(), - target_rect.width(), - target_rect.height(), - pixel_copy_rect.x() - pixel_bitmap_rect.x(), - pixel_copy_rect.y() - pixel_bitmap_rect.y(), - pixel_copy_rect.width(), - pixel_copy_rect.height(), - dib->memory(), - reinterpret_cast<BITMAPINFO*>(&hdr)); + gfx::StretchDIBits(hdc_, + target_rect.x(), + target_rect.y(), + target_rect.width(), + target_rect.height(), + pixel_copy_rect.x() - pixel_bitmap_rect.x(), + pixel_copy_rect.y() - pixel_bitmap_rect.y(), + pixel_copy_rect.width(), + pixel_copy_rect.height(), + dib->memory(), + &bitmap_info); } } diff --git a/content/browser/renderer_host/image_transport_factory.cc b/content/browser/renderer_host/image_transport_factory.cc index e37ea28..5970a3c 100644 --- a/content/browser/renderer_host/image_transport_factory.cc +++ b/content/browser/renderer_host/image_transport_factory.cc @@ -33,12 +33,16 @@ #include "third_party/khronos/GLES2/gl2ext.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_setup.h" +#include "ui/compositor/compositor_switches.h" #include "ui/compositor/test_web_graphics_context_3d.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" #if defined(OS_WIN) +#include "content/browser/renderer_host/software_output_device_win.h" #include "ui/surface/accelerated_surface_win.h" +#elif defined(USE_X11) +#include "content/browser/renderer_host/software_output_device_linux.h" #endif namespace content { @@ -669,6 +673,26 @@ WebKit::WebGraphicsContext3D* CreateTestContext() { return test_context; } +class SoftwareTransportFactory : public DefaultTransportFactory { + public: + cc::OutputSurface* CreateOutputSurface(ui::Compositor* compositor) { +#if defined(OS_WIN) + scoped_ptr<SoftwareOutputDeviceWin> software_device( + new SoftwareOutputDeviceWin(compositor)); + return new cc::OutputSurface( + software_device.PassAs<cc::SoftwareOutputDevice>()); +#elif defined(USE_X11) + scoped_ptr<SoftwareOutputDeviceLinux> software_device( + new SoftwareOutputDeviceLinux(compositor)); + return new cc::OutputSurface( + software_device.PassAs<cc::SoftwareOutputDevice>()); +#else + NOTIMPLEMENTED(); + return NULL; +#endif + } +}; + } // anonymous namespace // static @@ -677,10 +701,13 @@ void ImageTransportFactory::Initialize() { if (command_line->HasSwitch(switches::kTestCompositor)) { ui::SetupTestCompositor(); } - if (ui::IsTestCompositorEnabled()) - g_factory = new DefaultTransportFactory(); - else - g_factory = new GpuProcessTransportFactory(); + if (ui::IsTestCompositorEnabled()) { + g_factory = new DefaultTransportFactory; + } else if (command_line->HasSwitch(switches::kUIEnableSoftwareCompositing)) { + g_factory = new SoftwareTransportFactory; + } else { + g_factory = new GpuProcessTransportFactory; + } ui::ContextFactory::SetInstance(g_factory->AsContextFactory()); } diff --git a/content/browser/renderer_host/software_output_device_linux.cc b/content/browser/renderer_host/software_output_device_linux.cc new file mode 100644 index 0000000..58289dd --- /dev/null +++ b/content/browser/renderer_host/software_output_device_linux.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/software_output_device_linux.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "content/public/browser/browser_thread.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkDevice.h" +#include "ui/compositor/compositor.h" + +namespace content { + +SoftwareOutputDeviceLinux::SoftwareOutputDeviceLinux(ui::Compositor* compositor) + : compositor_(compositor), + display_(ui::GetXDisplay()), + gc_(NULL), + image_(NULL) { + // TODO(skaslev) Remove this when crbug.com/180702 is fixed. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + gc_ = XCreateGC(display_, compositor_->widget(), 0, NULL); +} + +SoftwareOutputDeviceLinux::~SoftwareOutputDeviceLinux() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + XFreeGC(display_, gc_); + ClearImage(); +} + +void SoftwareOutputDeviceLinux::ClearImage() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (image_) { + // XDestroyImage deletes the data referenced by the image which + // is actually owned by the device_. So we have to reset data here. + image_->data = NULL; + XDestroyImage(image_); + image_ = NULL; + } +} + +void SoftwareOutputDeviceLinux::Resize(const gfx::Size& viewport_size) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + cc::SoftwareOutputDevice::Resize(viewport_size); + + ClearImage(); + if (!device_) + return; + + const SkBitmap& bitmap = device_->accessBitmap(false); + image_ = XCreateImage(display_, CopyFromParent, + DefaultDepth(display_, DefaultScreen(display_)), + ZPixmap, 0, + static_cast<char*>(bitmap.getPixels()), + viewport_size_.width(), viewport_size_.height(), + 32, 4 * viewport_size_.width()); +} + +void SoftwareOutputDeviceLinux::EndPaint(cc::SoftwareFrameData* frame_data) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(device_); + DCHECK(frame_data == NULL); + + if (!device_) + return; + + gfx::Rect rect = damage_rect_; + rect.Intersect(gfx::Rect(viewport_size_)); + if (rect.IsEmpty()) + return; + + // TODO(skaslev): Maybe switch XShmPutImage since it's async. + XPutImage(display_, compositor_->widget(), gc_, image_, + rect.x(), rect.y(), + rect.x(), rect.y(), + rect.width(), rect.height()); +} + +} // namespace content diff --git a/content/browser/renderer_host/software_output_device_linux.h b/content/browser/renderer_host/software_output_device_linux.h new file mode 100644 index 0000000..654936e --- /dev/null +++ b/content/browser/renderer_host/software_output_device_linux.h @@ -0,0 +1,38 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_OUTPUT_DEVICE_LINUX_H_ +#define CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_OUTPUT_DEVICE_LINUX_H_ + +#include "cc/software_output_device.h" +#include "ui/base/x/x11_util.h" + +namespace ui { +class Compositor; +} + +namespace content { + +class SoftwareOutputDeviceLinux : public cc::SoftwareOutputDevice { + public: + explicit SoftwareOutputDeviceLinux(ui::Compositor* compositor); + + virtual ~SoftwareOutputDeviceLinux(); + + virtual void Resize(const gfx::Size& viewport_size) OVERRIDE; + + virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE; + + private: + void ClearImage(); + + ui::Compositor* compositor_; + Display* display_; + GC gc_; + XImage* image_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_OUTPUT_DEVICE_LINUX_H_ diff --git a/content/browser/renderer_host/software_output_device_win.cc b/content/browser/renderer_host/software_output_device_win.cc new file mode 100644 index 0000000..b78cd4da --- /dev/null +++ b/content/browser/renderer_host/software_output_device_win.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/software_output_device_win.h" + +#include "content/public/browser/browser_thread.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/gdi_util.h" + +namespace content { + +SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(ui::Compositor* compositor) + : compositor_(compositor) { + // TODO(skaslev) Remove this when crbug.com/180702 is fixed. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + hdc_ = ::GetWindowDC(compositor->widget()); +} + +SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + ::ReleaseDC(compositor_->widget(), hdc_); +} + +void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_size) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + cc::SoftwareOutputDevice::Resize(viewport_size); + memset(&bitmap_info_, 0, sizeof(bitmap_info_)); + gfx::CreateBitmapHeader(viewport_size_.width(), viewport_size_.height(), + &bitmap_info_.bmiHeader); +} + +void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(device_); + DCHECK(frame_data == NULL); + + if (!device_) + return; + + gfx::Rect rect = damage_rect_; + rect.Intersect(gfx::Rect(viewport_size_)); + if (rect.IsEmpty()) + return; + + const SkBitmap& bitmap = device_->accessBitmap(false); + gfx::StretchDIBits(hdc_, + rect.x(), rect.y(), + rect.width(), rect.height(), + rect.x(), rect.y(), + rect.width(), rect.height(), + bitmap.getPixels(), + &bitmap_info_); +} + +} // namespace content diff --git a/content/browser/renderer_host/software_output_device_win.h b/content/browser/renderer_host/software_output_device_win.h new file mode 100644 index 0000000..ab8f6bf --- /dev/null +++ b/content/browser/renderer_host/software_output_device_win.h @@ -0,0 +1,36 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_OUTPUT_DEVICE_WIN_H_ +#define CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_OUTPUT_DEVICE_WIN_H_ + +#include "cc/software_output_device.h" + +#include <windows.h> + +namespace ui { +class Compositor; +} + +namespace content { + +class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice { + public: + explicit SoftwareOutputDeviceWin(ui::Compositor* compositor); + + virtual ~SoftwareOutputDeviceWin(); + + virtual void Resize(const gfx::Size& viewport_size) OVERRIDE; + + virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE; + + private: + ui::Compositor* compositor_; + HDC hdc_; + BITMAPINFO bitmap_info_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_OUTPUT_DEVICE_WIN_H_ |