summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--o3d/core/cross/client.cc43
-rw-r--r--o3d/core/cross/client.h8
-rw-r--r--o3d/core/cross/renderer.h5
-rw-r--r--o3d/plugin/linux/main_linux.cc10
-rw-r--r--o3d/plugin/mac/plugin_mac.mm2
-rw-r--r--o3d/plugin/win/main_win.cc2
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());
}