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

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

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