Chromium Code Reviews| Index: gpu/gles2_conform_support/egl/display.cc |
| diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc |
| index 4b010f24152222e7c39d9d9ecebe6798ac47da14..38ff51d5aa3a2cf460de1d6896d18381e73dabe9 100644 |
| --- a/gpu/gles2_conform_support/egl/display.cc |
| +++ b/gpu/gles2_conform_support/egl/display.cc |
| @@ -4,133 +4,106 @@ |
| #include "gpu/gles2_conform_support/egl/display.h" |
| -#include <stddef.h> |
| -#include <stdint.h> |
| - |
| -#include <vector> |
| -#include "base/at_exit.h" |
| -#include "base/bind.h" |
| -#include "base/bind_helpers.h" |
| -#include "base/lazy_instance.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/context.h" |
| #include "gpu/gles2_conform_support/egl/surface.h" |
| -#include "gpu/gles2_conform_support/egl/test_support.h" |
| - |
| -namespace { |
| -const int32_t kCommandBufferSize = 1024 * 1024; |
| -const int32_t kTransferBufferSize = 512 * 1024; |
| -} |
| +#include "gpu/gles2_conform_support/egl/thread_state.h" |
| namespace egl { |
| -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) |
| -// egl::Display is used for comformance tests and command_buffer_gles. We only |
| -// need the exit manager for the command_buffer_gles library. |
| -// TODO(hendrikw): Find a cleaner solution for this. |
| -namespace { |
| -base::LazyInstance<base::Lock>::Leaky g_exit_manager_lock; |
| -int g_exit_manager_use_count; |
| -base::AtExitManager* g_exit_manager; |
| -void RefAtExitManager() { |
| - base::AutoLock lock(g_exit_manager_lock.Get()); |
| -#if defined(COMPONENT_BUILD) |
| - if (g_command_buffer_gles_has_atexit_manager) { |
| - return; |
| - } |
| -#endif |
| - if (g_exit_manager_use_count == 0) { |
| - g_exit_manager = new base::AtExitManager; |
| - } |
| - ++g_exit_manager_use_count; |
| -} |
| -void ReleaseAtExitManager() { |
| - base::AutoLock lock(g_exit_manager_lock.Get()); |
| -#if defined(COMPONENT_BUILD) |
| - if (g_command_buffer_gles_has_atexit_manager) { |
| - return; |
| - } |
| -#endif |
| - --g_exit_manager_use_count; |
| - if (g_exit_manager_use_count == 0) { |
| - delete g_exit_manager; |
| - g_exit_manager = nullptr; |
| - } |
| -} |
| -} |
| -#endif |
| - |
| -Display::Display(EGLNativeDisplayType display_id) |
| - : display_id_(display_id), |
| - is_initialized_(false), |
| - create_offscreen_(false), |
| - create_offscreen_width_(0), |
| - create_offscreen_height_(0), |
| - next_fence_sync_release_(1) { |
| -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) |
| - RefAtExitManager(); |
| -#endif |
| + |
| +Display::Display() : is_initialized_(false) { |
| + configs_[0] = nullptr; |
| + configs_[1] = nullptr; |
| } |
| Display::~Display() { |
| - gles2::Terminate(); |
| -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) |
| - ReleaseAtExitManager(); |
| -#endif |
| + surfaces_.clear(); |
| + contexts_.clear(); |
| + delete configs_[0]; |
| + delete configs_[1]; |
|
piman
2016/02/23 23:37:16
use scoped_ptr<Config>[2] instead?
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| } |
| -bool Display::Initialize() { |
| - gles2::Initialize(); |
| +EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) { |
| + base::AutoLock auto_lock(lock_); |
| is_initialized_ = true; |
| - return true; |
| -} |
| -bool Display::IsValidConfig(EGLConfig config) { |
| - return (config != NULL) && (config == config_.get()); |
| -} |
| - |
| -bool Display::ChooseConfigs(EGLConfig* configs, |
| - EGLint config_size, |
| - EGLint* num_config) { |
| - // TODO(alokp): Find out a way to find all configs. CommandBuffer currently |
| - // does not support finding or choosing configs. |
| - *num_config = 1; |
| - if (configs != NULL) { |
| - if (config_ == NULL) { |
| - config_.reset(new Config); |
| - } |
| - configs[0] = config_.get(); |
| + if (major) |
| + *major = 1; |
| + if (minor) |
| + *minor = 4; |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLBoolean Display::Terminate(ThreadState* ts) { |
| + base::AutoLock auto_lock(lock_); |
| + is_initialized_ = false; |
| + surfaces_.clear(); |
| + contexts_.clear(); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +const char* Display::QueryString(ThreadState* ts, EGLint name) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError<const char*>(EGL_NOT_INITIALIZED, nullptr); |
| + switch (name) { |
| + case EGL_CLIENT_APIS: |
| + return ts->ReturnSuccess("OpenGL_ES"); |
| + case EGL_EXTENSIONS: |
| + return ts->ReturnSuccess(""); |
| + case EGL_VENDOR: |
| + return ts->ReturnSuccess("Google Inc."); |
| + case EGL_VERSION: |
| + return ts->ReturnSuccess("1.4"); |
| + default: |
| + return ts->ReturnError<const char*>(EGL_BAD_PARAMETER, nullptr); |
| } |
| - return true; |
| } |
| -bool Display::GetConfigs(EGLConfig* configs, |
| - EGLint config_size, |
| - EGLint* num_config) { |
| - // TODO(alokp): Find out a way to find all configs. CommandBuffer currently |
| - // does not support finding or choosing configs. |
| - *num_config = 1; |
| - if (configs != NULL) { |
| - if (config_ == NULL) { |
| - config_.reset(new Config); |
| +EGLBoolean Display::ChooseConfig(ThreadState* ts, |
| + const EGLint* attrib_list, |
| + EGLConfig* configs, |
| + EGLint config_size, |
| + EGLint* num_config) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + if (num_config == nullptr) |
| + return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE); |
| + if (!Config::ValidateAttributeList(attrib_list)) |
| + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE); |
| + InitializeConfigsIfNeeded(); |
| + if (!configs) |
| + config_size = 0; |
| + *num_config = 0; |
| + for (size_t i = 0; i < arraysize(configs_); ++i) { |
| + if (configs_[i]->matches(attrib_list)) { |
| + if (*num_config < config_size) { |
| + configs[*num_config] = configs_[i]; |
| + } |
| + ++*num_config; |
| } |
| - configs[0] = config_.get(); |
| } |
| - return true; |
| -} |
| - |
| -bool Display::GetConfigAttrib(EGLConfig config, |
| - EGLint attribute, |
| - EGLint* value) { |
| - const egl::Config* cfg = static_cast<egl::Config*>(config); |
| - return cfg->GetAttrib(attribute, value); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLBoolean Display::GetConfigs(ThreadState* ts, |
| + EGLConfig* configs, |
| + EGLint config_size, |
| + EGLint* num_config) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + if (num_config == nullptr) |
| + return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE); |
| + InitializeConfigsIfNeeded(); |
| + if (!configs) |
| + config_size = 0; |
| + *num_config = arraysize(configs_); |
| + size_t count = |
| + std::min(arraysize(configs_), static_cast<size_t>(config_size)); |
| + std::copy(configs_, configs_ + count, configs); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| } |
| bool Display::IsValidNativeWindow(EGLNativeWindowType win) { |
| @@ -142,246 +115,217 @@ bool Display::IsValidNativeWindow(EGLNativeWindowType win) { |
| #endif // OS_WIN |
| } |
| -bool Display::IsValidSurface(EGLSurface surface) { |
| - return (surface != NULL) && (surface == surface_.get()); |
| -} |
| - |
| -EGLSurface Display::CreateWindowSurface(EGLConfig config, |
| - EGLNativeWindowType win, |
| - const EGLint* attrib_list) { |
| - if (surface_ != NULL) { |
| - // We do not support more than one window surface. |
| - return EGL_NO_SURFACE; |
| - } |
| - |
| - { |
| - gpu::TransferBufferManager* manager = |
| - new gpu::TransferBufferManager(nullptr); |
| - transfer_buffer_manager_ = manager; |
| - manager->Initialize(); |
| - } |
| - scoped_ptr<gpu::CommandBufferService> command_buffer( |
| - new gpu::CommandBufferService(transfer_buffer_manager_.get())); |
| - if (!command_buffer->Initialize()) |
| - return NULL; |
| - |
| - scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( |
| - NULL, NULL, new gpu::gles2::ShaderTranslatorCache, |
| - new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); |
| - |
| - decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); |
| - if (!decoder_.get()) |
| - return EGL_NO_SURFACE; |
| - |
| - gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), |
| - decoder_.get(), |
| - NULL)); |
| - |
| - decoder_->set_engine(gpu_scheduler_.get()); |
| - gfx::Size size(create_offscreen_width_, create_offscreen_height_); |
| - if (create_offscreen_) { |
| - gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); |
| - create_offscreen_ = false; |
| - create_offscreen_width_ = 0; |
| - create_offscreen_height_ = 0; |
| - } else { |
| - gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); |
| - } |
| - if (!gl_surface_.get()) |
| - return EGL_NO_SURFACE; |
| - |
| - gl_context_ = gfx::GLContext::CreateGLContext(NULL, |
| - gl_surface_.get(), |
| - gfx::PreferDiscreteGpu); |
| - if (!gl_context_.get()) |
| - return EGL_NO_SURFACE; |
| - |
| - gl_context_->MakeCurrent(gl_surface_.get()); |
| - |
| - EGLint depth_size = 0; |
| - EGLint alpha_size = 0; |
| - EGLint stencil_size = 0; |
| - GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); |
| - GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); |
| - GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); |
| - std::vector<int32_t> attribs; |
| - attribs.push_back(EGL_DEPTH_SIZE); |
| - attribs.push_back(depth_size); |
| - attribs.push_back(EGL_ALPHA_SIZE); |
| - attribs.push_back(alpha_size); |
| - attribs.push_back(EGL_STENCIL_SIZE); |
| - attribs.push_back(stencil_size); |
| - // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null |
| - attribs.push_back(EGL_NONE); |
| - |
| - if (!decoder_->Initialize(gl_surface_.get(), |
| - gl_context_.get(), |
| - gl_surface_->IsOffscreen(), |
| - size, |
| - gpu::gles2::DisallowedFeatures(), |
| - attribs)) { |
| - return EGL_NO_SURFACE; |
| +EGLBoolean Display::GetConfigAttrib(ThreadState* ts, |
| + EGLConfig cfg, |
| + EGLint attribute, |
| + EGLint* value) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + const egl::Config* config = GetConfig(cfg); |
| + if (!config) |
| + return ts->ReturnError(EGL_BAD_CONFIG, EGL_FALSE); |
| + if (!config->GetAttrib(attribute, value)) |
| + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLSurface Display::CreatePbufferSurface(ThreadState* ts, |
| + EGLConfig cfg, |
| + const EGLint* attrib_list) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
| + const egl::Config* config = GetConfig(cfg); |
| + if (!config) |
| + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); |
| + EGLint value = EGL_NONE; |
| + config->GetAttrib(EGL_SURFACE_TYPE, &value); |
| + if ((value & EGL_PBUFFER_BIT) == 0) |
| + return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_SURFACE); |
| + if (!egl::Surface::ValidatePbufferAttributeList(attrib_list)) |
| + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); |
| + |
| + int width = 1; |
| + int height = 1; |
| + if (attrib_list) { |
| + for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) { |
| + switch (attr[0]) { |
| + case EGL_WIDTH: |
| + width = attr[1]; |
| + break; |
| + case EGL_HEIGHT: |
| + height = attr[1]; |
| + break; |
| + } |
| + } |
| } |
| + scoped_refptr<gfx::GLSurface> gl_surface; |
| + gl_surface = |
| + gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(width, height)); |
| + if (!gl_surface) |
| + return ts->ReturnError(EGL_BAD_ALLOC, nullptr); |
| + Surface* surface = new Surface(gl_surface.get()); |
|
piman
2016/02/23 23:37:17
nit: scoped_refptr<Surface>
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| - 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> cmd_helper( |
| - new gpu::gles2::GLES2CmdHelper(command_buffer.get())); |
| - if (!cmd_helper->Initialize(kCommandBufferSize)) |
| - return NULL; |
| - |
| - scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer( |
| - cmd_helper.get())); |
| - |
| - command_buffer_.reset(command_buffer.release()); |
| - transfer_buffer_.reset(transfer_buffer.release()); |
| - gles2_cmd_helper_.reset(cmd_helper.release()); |
| - surface_.reset(new Surface(win)); |
| - |
| - return surface_.get(); |
| + surfaces_.emplace_back(surface); |
| + return ts->ReturnSuccess<EGLSurface>(surface); |
| } |
| -void Display::DestroySurface(EGLSurface surface) { |
| - DCHECK(IsValidSurface(surface)); |
| - gpu_scheduler_.reset(); |
| - if (decoder_.get()) { |
| - decoder_->Destroy(true); |
| +EGLSurface Display::CreateWindowSurface(ThreadState* ts, |
| + EGLConfig cfg, |
| + EGLNativeWindowType win, |
| + const EGLint* attrib_list) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
| + const egl::Config* config = GetConfig(cfg); |
| + if (!config) |
| + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); |
| + EGLint value = EGL_NONE; |
| + config->GetAttrib(EGL_SURFACE_TYPE, &value); |
| + if ((value & EGL_WINDOW_BIT) == 0) |
| + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); |
| + if (!IsValidNativeWindow(win)) |
| + return ts->ReturnError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); |
| + if (!Surface::ValidateWindowAttributeList(attrib_list)) |
| + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); |
| + scoped_refptr<gfx::GLSurface> gl_surface; |
| + gl_surface = gfx::GLSurface::CreateViewGLSurface(win); |
| + if (!gl_surface) |
| + return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
| + Surface* surface = new Surface(gl_surface.get()); |
|
piman
2016/02/23 23:37:17
nit: scoped_refptr<Surface>
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| + surfaces_.emplace_back(surface); |
| + return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
|
Kimmo Kinnunen
2016/02/24 07:33:27
There was a bit of an error here, changed this too
|
| +} |
| + |
| +EGLBoolean Display::DestroySurface(ThreadState* ts, EGLSurface sfe) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + auto it = std::find(surfaces_.begin(), surfaces_.end(), sfe); |
| + if (it == surfaces_.end()) |
| + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); |
| + surfaces_.erase(it); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLBoolean Display::ReleaseCurrent(ThreadState* ts) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnSuccess(EGL_TRUE); |
| + ThreadState::AutoCurrentContextRestore accr(ts); |
| + if (ts->current_context()) { |
| + Context::MakeCurrent(ts->current_context(), |
| + ts->current_surface()->gl_surface(), nullptr, nullptr); |
| + accr.SetCurrent(nullptr, nullptr); |
| } |
| - decoder_.reset(); |
| - gl_surface_ = NULL; |
| - gl_context_ = NULL; |
| - surface_.reset(); |
| -} |
| - |
| -void Display::SwapBuffers(EGLSurface surface) { |
| - DCHECK(IsValidSurface(surface)); |
| - context_->SwapBuffers(); |
| -} |
| - |
| -bool Display::IsValidContext(EGLContext ctx) { |
| - return (ctx != NULL) && (ctx == context_.get()); |
| -} |
| - |
| -EGLContext Display::CreateContext(EGLConfig config, |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLBoolean Display::MakeCurrent(ThreadState* ts, |
| + EGLSurface draw, |
| + EGLSurface read, |
| + EGLSurface ctx) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + ThreadState::AutoCurrentContextRestore accr(ts); |
| + // Client might have called use because it changed some other gl binding |
| + // global state. For example, the client might have called eglMakeCurrent on |
| + // the same EGL as what command buffer uses. The client probably knows that |
| + // this invalidates the internal state of command buffer, too. So reset the |
| + // current context with accr in any case, regardless whether context or |
| + // surface pointer changes. |
| + Surface* new_surface = GetSurface(draw); |
| + if (!new_surface) |
| + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); |
| + new_surface = GetSurface(read); |
| + if (!new_surface) |
| + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); |
| + egl::Context* new_context = GetContext(ctx); |
| + if (!new_context) |
| + return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE); |
| + if (draw != read) |
| + return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE); |
| + |
| + Surface* current_surface = ts->current_surface(); |
| + Context* current_context = ts->current_context(); |
| + |
| + if (current_context != new_context && |
| + new_context->is_current_in_some_thread()) |
| + return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE); |
| + |
| + if (current_surface != new_surface && |
| + new_surface->is_current_in_some_thread()) |
| + return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE); |
| + |
| + if (!Context::MakeCurrent( |
| + current_context, |
| + current_context ? current_surface->gl_surface() : nullptr, |
| + new_context, new_context ? new_surface->gl_surface() : nullptr)) |
| + return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE); |
| + |
| + accr.SetCurrent(new_surface, new_context); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLBoolean Display::SwapBuffers(ThreadState* ts, EGLSurface sfe) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + egl::Surface* surface = GetSurface(sfe); |
| + if (!surface) |
| + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); |
| + if (ts->current_surface() != surface) |
| + return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); |
| + ts->current_context()->FlushAndSwapBuffers(surface->gl_surface()); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| +} |
| + |
| +EGLContext Display::CreateContext(ThreadState* ts, |
| + EGLConfig cfg, |
| EGLContext share_ctx, |
| const EGLint* attrib_list) { |
| - DCHECK(IsValidConfig(config)); |
| - // TODO(alokp): Add support for shared contexts. |
| - if (share_ctx != NULL) |
| - return EGL_NO_CONTEXT; |
| - |
| - DCHECK(command_buffer_ != NULL); |
| - DCHECK(transfer_buffer_.get()); |
| - |
| - bool bind_generates_resources = true; |
| - bool lose_context_when_out_of_memory = false; |
| - bool support_client_side_arrays = true; |
| - |
| - context_.reset( |
| - new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), |
| - NULL, |
| - transfer_buffer_.get(), |
| - bind_generates_resources, |
| - lose_context_when_out_of_memory, |
| - support_client_side_arrays, |
| - this)); |
| - |
| - if (!context_->Initialize( |
| - kTransferBufferSize, |
| - kTransferBufferSize / 2, |
| - kTransferBufferSize * 2, |
| - gpu::gles2::GLES2Implementation::kNoLimit)) { |
| - return EGL_NO_CONTEXT; |
| - } |
| - |
| - context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); |
| - context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); |
| - |
| - return context_.get(); |
| -} |
| - |
| -void Display::DestroyContext(EGLContext ctx) { |
| - DCHECK(IsValidContext(ctx)); |
| - context_.reset(); |
| - transfer_buffer_.reset(); |
| -} |
| - |
| -bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { |
| - if (ctx == EGL_NO_CONTEXT) { |
| - gles2::SetGLContext(NULL); |
| - } else { |
| - DCHECK(IsValidSurface(draw)); |
| - DCHECK(IsValidSurface(read)); |
| - DCHECK(IsValidContext(ctx)); |
| - gles2::SetGLContext(context_.get()); |
| - gl_context_->MakeCurrent(gl_surface_.get()); |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_CONTEXT); |
| + if (share_ctx != EGL_NO_CONTEXT) { |
| + egl::Context* share_context = GetContext(share_ctx); |
| + if (!share_context) |
| + return ts->ReturnError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); |
| + // TODO(alokp): Add support for shared contexts. |
| + return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_CONTEXT); |
| } |
| - return true; |
| -} |
| - |
| -gpu::Capabilities Display::GetCapabilities() { |
| - return decoder_->GetCapabilities(); |
| -} |
| - |
| -int32_t Display::CreateImage(ClientBuffer buffer, |
| - size_t width, |
| - size_t height, |
| - unsigned internalformat) { |
| - NOTIMPLEMENTED(); |
| - return -1; |
| -} |
| - |
| -void Display::DestroyImage(int32_t id) { |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -int32_t Display::CreateGpuMemoryBufferImage(size_t width, |
| - size_t height, |
| - unsigned internalformat, |
| - unsigned usage) { |
| - NOTIMPLEMENTED(); |
| - return -1; |
| -} |
| - |
| -void Display::SignalQuery(uint32_t query, const base::Closure& callback) { |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -void Display::SetLock(base::Lock*) { |
| - NOTIMPLEMENTED(); |
| -} |
| - |
| -bool Display::IsGpuChannelLost() { |
| - NOTIMPLEMENTED(); |
| - return false; |
| -} |
| - |
| -void Display::EnsureWorkVisible() { |
| - // This is only relevant for out-of-process command buffers. |
| -} |
| - |
| -gpu::CommandBufferNamespace Display::GetNamespaceID() const { |
| - return gpu::CommandBufferNamespace::IN_PROCESS; |
| -} |
| - |
| -gpu::CommandBufferId Display::GetCommandBufferID() const { |
| - return gpu::CommandBufferId(); |
| -} |
| - |
| -int32_t Display::GetExtraCommandBufferData() const { |
| - return 0; |
| + if (!egl::Context::ValidateAttributeList(attrib_list)) |
| + return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); |
| + const egl::Config* config = GetConfig(cfg); |
| + if (!config) |
| + return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_CONTEXT); |
| + scoped_refptr<Context> context(new Context(this, config)); |
| + if (!context) |
| + return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); |
| + contexts_.emplace_back(context.get()); |
| + return ts->ReturnSuccess<EGLContext>(context.get()); |
| +} |
| + |
| +EGLBoolean Display::DestroyContext(ThreadState* ts, EGLContext ctx) { |
| + base::AutoLock auto_lock(lock_); |
| + if (!is_initialized_) |
| + return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); |
| + auto it = std::find(contexts_.begin(), contexts_.end(), ctx); |
| + if (it == contexts_.end()) |
| + return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE); |
| + contexts_.erase(it); |
| + return ts->ReturnSuccess(EGL_TRUE); |
| } |
| uint64_t Display::GenerateFenceSyncRelease() { |
| + base::AutoLock auto_lock(lock_); |
| return next_fence_sync_release_++; |
| } |
| bool Display::IsFenceSyncRelease(uint64_t release) { |
| + base::AutoLock auto_lock(lock_); |
| return release > 0 && release < next_fence_sync_release_; |
| } |
| @@ -393,13 +337,37 @@ bool Display::IsFenceSyncFlushReceived(uint64_t release) { |
| return IsFenceSyncRelease(release); |
| } |
| -void Display::SignalSyncToken(const gpu::SyncToken& sync_token, |
| - const base::Closure& callback) { |
| - NOTIMPLEMENTED(); |
| +void Display::InitializeConfigsIfNeeded() { |
|
piman
2016/02/23 23:37:17
nit: lock_.AssertAcquired();
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| + if (!configs_[0]) { |
| + // The interface offers separate configs for window and pbuffer. |
| + // This way we can record the client intention at context creation time. |
| + // The GL implementation (gfx::GLContext and gfx::GLSurface) needs this |
| + // distinction when creating a context. |
| + configs_[0] = new Config(EGL_WINDOW_BIT); |
| + configs_[1] = new Config(EGL_PBUFFER_BIT); |
| + } |
| +} |
| + |
| +const Config* Display::GetConfig(EGLConfig cfg) { |
|
piman
2016/02/23 23:37:16
nit: lock_.AssertAcquired();
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| + for (const Config* config : configs_) { |
| + if (config == cfg) |
| + return config; |
| + } |
| + return nullptr; |
| +} |
| + |
| +Surface* Display::GetSurface(EGLSurface surface) { |
|
piman
2016/02/23 23:37:17
nit: lock_.AssertAcquired();
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| + auto it = std::find(surfaces_.begin(), surfaces_.end(), surface); |
| + if (it == surfaces_.end()) |
| + return nullptr; |
| + return it->get(); |
| } |
| -bool Display::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { |
| - return false; |
| +Context* Display::GetContext(EGLContext context) { |
|
piman
2016/02/23 23:37:16
nit: lock_.AssertAcquired();
Kimmo Kinnunen
2016/02/24 07:33:27
Done.
|
| + auto it = std::find(contexts_.begin(), contexts_.end(), context); |
| + if (it == contexts_.end()) |
| + return nullptr; |
| + return it->get(); |
| } |
| } // namespace egl |