Index: gpu/gles2_conform_support/egl/context.cc |
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ead2598deeb932aae7b3b29014075bd72d37acb3 |
--- /dev/null |
+++ b/gpu/gles2_conform_support/egl/context.cc |
@@ -0,0 +1,347 @@ |
+// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "gpu/gles2_conform_support/egl/context.h" |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "gpu/command_buffer/client/gles2_implementation.h" |
+#include "gpu/command_buffer/client/gles2_lib.h" |
+#include "gpu/command_buffer/client/transfer_buffer.h" |
+#include "gpu/command_buffer/common/value_state.h" |
+#include "gpu/command_buffer/service/context_group.h" |
+#include "gpu/command_buffer/service/mailbox_manager.h" |
+#include "gpu/command_buffer/service/memory_tracking.h" |
+#include "gpu/command_buffer/service/transfer_buffer_manager.h" |
+#include "gpu/command_buffer/service/valuebuffer_manager.h" |
+#include "gpu/gles2_conform_support/egl/config.h" |
+#include "gpu/gles2_conform_support/egl/display.h" |
+#include "gpu/gles2_conform_support/egl/surface.h" |
+#include "gpu/gles2_conform_support/egl/thread_state.h" |
+ |
+namespace { |
+const int32_t kCommandBufferSize = 1024 * 1024; |
+const int32_t kTransferBufferSize = 512 * 1024; |
+const bool kBindGeneratesResources = true; |
+const bool kLoseContextWhenOutOfMemory = false; |
+const bool kSupportClientSideArrays = true; |
+} |
+ |
+namespace egl { |
+Context::Context(Display* display, const Config* config) |
+ : display_(display), config_(config), is_current_in_some_thread_(false) {} |
+ |
+Context::~Context() { |
+ // We might not have a surface, so we must lose the context. |
+ // Cleanup will execute GL commands otherwise. |
+ if (!WasContextLost()) |
+ MarkContextLost(); |
+ Cleanup(); |
+} |
+ |
+void Context::SetDestroyed(Surface* current_surface_if_own) { |
+ if (WasContextLost()) |
+ return; |
+ if (!client_gl_context_) |
+ return; |
+ if (!current_surface_if_own) |
+ return; |
+ if (!gl_context_->MakeCurrent(current_surface_if_own->gl_surface())) |
+ return; |
+ client_gl_context_->Flush(); |
+} |
+ |
+void Context::FlushAndSwapBuffers(Surface* current_surface) { |
+ if (WasContextLost()) |
+ return; |
+ if (!client_gl_context_) |
+ return; |
+ if (!gl_context_->MakeCurrent(current_surface->gl_surface())) { |
+ MarkContextLost(); |
+ return; |
+ } |
+ client_gl_context_->Flush(); |
+ current_surface->gl_surface()->SwapBuffers(); |
+} |
+ |
+void Context::MakeCurrentRelease(Surface* current_surface) { |
+ // MakeCurrentRelease always succeeds. |
+ is_current_in_some_thread_ = false; |
+ if (WasContextLost()) |
+ return; |
+ if (!gl_context_->MakeCurrent(current_surface->gl_surface())) { |
+ MarkContextLost(); |
+ return; |
+ } |
+ client_gl_context_->Flush(); |
+ decoder_->SetSurface(nullptr); |
+ decoder_->ReleaseCurrent(); |
+} |
+ |
+bool Context::MakeCurrentSwitchSurface(Surface* current_surface, |
+ Surface* new_surface) { |
+ if (WasContextLost()) |
+ return false; |
+ if (!IsCompatibleSurface(new_surface->gl_surface())) |
+ return false; |
+ if (!gl_context_->MakeCurrent(current_surface->gl_surface())) { |
+ MarkContextLost(); |
+ return false; |
+ } |
+ client_gl_context_->Flush(); |
+ if (current_surface != new_surface) |
+ decoder_->SetSurface(new_surface->gl_surface()); |
+ if (!decoder_->MakeCurrent()) { |
+ MarkContextLost(); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+bool Context::MakeCurrent(Surface* new_surface) { |
+ DCHECK(new_surface); |
+ if (WasContextLost()) |
+ return false; |
+ if (!IsCompatibleSurface(new_surface->gl_surface())) |
+ return false; |
+ if (client_gl_context_) { |
+ if (!gl_context_->MakeCurrent(new_surface->gl_surface())) { |
+ MarkContextLost(); |
+ return false; |
+ } |
+ decoder_->SetSurface(new_surface->gl_surface()); |
+ if (!decoder_->MakeCurrent()) { |
+ MarkContextLost(); |
+ return false; |
+ } |
+ is_current_in_some_thread_ = true; |
+ return true; |
+ } |
+ gfx::GLSurface* gl_surface = new_surface->gl_surface(); |
+ scoped_refptr<gpu::TransferBufferManager> transfer_buffer_manager( |
+ new gpu::TransferBufferManager(nullptr)); |
+ transfer_buffer_manager->Initialize(); |
+ |
+ scoped_ptr<gpu::CommandBufferService> command_buffer( |
+ new gpu::CommandBufferService(transfer_buffer_manager.get())); |
+ if (!command_buffer->Initialize()) |
+ return false; |
+ |
+ scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( |
+ NULL, NULL, new gpu::gles2::ShaderTranslatorCache, |
+ new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); |
+ |
+ scoped_ptr<gpu::gles2::GLES2Decoder> decoder( |
+ gpu::gles2::GLES2Decoder::Create(group.get())); |
+ if (!decoder.get()) |
+ return false; |
+ |
+ scoped_ptr<gpu::GpuScheduler> gpu_scheduler(new gpu::GpuScheduler( |
+ command_buffer.get(), decoder.get(), decoder.get())); |
+ |
+ decoder->set_engine(gpu_scheduler.get()); |
+ |
+ scoped_refptr<gfx::GLContext> gl_context(gfx::GLContext::CreateGLContext( |
+ nullptr, gl_surface, gfx::PreferDiscreteGpu)); |
+ if (!gl_context) |
+ return false; |
+ |
+ gl_context->MakeCurrent(gl_surface); |
+ |
+ gpu::gles2::ContextCreationAttribHelper helper; |
+ config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size); |
+ config_->GetAttrib(EGL_BLUE_SIZE, &helper.blue_size); |
+ config_->GetAttrib(EGL_GREEN_SIZE, &helper.green_size); |
+ config_->GetAttrib(EGL_RED_SIZE, &helper.red_size); |
+ config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size); |
+ config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size); |
+ config_->GetAttrib(EGL_SAMPLES, &helper.samples); |
+ config_->GetAttrib(EGL_SAMPLE_BUFFERS, &helper.sample_buffers); |
+ |
+ helper.buffer_preserved = false; |
+ helper.bind_generates_resource = kBindGeneratesResources; |
+ helper.fail_if_major_perf_caveat = false; |
+ helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory; |
+ helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2; |
+ std::vector<int32_t> attribs; |
+ helper.Serialize(&attribs); |
+ |
+ if (!decoder->Initialize(gl_surface, gl_context.get(), |
+ gl_surface->IsOffscreen(), gl_surface->GetSize(), |
+ gpu::gles2::DisallowedFeatures(), attribs)) { |
+ return false; |
+ } |
+ |
+ command_buffer->SetPutOffsetChangeCallback(base::Bind( |
+ &gpu::GpuScheduler::PutChanged, base::Unretained(gpu_scheduler.get()))); |
+ command_buffer->SetGetBufferChangeCallback(base::Bind( |
+ &gpu::GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler.get()))); |
+ |
+ scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper( |
+ new gpu::gles2::GLES2CmdHelper(command_buffer.get())); |
+ if (!gles2_cmd_helper->Initialize(kCommandBufferSize)) { |
+ decoder->Destroy(true); |
+ return false; |
+ } |
+ |
+ scoped_ptr<gpu::TransferBuffer> transfer_buffer( |
+ new gpu::TransferBuffer(gles2_cmd_helper.get())); |
+ |
+ gles2_cmd_helper_.reset(gles2_cmd_helper.release()); |
+ transfer_buffer_.reset(transfer_buffer.release()); |
+ command_buffer_.reset(command_buffer.release()); |
+ gpu_scheduler_.reset(gpu_scheduler.release()); |
+ decoder_.reset(decoder.release()); |
+ gl_context_ = gl_context.get(); |
+ |
+ scoped_ptr<gpu::gles2::GLES2Implementation> context( |
+ new gpu::gles2::GLES2Implementation( |
+ gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(), |
+ kBindGeneratesResources, kLoseContextWhenOutOfMemory, |
+ kSupportClientSideArrays, this)); |
+ |
+ if (!context->Initialize(kTransferBufferSize, kTransferBufferSize / 2, |
+ kTransferBufferSize * 2, |
+ gpu::gles2::GLES2Implementation::kNoLimit)) { |
+ Cleanup(); |
+ return false; |
+ } |
+ |
+ context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); |
+ context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); |
+ client_gl_context_.reset(context.release()); |
+ is_current_in_some_thread_ = true; |
+ return true; |
+} |
+ |
+gfx::GLContext* Context::gl_context() const { |
+ return gl_context_.get(); |
+} |
+ |
+gpu::gles2::GLES2Interface* Context::client_gl_context() const { |
+ return client_gl_context_.get(); |
+} |
+ |
+bool Context::ValidateAttributeList(const EGLint* attrib_list) { |
+ if (attrib_list) { |
+ for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) { |
+ switch (attrib_list[i]) { |
+ case EGL_CONTEXT_CLIENT_VERSION: |
+ break; |
+ default: |
+ return false; |
+ } |
+ } |
+ } |
+ return true; |
+} |
+ |
+gpu::Capabilities Context::GetCapabilities() { |
+ return decoder_->GetCapabilities(); |
+} |
+ |
+int32_t Context::CreateImage(ClientBuffer buffer, |
+ size_t width, |
+ size_t height, |
+ unsigned internalformat) { |
+ NOTIMPLEMENTED(); |
+ return -1; |
+} |
+ |
+void Context::DestroyImage(int32_t id) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+int32_t Context::CreateGpuMemoryBufferImage(size_t width, |
+ size_t height, |
+ unsigned internalformat, |
+ unsigned usage) { |
+ NOTIMPLEMENTED(); |
+ return -1; |
+} |
+ |
+void Context::SignalQuery(uint32_t query, const base::Closure& callback) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void Context::SetLock(base::Lock*) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+bool Context::IsGpuChannelLost() { |
+ NOTIMPLEMENTED(); |
+ return false; |
+} |
+ |
+void Context::EnsureWorkVisible() { |
+ // This is only relevant for out-of-process command buffers. |
+} |
+ |
+gpu::CommandBufferNamespace Context::GetNamespaceID() const { |
+ return gpu::CommandBufferNamespace::IN_PROCESS; |
+} |
+ |
+uint64_t Context::GetCommandBufferID() const { |
+ return 0; |
+} |
+ |
+int32_t Context::GetExtraCommandBufferData() const { |
+ return 0; |
+} |
+ |
+uint64_t Context::GenerateFenceSyncRelease() { |
+ return display_->GenerateFenceSyncRelease(); |
+} |
+ |
+bool Context::IsFenceSyncRelease(uint64_t release) { |
+ return display_->IsFenceSyncRelease(release); |
+} |
+ |
+bool Context::IsFenceSyncFlushed(uint64_t release) { |
+ return display_->IsFenceSyncFlushed(release); |
+} |
+ |
+bool Context::IsFenceSyncFlushReceived(uint64_t release) { |
+ return display_->IsFenceSyncFlushReceived(release); |
+} |
+ |
+void Context::SignalSyncToken(const gpu::SyncToken& sync_token, |
+ const base::Closure& callback) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { |
+ return false; |
+} |
+ |
+void Context::Cleanup() { |
+ client_gl_context_.reset(); |
+ gl_context_ = nullptr; |
+ |
+ transfer_buffer_.reset(); |
+ gpu_scheduler_.reset(); |
+ if (decoder_) |
+ decoder_->Destroy(false); |
+ gles2_cmd_helper_.reset(); |
+ command_buffer_.reset(); |
+} |
+ |
+void Context::MarkContextLost() { |
+ if (!decoder_) |
+ return; |
+ decoder_->MarkContextLost(gpu::error::kMakeCurrentFailed); |
+} |
+ |
+bool Context::WasContextLost() const { |
+ return decoder_ && decoder_->WasContextLost(); |
+} |
+ |
+bool Context::IsCompatibleSurface(gfx::GLSurface* gl_surface) { |
+ EGLint value = EGL_NONE; |
+ config_->GetAttrib(EGL_SURFACE_TYPE, &value); |
+ bool config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0; |
+ return gl_surface->IsOffscreen() == config_is_offscreen; |
+} |
+ |
+} // namespace egl |