Add a new CefBrowserHost::SetWindowlessFrameRate method to support

dynamic configuration of the windowless frame rate (issue #1629).
This commit is contained in:
Marshall Greenblatt 2015-05-13 11:43:50 -04:00
parent 42341b40fa
commit 483a841348
17 changed files with 252 additions and 19 deletions

View File

@ -505,6 +505,26 @@ typedef struct _cef_browser_host_t {
void (CEF_CALLBACK *notify_move_or_resize_started)(
struct _cef_browser_host_t* self);
///
// Returns the maximum rate in frames per second (fps) that
// cef_render_handler_t:: OnPaint will be called for a windowless browser. The
// actual fps may be lower if the browser cannot generate frames at the
// requested rate. The minimum value is 1 and the maximum value is 60 (default
// 30). This function can only be called on the UI thread.
///
int (CEF_CALLBACK *get_windowless_frame_rate)(
struct _cef_browser_host_t* self);
///
// Set the maximum rate in frames per second (fps) that cef_render_handler_t::
// OnPaint will be called for a windowless browser. The actual fps may be
// lower if the browser cannot generate frames at the requested rate. The
// minimum value is 1 and the maximum value is 60 (default 30). Can also be
// set at browser creation via cef_browser_tSettings.windowless_frame_rate.
///
void (CEF_CALLBACK *set_windowless_frame_rate)(
struct _cef_browser_host_t* self, int frame_rate);
///
// Get the NSTextInputContext implementation for enabling IME on Mac when
// window rendering is disabled.

View File

@ -555,6 +555,26 @@ class CefBrowserHost : public virtual CefBase {
/*--cef()--*/
virtual void NotifyMoveOrResizeStarted() =0;
///
// Returns the maximum rate in frames per second (fps) that CefRenderHandler::
// OnPaint will be called for a windowless browser. The actual fps may be
// lower if the browser cannot generate frames at the requested rate. The
// minimum value is 1 and the maximum value is 60 (default 30). This method
// can only be called on the UI thread.
///
/*--cef()--*/
virtual int GetWindowlessFrameRate() =0;
///
// Set the maximum rate in frames per second (fps) that CefRenderHandler::
// OnPaint will be called for a windowless browser. The actual fps may be
// lower if the browser cannot generate frames at the requested rate. The
// minimum value is 1 and the maximum value is 60 (default 30). Can also be
// set at browser creation via CefBrowserSettings.windowless_frame_rate.
///
/*--cef()--*/
virtual void SetWindowlessFrameRate(int frame_rate) =0;
///
// Get the NSTextInputContext implementation for enabling IME on Mac when
// window rendering is disabled.

View File

@ -477,7 +477,8 @@ typedef struct _cef_browser_settings_t {
// The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint
// will be called for a windowless browser. The actual fps may be lower if
// the browser cannot generate frames at the requested rate. The minimum
// value is 1 and the maximum value is 60 (default 30).
// value is 1 and the maximum value is 60 (default 30). This value can also be
// changed dynamically via CefBrowserHost::SetWindowlessFrameRate.
///
int windowless_frame_rate;

View File

@ -1267,6 +1267,40 @@ void CefBrowserHostImpl::NotifyMoveOrResizeStarted() {
PlatformNotifyMoveOrResizeStarted();
}
int CefBrowserHostImpl::GetWindowlessFrameRate() {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
NOTREACHED() << "called on invalid thread";
return 0;
}
return CefRenderWidgetHostViewOSR::ClampFrameRate(
settings_.windowless_frame_rate);
}
void CefBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::SetWindowlessFrameRate, this,
frame_rate));
return;
}
if (!IsWindowless())
return;
settings_.windowless_frame_rate = frame_rate;
if (!web_contents())
return;
CefRenderWidgetHostViewOSR* view =
static_cast<CefRenderWidgetHostViewOSR*>(
web_contents()->GetRenderViewHost()->GetView());
if (view)
view->UpdateFrameRate();
}
// CefBrowser methods.
// -----------------------------------------------------------------------------

