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

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

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