Merge revision 739 changes:

- Add the ability to customize the animation frame rate (issue #697).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1025@740 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2012-08-14 23:34:56 +00:00
parent f0e11cc5df
commit 4a9c00b2e7
16 changed files with 128 additions and 113 deletions

View File

@ -224,6 +224,13 @@ typedef struct _cef_browser_settings_t {
///
bool history_disabled;
///
// The number of frames per second (fps) for the requestAnimationFrame timer
// and calls to CefRenderHandler::OnPaint(). The value must be between 0 and
// 90. Specify zero for the default frame rate of 30 fps.
///
int animation_frame_rate;
// The below values map to WebPreferences settings.
///

View File

@ -331,6 +331,7 @@ struct CefBrowserSettingsTraits {
target->drag_drop_disabled = src->drag_drop_disabled;
target->load_drops_disabled = src->load_drops_disabled;
target->history_disabled = src->history_disabled;
target->animation_frame_rate = src->animation_frame_rate;
cef_string_set(src->standard_font_family.str,
src->standard_font_family.length, &target->standard_font_family, copy);

View File

@ -92,6 +92,8 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) {
if (!settings_.developer_tools_disabled)
dev_tools_agent_->SetWebView(webviewhost_->webview());
webviewhost_->SetFrameRate(settings_.animation_frame_rate);
window_info_.m_Widget = webviewhost_->view_handle();
g_signal_connect(G_OBJECT(window_info_.m_Widget), "destroy",
G_CALLBACK(window_destroyed), this);

View File

@ -108,6 +108,8 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) {
if (!settings_.developer_tools_disabled)
dev_tools_agent_->SetWebView(webviewhost_->webview());
webviewhost_->SetFrameRate(settings_.animation_frame_rate);
BrowserWebView* browserView = (BrowserWebView*)webviewhost_->view_handle();
browserView.browser = this;
window_info_.m_View = browserView;

View File

@ -219,6 +219,8 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) {
if (!settings_.developer_tools_disabled)
dev_tools_agent_->SetWebView(webviewhost_->webview());
webviewhost_->SetFrameRate(settings_.animation_frame_rate);
Unlock();
if (!window_info_.m_bWindowRenderingDisabled) {

View File

@ -14,24 +14,15 @@
using webkit::npapi::WebPluginGeometry;
using WebKit::WebSize;
const int WebWidgetHost::kDefaultFrameRate = 30;
const int WebWidgetHost::kMaxFrameRate = 90;
void WebWidgetHost::ScheduleComposite() {
if (invalidate_timer_.IsRunning())
return;
// Try to paint at 60fps.
static int64 kDesiredRate = 16;
// Maintain the desired rate.
invalidate_timer_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kDesiredRate),
this,
&WebWidgetHost::Invalidate);
ScheduleInvalidateTimer();
}
void WebWidgetHost::ScheduleAnimation() {
ScheduleComposite();
ScheduleInvalidateTimer();
}
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
@ -49,6 +40,12 @@ void WebWidgetHost::UpdateRedrawRect(const gfx::Rect& rect) {
redraw_rect_ = redraw_rect_.Union(rect);
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
if (rect.IsEmpty())
return;
DidInvalidateRect(rect);
}
void WebWidgetHost::SetSize(int width, int height) {
webwidget_->resize(WebSize(width, height));
DidInvalidateRect(gfx::Rect(0, 0, width, height));
@ -98,28 +95,69 @@ gfx::PluginWindowHandle WebWidgetHost::GetWindowedPluginAt(int x, int y) {
return gfx::kNullPluginWindow;
}
void WebWidgetHost::SetFrameRate(int frames_per_second) {
if (frames_per_second <= 0)
frames_per_second = kDefaultFrameRate;
if (frames_per_second > kMaxFrameRate)
frames_per_second = kMaxFrameRate;
frame_delay_ = 1000 / frames_per_second;
}
void WebWidgetHost::ScheduleInvalidateTimer() {
if (invalidate_timer_.IsRunning())
return;
// Maintain the desired rate.
base::TimeDelta delta = base::TimeTicks::Now() - last_invalidate_time_;
int64 actualRate = delta.InMilliseconds();
if (actualRate >= frame_delay_)
delta = base::TimeDelta::FromMilliseconds(1);
else
delta = base::TimeDelta::FromMilliseconds(frame_delay_ - actualRate);
invalidate_timer_.Start(
FROM_HERE,
delta,
this,
&WebWidgetHost::DoInvalidate);
}
void WebWidgetHost::DoInvalidate() {
if (!webwidget_)
return;
WebSize size = webwidget_->size();
InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
last_invalidate_time_ = base::TimeTicks::Now();
}
void WebWidgetHost::SchedulePaintTimer() {
if (layouting_ || paint_timer_.IsRunning())
return;
// Maintain the desired rate.
base::TimeDelta delta = base::TimeTicks::Now() - last_paint_time_;
int64 actualRate = delta.InMilliseconds();
if (actualRate >= frame_delay_)
delta = base::TimeDelta::FromMilliseconds(1);
else
delta = base::TimeDelta::FromMilliseconds(frame_delay_ - actualRate);
paint_timer_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(0), // Fire immediately.
delta,
this,
&WebWidgetHost::DoPaint);
}
void WebWidgetHost::DoPaint() {
if (MessageLoop::current()->IsIdle()) {
// Paint to the delegate.
#if defined(OS_MACOSX)
SkRegion region;
Paint(region);
SkRegion region;
Paint(region);
#else
Paint();
Paint();
#endif
} else {
// Try again later.
SchedulePaintTimer();
}
last_paint_time_ = base::TimeTicks::Now();
}

View File

@ -85,10 +85,6 @@ class WebWidgetHost {
// Called for requestAnimationFrame animations.
void ScheduleAnimation();
// Invalidate the complete client area. This is called at a reasonable frame
// rate by the Schedule*() methods.
void Invalidate();
#if defined(OS_WIN)
void SetCursor(HCURSOR cursor);
#endif
@ -139,6 +135,8 @@ class WebWidgetHost {
void MoveWindowedPlugin(const webkit::npapi::WebPluginGeometry& geometry);
gfx::PluginWindowHandle GetWindowedPluginAt(int x, int y);
void SetFrameRate(int frames_per_second);
void set_popup(bool popup) { popup_ = popup; }
bool popup() { return popup_; }
@ -147,6 +145,10 @@ class WebWidgetHost {
protected:
WebWidgetHost();
// Called from the Schedule*() methods.
void ScheduleInvalidateTimer();
void DoInvalidate();
// If window rendering is disabled paint messages are generated after all
// other pending messages have been processed.
void SchedulePaintTimer();
@ -240,9 +242,13 @@ class WebWidgetHost {
// Used to coalesce DidInvalidateRect() events into a single DoPaint() call.
// Used when window rendering is disabled.
base::OneShotTimer<WebWidgetHost> paint_timer_;
base::TimeTicks last_paint_time_;
// Used to coalesce Schedule*() events into a single Invalidate() call.
base::OneShotTimer<WebWidgetHost> invalidate_timer_;
base::TimeTicks last_invalidate_time_;
int64 frame_delay_;
#if defined(OS_WIN)
// Used to call UpdateImeInputState() while IME is active.
@ -293,6 +299,9 @@ class WebWidgetHost {
bool painting_;
bool layouting_;
static const int kDefaultFrameRate;
static const int kMaxFrameRate;
};
#endif // CEF_LIBCEF_WEBWIDGET_HOST_H_

View File

@ -290,26 +290,14 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
DidInvalidateRect(clip_rect);
}
void WebWidgetHost::Invalidate() {
int width = logical_size_.width();
int height = logical_size_.height();
GdkRectangle grect = {
0,
0,
width,
height
};
GdkWindow* window = view_->window;
gdk_window_invalidate_rect(window, &grect, 0);
}
WebWidgetHost::WebWidgetHost()
: view_(NULL),
paint_delegate_(NULL),
webwidget_(NULL),
canvas_w_(0),
canvas_h_(0),
popup_(false) {
popup_(false),
frame_delay_(1000 / kDefaultFrameRate) {
set_painting(false);
}
@ -406,11 +394,6 @@ void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) {
if (!canvas_.get())
return false;

View File

@ -82,6 +82,7 @@ WebWidgetHost::WebWidgetHost()
canvas_w_(0),
canvas_h_(0),
popup_(false),
frame_delay_(1000 / kDefaultFrameRate),
mouse_modifiers_(0),
painting_(false),
layouting_(false) {
@ -320,25 +321,10 @@ void WebWidgetHost::Paint(SkRegion& update_rgn) {
}
}
void WebWidgetHost::Invalidate() {
if (!webwidget_)
return;
WebSize size = webwidget_->size();
InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
}
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
if (rect.IsEmpty())
return;
DidInvalidateRect(rect);
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) {
if (!canvas_.get())
return false;

View File

@ -316,13 +316,6 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
::InvalidateRect(view_, &r, FALSE);
}
void WebWidgetHost::Invalidate() {
if (!webwidget_)
return;
WebSize size = webwidget_->size();
InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
}
void WebWidgetHost::SetCursor(HCURSOR cursor) {
DCHECK(view_);
SetClassLong(view_, GCL_HCURSOR,
@ -338,6 +331,7 @@ WebWidgetHost::WebWidgetHost()
canvas_h_(0),
popup_(false),
track_mouse_leave_(false),
frame_delay_(1000 / kDefaultFrameRate),
tooltip_view_(NULL),
tooltip_showing_(false),
ime_notification_(false),
@ -530,13 +524,6 @@ void WebWidgetHost::Paint() {
}
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
if (rect.IsEmpty())
return;
DidInvalidateRect(rect);
}
bool WebWidgetHost::GetImage(int width, int height, void* buffer) {
const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false);
DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config);

View File

@ -11,11 +11,6 @@ patches = [
'name': 'build',
'path': '../build/',
},
{
# http://codereview.chromium.org/6730028/
'name': 'base',
'path': '../base/',
},
{
# http://code.google.com/p/gyp/issues/detail?id=223
# http://codereview.chromium.org/10383117/

View File

@ -1,33 +0,0 @@
Index: message_loop.cc
===================================================================
--- message_loop.cc (revision 119867)
+++ message_loop.cc (working copy)
@@ -362,9 +362,13 @@
}
void MessageLoop::AssertIdle() const {
+ DCHECK(IsIdle());
+}
+
+bool MessageLoop::IsIdle() const {
// We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
base::AutoLock lock(incoming_queue_lock_);
- DCHECK(incoming_queue_.empty());
+ return incoming_queue_.empty();
}
bool MessageLoop::is_running() const {
Index: message_loop.h
===================================================================
--- message_loop.h (revision 119867)
+++ message_loop.h (working copy)
@@ -345,6 +345,9 @@
// Asserts that the MessageLoop is "idle".
void AssertIdle() const;
+ // Returns true if the MessageLoop is "idle".
+ bool IsIdle() const;
+
#if defined(OS_WIN)
void set_os_modal_loop(bool os_modal_loop) {
os_modal_loop_ = os_modal_loop;

View File

@ -297,6 +297,10 @@ void AppGetBrowserSettings(CefBrowserSettings& settings) {
g_command_line->HasSwitch(cefclient::kLoadDropsDisabled);
settings.history_disabled =
g_command_line->HasSwitch(cefclient::kHistoryDisabled);
settings.animation_frame_rate = GetIntValue(
g_command_line->GetSwitchValue(cefclient::kAnimationFrameRate));
settings.remote_fonts_disabled =
g_command_line->HasSwitch(cefclient::kRemoteFontsDisabled);

View File

@ -38,6 +38,7 @@ const char kPackLoadingDisabled[] = "pack-loading-disabled";
const char kDragDropDisabled[] = "drag-drop-disabled";
const char kLoadDropsDisabled[] = "load-drops-disabled";
const char kHistoryDisabled[] = "history-disabled";
const char kAnimationFrameRate[] = "animation-frame-rate";
const char kRemoteFontsDisabled[] = "remote-fonts-disabled";
const char kDefaultEncoding[] = "default-encoding";
const char kEncodingDetectorEnabled[] = "encoding-detector-enabled";

View File

@ -40,6 +40,7 @@ extern const char kPackLoadingDisabled[];
extern const char kDragDropDisabled[];
extern const char kLoadDropsDisabled[];
extern const char kHistoryDisabled[];
extern const char kAnimationFrameRate[];
extern const char kRemoteFontsDisabled[];
extern const char kDefaultEncoding[];
extern const char kEncodingDetectorEnabled[];

View File

@ -64,6 +64,11 @@ class ClientOSRHandler : public CefClient,
~ClientOSRHandler() {
}
// Called immediately before the plugin is destroyed.
void Detach() {
plugin_ = NULL;
}
// CefClient methods
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
return this;
@ -202,6 +207,9 @@ class ClientOSRHandler : public CefClient,
CefRect& rect) OVERRIDE {
REQUIRE_UI_THREAD();
if (!plugin_)
return false;
// The simulated screen and view rectangle are the same. This is necessary
// for popup menus to be located and sized inside the view.
RECT clientRect;
@ -225,6 +233,9 @@ class ClientOSRHandler : public CefClient,
int& screenY) OVERRIDE {
REQUIRE_UI_THREAD();
if (!plugin_)
return false;
// Convert the point from view coordinates to actual screen coordinates.
POINT screen_pt = {viewX, viewY};
MapWindowPoints(plugin_->hWnd, HWND_DESKTOP, &screen_pt, 1);
@ -236,12 +247,20 @@ class ClientOSRHandler : public CefClient,
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) OVERRIDE {
REQUIRE_UI_THREAD();
if (!plugin_)
return;
plugin_->renderer.OnPopupShow(browser, show);
}
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) OVERRIDE {
REQUIRE_UI_THREAD();
if (!plugin_)
return;
plugin_->renderer.OnPopupSize(browser, rect);
}
@ -251,6 +270,9 @@ class ClientOSRHandler : public CefClient,
const void* buffer) OVERRIDE {
REQUIRE_UI_THREAD();
if (!plugin_)
return;
wglMakeCurrent(plugin_->hDC, plugin_->hRC);
plugin_->renderer.OnPaint(browser, type, dirtyRects, buffer);
}
@ -259,6 +281,9 @@ class ClientOSRHandler : public CefClient,
CefCursorHandle cursor) OVERRIDE {
REQUIRE_UI_THREAD();
if (!plugin_)
return;
// Change the plugin window's cursor.
SetClassLong(plugin_->hWnd, GCL_HCURSOR,
static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor)));
@ -357,6 +382,11 @@ NPError NPP_DestroyImpl(NPP instance, NPSavedData** save) {
ClientPlugin* plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
if (plugin) {
if (g_offscreenBrowser.get()) {
CefRefPtr<ClientOSRHandler> handler =
static_cast<ClientOSRHandler*>(g_offscreenBrowser->GetClient().get());
handler->Detach();
}
if (plugin->hWnd) {
DestroyWindow(plugin->hWnd);
DisableGL(plugin);