View File

@ -192,6 +192,8 @@ class CefBrowserHostImpl : public CefBrowserHost,
void SendFocusEvent(bool setFocus) override;
void SendCaptureLostEvent() override;
void NotifyMoveOrResizeStarted() override;
int GetWindowlessFrameRate() override;
void SetWindowlessFrameRate(int frame_rate) override;
CefTextInputContext GetNSTextInputContext() override;
void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) override;
void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) override;

View File

@ -172,6 +172,10 @@ class CefCopyFrameGenerator {
bool frame_pending() const { return frame_pending_; }
void set_frame_rate_threshold_ms(int frame_rate_threshold_ms) {
frame_rate_threshold_ms_ = frame_rate_threshold_ms;
}
private:
void InternalGenerateCopyFrame() {
frame_pending_ = false;
@ -375,7 +379,7 @@ class CefCopyFrameGenerator {
}
}
const int frame_rate_threshold_ms_;
int frame_rate_threshold_ms_;
CefRenderWidgetHostViewOSR* view_;
base::TimeTicks frame_start_time_;
@ -411,6 +415,12 @@ class CefBeginFrameTimer : public cc::TimeSourceClient {
return time_source_->Active();
}
void SetFrameRateThresholdMs(int frame_rate_threshold_ms) {
time_source_->SetTimebaseAndInterval(
time_source_->Now(),
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms));
}
private:
// cc::TimerSourceClient implementation.
void OnTimerTick() override {
@ -1182,6 +1192,11 @@ void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) {
}
}
void CefRenderWidgetHostViewOSR::UpdateFrameRate() {
frame_rate_threshold_ms_ = 0;
SetFrameRate();
}
void CefRenderWidgetHostViewOSR::HoldResize() {
if (!hold_resize_)
hold_resize_ = true;
@ -1233,6 +1248,15 @@ void CefRenderWidgetHostViewOSR::OnPaint(
ReleaseResize();
}
// static
int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
if (frame_rate < 1)
return kDefaultFrameRate;
else if (frame_rate > kMaximumFrameRate)
return kMaximumFrameRate;
return frame_rate;
}
void CefRenderWidgetHostViewOSR::SetFrameRate() {
DCHECK(browser_impl_.get());
if (!browser_impl_.get())
@ -1242,24 +1266,29 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() {
if (frame_rate_threshold_ms_ != 0)
return;
int frame_rate = browser_impl_->settings().windowless_frame_rate;
if (frame_rate < 1)
frame_rate = kDefaultFrameRate;
else if (frame_rate > kMaximumFrameRate)
frame_rate = kMaximumFrameRate;
const int frame_rate =
ClampFrameRate(browser_impl_->settings().windowless_frame_rate);
frame_rate_threshold_ms_ = 1000 / frame_rate;
// Configure the VSync interval for the browser process.
compositor_->vsync_manager()->SetAuthoritativeVSyncInterval(
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms_));
if (copy_frame_generator_.get()) {
copy_frame_generator_->set_frame_rate_threshold_ms(
frame_rate_threshold_ms_);
}
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableBeginFrameScheduling)) {
DCHECK(!begin_frame_timer_.get());
begin_frame_timer_.reset(new CefBeginFrameTimer(
frame_rate_threshold_ms_,
base::Bind(&CefRenderWidgetHostViewOSR::OnBeginFrameTimerTick,
weak_ptr_factory_.GetWeakPtr())));
if (begin_frame_timer_.get()) {
begin_frame_timer_->SetFrameRateThresholdMs(frame_rate_threshold_ms_);
} else {
begin_frame_timer_.reset(new CefBeginFrameTimer(
frame_rate_threshold_ms_,
base::Bind(&CefRenderWidgetHostViewOSR::OnBeginFrameTimerTick,
weak_ptr_factory_.GetWeakPtr())));
}
}
}

