diff options
-rw-r--r-- | o3d/core/cross/client.cc | 43 | ||||
-rw-r--r-- | o3d/core/cross/client.h | 8 | ||||
-rw-r--r-- | o3d/core/cross/renderer.h | 5 | ||||
-rw-r--r-- | o3d/plugin/linux/main_linux.cc | 10 | ||||
-rw-r--r-- | o3d/plugin/mac/plugin_mac.mm | 2 | ||||
-rw-r--r-- | o3d/plugin/win/main_win.cc | 2 |
6 files changed, 60 insertions, 10 deletions
diff --git a/o3d/core/cross/client.cc b/o3d/core/cross/client.cc index 271df8e42..f534ef3 100644 --- a/o3d/core/cross/client.cc +++ b/o3d/core/cross/client.cc @@ -65,6 +65,25 @@ using std::vector; using std::make_pair; namespace o3d { +// If Renderer::max_fps has been set, rendering is driven by incoming new +// textures. We draw on each new texture as long as not exceeding max_fps. +// +// If we are in RENDERMODE_ON_DEMAND mode, Client::Render() can still set dirty +// specifically. +// +// If we are in RENDERMODE_CONTINUOUS mode, we do NOT set dirty on each tick any +// more (since it is already driven by new textures.). +// There is one problem here: what if new texture don't come in for some reason? +// If that happened, no rendering callback will be invoked and this can cause +// problem sometimes. For example, some UI may depend on the rendering callback +// to work correctly. +// So, in RENDERMODE_CONTINUOUS mode, if we have set max_fps but haven't +// received any new texture for a while, we draw anyway to trigger the rendering +// callback. +// This value defines the minimum number of draws per seconds in +// RENDERMODE_CONTINUOUS mode. +static const float kContinuousModeMinDrawPerSecond = 15; +// TODO(zhurunz) Tuning this value. // Client constructor. Creates the default root node for the scenegraph Client::Client(ServiceLocator* service_locator) @@ -356,6 +375,30 @@ bool Client::IsRendering() { return (renderer_.IsAvailable() && renderer_->rendering()); } +bool Client::NeedsContinuousRender() { + // Sanity check + if (!renderer_.IsAvailable()) { + return false; + } + + bool needRender = false; + // Only may happen in RENDERMODE_CONTINUOUS mode. + if (render_mode() == RENDERMODE_CONTINUOUS) { + // Always need a draw in normal RENDERMODE_CONTINUOUS mode. + needRender = true; + + // If max_fps has been set, only need a draw when "long time no draw". + int max_fps = renderer_->max_fps(); + if (max_fps > 0 && + render_elapsed_time_timer_.GetElapsedTimeWithoutClearing() < + 1.0/kContinuousModeMinDrawPerSecond) + { + needRender = false; + } + } + return needRender; +} + // Executes draw calls for all visible shapes in a subtree void Client::RenderTree(RenderNode *tree_root) { if (!renderer_.IsAvailable()) diff --git a/o3d/core/cross/client.h b/o3d/core/cross/client.h index 1dcb36d..4affeb2 100644 --- a/o3d/core/cross/client.h +++ b/o3d/core/cross/client.h @@ -264,6 +264,14 @@ class Client { // the plugin to become reentrant. Detect this at a higher level. bool IsRendering(); + // If Renderer::max_fps has been set in RENDERMODE_CONTINUOUS mode, we don't + // draw on each tick but just let new textures drive the rendering. There is + // only one exception: if we haven't received any new textures for a while, we + // still need to draw in order to trigger rendering callback. Since there + // might be some UI depends on rendering callback. + // This function determines if this has happened and if we need a draw. + bool NeedsContinuousRender(); + // Sets the texture to use when a Texture or Sampler is missing while // rendering. If you set it to NULL you'll get an error if you try to render // something that is missing a needed Texture, Sampler or ParamSampler diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h index 76f18e2..3be95f4 100644 --- a/o3d/core/cross/renderer.h +++ b/o3d/core/cross/renderer.h @@ -210,9 +210,8 @@ class Renderer { need_to_render_ = need_to_render; } - // We only respect max_fps in RENDERMODE_ON_DEMAND. - // When max_fps is set to positive value in RENDERMODE_ON_DEMAND, - // we render on every new texture without exceeding max_fps. + // When max_fps is set to positive value, we render on every new texture as + // long as not exceeding max_fps. // Get max_fps int max_fps() const { diff --git a/o3d/plugin/linux/main_linux.cc b/o3d/plugin/linux/main_linux.cc index 7e3ffb3..d2d79af 100644 --- a/o3d/plugin/linux/main_linux.cc +++ b/o3d/plugin/linux/main_linux.cc @@ -83,7 +83,7 @@ void LinuxTimer(XtPointer data, XtIntervalId* id) { obj->client()->Tick(); obj->draw_ = true; if (obj->renderer()) { - if (obj->client()->render_mode() == o3d::Client::RENDERMODE_CONTINUOUS || + if (obj->client()->NeedsContinuousRender() || obj->renderer()->need_to_render()) { // NOTE: this draws no matter what instead of just invalidating the @@ -93,7 +93,7 @@ void LinuxTimer(XtPointer data, XtIntervalId* id) { } } obj->xt_interval_ = - XtAppAddTimeOut(obj->xt_app_context_, 10, LinuxTimer, obj); + XtAppAddTimeOut(obj->xt_app_context_, 8, LinuxTimer, obj); } void LinuxExposeHandler(Widget w, @@ -606,7 +606,7 @@ static gboolean GtkTimeoutCallback(gpointer user_data) { obj->draw_ = true; obj->client()->Tick(); if (obj->renderer()) { - if (obj->client()->render_mode() == o3d::Client::RENDERMODE_CONTINUOUS || + if (obj->client()->NeedsContinuousRender() || obj->renderer()->need_to_render()) { GtkWidget *widget; @@ -802,7 +802,7 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) { } gtk_widget_show(obj->gtk_container_); drawable = GDK_WINDOW_XID(obj->gtk_container_->window); - obj->timeout_id_ = g_timeout_add(10, GtkTimeoutCallback, obj); + obj->timeout_id_ = g_timeout_add(8, GtkTimeoutCallback, obj); } else { // No XEmbed support, the xwindow is a Xt Widget. Widget widget = XtWindowToWidget(display, xwindow); @@ -822,7 +822,7 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) { LinuxEnterLeaveHandler, obj); obj->xt_app_context_ = XtWidgetToApplicationContext(widget); obj->xt_interval_ = - XtAppAddTimeOut(obj->xt_app_context_, 10, LinuxTimer, obj); + XtAppAddTimeOut(obj->xt_app_context_, 8, LinuxTimer, obj); } // Create and assign the graphics context. diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm index 26c8f7c..66b8ba6 100644 --- a/o3d/plugin/mac/plugin_mac.mm +++ b/o3d/plugin/mac/plugin_mac.mm @@ -280,7 +280,7 @@ void RenderTimer::TimerCallback(CFRunLoopTimerRef timer, void* info) { obj->IsOffscreenRenderingEnabled(); if (plugin_visible && obj->renderer()) { - if (obj->client()->render_mode() == o3d::Client::RENDERMODE_CONTINUOUS || + if (obj->client()->NeedsContinuousRender() || obj->renderer()->need_to_render()) { // Force a sync to the VBL (once per timer callback) // to avoid tearing diff --git a/o3d/plugin/win/main_win.cc b/o3d/plugin/win/main_win.cc index 3f8a465..3042306 100644 --- a/o3d/plugin/win/main_win.cc +++ b/o3d/plugin/win/main_win.cc @@ -488,7 +488,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { // If rendering continuously, invalidate the window and force a paint if // it is visible. The paint invalidates the renderer and Tick will later // repaint the window. - if (obj->client()->render_mode() == o3d::Client::RENDERMODE_CONTINUOUS) { + if (obj->client()->NeedsContinuousRender()) { InvalidateRect(obj->GetHWnd(), NULL, FALSE); UpdateWindow(obj->GetHWnd()); } |