Index: content/renderer/gpu/render_widget_compositor.cc |
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc |
index e7a7e3e0f5957e9b99ffc5f6c7c6e9b9e2f1b987..7878af85c19a575556679d095ed418b851b8862c 100644 |
--- a/content/renderer/gpu/render_widget_compositor.cc |
+++ b/content/renderer/gpu/render_widget_compositor.cc |
@@ -7,6 +7,10 @@ |
#include <limits> |
#include <string> |
+#if defined(OS_ANDROID) |
+#include "base/android/sys_utils.h" |
+#endif |
+ |
#include "base/command_line.h" |
#include "base/logging.h" |
#include "base/strings/string_number_conversions.h" |
@@ -286,6 +290,30 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( |
} |
#endif |
+// If we raster too fast we become upload bound, and pending |
+// uploads consume memory. For maximum upload throughput, we would |
+// want to allow for upload_throughput * pipeline_time of pending |
+// uploads, after which we are just wasting memory. Since we don't |
+// know our upload throughput yet, this just caps our memory usage. |
+#if defined(OS_ANDROID) |
+ size_t divider = 1; |
+ if (base::android::SysUtils::IsLowEndDevice()) |
+ divider = 3; |
+ |
+ // For reference Nexus10 can upload 1MB in about 2.5ms. |
+ const size_t kMaxBytesUploadedPerMs = (2 * 1024 * 1024) / (5 * divider); |
+#else |
+ // For reference Chromebook Pixel can upload 1MB in about 0.5ms. |
+ const size_t kMaxBytesUploadedPerMs = 1024 * 1024 * 2; |
+#endif |
+ |
+ // Assuming a two frame deep pipeline. |
+ const size_t kMsPerFrame = 16; |
+ settings.max_transfer_buffer_usage_bytes |
+ = 2 * kMsPerFrame * kMaxBytesUploadedPerMs; |
+ compositor->SetMaxTransferBufferUsageBytes( |
+ settings.max_transfer_buffer_usage_bytes); |
+ |
if (!compositor->initialize(settings)) |
return scoped_ptr<RenderWidgetCompositor>(); |
@@ -296,7 +324,8 @@ RenderWidgetCompositor::RenderWidgetCompositor(RenderWidget* widget, |
bool threaded) |
: threaded_(threaded), |
suppress_schedule_composite_(false), |
- widget_(widget) { |
+ widget_(widget), |
+ max_transfer_buffer_usage_bytes_(0) { |
} |
RenderWidgetCompositor::~RenderWidgetCompositor() {} |
@@ -552,7 +581,8 @@ void RenderWidgetCompositor::ApplyScrollAndScale(gfx::Vector2d scroll_delta, |
scoped_ptr<cc::OutputSurface> RenderWidgetCompositor::CreateOutputSurface( |
bool fallback) { |
- return widget_->CreateOutputSurface(fallback); |
+ return widget_->CreateOutputSurface(fallback, |
+ max_transfer_buffer_usage_bytes_); |
} |
void RenderWidgetCompositor::DidInitializeOutputSurface(bool success) { |
@@ -593,4 +623,9 @@ RenderWidgetCompositor::OffscreenContextProviderForCompositorThread() { |
OffscreenContextProviderForCompositorThread(); |
} |
+void RenderWidgetCompositor::SetMaxTransferBufferUsageBytes( |
+ size_t max_transfer_buffer_usage_bytes) { |
+ max_transfer_buffer_usage_bytes_ = max_transfer_buffer_usage_bytes; |
+} |
+ |
} // namespace content |