View File

@ -234,6 +234,7 @@ class CefRenderWidgetHostViewOSR
void SendMouseEvent(const blink::WebMouseEvent& event);
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
void SendFocusEvent(bool focus);
void UpdateFrameRate();
void HoldResize();
void ReleaseResize();
@ -269,6 +270,8 @@ class CefRenderWidgetHostViewOSR
content::RenderWidgetHostImpl* render_widget_host() const
{ return render_widget_host_; }
static int ClampFrameRate(int frame_rate);
private:
void SetFrameRate();
void SetDeviceScaleFactor();

View File

@ -676,6 +676,34 @@ void CEF_CALLBACK browser_host_notify_move_or_resize_started(
CefBrowserHostCppToC::Get(self)->NotifyMoveOrResizeStarted();
}
int CEF_CALLBACK browser_host_get_windowless_frame_rate(
struct _cef_browser_host_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
int _retval = CefBrowserHostCppToC::Get(self)->GetWindowlessFrameRate();
// Return type: simple
return _retval;
}
void CEF_CALLBACK browser_host_set_windowless_frame_rate(
struct _cef_browser_host_t* self, int frame_rate) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefBrowserHostCppToC::Get(self)->SetWindowlessFrameRate(
frame_rate);
}
cef_text_input_context_t CEF_CALLBACK browser_host_get_nstext_input_context(
struct _cef_browser_host_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -879,6 +907,10 @@ CefBrowserHostCppToC::CefBrowserHostCppToC() {
GetStruct()->send_capture_lost_event = browser_host_send_capture_lost_event;
GetStruct()->notify_move_or_resize_started =
browser_host_notify_move_or_resize_started;
GetStruct()->get_windowless_frame_rate =
browser_host_get_windowless_frame_rate;
GetStruct()->set_windowless_frame_rate =
browser_host_set_windowless_frame_rate;
GetStruct()->get_nstext_input_context = browser_host_get_nstext_input_context;
GetStruct()->handle_key_event_before_text_input_client =
browser_host_handle_key_event_before_text_input_client;

View File

@ -563,6 +563,32 @@ void CefBrowserHostCToCpp::NotifyMoveOrResizeStarted() {
_struct->notify_move_or_resize_started(_struct);
}
int CefBrowserHostCToCpp::GetWindowlessFrameRate() {
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_windowless_frame_rate))
return 0;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->get_windowless_frame_rate(_struct);
// Return type: simple
return _retval;
}
void CefBrowserHostCToCpp::SetWindowlessFrameRate(int frame_rate) {
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, set_windowless_frame_rate))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->set_windowless_frame_rate(_struct,
frame_rate);
}
CefTextInputContext CefBrowserHostCToCpp::GetNSTextInputContext() {
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_nstext_input_context))

View File

@ -77,6 +77,8 @@ class CefBrowserHostCToCpp
void SendFocusEvent(bool setFocus) OVERRIDE;
void SendCaptureLostEvent() OVERRIDE;
void NotifyMoveOrResizeStarted() OVERRIDE;
int GetWindowlessFrameRate() OVERRIDE;
void SetWindowlessFrameRate(int frame_rate) OVERRIDE;
CefTextInputContext GetNSTextInputContext() OVERRIDE;
void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) OVERRIDE;
void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) OVERRIDE;

View File

@ -38,7 +38,10 @@
#define ID_TESTS_ZOOM_IN 32710
#define ID_TESTS_ZOOM_OUT 32711
#define ID_TESTS_ZOOM_RESET 32712
#define ID_TESTS_LAST 32712
#define ID_TESTS_FPS_INCREASE 32713
#define ID_TESTS_FPS_DECREASE 32714
#define ID_TESTS_FPS_RESET 32715
#define ID_TESTS_LAST 32715
#define IDC_STATIC -1
#define IDS_BINDING 1000
#define IDS_DIALOGS 1001

