OLD | NEW |
(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 namespace { |
| 24 const int32_t kCommandBufferSize = 1024 * 1024; |
| 25 const int32_t kTransferBufferSize = 512 * 1024; |
| 26 const bool kBindGeneratesResources = true; |
| 27 const bool kLoseContextWhenOutOfMemory = false; |
| 28 const bool kSupportClientSideArrays = true; |
| 29 } |
| 30 |
| 31 namespace egl { |
| 32 Context::Context(Display* display, const Config* config) |
| 33 : display_(display), config_(config), is_current_in_some_thread_(false) {} |
| 34 |
| 35 Context::~Context() { |
| 36 // We might not have a surface, so we must lose the context. |
| 37 // Cleanup will execute GL commands otherwise. |
| 38 if (!WasContextLost()) |
| 39 MarkContextLost(); |
| 40 Cleanup(); |
| 41 } |
| 42 |
| 43 void Context::SetDestroyed(Surface* current_surface_if_own) { |
| 44 if (WasContextLost()) |
| 45 return; |
| 46 if (!client_gl_context_) |
| 47 return; |
| 48 if (!current_surface_if_own) |
| 49 return; |
| 50 if (!gl_context_->MakeCurrent(current_surface_if_own->gl_surface())) |
| 51 return; |
| 52 client_gl_context_->Flush(); |
| 53 } |
| 54 |
| 55 void Context::FlushAndSwapBuffers(Surface* current_surface) { |
| 56 if (WasContextLost()) |
| 57 return; |
| 58 if (!client_gl_context_) |
| 59 return; |
| 60 if (!gl_context_->MakeCurrent(current_surface->gl_surface())) { |
| 61 MarkContextLost(); |
| 62 return; |
| 63 } |
| 64 client_gl_context_->Flush(); |
| 65 current_surface->gl_surface()->SwapBuffers(); |
| 66 } |
| 67 |
| 68 void Context::MakeCurrentRelease(Surface* current_surface) { |
| 69 // MakeCurrentRelease always succeeds. |
| 70 is_current_in_some_thread_ = false; |
| 71 if (WasContextLost()) |
| 72 return; |
| 73 if (!gl_context_->MakeCurrent(current_surface->gl_surface())) { |
| 74 MarkContextLost(); |
| 75 return; |
| 76 } |
| 77 client_gl_context_->Flush(); |
| 78 decoder_->SetSurface(nullptr); |
| 79 decoder_->ReleaseCurrent(); |
| 80 } |
| 81 |
| 82 bool Context::MakeCurrentSwitchSurface(Surface* current_surface, |
| 83 Surface* new_surface) { |
| 84 if (WasContextLost()) |
| 85 return false; |
| 86 if (!IsCompatibleSurface(new_surface->gl_surface())) |
| 87 return false; |
| 88 if (!gl_context_->MakeCurrent(current_surface->gl_surface())) { |
| 89 MarkContextLost(); |
| 90 return false; |
| 91 } |
| 92 client_gl_context_->Flush(); |
| 93 if (current_surface != new_surface) |
| 94 decoder_->SetSurface(new_surface->gl_surface()); |
| 95 if (!decoder_->MakeCurrent()) { |
| 96 MarkContextLost(); |
| 97 return false; |
| 98 } |
| 99 return true; |
| 100 } |
| 101 |
| 102 bool Context::MakeCurrent(Surface* new_surface) { |
| 103 DCHECK(new_surface); |
| 104 if (WasContextLost()) |
| 105 return false; |
| 106 if (!IsCompatibleSurface(new_surface->gl_surface())) |
| 107 return false; |
| 108 if (client_gl_context_) { |
| 109 if (!gl_context_->MakeCurrent(new_surface->gl_surface())) { |
| 110 MarkContextLost(); |
| 111 return false; |
| 112 } |
| 113 decoder_->SetSurface(new_surface->gl_surface()); |
| 114 if (!decoder_->MakeCurrent()) { |
| 115 MarkContextLost(); |
| 116 return false; |
| 117 } |
| 118 is_current_in_some_thread_ = true; |
| 119 return true; |
| 120 } |
| 121 gfx::GLSurface* gl_surface = new_surface->gl_surface(); |
| 122 scoped_refptr<gpu::TransferBufferManager> transfer_buffer_manager( |
| 123 new gpu::TransferBufferManager(nullptr)); |
| 124 transfer_buffer_manager->Initialize(); |
| 125 |
| 126 scoped_ptr<gpu::CommandBufferService> command_buffer( |
| 127 new gpu::CommandBufferService(transfer_buffer_manager.get())); |
| 128 if (!command_buffer->Initialize()) |
| 129 return false; |
| 130 |
| 131 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( |
| 132 NULL, NULL, new gpu::gles2::ShaderTranslatorCache, |
| 133 new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); |
| 134 |
| 135 scoped_ptr<gpu::gles2::GLES2Decoder> decoder( |
| 136 gpu::gles2::GLES2Decoder::Create(group.get())); |
| 137 if (!decoder.get()) |
| 138 return false; |
| 139 |
| 140 scoped_ptr<gpu::GpuScheduler> gpu_scheduler(new gpu::GpuScheduler( |
| 141 command_buffer.get(), decoder.get(), decoder.get())); |
| 142 |
| 143 decoder->set_engine(gpu_scheduler.get()); |
| 144 |
| 145 scoped_refptr<gfx::GLContext> gl_context(gfx::GLContext::CreateGLContext( |
| 146 nullptr, gl_surface, gfx::PreferDiscreteGpu)); |
| 147 if (!gl_context) |
| 148 return false; |
| 149 |
| 150 gl_context->MakeCurrent(gl_surface); |
| 151 |
| 152 gpu::gles2::ContextCreationAttribHelper helper; |
| 153 config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size); |
| 154 config_->GetAttrib(EGL_BLUE_SIZE, &helper.blue_size); |
| 155 config_->GetAttrib(EGL_GREEN_SIZE, &helper.green_size); |
| 156 config_->GetAttrib(EGL_RED_SIZE, &helper.red_size); |
| 157 config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size); |
| 158 config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size); |
| 159 config_->GetAttrib(EGL_SAMPLES, &helper.samples); |
| 160 config_->GetAttrib(EGL_SAMPLE_BUFFERS, &helper.sample_buffers); |
| 161 |
| 162 helper.buffer_preserved = false; |
| 163 helper.bind_generates_resource = kBindGeneratesResources; |
| 164 helper.fail_if_major_perf_caveat = false; |
| 165 helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory; |
| 166 helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2; |
| 167 std::vector<int32_t> attribs; |
| 168 helper.Serialize(&attribs); |
| 169 |
| 170 if (!decoder->Initialize(gl_surface, gl_context.get(), |
| 171 gl_surface->IsOffscreen(), gl_surface->GetSize(), |
| 172 gpu::gles2::DisallowedFeatures(), attribs)) { |
| 173 return false; |
| 174 } |
| 175 |
| 176 command_buffer->SetPutOffsetChangeCallback(base::Bind( |
| 177 &gpu::GpuScheduler::PutChanged, base::Unretained(gpu_scheduler.get()))); |
| 178 command_buffer->SetGetBufferChangeCallback(base::Bind( |
| 179 &gpu::GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler.get()))); |
| 180 |
| 181 scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper( |
| 182 new gpu::gles2::GLES2CmdHelper(command_buffer.get())); |
| 183 if (!gles2_cmd_helper->Initialize(kCommandBufferSize)) { |
| 184 decoder->Destroy(true); |
| 185 return false; |
| 186 } |
| 187 |
| 188 scoped_ptr<gpu::TransferBuffer> transfer_buffer( |
| 189 new gpu::TransferBuffer(gles2_cmd_helper.get())); |
| 190 |
| 191 gles2_cmd_helper_.reset(gles2_cmd_helper.release()); |
| 192 transfer_buffer_.reset(transfer_buffer.release()); |
| 193 command_buffer_.reset(command_buffer.release()); |
| 194 gpu_scheduler_.reset(gpu_scheduler.release()); |
| 195 decoder_.reset(decoder.release()); |
| 196 gl_context_ = gl_context.get(); |
| 197 |
| 198 scoped_ptr<gpu::gles2::GLES2Implementation> context( |
| 199 new gpu::gles2::GLES2Implementation( |
| 200 gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(), |
| 201 kBindGeneratesResources, kLoseContextWhenOutOfMemory, |
| 202 kSupportClientSideArrays, this)); |
| 203 |
| 204 if (!context->Initialize(kTransferBufferSize, kTransferBufferSize / 2, |
| 205 kTransferBufferSize * 2, |
| 206 gpu::gles2::GLES2Implementation::kNoLimit)) { |
| 207 Cleanup(); |
| 208 return false; |
| 209 } |
| 210 |
| 211 context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); |
| 212 context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); |
| 213 client_gl_context_.reset(context.release()); |
| 214 is_current_in_some_thread_ = true; |
| 215 return true; |
| 216 } |
| 217 |
| 218 gfx::GLContext* Context::gl_context() const { |
| 219 return gl_context_.get(); |
| 220 } |
| 221 |
| 222 gpu::gles2::GLES2Interface* Context::client_gl_context() const { |
| 223 return client_gl_context_.get(); |
| 224 } |
| 225 |
| 226 bool Context::ValidateAttributeList(const EGLint* attrib_list) { |
| 227 if (attrib_list) { |
| 228 for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) { |
| 229 switch (attrib_list[i]) { |
| 230 case EGL_CONTEXT_CLIENT_VERSION: |
| 231 break; |
| 232 default: |
| 233 return false; |
| 234 } |
| 235 } |
| 236 } |
| 237 return true; |
| 238 } |
| 239 |
| 240 gpu::Capabilities Context::GetCapabilities() { |
| 241 return decoder_->GetCapabilities(); |
| 242 } |
| 243 |
| 244 int32_t Context::CreateImage(ClientBuffer buffer, |
| 245 size_t width, |
| 246 size_t height, |
| 247 unsigned internalformat) { |
| 248 NOTIMPLEMENTED(); |
| 249 return -1; |
| 250 } |
| 251 |
| 252 void Context::DestroyImage(int32_t id) { |
| 253 NOTIMPLEMENTED(); |
| 254 } |
| 255 |
| 256 int32_t Context::CreateGpuMemoryBufferImage(size_t width, |
| 257 size_t height, |
| 258 unsigned internalformat, |
| 259 unsigned usage) { |
| 260 NOTIMPLEMENTED(); |
| 261 return -1; |
| 262 } |
| 263 |
| 264 void Context::SignalQuery(uint32_t query, const base::Closure& callback) { |
| 265 NOTIMPLEMENTED(); |
| 266 } |
| 267 |
| 268 void Context::SetLock(base::Lock*) { |
| 269 NOTIMPLEMENTED(); |
| 270 } |
| 271 |
| 272 bool Context::IsGpuChannelLost() { |
| 273 NOTIMPLEMENTED(); |
| 274 return false; |
| 275 } |
| 276 |
| 277 void Context::EnsureWorkVisible() { |
| 278 // This is only relevant for out-of-process command buffers. |
| 279 } |
| 280 |
| 281 gpu::CommandBufferNamespace Context::GetNamespaceID() const { |
| 282 return gpu::CommandBufferNamespace::IN_PROCESS; |
| 283 } |
| 284 |
| 285 uint64_t Context::GetCommandBufferID() const { |
| 286 return 0; |
| 287 } |
| 288 |
| 289 int32_t Context::GetExtraCommandBufferData() const { |
| 290 return 0; |
| 291 } |
| 292 |
| 293 uint64_t Context::GenerateFenceSyncRelease() { |
| 294 return display_->GenerateFenceSyncRelease(); |
| 295 } |
| 296 |
| 297 bool Context::IsFenceSyncRelease(uint64_t release) { |
| 298 return display_->IsFenceSyncRelease(release); |
| 299 } |
| 300 |
| 301 bool Context::IsFenceSyncFlushed(uint64_t release) { |
| 302 return display_->IsFenceSyncFlushed(release); |
| 303 } |
| 304 |
| 305 bool Context::IsFenceSyncFlushReceived(uint64_t release) { |
| 306 return display_->IsFenceSyncFlushReceived(release); |
| 307 } |
| 308 |
| 309 void Context::SignalSyncToken(const gpu::SyncToken& sync_token, |
| 310 const base::Closure& callback) { |
| 311 NOTIMPLEMENTED(); |
| 312 } |
| 313 |
| 314 bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { |
| 315 return false; |
| 316 } |
| 317 |
| 318 void Context::Cleanup() { |
| 319 client_gl_context_.reset(); |
| 320 gl_context_ = nullptr; |
| 321 |
| 322 transfer_buffer_.reset(); |
| 323 gpu_scheduler_.reset(); |
| 324 if (decoder_) |
| 325 decoder_->Destroy(false); |
| 326 gles2_cmd_helper_.reset(); |
| 327 command_buffer_.reset(); |
| 328 } |
| 329 |
| 330 void Context::MarkContextLost() { |
| 331 if (!decoder_) |
| 332 return; |
| 333 decoder_->MarkContextLost(gpu::error::kMakeCurrentFailed); |
| 334 } |
| 335 |
| 336 bool Context::WasContextLost() const { |
| 337 return decoder_ && decoder_->WasContextLost(); |
| 338 } |
| 339 |
| 340 bool Context::IsCompatibleSurface(gfx::GLSurface* gl_surface) { |
| 341 EGLint value = EGL_NONE; |
| 342 config_->GetAttrib(EGL_SURFACE_TYPE, &value); |
| 343 bool config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0; |
| 344 return gl_surface->IsOffscreen() == config_is_offscreen; |
| 345 } |
| 346 |
| 347 } // namespace egl |
OLD | NEW |