OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "mojo/services/gles2/command_buffer_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/macros.h" | |
9 #include "base/memory/shared_memory.h" | |
10 #include "gpu/command_buffer/common/constants.h" | |
11 #include "gpu/command_buffer/service/command_buffer_service.h" | |
12 #include "gpu/command_buffer/service/context_group.h" | |
13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | |
14 #include "gpu/command_buffer/service/gpu_scheduler.h" | |
15 #include "gpu/command_buffer/service/image_manager.h" | |
16 #include "gpu/command_buffer/service/mailbox_manager.h" | |
17 #include "gpu/command_buffer/service/memory_tracking.h" | |
18 #include "mojo/services/gles2/command_buffer_type_conversions.h" | |
19 #include "mojo/services/gles2/mojo_buffer_backing.h" | |
20 #include "ui/gl/gl_context.h" | |
21 #include "ui/gl/gl_surface.h" | |
22 | |
23 namespace mojo { | |
24 | |
25 namespace { | |
26 | |
27 class MemoryTrackerStub : public gpu::gles2::MemoryTracker { | |
28 public: | |
29 MemoryTrackerStub() {} | |
30 | |
31 void TrackMemoryAllocatedChange( | |
32 size_t old_size, | |
33 size_t new_size, | |
34 gpu::gles2::MemoryTracker::Pool pool) override {} | |
35 | |
36 bool EnsureGPUMemoryAvailable(size_t size_needed) override { return true; }; | |
37 | |
38 private: | |
39 ~MemoryTrackerStub() override {} | |
40 | |
41 DISALLOW_COPY_AND_ASSIGN(MemoryTrackerStub); | |
42 }; | |
43 | |
44 } // anonymous namespace | |
45 | |
46 CommandBufferImpl::CommandBufferImpl( | |
47 gfx::GLShareGroup* share_group, | |
48 gpu::gles2::MailboxManager* mailbox_manager) | |
49 : widget_(gfx::kNullAcceleratedWidget), | |
50 size_(1, 1), | |
51 share_group_(share_group), | |
52 mailbox_manager_(mailbox_manager) { | |
53 } | |
54 | |
55 CommandBufferImpl::CommandBufferImpl( | |
56 gfx::AcceleratedWidget widget, | |
57 const gfx::Size& size, | |
58 gfx::GLShareGroup* share_group, | |
59 gpu::gles2::MailboxManager* mailbox_manager) | |
60 : widget_(widget), | |
61 size_(size), | |
62 share_group_(share_group), | |
63 mailbox_manager_(mailbox_manager) { | |
64 } | |
65 | |
66 CommandBufferImpl::~CommandBufferImpl() { | |
67 client()->DidDestroy(); | |
68 if (decoder_) { | |
69 bool have_context = decoder_->MakeCurrent(); | |
70 decoder_->Destroy(have_context); | |
71 } | |
72 } | |
73 | |
74 void CommandBufferImpl::Initialize( | |
75 CommandBufferSyncClientPtr sync_client, | |
76 mojo::ScopedSharedBufferHandle shared_state) { | |
77 sync_client_ = sync_client.Pass(); | |
78 sync_client_->DidInitialize(DoInitialize(shared_state.Pass())); | |
79 } | |
80 | |
81 bool CommandBufferImpl::DoInitialize( | |
82 mojo::ScopedSharedBufferHandle shared_state) { | |
83 if (widget_ == gfx::kNullAcceleratedWidget) | |
84 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size_); | |
85 else | |
86 surface_ = gfx::GLSurface::CreateViewGLSurface(widget_); | |
87 if (!surface_.get()) | |
88 return false; | |
89 | |
90 // TODO(piman): virtual contexts, gpu preference. | |
91 context_ = gfx::GLContext::CreateGLContext( | |
92 share_group_.get(), surface_.get(), gfx::PreferIntegratedGpu); | |
93 if (!context_.get()) | |
94 return false; | |
95 | |
96 if (!context_->MakeCurrent(surface_.get())) | |
97 return false; | |
98 | |
99 // TODO(piman): ShaderTranslatorCache is currently per-ContextGroup but | |
100 // only needs to be per-thread. | |
101 scoped_refptr<gpu::gles2::ContextGroup> context_group = | |
102 new gpu::gles2::ContextGroup(mailbox_manager_.get(), | |
103 new MemoryTrackerStub, | |
104 new gpu::gles2::ShaderTranslatorCache, | |
105 NULL, | |
106 true); | |
107 | |
108 command_buffer_.reset( | |
109 new gpu::CommandBufferService(context_group->transfer_buffer_manager())); | |
110 bool result = command_buffer_->Initialize(); | |
111 DCHECK(result); | |
112 | |
113 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group.get())); | |
114 scheduler_.reset(new gpu::GpuScheduler( | |
115 command_buffer_.get(), decoder_.get(), decoder_.get())); | |
116 decoder_->set_engine(scheduler_.get()); | |
117 decoder_->SetResizeCallback( | |
118 base::Bind(&CommandBufferImpl::OnResize, base::Unretained(this))); | |
119 | |
120 gpu::gles2::DisallowedFeatures disallowed_features; | |
121 | |
122 // TODO(piman): attributes. | |
123 std::vector<int32> attrib_vector; | |
124 if (!decoder_->Initialize(surface_, | |
125 context_, | |
126 false /* offscreen */, | |
127 size_, | |
128 disallowed_features, | |
129 attrib_vector)) | |
130 return false; | |
131 | |
132 command_buffer_->SetPutOffsetChangeCallback(base::Bind( | |
133 &gpu::GpuScheduler::PutChanged, base::Unretained(scheduler_.get()))); | |
134 command_buffer_->SetGetBufferChangeCallback(base::Bind( | |
135 &gpu::GpuScheduler::SetGetBuffer, base::Unretained(scheduler_.get()))); | |
136 command_buffer_->SetParseErrorCallback( | |
137 base::Bind(&CommandBufferImpl::OnParseError, base::Unretained(this))); | |
138 | |
139 // TODO(piman): other callbacks | |
140 | |
141 const size_t kSize = sizeof(gpu::CommandBufferSharedState); | |
142 scoped_ptr<gpu::BufferBacking> backing( | |
143 gles2::MojoBufferBacking::Create(shared_state.Pass(), kSize)); | |
144 if (!backing) | |
145 return false; | |
146 | |
147 command_buffer_->SetSharedStateBuffer(backing.Pass()); | |
148 return true; | |
149 } | |
150 | |
151 void CommandBufferImpl::SetGetBuffer(int32_t buffer) { | |
152 command_buffer_->SetGetBuffer(buffer); | |
153 } | |
154 | |
155 void CommandBufferImpl::Flush(int32_t put_offset) { | |
156 if (!context_->MakeCurrent(surface_.get())) { | |
157 DLOG(WARNING) << "Context lost"; | |
158 client()->LostContext(gpu::error::kUnknown); | |
159 return; | |
160 } | |
161 command_buffer_->Flush(put_offset); | |
162 } | |
163 | |
164 void CommandBufferImpl::MakeProgress(int32_t last_get_offset) { | |
165 // TODO(piman): handle out-of-order. | |
166 sync_client_->DidMakeProgress( | |
167 CommandBufferState::From(command_buffer_->GetLastState())); | |
168 } | |
169 | |
170 void CommandBufferImpl::RegisterTransferBuffer( | |
171 int32_t id, | |
172 mojo::ScopedSharedBufferHandle transfer_buffer, | |
173 uint32_t size) { | |
174 // Take ownership of the memory and map it into this process. | |
175 // This validates the size. | |
176 scoped_ptr<gpu::BufferBacking> backing( | |
177 gles2::MojoBufferBacking::Create(transfer_buffer.Pass(), size)); | |
178 if (!backing) { | |
179 DVLOG(0) << "Failed to map shared memory."; | |
180 return; | |
181 } | |
182 command_buffer_->RegisterTransferBuffer(id, backing.Pass()); | |
183 } | |
184 | |
185 void CommandBufferImpl::DestroyTransferBuffer(int32_t id) { | |
186 command_buffer_->DestroyTransferBuffer(id); | |
187 } | |
188 | |
189 void CommandBufferImpl::Echo(const Callback<void()>& callback) { | |
190 callback.Run(); | |
191 } | |
192 | |
193 void CommandBufferImpl::OnParseError() { | |
194 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); | |
195 client()->LostContext(state.context_lost_reason); | |
196 } | |
197 | |
198 void CommandBufferImpl::OnResize(gfx::Size size, float scale_factor) { | |
199 surface_->Resize(size); | |
200 } | |
201 | |
202 } // namespace mojo | |
OLD | NEW |