summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/client/gl_in_process_context.cc164
-rw-r--r--gpu/command_buffer/client/gl_in_process_context.h47
-rw-r--r--gpu/command_buffer/service/in_process_command_buffer.cc55
-rw-r--r--gpu/command_buffer/service/in_process_command_buffer.h16
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);
};