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

Side by Side Diff: gpu/gles2_conform_support/egl/context.cc

Issue 1929973003: Revert of command_buffer_gles2: Implement EGL default Display as a global object (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@command_buffer_gles2-multiple-contexts
Patch Set: Created 4 years, 7 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
« no previous file with comments | « gpu/gles2_conform_support/egl/context.h ('k') | gpu/gles2_conform_support/egl/display.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016 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 "gpu/gles2_conform_support/egl/context.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "gpu/command_buffer/client/gles2_implementation.h"
11 #include "gpu/command_buffer/client/gles2_lib.h"
12 #include "gpu/command_buffer/client/shared_memory_limits.h"
13 #include "gpu/command_buffer/client/transfer_buffer.h"
14 #include "gpu/command_buffer/service/context_group.h"
15 #include "gpu/command_buffer/service/mailbox_manager.h"
16 #include "gpu/command_buffer/service/memory_tracking.h"
17 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
18 #include "gpu/gles2_conform_support/egl/config.h"
19 #include "gpu/gles2_conform_support/egl/display.h"
20 #include "gpu/gles2_conform_support/egl/surface.h"
21 #include "gpu/gles2_conform_support/egl/thread_state.h"
22
23 // The slight complexification in this file comes from following properties:
24 // 1) Command buffer connection (context) can not be established without a
25 // GLSurface. EGL Context can be created independent of a surface. This is why
26 // the connection is created only during first MakeCurrent.
27 // 2) Command buffer MakeCurrent calls need the real gl context and surface be
28 // current.
29 // 3) Client can change real EGL context behind the scenes and then still expect
30 // command buffer MakeCurrent re-set the command buffer context. This is why all
31 // MakeCurrent calls must actually reset the real context, even though command
32 // buffer current context does not change.
33 // 4) EGL context can be destroyed without surface, but command buffer would
34 // need the surface to run various cleanups. If context is destroyed
35 // surfaceless, the context is marked lost before destruction. This is avoided
36 // if possible, since command buffer at the time of writing prints out debug
37 // text in this case.
38
39 namespace {
40 const int32_t kCommandBufferSize = 1024 * 1024;
41 const int32_t kTransferBufferSize = 512 * 1024;
42 const bool kBindGeneratesResources = true;
43 const bool kLoseContextWhenOutOfMemory = false;
44 const bool kSupportClientSideArrays = true;
45 }
46
47 namespace egl {
48 Context::Context(Display* display, const Config* config)
49 : display_(display),
50 config_(config),
51 is_current_in_some_thread_(false),
52 is_destroyed_(false),
53 gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) {
54 }
55
56 Context::~Context() {
57 // We might not have a surface, so we must lose the context. Cleanup will
58 // execute GL commands otherwise. TODO: if shared contexts are ever
59 // implemented, this will leak the GL resources. For pbuffer contexts, one
60 // could track the last current surface or create a surface for destroying
61 // purposes only. Other option would be to make the service usable without
62 // surface.
63 if (HasService()) {
64 if (!WasServiceContextLost())
65 MarkServiceContextLost();
66 DestroyService();
67 }
68 }
69
70 void Context::MarkDestroyed() {
71 is_destroyed_ = true;
72 }
73
74 bool Context::SwapBuffers(Surface* current_surface) {
75 DCHECK(HasService() && is_current_in_some_thread_);
76 if (WasServiceContextLost())
77 return false;
78 client_gl_context_->SwapBuffers();
79 return true;
80 }
81
82 bool Context::MakeCurrent(Context* current_context,
83 Surface* current_surface,
84 Context* new_context,
85 Surface* new_surface) {
86 if (!new_context && !current_context) {
87 return true;
88 }
89 bool cleanup_old_current_context = false;
90 if (current_context) {
91 if (current_context->Flush(current_surface->gl_surface()))
92 cleanup_old_current_context = new_context != current_context;
93 }
94
95 if (new_context) {
96 if (!new_context->IsCompatibleSurface(new_surface))
97 return false;
98
99 if (new_context->HasService()) {
100 if (new_context->WasServiceContextLost())
101 return false;
102 if (new_context != current_context) {
103 // If Flush did not set the current context, set it now. Otherwise
104 // calling into the decoder is not ok.
105 if (!new_context->gl_context_->MakeCurrent(new_surface->gl_surface())) {
106 new_context->MarkServiceContextLost();
107 return false;
108 }
109 }
110 if (new_context != current_context || new_surface != current_surface)
111 new_context->decoder_->SetSurface(new_surface->gl_surface());
112 if (!new_context->decoder_->MakeCurrent()) {
113 new_context->MarkServiceContextLost();
114 return false;
115 }
116 } else {
117 if (!new_context->CreateService(new_surface->gl_surface())) {
118 return false;
119 }
120 }
121 }
122
123 // The current_surface will be released when MakeCurrent succeeds.
124 // Cleanup in this case only.
125 if (cleanup_old_current_context) {
126 if (current_context->is_destroyed_ && current_surface != new_surface) {
127 current_context->gl_context_->MakeCurrent(current_surface->gl_surface());
128 // If we are releasing the context and we have one ref, it means that the
129 // ref will be lost and the object will be destroyed. Destroy the service
130 // explicitly here, so that cleanup can happen and client GL
131 // implementation does not print errors.
132 current_context->DestroyService();
133 } else {
134 current_context->decoder_->ReleaseSurface();
135 }
136 }
137
138 return true;
139 }
140
141 bool Context::ValidateAttributeList(const EGLint* attrib_list) {
142 if (attrib_list) {
143 for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) {
144 switch (attrib_list[i]) {
145 case EGL_CONTEXT_CLIENT_VERSION:
146 break;
147 default:
148 return false;
149 }
150 }
151 }
152 return true;
153 }
154
155 void Context::SetGpuControlClient(gpu::GpuControlClient*) {
156 // The client is not currently called, so don't store it.
157 }
158
159 gpu::Capabilities Context::GetCapabilities() {
160 return decoder_->GetCapabilities();
161 }
162
163 int32_t Context::CreateImage(ClientBuffer buffer,
164 size_t width,
165 size_t height,
166 unsigned internalformat) {
167 NOTIMPLEMENTED();
168 return -1;
169 }
170
171 void Context::DestroyImage(int32_t id) {
172 NOTIMPLEMENTED();
173 }
174
175 int32_t Context::CreateGpuMemoryBufferImage(size_t width,
176 size_t height,
177 unsigned internalformat,
178 unsigned usage) {
179 NOTIMPLEMENTED();
180 return -1;
181 }
182
183 void Context::SignalQuery(uint32_t query, const base::Closure& callback) {
184 NOTIMPLEMENTED();
185 }
186
187 void Context::SetLock(base::Lock*) {
188 NOTIMPLEMENTED();
189 }
190
191 bool Context::IsGpuChannelLost() {
192 NOTIMPLEMENTED();
193 return false;
194 }
195
196 void Context::EnsureWorkVisible() {
197 // This is only relevant for out-of-process command buffers.
198 }
199
200 gpu::CommandBufferNamespace Context::GetNamespaceID() const {
201 return gpu::CommandBufferNamespace::IN_PROCESS;
202 }
203
204 gpu::CommandBufferId Context::GetCommandBufferID() const {
205 return gpu::CommandBufferId();
206 }
207
208 int32_t Context::GetExtraCommandBufferData() const {
209 return 0;
210 }
211
212 uint64_t Context::GenerateFenceSyncRelease() {
213 return display_->GenerateFenceSyncRelease();
214 }
215
216 bool Context::IsFenceSyncRelease(uint64_t release) {
217 return display_->IsFenceSyncRelease(release);
218 }
219
220 bool Context::IsFenceSyncFlushed(uint64_t release) {
221 return display_->IsFenceSyncFlushed(release);
222 }
223
224 bool Context::IsFenceSyncFlushReceived(uint64_t release) {
225 return display_->IsFenceSyncFlushReceived(release);
226 }
227
228 void Context::SignalSyncToken(const gpu::SyncToken& sync_token,
229 const base::Closure& callback) {
230 NOTIMPLEMENTED();
231 }
232
233 bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) {
234 return false;
235 }
236
237 void Context::ApplyCurrentContext(gfx::GLSurface* current_surface) {
238 DCHECK(HasService());
239 // The current_surface will be the same as
240 // the surface of the decoder. We can not DCHECK as there is
241 // no accessor.
242 if (!WasServiceContextLost()) {
243 if (!gl_context_->MakeCurrent(current_surface))
244 MarkServiceContextLost();
245 }
246 gles2::SetGLContext(client_gl_context_.get());
247 }
248
249 void Context::ApplyContextReleased() {
250 gles2::SetGLContext(nullptr);
251 }
252
253 bool Context::CreateService(gfx::GLSurface* gl_surface) {
254 scoped_refptr<gpu::TransferBufferManager> transfer_buffer_manager(
255 new gpu::TransferBufferManager(nullptr));
256 transfer_buffer_manager->Initialize();
257
258 std::unique_ptr<gpu::CommandBufferService> command_buffer(
259 new gpu::CommandBufferService(transfer_buffer_manager.get()));
260 if (!command_buffer->Initialize())
261 return false;
262 scoped_refptr<gpu::gles2::FeatureInfo> feature_info(
263 new gpu::gles2::FeatureInfo(gpu_driver_bug_workarounds_));
264 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
265 gpu_preferences_, nullptr, nullptr,
266 new gpu::gles2::ShaderTranslatorCache(gpu_preferences_),
267 new gpu::gles2::FramebufferCompletenessCache, feature_info, true));
268
269 std::unique_ptr<gpu::gles2::GLES2Decoder> decoder(
270 gpu::gles2::GLES2Decoder::Create(group.get()));
271 if (!decoder.get())
272 return false;
273
274 std::unique_ptr<gpu::CommandExecutor> command_executor(
275 new gpu::CommandExecutor(command_buffer.get(), decoder.get(),
276 decoder.get()));
277
278 decoder->set_engine(command_executor.get());
279
280 scoped_refptr<gfx::GLContext> gl_context(gfx::GLContext::CreateGLContext(
281 nullptr, gl_surface, gfx::PreferDiscreteGpu));
282 if (!gl_context)
283 return false;
284
285 gl_context->MakeCurrent(gl_surface);
286
287 gpu::gles2::ContextCreationAttribHelper helper;
288 config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size);
289 config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size);
290 config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size);
291
292 helper.buffer_preserved = false;
293 helper.bind_generates_resource = kBindGeneratesResources;
294 helper.fail_if_major_perf_caveat = false;
295 helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory;
296 helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2;
297 std::vector<int32_t> attribs;
298 helper.Serialize(&attribs);
299
300 if (!decoder->Initialize(gl_surface, gl_context.get(),
301 gl_surface->IsOffscreen(), gl_surface->GetSize(),
302 gpu::gles2::DisallowedFeatures(), attribs)) {
303 return false;
304 }
305
306 command_buffer->SetPutOffsetChangeCallback(
307 base::Bind(&gpu::CommandExecutor::PutChanged,
308 base::Unretained(command_executor.get())));
309 command_buffer->SetGetBufferChangeCallback(
310 base::Bind(&gpu::CommandExecutor::SetGetBuffer,
311 base::Unretained(command_executor.get())));
312
313 std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper(
314 new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
315 if (!gles2_cmd_helper->Initialize(kCommandBufferSize)) {
316 decoder->Destroy(true);
317 return false;
318 }
319
320 std::unique_ptr<gpu::TransferBuffer> transfer_buffer(
321 new gpu::TransferBuffer(gles2_cmd_helper.get()));
322
323 gles2_cmd_helper_.reset(gles2_cmd_helper.release());
324 transfer_buffer_.reset(transfer_buffer.release());
325 command_buffer_.reset(command_buffer.release());
326 command_executor_.reset(command_executor.release());
327 decoder_.reset(decoder.release());
328 gl_context_ = gl_context.get();
329
330 std::unique_ptr<gpu::gles2::GLES2Implementation> context(
331 new gpu::gles2::GLES2Implementation(
332 gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(),
333 kBindGeneratesResources, kLoseContextWhenOutOfMemory,
334 kSupportClientSideArrays, this));
335
336 if (!context->Initialize(kTransferBufferSize, kTransferBufferSize / 2,
337 kTransferBufferSize * 2,
338 gpu::SharedMemoryLimits::kNoLimit)) {
339 DestroyService();
340 return false;
341 }
342
343 context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
344 context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
345 client_gl_context_.reset(context.release());
346 return true;
347 }
348
349 void Context::DestroyService() {
350 DCHECK(HasService());
351 bool have_context = !WasServiceContextLost();
352 // The client gl interface might still be set to current global
353 // interface. This will be cleaned up in ApplyContextReleased
354 // with AutoCurrentContextRestore.
355 client_gl_context_.reset();
356 gl_context_ = nullptr;
357
358 transfer_buffer_.reset();
359 command_executor_.reset();
360 if (decoder_)
361 decoder_->Destroy(have_context);
362 gles2_cmd_helper_.reset();
363 command_buffer_.reset();
364 }
365
366 bool Context::HasService() const {
367 return decoder_ != nullptr;
368 }
369
370 void Context::MarkServiceContextLost() {
371 decoder_->GetContextGroup()->LoseContexts(gpu::error::kMakeCurrentFailed);
372 }
373
374 bool Context::WasServiceContextLost() const {
375 return decoder_->WasContextLost();
376 }
377
378 bool Context::IsCompatibleSurface(Surface* surface) const {
379 // Inspect current_surface->config() instead of gl_surface()->IsOffscreen()
380 // because GTF windowless window surfaces might be emulated with offscreen
381 // surfaces.
382 EGLint value = EGL_NONE;
383 config_->GetAttrib(EGL_SURFACE_TYPE, &value);
384 bool context_config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0;
385 surface->config()->GetAttrib(EGL_SURFACE_TYPE, &value);
386 bool surface_config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0;
387 return surface_config_is_offscreen == context_config_is_offscreen;
388 }
389
390 bool Context::Flush(gfx::GLSurface* gl_surface) {
391 if (WasServiceContextLost())
392 return false;
393 if (!gl_context_->MakeCurrent(gl_surface)) {
394 MarkServiceContextLost();
395 return false;
396 }
397 client_gl_context_->Flush();
398 return true;
399 }
400
401 } // namespace egl
OLDNEW
« no previous file with comments | « gpu/gles2_conform_support/egl/context.h ('k') | gpu/gles2_conform_support/egl/display.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698