Commit 5b86251b authored by boliu@chromium.org's avatar boliu@chromium.org

Factor out cc::OutputSurface::InitializeAndSetContext3D

This is a protected method so that it can be called by subclasses to set
and initialize a new Context3D post construction time.

BUG=230197

Review URL: https://chromiumcodereview.appspot.com/15647021

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204976 0039d316-1c4b-4281-b951-d872f2087c98
parent a21d25b3
......@@ -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) {
......
......@@ -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);
};
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment