summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/output/output_surface.cc56
-rw-r--r--cc/output/output_surface.h14
-rw-r--r--cc/output/output_surface_unittest.cc97
3 files changed, 154 insertions, 13 deletions
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 1be41892..84d94b8 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -30,7 +30,9 @@ class OutputSurfaceCallbacks
public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
public:
explicit OutputSurfaceCallbacks(OutputSurfaceClient* client)
- : client_(client) {}
+ : client_(client) {
+ DCHECK(client_);
+ }
// WK:WGC3D::WGSwapBuffersCompleteCallbackCHROMIUM implementation.
virtual void onSwapBuffersComplete() { client_->OnSwapBuffersComplete(); }
@@ -78,24 +80,60 @@ bool OutputSurface::ForcedDrawToSoftwareDevice() const {
bool OutputSurface::BindToClient(
cc::OutputSurfaceClient* client) {
DCHECK(client);
- if (context3d_ && !context3d_->makeContextCurrent())
- return false;
client_ = client;
- if (!context3d_)
- return true;
- string extensions_string = UTF16ToASCII(context3d_->getString(GL_EXTENSIONS));
+ bool success = true;
+
+ if (context3d_) {
+ success = context3d_->makeContextCurrent();
+ if (success)
+ SetContext3D(context3d_.Pass());
+ }
+
+ if (!success)
+ client_ = NULL;
+
+ return success;
+}
+
+bool OutputSurface::InitializeAndSetContext3D(
+ scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
+ scoped_refptr<ContextProvider> offscreen_context_provider) {
+ DCHECK(!context3d_);
+ DCHECK(context3d);
+ DCHECK(client_);
+
+ bool success = false;
+ if (context3d->makeContextCurrent()) {
+ SetContext3D(context3d.Pass());
+ if (client_->DeferredInitialize(offscreen_context_provider))
+ success = true;
+ }
+
+ if (!success) {
+ context3d_.reset();
+ callbacks_.reset();
+ }
+
+ return success;
+}
+
+void OutputSurface::SetContext3D(
+ scoped_ptr<WebKit::WebGraphicsContext3D> context3d) {
+ DCHECK(!context3d_);
+ DCHECK(context3d);
+ DCHECK(client_);
+
+ string extensions_string = UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
vector<string> extensions_list;
base::SplitString(extensions_string, ' ', &extensions_list);
set<string> extensions(extensions_list.begin(), extensions_list.end());
-
has_gl_discard_backbuffer_ =
extensions.count("GL_CHROMIUM_discard_backbuffer") > 0;
+ context3d_ = context3d.Pass();
callbacks_.reset(new OutputSurfaceCallbacks(client_));
context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get());
context3d_->setContextLostCallback(callbacks_.get());
-
- return true;
}
void OutputSurface::SendFrameToParentCompositor(CompositorFrame* frame) {
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 00877de..fb93eb7 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -6,8 +6,10 @@
#define CC_OUTPUT_OUTPUT_SURFACE_H_
#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/output/context_provider.h"
#include "cc/output/software_output_device.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
@@ -106,17 +108,25 @@ class CC_EXPORT OutputSurface {
virtual void SetNeedsBeginFrame(bool enable) {}
protected:
+ // Synchronously initialize context3d and enter hardware mode.
+ // This can only supported in threaded compositing mode.
+ // |offscreen_context_provider| should match what is returned by
+ // LayerTreeClient::OffscreenContextProviderForCompositorThread.
+ bool InitializeAndSetContext3D(
+ scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
+ scoped_refptr<ContextProvider> offscreen_context_provider);
+
OutputSurfaceClient* client_;
struct cc::OutputSurface::Capabilities capabilities_;
+ scoped_ptr<OutputSurfaceCallbacks> callbacks_;
scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
scoped_ptr<cc::SoftwareOutputDevice> software_device_;
bool has_gl_discard_backbuffer_;
gfx::Size surface_size_;
float device_scale_factor_;
- scoped_ptr<OutputSurfaceCallbacks> callbacks_;
-
private:
+ void SetContext3D(scoped_ptr<WebKit::WebGraphicsContext3D> context3d);
DISALLOW_COPY_AND_ASSIGN(OutputSurface);
};
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index 1d365d9..72bf0a4 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -4,7 +4,9 @@
#include "cc/output/output_surface.h"
#include "cc/output/output_surface_client.h"
+#include "cc/output/software_output_device.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
@@ -24,13 +26,25 @@ class TestOutputSurface : public OutputSurface {
: OutputSurface(context3d.Pass(), software_device.Pass()) {}
OutputSurfaceClient* client() { return client_; }
+
+ bool InitializeNewContext3D(
+ scoped_ptr<WebKit::WebGraphicsContext3D> new_context3d) {
+ return InitializeAndSetContext3D(new_context3d.Pass(),
+ scoped_refptr<ContextProvider>());
+ }
};
class FakeOutputSurfaceClient : public OutputSurfaceClient {
public:
+ FakeOutputSurfaceClient()
+ : deferred_initialize_result_(true),
+ deferred_initialize_called_(false),
+ did_lose_output_surface_called_(false) {}
+
virtual bool DeferredInitialize(
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE {
- return true;
+ deferred_initialize_called_ = true;
+ return deferred_initialize_result_;
}
virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
@@ -39,9 +53,28 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
virtual void OnSendFrameToParentCompositorAck(const CompositorFrameAck& ack)
OVERRIDE {}
virtual void OnSwapBuffersComplete() OVERRIDE {}
- virtual void DidLoseOutputSurface() OVERRIDE {}
+ virtual void DidLoseOutputSurface() OVERRIDE {
+ did_lose_output_surface_called_ = true;
+ }
virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
gfx::Rect viewport) OVERRIDE {}
+
+ void set_deferred_initialize_result(bool result) {
+ deferred_initialize_result_ = result;
+ }
+
+ bool deferred_initialize_called() {
+ return deferred_initialize_called_;
+ }
+
+ bool did_lose_output_surface_called() {
+ return did_lose_output_surface_called_;
+ }
+
+ private:
+ bool deferred_initialize_result_;
+ bool deferred_initialize_called_;
+ bool did_lose_output_surface_called_;
};
TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
@@ -55,6 +88,13 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
FakeOutputSurfaceClient client;
EXPECT_TRUE(output_surface.BindToClient(&client));
EXPECT_EQ(&client, output_surface.client());
+ EXPECT_FALSE(client.deferred_initialize_called());
+
+ // Verify DidLoseOutputSurface callback is hooked up correctly.
+ EXPECT_FALSE(client.did_lose_output_surface_called());
+ output_surface.context3d()->loseContextCHROMIUM(
+ GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+ EXPECT_TRUE(client.did_lose_output_surface_called());
}
TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
@@ -73,5 +113,58 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
EXPECT_EQ(NULL, output_surface.client());
}
+class InitializeNewContext3D : public ::testing::Test {
+ public:
+ InitializeNewContext3D()
+ : context3d_(TestWebGraphicsContext3D::Create()),
+ output_surface_(
+ scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)) {}
+
+ protected:
+ void BindOutputSurface() {
+ EXPECT_TRUE(output_surface_.BindToClient(&client_));
+ EXPECT_EQ(&client_, output_surface_.client());
+ }
+
+ void InitializeNewContextExpectFail() {
+ EXPECT_FALSE(output_surface_.InitializeNewContext3D(
+ context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
+ EXPECT_EQ(&client_, output_surface_.client());
+
+ EXPECT_FALSE(output_surface_.context3d());
+ EXPECT_TRUE(output_surface_.software_device());
+ }
+
+ scoped_ptr<TestWebGraphicsContext3D> context3d_;
+ TestOutputSurface output_surface_;
+ FakeOutputSurfaceClient client_;
+};
+
+TEST_F(InitializeNewContext3D, Success) {
+ BindOutputSurface();
+ EXPECT_FALSE(client_.deferred_initialize_called());
+
+ EXPECT_TRUE(output_surface_.InitializeNewContext3D(
+ context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
+ EXPECT_TRUE(client_.deferred_initialize_called());
+
+ EXPECT_FALSE(client_.did_lose_output_surface_called());
+ output_surface_.context3d()->loseContextCHROMIUM(
+ GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+ EXPECT_TRUE(client_.did_lose_output_surface_called());
+}
+
+TEST_F(InitializeNewContext3D, Context3dMakeCurrentFails) {
+ BindOutputSurface();
+ context3d_->set_times_make_current_succeeds(0);
+ InitializeNewContextExpectFail();
+}
+
+TEST_F(InitializeNewContext3D, ClientDeferredInitializeFails) {
+ BindOutputSurface();
+ client_.set_deferred_initialize_result(false);
+ InitializeNewContextExpectFail();
+}
+
} // namespace
} // namespace cc