diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-16 20:54:53 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-16 20:54:53 +0000 |
commit | 7196e011d46f597b406e43a1978fa9d846e747c4 (patch) | |
tree | b13701827207e5a223c9a916bdd90d6ca892e6d8 | |
parent | c59aa47960369c63ac773d5cf4b2d1052d4a69c3 (diff) | |
download | chromium_src-7196e011d46f597b406e43a1978fa9d846e747c4.zip chromium_src-7196e011d46f597b406e43a1978fa9d846e747c4.tar.gz chromium_src-7196e011d46f597b406e43a1978fa9d846e747c4.tar.bz2 |
Automatically put all GL contexts associated with a particular GPU channel (and renderer process) in the same share group.
This is work towards allowing offscreen canvas contexts to be allocated before compositor view contexts are created. This is a problem because a canvas might be created before the window it will be displayed in exists.
This does not fix the bug on its own.
BUG=80703
Review URL: http://codereview.chromium.org/7104148
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89395 0039d316-1c4b-4281-b951-d872f2087c98
34 files changed, 236 insertions, 123 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index dbb8e6a..0031602 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -33,6 +33,7 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, renderer_id_(renderer_id), renderer_process_(base::kNullProcessHandle), renderer_pid_(base::kNullProcessId), + share_group_(new gfx::GLShareGroup), watchdog_(watchdog) { DCHECK(gpu_channel_manager); DCHECK(renderer_id); diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index a7bf112..10b2315 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -11,6 +11,7 @@ #include <vector> #include "base/id_map.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/process.h" #include "build/build_config.h" @@ -19,6 +20,7 @@ #include "content/common/gpu/gpu_surface_stub.h" #include "content/common/message_router.h" #include "ipc/ipc_sync_channel.h" +#include "ui/gfx/gl/gl_share_group.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" @@ -84,6 +86,8 @@ class GpuChannel : public IPC::Channel::Listener, void ViewResized(int32 command_buffer_route_id); + gfx::GLShareGroup* share_group() const { return share_group_.get(); } + #if defined(OS_MACOSX) virtual void AcceleratedSurfaceBuffersSwapped( int32 route_id, uint64 swap_buffers_count); @@ -156,6 +160,10 @@ class GpuChannel : public IPC::Channel::Listener, // Used to implement message routing functionality to CommandBuffer objects MessageRouter router_; + // The share group that all contexts associated with a particular renderer + // process use. + scoped_refptr<gfx::GLShareGroup> share_group_; + #if defined(ENABLE_GPU) typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap; StubMap stubs_; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index a677337..a88161d 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -144,7 +144,8 @@ void GpuCommandBufferStub::OnInitialize( allowed_extensions_.c_str(), requested_attribs_, parent_processor, - parent_texture_id_)) { + parent_texture_id_, + channel_->share_group())) { command_buffer_->SetPutOffsetChangeCallback( NewCallback(scheduler_.get(), &gpu::GpuScheduler::PutChanged)); diff --git a/content/gpu/gpu_info_collector.cc b/content/gpu/gpu_info_collector.cc index 2e4630b..93cd767 100644 --- a/content/gpu/gpu_info_collector.cc +++ b/content/gpu/gpu_info_collector.cc @@ -31,8 +31,8 @@ scoped_refptr<gfx::GLSurface> InitializeGLSurface() { scoped_refptr<gfx::GLContext> InitializeGLContext(gfx::GLSurface* surface) { - scoped_refptr<gfx::GLContext> context(gfx::GLContext::CreateGLContext(NULL, - surface)); + scoped_refptr<gfx::GLContext> context( + gfx::GLContext::CreateGLContext(NULL, surface)); if (!context.get()) { LOG(ERROR) << "gfx::GLContext::CreateGLContext failed"; return NULL; diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc index 90825b09..b95a2c2 100644 --- a/gpu/command_buffer/client/gles2_demo.cc +++ b/gpu/command_buffer/client/gles2_demo.cc @@ -65,7 +65,8 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) { NULL, std::vector<int32>(), NULL, - 0)) { + 0, + NULL)) { return NULL; } diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index 7f74734..78845df 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -27,6 +27,7 @@ namespace gfx { class GLContext; +class GLShareGroup; class GLSurface; } @@ -63,7 +64,8 @@ class GpuScheduler : public CommandBufferEngine { const char* allowed_extensions, const std::vector<int32>& attribs, GpuScheduler* parent, - uint32 parent_texture_id); + uint32 parent_texture_id, + gfx::GLShareGroup* share_group); void Destroy(); void DestroyCommon(); diff --git a/gpu/command_buffer/service/gpu_scheduler_linux.cc b/gpu/command_buffer/service/gpu_scheduler_linux.cc index f1d49da..84d821e 100644 --- a/gpu/command_buffer/service/gpu_scheduler_linux.cc +++ b/gpu/command_buffer/service/gpu_scheduler_linux.cc @@ -4,6 +4,7 @@ #include "gpu/command_buffer/service/gpu_scheduler.h" #include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_share_group.h" #include "ui/gfx/gl/gl_surface.h" using ::base::SharedMemory; @@ -17,28 +18,21 @@ bool GpuScheduler::Initialize( const char* allowed_extensions, const std::vector<int32>& attribs, GpuScheduler* parent, - uint32 parent_texture_id) { - // Get the parent decoder and the GLContext to share IDs with, if any. + uint32 parent_texture_id, + gfx::GLShareGroup* share_group) { + // Get the parent decoder. gles2::GLES2Decoder* parent_decoder = NULL; - gfx::GLContext* parent_context = NULL; - void* parent_handle = NULL; if (parent) { parent_decoder = parent->decoder_.get(); DCHECK(parent_decoder); - - parent_context = parent_decoder->GetGLContext(); - DCHECK(parent_context); } // Create either a view or pbuffer based GLSurface. scoped_refptr<gfx::GLSurface> surface; - if (window) { - DCHECK(!parent_handle); - + if (window) surface = gfx::GLSurface::CreateViewGLSurface(window); - } else { + else surface = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)); - } if (!surface.get()) { LOG(ERROR) << "GpuScheduler::Initialize failed.\n"; @@ -48,7 +42,7 @@ bool GpuScheduler::Initialize( // Create a GLContext and attach the surface. scoped_refptr<gfx::GLContext> context( - gfx::GLContext::CreateGLContext(parent_context, surface.get())); + gfx::GLContext::CreateGLContext(share_group, surface.get())); if (!context.get()) { LOG(ERROR) << "CreateGLContext failed.\n"; Destroy(); diff --git a/gpu/command_buffer/service/gpu_scheduler_mac.cc b/gpu/command_buffer/service/gpu_scheduler_mac.cc index 449a90f..0e4d8d6 100644 --- a/gpu/command_buffer/service/gpu_scheduler_mac.cc +++ b/gpu/command_buffer/service/gpu_scheduler_mac.cc @@ -4,6 +4,7 @@ #include "gpu/command_buffer/service/gpu_scheduler.h" #include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_share_group.h" #include "ui/gfx/gl/gl_surface.h" using ::base::SharedMemory; @@ -17,16 +18,13 @@ bool GpuScheduler::Initialize( const char* allowed_extensions, const std::vector<int32>& attribs, GpuScheduler* parent, - uint32 parent_texture_id) { - // Get the parent decoder and the GLContext to share IDs with, if any. + uint32 parent_texture_id, + gfx::GLShareGroup* share_group) { + // Get the parent decoder. gles2::GLES2Decoder* parent_decoder = NULL; - gfx::GLContext* parent_context = NULL; if (parent) { parent_decoder = parent->decoder_.get(); DCHECK(parent_decoder); - - parent_context = parent_decoder->GetGLContext(); - DCHECK(parent_context); } scoped_refptr<gfx::GLSurface> surface( @@ -39,7 +37,7 @@ bool GpuScheduler::Initialize( // Create a GLContext and attach the surface. scoped_refptr<gfx::GLContext> context( - gfx::GLContext::CreateGLContext(parent_context, surface.get())); + gfx::GLContext::CreateGLContext(share_group, surface.get())); if (!context.get()) { LOG(ERROR) << "CreateGLContext failed.\n"; Destroy(); diff --git a/gpu/command_buffer/service/gpu_scheduler_win.cc b/gpu/command_buffer/service/gpu_scheduler_win.cc index 81ab10b..a92d225 100644 --- a/gpu/command_buffer/service/gpu_scheduler_win.cc +++ b/gpu/command_buffer/service/gpu_scheduler_win.cc @@ -6,6 +6,7 @@ #include "gpu/command_buffer/service/gpu_scheduler.h" #include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_share_group.h" #include "ui/gfx/gl/gl_surface.h" using ::base::SharedMemory; @@ -19,16 +20,13 @@ bool GpuScheduler::Initialize( const char* allowed_extensions, const std::vector<int32>& attribs, GpuScheduler* parent, - uint32 parent_texture_id) { - // Get the parent decoder and the GLContext to share IDs with, if any. + uint32 parent_texture_id, + gfx::GLShareGroup* share_group) { + // Get the parent decoder. gles2::GLES2Decoder* parent_decoder = NULL; - gfx::GLContext* parent_context = NULL; if (parent) { parent_decoder = parent->decoder_.get(); DCHECK(parent_decoder); - - parent_context = parent_decoder->GetGLContext(); - DCHECK(parent_context); } // Create either a view or pbuffer based GLSurface. @@ -47,7 +45,7 @@ bool GpuScheduler::Initialize( // Create a GLContext and attach the surface. scoped_refptr<gfx::GLContext> context( - gfx::GLContext::CreateGLContext(parent_context, surface.get())); + gfx::GLContext::CreateGLContext(share_group, surface.get())); if (!context.get()) { LOG(ERROR) << "CreateGLContext failed.\n"; Destroy(); diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc index 4cbfbf6..01ce0d8 100644 --- a/gpu/demos/framework/window.cc +++ b/gpu/demos/framework/window.cc @@ -64,7 +64,9 @@ bool Window::CreateRenderContext(gfx::PluginWindowHandle hwnd) { if (!gpu_scheduler->Initialize(hwnd, gfx::Size(), gpu::gles2::DisallowedExtensions(), NULL, std::vector<int32>(), - NULL, 0)) { + NULL, + 0, + NULL)) { return false; } diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 2308196..3f18c7e 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -112,7 +112,7 @@ EGLSurface Display::CreateWindowSurface(EGLConfig config, new GpuScheduler(command_buffer_.get(), NULL, NULL)); if (!gpu_scheduler->Initialize( win, gfx::Size(), gpu::gles2::DisallowedExtensions(), NULL, - attribs, NULL, 0)) + attribs, NULL, 0, NULL)) return EGL_NO_SURFACE; command_buffer_->SetPutOffsetChangeCallback( diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp index 507c4e5..5da7cf3 100644 --- a/ui/gfx/gl/gl.gyp +++ b/ui/gfx/gl/gl.gyp @@ -74,6 +74,8 @@ 'gl_implementation_win.cc', 'gl_interface.cc', 'gl_interface.h', + 'gl_share_group.cc', + 'gl_share_group.h', 'gl_surface.cc', 'gl_surface.h', 'gl_surface_linux.cc', diff --git a/ui/gfx/gl/gl_context.cc b/ui/gfx/gl/gl_context.cc index 9cf1e40..c19741f 100644 --- a/ui/gfx/gl/gl_context.cc +++ b/ui/gfx/gl/gl_context.cc @@ -13,10 +13,15 @@ namespace gfx { -GLContext::GLContext() { +GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) { + if (!share_group_.get()) + share_group_ = new GLShareGroup; + + share_group_->AddContext(this); } GLContext::~GLContext() { + share_group_->RemoveContext(this); } std::string GLContext::GetExtensions() { @@ -35,6 +40,10 @@ bool GLContext::HasExtension(const char* name) { return extensions.find(delimited_name) != std::string::npos; } +GLShareGroup* GLContext::share_group() { + return share_group_.get(); +} + bool GLContext::LosesAllContextsOnContextLost() { switch (GetGLImplementation()) { diff --git a/ui/gfx/gl/gl_context.h b/ui/gfx/gl/gl_context.h index 77f167f..2159423 100644 --- a/ui/gfx/gl/gl_context.h +++ b/ui/gfx/gl/gl_context.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "ui/gfx/gl/gl_share_group.h" namespace gfx { @@ -18,14 +19,13 @@ class GLSurface; // Encapsulates an OpenGL context, hiding platform specific management. class GLContext : public base::RefCounted<GLContext> { public: - GLContext(); + explicit GLContext(GLShareGroup* share_group); // Initializes the GL context to be compatible with the given surface. The GL // context can be made with other surface's of the same type. The compatible // surface is only needed for certain platforms like WGL, OSMesa and GLX. It // should be specific for all platforms though. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface) = 0; + virtual bool Initialize(GLSurface* compatible_surface) = 0; // Destroys the GL context. virtual void Destroy() = 0; @@ -53,11 +53,13 @@ class GLContext : public base::RefCounted<GLContext> { // context must be current. bool HasExtension(const char* name); + GLShareGroup* share_group(); + // Create a GL context that is compatible with the given surface. - // |share_context|, if non-NULL, is a context which the + // |share_group|, if non-NULL, is a group of contexts which the // internally created OpenGL context shares textures and other resources. static scoped_refptr<GLContext> CreateGLContext( - GLContext* shared_context, + GLShareGroup* share_group, GLSurface* compatible_surface); static bool LosesAllContextsOnContextLost(); @@ -66,6 +68,7 @@ class GLContext : public base::RefCounted<GLContext> { virtual ~GLContext(); private: + scoped_refptr<GLShareGroup> share_group_; friend class base::RefCounted<GLContext>; DISALLOW_COPY_AND_ASSIGN(GLContext); }; diff --git a/ui/gfx/gl/gl_context_cgl.cc b/ui/gfx/gl/gl_context_cgl.cc index 8d3d819..1629cec 100644 --- a/ui/gfx/gl/gl_context_cgl.cc +++ b/ui/gfx/gl/gl_context_cgl.cc @@ -10,22 +10,22 @@ namespace gfx { -GLContextCGL::GLContextCGL() - : context_(NULL) { +GLContextCGL::GLContextCGL(GLShareGroup* share_group) + : GLContext(share_group), + context_(NULL) { } GLContextCGL::~GLContextCGL() { Destroy(); } -bool GLContextCGL::Initialize(GLContext* shared_context, - GLSurface* compatible_surface) { +bool GLContextCGL::Initialize(GLSurface* compatible_surface) { DCHECK(compatible_surface); CGLError res = CGLCreateContext( static_cast<CGLPixelFormatObj>(GLSurfaceCGL::GetPixelFormat()), - shared_context ? - static_cast<CGLContextObj>(shared_context->GetHandle()) : NULL, + share_group() ? + static_cast<CGLContextObj>(share_group()->GetHandle()) : NULL, reinterpret_cast<CGLContextObj*>(&context_)); if (res != kCGLNoError) { LOG(ERROR) << "Error creating context."; diff --git a/ui/gfx/gl/gl_context_cgl.h b/ui/gfx/gl/gl_context_cgl.h index 0ebf558..14b59b3 100644 --- a/ui/gfx/gl/gl_context_cgl.h +++ b/ui/gfx/gl/gl_context_cgl.h @@ -11,12 +11,11 @@ class GLSurface; // Encapsulates a CGL OpenGL context. class GLContextCGL : public GLContext { public: - GLContextCGL(); + explicit GLContextCGL(GLShareGroup* share_group); virtual ~GLContextCGL(); // Implement GLContext. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface); + virtual bool Initialize(GLSurface* compatible_surface); virtual void Destroy(); virtual bool MakeCurrent(GLSurface* surface); virtual void ReleaseCurrent(GLSurface* surface); diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc index 14701c0..63f63e9 100644 --- a/ui/gfx/gl/gl_context_egl.cc +++ b/ui/gfx/gl/gl_context_egl.cc @@ -32,8 +32,9 @@ std::string GLContextEGL::GetExtensions() { return GLContext::GetExtensions() + " " + extensions; } -GLContextEGL::GLContextEGL() - : context_(NULL) +GLContextEGL::GLContextEGL(GLShareGroup* share_group) + : GLContext(share_group), + context_(NULL) { } @@ -41,8 +42,7 @@ GLContextEGL::~GLContextEGL() { Destroy(); } -bool GLContextEGL::Initialize(GLContext* shared_context, - GLSurface* compatible_surface) { +bool GLContextEGL::Initialize(GLSurface* compatible_surface) { DCHECK(compatible_surface); DCHECK(!context_); @@ -54,7 +54,7 @@ bool GLContextEGL::Initialize(GLContext* shared_context, context_ = eglCreateContext( GLSurfaceEGL::GetDisplay(), GLSurfaceEGL::GetConfig(), - shared_context ? shared_context->GetHandle() : NULL, + share_group() ? share_group()->GetHandle() : NULL, kContextAttributes); if (!context_) { LOG(ERROR) << "eglCreateContext failed with error " diff --git a/ui/gfx/gl/gl_context_egl.h b/ui/gfx/gl/gl_context_egl.h index 2e8a446..f1a8193 100644 --- a/ui/gfx/gl/gl_context_egl.h +++ b/ui/gfx/gl/gl_context_egl.h @@ -19,12 +19,11 @@ class GLSurface; // Encapsulates an EGL OpenGL ES context. class GLContextEGL : public GLContext { public: - GLContextEGL(); + explicit GLContextEGL(GLShareGroup* share_group); virtual ~GLContextEGL(); // Implement GLContext. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface); + virtual bool Initialize(GLSurface* compatible_surface); virtual void Destroy(); virtual bool MakeCurrent(GLSurface* surface); virtual void ReleaseCurrent(GLSurface* surface); diff --git a/ui/gfx/gl/gl_context_glx.cc b/ui/gfx/gl/gl_context_glx.cc index 2625ad6..1b1a355 100644 --- a/ui/gfx/gl/gl_context_glx.cc +++ b/ui/gfx/gl/gl_context_glx.cc @@ -44,19 +44,21 @@ bool IsCompositingWindowManagerActive(Display* display) { } // namespace anonymous -GLContextGLX::GLContextGLX() - : context_(NULL) { +GLContextGLX::GLContextGLX(GLShareGroup* share_group) + : GLContext(share_group), + context_(NULL) { } GLContextGLX::~GLContextGLX() { Destroy(); } -bool GLContextGLX::Initialize(GLContext* shared_context, - GLSurface* compatible_surface) { +bool GLContextGLX::Initialize(GLSurface* compatible_surface) { GLSurfaceGLX* surface_glx = static_cast<GLSurfaceGLX*>(compatible_surface); GLXFBConfig config = static_cast<GLXFBConfig>(surface_glx->GetConfig()); + GLXContext share_handle = static_cast<GLXContext>( + share_group() ? share_group()->GetHandle() : NULL); // The means by which the context is created depends on whether the drawable // type works reliably with GLX 1.3. If it does not then fall back to GLX 1.2. @@ -65,8 +67,7 @@ bool GLContextGLX::Initialize(GLContext* shared_context, GLSurfaceGLX::GetDisplay(), static_cast<GLXFBConfig>(surface_glx->GetConfig()), GLX_RGBA_TYPE, - static_cast<GLXContext>( - shared_context ? shared_context->GetHandle() : NULL), + share_handle, True); } else { Display* display = GLSurfaceGLX::GetDisplay(); @@ -94,7 +95,11 @@ bool GLContextGLX::Initialize(GLContext* shared_context, } // Attempt to create a context with each visual in turn until one works. - context_ = glXCreateContext(display, visual_info_list.get(), 0, True); + context_ = glXCreateContext( + display, + visual_info_list.get(), + share_handle, + True); } if (!context_) { diff --git a/ui/gfx/gl/gl_context_glx.h b/ui/gfx/gl/gl_context_glx.h index 0ee6b1a..e89bcb2 100644 --- a/ui/gfx/gl/gl_context_glx.h +++ b/ui/gfx/gl/gl_context_glx.h @@ -13,12 +13,11 @@ class GLSurface; // Encapsulates a GLX OpenGL context. class GLContextGLX : public GLContext { public: - GLContextGLX(); + explicit GLContextGLX(GLShareGroup* share_group); virtual ~GLContextGLX(); // Implement GLContext. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface); + virtual bool Initialize(GLSurface* compatible_surface); virtual void Destroy(); virtual bool MakeCurrent(GLSurface* surface); virtual void ReleaseCurrent(GLSurface* surface); diff --git a/ui/gfx/gl/gl_context_linux.cc b/ui/gfx/gl/gl_context_linux.cc index 8cf2eeb..238bd5f 100644 --- a/ui/gfx/gl/gl_context_linux.cc +++ b/ui/gfx/gl/gl_context_linux.cc @@ -20,27 +20,29 @@ namespace gfx { +class GLShareGroup; + scoped_refptr<GLContext> GLContext::CreateGLContext( - GLContext* shared_context, + GLShareGroup* share_group, GLSurface* compatible_surface) { switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { - scoped_refptr<GLContext> context(new GLContextOSMesa); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextOSMesa(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; } case kGLImplementationEGLGLES2: { - scoped_refptr<GLContext> context(new GLContextEGL); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextEGL(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; } case kGLImplementationDesktopGL: { - scoped_refptr<GLContext> context(new GLContextGLX); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextGLX(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; diff --git a/ui/gfx/gl/gl_context_mac.cc b/ui/gfx/gl/gl_context_mac.cc index 482d93d..cdfc6f4 100644 --- a/ui/gfx/gl/gl_context_mac.cc +++ b/ui/gfx/gl/gl_context_mac.cc @@ -16,20 +16,22 @@ namespace gfx { +class GLShareGroup; + scoped_refptr<GLContext> GLContext::CreateGLContext( - GLContext* shared_context, + GLShareGroup* share_group, GLSurface* compatible_surface) { switch (GetGLImplementation()) { case kGLImplementationDesktopGL: { - scoped_refptr<GLContext> context(new GLContextCGL); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextCGL(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; } case kGLImplementationOSMesaGL: { - scoped_refptr<GLContext> context(new GLContextOSMesa); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextOSMesa(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc index 5fe5150..2b45836 100644 --- a/ui/gfx/gl/gl_context_osmesa.cc +++ b/ui/gfx/gl/gl_context_osmesa.cc @@ -12,21 +12,20 @@ namespace gfx { -GLContextOSMesa::GLContextOSMesa() - : context_(NULL) { +GLContextOSMesa::GLContextOSMesa(GLShareGroup* share_group) + : GLContext(share_group), + context_(NULL) { } GLContextOSMesa::~GLContextOSMesa() { Destroy(); } -bool GLContextOSMesa::Initialize(GLContext* shared_context, - GLSurface* compatible_surface) { +bool GLContextOSMesa::Initialize(GLSurface* compatible_surface) { DCHECK(!context_); - OSMesaContext shared_handle = NULL; - if (shared_context) - shared_handle = static_cast<OSMesaContext>(shared_context->GetHandle()); + OSMesaContext share_handle = static_cast<OSMesaContext>( + share_group() ? share_group()->GetHandle() : NULL); GLuint format = static_cast<GLSurfaceOSMesa*>(compatible_surface)->GetFormat(); @@ -34,7 +33,7 @@ bool GLContextOSMesa::Initialize(GLContext* shared_context, 24, // depth bits 8, // stencil bits 0, // accum bits - shared_handle); + share_handle); if (!context_) { LOG(ERROR) << "OSMesaCreateContextExt failed."; return false; diff --git a/ui/gfx/gl/gl_context_osmesa.h b/ui/gfx/gl/gl_context_osmesa.h index 633c0ad..6b4c0a9 100644 --- a/ui/gfx/gl/gl_context_osmesa.h +++ b/ui/gfx/gl/gl_context_osmesa.h @@ -12,17 +12,17 @@ typedef struct osmesa_context *OSMesaContext; namespace gfx { +class GLShareGroup; class GLSurface; // Encapsulates an OSMesa OpenGL context that uses software rendering. class GLContextOSMesa : public GLContext { public: - GLContextOSMesa(); + explicit GLContextOSMesa(GLShareGroup* share_group); virtual ~GLContextOSMesa(); // Implement GLContext. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface); + virtual bool Initialize(GLSurface* compatible_surface); virtual void Destroy(); virtual bool MakeCurrent(GLSurface* surface); virtual void ReleaseCurrent(GLSurface* surface); diff --git a/ui/gfx/gl/gl_context_stub.cc b/ui/gfx/gl/gl_context_stub.cc index 195a396..82b7b94 100644 --- a/ui/gfx/gl/gl_context_stub.cc +++ b/ui/gfx/gl/gl_context_stub.cc @@ -6,14 +6,13 @@ namespace gfx { -GLContextStub::GLContextStub() { +GLContextStub::GLContextStub() : GLContext(NULL) { } GLContextStub::~GLContextStub() { } -bool GLContextStub::Initialize(GLContext* shared_context, - GLSurface* compatible_surface) { +bool GLContextStub::Initialize(GLSurface* compatible_surface) { return true; } diff --git a/ui/gfx/gl/gl_context_stub.h b/ui/gfx/gl/gl_context_stub.h index 58c2270..44219a2 100644 --- a/ui/gfx/gl/gl_context_stub.h +++ b/ui/gfx/gl/gl_context_stub.h @@ -17,8 +17,7 @@ class GLContextStub : public GLContext { virtual ~GLContextStub(); // Implement GLContext. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface); + virtual bool Initialize(GLSurface* compatible_surface); virtual void Destroy(); virtual bool MakeCurrent(GLSurface* surface); virtual void ReleaseCurrent(GLSurface* surface); diff --git a/ui/gfx/gl/gl_context_wgl.cc b/ui/gfx/gl/gl_context_wgl.cc index 7df8772..8533be7 100644 --- a/ui/gfx/gl/gl_context_wgl.cc +++ b/ui/gfx/gl/gl_context_wgl.cc @@ -13,8 +13,9 @@ namespace gfx { -GLContextWGL::GLContextWGL() - : context_(NULL) { +GLContextWGL::GLContextWGL(GLShareGroup* share_group) + : GLContext(share_group), + context_(NULL) { } GLContextWGL::~GLContextWGL() { @@ -36,8 +37,7 @@ std::string GLContextWGL::GetExtensions() { return GLContext::GetExtensions(); } -bool GLContextWGL::Initialize(GLContext* shared_context, - GLSurface* compatible_surface) { +bool GLContextWGL::Initialize(GLSurface* compatible_surface) { GLSurfaceWGL* surface_wgl = static_cast<GLSurfaceWGL*>(compatible_surface); // TODO(apatrick): When contexts and surfaces are separated, we won't be @@ -51,13 +51,14 @@ bool GLContextWGL::Initialize(GLContext* shared_context, return false; } - if (shared_context) { - if (!wglShareLists( - static_cast<HGLRC>(shared_context->GetHandle()), - context_)) { - LOG(ERROR) << "Could not share GL contexts."; - Destroy(); - return false; + if (share_group()) { + HGLRC share_handle = static_cast<HGLRC>(share_group()->GetHandle()); + if (share_handle) { + if (!wglShareLists(share_handle, context_)) { + LOG(ERROR) << "Could not share GL contexts."; + Destroy(); + return false; + } } } diff --git a/ui/gfx/gl/gl_context_wgl.h b/ui/gfx/gl/gl_context_wgl.h index f48a564..3684c96 100644 --- a/ui/gfx/gl/gl_context_wgl.h +++ b/ui/gfx/gl/gl_context_wgl.h @@ -17,12 +17,11 @@ class GLSurface; // This class is a wrapper around a GL context. class GLContextWGL : public GLContext { public: - GLContextWGL(); + explicit GLContextWGL(GLShareGroup* share_group); virtual ~GLContextWGL(); // Implement GLContext. - virtual bool Initialize(GLContext* shared_context, - GLSurface* compatible_surface); + virtual bool Initialize(GLSurface* compatible_surface); virtual void Destroy(); virtual bool MakeCurrent(GLSurface* surface); virtual void ReleaseCurrent(GLSurface* surface); diff --git a/ui/gfx/gl/gl_context_win.cc b/ui/gfx/gl/gl_context_win.cc index c9f90706..3ca5f3b 100644 --- a/ui/gfx/gl/gl_context_win.cc +++ b/ui/gfx/gl/gl_context_win.cc @@ -21,26 +21,26 @@ namespace gfx { scoped_refptr<GLContext> GLContext::CreateGLContext( - GLContext* shared_context, + GLShareGroup* share_group, GLSurface* compatible_surface) { switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { - scoped_refptr<GLContext> context(new GLContextOSMesa); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextOSMesa(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; } case kGLImplementationEGLGLES2: { - scoped_refptr<GLContext> context(new GLContextEGL); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextEGL(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; } case kGLImplementationDesktopGL: { - scoped_refptr<GLContext> context(new GLContextWGL); - if (!context->Initialize(shared_context, compatible_surface)) + scoped_refptr<GLContext> context(new GLContextWGL(share_group)); + if (!context->Initialize(compatible_surface)) return NULL; return context; diff --git a/ui/gfx/gl/gl_share_group.cc b/ui/gfx/gl/gl_share_group.cc new file mode 100644 index 0000000..fa2bfcb --- /dev/null +++ b/ui/gfx/gl/gl_share_group.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2011 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 "ui/gfx/gl/gl_share_group.h" + +#include "ui/gfx/gl/gl_context.h" + +namespace gfx { + +GLShareGroup::GLShareGroup() { +} + +void GLShareGroup::AddContext(GLContext* context) { + contexts_.insert(context); +} + +void GLShareGroup::RemoveContext(GLContext* context) { + contexts_.erase(context); +} + +void* GLShareGroup::GetHandle() { + for (ContextSet::iterator it = contexts_.begin(); + it != contexts_.end(); + ++it) { + if ((*it)->GetHandle()) + return (*it)->GetHandle(); + } + + return NULL; +} + +GLShareGroup::~GLShareGroup() { +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_share_group.h b/ui/gfx/gl/gl_share_group.h new file mode 100644 index 0000000..33bebb9 --- /dev/null +++ b/ui/gfx/gl/gl_share_group.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 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 UI_GFX_GL_GL_SHARE_GROUP_H_ +#define UI_GFX_GL_GL_SHARE_GROUP_H_ +#pragma once + +#include <set> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" + +namespace gfx { + +class GLContext; + +// A group of GL contexts that share an ID namespace. +class GLShareGroup : public base::RefCounted<GLShareGroup> { + public: + GLShareGroup(); + + // These two should only be called from the constructor and destructor of + // GLContext. + void AddContext(GLContext* context); + void RemoveContext(GLContext* context); + + // Returns a handle to any initialized context in the share group or NULL if + // there are no initialized contexts in the share group. + void* GetHandle(); + + private: + friend class base::RefCounted<GLShareGroup>; + ~GLShareGroup(); + + // References to GLContext are by raw pointer to avoid a reference count + // cycle. + typedef std::set<GLContext*> ContextSet; + ContextSet contexts_; + DISALLOW_COPY_AND_ASSIGN(GLShareGroup); +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_SHARE_GROUP_H_ diff --git a/ui/gfx/surface/accelerated_surface_mac.cc b/ui/gfx/surface/accelerated_surface_mac.cc index ce2f7a0..123e907 100644 --- a/ui/gfx/surface/accelerated_surface_mac.cc +++ b/ui/gfx/surface/accelerated_surface_mac.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" #include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface.h" #include "ui/gfx/rect.h" @@ -41,7 +42,10 @@ bool AcceleratedSurface::Initialize(gfx::GLContext* share_context, return false; } - gl_context_ = gfx::GLContext::CreateGLContext(share_context, + gfx::GLShareGroup* share_group = + share_context ? share_context->share_group() : NULL; + + gl_context_ = gfx::GLContext::CreateGLContext(share_group, gl_surface_.get()); if (!gl_context_.get()) { Destroy(); diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc index 25795a7..1f7e672 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -29,6 +29,7 @@ #include "gpu/GLES2/gles2_command_buffer.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "ui/gfx/gl/gl_share_group.h" #include "webkit/glue/gl_bindings_skia_cmd_buffer.h" using gpu::Buffer; @@ -526,6 +527,9 @@ bool GLInProcessContext::Initialize(bool onscreen, const char* allowed_extensions, const int32* attrib_list, const GURL& active_url) { + // Use one share group for all contexts. + static scoped_refptr<gfx::GLShareGroup> share_group(new gfx::GLShareGroup); + DCHECK(size.width() >= 0 && size.height() >= 0); // Ensure the gles2 library is initialized first in a thread safe way. @@ -585,7 +589,8 @@ bool GLInProcessContext::Initialize(bool onscreen, allowed_extensions, attribs, NULL, - 0)) { + 0, + share_group.get())) { LOG(ERROR) << "Could not initialize GpuScheduler."; command_buffer_.reset(); } @@ -600,7 +605,8 @@ bool GLInProcessContext::Initialize(bool onscreen, allowed_extensions, attribs, parent_scheduler, - parent_texture_id_)) { + parent_texture_id_, + share_group.get())) { LOG(ERROR) << "Could not initialize offscreen GpuScheduler."; command_buffer_.reset(); } diff --git a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc index 3ff4387..f01543a 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_impl.cc +++ b/webkit/gpu/webgraphicscontext3d_in_process_impl.cc @@ -110,7 +110,7 @@ bool WebGraphicsContext3DInProcessImpl::initialize( gfx::BindSkiaToInProcessGL(); render_directly_to_web_view_ = render_directly_to_web_view; - gfx::GLContext* share_context = 0; + gfx::GLShareGroup* share_group = 0; if (!render_directly_to_web_view) { // Pick up the compositor's context to share resources with. @@ -118,7 +118,7 @@ bool WebGraphicsContext3DInProcessImpl::initialize( if (view_context) { WebGraphicsContext3DInProcessImpl* contextImpl = static_cast<WebGraphicsContext3DInProcessImpl*>(view_context); - share_context = contextImpl->gl_context_.get(); + share_group = contextImpl->gl_context_->share_group(); } else { // The compositor's context didn't get created // successfully, so conceptually there is no way we can @@ -154,7 +154,7 @@ bool WebGraphicsContext3DInProcessImpl::initialize( return false; } - gl_context_ = gfx::GLContext::CreateGLContext(share_context, + gl_context_ = gfx::GLContext::CreateGLContext(share_group, gl_surface_.get()); if (!gl_context_.get()) { if (!is_gles2_) @@ -169,7 +169,7 @@ bool WebGraphicsContext3DInProcessImpl::initialize( // necessary. webView->mainFrame()->collectGarbage(); - gl_context_ = gfx::GLContext::CreateGLContext(share_context, + gl_context_ = gfx::GLContext::CreateGLContext(share_group, gl_surface_.get()); if (!gl_context_.get()) return false; |