summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-22 20:32:05 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-22 20:32:05 +0000
commit0a4517266a77d10a276d6c674efafc79e4c7f7a5 (patch)
tree88b095919aa268128698e980d9b780b09f839aad /cc
parent3395887c69c58e75b084ef919dc88fd037bb9bc0 (diff)
downloadchromium_src-0a4517266a77d10a276d6c674efafc79e4c7f7a5.zip
chromium_src-0a4517266a77d10a276d6c674efafc79e4c7f7a5.tar.gz
chromium_src-0a4517266a77d10a276d6c674efafc79e4c7f7a5.tar.bz2
cc: Route offscreen context creation for compositor to the browser.
Currently the compositor asks WebKit for the SharedGraphicsContext. For the browser compositor, we instead route requests for an offscreen context to ui/compositor, where we are able to create the context. This patch only addresses offscreen contexts for the browser compositor. The renderer compositor still gets its contexts from WebKit, but now via the LayerTreeHostClient interface instead of directly going to the WebSharedGraphicsContext3D. Tested by the lost context unit tests. They now test that on context loss, the shared context is also recreated, and that if it fails to be recreated that we retry context creation. BUG=169373,175383 Review URL: https://chromiumcodereview.appspot.com/12212007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184165 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/cc.gyp1
-rw-r--r--cc/cc_tests.gyp2
-rw-r--r--cc/context_provider.h42
-rw-r--r--cc/gl_renderer.cc103
-rw-r--r--cc/layer.cc15
-rw-r--r--cc/layer_tree_host.cc6
-rw-r--r--cc/layer_tree_host.h9
-rw-r--r--cc/layer_tree_host_client.h9
-rw-r--r--cc/layer_tree_host_unittest_context.cc234
-rw-r--r--cc/occlusion_tracker_unittest.cc1
-rw-r--r--cc/render_surface_filters.cc7
-rw-r--r--cc/render_surface_filters.h3
-rw-r--r--cc/resource_provider.cc7
-rw-r--r--cc/resource_provider.h6
-rw-r--r--cc/resource_update_controller.cc38
-rw-r--r--cc/resource_update_controller.h7
-rw-r--r--cc/resource_update_controller_unittest.cc5
-rw-r--r--cc/single_thread_proxy.cc31
-rw-r--r--cc/single_thread_proxy.h4
-rw-r--r--cc/test/fake_context_provider.cc61
-rw-r--r--cc/test/fake_context_provider.h45
-rw-r--r--cc/test/fake_layer_tree_host_client.cc23
-rw-r--r--cc/test/fake_layer_tree_host_client.h14
-rw-r--r--cc/test/layer_tree_test_common.cc37
-rw-r--r--cc/test/layer_tree_test_common.h15
-rw-r--r--cc/test/test_web_graphics_context_3d.cc4
-rw-r--r--cc/test/test_web_graphics_context_3d.h6
-rw-r--r--cc/thread_proxy.cc40
-rw-r--r--cc/thread_proxy.h6
-rw-r--r--cc/tiled_layer_unittest.cc3
30 files changed, 647 insertions, 137 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 3e013b5..5a8d084 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -35,6 +35,7 @@
'content_layer_updater.h',
'contents_scaling_layer.cc',
'contents_scaling_layer.h',
+ 'context_provider.h',
'damage_tracker.cc',
'damage_tracker.h',
'debug_border_draw_quad.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index ccfdf3f..1361914 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -79,6 +79,8 @@
'test/fake_content_layer_client.h',
'test/fake_content_layer_impl.cc',
'test/fake_content_layer_impl.h',
+ 'test/fake_context_provider.cc',
+ 'test/fake_context_provider.h',
'test/fake_impl_proxy.h',
'test/fake_output_surface.h',
'test/fake_layer_tree_host_client.cc',
diff --git a/cc/context_provider.h b/cc/context_provider.h
new file mode 100644
index 0000000..ffb4822f
--- /dev/null
+++ b/cc/context_provider.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_CONTEXT_PROVIDER_H_
+#define CC_CONTEXT_PROVIDER_H_
+
+#include "base/memory/ref_counted.h"
+
+class GrContext;
+namespace WebKit { class WebGraphicsContext3D; }
+
+namespace cc {
+
+class ContextProvider : public base::RefCountedThreadSafe<ContextProvider> {
+ public:
+ // Initialize and create a 3d context. This must be called from the main
+ // thread. Calling it more than once should have no effect.
+ virtual bool InitializeOnMainThread() = 0;
+
+ // Bind the 3d context to the current thread. This should be called before
+ // accessing the contexts. Calling it more than once should have no effect.
+ // Once this function has been called, the class should only be accessed
+ // from the same thread.
+ virtual bool BindToCurrentThread() = 0;
+
+ virtual WebKit::WebGraphicsContext3D* Context3d() = 0;
+ virtual class GrContext* GrContext() = 0;
+
+ // Ask the provider to check if the contexts are valid or lost. If they are,
+ // this should invalidate the provider so that it can be replaced with a new
+ // one.
+ virtual void VerifyContexts() = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<ContextProvider>;
+ virtual ~ContextProvider() {}
+};
+
+} // namespace cc
+
+#endif // CC_CONTEXT_PROVIDER_H_
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index 7189960..6a4413d 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -15,6 +15,7 @@
#include "build/build_config.h"
#include "cc/compositor_frame.h"
#include "cc/compositor_frame_metadata.h"
+#include "cc/context_provider.h"
#include "cc/damage_tracker.h"
#include "cc/geometry_binding.h"
#include "cc/gl_frame_data.h"
@@ -31,7 +32,6 @@
#include "cc/video_layer_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebSharedGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -45,7 +45,6 @@
using WebKit::WebGraphicsContext3D;
using WebKit::WebGraphicsMemoryAllocation;
-using WebKit::WebSharedGraphicsContext3D;
namespace cc {
@@ -155,6 +154,8 @@ bool GLRenderer::initialize()
// so we only need to avoid POT textures if we have an NPOT fast-path.
m_capabilities.avoidPow2Textures = extensions.count("GL_CHROMIUM_fast_NPOT_MO8_textures");
+ m_capabilities.usingOffscreenContext3d = true;
+
m_isUsingBindUniform = extensions.count("GL_CHROMIUM_bind_uniform_location");
// Make sure scissoring starts as disabled.
@@ -372,67 +373,71 @@ void GLRenderer::drawDebugBorderQuad(const DrawingFrame& frame, const DebugBorde
GLC(context(), context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0));
}
-static WebGraphicsContext3D* getFilterContext(bool hasImplThread)
-{
- if (hasImplThread)
- return WebSharedGraphicsContext3D::compositorThreadContext();
- else
- return WebSharedGraphicsContext3D::mainThreadContext();
-}
-
-static GrContext* getFilterGrContext(bool hasImplThread)
-{
- if (hasImplThread)
- return WebSharedGraphicsContext3D::compositorThreadGrContext();
- else
- return WebSharedGraphicsContext3D::mainThreadGrContext();
-}
-
-static inline SkBitmap applyFilters(GLRenderer* renderer, const WebKit::WebFilterOperations& filters, ScopedResource* sourceTexture, bool hasImplThread)
+static inline SkBitmap applyFilters(GLRenderer* renderer, const WebKit::WebFilterOperations& filters, ScopedResource* sourceTextureResource)
{
if (filters.isEmpty())
return SkBitmap();
- WebGraphicsContext3D* filterContext = getFilterContext(hasImplThread);
- GrContext* filterGrContext = getFilterGrContext(hasImplThread);
-
- if (!filterContext || !filterGrContext)
+ cc::ContextProvider* offscreenContexts = renderer->resourceProvider()->offscreenContextProvider();
+ if (!offscreenContexts || !offscreenContexts->Context3d() || !offscreenContexts->GrContext())
return SkBitmap();
- renderer->context()->flush();
+ ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTextureResource->id());
+
+ // Flush the compositor context to ensure that textures there are available
+ // in the shared context. Do this after locking/creating the compositor
+ // texture.
+ renderer->resourceProvider()->flush();
- ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id());
- SkBitmap source = RenderSurfaceFilters::apply(filters, lock.textureId(), sourceTexture->size(), filterContext, filterGrContext);
+ // Make sure skia uses the correct GL context.
+ offscreenContexts->Context3d()->makeContextCurrent();
+
+ SkBitmap source = RenderSurfaceFilters::apply(filters, lock.textureId(), sourceTextureResource->size(), offscreenContexts->GrContext());
+
+ // Flush skia context so that all the rendered stuff appears on the
+ // texture.
+ offscreenContexts->GrContext()->flush();
+
+ // Flush the GL context so rendering results from this context are
+ // visible in the compositor's context.
+ offscreenContexts->Context3d()->flush();
+
+ // Use the compositor's GL context again.
+ renderer->resourceProvider()->graphicsContext3D()->makeContextCurrent();
return source;
}
-static SkBitmap applyImageFilter(GLRenderer* renderer, SkImageFilter* filter, ScopedResource* sourceTexture, bool hasImplThread)
+static SkBitmap applyImageFilter(GLRenderer* renderer, SkImageFilter* filter, ScopedResource* sourceTextureResource)
{
if (!filter)
return SkBitmap();
- WebGraphicsContext3D* context3d = getFilterContext(hasImplThread);
- GrContext* grContext = getFilterGrContext(hasImplThread);
-
- if (!context3d || !grContext)
+ cc::ContextProvider* offscreenContexts = renderer->resourceProvider()->offscreenContextProvider();
+ if (!offscreenContexts || !offscreenContexts->Context3d() || !offscreenContexts->GrContext())
return SkBitmap();
- renderer->context()->flush();
+ ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTextureResource->id());
- ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id());
+ // Flush the compositor context to ensure that textures there are available
+ // in the shared context. Do this after locking/creating the compositor
+ // texture.
+ renderer->resourceProvider()->flush();
+
+ // Make sure skia uses the correct GL context.
+ offscreenContexts->Context3d()->makeContextCurrent();
// Wrap the source texture in a Ganesh platform texture.
GrBackendTextureDesc backendTextureDescription;
- backendTextureDescription.fWidth = sourceTexture->size().width();
- backendTextureDescription.fHeight = sourceTexture->size().height();
+ backendTextureDescription.fWidth = sourceTextureResource->size().width();
+ backendTextureDescription.fHeight = sourceTextureResource->size().height();
backendTextureDescription.fConfig = kSkia8888_GrPixelConfig;
backendTextureDescription.fTextureHandle = lock.textureId();
backendTextureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
- skia::RefPtr<GrTexture> texture = skia::AdoptRef(grContext->wrapBackendTexture(backendTextureDescription));
+ skia::RefPtr<GrTexture> texture = skia::AdoptRef(offscreenContexts->GrContext()->wrapBackendTexture(backendTextureDescription));
// Place the platform texture inside an SkBitmap.
SkBitmap source;
- source.setConfig(SkBitmap::kARGB_8888_Config, sourceTexture->size().width(), sourceTexture->size().height());
+ source.setConfig(SkBitmap::kARGB_8888_Config, sourceTextureResource->size().width(), sourceTextureResource->size().height());
skia::RefPtr<SkGrPixelRef> pixelRef = skia::AdoptRef(new SkGrPixelRef(texture.get()));
source.setPixelRef(pixelRef.get());
@@ -444,11 +449,11 @@ static SkBitmap applyImageFilter(GLRenderer* renderer, SkImageFilter* filter, Sc
desc.fHeight = source.height();
desc.fConfig = kSkia8888_GrPixelConfig;
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
- GrAutoScratchTexture scratchTexture(grContext, desc, GrContext::kExact_ScratchTexMatch);
+ GrAutoScratchTexture scratchTexture(offscreenContexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch);
skia::RefPtr<GrTexture> backingStore = skia::AdoptRef(scratchTexture.detach());
// Create a device and canvas using that backing store.
- SkGpuDevice device(grContext, backingStore.get());
+ SkGpuDevice device(offscreenContexts->GrContext(), backingStore.get());
SkCanvas canvas(&device);
// Draw the source bitmap through the filter to the canvas.
@@ -456,8 +461,18 @@ static SkBitmap applyImageFilter(GLRenderer* renderer, SkImageFilter* filter, Sc
paint.setImageFilter(filter);
canvas.clear(0x0);
canvas.drawSprite(source, 0, 0, &paint);
- canvas.flush();
- context3d->flush();
+
+ // Flush skia context so that all the rendered stuff appears on the
+ // texture.
+ offscreenContexts->GrContext()->flush();
+
+ // Flush the GL context so rendering results from this context are
+ // visible in the compositor's context.
+ offscreenContexts->Context3d()->flush();
+
+ // Use the compositor's GL context again.
+ renderer->resourceProvider()->graphicsContext3D()->makeContextCurrent();
+
return device.accessBitmap(false);
}
@@ -505,7 +520,7 @@ scoped_ptr<ScopedResource> GLRenderer::drawBackgroundFilters(
if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
return scoped_ptr<ScopedResource>();
- SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgroundTexture.get(), m_client->hasImplThread());
+ SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgroundTexture.get());
if (!filteredDeviceBackground.getTexture())
return scoped_ptr<ScopedResource>();
@@ -558,9 +573,9 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
// Apply filters to the contents texture.
SkBitmap filterBitmap;
if (quad->filter) {
- filterBitmap = applyImageFilter(this, quad->filter.get(), contentsTexture, m_client->hasImplThread());
+ filterBitmap = applyImageFilter(this, quad->filter.get(), contentsTexture);
} else {
- filterBitmap = applyFilters(this, quad->filters, contentsTexture, m_client->hasImplThread());
+ filterBitmap = applyFilters(this, quad->filters, contentsTexture);
}
// Draw the background texture if there is one.
diff --git a/cc/layer.cc b/cc/layer.cc
index 1f22bad..d78afaf 100644
--- a/cc/layer.cc
+++ b/cc/layer.cc
@@ -97,6 +97,9 @@ void Layer::setLayerTreeHost(LayerTreeHost* host)
if (host && m_layerAnimationController->hasAnyAnimation())
host->setNeedsCommit();
+ if (host && (!m_filters.isEmpty() || !m_backgroundFilters.isEmpty() || m_filter))
+ m_layerTreeHost->setNeedsFilterContext();
+
}
void Layer::setNeedsCommit()
@@ -365,8 +368,8 @@ void Layer::setFilters(const WebKit::WebFilterOperations& filters)
DCHECK(!m_filter);
m_filters = filters;
setNeedsCommit();
- if (!filters.isEmpty())
- LayerTreeHost::setNeedsFilterContext(true);
+ if (!filters.isEmpty() && m_layerTreeHost)
+ m_layerTreeHost->setNeedsFilterContext();
}
void Layer::setFilter(const skia::RefPtr<SkImageFilter>& filter)
@@ -376,8 +379,8 @@ void Layer::setFilter(const skia::RefPtr<SkImageFilter>& filter)
DCHECK(m_filters.isEmpty());
m_filter = filter;
setNeedsCommit();
- if (filter)
- LayerTreeHost::setNeedsFilterContext(true);
+ if (filter && m_layerTreeHost)
+ m_layerTreeHost->setNeedsFilterContext();
}
void Layer::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters)
@@ -386,8 +389,8 @@ void Layer::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFi
return;
m_backgroundFilters = backgroundFilters;
setNeedsCommit();
- if (!backgroundFilters.isEmpty())
- LayerTreeHost::setNeedsFilterContext(true);
+ if (!backgroundFilters.isEmpty() && m_layerTreeHost)
+ m_layerTreeHost->setNeedsFilterContext();
}
void Layer::setOpacity(float opacity)
diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc
index 3d97269..eff03f6 100644
--- a/cc/layer_tree_host.cc
+++ b/cc/layer_tree_host.cc
@@ -36,8 +36,6 @@ static int numLayerTreeInstances;
namespace cc {
-bool LayerTreeHost::s_needsFilterContext = false;
-
RendererCapabilities::RendererCapabilities()
: bestTextureFormat(0)
, usingPartialSwap(false)
@@ -48,6 +46,7 @@ RendererCapabilities::RendererCapabilities()
, usingDiscardBackbuffer(false)
, usingEglImage(false)
, allowPartialTextureUpdates(false)
+ , usingOffscreenContext3d(false)
, maxTextureSize(0)
, avoidPow2Textures(false)
{
@@ -73,6 +72,7 @@ scoped_ptr<LayerTreeHost> LayerTreeHost::create(LayerTreeHostClient* client, con
LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings)
: m_animating(false)
, m_needsFullTreeSync(true)
+ , m_needsFilterContext(false)
, m_client(client)
, m_commitNumber(0)
, m_renderingStats()
@@ -183,6 +183,8 @@ LayerTreeHost::RecreateResult LayerTreeHost::recreateOutputSurface()
return RecreateSucceeded;
}
+ m_client->willRetryRecreateOutputSurface();
+
// Tolerate a certain number of recreation failures to work around races
// in the output-surface-lost machinery.
m_numFailedRecreateAttempts++;
diff --git a/cc/layer_tree_host.h b/cc/layer_tree_host.h
index aae0400..40e5c25 100644
--- a/cc/layer_tree_host.h
+++ b/cc/layer_tree_host.h
@@ -69,6 +69,7 @@ struct CC_EXPORT RendererCapabilities {
bool usingDiscardBackbuffer;
bool usingEglImage;
bool allowPartialTextureUpdates;
+ bool usingOffscreenContext3d;
int maxTextureSize;
bool avoidPow2Textures;
};
@@ -83,9 +84,8 @@ public:
// Returns true if any LayerTreeHost is alive.
static bool anyLayerTreeHostInstanceExists();
- static bool needsFilterContext() { return s_needsFilterContext; }
- static void setNeedsFilterContext(bool needsFilterContext) { s_needsFilterContext = needsFilterContext; }
- bool needsSharedContext() const { return needsFilterContext() || settings().acceleratePainting; }
+ void setNeedsFilterContext() { m_needsFilterContext = true; }
+ bool needsOffscreenContext() const { return m_needsFilterContext || settings().acceleratePainting; }
// LayerTreeHost interface to Proxy.
void willBeginFrame() { m_client->willBeginFrame(); }
@@ -233,6 +233,7 @@ private:
bool m_animating;
bool m_needsFullTreeSync;
+ bool m_needsFilterContext;
base::CancelableClosure m_prepaintCallback;
@@ -277,8 +278,6 @@ private:
scoped_ptr<AnimationRegistrar> m_animationRegistrar;
- static bool s_needsFilterContext;
-
DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
};
diff --git a/cc/layer_tree_host_client.h b/cc/layer_tree_host_client.h
index 25d93aef..f2b9a14 100644
--- a/cc/layer_tree_host_client.h
+++ b/cc/layer_tree_host_client.h
@@ -5,6 +5,7 @@
#ifndef CC_LAYER_TREE_HOST_CLIENT_H_
#define CC_LAYER_TREE_HOST_CLIENT_H_
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
namespace gfx {
@@ -12,6 +13,7 @@ class Vector2d;
}
namespace cc {
+class ContextProvider;
class InputHandler;
class OutputSurface;
@@ -34,6 +36,13 @@ public:
// Used only in the single-threaded path.
virtual void scheduleComposite() = 0;
+ // These must always return a valid ContextProvider. But the provider does not need to be capable of creating contexts.
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForMainThread() = 0;
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForCompositorThread() = 0;
+
+ // This hook is for testing.
+ virtual void willRetryRecreateOutputSurface() {}
+
protected:
virtual ~LayerTreeHostClient() { }
};
diff --git a/cc/layer_tree_host_unittest_context.cc b/cc/layer_tree_host_unittest_context.cc
index 41ebbfd..0147ca9 100644
--- a/cc/layer_tree_host_unittest_context.cc
+++ b/cc/layer_tree_host_unittest_context.cc
@@ -19,6 +19,7 @@
#include "cc/test/fake_content_layer.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_content_layer_impl.h"
+#include "cc/test/fake_context_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_scrollbar_layer.h"
#include "cc/test/fake_scrollbar_theme_painter.h"
@@ -33,6 +34,7 @@
#include "cc/video_layer_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "media/base/media.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations.h"
using media::VideoFrame;
using WebKit::WebGraphicsContext3D;
@@ -53,7 +55,13 @@ class LayerTreeHostContextTest : public ThreadedTest {
times_to_lose_during_draw_(0),
times_to_fail_recreate_(0),
times_to_fail_reinitialize_(0),
- times_to_lose_on_recreate_(0) {
+ times_to_lose_on_recreate_(0),
+ times_to_fail_create_offscreen_(0),
+ times_to_fail_recreate_offscreen_(0),
+ times_to_expect_recreate_retried_(0),
+ times_recreate_retried_(0),
+ times_offscreen_created_(0),
+ committed_at_least_once_(false) {
media::InitializeMediaLibraryForTesting();
}
@@ -70,6 +78,7 @@ class LayerTreeHostContextTest : public ThreadedTest {
virtual scoped_ptr<OutputSurface> createOutputSurface() OVERRIDE {
if (times_to_fail_create_) {
--times_to_fail_create_;
+ ExpectRecreateToRetry();
return scoped_ptr<OutputSurface>();
}
@@ -82,29 +91,88 @@ class LayerTreeHostContextTest : public ThreadedTest {
// The number of times MakeCurrent succeeds is not important, and
// can be changed if needed to make this pass with future changes.
context3d_->set_times_make_current_succeeds(2);
+ ExpectRecreateToRetry();
} else if (times_to_lose_on_create_) {
--times_to_lose_on_create_;
LoseContext();
+ ExpectRecreateToRetry();
}
return FakeOutputSurface::Create3d(
context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>();
}
- virtual bool prepareToDrawOnThread(
- LayerTreeHostImpl*, LayerTreeHostImpl::FrameData&, bool result)
- OVERRIDE {
- EXPECT_TRUE(result);
- if (!times_to_lose_during_draw_)
- return result;
+ scoped_ptr<TestWebGraphicsContext3D> CreateOffscreenContext3d() {
+ if (!context3d_)
+ return scoped_ptr<TestWebGraphicsContext3D>();
- --times_to_lose_during_draw_;
- if (context3d_)
- context3d_->set_times_make_current_succeeds(0);
- return result;
+ ++times_offscreen_created_;
+
+ if (times_to_fail_create_offscreen_) {
+ --times_to_fail_create_offscreen_;
+ ExpectRecreateToRetry();
+ return scoped_ptr<TestWebGraphicsContext3D>();
+ }
+
+ scoped_ptr<TestWebGraphicsContext3D> offscreen_context3d =
+ TestWebGraphicsContext3D::Create().Pass();
+ DCHECK(offscreen_context3d);
+ context3d_->add_share_group_context(offscreen_context3d.get());
+
+ return offscreen_context3d.Pass();
+ }
+
+ virtual scoped_refptr<cc::ContextProvider>
+ OffscreenContextProviderForMainThread() OVERRIDE {
+ DCHECK(!implThread());
+
+ if (!offscreen_contexts_main_thread_ ||
+ offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
+ offscreen_contexts_main_thread_ = new FakeContextProvider(
+ base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
+ base::Unretained(this)));
+ }
+ return offscreen_contexts_main_thread_;
+ }
+
+ virtual scoped_refptr<cc::ContextProvider>
+ OffscreenContextProviderForCompositorThread() OVERRIDE {
+ DCHECK(implThread());
+
+ if (!offscreen_contexts_compositor_thread_ ||
+ offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
+ offscreen_contexts_compositor_thread_ = new FakeContextProvider(
+ base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
+ base::Unretained(this)));
}
+ return offscreen_contexts_compositor_thread_;
+ }
+
+ virtual bool prepareToDrawOnThread(
+ LayerTreeHostImpl*, LayerTreeHostImpl::FrameData&, bool result)
+ OVERRIDE {
+ EXPECT_TRUE(result);
+ if (!times_to_lose_during_draw_)
+ return result;
+
+ --times_to_lose_during_draw_;
+ context3d_->set_times_make_current_succeeds(0);
+
+ times_to_fail_create_ = times_to_fail_recreate_;
+ times_to_fail_recreate_ = 0;
+ times_to_fail_initialize_ = times_to_fail_reinitialize_;
+ times_to_fail_reinitialize_ = 0;
+ times_to_lose_on_create_ = times_to_lose_on_recreate_;
+ times_to_lose_on_recreate_ = 0;
+ times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
+ times_to_fail_recreate_offscreen_ = 0;
+
+ return result;
+ }
virtual void commitCompleteOnThread(LayerTreeHostImpl *host_impl) OVERRIDE {
+ committed_at_least_once_ = true;
+
if (!times_to_lose_during_commit_)
return;
--times_to_lose_during_commit_;
@@ -116,6 +184,22 @@ class LayerTreeHostContextTest : public ThreadedTest {
times_to_fail_reinitialize_ = 0;
times_to_lose_on_create_ = times_to_lose_on_recreate_;
times_to_lose_on_recreate_ = 0;
+ times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
+ times_to_fail_recreate_offscreen_ = 0;
+ }
+
+ virtual void willRetryRecreateOutputSurface() OVERRIDE {
+ ++times_recreate_retried_;
+ }
+
+ virtual void TearDown() OVERRIDE {
+ ThreadedTest::TearDown();
+ EXPECT_EQ(times_to_expect_recreate_retried_, times_recreate_retried_);
+ }
+
+ void ExpectRecreateToRetry() {
+ if (committed_at_least_once_)
+ ++times_to_expect_recreate_retried_;
}
protected:
@@ -128,6 +212,15 @@ class LayerTreeHostContextTest : public ThreadedTest {
int times_to_fail_reinitialize_;
int times_to_fail_recreate_;
int times_to_lose_on_recreate_;
+ int times_to_fail_create_offscreen_;
+ int times_to_fail_recreate_offscreen_;
+ int times_to_expect_recreate_retried_;
+ int times_recreate_retried_;
+ int times_offscreen_created_;
+ bool committed_at_least_once_;
+
+ scoped_refptr<FakeContextProvider> offscreen_contexts_main_thread_;
+ scoped_refptr<FakeContextProvider> offscreen_contexts_compositor_thread_;
};
class LayerTreeHostContextTestLostContextSucceeds :
@@ -151,8 +244,8 @@ class LayerTreeHostContextTestLostContextSucceeds :
}
virtual void afterTest() OVERRIDE {
- EXPECT_EQ(8, test_case_);
- EXPECT_EQ(6 + 10 + 10, num_losses_);
+ EXPECT_EQ(10, test_case_);
+ EXPECT_EQ(8 + 10 + 10, num_losses_);
}
virtual void didCommitAndDrawFrame() OVERRIDE {
@@ -185,36 +278,56 @@ class LayerTreeHostContextTestLostContextSucceeds :
3, // times_to_fail_reinitialize
0, // times_to_fail_recreate
0, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
3, // times_to_fail_reinitialize
0, // times_to_fail_recreate
0, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
{ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
0, // times_to_fail_reinitialize
3, // times_to_fail_recreate
0, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
0, // times_to_fail_reinitialize
3, // times_to_fail_recreate
0, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
{ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
3, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
{ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
3, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
+ },
+ { 1, // times_to_lose_during_commit
+ 0, // times_to_lose_during_draw
+ 0, // times_to_fail_reinitialize
+ 0, // times_to_fail_recreate
+ 0, // times_to_lose_on_recreate
+ 3, // times_to_fail_recreate_offscreen
+ },
+ { 0, // times_to_lose_during_commit
+ 1, // times_to_lose_during_draw
+ 0, // times_to_fail_reinitialize
+ 0, // times_to_fail_recreate
+ 0, // times_to_lose_on_recreate
+ 3, // times_to_fail_recreate_offscreen
},
// Losing the context and recreating it any number of times should
// succeed.
@@ -223,12 +336,14 @@ class LayerTreeHostContextTestLostContextSucceeds :
0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
0, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
{ 0, // times_to_lose_during_commit
10, // times_to_lose_during_draw
0, // times_to_fail_reinitialize
0, // times_to_fail_recreate
0, // times_to_lose_on_recreate
+ 0, // times_to_fail_recreate_offscreen
},
};
@@ -242,6 +357,8 @@ class LayerTreeHostContextTestLostContextSucceeds :
times_to_fail_reinitialize_ = kTests[test_case_].times_to_fail_reinitialize;
times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
times_to_lose_on_recreate_ = kTests[test_case_].times_to_lose_on_recreate;
+ times_to_fail_recreate_offscreen_ =
+ kTests[test_case_].times_to_fail_recreate_offscreen;
++test_case_;
return true;
}
@@ -252,9 +369,10 @@ class LayerTreeHostContextTestLostContextSucceeds :
int times_to_fail_reinitialize;
int times_to_fail_recreate;
int times_to_lose_on_recreate;
+ int times_to_fail_recreate_offscreen;
};
- private:
+ protected:
size_t test_case_;
int num_losses_;
bool recovered_context_;
@@ -281,9 +399,12 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent :
content_->setAnchorPoint(gfx::PointF());
content_->setIsDrawable(true);
if (use_surface_) {
- // TODO(danakj): Give the surface a filter to test more code when we can
- // do so without crashing in the shared context creation.
content_->setForceRenderSurface(true);
+ // Filters require us to create an offscreen context.
+ WebKit::WebFilterOperations filters;
+ filters.append(WebKit::WebFilterOperation::createGrayscaleFilter(0.5f));
+ content_->setFilters(filters);
+ content_->setBackgroundFilters(filters);
}
root_->addChild(content_);
@@ -307,6 +428,31 @@ class LayerTreeHostContextTestLostContextSucceedsWithContent :
// TestWebGraphicsContext3D ensures that this resource is created with
// the active context.
EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
+
+ cc::ContextProvider* contexts =
+ host_impl->resourceProvider()->offscreenContextProvider();
+ if (use_surface_) {
+ EXPECT_TRUE(contexts->Context3d());
+ // TODO(danakj): Make a fake GrContext.
+ //EXPECT_TRUE(contexts->GrContext());
+ } else {
+ EXPECT_FALSE(contexts);
+ }
+ }
+
+ virtual void afterTest() OVERRIDE {
+ LayerTreeHostContextTestLostContextSucceeds::afterTest();
+ if (use_surface_) {
+ // 1 create to start with +
+ // 6 from test cases that fail on initializing the renderer (after the
+ // offscreen context is created) +
+ // 6 from test cases that lose the offscreen context directly +
+ // All the test cases that recreate both contexts only once
+ // per time it is lost.
+ EXPECT_EQ(6 + 6 + 1 + num_losses_, times_offscreen_created_);
+ } else {
+ EXPECT_EQ(0, times_offscreen_created_);
+ }
}
protected:
@@ -340,6 +486,54 @@ TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
runTest(true);
}
+class LayerTreeHostContextTestOffscreenContextFails
+ : public LayerTreeHostContextTest {
+ public:
+ virtual void setupTree() OVERRIDE {
+ root_ = Layer::create();
+ root_->setBounds(gfx::Size(10, 10));
+ root_->setAnchorPoint(gfx::PointF());
+ root_->setIsDrawable(true);
+
+ content_ = FakeContentLayer::Create(&client_);
+ content_->setBounds(gfx::Size(10, 10));
+ content_->setAnchorPoint(gfx::PointF());
+ content_->setIsDrawable(true);
+ content_->setForceRenderSurface(true);
+ // Filters require us to create an offscreen context.
+ WebKit::WebFilterOperations filters;
+ filters.append(WebKit::WebFilterOperation::createGrayscaleFilter(0.5f));
+ content_->setFilters(filters);
+ content_->setBackgroundFilters(filters);
+
+ root_->addChild(content_);
+
+ m_layerTreeHost->setRootLayer(root_);
+ LayerTreeHostContextTest::setupTree();
+ }
+
+ virtual void beginTest() OVERRIDE {
+ times_to_fail_create_offscreen_ = 1;
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void drawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ cc::ContextProvider* contexts =
+ host_impl->resourceProvider()->offscreenContextProvider();
+ EXPECT_FALSE(contexts);
+ endTest();
+ }
+
+ virtual void afterTest() OVERRIDE {}
+
+ protected:
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> root_;
+ scoped_refptr<ContentLayer> content_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestOffscreenContextFails)
+
class LayerTreeHostContextTestLostContextFails :
public LayerTreeHostContextTest {
public:
@@ -493,6 +687,7 @@ class LayerTreeHostContextTestLostContextAndEvictTextures :
}
virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::commitCompleteOnThread(impl);
if (num_commits_ > 1)
return;
++num_commits_;
@@ -579,6 +774,7 @@ class LayerTreeHostContextTestLostContextWhileUpdatingResources :
}
virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::commitCompleteOnThread(impl);
endTest();
}
@@ -625,6 +821,8 @@ class LayerTreeHostContextTestLayersNotified :
}
virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ LayerTreeHostContextTest::commitCompleteOnThread(host_impl);
+
FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
host_impl->rootLayer());
FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>(
@@ -787,6 +985,8 @@ class LayerTreeHostContextTestDontUseLostResources :
}
virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ LayerTreeHostContextTest::commitCompleteOnThread(host_impl);
+
ResourceProvider* resource_provider = host_impl->resourceProvider();
if (host_impl->activeTree()->source_frame_number() == 0) {
@@ -995,6 +1195,8 @@ class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
}
virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ LayerTreeHostContextTest::commitCompleteOnThread(impl);
+
++commits_;
size_t upload_count = scrollbar_layer_->last_update_full_upload_size() +
scrollbar_layer_->last_update_partial_upload_size();
diff --git a/cc/occlusion_tracker_unittest.cc b/cc/occlusion_tracker_unittest.cc
index 0065401..63cdeb6 100644
--- a/cc/occlusion_tracker_unittest.cc
+++ b/cc/occlusion_tracker_unittest.cc
@@ -189,7 +189,6 @@ protected:
m_renderSurfaceLayerListImpl.clear();
m_replicaLayers.clear();
m_maskLayers.clear();
- LayerTreeHost::setNeedsFilterContext(false);
}
typename Types::HostType* getHost();
diff --git a/cc/render_surface_filters.cc b/cc/render_surface_filters.cc
index 29c031c..f04fbb9 100644
--- a/cc/render_surface_filters.cc
+++ b/cc/render_surface_filters.cc
@@ -8,7 +8,6 @@
#include "skia/ext/refptr.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperation.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
@@ -377,10 +376,9 @@ WebKit::WebFilterOperations RenderSurfaceFilters::optimize(const WebKit::WebFilt
return newList;
}
-SkBitmap RenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const gfx::SizeF& size, WebKit::WebGraphicsContext3D* context3D, GrContext* grContext)
+SkBitmap RenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters, unsigned textureId, gfx::SizeF size, GrContext* grContext)
{
- if (!context3D || !grContext)
- return SkBitmap();
+ DCHECK(grContext);
WebKit::WebFilterOperations optimizedFilters = optimize(filters);
FilterBufferState state(grContext, size, textureId);
@@ -448,7 +446,6 @@ SkBitmap RenderSurfaceFilters::apply(const WebKit::WebFilterOperations& filters,
}
state.swap();
}
- context3D->flush();
return state.source();
}
diff --git a/cc/render_surface_filters.h b/cc/render_surface_filters.h
index 0186613..86f366b 100644
--- a/cc/render_surface_filters.h
+++ b/cc/render_surface_filters.h
@@ -17,14 +17,13 @@ class SizeF;
namespace WebKit {
class WebFilterOperations;
-class WebGraphicsContext3D;
}
namespace cc {
class CC_EXPORT RenderSurfaceFilters {
public:
- static SkBitmap apply(const WebKit::WebFilterOperations& filters, unsigned textureId, const gfx::SizeF&, WebKit::WebGraphicsContext3D*, GrContext*);
+ static SkBitmap apply(const WebKit::WebFilterOperations& filters, unsigned textureId, gfx::SizeF, GrContext*);
static WebKit::WebFilterOperations optimize(const WebKit::WebFilterOperations& filters);
private:
diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc
index 5de3149..104b0cc 100644
--- a/cc/resource_provider.cc
+++ b/cc/resource_provider.cc
@@ -11,6 +11,7 @@
#include "base/stl_util.h"
#include "base/string_split.h"
#include "base/string_util.h"
+#include "cc/context_provider.h"
#include "cc/gl_renderer.h" // For the GLC() macro.
#include "cc/platform_color.h"
#include "cc/texture_uploader.h"
@@ -1133,4 +1134,10 @@ void ResourceProvider::enableReadLockFences(ResourceProvider::ResourceId id, boo
resource->enableReadLockFences = enable;
}
+void ResourceProvider::setOffscreenContextProvider(scoped_refptr<cc::ContextProvider> offscreenContextProvider) {
+ if (offscreenContextProvider)
+ offscreenContextProvider->BindToCurrentThread();
+ m_offscreenContextProvider = offscreenContextProvider;
+}
+
} // namespace cc
diff --git a/cc/resource_provider.h b/cc/resource_provider.h
index 5b31139..e63093c 100644
--- a/cc/resource_provider.h
+++ b/cc/resource_provider.h
@@ -35,6 +35,7 @@ class Vector2d;
namespace cc {
+class ContextProvider;
class TextureUploader;
// This class is not thread-safe and can only be called from the thread it was
@@ -263,6 +264,9 @@ public:
// Indicates if we can currently lock this resource for write.
bool canLockForWrite(ResourceId);
+ cc::ContextProvider* offscreenContextProvider() { return m_offscreenContextProvider.get(); }
+ void setOffscreenContextProvider(scoped_refptr<cc::ContextProvider> offscreenContextProvider);
+
private:
struct Resource {
Resource();
@@ -334,6 +338,8 @@ private:
int m_maxTextureSize;
GLenum m_bestTextureFormat;
+ scoped_refptr<cc::ContextProvider> m_offscreenContextProvider;
+
base::ThreadChecker m_threadChecker;
scoped_refptr<Fence> m_currentReadLockFence;
diff --git a/cc/resource_update_controller.cc b/cc/resource_update_controller.cc
index d60b5bb..f305946 100644
--- a/cc/resource_update_controller.cc
+++ b/cc/resource_update_controller.cc
@@ -7,18 +7,17 @@
#include <limits>
#include "base/debug/trace_event.h"
+#include "cc/context_provider.h"
#include "cc/prioritized_resource.h"
#include "cc/resource_provider.h"
#include "cc/texture_copier.h"
#include "cc/thread.h"
#include "skia/ext/refptr.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebSharedGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/gpu/SkGpuDevice.h"
using WebKit::WebGraphicsContext3D;
-using WebKit::WebSharedGraphicsContext3D;
namespace {
@@ -67,9 +66,8 @@ size_t ResourceUpdateController::maxFullUpdatesPerTick(
return texturesPerTick ? texturesPerTick : 1;
}
-ResourceUpdateController::ResourceUpdateController(ResourceUpdateControllerClient* client, Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider, bool hasImplThread)
+ResourceUpdateController::ResourceUpdateController(ResourceUpdateControllerClient* client, Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider)
: m_client(client)
- , m_hasImplThread(hasImplThread)
, m_queue(queue.Pass())
, m_resourceProvider(resourceProvider)
, m_textureUpdatesPerTick(maxFullUpdatesPerTick(resourceProvider))
@@ -130,27 +128,22 @@ void ResourceUpdateController::updateTexture(ResourceUpdate update)
DCHECK(m_resourceProvider->resourceType(texture->resourceId()) ==
ResourceProvider::GLTexture);
- WebGraphicsContext3D* paintContext = m_hasImplThread ?
- WebSharedGraphicsContext3D::compositorThreadContext() :
- WebSharedGraphicsContext3D::mainThreadContext();
- GrContext* paintGrContext = m_hasImplThread ?
- WebSharedGraphicsContext3D::compositorThreadGrContext() :
- WebSharedGraphicsContext3D::mainThreadGrContext();
-
- // Flush the context in which the backing texture is created so that it
- // is available in other shared contexts. It is important to do here
- // because the backing texture is created in one context while it is
- // being written to in another.
+ cc::ContextProvider* offscreenContexts = m_resourceProvider->offscreenContextProvider();
+
ResourceProvider::ScopedWriteLockGL lock(
m_resourceProvider, texture->resourceId());
+
+ // Flush the compositor context to ensure that textures there are available
+ // in the shared context. Do this after locking/creating the compositor
+ // texture.
m_resourceProvider->flush();
- // Make sure ganesh uses the correct GL context.
- paintContext->makeContextCurrent();
+ // Make sure skia uses the correct GL context.
+ offscreenContexts->Context3d()->makeContextCurrent();
// Create an accelerated canvas to draw on.
skia::RefPtr<SkCanvas> canvas = createAcceleratedCanvas(
- paintGrContext, texture->size(), lock.textureId());
+ offscreenContexts->GrContext(), texture->size(), lock.textureId());
// The compositor expects the textures to be upside-down so it can flip
// the final composited image. Ganesh renders the image upright so we
@@ -169,13 +162,16 @@ void ResourceUpdateController::updateTexture(ResourceUpdate update)
pictureRect.y() - sourceRect.y() + destOffset.y());
canvas->drawPicture(*update.picture);
- // Flush ganesh context so that all the rendered stuff appears on the
+ // Flush skia context so that all the rendered stuff appears on the
// texture.
- paintGrContext->flush();
+ offscreenContexts->GrContext()->flush();
// Flush the GL context so rendering results from this context are
// visible in the compositor's context.
- paintContext->flush();
+ offscreenContexts->Context3d()->flush();
+
+ // Use the compositor's GL context again.
+ m_resourceProvider->graphicsContext3D()->makeContextCurrent();
}
if (update.bitmap) {
diff --git a/cc/resource_update_controller.h b/cc/resource_update_controller.h
index bd3e2b8..fbec7c4 100644
--- a/cc/resource_update_controller.h
+++ b/cc/resource_update_controller.h
@@ -27,9 +27,9 @@ protected:
class CC_EXPORT ResourceUpdateController {
public:
- static scoped_ptr<ResourceUpdateController> create(ResourceUpdateControllerClient* client, Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider, bool hasImplThread)
+ static scoped_ptr<ResourceUpdateController> create(ResourceUpdateControllerClient* client, Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider)
{
- return make_scoped_ptr(new ResourceUpdateController(client, thread, queue.Pass(), resourceProvider, hasImplThread));
+ return make_scoped_ptr(new ResourceUpdateController(client, thread, queue.Pass(), resourceProvider));
}
static size_t maxPartialTextureUpdates();
@@ -48,7 +48,7 @@ public:
virtual size_t updateMoreTexturesSize() const;
protected:
- ResourceUpdateController(ResourceUpdateControllerClient*, Thread*, scoped_ptr<ResourceUpdateQueue>, ResourceProvider*, bool hasImplThread);
+ ResourceUpdateController(ResourceUpdateControllerClient*, Thread*, scoped_ptr<ResourceUpdateQueue>, ResourceProvider*);
private:
static size_t maxFullUpdatesPerTick(ResourceProvider*);
@@ -64,7 +64,6 @@ private:
void onTimerFired();
ResourceUpdateControllerClient* m_client;
- bool m_hasImplThread;
scoped_ptr<ResourceUpdateQueue> m_queue;
bool m_contentsTexturesPurged;
ResourceProvider* m_resourceProvider;
diff --git a/cc/resource_update_controller_unittest.cc b/cc/resource_update_controller_unittest.cc
index 9dfcb3e..b9c0f66 100644
--- a/cc/resource_update_controller_unittest.cc
+++ b/cc/resource_update_controller_unittest.cc
@@ -185,8 +185,7 @@ protected:
NULL,
m_proxy.implThread(),
m_queue.Pass(),
- m_resourceProvider.get(),
- m_proxy.hasImplThread());
+ m_resourceProvider.get());
updateController->finalize();
}
@@ -365,7 +364,7 @@ public:
protected:
FakeResourceUpdateController(cc::ResourceUpdateControllerClient* client, cc::Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider)
- : cc::ResourceUpdateController(client, thread, queue.Pass(), resourceProvider, false)
+ : cc::ResourceUpdateController(client, thread, queue.Pass(), resourceProvider)
, m_updateMoreTexturesSize(0) { }
base::TimeTicks m_now;
diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc
index 1301355..9c51d4ca3 100644
--- a/cc/single_thread_proxy.cc
+++ b/cc/single_thread_proxy.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
+#include "cc/context_provider.h"
#include "cc/draw_quad.h"
#include "cc/layer_tree_host.h"
#include "cc/layer_tree_impl.h"
@@ -25,6 +26,7 @@ SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layerTreeHost)
: Proxy(scoped_ptr<Thread>(NULL))
, m_layerTreeHost(layerTreeHost)
, m_outputSurfaceLost(false)
+ , m_createdOffscreenContextProvider(false)
, m_rendererInitialized(false)
, m_nextFrameIsNewlyCommittedFrame(false)
, m_insideDraw(false)
@@ -139,6 +141,12 @@ bool SingleThreadProxy::recreateOutputSurface()
scoped_ptr<OutputSurface> outputSurface = m_layerTreeHost->createOutputSurface();
if (!outputSurface.get())
return false;
+ scoped_refptr<cc::ContextProvider> offscreenContextProvider;
+ if (m_createdOffscreenContextProvider) {
+ offscreenContextProvider = m_layerTreeHost->client()->OffscreenContextProviderForMainThread();
+ if (!offscreenContextProvider->InitializeOnMainThread())
+ return false;
+ }
bool initialized;
{
@@ -148,6 +156,9 @@ bool SingleThreadProxy::recreateOutputSurface()
initialized = m_layerTreeHostImpl->initializeRenderer(outputSurface.Pass());
if (initialized) {
m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities();
+ m_layerTreeHostImpl->resourceProvider()->setOffscreenContextProvider(offscreenContextProvider);
+ } else if (offscreenContextProvider) {
+ offscreenContextProvider->VerifyContexts();
}
}
@@ -196,8 +207,7 @@ void SingleThreadProxy::doCommit(scoped_ptr<ResourceUpdateQueue> queue)
NULL,
Proxy::mainThread(),
queue.Pass(),
- m_layerTreeHostImpl->resourceProvider(),
- hasImplThread());
+ m_layerTreeHostImpl->resourceProvider());
updateController->finalize();
m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
@@ -382,6 +392,15 @@ bool SingleThreadProxy::commitAndComposite()
if (!m_layerTreeHost->initializeRendererIfNeeded())
return false;
+ scoped_refptr<cc::ContextProvider> offscreenContextProvider;
+ if (m_RendererCapabilitiesForMainThread.usingOffscreenContext3d && m_layerTreeHost->needsOffscreenContext()) {
+ offscreenContextProvider = m_layerTreeHost->client()->OffscreenContextProviderForMainThread();
+ if (offscreenContextProvider->InitializeOnMainThread())
+ m_createdOffscreenContextProvider = true;
+ else
+ offscreenContextProvider = NULL;
+ }
+
m_layerTreeHost->contentsTextureManager()->unlinkAndClearEvictedBackings();
scoped_ptr<ResourceUpdateQueue> queue = make_scoped_ptr(new ResourceUpdateQueue);
@@ -389,18 +408,20 @@ bool SingleThreadProxy::commitAndComposite()
m_layerTreeHost->willCommit();
doCommit(queue.Pass());
- bool result = doComposite();
+ bool result = doComposite(offscreenContextProvider);
m_layerTreeHost->didBeginFrame();
return result;
}
-bool SingleThreadProxy::doComposite()
+bool SingleThreadProxy::doComposite(scoped_refptr<cc::ContextProvider> offscreenContextProvider)
{
DCHECK(!m_outputSurfaceLost);
{
DebugScopedSetImplThread impl(this);
base::AutoReset<bool> markInside(&m_insideDraw, true);
+ m_layerTreeHostImpl->resourceProvider()->setOffscreenContextProvider(offscreenContextProvider);
+
if (!m_layerTreeHostImpl->visible())
return false;
@@ -422,6 +443,8 @@ bool SingleThreadProxy::doComposite()
}
if (m_outputSurfaceLost) {
+ if (cc::ContextProvider* offscreenContexts = m_layerTreeHostImpl->resourceProvider()->offscreenContextProvider())
+ offscreenContexts->VerifyContexts();
m_layerTreeHost->didLoseOutputSurface();
return false;
}
diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h
index a499501..a8be093 100644
--- a/cc/single_thread_proxy.h
+++ b/cc/single_thread_proxy.h
@@ -14,6 +14,7 @@
namespace cc {
+class ContextProvider;
class LayerTreeHost;
class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
@@ -73,12 +74,13 @@ private:
bool commitAndComposite();
void doCommit(scoped_ptr<ResourceUpdateQueue>);
- bool doComposite();
+ bool doComposite(scoped_refptr<cc::ContextProvider> offscreenContextProvider);
void didSwapFrame();
// Accessed on main thread only.
LayerTreeHost* m_layerTreeHost;
bool m_outputSurfaceLost;
+ bool m_createdOffscreenContextProvider;
// Holds on to the context between initializeContext() and initializeRenderer() calls. Shouldn't
// be used for anything else.
diff --git a/cc/test/fake_context_provider.cc b/cc/test/fake_context_provider.cc
new file mode 100644
index 0000000..ed777fc
--- /dev/null
+++ b/cc/test/fake_context_provider.cc
@@ -0,0 +1,61 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/fake_context_provider.h"
+
+#include "cc/test/test_web_graphics_context_3d.h"
+
+namespace cc {
+
+FakeContextProvider::FakeContextProvider()
+ : destroyed_(false) {
+}
+
+FakeContextProvider::FakeContextProvider(
+ const CreateCallback& create_callback)
+ : create_callback_(create_callback),
+ destroyed_(false) {
+}
+
+FakeContextProvider::~FakeContextProvider() {}
+
+bool FakeContextProvider::InitializeOnMainThread() {
+ if (destroyed_)
+ return false;
+ if (context3d_)
+ return true;
+
+ if (create_callback_.is_null())
+ context3d_ = TestWebGraphicsContext3D::Create().Pass();
+ else
+ context3d_ = create_callback_.Run();
+ destroyed_ = !context3d_;
+ return !!context3d_;
+}
+
+bool FakeContextProvider::BindToCurrentThread() {
+ return context3d_->makeContextCurrent();
+}
+
+WebKit::WebGraphicsContext3D* FakeContextProvider::Context3d() {
+ return context3d_.get();
+}
+class GrContext* FakeContextProvider::GrContext() {
+ // TODO(danakj): Make a fake GrContext.
+ return NULL;
+}
+
+void FakeContextProvider::VerifyContexts() {
+ if (!Context3d() || Context3d()->isContextLost()) {
+ base::AutoLock lock(destroyed_lock_);
+ destroyed_ = true;
+ }
+}
+
+bool FakeContextProvider::DestroyedOnMainThread() {
+ base::AutoLock lock(destroyed_lock_);
+ return destroyed_;
+}
+
+} // namespace cc
diff --git a/cc/test/fake_context_provider.h b/cc/test/fake_context_provider.h
new file mode 100644
index 0000000..f7c1839
--- /dev/null
+++ b/cc/test/fake_context_provider.h
@@ -0,0 +1,45 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_FAKE_CONTEXT_PROVIDER_H_
+#define CC_TEST_FAKE_CONTEXT_PROVIDER_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "cc/context_provider.h"
+
+namespace cc {
+class TestWebGraphicsContext3D;
+
+class FakeContextProvider : public cc::ContextProvider {
+ public:
+ typedef base::Callback<scoped_ptr<TestWebGraphicsContext3D>(void)>
+ CreateCallback;
+
+ FakeContextProvider();
+ explicit FakeContextProvider(const CreateCallback& create_callback);
+
+ virtual bool InitializeOnMainThread() OVERRIDE;
+ virtual bool BindToCurrentThread() OVERRIDE;
+ virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
+ virtual class GrContext* GrContext() OVERRIDE;
+ virtual void VerifyContexts() OVERRIDE;
+
+ bool DestroyedOnMainThread();
+
+ protected:
+ virtual ~FakeContextProvider();
+
+ CreateCallback create_callback_;
+ scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
+
+ base::Lock destroyed_lock_;
+ bool destroyed_;
+};
+
+} // namespace cc
+
+#endif // CC_TEST_FAKE_CONTEXT_PROVIDER_H_
+
diff --git a/cc/test/fake_layer_tree_host_client.cc b/cc/test/fake_layer_tree_host_client.cc
index e3e7735..253f5fd 100644
--- a/cc/test/fake_layer_tree_host_client.cc
+++ b/cc/test/fake_layer_tree_host_client.cc
@@ -4,8 +4,19 @@
#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/context_provider.h"
+#include "cc/test/test_web_graphics_context_3d.h"
+
namespace cc {
+FakeLayerImplTreeHostClient::FakeLayerImplTreeHostClient(bool useSoftwareRendering, bool useDelegatingRenderer)
+ : m_useSoftwareRendering(useSoftwareRendering)
+ , m_useDelegatingRenderer(useDelegatingRenderer)
+{
+}
+
+FakeLayerImplTreeHostClient::~FakeLayerImplTreeHostClient() { }
+
scoped_ptr<OutputSurface> FakeLayerImplTreeHostClient::createOutputSurface()
{
if (m_useSoftwareRendering) {
@@ -27,4 +38,16 @@ scoped_ptr<InputHandler> FakeLayerImplTreeHostClient::createInputHandler()
return scoped_ptr<InputHandler>();
}
+scoped_refptr<cc::ContextProvider> FakeLayerImplTreeHostClient::OffscreenContextProviderForMainThread() {
+ if (!m_mainThreadContexts || m_mainThreadContexts->DestroyedOnMainThread())
+ m_mainThreadContexts = new FakeContextProvider;
+ return m_mainThreadContexts;
+}
+
+scoped_refptr<cc::ContextProvider> FakeLayerImplTreeHostClient::OffscreenContextProviderForCompositorThread() {
+ if (!m_compositorThreadContexts || m_compositorThreadContexts->DestroyedOnMainThread())
+ m_compositorThreadContexts = new FakeContextProvider;
+ return m_compositorThreadContexts;
+}
+
} // namespace cc
diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h
index f10ba59..65a40ef 100644
--- a/cc/test/fake_layer_tree_host_client.h
+++ b/cc/test/fake_layer_tree_host_client.h
@@ -8,17 +8,15 @@
#include "base/memory/scoped_ptr.h"
#include "cc/input_handler.h"
#include "cc/layer_tree_host.h"
+#include "cc/test/fake_context_provider.h"
#include "cc/test/fake_output_surface.h"
namespace cc {
class FakeLayerImplTreeHostClient : public LayerTreeHostClient {
public:
- FakeLayerImplTreeHostClient(bool useSoftwareRendering = false, bool useDelegatingRenderer = false)
- : m_useSoftwareRendering(useSoftwareRendering)
- , m_useDelegatingRenderer(useDelegatingRenderer)
- {
- }
+ FakeLayerImplTreeHostClient(bool useSoftwareRendering = false, bool useDelegatingRenderer = false);
+ virtual ~FakeLayerImplTreeHostClient();
virtual void willBeginFrame() OVERRIDE { }
virtual void didBeginFrame() OVERRIDE { }
@@ -37,9 +35,15 @@ public:
// Used only in the single-threaded path.
virtual void scheduleComposite() OVERRIDE { }
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForMainThread() OVERRIDE;
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForCompositorThread() OVERRIDE;
+
private:
bool m_useSoftwareRendering;
bool m_useDelegatingRenderer;
+
+ scoped_refptr<FakeContextProvider> m_mainThreadContexts;
+ scoped_refptr<FakeContextProvider> m_compositorThreadContexts;
};
} // namespace cc
diff --git a/cc/test/layer_tree_test_common.cc b/cc/test/layer_tree_test_common.cc
index 4bd689c..0100135 100644
--- a/cc/test/layer_tree_test_common.cc
+++ b/cc/test/layer_tree_test_common.cc
@@ -15,6 +15,7 @@
#include "cc/single_thread_proxy.h"
#include "cc/thread_impl.h"
#include "cc/test/animation_test_common.h"
+#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/occlusion_tracker_test_common.h"
#include "cc/test/tiled_layer_test_common.h"
@@ -28,6 +29,15 @@ using namespace WebKit;
namespace cc {
+TestHooks::TestHooks()
+{
+ bool useSoftwareRendering = false;
+ bool useDelegatingRenderer = false;
+ m_fakeClient.reset(new FakeLayerImplTreeHostClient(useSoftwareRendering, useDelegatingRenderer));
+}
+
+TestHooks::~TestHooks() { }
+
bool TestHooks::prepareToDrawOnThread(cc::LayerTreeHostImpl*, LayerTreeHostImpl::FrameData&, bool)
{
return true;
@@ -43,6 +53,16 @@ scoped_ptr<OutputSurface> TestHooks::createOutputSurface()
return createFakeOutputSurface();
}
+scoped_refptr<cc::ContextProvider> TestHooks::OffscreenContextProviderForMainThread()
+{
+ return m_fakeClient->OffscreenContextProviderForMainThread();
+}
+
+scoped_refptr<cc::ContextProvider> TestHooks::OffscreenContextProviderForCompositorThread()
+{
+ return m_fakeClient->OffscreenContextProviderForCompositorThread();
+}
+
scoped_ptr<MockLayerTreeHostImpl> MockLayerTreeHostImpl::create(TestHooks* testHooks, const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
{
return make_scoped_ptr(new MockLayerTreeHostImpl(testHooks, settings, client, proxy));
@@ -198,6 +218,11 @@ public:
m_testHooks->didRecreateOutputSurface(succeeded);
}
+ virtual void willRetryRecreateOutputSurface() OVERRIDE
+ {
+ m_testHooks->willRetryRecreateOutputSurface();
+ }
+
virtual scoped_ptr<InputHandler> createInputHandler() OVERRIDE
{
return scoped_ptr<InputHandler>();
@@ -226,6 +251,16 @@ public:
m_testHooks->scheduleComposite();
}
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForMainThread() OVERRIDE
+ {
+ return m_testHooks->OffscreenContextProviderForMainThread();
+ }
+
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForCompositorThread() OVERRIDE
+ {
+ return m_testHooks->OffscreenContextProviderForCompositorThread();
+ }
+
private:
explicit ThreadedMockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHooks) { }
@@ -312,8 +347,6 @@ void ThreadedTest::doBeginTest()
if (m_endWhenBeginReturns)
realEndTest();
- LayerTreeHost::setNeedsFilterContext(false);
-
// Allow commits to happen once beginTest() has had a chance to post tasks
// so that those tasks will happen before the first commit.
if (m_layerTreeHost)
diff --git a/cc/test/layer_tree_test_common.h b/cc/test/layer_tree_test_common.h
index 82144bd..b7352bf 100644
--- a/cc/test/layer_tree_test_common.h
+++ b/cc/test/layer_tree_test_common.h
@@ -13,7 +13,12 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationDelegate.h"
+namespace Webkit {
+class WebGraphicsContext3D;
+}
+
namespace cc {
+class FakeLayerImplTreeHostClient;
class LayerImpl;
class LayerTreeHost;
class LayerTreeHostClient;
@@ -22,6 +27,9 @@ class LayerTreeHostImpl;
// Used by test stubs to notify the test when something interesting happens.
class TestHooks : public WebKit::WebAnimationDelegate {
public:
+ TestHooks();
+ virtual ~TestHooks();
+
virtual void beginCommitOnThread(LayerTreeHostImpl*) { }
virtual void commitCompleteOnThread(LayerTreeHostImpl*) { }
virtual bool prepareToDrawOnThread(
@@ -34,6 +42,7 @@ public:
virtual void animate(base::TimeTicks monotonicTime) { }
virtual void layout() { }
virtual void didRecreateOutputSurface(bool succeeded) { }
+ virtual void willRetryRecreateOutputSurface() { }
virtual void didAddAnimation() { }
virtual void didCommit() { }
virtual void didCommitAndDrawFrame() { }
@@ -46,6 +55,12 @@ public:
virtual void notifyAnimationFinished(double time) OVERRIDE { }
virtual scoped_ptr<OutputSurface> createOutputSurface();
+
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForMainThread();
+ virtual scoped_refptr<cc::ContextProvider> OffscreenContextProviderForCompositorThread();
+
+private:
+ scoped_ptr<FakeLayerImplTreeHostClient> m_fakeClient;
};
class TimeoutTask;
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index c1ac0e7..b4a2c7e 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -302,6 +302,10 @@ void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current,
context_lost_ = true;
if (context_lost_callback_)
context_lost_callback_->onContextLost();
+
+ for (size_t i = 0; i < shared_contexts_.size(); ++i)
+ shared_contexts_[i]->loseContextCHROMIUM(current, other);
+ shared_contexts_.clear();
}
WebKit::WebGLId TestWebGraphicsContext3D::NextTextureId() {
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index abfd9c9..212da16 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -122,6 +122,11 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
have_extension_egl_image_ = have;
}
+ // When this context is lost, all contexts in its share group are also lost.
+ void add_share_group_context(WebKit::WebGraphicsContext3D* context3d) {
+ shared_contexts_.push_back(context3d);
+ }
+
static const WebKit::WebGLId kExternalTextureId;
virtual WebKit::WebGLId NextTextureId();
@@ -142,6 +147,7 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
WebGraphicsContextLostCallback* context_lost_callback_;
std::vector<WebKit::WebGLId> textures_;
base::hash_set<WebKit::WebGLId> used_textures_;
+ std::vector<WebKit::WebGraphicsContext3D*> shared_contexts_;
int width_;
int height_;
};
diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc
index ddc61c0..51f073d 100644
--- a/cc/thread_proxy.cc
+++ b/cc/thread_proxy.cc
@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
+#include "cc/context_provider.h"
#include "cc/delay_based_time_source.h"
#include "cc/draw_quad.h"
#include "cc/frame_rate_controller.h"
@@ -17,9 +18,6 @@
#include "cc/prioritized_resource_manager.h"
#include "cc/scheduler.h"
#include "cc/thread.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebSharedGraphicsContext3D.h"
-
-using WebKit::WebSharedGraphicsContext3D;
namespace {
@@ -43,6 +41,7 @@ ThreadProxy::ThreadProxy(LayerTreeHost* layerTreeHost, scoped_ptr<Thread> implTh
, m_animateRequested(false)
, m_commitRequested(false)
, m_commitRequestSentToImplThread(false)
+ , m_createdOffscreenContextProvider(false)
, m_layerTreeHost(layerTreeHost)
, m_rendererInitialized(false)
, m_started(false)
@@ -228,9 +227,12 @@ bool ThreadProxy::recreateOutputSurface()
scoped_ptr<OutputSurface> outputSurface = m_layerTreeHost->createOutputSurface();
if (!outputSurface.get())
return false;
- if (m_layerTreeHost->needsSharedContext())
- if (!WebSharedGraphicsContext3D::createCompositorThreadContext())
+ scoped_refptr<cc::ContextProvider> offscreenContextProvider;
+ if (m_createdOffscreenContextProvider) {
+ offscreenContextProvider = m_layerTreeHost->client()->OffscreenContextProviderForCompositorThread();
+ if (!offscreenContextProvider->InitializeOnMainThread())
return false;
+ }
// Make a blocking call to recreateOutputSurfaceOnImplThread. The results of that
// call are pushed into the recreateSucceeded and capabilities local
@@ -243,6 +245,7 @@ bool ThreadProxy::recreateOutputSurface()
m_implThreadWeakPtr,
&completion,
base::Passed(&outputSurface),
+ offscreenContextProvider,
&recreateSucceeded,
&capabilities));
completion.wait();
@@ -314,6 +317,8 @@ void ThreadProxy::checkOutputSurfaceStatusOnImplThread()
TRACE_EVENT0("cc", "ThreadProxy::checkOutputSurfaceStatusOnImplThread");
if (!m_layerTreeHostImpl->isContextLost())
return;
+ if (cc::ContextProvider* offscreenContexts = m_layerTreeHostImpl->resourceProvider()->offscreenContextProvider())
+ offscreenContexts->VerifyContexts();
m_schedulerOnImplThread->didLoseOutputSurface();
}
@@ -599,9 +604,6 @@ void ThreadProxy::beginFrame(scoped_ptr<BeginFrameAndCommitState> beginFrameStat
return;
}
- if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::haveCompositorThreadContext())
- WebSharedGraphicsContext3D::createCompositorThreadContext();
-
// Do not notify the impl thread of commit requests that occur during
// the apply/animate/layout part of the beginFrameAndCommit process since
// those commit requests will get painted immediately. Once we have done
@@ -671,6 +673,15 @@ void ThreadProxy::beginFrame(scoped_ptr<BeginFrameAndCommitState> beginFrameStat
setNeedsAnimate();
}
+ scoped_refptr<cc::ContextProvider> offscreenContextProvider;
+ if (m_RendererCapabilitiesMainThreadCopy.usingOffscreenContext3d && m_layerTreeHost->needsOffscreenContext()) {
+ offscreenContextProvider = m_layerTreeHost->client()->OffscreenContextProviderForCompositorThread();
+ if (offscreenContextProvider->InitializeOnMainThread())
+ m_createdOffscreenContextProvider = true;
+ else
+ offscreenContextProvider = NULL;
+ }
+
// Notify the impl thread that the beginFrame has completed. This will
// begin the commit process, which is blocking from the main thread's
// point of view, but asynchronously performed on the impl thread,
@@ -682,7 +693,7 @@ void ThreadProxy::beginFrame(scoped_ptr<BeginFrameAndCommitState> beginFrameStat
base::TimeTicks startTime = base::TimeTicks::HighResNow();
CompletionEvent completion;
- Proxy::implThread()->postTask(base::Bind(&ThreadProxy::beginFrameCompleteOnImplThread, m_implThreadWeakPtr, &completion, queue.release()));
+ Proxy::implThread()->postTask(base::Bind(&ThreadProxy::beginFrameCompleteOnImplThread, m_implThreadWeakPtr, &completion, queue.release(), offscreenContextProvider));
completion.wait();
base::TimeTicks endTime = base::TimeTicks::HighResNow();
@@ -694,7 +705,7 @@ void ThreadProxy::beginFrame(scoped_ptr<BeginFrameAndCommitState> beginFrameStat
m_layerTreeHost->didBeginFrame();
}
-void ThreadProxy::beginFrameCompleteOnImplThread(CompletionEvent* completion, ResourceUpdateQueue* rawQueue)
+void ThreadProxy::beginFrameCompleteOnImplThread(CompletionEvent* completion, ResourceUpdateQueue* rawQueue, scoped_refptr<cc::ContextProvider> offscreenContextProvider)
{
scoped_ptr<ResourceUpdateQueue> queue(rawQueue);
@@ -710,6 +721,8 @@ void ThreadProxy::beginFrameCompleteOnImplThread(CompletionEvent* completion, Re
return;
}
+ m_layerTreeHostImpl->resourceProvider()->setOffscreenContextProvider(offscreenContextProvider);
+
if (m_layerTreeHost->contentsTextureManager()->linkedEvictedBackingsExist()) {
// Clear any uploads we were making to textures linked to evicted
// resources
@@ -721,7 +734,7 @@ void ThreadProxy::beginFrameCompleteOnImplThread(CompletionEvent* completion, Re
m_layerTreeHost->contentsTextureManager()->pushTexturePrioritiesToBackings();
- m_currentResourceUpdateControllerOnImplThread = ResourceUpdateController::create(this, Proxy::implThread(), queue.Pass(), m_layerTreeHostImpl->resourceProvider(), hasImplThread());
+ m_currentResourceUpdateControllerOnImplThread = ResourceUpdateController::create(this, Proxy::implThread(), queue.Pass(), m_layerTreeHostImpl->resourceProvider());
m_currentResourceUpdateControllerOnImplThread->performMoreUpdates(
m_schedulerOnImplThread->anticipatedDrawTime());
@@ -1059,7 +1072,7 @@ size_t ThreadProxy::maxPartialTextureUpdates() const
return ResourceUpdateController::maxPartialTextureUpdates();
}
-void ThreadProxy::recreateOutputSurfaceOnImplThread(CompletionEvent* completion, scoped_ptr<OutputSurface> outputSurface, bool* recreateSucceeded, RendererCapabilities* capabilities)
+void ThreadProxy::recreateOutputSurfaceOnImplThread(CompletionEvent* completion, scoped_ptr<OutputSurface> outputSurface, scoped_refptr<cc::ContextProvider> offscreenContextProvider, bool* recreateSucceeded, RendererCapabilities* capabilities)
{
TRACE_EVENT0("cc", "ThreadProxy::recreateOutputSurfaceOnImplThread");
DCHECK(isImplThread());
@@ -1067,7 +1080,10 @@ void ThreadProxy::recreateOutputSurfaceOnImplThread(CompletionEvent* completion,
*recreateSucceeded = m_layerTreeHostImpl->initializeRenderer(outputSurface.Pass());
if (*recreateSucceeded) {
*capabilities = m_layerTreeHostImpl->rendererCapabilities();
+ m_layerTreeHostImpl->resourceProvider()->setOffscreenContextProvider(offscreenContextProvider);
m_schedulerOnImplThread->didRecreateOutputSurface();
+ } else if (offscreenContextProvider) {
+ offscreenContextProvider->VerifyContexts();
}
completion->signal();
}
diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h
index 9e383bb..504dca3 100644
--- a/cc/thread_proxy.h
+++ b/cc/thread_proxy.h
@@ -17,6 +17,7 @@
namespace cc {
+class ContextProvider;
class InputHandler;
class LayerTreeHost;
class ResourceUpdateQueue;
@@ -123,7 +124,7 @@ private:
bool commitPending;
};
void forceBeginFrameOnImplThread(CompletionEvent*);
- void beginFrameCompleteOnImplThread(CompletionEvent*, ResourceUpdateQueue*);
+ void beginFrameCompleteOnImplThread(CompletionEvent*, ResourceUpdateQueue*, scoped_refptr<cc::ContextProvider> offscreenContextProvider);
void beginFrameAbortedOnImplThread();
void requestReadbackOnImplThread(ReadbackRequest*);
void requestStartPageScaleAnimationOnImplThread(gfx::Vector2d targetOffset, bool useAnchor, float scale, base::TimeDelta duration);
@@ -137,7 +138,7 @@ private:
void manageTilesOnImplThread();
void setFullRootLayerDamageOnImplThread();
void acquireLayerTexturesForMainThreadOnImplThread(CompletionEvent*);
- void recreateOutputSurfaceOnImplThread(CompletionEvent*, scoped_ptr<OutputSurface>, bool* recreateSucceeded, RendererCapabilities*);
+ void recreateOutputSurfaceOnImplThread(CompletionEvent*, scoped_ptr<OutputSurface>, scoped_refptr<cc::ContextProvider> offscreenContextProvider, bool* recreateSucceeded, RendererCapabilities*);
void renderingStatsOnImplThread(CompletionEvent*, RenderingStats*);
ScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapInternal(bool forcedDraw);
void forceSerializeOnSwapBuffersOnImplThread(CompletionEvent*);
@@ -153,6 +154,7 @@ private:
bool m_animateRequested; // Set only when setNeedsAnimate is called.
bool m_commitRequested; // Set only when setNeedsCommit is called.
bool m_commitRequestSentToImplThread; // Set by setNeedsCommit and setNeedsAnimate.
+ bool m_createdOffscreenContextProvider; // Set by beginFrame.
base::CancelableClosure m_outputSurfaceRecreationCallback;
LayerTreeHost* m_layerTreeHost;
bool m_rendererInitialized;
diff --git a/cc/tiled_layer_unittest.cc b/cc/tiled_layer_unittest.cc
index ac8baf5..73006b4 100644
--- a/cc/tiled_layer_unittest.cc
+++ b/cc/tiled_layer_unittest.cc
@@ -93,8 +93,7 @@ public:
NULL,
m_proxy->implThread(),
m_queue.Pass(),
- m_resourceProvider.get(),
- m_proxy->hasImplThread());
+ m_resourceProvider.get());
updateController->finalize();
m_queue = make_scoped_ptr(new ResourceUpdateQueue);
}