diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc
index b6b369580c81a..d742ec51c4cc0 100644
--- a/cc/resource_provider.cc
+++ b/cc/resource_provider.cc
@@ -322,6 +322,14 @@ double ResourceProvider::estimatedUploadsPerSecond()
     return m_textureUploader->estimatedTexturesPerSecond();
 }
 
+void ResourceProvider::flushUploads()
+{
+    if (!m_textureUploader)
+        return;
+
+    m_textureUploader->flush();
+}
+
 void ResourceProvider::flush()
 {
     DCHECK(Proxy::isImplThread());
@@ -508,7 +516,7 @@ bool ResourceProvider::initialize()
 
     m_textureCopier = AcceleratedTextureCopier::create(context3d, useBindUniform);
 
-    m_textureUploader = TextureUploader::create(context3d, useMapSub);
+    m_textureUploader = TextureUploader::create(context3d, useMapSub, m_useShallowFlush);
     GLC(context3d, context3d->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
     return true;
 }
diff --git a/cc/resource_provider.h b/cc/resource_provider.h
index f7db99c9a4fe1..e0cbd37216fe6 100644
--- a/cc/resource_provider.h
+++ b/cc/resource_provider.h
@@ -85,6 +85,7 @@ public:
     size_t numBlockingUploads();
     void markPendingUploadsAsNonBlocking();
     double estimatedUploadsPerSecond();
+    void flushUploads();
 
     // Flush all context operations, kicking uploads and ensuring ordering with
     // respect to other contexts.
diff --git a/cc/resource_update_controller.cc b/cc/resource_update_controller.cc
index 5295724ef1011..10c3b4db849bd 100644
--- a/cc/resource_update_controller.cc
+++ b/cc/resource_update_controller.cc
@@ -32,9 +32,6 @@ const double textureUpdateTickRate = 0.004;
 // Measured in seconds.
 const double uploaderBusyTickRate = 0.001;
 
-// Flush interval when performing texture uploads.
-const int textureUploadFlushPeriod = 4;
-
 // Number of blocking update intervals to allow.
 const size_t maxBlockingUpdateIntervals = 4;
 
@@ -193,25 +190,13 @@ void ResourceUpdateController::updateTexture(ResourceUpdate update)
 
 void ResourceUpdateController::finalize()
 {
-    size_t uploadCount = 0;
-    while (m_queue->fullUploadSize()) {
-        if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
-            m_resourceProvider->shallowFlushIfSupported();
-
+    while (m_queue->fullUploadSize())
         updateTexture(m_queue->takeFirstFullUpload());
-        uploadCount++;
-    }
-
-    while (m_queue->partialUploadSize()) {
-        if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
-            m_resourceProvider->shallowFlushIfSupported();
 
+    while (m_queue->partialUploadSize())
         updateTexture(m_queue->takeFirstPartialUpload());
-        uploadCount++;
-    }
 
-    if (uploadCount)
-        m_resourceProvider->shallowFlushIfSupported();
+    m_resourceProvider->flushUploads();
 
     if (m_queue->copySize()) {
         TextureCopier* copier = m_resourceProvider->textureCopier();
@@ -291,14 +276,10 @@ void ResourceUpdateController::updateMoreTexturesNow()
     if (!uploads)
         return;
 
-    size_t uploadCount = 0;
-    while (m_queue->fullUploadSize() && uploadCount < uploads) {
-        if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
-            m_resourceProvider->shallowFlushIfSupported();
+    while (m_queue->fullUploadSize() && uploads--)
         updateTexture(m_queue->takeFirstFullUpload());
-        uploadCount++;
-    }
-    m_resourceProvider->shallowFlushIfSupported();
+
+    m_resourceProvider->flushUploads();
 }
 
 }  // namespace cc
diff --git a/cc/texture_uploader.cc b/cc/texture_uploader.cc
index 6d4dc4fbefe64..5603d62e16e6e 100644
--- a/cc/texture_uploader.cc
+++ b/cc/texture_uploader.cc
@@ -31,6 +31,9 @@ static const size_t uploadHistorySizeInitial = 100;
 // More than one thread will not access this variable, so we do not need to synchronize access.
 static const double defaultEstimatedTexturesPerSecond = 48.0 * 60.0;
 
+// Flush interval when performing texture uploads.
+const int textureUploadFlushPeriod = 4;
+
 } // anonymous namespace
 
 namespace cc {
@@ -89,11 +92,15 @@ bool TextureUploader::Query::isNonBlocking()
 }
 
 TextureUploader::TextureUploader(
-    WebKit::WebGraphicsContext3D* context, bool useMapTexSubImage)
+    WebKit::WebGraphicsContext3D* context,
+    bool useMapTexSubImage,
+    bool useShallowFlush)
     : m_context(context)
     , m_numBlockingTextureUploads(0)
     , m_useMapTexSubImage(useMapTexSubImage)
     , m_subImageSize(0)
