diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-04 23:06:38 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-04 23:06:38 +0000 |
commit | 84e4d4fa159d9a92b42f7f2f4d612748d217e4b7 (patch) | |
tree | 87eb04b28704300bf2a59b89e49d7df61bb9bded | |
parent | f368038ed50461fa08162b09a6152454d25e6f68 (diff) | |
download | chromium_src-84e4d4fa159d9a92b42f7f2f4d612748d217e4b7.zip chromium_src-84e4d4fa159d9a92b42f7f2f4d612748d217e4b7.tar.gz chromium_src-84e4d4fa159d9a92b42f7f2f4d612748d217e4b7.tar.bz2 |
Create GLES2 context synchronously.
This introduces the infrastructure for "synchronous IPCs", and uses it for
context creation. Though not strictly necessary for the current hack, it will be
needed for the command buffer implementation, as well as for implementing an EGL
layer.
BUG=333157
R=darin@chromium.org
Review URL: https://codereview.chromium.org/147083005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248804 0039d316-1c4b-4281-b951-d872f2087c98
30 files changed, 185 insertions, 156 deletions
diff --git a/mojo/apps/js/bindings/gl/context.cc b/mojo/apps/js/bindings/gl/context.cc index a4f54fe..612f20e 100644 --- a/mojo/apps/js/bindings/gl/context.cc +++ b/mojo/apps/js/bindings/gl/context.cc @@ -35,9 +35,9 @@ gin::WrapperInfo Context::kWrapperInfo = { gin::kEmbedderNativeGin }; gin::Handle<Context> Context::Create( v8::Isolate* isolate, mojo::Handle handle, - v8::Handle<v8::Function> did_create_callback) { + v8::Handle<v8::Function> context_lost_callback) { return gin::CreateHandle(isolate, - new Context(isolate, handle, did_create_callback)); + new Context(isolate, handle, context_lost_callback)); } void Context::BufferData(GLenum target, const gin::ArrayBufferView& buffer, @@ -150,44 +150,34 @@ gin::ObjectTemplateBuilder Context::GetObjectTemplateBuilder( Context::Context(v8::Isolate* isolate, mojo::Handle handle, - v8::Handle<v8::Function> did_create_callback) { + v8::Handle<v8::Function> context_lost_callback) { v8::Handle<v8::Context> context = isolate->GetCurrentContext(); runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); - did_create_callback_.Reset(isolate, did_create_callback); + context_lost_callback_.Reset(isolate, context_lost_callback); context_ = MojoGLES2CreateContext( handle.value(), - &DidCreateContextThunk, &ContextLostThunk, NULL, this); + MojoGLES2MakeCurrent(context_); } Context::~Context() { MojoGLES2DestroyContext(context_); } -void Context::DidCreateContext() { - // TODO(aa): When we want to support multiple contexts, we should add - // Context::MakeCurrent() for developers to switch between them. - MojoGLES2MakeCurrent(context_); +void Context::ContextLost() { if (!runner_) return; gin::Runner::Scope scope(runner_.get()); v8::Isolate* isolate = runner_->isolate(); v8::Handle<v8::Function> callback = v8::Local<v8::Function>::New( - isolate, did_create_callback_); + isolate, context_lost_callback_); runner_->Call(callback, runner_->global(), 0, NULL); } -void Context::DidCreateContextThunk(void* closure) { - static_cast<Context*>(closure)->DidCreateContext(); -} - -void Context::ContextLost() { -} - void Context::ContextLostThunk(void* closure) { static_cast<Context*>(closure)->ContextLost(); } diff --git a/mojo/apps/js/bindings/gl/context.h b/mojo/apps/js/bindings/gl/context.h index 94f56b6..d8daa82 100644 --- a/mojo/apps/js/bindings/gl/context.h +++ b/mojo/apps/js/bindings/gl/context.h @@ -30,11 +30,11 @@ class Context : public gin::Wrappable<Context> { public: static gin::WrapperInfo kWrapperInfo; - // TODO(piman): lost context callback, draw animation frame callback. + // TODO(piman): draw animation frame callback. static gin::Handle<Context> Create( v8::Isolate* isolate, mojo::Handle handle, - v8::Handle<v8::Function> did_create_callback); + v8::Handle<v8::Function> context_lost_callback); static void BufferData(GLenum target, const gin::ArrayBufferView& buffer, GLenum usage); @@ -59,16 +59,14 @@ class Context : public gin::Wrappable<Context> { explicit Context(v8::Isolate* isolate, mojo::Handle handle, - v8::Handle<v8::Function> did_create_callback); + v8::Handle<v8::Function> context_lost_callback); virtual ~Context(); - void DidCreateContext(); - static void DidCreateContextThunk(void* closure); void ContextLost(); static void ContextLostThunk(void* closure); base::WeakPtr<gin::Runner> runner_; - v8::Persistent<v8::Function> did_create_callback_; + v8::Persistent<v8::Function> context_lost_callback_; MojoGLES2Context context_; }; diff --git a/mojo/apps/js/bindings/gl/module.cc b/mojo/apps/js/bindings/gl/module.cc index 973e9be..ef53e3d 100644 --- a/mojo/apps/js/bindings/gl/module.cc +++ b/mojo/apps/js/bindings/gl/module.cc @@ -25,8 +25,8 @@ gin::WrapperInfo kWrapperInfo = { gin::kEmbedderNativeGin }; gin::Handle<Context> CreateContext( const gin::Arguments& args, mojo::Handle handle, - v8::Handle<v8::Function> did_create_callback) { - return Context::Create(args.isolate(), handle, did_create_callback); + v8::Handle<v8::Function> context_lost_callback) { + return Context::Create(args.isolate(), handle, context_lost_callback); } } // namespace diff --git a/mojo/apps/js/main.js b/mojo/apps/js/main.js index 1a159670..6e59315 100644 --- a/mojo/apps/js/main.js +++ b/mojo/apps/js/main.js @@ -280,9 +280,9 @@ define([ this.shell_ = shell; var pipe = new core.createMessagePipe(); + this.shell_.connect('mojo:mojo_native_viewport_service', pipe.handle1); new connector.Connection(pipe.handle0, NativeViewportClientImpl, nativeViewport.NativeViewportProxy); - this.shell_.connect('mojo:mojo_native_viewport_service', pipe.handle1); } // TODO(aa): It is a bummer to need this stub object in JavaScript. We should // have a 'client' object that contains both the sending and receiving bits of @@ -295,7 +295,6 @@ define([ this.remote_ = remote; var pipe = core.createMessagePipe(); - this.gles2_ = new GLES2ClientImpl(pipe.handle0); var rect = new nativeViewport.Rect; rect.position = new nativeViewport.Point; @@ -305,6 +304,7 @@ define([ this.remote_.create(rect); this.remote_.show(); this.remote_.createGLES2Context(pipe.handle1); + this.gles2_ = new GLES2ClientImpl(pipe.handle0); } NativeViewportClientImpl.prototype = Object.create(nativeViewport.NativeViewportClientStub.prototype); @@ -319,12 +319,10 @@ define([ } function GLES2ClientImpl(remotePipe) { - this.gl_ = new gljs.Context(remotePipe, this.didCreateContext.bind(this)); + this.gl_ = new gljs.Context(remotePipe, this.contextLost.bind(this)); this.lastTime_ = monotonicClock.seconds(); this.angle_ = 45; - } - GLES2ClientImpl.prototype.didCreateContext = function() { this.program_ = loadProgram(this.gl_); this.positionLocation_ = this.gl_.getAttribLocation(this.program_, 'a_position'); @@ -335,17 +333,15 @@ define([ this.mvpMatrix_.loadIdentity(); this.gl_.clearColor(0, 0, 0, 0); - this.timer_ = timer.createRepeating(16, this.handleTimer.bind(this)); - }; + } GLES2ClientImpl.prototype.setDimensions = function(size) { this.width_ = size.width; this.height_ = size.height; + this.timer_ = timer.createRepeating(16, this.handleTimer.bind(this)); } GLES2ClientImpl.prototype.drawCube = function() { - if (!this.width_ || !this.height_) - return; this.gl_.viewport(0, 0, this.width_, this.height_); this.gl_.clear(this.gl_.COLOR_BUFFER_BIT); this.gl_.useProgram(this.program_); diff --git a/mojo/examples/aura_demo/aura_demo.cc b/mojo/examples/aura_demo/aura_demo.cc index 91fa7cd..3e1181d 100644 --- a/mojo/examples/aura_demo/aura_demo.cc +++ b/mojo/examples/aura_demo/aura_demo.cc @@ -126,12 +126,12 @@ class AuraDemo : public ShellClient { ScopedMessagePipeHandle client_handle, native_viewport_handle; CreateMessagePipe(&client_handle, &native_viewport_handle); + mojo::AllocationScope scope; + shell_->Connect("mojo:mojo_native_viewport_service", client_handle.Pass()); root_window_host_.reset(new WindowTreeHostMojo( native_viewport_handle.Pass(), gfx::Rect(800, 600), base::Bind(&AuraDemo::HostContextCreated, base::Unretained(this)))); - AllocationScope scope; - shell_->Connect("mojo:mojo_native_viewport_service", client_handle.Pass()); } virtual void AcceptConnection(ScopedMessagePipeHandle handle) MOJO_OVERRIDE { diff --git a/mojo/examples/aura_demo/root_window_host_mojo.cc b/mojo/examples/aura_demo/root_window_host_mojo.cc index af6e87f..0fb4ddf 100644 --- a/mojo/examples/aura_demo/root_window_host_mojo.cc +++ b/mojo/examples/aura_demo/root_window_host_mojo.cc @@ -31,8 +31,7 @@ WindowTreeHostMojo::WindowTreeHostMojo( ScopedMessagePipeHandle viewport_handle, const gfx::Rect& bounds, const base::Callback<void()>& compositor_created_callback) - : context_created_(false), - native_viewport_(viewport_handle.Pass(), this), + : native_viewport_(viewport_handle.Pass(), this), compositor_created_callback_(compositor_created_callback), bounds_(bounds) { AllocationScope scope; @@ -51,11 +50,8 @@ WindowTreeHostMojo::WindowTreeHostMojo( } CHECK(context_factory_) << "No GL bindings."; - gles2_client_.reset(new GLES2ClientImpl( - gles2_handle.Pass(), - base::Bind(&WindowTreeHostMojo::DidCreateContext, - base::Unretained(this)))); native_viewport_->CreateGLES2Context(gles2_client_handle.Pass()); + gles2_client_.reset(new GLES2ClientImpl(gles2_handle.Pass())); } WindowTreeHostMojo::~WindowTreeHostMojo() {} @@ -170,7 +166,9 @@ void WindowTreeHostMojo::OnBoundsChanged(const Rect& bounds) { bounds.size().width(), bounds.size().height()); if (delegate_) window()->SetBounds(gfx::Rect(bounds_.size())); - CreateCompositorIfNeeded(); + CreateCompositor(GetAcceleratedWidget()); + compositor_created_callback_.Run(); + NotifyHostResized(bounds_.size()); } void WindowTreeHostMojo::OnDestroyed() { @@ -207,21 +205,5 @@ void WindowTreeHostMojo::OnEvent(const Event& event) { } }; -//////////////////////////////////////////////////////////////////////////////// -// WindowTreeHostMojo, private: - -void WindowTreeHostMojo::DidCreateContext() { - context_created_ = true; - CreateCompositorIfNeeded(); -} - -void WindowTreeHostMojo::CreateCompositorIfNeeded() { - if (bounds_.IsEmpty() || !context_created_) - return; - CreateCompositor(GetAcceleratedWidget()); - compositor_created_callback_.Run(); - NotifyHostResized(bounds_.size()); -} - } // namespace examples } // namespace mojo diff --git a/mojo/examples/aura_demo/root_window_host_mojo.h b/mojo/examples/aura_demo/root_window_host_mojo.h index 6333a54..ab5e737 100644 --- a/mojo/examples/aura_demo/root_window_host_mojo.h +++ b/mojo/examples/aura_demo/root_window_host_mojo.h @@ -66,13 +66,9 @@ class WindowTreeHostMojo : public aura::WindowTreeHost, virtual void OnBoundsChanged(const Rect& bounds) OVERRIDE; virtual void OnEvent(const Event& event) OVERRIDE; - void DidCreateContext(); - void CreateCompositorIfNeeded(); - static ui::ContextFactory* context_factory_; scoped_ptr<GLES2ClientImpl> gles2_client_; - bool context_created_; RemotePtr<NativeViewport> native_viewport_; base::Callback<void()> compositor_created_callback_; diff --git a/mojo/examples/compositor_app/compositor_app.cc b/mojo/examples/compositor_app/compositor_app.cc index f8c7078..cbebb76 100644 --- a/mojo/examples/compositor_app/compositor_app.cc +++ b/mojo/examples/compositor_app/compositor_app.cc @@ -37,10 +37,10 @@ class SampleApp : public ShellClient { : shell_(shell_handle.Pass(), this) { ScopedMessagePipeHandle client_handle, native_viewport_handle; CreateMessagePipe(&client_handle, &native_viewport_handle); - native_viewport_client_.reset( - new NativeViewportClientImpl(native_viewport_handle.Pass())); AllocationScope scope; shell_->Connect("mojo:mojo_native_viewport_service", client_handle.Pass()); + native_viewport_client_.reset( + new NativeViewportClientImpl(native_viewport_handle.Pass())); } virtual void AcceptConnection(ScopedMessagePipeHandle handle) MOJO_OVERRIDE { @@ -59,18 +59,11 @@ class SampleApp : public ShellClient { ScopedMessagePipeHandle gles2_client_handle; CreateMessagePipe(&gles2_handle, &gles2_client_handle); - gles2_client_.reset(new GLES2ClientImpl( - gles2_handle.Pass(), - base::Bind(&NativeViewportClientImpl::DidCreateContext, - base::Unretained(this)))); viewport_->CreateGLES2Context(gles2_client_handle.Pass()); + gles2_client_.reset(new GLES2ClientImpl(gles2_handle.Pass())); host_.reset(new CompositorHost(gles2_client_.get())); } - void DidCreateContext() { - host_->DidCreateContext(); - } - virtual ~NativeViewportClientImpl() {} virtual void OnCreated() MOJO_OVERRIDE { diff --git a/mojo/examples/compositor_app/compositor_host.cc b/mojo/examples/compositor_app/compositor_host.cc index cc45c19..6ae3f78 100644 --- a/mojo/examples/compositor_app/compositor_host.cc +++ b/mojo/examples/compositor_app/compositor_host.cc @@ -69,9 +69,6 @@ CompositorHost::~CompositorHost() {} void CompositorHost::SetSize(gfx::Size viewport_size) { tree_->SetViewportSize(viewport_size); -} - -void CompositorHost::DidCreateContext() { tree_->SetLayerTreeHostClientReady(); tree_->InitializeOutputSurfaceIfNeeded(); } diff --git a/mojo/examples/compositor_app/compositor_host.h b/mojo/examples/compositor_app/compositor_host.h index 3b4064f..ba03a54 100644 --- a/mojo/examples/compositor_app/compositor_host.h +++ b/mojo/examples/compositor_app/compositor_host.h @@ -26,7 +26,6 @@ class CompositorHost : public cc::LayerTreeHostClient { virtual ~CompositorHost(); void SetSize(gfx::Size viewport_size); - void DidCreateContext(); // cc::LayerTreeHostClient implementation. virtual void WillBeginMainFrame(int frame_id) OVERRIDE; diff --git a/mojo/examples/compositor_app/gles2_client_impl.cc b/mojo/examples/compositor_app/gles2_client_impl.cc index 5cc0321..fc28952 100644 --- a/mojo/examples/compositor_app/gles2_client_impl.cc +++ b/mojo/examples/compositor_app/gles2_client_impl.cc @@ -11,13 +11,9 @@ namespace mojo { namespace examples { -GLES2ClientImpl::GLES2ClientImpl( - ScopedMessagePipeHandle pipe, - const base::Callback<void()>& context_created_callback) - : context_created_callback_(context_created_callback) { +GLES2ClientImpl::GLES2ClientImpl(ScopedMessagePipeHandle pipe) { context_ = MojoGLES2CreateContext( pipe.release().value(), - &DidCreateContextThunk, &ContextLostThunk, NULL, this); @@ -42,16 +38,6 @@ gpu::ContextSupport* GLES2ClientImpl::Support() const { MojoGLES2GetContextSupport(context_)); } -void GLES2ClientImpl::DidCreateContext() { - TRACE_EVENT0("compositor_app", "DidCreateContext"); - if (!context_created_callback_.is_null()) - context_created_callback_.Run(); -} - -void GLES2ClientImpl::DidCreateContextThunk(void* closure) { - static_cast<GLES2ClientImpl*>(closure)->DidCreateContext(); -} - void GLES2ClientImpl::ContextLost() { if (context_) { MojoGLES2DestroyContext(context_); diff --git a/mojo/examples/compositor_app/gles2_client_impl.h b/mojo/examples/compositor_app/gles2_client_impl.h index 657bf79..2ee41d6 100644 --- a/mojo/examples/compositor_app/gles2_client_impl.h +++ b/mojo/examples/compositor_app/gles2_client_impl.h @@ -23,22 +23,16 @@ namespace examples { class GLES2ClientImpl { public: - GLES2ClientImpl( - ScopedMessagePipeHandle pipe, - const base::Callback<void()>& context_created_callback); + explicit GLES2ClientImpl(ScopedMessagePipeHandle pipe); virtual ~GLES2ClientImpl(); gpu::gles2::GLES2Interface* Interface() const; gpu::ContextSupport* Support() const; private: - void DidCreateContext(); - static void DidCreateContextThunk(void* closure); void ContextLost(); static void ContextLostThunk(void* closure); - base::Callback<void()> context_created_callback_; - MojoGLES2Context context_; MOJO_DISALLOW_COPY_AND_ASSIGN(GLES2ClientImpl); diff --git a/mojo/examples/launcher/launcher.cc b/mojo/examples/launcher/launcher.cc index cb4620e..c2d94c7 100644 --- a/mojo/examples/launcher/launcher.cc +++ b/mojo/examples/launcher/launcher.cc @@ -202,11 +202,11 @@ class LauncherImpl : public ShellClient, ScopedMessagePipeHandle client_handle, native_viewport_handle; CreateMessagePipe(&client_handle, &native_viewport_handle); + AllocationScope scope; + shell_->Connect("mojo:mojo_native_viewport_service", client_handle.Pass()); root_window_host_.reset(new WindowTreeHostMojo( native_viewport_handle.Pass(), gfx::Rect(50, 50, 450, 60), base::Bind(&LauncherImpl::HostContextCreated, base::Unretained(this)))); - AllocationScope scope; - shell_->Connect("mojo:mojo_native_viewport_service", client_handle.Pass()); } private: diff --git a/mojo/examples/sample_app/gles2_client_impl.cc b/mojo/examples/sample_app/gles2_client_impl.cc index eb7f47b..8abff8b 100644 --- a/mojo/examples/sample_app/gles2_client_impl.cc +++ b/mojo/examples/sample_app/gles2_client_impl.cc @@ -22,14 +22,13 @@ float CalculateDragDistance(const gfx::PointF& start, const Point& end) { } GLES2ClientImpl::GLES2ClientImpl(ScopedMessagePipeHandle pipe) - : getting_animation_frames_(false), - context_created_(false) { + : getting_animation_frames_(false) { context_ = MojoGLES2CreateContext( pipe.release().value(), - &DidCreateContextThunk, &ContextLostThunk, &DrawAnimationFrameThunk, this); + MojoGLES2MakeCurrent(context_); } GLES2ClientImpl::~GLES2ClientImpl() { @@ -38,7 +37,10 @@ GLES2ClientImpl::~GLES2ClientImpl() { void GLES2ClientImpl::SetSize(const Size& size) { size_ = gfx::Size(size.width(), size.height()); - InitializeCubeIfNeeded(); + if (size_.IsEmpty()) + return; + cube_.Init(size_.width(), size_.height()); + RequestAnimationFrames(); } void GLES2ClientImpl::HandleInputEvent(const Event& event) { @@ -81,23 +83,6 @@ void GLES2ClientImpl::HandleInputEvent(const Event& event) { } } -void GLES2ClientImpl::DidCreateContext() { - MojoGLES2MakeCurrent(context_); - context_created_ = true; - InitializeCubeIfNeeded(); -} - -void GLES2ClientImpl::InitializeCubeIfNeeded() { - if (size_.IsEmpty() || !context_created_) - return; - cube_.Init(size_.width(), size_.height()); - RequestAnimationFrames(); -} - -void GLES2ClientImpl::DidCreateContextThunk(void* closure) { - static_cast<GLES2ClientImpl*>(closure)->DidCreateContext(); -} - void GLES2ClientImpl::ContextLost() { CancelAnimationFrames(); } diff --git a/mojo/examples/sample_app/gles2_client_impl.h b/mojo/examples/sample_app/gles2_client_impl.h index a30b546..9833e2a 100644 --- a/mojo/examples/sample_app/gles2_client_impl.h +++ b/mojo/examples/sample_app/gles2_client_impl.h @@ -24,8 +24,6 @@ class GLES2ClientImpl { void HandleInputEvent(const Event& event); private: - void DidCreateContext(); - static void DidCreateContextThunk(void* closure); void ContextLost(); static void ContextLostThunk(void* closure); void DrawAnimationFrame(); @@ -34,8 +32,6 @@ class GLES2ClientImpl { void RequestAnimationFrames(); void CancelAnimationFrames(); - void InitializeCubeIfNeeded(); - MojoTimeTicks last_time_; gfx::Size size_; SpinningCube cube_; @@ -45,7 +41,6 @@ class GLES2ClientImpl { bool getting_animation_frames_; MojoGLES2Context context_; - bool context_created_; MOJO_DISALLOW_COPY_AND_ASSIGN(GLES2ClientImpl); }; diff --git a/mojo/examples/sample_app/sample_app.cc b/mojo/examples/sample_app/sample_app.cc index bca805f..477d8be 100644 --- a/mojo/examples/sample_app/sample_app.cc +++ b/mojo/examples/sample_app/sample_app.cc @@ -35,10 +35,10 @@ class SampleApp : public ShellClient { : shell_(shell_handle.Pass(), this) { MessagePipe pipe; - native_viewport_client_.reset( - new NativeViewportClientImpl(pipe.handle0.Pass())); mojo::AllocationScope scope; shell_->Connect("mojo:mojo_native_viewport_service", pipe.handle1.Pass()); + native_viewport_client_.reset( + new NativeViewportClientImpl(pipe.handle0.Pass())); } virtual void AcceptConnection(ScopedMessagePipeHandle handle) MOJO_OVERRIDE { @@ -63,8 +63,8 @@ class SampleApp : public ShellClient { viewport_->Show(); MessagePipe pipe; - gles2_client_.reset(new GLES2ClientImpl(pipe.handle0.Pass())); viewport_->CreateGLES2Context(pipe.handle1.Pass()); + gles2_client_.reset(new GLES2ClientImpl(pipe.handle0.Pass())); } virtual ~NativeViewportClientImpl() { diff --git a/mojo/gles2/gles2_client_impl.cc b/mojo/gles2/gles2_client_impl.cc index eec5019..f776d8e 100644 --- a/mojo/gles2/gles2_client_impl.cc +++ b/mojo/gles2/gles2_client_impl.cc @@ -4,23 +4,20 @@ #include "mojo/gles2/gles2_client_impl.h" -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - +#include "mojo/public/bindings/sync_dispatcher.h" #include "mojo/public/gles2/gles2.h" +#include "mojo/public/system/core_cpp.h" namespace mojo { namespace gles2 { GLES2ClientImpl::GLES2ClientImpl(MojoAsyncWaiter* async_waiter, ScopedMessagePipeHandle pipe, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure) : service_(pipe.Pass(), this, NULL, async_waiter), implementation_(NULL), - created_callback_(created_callback), lost_callback_(lost_callback), animation_callback_(animation_callback), closure_(closure) { @@ -30,6 +27,17 @@ GLES2ClientImpl::~GLES2ClientImpl() { service_->Destroy(); } +bool GLES2ClientImpl::Initialize() { + MessagePipe sync_pipe; + sync_dispatcher_.reset( + new SyncDispatcher<GLES2SyncClient>(sync_pipe.handle1.Pass(), this)); + service_->Initialize(sync_pipe.handle0.Pass()); + // Wait for DidCreateContext to come on the sync client pipe. + if (!sync_dispatcher_->WaitAndDispatchOneMessage()) + return false; + return !!implementation_; +} + void GLES2ClientImpl::RequestAnimationFrames() { service_->RequestAnimationFrames(); } @@ -46,7 +54,6 @@ void GLES2ClientImpl::DidCreateContext(uint64_t encoded) { // still in-process, we just reinterpret_cast the value into a GL interface. implementation_ = reinterpret_cast<gpu::gles2::GLES2Implementation*>( static_cast<uintptr_t>(encoded)); - created_callback_(closure_); } void GLES2ClientImpl::ContextLost() { @@ -57,5 +64,5 @@ void GLES2ClientImpl::DrawAnimationFrame() { animation_callback_(closure_); } -} // namespace examples +} // namespace gles2 } // namespace mojo diff --git a/mojo/gles2/gles2_client_impl.h b/mojo/gles2/gles2_client_impl.h index 7c5073f7..45a0f0d 100644 --- a/mojo/gles2/gles2_client_impl.h +++ b/mojo/gles2/gles2_client_impl.h @@ -5,6 +5,7 @@ #ifndef MOJO_GLES2_GLES2_CLIENT_IMPL_H_ #define MOJO_GLES2_GLES2_CLIENT_IMPL_H_ +#include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "mojo/public/bindings/remote_ptr.h" #include "mojo/public/gles2/gles2.h" @@ -13,17 +14,23 @@ struct MojoGLES2ContextPrivate {}; namespace mojo { + +template<typename S> class SyncDispatcher; + namespace gles2 { -class GLES2ClientImpl : public GLES2Client, public MojoGLES2ContextPrivate { +class GLES2ClientImpl : public GLES2Client, + public GLES2SyncClient, + public MojoGLES2ContextPrivate { public: explicit GLES2ClientImpl(MojoAsyncWaiter* async_waiter, ScopedMessagePipeHandle pipe, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure); virtual ~GLES2ClientImpl(); + bool Initialize(); + gpu::gles2::GLES2Interface* interface() const { return implementation_; } gpu::ContextSupport* context_support() const { return implementation_; } void RequestAnimationFrames(); @@ -34,10 +41,11 @@ class GLES2ClientImpl : public GLES2Client, public MojoGLES2ContextPrivate { virtual void ContextLost() MOJO_OVERRIDE; virtual void DrawAnimationFrame() MOJO_OVERRIDE; + bool WaitForSyncMessageAndDispatch(); RemotePtr<GLES2> service_; + scoped_ptr<SyncDispatcher<GLES2SyncClient> > sync_dispatcher_; gpu::gles2::GLES2Implementation* implementation_; - MojoGLES2ContextCreated created_callback_; MojoGLES2ContextLost lost_callback_; MojoGLES2DrawAnimationFrame animation_callback_; void* closure_; diff --git a/mojo/gles2/gles2_support_impl.cc b/mojo/gles2/gles2_support_impl.cc index 14d99ac..9a90a09 100644 --- a/mojo/gles2/gles2_support_impl.cc +++ b/mojo/gles2/gles2_support_impl.cc @@ -60,18 +60,19 @@ void GLES2SupportImpl::Terminate() { MojoGLES2Context GLES2SupportImpl::CreateContext( MessagePipeHandle handle, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure) { mojo::ScopedMessagePipeHandle scoped_handle = mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(handle)); - return new GLES2ClientImpl(async_waiter_, - scoped_handle.Pass(), - created_callback, - lost_callback, - animation_callback, - closure); + scoped_ptr<GLES2ClientImpl> client(new GLES2ClientImpl(async_waiter_, + scoped_handle.Pass(), + lost_callback, + animation_callback, + closure)); + if (!client->Initialize()) + client.reset(); + return client.release(); } void GLES2SupportImpl::DestroyContext(MojoGLES2Context context) { diff --git a/mojo/gles2/gles2_support_impl.h b/mojo/gles2/gles2_support_impl.h index 90d1ea3..a57000d 100644 --- a/mojo/gles2/gles2_support_impl.h +++ b/mojo/gles2/gles2_support_impl.h @@ -22,7 +22,6 @@ class MOJO_GLES2_IMPL_EXPORT GLES2SupportImpl : public GLES2Support { virtual void Terminate() OVERRIDE; virtual MojoGLES2Context CreateContext( MessagePipeHandle handle, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure) OVERRIDE; diff --git a/mojo/mojo_public.gypi b/mojo/mojo_public.gypi index eb12232..c68d6fa 100644 --- a/mojo/mojo_public.gypi +++ b/mojo/mojo_public.gypi @@ -168,6 +168,7 @@ 'public/bindings/error_handler.h', 'public/bindings/passable.h', 'public/bindings/remote_ptr.h', + 'public/bindings/sync_dispatcher.h', 'public/bindings/type_converter.h', 'public/bindings/lib/array.cc', 'public/bindings/lib/array_internal.h', @@ -188,6 +189,7 @@ 'public/bindings/lib/message_queue.h', 'public/bindings/lib/scratch_buffer.cc', 'public/bindings/lib/scratch_buffer.h', + 'public/bindings/lib/sync_dispatcher.cc', ], }, { diff --git a/mojo/public/bindings/lib/sync_dispatcher.cc b/mojo/public/bindings/lib/sync_dispatcher.cc new file mode 100644 index 0000000..bbc521c --- /dev/null +++ b/mojo/public/bindings/lib/sync_dispatcher.cc @@ -0,0 +1,50 @@ +// Copyright 2014 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 "mojo/public/bindings/sync_dispatcher.h" + +#include <stdlib.h> + +#include "mojo/public/bindings/lib/message.h" + +namespace mojo { + +bool WaitForMessageAndDispatch(MessagePipeHandle handle, + mojo::MessageReceiver* receiver) { + uint32_t num_bytes = 0, num_handles = 0; + while (true) { + MojoResult rv = ReadMessageRaw(handle, + NULL, + &num_bytes, + NULL, + &num_handles, + MOJO_READ_MESSAGE_FLAG_NONE); + if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) + break; + if (rv != MOJO_RESULT_SHOULD_WAIT) + return false; + rv = Wait(handle, MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE); + if (rv != MOJO_RESULT_OK) + return false; + } + + Message message; + message.data = static_cast<MessageData*>(malloc(num_bytes)); + message.handles.resize(num_handles); + + MojoResult rv = + ReadMessageRaw(handle, + message.data, + &num_bytes, + message.handles.empty() + ? NULL + : reinterpret_cast<MojoHandle*>(&message.handles[0]), + &num_handles, + MOJO_READ_MESSAGE_FLAG_NONE); + if (rv != MOJO_RESULT_OK) + return false; + return receiver->Accept(&message); +} + +} // namespace mojo diff --git a/mojo/public/bindings/sync_dispatcher.h b/mojo/public/bindings/sync_dispatcher.h new file mode 100644 index 0000000..096ffbd --- /dev/null +++ b/mojo/public/bindings/sync_dispatcher.h @@ -0,0 +1,37 @@ +// Copyright 2014 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 MOJO_PUBLIC_BINDINGS_SYNC_DISPATCHER_H_ +#define MOJO_PUBLIC_BINDINGS_SYNC_DISPATCHER_H_ + +#include "mojo/public/system/core_cpp.h" + +namespace mojo { + +class MessageReceiver; + +// Waits for one message to arrive on the message pipe, and dispatch it to the +// receiver. Returns true on success, false on failure. +bool WaitForMessageAndDispatch(MessagePipeHandle handle, + mojo::MessageReceiver* receiver); + +template<typename S> class SyncDispatcher { + public: + SyncDispatcher(ScopedMessagePipeHandle message_pipe, S* sink) + : message_pipe_(message_pipe.Pass()), + stub_(sink) { + } + + bool WaitAndDispatchOneMessage() { + return WaitForMessageAndDispatch(message_pipe_.get(), &stub_); + } + + private: + ScopedMessagePipeHandle message_pipe_; + typename S::_Stub stub_; +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_BINDINGS_SYNC_DISPATCHER_H_ diff --git a/mojo/public/gles2/gles2.h b/mojo/public/gles2/gles2.h index fbf9fa2..8effd31 100644 --- a/mojo/public/gles2/gles2.h +++ b/mojo/public/gles2/gles2.h @@ -23,7 +23,6 @@ MOJO_GLES2_EXPORT void MojoGLES2Initialize(MojoAsyncWaiter* async_waiter); MOJO_GLES2_EXPORT void MojoGLES2Terminate(); MOJO_GLES2_EXPORT MojoGLES2Context MojoGLES2CreateContext( MojoHandle handle, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure); diff --git a/mojo/public/gles2/gles2_private.cc b/mojo/public/gles2/gles2_private.cc index 536e0fc..1752828 100644 --- a/mojo/public/gles2/gles2_private.cc +++ b/mojo/public/gles2/gles2_private.cc @@ -27,12 +27,10 @@ void MojoGLES2Terminate() { MojoGLES2Context MojoGLES2CreateContext( MojoHandle handle, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure) { return g_gles2_support->CreateContext(mojo::MessagePipeHandle(handle), - created_callback, lost_callback, animation_callback, closure); diff --git a/mojo/public/gles2/gles2_private.h b/mojo/public/gles2/gles2_private.h index 87ea4b9..8465cae 100644 --- a/mojo/public/gles2/gles2_private.h +++ b/mojo/public/gles2/gles2_private.h @@ -28,7 +28,6 @@ class MOJO_GLES2_EXPORT GLES2Support { virtual void Terminate() = 0; virtual MojoGLES2Context CreateContext( MessagePipeHandle handle, - MojoGLES2ContextCreated created_callback, MojoGLES2ContextLost lost_callback, MojoGLES2DrawAnimationFrame animation_callback, void* closure) = 0; diff --git a/mojo/public/gles2/gles2_types.h b/mojo/public/gles2/gles2_types.h index b6a9838..c7d2216 100644 --- a/mojo/public/gles2/gles2_types.h +++ b/mojo/public/gles2/gles2_types.h @@ -16,8 +16,6 @@ extern "C" { #endif typedef struct MojoGLES2ContextPrivate *MojoGLES2Context; -// TODO(piman): create context synchronously -typedef void (*MojoGLES2ContextCreated)(void* closure); typedef void (*MojoGLES2ContextLost)(void* closure); typedef void (*MojoGLES2DrawAnimationFrame)(void* closure); diff --git a/mojo/services/gles2/gles2.mojom b/mojo/services/gles2/gles2.mojom index a27fd53..d7199d7 100644 --- a/mojo/services/gles2/gles2.mojom +++ b/mojo/services/gles2/gles2.mojom @@ -6,6 +6,7 @@ module mojo { [Peer=GLES2Client] interface GLES2 { + void Initialize(handle<message_pipe> gles2_sync_client); void RequestAnimationFrames(); void CancelAnimationFrames(); void Destroy(); @@ -13,9 +14,15 @@ interface GLES2 { [Peer=GLES2] interface GLES2Client { - void DidCreateContext(uint64 encoded); void ContextLost(); void DrawAnimationFrame(); }; +// TODO(piman): I don't want to have a peer but generator crashes if I don't +// have one. https://crbug.com/320086 +[Peer=GLES2] +interface GLES2SyncClient { + void DidCreateContext(uint64 encoded); +}; + } diff --git a/mojo/services/gles2/gles2_impl.cc b/mojo/services/gles2/gles2_impl.cc index 63ed9d7..1a16a25 100644 --- a/mojo/services/gles2/gles2_impl.cc +++ b/mojo/services/gles2/gles2_impl.cc @@ -19,6 +19,11 @@ GLES2Impl::GLES2Impl(ScopedMessagePipeHandle client) GLES2Impl::~GLES2Impl() { } +void GLES2Impl::Initialize(ScopedMessagePipeHandle sync_client_handle) { + sync_client_.reset(sync_client_handle.Pass()); + SendDidCreateContextIfNeeded(); +} + void GLES2Impl::RequestAnimationFrames() { timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(16), this, &GLES2Impl::DrawAnimationFrame); @@ -39,11 +44,16 @@ void GLES2Impl::CreateContext(gfx::AcceleratedWidget widget, false, widget, size, false, attribs, gfx::PreferDiscreteGpu)); gl_context_->SetContextLostCallback(base::Bind( &GLES2Impl::OnGLContextLost, base::Unretained(this))); + SendDidCreateContextIfNeeded(); +} +void GLES2Impl::SendDidCreateContextIfNeeded() { + if (sync_client_.is_null() || !gl_context_.get()) + return; gpu::gles2::GLES2Interface* gl = gl_context_->GetImplementation(); uint64_t encoded_gl = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(gl)); - client_->DidCreateContext(encoded_gl); + sync_client_->DidCreateContext(encoded_gl); } void GLES2Impl::OnGLContextLost() { diff --git a/mojo/services/gles2/gles2_impl.h b/mojo/services/gles2/gles2_impl.h index 077bdcd..0bdd5c9 100644 --- a/mojo/services/gles2/gles2_impl.h +++ b/mojo/services/gles2/gles2_impl.h @@ -28,16 +28,19 @@ class GLES2Impl : public GLES2 { void CreateContext(gfx::AcceleratedWidget widget, const gfx::Size& size); private: + virtual void Initialize(ScopedMessagePipeHandle sync_client_handle) OVERRIDE; virtual void RequestAnimationFrames() OVERRIDE; virtual void CancelAnimationFrames() OVERRIDE; virtual void Destroy() OVERRIDE; + void SendDidCreateContextIfNeeded(); void OnGLContextLost(); void DrawAnimationFrame(); base::RepeatingTimer<GLES2Impl> timer_; scoped_ptr<gpu::GLInProcessContext> gl_context_; RemotePtr<GLES2Client> client_; + RemotePtr<GLES2SyncClient> sync_client_; DISALLOW_COPY_AND_ASSIGN(GLES2Impl); }; |