| 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
|
|
|