+    , m_useShallowFlush(useShallowFlush)
+    , m_numTextureUploadsSinceLastFlush(0)
 {
     for (size_t i = uploadHistorySizeInitial; i > 0; i--)
         m_texturesPerSecondHistory.insert(defaultEstimatedTexturesPerSecond);
@@ -173,6 +180,20 @@ void TextureUploader::upload(const uint8* image,
 
     if (isFullUpload)
         endQuery();
+
+    m_numTextureUploadsSinceLastFlush++;
+    if (m_numTextureUploadsSinceLastFlush >= textureUploadFlushPeriod)
+      flush();
+}
+
+void TextureUploader::flush() {
+  if (!m_numTextureUploadsSinceLastFlush)
+    return;
+
+  if (m_useShallowFlush)
+    m_context->shallowFlushCHROMIUM();
+
+  m_numTextureUploadsSinceLastFlush = 0;
 }
 
 void TextureUploader::uploadWithTexSubImage(const uint8* image,
diff --git a/cc/texture_uploader.h b/cc/texture_uploader.h
index 25b8d6bab0e02..decdbda68520e 100644
--- a/cc/texture_uploader.h
+++ b/cc/texture_uploader.h
@@ -28,9 +28,12 @@ namespace cc {
 class CC_EXPORT TextureUploader {
 public:
     static scoped_ptr<TextureUploader> create(
-        WebKit::WebGraphicsContext3D* context, bool useMapTexSubImage)
+        WebKit::WebGraphicsContext3D* context,
+        bool useMapTexSubImage,
+        bool useShallowFlush)
     {
-        return make_scoped_ptr(new TextureUploader(context, useMapTexSubImage));
+        return make_scoped_ptr(
+            new TextureUploader(context, useMapTexSubImage, useShallowFlush));
     }
     ~TextureUploader();
 
@@ -49,6 +52,8 @@ public:
                 GLenum format,
                 const gfx::Size& size);
 
+    void flush();
+
 private:
     class Query {
     public:
@@ -74,7 +79,9 @@ private:
         bool m_isNonBlocking;
     };
 
-    TextureUploader(WebKit::WebGraphicsContext3D*, bool useMapTexSubImage);
+    TextureUploader(WebKit::WebGraphicsContext3D*,
+                    bool useMapTexSubImage,
+                    bool useShallowFlush);
 
     void beginQuery();
     void endQuery();
@@ -101,6 +108,9 @@ private:
     size_t m_subImageSize;
     scoped_array<uint8> m_subImage;
 
+    bool m_useShallowFlush;
+    size_t m_numTextureUploadsSinceLastFlush;
+
     DISALLOW_COPY_AND_ASSIGN(TextureUploader);
 };
 
diff --git a/cc/texture_uploader_unittest.cc b/cc/texture_uploader_unittest.cc
index 783ea86c95c74..c3c1a7ef9a266 100644
--- a/cc/texture_uploader_unittest.cc
+++ b/cc/texture_uploader_unittest.cc
@@ -56,7 +56,7 @@ void uploadTexture(TextureUploader* uploader)
 TEST(TextureUploaderTest, NumBlockingUploads)
 {
     scoped_ptr<FakeWebGraphicsContext3DWithQueryTesting> fakeContext(new FakeWebGraphicsContext3DWithQueryTesting);
-    scoped_ptr<TextureUploader> uploader = TextureUploader::create(fakeContext.get(), false);
+    scoped_ptr<TextureUploader> uploader = TextureUploader::create(fakeContext.get(), false, false);
 
     fakeContext->setResultAvailable(0);
     EXPECT_EQ(0, uploader->numBlockingUploads());
@@ -77,7 +77,7 @@ TEST(TextureUploaderTest, NumBlockingUploads)
 TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking)
 {
     scoped_ptr<FakeWebGraphicsContext3DWithQueryTesting> fakeContext(new FakeWebGraphicsContext3DWithQueryTesting);
-    scoped_ptr<TextureUploader> uploader = TextureUploader::create(fakeContext.get(), false);
+    scoped_ptr<TextureUploader> uploader = TextureUploader::create(fakeContext.get(), false, false);
 
     fakeContext->setResultAvailable(0);
     EXPECT_EQ(0, uploader->numBlockingUploads());