Merge branch 'speedup-gpu' of https://github.com/MaxWhere/electron into speedup-gpu

This commit is contained in:
Heilig Benedek 2016-07-31 05:12:34 +02:00
commit 3e7ff466cd
15 changed files with 188 additions and 143 deletions

View file

@ -402,14 +402,6 @@ void WebContents::OnCreateWindow(const GURL& target_url,
Emit("new-window", target_url, frame_name, disposition);
}
void WebContents::RenderViewReady() {
// if (IsOffScreen()) {
// const auto rwhv = web_contents()->GetRenderWidgetHostView();
// auto osr_rwhv = static_cast<OffScreenRenderWidgetHostView *>(rwhv);
// osr_rwhv->SetPaintCallback(&paint_callback_);
// }
}
content::WebContents* WebContents::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
@ -445,12 +437,6 @@ void WebContents::MoveContents(content::WebContents* source,
void WebContents::CloseContents(content::WebContents* source) {
Emit("close");
if (IsOffScreen()) {
const auto osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>(
web_contents()->GetRenderWidgetHostView());
osr_rwhv->SetPainting(false);
}
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
owner_window()->CloseContents(source);
}
@ -1412,8 +1398,8 @@ void WebContents::OnPaint(
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate
, (char *)bitmap_pixels, sizeof(bitmap_pixels));
Emit("paint", damage_rect, bitmap_width, bitmap_height,
buffer.ToLocalChecked());
const gfx::Size bitmap_size = gfx::Size(bitmap_width, bitmap_height);
Emit("paint", damage_rect, buffer.ToLocalChecked(), bitmap_size);
}
void WebContents::StartPainting() {

View file

@ -278,7 +278,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
void MediaStartedPlaying(const MediaPlayerId& id) override;
void MediaStoppedPlaying(const MediaPlayerId& id) override;
void DidChangeThemeColor(SkColor theme_color) override;
void RenderViewReady() override;
// brightray::InspectableWebContentsDelegate:
void DevToolsReloadPage() override;

View file

@ -1,18 +1,17 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/osr_output_device.h"
#include <iostream>
#include "third_party/skia/include/core/SkDevice.h"
#include "ui/gfx/skia_util.h"
namespace atom {
OffScreenOutputDevice::OffScreenOutputDevice(bool transparent,
const OnPaintCallback& callback)
: transparent_(transparent),
const OnPaintCallback& callback):
transparent_(transparent),
callback_(callback),
active_(false) {
DCHECK(!callback_.is_null());
@ -22,8 +21,6 @@ OffScreenOutputDevice::~OffScreenOutputDevice() { }
void OffScreenOutputDevice::Resize(
const gfx::Size& pixel_size, float scale_factor) {
std::cout << pixel_size.width() << "x" << pixel_size.height() << std::endl;
scale_factor_ = scale_factor;
if (viewport_pixel_size_ == pixel_size) return;
@ -47,7 +44,6 @@ void OffScreenOutputDevice::Resize(
}
SkCanvas* OffScreenOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
// std::cout << "BeginPaint" << std::endl;
DCHECK(canvas_.get());
DCHECK(bitmap_.get());
@ -57,8 +53,6 @@ SkCanvas* OffScreenOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
}
void OffScreenOutputDevice::EndPaint() {
// std::cout << "EndPaint" << std::endl;
DCHECK(canvas_.get());
DCHECK(bitmap_.get());
@ -75,7 +69,6 @@ void OffScreenOutputDevice::SetActive(bool active) {
return;
active_ = active;
// Call OnPaint immediately if deactivated while a damage rect is pending.
if (!active_ && !pending_damage_rect_.IsEmpty())
OnPaint(pending_damage_rect_);
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
@ -9,7 +9,6 @@
#include "cc/output/software_output_device.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "base/callback.h"
namespace atom {

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
@ -26,14 +26,10 @@
#include "cc/scheduler/delay_based_time_source.h"
#include "content/public/browser/browser_thread.h"
#include <iostream>
const float kDefaultScaleFactor = 1.0;
const int kFrameRetryLimit = 2;
// const int kResizeLockTimeoutMs = 67;
namespace atom {
class AtomCopyFrameGenerator {
@ -619,6 +615,7 @@ void OffScreenRenderWidgetHostView::RenderProcessGone(base::TerminationStatus,in
}
void OffScreenRenderWidgetHostView::Destroy() {
delete this;
}
void OffScreenRenderWidgetHostView::SetTooltipText(const base::string16 &) {

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

View file

@ -1,17 +1,13 @@
#include "atom/browser/osr_render_widget_host_view.h"
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <algorithm>
#include <limits>
#include <utility>
#include <iostream>
#include "atom/browser/osr_render_widget_host_view.h"
#import <Cocoa/Cocoa.h>
#include "base/compiler_specific.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/view_messages.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/events/latency_info.h"
ui::AcceleratedWidgetMac* atom::OffScreenRenderWidgetHostView::GetAcceleratedWidgetMac()
const {
@ -20,7 +16,8 @@ ui::AcceleratedWidgetMac* atom::OffScreenRenderWidgetHostView::GetAcceleratedWid
return nullptr;
}
NSView* atom::OffScreenRenderWidgetHostView::AcceleratedWidgetGetNSView() const {
NSView* atom::OffScreenRenderWidgetHostView::AcceleratedWidgetGetNSView()
const {
return [window_ contentView];
}
@ -75,13 +72,11 @@ void atom::OffScreenRenderWidgetHostView::SelectionChanged(
}
void atom::OffScreenRenderWidgetHostView::CreatePlatformWidget() {
// Create a borderless non-visible 1x1 window.
window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
// Create a CALayer which is used by BrowserCompositorViewMac for rendering.
background_layer_ = [[[CALayer alloc] init] retain];
[background_layer_ setBackgroundColor:CGColorGetConstantColor(kCGColorClear)];
NSView* content_view = [window_ contentView];
@ -95,9 +90,6 @@ void atom::OffScreenRenderWidgetHostView::CreatePlatformWidget() {
browser_compositor_->accelerated_widget_mac()->SetNSView(this);
browser_compositor_->compositor()->SetVisible(true);
// CEF needs the browser compositor to remain responsive whereas normal
// rendering on OS X does not. This effectively reverts the changes from
// https://crbug.com/463988#c6
compositor_->SetLocksWillTimeOut(true);
browser_compositor_->Unsuspend();
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

View file

@ -1,11 +1,9 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/osr_web_contents_view.h"
#include "atom/browser/osr_render_widget_host_view.h"
#include <iostream>
namespace atom {
@ -21,95 +19,49 @@ void OffScreenWebContentsView::SetWebContents(
web_contents_ = web_contents;
}
// Returns the native widget that contains the contents of the tab.
gfx::NativeView OffScreenWebContentsView::GetNativeView() const {
// std::cout << "GetNativeView" << std::endl;
return gfx::NativeView();
}
// Returns the native widget with the main content of the tab (i.e. the main
// render view host, though there may be many popups in the tab as children of
// the container).
gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
// std::cout << "GetContentNativeView" << std::endl;
return gfx::NativeView();
}
// Returns the outermost native view. This will be used as the parent for
// dialog boxes.
gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
// std::cout << "GetTopLevelNativeWindow" << std::endl;
return gfx::NativeWindow();
}
// Computes the rectangle for the native widget that contains the contents of
// the tab in the screen coordinate system.
void OffScreenWebContentsView::GetContainerBounds(gfx::Rect* out) const {
// std::cout << "GetContainerBounds" << std::endl;
*out = GetViewBounds();
}
// TODO(brettw) this is a hack. It's used in two places at the time of this
// writing: (1) when render view hosts switch, we need to size the replaced
// one to be correct, since it wouldn't have known about sizes that happened
// while it was hidden; (2) in constrained windows.
//
// (1) will be fixed once interstitials are cleaned up. (2) seems like it
// should be cleaned up or done some other way, since this works for normal
// WebContents without the special code.
void OffScreenWebContentsView::SizeContents(const gfx::Size& size) {
// std::cout << "SizeContents" << std::endl;
}
// Sets focus to the native widget for this tab.
void OffScreenWebContentsView::Focus() {
// std::cout << "OffScreenWebContentsView::Focus" << std::endl;
}
// Sets focus to the appropriate element when the WebContents is shown the
// first time.
void OffScreenWebContentsView::SetInitialFocus() {
// std::cout << "SetInitialFocus" << std::endl;
}
// Stores the currently focused view.
void OffScreenWebContentsView::StoreFocus() {
// std::cout << "StoreFocus" << std::endl;
}
// Restores focus to the last focus view. If StoreFocus has not yet been
// invoked, SetInitialFocus is invoked.
void OffScreenWebContentsView::RestoreFocus() {
// std::cout << "RestoreFocus" << std::endl;
}
// Returns the current drop data, if any.
content::DropData* OffScreenWebContentsView::GetDropData() const {
// std::cout << "GetDropData" << std::endl;
return nullptr;
}
// Get the bounds of the View, relative to the parent.
gfx::Rect OffScreenWebContentsView::GetViewBounds() const {
// std::cout << "OffScreenWebContentsView::GetViewBounds" << std::endl;
return view_ ? view_->GetViewBounds() : gfx::Rect();
}
void OffScreenWebContentsView::CreateView(
const gfx::Size& initial_size, gfx::NativeView context){
std::cout << context << std::endl;
// std::cout << "CreateView" << std::endl;
// std::cout << initial_size.width() << "x" << initial_size.height() << std::endl;
void OffScreenWebContentsView::CreateView(const gfx::Size& initial_size,
gfx::NativeView context) {
}
// Sets up the View that holds the rendered web page, receives messages for
// it and contains page plugins. The host view should be sized to the current
// size of the WebContents.
//
// |is_guest_view_hack| is temporary hack and will be removed once
// RenderWidgetHostViewGuest is not dependent on platform view.
// TODO(lazyboy): Remove |is_guest_view_hack| once http://crbug.com/330264 is
// fixed.
content::RenderWidgetHostViewBase*
OffScreenWebContentsView::CreateViewForWidget(
content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
@ -119,7 +71,6 @@ content::RenderWidgetHostViewBase*
return view_;
}
// Creates a new View that holds a popup and receives messages for it.
content::RenderWidgetHostViewBase*
OffScreenWebContentsView::CreateViewForPopupWidget(
content::RenderWidgetHost* render_widget_host) {
@ -129,30 +80,18 @@ content::RenderWidgetHostViewBase*
return view_;
}
// Sets the page title for the native widgets corresponding to the view. This
// is not strictly necessary and isn't expected to be displayed anywhere, but
// can aid certain debugging tools such as Spy++ on Windows where you are
// trying to find a specific window.
void OffScreenWebContentsView::SetPageTitle(const base::string16& title) {
// std::cout << "SetPageTitle" << std::endl;
// std::cout << title << std::endl;
}
// Invoked when the WebContents is notified that the RenderView has been
// fully created.
void OffScreenWebContentsView::RenderViewCreated(content::RenderViewHost* host){
// std::cout << "RenderViewCreated" << std::endl;
void OffScreenWebContentsView::RenderViewCreated(
content::RenderViewHost* host) {
}
// Invoked when the WebContents is notified that the RenderView has been
// swapped in.
void OffScreenWebContentsView::RenderViewSwappedIn(content::RenderViewHost* host){
// std::cout << "RenderViewSwappedIn" << std::endl;
void OffScreenWebContentsView::RenderViewSwappedIn(
content::RenderViewHost* host) {
}
// Invoked to enable/disable overscroll gesture navigation.
void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled) {
// std::cout << "SetOverscrollControllerEnabled" << std::endl;
}
#if defined(OS_MACOSX)
@ -183,5 +122,4 @@ void OffScreenWebContentsView::UpdateDragCursor(
blink::WebDragOperation operation) {
}
} // namespace atom

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013 GitHub, Inc.
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
@ -20,10 +20,10 @@ public:
void SetWebContents(content::WebContents*);
// content::WebContentsView
gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override;
gfx::NativeWindow GetTopLevelNativeWindow() const override;
void GetContainerBounds(gfx::Rect* out) const override;
void SizeContents(const gfx::Size& size) override;
void Focus() override;
@ -32,16 +32,13 @@ public:
void RestoreFocus() override;
content::DropData* GetDropData() const override;
gfx::Rect GetViewBounds() const override;
void CreateView(
const gfx::Size& initial_size, gfx::NativeView context) override;
content::RenderWidgetHostViewBase* CreateViewForWidget(
content::RenderWidgetHost* render_widget_host,
bool is_guest_view_hack) override;
content::RenderWidgetHostViewBase* CreateViewForPopupWidget(
content::RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(content::RenderViewHost* host) override;
void RenderViewSwappedIn(content::RenderViewHost* host) override;

View file

@ -189,8 +189,6 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
command_line->AppendSwitch(cc::switches::kEnableBeginFrameScheduling);
command_line->AppendSwitch(cc::switches::kShowFPSCounter);
// command_line->AppendSwitch("disable-gpu");
// command_line->AppendSwitch("disable-gpu-compositing");
}
// static

View file

@ -274,6 +274,8 @@ The `webPreferences` option is an object that can have the following properties:
* `defaultEncoding` String - Defaults to `ISO-8859-1`.
* `backgroundThrottling` Boolean - Whether to throttle animations and timers
when the page becomes background. Defaults to `true`.
* `offscreen` Boolean - Whether to enable offscreen rendering for the browser
window. Defaults to `false`.
### Instance Events

View file

@ -174,6 +174,36 @@ logging level for all code in the source files under a `foo/bar` directory.
This switch only works when `--enable-logging` is also passed.
## --disable-gpu
Disables the use of the GPU in the renderer process. If this is set with the
`--disable-gpu-compositing` switch, *offscreen rendering* will use a software
output device, which has much better overall performance but lacks of WebGL
and 3D CSS support.
## --disable-gpu-compositing
Disables the use of the GPU compositing in the renderer process. This should be
set with the `--disable-gpu` switch for *offscreen rendering*.
``` javascript
const {app, BrowserWindow} = require('electron');
app.commandLine.appendSwitch('disable-gpu');
app.commandLine.appendSwitch('disable-gpu-compositing');
let win = new BrowserWindow({
webPreferences: {
offscreen: true
}
});
win.loadURL('http://github.com');
win.webContents.on('paint', (event, dirty, data) => {
updateBitmap(dirty, data);
});
```
[app]: app.md
[append-switch]: app.md#appcommandlineappendswitchswitch-value
[ready]: app.md#event-ready

View file

@ -452,6 +452,41 @@ app.on('ready', () => {
Emitted when a page's view is repainted.
#### Event: 'paint'
Returns:
* `event` Event
* `dirtyRect` Object
* `x` Number - the x coordinate on the bitmap
* `y` Number - the y coordinate on the bitmap
* `width` Number - the width of the dirty area
* `height` Number - the height of the dirty area
* `data` Buffer - the bitmap data of the dirty rect
* `bitmapSize` Object
* `width` Number - the width of the whole bitmap
* `height` Number - the height of the whole bitmap
Emitted when a new frame is generated. Only the dirty area is passed in the
buffer.
```javascript
const {BrowserWindow} = require('electron');
let win = new BrowserWindow({
width: 800,
height: 1500,
webPreferences: {
offscreen: true
}
});
win.loadURL('http://github.com');
win.webContents.on('paint', (event, dirty, data) => {
updateBitmap(dirty, data);
});
```
### Instance Methods
#### `contents.loadURL(url[, options])`
@ -1024,6 +1059,27 @@ win.webContents.on('did-finish-load', () => {
Shows pop-up dictionary that searches the selected word on the page.
#### `contents.startPainting()`
If *offscreen rendering* is enabled and not painting, start painting.
#### `contents.stopPainting()`
If *offscreen rendering* is enabled and painting, stop painting.
#### `contents.isPainting()`
If *offscreen rendering* is enabled returns whether it is currently painting.
#### `contents.setFrameRate(fps)`
If *offscreen rendering* is enabled sets the frame rate to the specified number.
Only values between 1 and 60 are accepted.
#### `contents.getFrameRate()`
If *offscreen rendering* is enabled returns the current frame rate.
### Instance Properties
#### `contents.id`

View file

@ -0,0 +1,58 @@
# Offscreen Rendering
Offscreen rendering lets you obtain the content of a browser window in a bitmap,
so it can be rendered anywhere, for example on a texture in a 3D scene. The
offscreen rendering in Electron uses a similar approach than the [Chromium
Embedded Framework](https://bitbucket.org/chromiumembedded/cef) project.
Two modes of rendering can be used and only the dirty area is passed in the
`'paint'` event to be more efficient. The rendering can be stopped, continued
and the frame rate can be set. The specified frame rate is a top limit value,
when there is nothing happening on a webpage, no frames are generated. The
maximum frame rate is 60, because above that there is no benefit, just
performance loss.
## Two modes of rendering
### GPU accelerated
GPU accelerated rendering means that the GPU is used for composition. Because of
that the frame has to be copied from the GPU which requires more performance,
thus this mode is quite a bit slower than the other one. The benefit of this
mode that WebGL and 3D CSS animations are supported.
### Software output device
This mode uses a software output device for rendering in the CPU, so the frame
generation is much faster, thus this mode is preferred over the GPU accelerated
one. To enable this mode GPU acceleration has to be disabled like this:
``` javascript
const {app} = require('electron');
app.commandLine.appendSwitch('disable-gpu');
app.commandLine.appendSwitch('disable-gpu-compositing');
```
## Usage
``` javascript
const {app, BrowserWindow} = require('electron');
app.commandLine.appendSwitch('disable-gpu');
app.commandLine.appendSwitch('disable-gpu-compositing');
let win = new BrowserWindow({
width: 800,
height: 1500,
webPreferences: {
offscreen: true
}
});
win.loadURL('http://github.com');
win.webContents.setFrameRate(30);
win.webContents.on('paint', (event, dirty, data) => {
updateBitmap(dirty, data);
});
```