diff options
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/client/gl_in_process_context.cc | 164 | ||||
-rw-r--r-- | gpu/command_buffer/client/gl_in_process_context.h | 47 | ||||
-rw-r--r-- | gpu/command_buffer/service/in_process_command_buffer.cc | 55 | ||||
-rw-r--r-- | gpu/command_buffer/service/in_process_command_buffer.h | 16 |
4 files changed, 204 insertions, 78 deletions
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc index 97f1715..cdbfc9f 100644 --- a/gpu/command_buffer/client/gl_in_process_context.cc +++ b/gpu/command_buffer/client/gl_in_process_context.cc @@ -53,16 +53,17 @@ class GLInProcessContextImpl explicit GLInProcessContextImpl(); virtual ~GLInProcessContextImpl(); - bool Initialize(bool is_offscreen, + bool Initialize(scoped_refptr<gfx::GLSurface> surface, + bool is_offscreen, bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, const char* allowed_extensions, - const int32* attrib_list, - gfx::GpuPreference gpu_preference, - const base::Closure& context_lost_callback); + const GLInProcessContextAttribs& attribs, + gfx::GpuPreference gpu_preference); // GLInProcessContext implementation: + virtual void SetContextLostCallback(const base::Closure& callback) OVERRIDE; virtual void SignalSyncPoint(unsigned sync_point, const base::Closure& callback) OVERRIDE; virtual void SignalQuery(unsigned query, const base::Closure& callback) @@ -79,7 +80,7 @@ class GLInProcessContextImpl void Destroy(); void PollQueryCallbacks(); void CallQueryCallback(size_t index); - void OnContextLost(const base::Closure& callback); + void OnContextLost(); void OnSignalSyncPoint(const base::Closure& callback); scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; @@ -92,6 +93,7 @@ class GLInProcessContextImpl unsigned int share_group_id_; bool context_lost_; + base::Closure context_lost_callback_; DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl); }; @@ -147,9 +149,16 @@ gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { return gles2_implementation_.get(); } -void GLInProcessContextImpl::OnContextLost(const base::Closure& callback) { +void GLInProcessContextImpl::SetContextLostCallback( + const base::Closure& callback) { + context_lost_callback_ = callback; +} + +void GLInProcessContextImpl::OnContextLost() { context_lost_ = true; - callback.Run(); + if (!context_lost_callback_.is_null()) { + context_lost_callback_.Run(); + } } void GLInProcessContextImpl::OnSignalSyncPoint(const base::Closure& callback) { @@ -159,47 +168,63 @@ void GLInProcessContextImpl::OnSignalSyncPoint(const base::Closure& callback) { } bool GLInProcessContextImpl::Initialize( + scoped_refptr<gfx::GLSurface> surface, bool is_offscreen, bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, const char* allowed_extensions, - const int32* attrib_list, - gfx::GpuPreference gpu_preference, - const base::Closure& context_lost_callback) { + const GLInProcessContextAttribs& attribs, + gfx::GpuPreference gpu_preference) { DCHECK(size.width() >= 0 && size.height() >= 0); - std::vector<int32> attribs; - while (attrib_list) { - int32 attrib = *attrib_list++; - switch (attrib) { - // Known attributes - case ALPHA_SIZE: - case BLUE_SIZE: - case GREEN_SIZE: - case RED_SIZE: - case DEPTH_SIZE: - case STENCIL_SIZE: - case SAMPLES: - case SAMPLE_BUFFERS: - attribs.push_back(attrib); - attribs.push_back(*attrib_list++); - break; - case NONE: - attribs.push_back(attrib); - attrib_list = NULL; - break; - default: - attribs.push_back(NONE); - attrib_list = NULL; - break; - } + const int32 ALPHA_SIZE = 0x3021; + const int32 BLUE_SIZE = 0x3022; + const int32 GREEN_SIZE = 0x3023; + const int32 RED_SIZE = 0x3024; + const int32 DEPTH_SIZE = 0x3025; + const int32 STENCIL_SIZE = 0x3026; + const int32 SAMPLES = 0x3031; + const int32 SAMPLE_BUFFERS = 0x3032; + const int32 NONE = 0x3038; + + std::vector<int32> attrib_vector; + if (attribs.alpha_size >= 0) { + attrib_vector.push_back(ALPHA_SIZE); + attrib_vector.push_back(attribs.alpha_size); + } + if (attribs.blue_size >= 0) { + attrib_vector.push_back(BLUE_SIZE); + attrib_vector.push_back(attribs.blue_size); + } + if (attribs.green_size >= 0) { + attrib_vector.push_back(GREEN_SIZE); + attrib_vector.push_back(attribs.green_size); + } + if (attribs.red_size >= 0) { + attrib_vector.push_back(RED_SIZE); + attrib_vector.push_back(attribs.red_size); + } + if (attribs.depth_size >= 0) { + attrib_vector.push_back(DEPTH_SIZE); + attrib_vector.push_back(attribs.depth_size); + } + if (attribs.stencil_size >= 0) { + attrib_vector.push_back(STENCIL_SIZE); + attrib_vector.push_back(attribs.stencil_size); + } + if (attribs.samples >= 0) { + attrib_vector.push_back(SAMPLES); + attrib_vector.push_back(attribs.samples); + } + if (attribs.sample_buffers >= 0) { + attrib_vector.push_back(SAMPLE_BUFFERS); + attrib_vector.push_back(attribs.sample_buffers); } + attrib_vector.push_back(NONE); base::Closure wrapped_callback = - base::Bind(&GLInProcessContextImpl::OnContextLost, - AsWeakPtr(), - context_lost_callback); + base::Bind(&GLInProcessContextImpl::OnContextLost, AsWeakPtr()); command_buffer_.reset(new InProcessCommandBuffer()); scoped_ptr<base::AutoLock> scoped_shared_context_lock; @@ -223,15 +248,16 @@ bool GLInProcessContextImpl::Initialize( if (!share_group && !++share_group_id_) ++share_group_id_; } - if (!command_buffer_->Initialize(is_offscreen, - share_resources, - window, - size, - allowed_extensions, - attribs, - gpu_preference, - wrapped_callback, - share_group_id_)) { + if (!command_buffer_->Initialize(surface, + is_offscreen, + share_resources, + window, + size, + allowed_extensions, + attrib_vector, + gpu_preference, + wrapped_callback, + share_group_id_)) { LOG(INFO) << "Failed to initialize InProcessCommmandBuffer"; return false; } @@ -337,6 +363,16 @@ void GLInProcessContextImpl::SignalQuery( } // anonymous namespace +GLInProcessContextAttribs::GLInProcessContextAttribs() + : alpha_size(-1), + blue_size(-1), + green_size(-1), + red_size(-1), + depth_size(-1), + stencil_size(-1), + samples(-1), + sample_buffers(-1) {} + // static GLInProcessContext* GLInProcessContext::CreateContext( bool is_offscreen, @@ -344,20 +380,42 @@ GLInProcessContext* GLInProcessContext::CreateContext( const gfx::Size& size, bool share_resources, const char* allowed_extensions, - const int32* attrib_list, - gfx::GpuPreference gpu_preference, - const base::Closure& callback) { + const GLInProcessContextAttribs& attribs, + gfx::GpuPreference gpu_preference) { scoped_ptr<GLInProcessContextImpl> context( new GLInProcessContextImpl()); if (!context->Initialize( + NULL /* surface */, is_offscreen, share_resources, window, size, allowed_extensions, - attrib_list, - gpu_preference, - callback)) + attribs, + gpu_preference)) + return NULL; + + return context.release(); +} + +// static +GLInProcessContext* GLInProcessContext::CreateWithSurface( + scoped_refptr<gfx::GLSurface> surface, + bool share_resources, + const char* allowed_extensions, + const GLInProcessContextAttribs& attribs, + gfx::GpuPreference gpu_preference) { + scoped_ptr<GLInProcessContextImpl> context( + new GLInProcessContextImpl()); + if (!context->Initialize( + surface, + surface->IsOffscreen(), + share_resources, + gfx::kNullAcceleratedWidget, + surface->GetSize(), + allowed_extensions, + attribs, + gpu_preference)) return NULL; return context.release(); diff --git a/gpu/command_buffer/client/gl_in_process_context.h b/gpu/command_buffer/client/gl_in_process_context.h index 2d0754b..09f8140 100644 --- a/gpu/command_buffer/client/gl_in_process_context.h +++ b/gpu/command_buffer/client/gl_in_process_context.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "gles2_impl_export.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_surface.h" #include "ui/gl/gpu_preference.h" namespace gfx { @@ -23,6 +24,20 @@ class GLES2Implementation; class GpuMemoryBufferFactory; +// The default uninitialized value is -1. +struct GLES2_IMPL_EXPORT GLInProcessContextAttribs { + GLInProcessContextAttribs(); + + int32 alpha_size; + int32 blue_size; + int32 green_size; + int32 red_size; + int32 depth_size; + int32 stencil_size; + int32 samples; + int32 sample_buffers; +}; + class GLES2_IMPL_EXPORT GLInProcessContext { public: virtual ~GLInProcessContext() {} @@ -30,20 +45,6 @@ class GLES2_IMPL_EXPORT GLInProcessContext { // Must be called before any GLInProcessContext instances are created. static void SetGpuMemoryBufferFactory(GpuMemoryBufferFactory* factory); - // GLInProcessContext configuration attributes. These are the same as used by - // EGL. Attributes are matched using a closest fit algorithm. - enum Attribute { - ALPHA_SIZE = 0x3021, - BLUE_SIZE = 0x3022, - GREEN_SIZE = 0x3023, - RED_SIZE = 0x3024, - DEPTH_SIZE = 0x3025, - STENCIL_SIZE = 0x3026, - SAMPLES = 0x3031, - SAMPLE_BUFFERS = 0x3032, - NONE = 0x3038 // Attrib list = terminator - }; - // Create a GLInProcessContext, if |is_offscreen| is true, renders to an // offscreen context. |attrib_list| must be NULL or a NONE-terminated list // of attribute/value pairs. @@ -53,9 +54,21 @@ class GLES2_IMPL_EXPORT GLInProcessContext { const gfx::Size& size, bool share_resources, const char* allowed_extensions, - const int32* attrib_list, - gfx::GpuPreference gpu_preference, - const base::Closure& callback); + const GLInProcessContextAttribs& attribs, + gfx::GpuPreference gpu_preference); + + // Create context with the provided GLSurface. All other arguments match + // CreateContext factory above. Can only be called if the command buffer + // service runs on the same thread as this client because GLSurface is not + // thread safe. + static GLInProcessContext* CreateWithSurface( + scoped_refptr<gfx::GLSurface> surface, + bool share_resources, + const char* allowed_extensions, + const GLInProcessContextAttribs& attribs, + gfx::GpuPreference gpu_preference); + + virtual void SetContextLostCallback(const base::Closure& callback) = 0; virtual void SignalSyncPoint(unsigned sync_point, const base::Closure& callback) = 0; diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index 766a7e0..ccbfb32 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc @@ -20,6 +20,7 @@ #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/sequence_checker.h" #include "base/threading/thread.h" #include "gpu/command_buffer/common/id_allocator.h" #include "gpu/command_buffer/service/command_buffer_service.h" @@ -32,7 +33,6 @@ #include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" #include "ui/gl/gl_share_group.h" -#include "ui/gl/gl_surface.h" namespace gpu { @@ -244,6 +244,7 @@ InProcessCommandBuffer::~InProcessCommandBuffer() { } bool InProcessCommandBuffer::IsContextLost() { + CheckSequencedThread(); if (context_lost_ || !command_buffer_) { return true; } @@ -252,11 +253,13 @@ bool InProcessCommandBuffer::IsContextLost() { } void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) { + CheckSequencedThread(); DCHECK(!surface_->IsOffscreen()); surface_->Resize(size); } bool InProcessCommandBuffer::MakeCurrent() { + CheckSequencedThread(); command_buffer_lock_.AssertAcquired(); if (!context_lost_ && decoder_->MakeCurrent()) @@ -268,6 +271,7 @@ bool InProcessCommandBuffer::MakeCurrent() { } void InProcessCommandBuffer::PumpCommands() { + CheckSequencedThread(); command_buffer_lock_.AssertAcquired(); if (!MakeCurrent()) @@ -277,12 +281,14 @@ void InProcessCommandBuffer::PumpCommands() { } bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) { + CheckSequencedThread(); command_buffer_lock_.AssertAcquired(); command_buffer_->SetGetBuffer(transfer_buffer_id); return true; } bool InProcessCommandBuffer::Initialize( + scoped_refptr<gfx::GLSurface> surface, bool is_offscreen, bool share_resources, gfx::AcceleratedWidget window, @@ -297,8 +303,13 @@ bool InProcessCommandBuffer::Initialize( context_lost_callback_ = WrapCallback(context_lost_callback); share_group_id_ = share_group_id; - base::WaitableEvent completion(true, false); - bool result = false; + if (surface) { + // GPU thread must be the same as client thread due to GLSurface not being + // thread safe. + sequence_checker_.reset(new base::SequenceChecker); + surface_ = surface; + } + base::Callback<bool(void)> init_task = base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread, base::Unretained(this), @@ -308,6 +319,9 @@ bool InProcessCommandBuffer::Initialize( allowed_extensions, attribs, gpu_preference); + + base::WaitableEvent completion(true, false); + bool result = false; QueueTask( base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion)); completion.Wait(); @@ -321,6 +335,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( const char* allowed_extensions, const std::vector<int32>& attribs, gfx::GpuPreference gpu_preference) { + CheckSequencedThread(); // Use one share group for all contexts. CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, (new gfx::GLShareGroup)); @@ -377,10 +392,12 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( decoder_->set_engine(gpu_scheduler_.get()); - if (is_offscreen) - surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); - else - surface_ = gfx::GLSurface::CreateViewGLSurface(window); + if (!surface_) { + if (is_offscreen) + surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); + else + surface_ = gfx::GLSurface::CreateViewGLSurface(window); + } if (!surface_.get()) { LOG(ERROR) << "Could not create GLSurface."; @@ -448,6 +465,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( } void InProcessCommandBuffer::Destroy() { + CheckSequencedThread(); base::WaitableEvent completion(true, false); bool result = false; base::Callback<bool(void)> destroy_task = base::Bind( @@ -458,6 +476,7 @@ void InProcessCommandBuffer::Destroy() { } bool InProcessCommandBuffer::DestroyOnGpuThread() { + CheckSequencedThread(); command_buffer_.reset(); // Clean up GL resources if possible. bool have_context = context_ && context_->MakeCurrent(surface_); @@ -472,9 +491,15 @@ bool InProcessCommandBuffer::DestroyOnGpuThread() { return true; } +void InProcessCommandBuffer::CheckSequencedThread() { + DCHECK(!sequence_checker_ || + sequence_checker_->CalledOnValidSequencedThread()); +} + unsigned int InProcessCommandBuffer::CreateImageForGpuMemoryBuffer( gfx::GpuMemoryBufferHandle buffer, gfx::Size size) { + CheckSequencedThread(); unsigned int image_id; { // TODO: ID allocation should go through CommandBuffer @@ -494,12 +519,14 @@ void InProcessCommandBuffer::CreateImageOnGpuThread( gfx::GpuMemoryBufferHandle buffer, gfx::Size size, unsigned int image_id) { + CheckSequencedThread(); scoped_refptr<gfx::GLImage> gl_image = gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer, size); decoder_->GetContextGroup()->image_manager()->AddImage(gl_image, image_id); } void InProcessCommandBuffer::RemoveImage(unsigned int image_id) { + CheckSequencedThread(); { // TODO: ID allocation should go through CommandBuffer base::AutoLock lock(command_buffer_lock_); @@ -514,10 +541,12 @@ void InProcessCommandBuffer::RemoveImage(unsigned int image_id) { } void InProcessCommandBuffer::RemoveImageOnGpuThread(unsigned int image_id) { + CheckSequencedThread(); decoder_->GetContextGroup()->image_manager()->RemoveImage(image_id); } void InProcessCommandBuffer::OnContextLost() { + CheckSequencedThread(); if (!context_lost_callback_.is_null()) { context_lost_callback_.Run(); context_lost_callback_.Reset(); @@ -535,6 +564,7 @@ void InProcessCommandBuffer::OnContextLost() { } CommandBuffer::State InProcessCommandBuffer::GetStateFast() { + CheckSequencedThread(); base::AutoLock lock(state_after_last_flush_lock_); if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U) last_state_ = state_after_last_flush_; @@ -542,19 +572,23 @@ CommandBuffer::State InProcessCommandBuffer::GetStateFast() { } CommandBuffer::State InProcessCommandBuffer::GetState() { + CheckSequencedThread(); return GetStateFast(); } CommandBuffer::State InProcessCommandBuffer::GetLastState() { + CheckSequencedThread(); return last_state_; } int32 InProcessCommandBuffer::GetLastToken() { + CheckSequencedThread(); GetStateFast(); return last_state_.token; } void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) { + CheckSequencedThread(); ScopedEvent handle_flush(&flush_event_); base::AutoLock lock(command_buffer_lock_); command_buffer_->Flush(put_offset); @@ -568,6 +602,7 @@ void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) { } void InProcessCommandBuffer::Flush(int32 put_offset) { + CheckSequencedThread(); if (last_state_.error != gpu::error::kNoError) return; @@ -583,6 +618,7 @@ void InProcessCommandBuffer::Flush(int32 put_offset) { CommandBuffer::State InProcessCommandBuffer::FlushSync(int32 put_offset, int32 last_known_get) { + CheckSequencedThread(); if (put_offset == last_known_get || last_state_.error != gpu::error::kNoError) return last_state_; @@ -598,6 +634,7 @@ CommandBuffer::State InProcessCommandBuffer::FlushSync(int32 put_offset, } void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) { + CheckSequencedThread(); if (last_state_.error != gpu::error::kNoError) return; @@ -614,11 +651,13 @@ void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) { gpu::Buffer InProcessCommandBuffer::CreateTransferBuffer(size_t size, int32* id) { + CheckSequencedThread(); base::AutoLock lock(command_buffer_lock_); return command_buffer_->CreateTransferBuffer(size, id); } void InProcessCommandBuffer::DestroyTransferBuffer(int32 id) { + CheckSequencedThread(); base::Closure task = base::Bind(&CommandBuffer::DestroyTransferBuffer, base::Unretained(command_buffer_.get()), id); @@ -637,10 +676,12 @@ uint32 InProcessCommandBuffer::InsertSyncPoint() { } void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point, const base::Closure& callback) { + CheckSequencedThread(); QueueTask(WrapCallback(callback)); } gpu::error::Error InProcessCommandBuffer::GetLastError() { + CheckSequencedThread(); return last_state_.error; } diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h index d2e103a..9bdbd49 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.h +++ b/gpu/command_buffer/service/in_process_command_buffer.h @@ -17,8 +17,13 @@ #include "gpu/gpu_export.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_surface.h" #include "ui/gl/gpu_preference.h" +namespace base { +class SequenceChecker; +} + namespace gfx { class GLContext; class GLImage; @@ -57,7 +62,11 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { static void EnableVirtualizedContext(); - bool Initialize(bool is_offscreen, + // If |surface| is not NULL, use it directly; in this case, the command + // buffer gpu thread must be the same as the client thread. Otherwise create + // a new GLSurface. + bool Initialize(scoped_refptr<gfx::GLSurface> surface, + bool is_offscreen, bool share_resources, gfx::AcceleratedWidget window, const gfx::Size& size, @@ -118,6 +127,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { base::Closure WrapCallback(const base::Closure& callback); State GetStateFast(); void QueueTask(const base::Closure& task) { queue_->QueueTask(task); } + void CheckSequencedThread(); // Callbacks: void OnContextLost(); @@ -149,6 +159,10 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer { State state_after_last_flush_; base::Lock state_after_last_flush_lock_; + // Only used with explicit scheduling and the gpu thread is the same as + // the client thread. + scoped_ptr<base::SequenceChecker> sequence_checker_; + DISALLOW_COPY_AND_ASSIGN(InProcessCommandBuffer); }; |