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

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

Issue 19522006: GLInProcessContext: support async flushes and dedicated GPU thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 <set>
7 #include <utility> 8 #include <utility>
8 #include <vector> 9 #include <vector>
9 10
10 #include <GLES2/gl2.h> 11 #include <GLES2/gl2.h>
11 #ifndef GL_GLEXT_PROTOTYPES 12 #ifndef GL_GLEXT_PROTOTYPES
12 #define GL_GLEXT_PROTOTYPES 1 13 #define GL_GLEXT_PROTOTYPES 1
13 #endif 14 #endif
14 #include <GLES2/gl2ext.h> 15 #include <GLES2/gl2ext.h>
15 #include <GLES2/gl2extchromium.h> 16 #include <GLES2/gl2extchromium.h>
16 17
17 #include "base/bind.h" 18 #include "base/bind.h"
18 #include "base/bind_helpers.h" 19 #include "base/bind_helpers.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"
26 #include "gpu/command_buffer/client/gles2_implementation.h" 25 #include "gpu/command_buffer/client/gles2_implementation.h"
27 #include "gpu/command_buffer/client/gpu_memory_buffer.h" 26 #include "gpu/command_buffer/client/gpu_memory_buffer.h"
28 #include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" 27 #include "gpu/command_buffer/client/gpu_memory_buffer_factory.h"
29 #include "gpu/command_buffer/client/image_factory.h" 28 #include "gpu/command_buffer/client/image_factory.h"
30 #include "gpu/command_buffer/client/transfer_buffer.h" 29 #include "gpu/command_buffer/client/transfer_buffer.h"
30 #include "gpu/command_buffer/common/command_buffer.h"
31 #include "gpu/command_buffer/common/constants.h" 31 #include "gpu/command_buffer/common/constants.h"
32 #include "gpu/command_buffer/common/id_allocator.h" 32 #include "gpu/command_buffer/service/in_process_command_buffer.h"
33 #include "gpu/command_buffer/service/command_buffer_service.h"
34 #include "gpu/command_buffer/service/context_group.h"
35 #include "gpu/command_buffer/service/gl_context_virtual.h"
36 #include "gpu/command_buffer/service/gpu_scheduler.h"
37 #include "gpu/command_buffer/service/image_manager.h"
38 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
39 #include "ui/gfx/size.h" 33 #include "ui/gfx/size.h"
40 #include "ui/gl/gl_context.h"
41 #include "ui/gl/gl_image.h" 34 #include "ui/gl/gl_image.h"
42 #include "ui/gl/gl_share_group.h"
43 #include "ui/gl/gl_surface.h"
44 35
45 namespace gpu { 36 namespace gpu {
46 37
47 using gles2::ImageManager;
48
49 namespace { 38 namespace {
50 39
51 const int32 kCommandBufferSize = 1024 * 1024; 40 const int32 kCommandBufferSize = 1024 * 1024;
52 // TODO(kbr): make the transfer buffer size configurable via context 41 // TODO(kbr): make the transfer buffer size configurable via context
53 // creation attributes. 42 // creation attributes.
54 const size_t kStartTransferBufferSize = 4 * 1024 * 1024; 43 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
55 const size_t kMinTransferBufferSize = 1 * 256 * 1024; 44 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
56 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; 45 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
57 46
58 // In the normal command buffer implementation, all commands are passed over IPC
59 // to the gpu process where they are fed to the GLES2Decoder from a single
60 // thread. In layout tests, any thread could call this function. GLES2Decoder,
61 // and in particular the GL implementations behind it, are not generally
62 // threadsafe, so we guard entry points with a mutex.
63 static base::LazyInstance<base::Lock> g_decoder_lock =
64 LAZY_INSTANCE_INITIALIZER;
65
66 class GLInProcessContextImpl;
67
68 static base::LazyInstance<
69 std::set<GLInProcessContextImpl*> >
70 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
71
72 static bool g_use_virtualized_gl_context = false;
73
74 static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; 47 static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL;
75 48
76 // Also calls DetachFromThreadHack on all GLES2Decoders before the lock is
77 // 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
79 // shared resources on different threads.
80 // Remove this as part of crbug.com/234964.
81 class AutoLockAndDecoderDetachThread {
82 public:
83 AutoLockAndDecoderDetachThread(
84 base::Lock& lock,
85 const std::set<GLInProcessContextImpl*>& contexts);
86 ~AutoLockAndDecoderDetachThread();
87
88 private:
89 base::AutoLock auto_lock_;
90 const std::set<GLInProcessContextImpl*>& contexts_;
91 };
92
93 size_t SharedContextCount() {
94 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
95 g_all_shared_contexts.Get());
96 return g_all_shared_contexts.Get().size();
97 }
98
99 class GLInProcessContextImpl 49 class GLInProcessContextImpl
100 : public GLInProcessContext, 50 : public GLInProcessContext,
101 public gles2::ImageFactory, 51 public gles2::ImageFactory,
102 public base::SupportsWeakPtr<GLInProcessContextImpl> { 52 public base::SupportsWeakPtr<GLInProcessContextImpl> {
103 public: 53 public:
104 explicit GLInProcessContextImpl(bool share_resources); 54 explicit GLInProcessContextImpl();
105 virtual ~GLInProcessContextImpl(); 55 virtual ~GLInProcessContextImpl();
106 56
107 bool Initialize(bool is_offscreen, 57 bool Initialize(bool is_offscreen,
58 bool share_resources,
108 gfx::AcceleratedWidget window, 59 gfx::AcceleratedWidget window,
109 const gfx::Size& size, 60 const gfx::Size& size,
110 const char* allowed_extensions, 61 const char* allowed_extensions,
111 const int32* attrib_list, 62 const int32* attrib_list,
112 gfx::GpuPreference gpu_preference, 63 gfx::GpuPreference gpu_preference,
113 const base::Closure& context_lost_callback); 64 const base::Closure& context_lost_callback);
114 65
115 // GLInProcessContext implementation: 66 // GLInProcessContext implementation:
116 virtual void SignalSyncPoint(unsigned sync_point, 67 virtual void SignalSyncPoint(unsigned sync_point,
117 const base::Closure& callback) OVERRIDE; 68 const base::Closure& callback) OVERRIDE;
118 virtual void SignalQuery(unsigned query, const base::Closure& callback) 69 virtual void SignalQuery(unsigned query, const base::Closure& callback)
119 OVERRIDE; 70 OVERRIDE;
120 virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE; 71 virtual gles2::GLES2Implementation* GetImplementation() OVERRIDE;
121 72
122 // ImageFactory implementation: 73 // ImageFactory implementation:
123 virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer( 74 virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer(
124 int width, int height, GLenum internalformat, 75 int width, int height, GLenum internalformat,
125 unsigned* image_id) OVERRIDE; 76 unsigned* image_id) OVERRIDE;
126 virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE; 77 virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE;
127 78
128 // Other methods:
129 gles2::GLES2Decoder* GetDecoder();
130 bool GetBufferChanged(int32 transfer_buffer_id);
131 void PumpCommands();
132 void OnResizeView(gfx::Size size, float scale_factor);
133 void OnContextLost();
134
135 private: 79 private:
136 void Destroy(); 80 void Destroy();
137 bool IsCommandBufferContextLost();
138 void PollQueryCallbacks(); 81 void PollQueryCallbacks();
139 void CallQueryCallback(size_t index); 82 void CallQueryCallback(size_t index);
140 bool MakeCurrent(); 83 void OnContextLost(const base::Closure& callback);
84 void OnSignalSyncPoint(const base::Closure& callback);
141 85
142 gles2::ImageManager* GetImageManager();
143
144 base::Closure context_lost_callback_;
145 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
146 scoped_ptr<CommandBuffer> command_buffer_;
147 scoped_ptr<GpuScheduler> gpu_scheduler_;
148 scoped_ptr<gles2::GLES2Decoder> decoder_;
149 scoped_refptr<gfx::GLContext> context_;
150 scoped_refptr<gfx::GLSurface> surface_;
151 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; 86 scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_;
152 scoped_ptr<TransferBuffer> transfer_buffer_; 87 scoped_ptr<TransferBuffer> transfer_buffer_;
153 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_; 88 scoped_ptr<gles2::GLES2Implementation> gles2_implementation_;
154 bool share_resources_; 89 scoped_ptr<InProcessCommandBuffer> command_buffer_;
155 bool context_lost_;
156 90
157 typedef std::pair<unsigned, base::Closure> QueryCallback; 91 typedef std::pair<unsigned, base::Closure> QueryCallback;
158 std::vector<QueryCallback> query_callbacks_; 92 std::vector<QueryCallback> query_callbacks_;
159 93
160 std::vector<base::Closure> signal_sync_point_callbacks_; 94 unsigned int share_group_id_;
95 bool context_lost_;
161 96
162 DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl); 97 DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl);
163 }; 98 };
164 99
165 AutoLockAndDecoderDetachThread::AutoLockAndDecoderDetachThread( 100 base::LazyInstance<base::Lock> g_all_shared_contexts_lock =
166 base::Lock& lock, 101 LAZY_INSTANCE_INITIALIZER;
167 const std::set<GLInProcessContextImpl*>& contexts) 102 base::LazyInstance<std::set<GLInProcessContextImpl*> > g_all_shared_contexts =
168 : auto_lock_(lock), 103 LAZY_INSTANCE_INITIALIZER;
169 contexts_(contexts) {
170 }
171 104
172 void DetachThread(GLInProcessContextImpl* context) { 105 size_t SharedContextCount() {
173 if (context->GetDecoder()) 106 base::AutoLock lock(g_all_shared_contexts_lock.Get());
174 context->GetDecoder()->DetachFromThreadHack(); 107 return g_all_shared_contexts.Get().size();
175 }
176
177 AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() {
178 std::for_each(contexts_.begin(),
179 contexts_.end(),
180 &DetachThread);
181 } 108 }
182 109
183 scoped_ptr<GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer( 110 scoped_ptr<GpuMemoryBuffer> GLInProcessContextImpl::CreateGpuMemoryBuffer(
184 int width, int height, GLenum internalformat, unsigned int* image_id) { 111 int width, int height, GLenum internalformat, unsigned int* image_id) {
185 // We're taking the lock here because we're accessing the ContextGroup's
186 // shared IdManager.
187 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
188 g_all_shared_contexts.Get());
189 scoped_ptr<GpuMemoryBuffer> buffer( 112 scoped_ptr<GpuMemoryBuffer> buffer(
190 g_gpu_memory_buffer_factory->CreateGpuMemoryBuffer(width, 113 g_gpu_memory_buffer_factory->CreateGpuMemoryBuffer(width,
191 height, 114 height,
192 internalformat)); 115 internalformat));
193 if (!buffer) 116 if (!buffer)
194 return scoped_ptr<GpuMemoryBuffer>(); 117 return scoped_ptr<GpuMemoryBuffer>();
195 118
196 scoped_refptr<gfx::GLImage> gl_image = 119 *image_id = command_buffer_->CreateImageForGpuMemoryBuffer(
197 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(), 120 buffer->GetNativeBuffer(), gfx::Size(width, height));
198 gfx::Size(width, height));
199 *image_id = decoder_->GetContextGroup()
200 ->GetIdAllocator(gles2::id_namespaces::kImages)->AllocateID();
201 GetImageManager()->AddImage(gl_image.get(), *image_id);
202 return buffer.Pass(); 121 return buffer.Pass();
203 } 122 }
204 123
205 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) { 124 void GLInProcessContextImpl::DeleteGpuMemoryBuffer(unsigned int image_id) {
206 // We're taking the lock here because we're accessing the ContextGroup's 125 command_buffer_->RemoveImage(image_id);
207 // shared ImageManager.
208 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
209 g_all_shared_contexts.Get());
210 GetImageManager()->RemoveImage(image_id);
211 decoder_->GetContextGroup()->GetIdAllocator(gles2::id_namespaces::kImages)
212 ->FreeID(image_id);
213 } 126 }
214 127
215 GLInProcessContextImpl::GLInProcessContextImpl(bool share_resources) 128 GLInProcessContextImpl::GLInProcessContextImpl()
216 : share_resources_(share_resources), 129 : share_group_id_(0), context_lost_(false) {}
217 context_lost_(false) {
218 }
219 130
220 GLInProcessContextImpl::~GLInProcessContextImpl() { 131 GLInProcessContextImpl::~GLInProcessContextImpl() {
132 {
133 base::AutoLock lock(g_all_shared_contexts_lock.Get());
134 g_all_shared_contexts.Get().erase(this);
135 }
221 Destroy(); 136 Destroy();
222 } 137 }
223 138
224 bool GLInProcessContextImpl::MakeCurrent() {
225 if (decoder_->MakeCurrent())
226 return true;
227 DLOG(ERROR) << "Context lost because MakeCurrent failed.";
228 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
229 command_buffer_->SetParseError(gpu::error::kLostContext);
230 return false;
231 }
232
233 void GLInProcessContextImpl::PumpCommands() {
234 {
235 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
236 g_all_shared_contexts.Get());
237 if (!MakeCurrent())
238 return;
239 gpu_scheduler_->PutChanged();
240 CommandBuffer::State state = command_buffer_->GetState();
241 DCHECK((!error::IsError(state.error) && !context_lost_) ||
242 (error::IsError(state.error) && context_lost_));
243 }
244
245 if (!context_lost_ && signal_sync_point_callbacks_.size()) {
246 for (size_t n = 0; n < signal_sync_point_callbacks_.size(); n++) {
247 base::MessageLoop::current()->PostTask(FROM_HERE,
248 signal_sync_point_callbacks_[n]);
249 }
250 }
251 signal_sync_point_callbacks_.clear();
252 }
253
254 bool GLInProcessContextImpl::GetBufferChanged(int32 transfer_buffer_id) {
255 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
256 }
257
258 void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point, 139 void GLInProcessContextImpl::SignalSyncPoint(unsigned sync_point,
259 const base::Closure& callback) { 140 const base::Closure& callback) {
260 DCHECK(!callback.is_null()); 141 DCHECK(!callback.is_null());
261 signal_sync_point_callbacks_.push_back(callback); 142 base::Closure wrapped_callback = base::Bind(
262 } 143 &GLInProcessContextImpl::OnSignalSyncPoint, AsWeakPtr(), callback);
263 144 command_buffer_->SignalSyncPoint(sync_point, wrapped_callback);
264 bool GLInProcessContextImpl::IsCommandBufferContextLost() {
265 if (context_lost_ || !command_buffer_) {
266 return true;
267 }
268 CommandBuffer::State state = command_buffer_->GetState();
269 return error::IsError(state.error);
270 }
271
272 gles2::GLES2Decoder* GLInProcessContextImpl::GetDecoder() {
273 return decoder_.get();
274 }
275
276 void GLInProcessContextImpl::OnResizeView(gfx::Size size, float scale_factor) {
277 DCHECK(!surface_->IsOffscreen());
278 surface_->Resize(size);
279 } 145 }
280 146
281 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { 147 gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() {
282 return gles2_implementation_.get(); 148 return gles2_implementation_.get();
283 } 149 }
284 150
285 gles2::ImageManager* GLInProcessContextImpl::GetImageManager() { 151 void GLInProcessContextImpl::OnContextLost(const base::Closure& callback) {
286 return decoder_->GetContextGroup()->image_manager(); 152 context_lost_ = true;
153 callback.Run();
154 }
155
156 void GLInProcessContextImpl::OnSignalSyncPoint(const base::Closure& callback) {
157 // TODO: Should it always trigger callbacks?
158 if (!context_lost_)
159 callback.Run();
287 } 160 }
288 161
289 bool GLInProcessContextImpl::Initialize( 162 bool GLInProcessContextImpl::Initialize(
290 bool is_offscreen, 163 bool is_offscreen,
164 bool share_resources,
291 gfx::AcceleratedWidget window, 165 gfx::AcceleratedWidget window,
292 const gfx::Size& size, 166 const gfx::Size& size,
293 const char* allowed_extensions, 167 const char* allowed_extensions,
294 const int32* attrib_list, 168 const int32* attrib_list,
295 gfx::GpuPreference gpu_preference, 169 gfx::GpuPreference gpu_preference,
296 const base::Closure& context_lost_callback) { 170 const base::Closure& context_lost_callback) {
297 // Use one share group for all contexts.
298 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
299 (new gfx::GLShareGroup));
300
301 DCHECK(size.width() >= 0 && size.height() >= 0); 171 DCHECK(size.width() >= 0 && size.height() >= 0);
302 172
303 std::vector<int32> attribs; 173 std::vector<int32> attribs;
304 while (attrib_list) { 174 while (attrib_list) {
305 int32 attrib = *attrib_list++; 175 int32 attrib = *attrib_list++;
306 switch (attrib) { 176 switch (attrib) {
307 // Known attributes 177 // Known attributes
308 case ALPHA_SIZE: 178 case ALPHA_SIZE:
309 case BLUE_SIZE: 179 case BLUE_SIZE:
310 case GREEN_SIZE: 180 case GREEN_SIZE:
311 case RED_SIZE: 181 case RED_SIZE:
312 case DEPTH_SIZE: 182 case DEPTH_SIZE:
313 case STENCIL_SIZE: 183 case STENCIL_SIZE:
314 case SAMPLES: 184 case SAMPLES:
315 case SAMPLE_BUFFERS: 185 case SAMPLE_BUFFERS:
316 attribs.push_back(attrib); 186 attribs.push_back(attrib);
317 attribs.push_back(*attrib_list++); 187 attribs.push_back(*attrib_list++);
318 break; 188 break;
319 case NONE: 189 case NONE:
320 attribs.push_back(attrib); 190 attribs.push_back(attrib);
321 attrib_list = NULL; 191 attrib_list = NULL;
322 break; 192 break;
323 default: 193 default:
324 attribs.push_back(NONE); 194 attribs.push_back(NONE);
325 attrib_list = NULL; 195 attrib_list = NULL;
326 break; 196 break;
327 } 197 }
328 } 198 }
329 199
330 { 200 base::Closure wrapped_callback =
331 TransferBufferManager* manager = new TransferBufferManager(); 201 base::Bind(&GLInProcessContextImpl::OnContextLost,
332 transfer_buffer_manager_.reset(manager); 202 AsWeakPtr(),
333 manager->Initialize(); 203 context_lost_callback);
204 command_buffer_.reset(new InProcessCommandBuffer());
205
206 scoped_ptr<base::AutoLock> scoped_shared_context_lock;
207 scoped_refptr<gles2::ShareGroup> share_group;
208 if (share_resources) {
209 scoped_shared_context_lock.reset(
210 new base::AutoLock(g_all_shared_contexts_lock.Get()));
211 for (std::set<GLInProcessContextImpl*>::const_iterator it =
212 g_all_shared_contexts.Get().begin();
213 it != g_all_shared_contexts.Get().end();
214 it++) {
215 const GLInProcessContextImpl* context = *it;
216 if (!context->context_lost_) {
217 share_group = context->gles2_implementation_->share_group();
218 DCHECK(share_group);
219 share_group_id_ = context->share_group_id_;
220 break;
221 }
222 share_group_id_ = std::max(share_group_id_, context->share_group_id_);
223 }
224 if (!share_group && !++share_group_id_)
225 ++share_group_id_;
334 } 226 }
335 227 if (!command_buffer_->Initialize(is_offscreen,
336 scoped_ptr<CommandBufferService> command_buffer( 228 share_resources,
337 new CommandBufferService(transfer_buffer_manager_.get())); 229 window,
338 command_buffer->SetPutOffsetChangeCallback(base::Bind( 230 size,
339 &GLInProcessContextImpl::PumpCommands, base::Unretained(this))); 231 allowed_extensions,
340 command_buffer->SetGetBufferChangeCallback(base::Bind( 232 attribs,
341 &GLInProcessContextImpl::GetBufferChanged, base::Unretained(this))); 233 gpu_preference,
342 command_buffer->SetParseErrorCallback(base::Bind( 234 wrapped_callback,
343 &GLInProcessContextImpl::OnContextLost, base::Unretained(this))); 235 share_group_id_)) {
344 236 LOG(INFO) << "Failed to initialize InProcessCommmandBuffer";
345 command_buffer_ = command_buffer.Pass();
346 if (!command_buffer_->Initialize()) {
347 LOG(ERROR) << "Could not initialize command buffer.";
348 Destroy();
349 return false; 237 return false;
350 } 238 }
351 239
352 GLInProcessContextImpl* context_group = NULL;
353
354 {
355 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
356 g_all_shared_contexts.Get());
357 if (share_resources_ && !g_all_shared_contexts.Get().empty()) {
358 for (std::set<GLInProcessContextImpl*>::iterator it =
359 g_all_shared_contexts.Get().begin();
360 it != g_all_shared_contexts.Get().end();
361 ++it) {
362 if (!(*it)->IsCommandBufferContextLost()) {
363 context_group = *it;
364 break;
365 }
366 }
367 if (!context_group)
368 share_group = new gfx::GLShareGroup;
369 }
370
371 // TODO(gman): This needs to be true if this is Pepper.
372 bool bind_generates_resource = false;
373 decoder_.reset(gles2::GLES2Decoder::Create(
374 context_group ? context_group->decoder_->GetContextGroup()
375 : new gles2::ContextGroup(
376 NULL, NULL, NULL, NULL, bind_generates_resource)));
377
378 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
379 decoder_.get(),
380 decoder_.get()));
381
382 decoder_->set_engine(gpu_scheduler_.get());
383
384 if (is_offscreen)
385 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
386 else
387 surface_ = gfx::GLSurface::CreateViewGLSurface(window);
388
389 if (!surface_.get()) {
390 LOG(ERROR) << "Could not create GLSurface.";
391 Destroy();
392 return false;
393 }
394
395 if (g_use_virtualized_gl_context) {
396 context_ = share_group->GetSharedContext();
397 if (!context_.get()) {
398 context_ = gfx::GLContext::CreateGLContext(
399 share_group.get(), surface_.get(), gpu_preference);
400 share_group->SetSharedContext(context_.get());
401 }
402
403 context_ = new GLContextVirtual(
404 share_group.get(), context_.get(), decoder_->AsWeakPtr());
405 if (context_->Initialize(surface_.get(), gpu_preference)) {
406 VLOG(1) << "Created virtual GL context.";
407 } else {
408 context_ = NULL;
409 }
410 } else {
411 context_ = gfx::GLContext::CreateGLContext(share_group.get(),
412 surface_.get(),
413 gpu_preference);
414 }
415
416 if (!context_.get()) {
417 LOG(ERROR) << "Could not create GLContext.";
418 Destroy();
419 return false;
420 }
421
422 if (!context_->MakeCurrent(surface_.get())) {
423 LOG(ERROR) << "Could not make context current.";
424 Destroy();
425 return false;
426 }
427
428 gles2::DisallowedFeatures disallowed_features;
429 disallowed_features.swap_buffer_complete_callback = true;
430 disallowed_features.gpu_memory_manager = true;
431 if (!decoder_->Initialize(surface_,
432 context_,
433 is_offscreen,
434 size,
435 disallowed_features,
436 allowed_extensions,
437 attribs)) {
438 LOG(ERROR) << "Could not initialize decoder.";
439 Destroy();
440 return false;
441 }
442
443 if (!is_offscreen) {
444 decoder_->SetResizeCallback(base::Bind(
445 &GLInProcessContextImpl::OnResizeView, base::Unretained(this)));
446 }
447 }
448
449 // Create the GLES2 helper, which writes the command buffer protocol. 240 // Create the GLES2 helper, which writes the command buffer protocol.
450 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get())); 241 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
451 if (!gles2_helper_->Initialize(kCommandBufferSize)) { 242 if (!gles2_helper_->Initialize(kCommandBufferSize)) {
243 LOG(INFO) << "Failed to initialize GLES2CmdHelper";
452 Destroy(); 244 Destroy();
453 return false; 245 return false;
454 } 246 }
455 247
456 // Create a transfer buffer. 248 // Create a transfer buffer.
457 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); 249 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
458 250
459 // Create the object exposing the OpenGL API. 251 // Create the object exposing the OpenGL API.
460 gles2_implementation_.reset(new gles2::GLES2Implementation( 252 gles2_implementation_.reset(new gles2::GLES2Implementation(
461 gles2_helper_.get(), 253 gles2_helper_.get(),
462 context_group ? context_group->GetImplementation()->share_group() : NULL, 254 share_group,
463 transfer_buffer_.get(), 255 transfer_buffer_.get(),
464 false, 256 false,
465 this)); 257 this));
466 258
259 if (share_resources) {
260 g_all_shared_contexts.Get().insert(this);
261 scoped_shared_context_lock.reset();
262 }
263
467 if (!gles2_implementation_->Initialize( 264 if (!gles2_implementation_->Initialize(
468 kStartTransferBufferSize, 265 kStartTransferBufferSize,
469 kMinTransferBufferSize, 266 kMinTransferBufferSize,
470 kMaxTransferBufferSize)) { 267 kMaxTransferBufferSize)) {
471 return false; 268 return false;
472 } 269 }
473 270
474 if (share_resources_) {
475 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
476 g_all_shared_contexts.Get());
477 g_all_shared_contexts.Pointer()->insert(this);
478 }
479
480 context_lost_callback_ = context_lost_callback;
481 return true; 271 return true;
482 } 272 }
483 273
484 void GLInProcessContextImpl::Destroy() { 274 void GLInProcessContextImpl::Destroy() {
485 while (!query_callbacks_.empty()) { 275 while (!query_callbacks_.empty()) {
486 CallQueryCallback(0); 276 CallQueryCallback(0);
487 } 277 }
488 278
489 bool context_lost = IsCommandBufferContextLost();
490
491 if (gles2_implementation_) { 279 if (gles2_implementation_) {
492 // First flush the context to ensure that any pending frees of resources 280 // First flush the context to ensure that any pending frees of resources
493 // are completed. Otherwise, if this context is part of a share group, 281 // are completed. Otherwise, if this context is part of a share group,
494 // those resources might leak. Also, any remaining side effects of commands 282 // those resources might leak. Also, any remaining side effects of commands
495 // issued on this context might not be visible to other contexts in the 283 // issued on this context might not be visible to other contexts in the
496 // share group. 284 // share group.
497 gles2_implementation_->Flush(); 285 gles2_implementation_->Flush();
498 286
499 gles2_implementation_.reset(); 287 gles2_implementation_.reset();
500 } 288 }
501 289
502 transfer_buffer_.reset(); 290 transfer_buffer_.reset();
503 gles2_helper_.reset(); 291 gles2_helper_.reset();
504 command_buffer_.reset(); 292 command_buffer_.reset();
505
506 AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(),
507 g_all_shared_contexts.Get());
508 if (decoder_) {
509 decoder_->Destroy(!context_lost);
510 }
511
512 g_all_shared_contexts.Pointer()->erase(this);
513 }
514
515 void GLInProcessContextImpl::OnContextLost() {
516 if (!context_lost_callback_.is_null())
517 context_lost_callback_.Run();
518
519 context_lost_ = true;
520 if (share_resources_) {
521 for (std::set<GLInProcessContextImpl*>::iterator it =
522 g_all_shared_contexts.Get().begin();
523 it != g_all_shared_contexts.Get().end();
524 ++it)
525 (*it)->context_lost_ = true;
526 }
527 } 293 }
528 294
529 void GLInProcessContextImpl::CallQueryCallback(size_t index) { 295 void GLInProcessContextImpl::CallQueryCallback(size_t index) {
530 DCHECK_LT(index, query_callbacks_.size()); 296 DCHECK_LT(index, query_callbacks_.size());
531 QueryCallback query_callback = query_callbacks_[index]; 297 QueryCallback query_callback = query_callbacks_[index];
532 query_callbacks_[index] = query_callbacks_.back(); 298 query_callbacks_[index] = query_callbacks_.back();
533 query_callbacks_.pop_back(); 299 query_callbacks_.pop_back();
534 query_callback.second.Run(); 300 query_callback.second.Run();
535 } 301 }
536 302
303 // TODO(sievers): Move this to the service side
537 void GLInProcessContextImpl::PollQueryCallbacks() { 304 void GLInProcessContextImpl::PollQueryCallbacks() {
538 for (size_t i = 0; i < query_callbacks_.size();) { 305 for (size_t i = 0; i < query_callbacks_.size();) {
539 unsigned query = query_callbacks_[i].first; 306 unsigned query = query_callbacks_[i].first;
540 GLuint param = 0; 307 GLuint param = 0;
541 gles2::GLES2Implementation* gl = GetImplementation(); 308 gles2::GLES2Implementation* gl = GetImplementation();
542 if (gl->IsQueryEXT(query)) { 309 if (gl->IsQueryEXT(query)) {
543 gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param); 310 gl->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &param);
544 } else { 311 } else {
545 param = 1; 312 param = 1;
546 } 313 }
(...skipping 28 matching lines...) Expand all
575 GLInProcessContext* GLInProcessContext::CreateContext( 342 GLInProcessContext* GLInProcessContext::CreateContext(
576 bool is_offscreen, 343 bool is_offscreen,
577 gfx::AcceleratedWidget window, 344 gfx::AcceleratedWidget window,
578 const gfx::Size& size, 345 const gfx::Size& size,
579 bool share_resources, 346 bool share_resources,
580 const char* allowed_extensions, 347 const char* allowed_extensions,
581 const int32* attrib_list, 348 const int32* attrib_list,
582 gfx::GpuPreference gpu_preference, 349 gfx::GpuPreference gpu_preference,
583 const base::Closure& callback) { 350 const base::Closure& callback) {
584 scoped_ptr<GLInProcessContextImpl> context( 351 scoped_ptr<GLInProcessContextImpl> context(
585 new GLInProcessContextImpl(share_resources)); 352 new GLInProcessContextImpl());
586 if (!context->Initialize( 353 if (!context->Initialize(
587 is_offscreen, 354 is_offscreen,
355 share_resources,
588 window, 356 window,
589 size, 357 size,
590 allowed_extensions, 358 allowed_extensions,
591 attrib_list, 359 attrib_list,
592 gpu_preference, 360 gpu_preference,
593 callback)) 361 callback))
594 return NULL; 362 return NULL;
595 363
596 return context.release(); 364 return context.release();
597 } 365 }
598 366
599 // static 367 // static
600 void GLInProcessContext::SetGpuMemoryBufferFactory( 368 void GLInProcessContext::SetGpuMemoryBufferFactory(
601 GpuMemoryBufferFactory* factory) { 369 GpuMemoryBufferFactory* factory) {
602 DCHECK_EQ(0u, SharedContextCount()); 370 DCHECK_EQ(0u, SharedContextCount());
603 g_gpu_memory_buffer_factory = factory; 371 g_gpu_memory_buffer_factory = factory;
604 } 372 }
605 373
606 // static
607 void GLInProcessContext::EnableVirtualizedContext() {
608 DCHECK_EQ(0u, SharedContextCount());
609 g_use_virtualized_gl_context = true;
610 }
611
612 } // namespace gpu 374 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698