Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1207)

Side by Side Diff: gpu/command_buffer/client/gl_in_process_context.cc

Issue 20017005: gpu: Refactor GpuMemoryBuffer framework for multi-process support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/client/gl_in_process_context.h" 5 #include "gpu/command_buffer/client/gl_in_process_context.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include <GLES2/gl2.h> 10 #include <GLES2/gl2.h>
11 #ifndef GL_GLEXT_PROTOTYPES 11 #ifndef GL_GLEXT_PROTOTYPES
12 #define GL_GLEXT_PROTOTYPES 1 12 #define GL_GLEXT_PROTOTYPES 1
13 #endif 13 #endif
14 #include <GLES2/gl2ext.h> 14 #include <GLES2/gl2ext.h>
15 #include <GLES2/gl2extchromium.h> 15 #include <GLES2/gl2extchromium.h>
16 16
17 #include "base/bind.h" 17 #include "base/bind.h"
18 #include "base/bind_helpers.h" 18 #include "base/bind_helpers.h"
19 #include "base/callback.h" 19 #include "base/callback.h"
20 #include "base/lazy_instance.h" 20 #include "base/lazy_instance.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/memory/scoped_ptr.h" 22 #include "base/memory/scoped_ptr.h"
23 #include "base/memory/weak_ptr.h" 23 #include "base/memory/weak_ptr.h"
24 #include "base/message_loop/message_loop.h" 24 #include "base/message_loop/message_loop.h"
25 #include "base/synchronization/lock.h" 25 #include "base/synchronization/lock.h"
26 #include "gpu/command_buffer/client/gles2_implementation.h" 26 #include "gpu/command_buffer/client/gles2_implementation.h"
27 #include "gpu/command_buffer/client/gpu_memory_buffer.h"
28 #include "gpu/command_buffer/client/image_factory.h"
29 #include "gpu/command_buffer/client/transfer_buffer.h" 27 #include "gpu/command_buffer/client/transfer_buffer.h"
30 #include "gpu/command_buffer/common/constants.h" 28 #include "gpu/command_buffer/common/constants.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/service/command_buffer_service.h" 29 #include "gpu/command_buffer/service/command_buffer_service.h"
33 #include "gpu/command_buffer/service/context_group.h" 30 #include "gpu/command_buffer/service/context_group.h"
34 #include "gpu/command_buffer/service/gl_context_virtual.h" 31 #include "gpu/command_buffer/service/gl_context_virtual.h"
35 #include "gpu/command_buffer/service/gpu_scheduler.h" 32 #include "gpu/command_buffer/service/gpu_scheduler.h"
36 #include "gpu/command_buffer/service/image_manager.h" 33 #include "gpu/command_buffer/service/image_manager.h"
37 #include "gpu/command_buffer/service/transfer_buffer_manager.h" 34 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
38 #include "ui/gfx/size.h" 35 #include "ui/gfx/size.h"
39 #include "ui/gl/gl_context.h" 36 #include "ui/gl/gl_context.h"
40 #include "ui/gl/gl_image.h" 37 #include "ui/gl/gl_image.h"
41 #include "ui/gl/gl_share_group.h" 38 #include "ui/gl/gl_share_group.h"
42 #include "ui/gl/gl_surface.h" 39 #include "ui/gl/gl_surface.h"
43 40
44 namespace gpu { 41 namespace gpu {
45 42
46 using gles2::ImageManager;
47
48 namespace { 43 namespace {
49 44
50 const int32 kCommandBufferSize = 1024 * 1024; 45 const int32 kCommandBufferSize = 1024 * 1024;
51 // TODO(kbr): make the transfer buffer size configurable via context 46 // TODO(kbr): make the transfer buffer size configurable via context
52 // creation attributes. 47 // creation attributes.
53 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 48 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
54 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 49 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
55 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 50 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
56 51
57 // In the normal command buffer implementation, all commands are passed over IPC 52 // In the normal command buffer implementation, all commands are passed over IPC
58 // to the gpu process where they are fed to the GLES2Decoder from a single 53 // to the gpu process where they are fed to the GLES2Decoder from a single
59 // thread. In layout tests, any thread could call this function. GLES2Decoder, 54 // thread. In layout tests, any thread could call this function. GLES2Decoder,
60 // and in particular the GL implementations behind it, are not generally 55 // and in particular the GL implementations behind it, are not generally
61 // threadsafe, so we guard entry points with a mutex. 56 // threadsafe, so we guard entry points with a mutex.
62 static base::LazyInstance<base::Lock> g_decoder_lock = 57 static base::LazyInstance<base::Lock> g_decoder_lock =
63 LAZY_INSTANCE_INITIALIZER; 58 LAZY_INSTANCE_INITIALIZER;
64 59
65 class GLInProcessContextImpl; 60 class GLInProcessContextImpl;
66 61
67 static base::LazyInstance< 62 static base::LazyInstance<
68 std::set<GLInProcessContextImpl*> > 63 std::set<GLInProcessContextImpl*> >
69 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER; 64 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
70 65
71 static bool g_use_virtualized_gl_context = false; 66 static bool g_use_virtualized_gl_context = false;
72 67
73 static GLInProcessContext::GpuMemoryBufferCreator* g_gpu_memory_buffer_creator = 68 static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL;
74 NULL;
75 69
76 // Also calls DetachFromThreadHack on all GLES2Decoders before the lock is 70 // Also calls DetachFromThreadHack on all GLES2Decoders before the lock is
77 // released to maintain the invariant that all decoders are unbound while the 71 // released to maintain the invariant that all decoders are unbound while the
78 // lock is not held. This is to workaround DumpRenderTree using WGC3DIPCBI with 72 // lock is not held. This is to workaround DumpRenderTree using WGC3DIPCBI with
79 // shared resources on different threads. 73 // shared resources on different threads.
80 // Remove this as part of crbug.com/234964. 74 // Remove this as part of crbug.com/234964.
81 class AutoLockAndDecoderDetachThread { 75 class AutoLockAndDecoderDetachThread {
82 public: 76 public:
83 AutoLockAndDecoderDetachThread( 77 AutoLockAndDecoderDetachThread(
84 base::Lock& lock, 78 base::Lock& lock,
85 const std::set<GLInProcessContextImpl*>& contexts); 79 const std::set<GLInProcessContextImpl*>& contexts);
86 ~AutoLockAndDecoderDetachThread(); 80 ~AutoLockAndDecoderDetachThread();
87 81
88 private: 82 private:
89 base::AutoLock auto_lock_; 83 base::AutoLock auto_lock_;
90 const std::set<GLInProcessContextImpl*>& contexts_; 84 const std::set<GLInProcessContextImpl*>& contexts_;
91 }; 85 };
92 86
93 class GLInProcessContextImpl 87 class GLInProcessContextImpl
94 : public GLInProcessContext, 88 : public GLInProcessContext,
95 public gles2::ImageFactory,
96 public base::SupportsWeakPtr<GLInProcessContextImpl> { 89 public base::SupportsWeakPtr<GLInProcessContextImpl> {
97 public: 90 public:
98 explicit GLInProcessContextImpl(bool share_resources); 91 explicit GLInProcessContextImpl(bool share_resources);
99 virtual ~GLInProcessContextImpl(); 92 virtual ~GLInProcessContextImpl();
100 93
101 bool Initialize(bool is_offscreen, 94 bool Initialize(bool is_offscreen,
102 gfx::AcceleratedWidget window, 95 gfx::AcceleratedWidget window,
103 const gfx::Size& size, 96 const gfx::Size& size,
104 const char* allowed_extensions, 97 const char* allowed_extensions,
105 const int32* attrib_list, 98 const int32* attrib_list,
106 gfx::GpuPreference gpu_preference, 99 gfx::GpuPreference gpu_preference,
107 const base::Closure& context_lost_callback); 100 const base::Closure& context_lost_callback);
108 101
109 // GLInProcessContext implementation: 102 // GLInProcessContext implementation:
110 virtual void SignalSyncPoint(unsigned sync_point, 103 virtual void SignalSyncPoint(unsigned sync_point,
111 const base::Closure& callback) OVERRIDE; 104 const base::Closure& callback) OVERRIDE;
112 virtual void SignalQuery(unsigned query, const base::Closure& callback) 105 virtual void SignalQuery(unsigned query, const base::Closure& callback)
113 OVERRIDE; 106 OVERRIDE;
114 virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE; 107 virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE;
115 108
116 // ImageFactory implementation:
117 virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
118 int width, int height, GLenum internalformat,
119 unsigned* image_id) OVERRIDE;
120 virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE;
121
122 // Other methods: 109 // Other methods:
123 gles2::GLES2Decoder* GetDecoder(); 110 gles2::GLES2Decoder* GetDecoder();
124 bool GetBufferChanged(int32 transfer_buffer_id); 111 bool GetBufferChanged(int32 transfer_buffer_id);
125 void PumpCommands(); 112 void PumpCommands();
126 void OnResizeView(gfx::Size size, float scale_factor); 113 void OnResizeView(gfx::Size size, float scale_factor);
127 void OnContextLost(); 114 void OnContextLost();
128 115
129 private: 116 private:
130 void Destroy(); 117 void Destroy();
131 bool IsCommandBufferContextLost(); 118 bool IsCommandBufferContextLost();
132 void PollQueryCallbacks(); 119 void PollQueryCallbacks();
133 void CallQueryCallback(size_t index); 120 void CallQueryCallback(size_t index);
134 bool MakeCurrent(); 121 bool MakeCurrent();
135 122
136 gles2::ImageManager* GetImageManager();
137
138 base::Closure context_lost_callback_; 123 base::Closure context_lost_callback_;
139 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; 124 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
125 scoped_refptr<gles2::ImageManager> image_manager_;
140 scoped_ptr<CommandBuffer> command_buffer_; 126 scoped_ptr<CommandBuffer> command_buffer_;
141 scoped_ptr<GpuScheduler> gpu_scheduler_; 127 scoped_ptr<GpuScheduler> gpu_scheduler_;
142 scoped_ptr<gles2::GLES2Decoder> decoder_; 128 scoped_ptr<gles2::GLES2Decoder> decoder_;
143 scoped_refptr<gfx::GLContext> context_; 129 scoped_refptr<gfx::GLContext> context_;
144 scoped_refptr<gfx::GLSurface> surface_; 130 scoped_refptr<gfx::GLSurface> surface_;
145 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; 131 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_;
146 scoped_ptr<TransferBuffer> transfer_buffer_; 132 scoped_ptr<TransferBuffer> transfer_buffer_;
147 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_; 133 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_;
148 bool share_resources_; 134 bool share_resources_;
149 bool context_lost_; 135 bool context_lost_;
(...skipping 17 matching lines...) Expand all
167 if (context->GetDecoder()) 153 if (context->GetDecoder())
168 context->GetDecoder()->DetachFromThreadHack(); 154 context->GetDecoder()->DetachFromThreadHack();
169 } 155 }
170 156
171 AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() { 157 AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() {
172 std::for_each(contexts_.begin(), 158 std::for_each(contexts_.begin(),
173 contexts_.end(), 159 contexts_.end(),
174 &DetachThread); 160 &DetachThread);
175 } 161 }
176 162
177 scoped_ptr<GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer(
178 int width, int height, GLenum internalformat, unsigned int* image_id) {
179 // We're taking the lock here because we're accessing the ContextGroup's
180 // shared IdManager.
181 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
182 g_all_shared_contexts.Get());
183 // For Android WebView we assume the |internalformat| will always be
184 // GL_RGBA8_OES.
185 DCHECK_EQ(static_cast<GLenum>(GL_RGBA8_OES), internalformat);
186 scoped_ptr<GpuMemoryBuffer> buffer =
187 g_gpu_memory_buffer_creator(width, height);
188
189 if (buffer.get() == NULL)
190 return buffer.Pass();
191
192 scoped_refptr<gfx::GLImage> gl_image =
193 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(),
194 gfx::Size(width, height));
195 *image_id = decoder_->GetContextGroup()
196 ->GetIdAllocator(gles2::id_namespaces::kImages)->AllocateID();
197 GetImageManager()->AddImage(gl_image.get(), *image_id);
198 return buffer.Pass();
199 }
200
201 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) {
202 // We're taking the lock here because we're accessing the ContextGroup's
203 // shared ImageManager.
204 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
205 g_all_shared_contexts.Get());
206 GetImageManager()->RemoveImage(image_id);
207 decoder_->GetContextGroup()->GetIdAllocator(gles2::id_namespaces::kImages)
208 ->FreeID(image_id);
209 }
210
211 GLInProcessContextImpl::GLInProcessContextImpl(bool share_resources) 163 GLInProcessContextImpl::GLInProcessContextImpl(bool share_resources)
212 : share_resources_(share_resources), 164 : share_resources_(share_resources),
213 context_lost_(false) { 165 context_lost_(false) {
214 } 166 }
215 167
216 GLInProcessContextImpl::~GLInProcessContextImpl() { 168 GLInProcessContextImpl::~GLInProcessContextImpl() {
217 Destroy(); 169 Destroy();
218 } 170 }
219 171
220 bool GLInProcessContextImpl::MakeCurrent() { 172 bool GLInProcessContextImpl::MakeCurrent() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 223
272 void GLInProcessContextImpl::OnResizeView(gfx::Size size, float scale_factor) { 224 void GLInProcessContextImpl::OnResizeView(gfx::Size size, float scale_factor) {
273 DCHECK(!surface_->IsOffscreen()); 225 DCHECK(!surface_->IsOffscreen());
274 surface_->Resize(size); 226 surface_->Resize(size);
275 } 227 }
276 228
277 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { 229 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() {
278 return gles2_implementation_.get(); 230 return gles2_implementation_.get();
279 } 231 }
280 232
281 gles2::ImageManager* GLInProcessContextImpl::GetImageManager() {
282 return decoder_->GetContextGroup()->image_manager();
283 }
284
285 bool GLInProcessContextImpl::Initialize( 233 bool GLInProcessContextImpl::Initialize(
286 bool is_offscreen, 234 bool is_offscreen,
287 gfx::AcceleratedWidget window, 235 gfx::AcceleratedWidget window,
288 const gfx::Size& size, 236 const gfx::Size& size,
289 const char* allowed_extensions, 237 const char* allowed_extensions,
290 const int32* attrib_list, 238 const int32* attrib_list,
291 gfx::GpuPreference gpu_preference, 239 gfx::GpuPreference gpu_preference,
292 const base::Closure& context_lost_callback) { 240 const base::Closure& context_lost_callback) {
293 // Use one share group for all contexts. 241 // Use one share group for all contexts.
294 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, 242 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
(...skipping 27 matching lines...) Expand all
322 break; 270 break;
323 } 271 }
324 } 272 }
325 273
326 { 274 {
327 TransferBufferManager* manager = new TransferBufferManager(); 275 TransferBufferManager* manager = new TransferBufferManager();
328 transfer_buffer_manager_.reset(manager); 276 transfer_buffer_manager_.reset(manager);
329 manager->Initialize(); 277 manager->Initialize();
330 } 278 }
331 279
280 image_manager_ = new gles2::ImageManager();
281
332 scoped_ptr<CommandBufferService> command_buffer( 282 scoped_ptr<CommandBufferService> command_buffer(
333 new CommandBufferService(transfer_buffer_manager_.get())); 283 new CommandBufferService(transfer_buffer_manager_.get(),
284 image_manager_.get(),
285 g_gpu_memory_buffer_factory));
334 command_buffer->SetPutOffsetChangeCallback(base::Bind( 286 command_buffer->SetPutOffsetChangeCallback(base::Bind(
335 &GLInProcessContextImpl::PumpCommands, base::Unretained(this))); 287 &GLInProcessContextImpl::PumpCommands, base::Unretained(this)));
336 command_buffer->SetGetBufferChangeCallback(base::Bind( 288 command_buffer->SetGetBufferChangeCallback(base::Bind(
337 &GLInProcessContextImpl::GetBufferChanged, base::Unretained(this))); 289 &GLInProcessContextImpl::GetBufferChanged, base::Unretained(this)));
338 command_buffer->SetParseErrorCallback(base::Bind( 290 command_buffer->SetParseErrorCallback(base::Bind(
339 &GLInProcessContextImpl::OnContextLost, base::Unretained(this))); 291 &GLInProcessContextImpl::OnContextLost, base::Unretained(this)));
340 292
341 command_buffer_ = command_buffer.Pass(); 293 command_buffer_ = command_buffer.Pass();
342 if (!command_buffer_->Initialize()) { 294 if (!command_buffer_->Initialize()) {
343 LOG(ERROR) << "Could not initialize command buffer."; 295 LOG(ERROR) << "Could not initialize command buffer.";
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 403
452 // Create a transfer buffer. 404 // Create a transfer buffer.
453 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 405 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
454 406
455 // Create the object exposing the OpenGL API. 407 // Create the object exposing the OpenGL API.
456 gles2_implementation_.reset(new gles2::GLES2Implementation( 408 gles2_implementation_.reset(new gles2::GLES2Implementation(
457 gles2_helper_.get(), 409 gles2_helper_.get(),
458 context_group ? context_group->GetImplementation()->share_group() : NULL, 410 context_group ? context_group->GetImplementation()->share_group() : NULL,
459 transfer_buffer_.get(), 411 transfer_buffer_.get(),
460 true, 412 true,
461 false, 413 false));
462 this));
463 414
464 if (!gles2_implementation_->Initialize( 415 if (!gles2_implementation_->Initialize(
465 kStartTransferBufferSize, 416 kStartTransferBufferSize,
466 kMinTransferBufferSize, 417 kMinTransferBufferSize,
467 kMaxTransferBufferSize)) { 418 kMaxTransferBufferSize)) {
468 return false; 419 return false;
469 } 420 }
470 421
471 if (share_resources_) { 422 if (share_resources_) {
472 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), 423 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 allowed_extensions, 538 allowed_extensions,
588 attrib_list, 539 attrib_list,
589 gpu_preference, 540 gpu_preference,
590 callback)) 541 callback))
591 return NULL; 542 return NULL;
592 543
593 return context.release(); 544 return context.release();
594 } 545 }
595 546
596 // static 547 // static
597 void GLInProcessContext::SetGpuMemoryBufferCreator( 548 void GLInProcessContext::SetGpuMemoryBufferFactory(
598 GpuMemoryBufferCreator* creator) { 549 GpuMemoryBufferFactory* factory) {
599 g_gpu_memory_buffer_creator = creator; 550 #if !defined(NDEBUG)
551 {
552 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
553 g_all_shared_contexts.Get());
554 DCHECK(g_all_shared_contexts.Get().empty());
555 }
556 #endif // !defined(NDEBUG)
557 g_gpu_memory_buffer_factory = factory;
600 } 558 }
601 559
602 // static 560 // static
603 void GLInProcessContext::EnableVirtualizedContext() { 561 void GLInProcessContext::EnableVirtualizedContext() {
604 #if !defined(NDEBUG) 562 #if !defined(NDEBUG)
605 { 563 {
606 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), 564 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
607 g_all_shared_contexts.Get()); 565 g_all_shared_contexts.Get());
608 DCHECK(g_all_shared_contexts.Get().empty()); 566 DCHECK(g_all_shared_contexts.Get().empty());
609 } 567 }
610 #endif // !defined(NDEBUG) 568 #endif // !defined(NDEBUG)
611 g_use_virtualized_gl_context = true; 569 g_use_virtualized_gl_context = true;
612 } 570 }
613 571
614 } // namespace gpu 572 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698