View File

@ -588,6 +588,11 @@ GtkWidget* RootWindowGtk::CreateMenuBar() {
AddMenuEntry(test_menu, "Zoom In", ID_TESTS_ZOOM_IN);
AddMenuEntry(test_menu, "Zoom Out", ID_TESTS_ZOOM_OUT);
AddMenuEntry(test_menu, "Zoom Reset", ID_TESTS_ZOOM_RESET);
if (with_osr_) {
AddMenuEntry(test_menu, "FPS Increase", ID_TESTS_FPS_INCREASE);
AddMenuEntry(test_menu, "FPS Decrease", ID_TESTS_FPS_DECREASE);
AddMenuEntry(test_menu, "FPS Reset", ID_TESTS_FPS_RESET);
}
AddMenuEntry(test_menu, "Begin Tracing", ID_TESTS_TRACING_BEGIN);
AddMenuEntry(test_menu, "End Tracing", ID_TESTS_TRACING_END);
AddMenuEntry(test_menu, "Print", ID_TESTS_PRINT);

View File

@ -46,6 +46,7 @@ INT_PTR CALLBACK AboutWndProc(HWND hDlg, UINT message,
RootWindowWin::RootWindowWin()
: delegate_(NULL),
with_controls_(false),
with_osr_(false),
is_popup_(false),
start_rect_(),
initialized_(false),
@ -86,13 +87,14 @@ void RootWindowWin::Init(RootWindow::Delegate* delegate,
delegate_ = delegate;
with_controls_ = with_controls;
with_osr_ = with_osr;
start_rect_.left = bounds.x;
start_rect_.top = bounds.y;
start_rect_.right = bounds.x + bounds.width;
start_rect_.bottom = bounds.y + bounds.height;
CreateBrowserWindow(with_osr, url);
CreateBrowserWindow(url);
initialized_ = true;
@ -117,6 +119,7 @@ void RootWindowWin::InitAsPopup(RootWindow::Delegate* delegate,
delegate_ = delegate;
with_controls_ = with_controls;
with_osr_ = with_osr;
is_popup_ = true;
if (popupFeatures.xSet)
@ -128,7 +131,7 @@ void RootWindowWin::InitAsPopup(RootWindow::Delegate* delegate,
if (popupFeatures.heightSet)
start_rect_.bottom = start_rect_.top + popupFeatures.height;
CreateBrowserWindow(with_osr, std::string());
CreateBrowserWindow(std::string());
initialized_ = true;
@ -199,9 +202,8 @@ ClientWindowHandle RootWindowWin::GetWindowHandle() const {
return hwnd_;
}
void RootWindowWin::CreateBrowserWindow(bool with_osr,
const std::string& startup_url) {
if (with_osr) {
void RootWindowWin::CreateBrowserWindow(const std::string& startup_url) {
if (with_osr_) {
OsrRenderer::Settings settings;
MainContext::Get()->PopulateOsrSettings(&settings);
browser_window_.reset(new BrowserWindowOsrWin(this, startup_url, settings));
@ -316,6 +318,19 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings) {
SetUserDataPtr(edit_hwnd_, this);
rect.top += URLBAR_HEIGHT;
if (!with_osr_) {
// Remove the menu items that are only used with OSR.
HMENU hMenu = ::GetMenu(hwnd_);
if (hMenu) {
HMENU hTestMenu = ::GetSubMenu(hMenu, 2);
if (hTestMenu) {
::RemoveMenu(hTestMenu, ID_TESTS_FPS_INCREASE, MF_BYCOMMAND);
::RemoveMenu(hTestMenu, ID_TESTS_FPS_DECREASE, MF_BYCOMMAND);
::RemoveMenu(hTestMenu, ID_TESTS_FPS_RESET, MF_BYCOMMAND);
}
}
}
} else {
// No controls so also remove the default menu.
::SetMenu(hwnd_, NULL);

View File

@ -49,7 +49,7 @@ class RootWindowWin : public RootWindow,
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
void CreateBrowserWindow(bool with_osr, const std::string& startup_url);
void CreateBrowserWindow(const std::string& startup_url);
void CreateRootWindow(const CefBrowserSettings& settings);
// Register the root window class.
@ -97,6 +97,7 @@ class RootWindowWin : public RootWindow,
// Members set during initialization.
RootWindow::Delegate* delegate_;
bool with_controls_;
bool with_osr_;
bool is_popup_;
RECT start_rect_;
scoped_ptr<BrowserWindow> browser_window_;

View File

@ -171,6 +171,29 @@ void ModifyZoom(CefRefPtr<CefBrowser> browser, double delta) {
browser->GetHost()->GetZoomLevel() + delta);
}
void ModifyFPS(CefRefPtr<CefBrowser> browser, int fps_delta) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&ModifyFPS, browser, fps_delta));
return;
}
int fps;
if (fps_delta == 0) {
// Reset to the default value.
CefBrowserSettings settings;
MainContext::Get()->PopulateBrowserSettings(&settings);
fps = settings.windowless_frame_rate;
} else {
// Modify the existing value.
fps = browser->GetHost()->GetWindowlessFrameRate() + fps_delta;
if (fps <= 0)
fps = 1;
}
browser->GetHost()->SetWindowlessFrameRate(fps);
}
void BeginTracing() {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
@ -318,6 +341,15 @@ void RunTest(CefRefPtr<CefBrowser> browser, int id) {
case ID_TESTS_ZOOM_RESET:
browser->GetHost()->SetZoomLevel(0.0);
break;
case ID_TESTS_FPS_INCREASE:
ModifyFPS(browser, 10);
break;
case ID_TESTS_FPS_DECREASE:
ModifyFPS(browser, -10);
break;
case ID_TESTS_FPS_RESET:
ModifyFPS(browser, 0);
break;
case ID_TESTS_TRACING_BEGIN:
BeginTracing();
break;

View File

@ -135,6 +135,11 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) {
AddMenuItem(testMenu, @"Zoom In", ID_TESTS_ZOOM_IN);
AddMenuItem(testMenu, @"Zoom Out", ID_TESTS_ZOOM_OUT);
AddMenuItem(testMenu, @"Zoom Reset", ID_TESTS_ZOOM_RESET);
if (with_osr_) {
AddMenuItem(testMenu, @"FPS Increase", ID_TESTS_FPS_INCREASE);
AddMenuItem(testMenu, @"FPS Decrease", ID_TESTS_FPS_DECREASE);
AddMenuItem(testMenu, @"FPS Reset", ID_TESTS_FPS_RESET);
}
AddMenuItem(testMenu, @"Begin Tracing", ID_TESTS_TRACING_BEGIN);
AddMenuItem(testMenu, @"End Tracing", ID_TESTS_TRACING_END);
AddMenuItem(testMenu, @"Print", ID_TESTS_PRINT);

View File

@ -80,6 +80,9 @@ BEGIN
MENUITEM "Zoom In", ID_TESTS_ZOOM_IN
MENUITEM "Zoom Out", ID_TESTS_ZOOM_OUT
MENUITEM "Zoom Reset", ID_TESTS_ZOOM_RESET
MENUITEM "FPS Increase", ID_TESTS_FPS_INCREASE
MENUITEM "FPS Decrease", ID_TESTS_FPS_DECREASE
MENUITEM "FPS Reset", ID_TESTS_FPS_RESET
MENUITEM "Begin Tracing", ID_TESTS_TRACING_BEGIN
MENUITEM "End Tracing", ID_TESTS_TRACING_END
MENUITEM "Print", ID_TESTS_PRINT