| 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 f12c94257376c4a3298655a9b4ca082964b98902..b4e01587fd4144d0272380f49a9b153802849211 100644
|
| --- a/gpu/gles2_conform_support/egl/display.cc
|
| +++ b/gpu/gles2_conform_support/egl/display.cc
|
| @@ -4,134 +4,115 @@
|
|
|
| #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/command_line.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/shared_memory_limits.h"
|
| -#include "gpu/command_buffer/client/transfer_buffer.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/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),
|
| - gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()),
|
| - 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),
|
| + next_create_window_surface_creates_pbuffer_(false),
|
| + window_surface_pbuffer_width_(0),
|
| + window_surface_pbuffer_height_(0) {
|
| }
|
|
|
| Display::~Display() {
|
| - gles2::Terminate();
|
| -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
|
| - ReleaseAtExitManager();
|
| -#endif
|
| + surfaces_.clear();
|
| + contexts_.clear();
|
| }
|
| -
|
| -bool Display::Initialize() {
|
| - gles2::Initialize();
|
| - is_initialized_ = true;
|
| - return true;
|
| +void Display::SetNextCreateWindowSurfaceCreatesPBuffer(EGLint width,
|
| + EGLint height) {
|
| + next_create_window_surface_creates_pbuffer_ = true;
|
| + window_surface_pbuffer_width_ = width;
|
| + window_surface_pbuffer_height_ = height;
|
| }
|
|
|
| -bool Display::IsValidConfig(EGLConfig config) {
|
| - return (config != NULL) && (config == config_.get());
|
| -}
|
| +EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) {
|
| + base::AutoLock auto_lock(lock_);
|
| + is_initialized_ = true;
|
|
|
| -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();
|
| + for (const auto& context : contexts_)
|
| + context->MarkDestroyed();
|
| + 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].get();
|
| + }
|
| + ++*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));
|
| + for (size_t i = 0; i < count; ++i)
|
| + configs[i] = configs_[i].get();
|
| + return ts->ReturnSuccess(EGL_TRUE);
|
| }
|
|
|
| bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
|
| @@ -143,241 +124,233 @@ bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
|
| #endif // OS_WIN
|
| }
|
|
|
| -bool Display::IsValidSurface(EGLSurface surface) {
|
| - return (surface != NULL) && (surface == surface_.get());
|
| +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;
|
| + }
|
| + }
|
| + }
|
| + return DoCreatePbufferSurface(ts, config, width, height);
|
| +}
|
| +
|
| +EGLSurface Display::DoCreatePbufferSurface(ThreadState* ts,
|
| + const Config* config,
|
| + EGLint width,
|
| + EGLint height) {
|
| + lock_.AssertAcquired();
|
| + 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);
|
| + surfaces_.emplace_back(new Surface(gl_surface.get(), config));
|
| + return ts->ReturnSuccess<EGLSurface>(surfaces_.back().get());
|
| }
|
|
|
| -EGLSurface Display::CreateWindowSurface(EGLConfig config,
|
| +EGLSurface Display::CreateWindowSurface(ThreadState* ts,
|
| + EGLConfig cfg,
|
| EGLNativeWindowType win,
|
| const EGLint* attrib_list) {
|
| - if (surface_ != NULL) {
|
| - // We do not support more than one window surface.
|
| - return EGL_NO_SURFACE;
|
| + 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 (!next_create_window_surface_creates_pbuffer_ && !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);
|
| + if (next_create_window_surface_creates_pbuffer_) {
|
| + EGLSurface result = DoCreatePbufferSurface(ts, config,
|
| + window_surface_pbuffer_width_,
|
| + window_surface_pbuffer_height_);
|
| + next_create_window_surface_creates_pbuffer_ = false;
|
| + window_surface_pbuffer_width_ = 0;
|
| + window_surface_pbuffer_height_ = 0;
|
| + return result;
|
| }
|
| -
|
| - {
|
| - gpu::TransferBufferManager* manager =
|
| - new gpu::TransferBufferManager(nullptr);
|
| - transfer_buffer_manager_ = manager;
|
| - manager->Initialize();
|
| - }
|
| - std::unique_ptr<gpu::CommandBufferService> command_buffer(
|
| - new gpu::CommandBufferService(transfer_buffer_manager_.get()));
|
| -
|
| - scoped_refptr<gpu::gles2::FeatureInfo> feature_info(
|
| - new gpu::gles2::FeatureInfo(gpu_driver_bug_workarounds_));
|
| - scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
|
| - gpu_preferences_, NULL, NULL,
|
| - new gpu::gles2::ShaderTranslatorCache(gpu_preferences_),
|
| - new gpu::gles2::FramebufferCompletenessCache, feature_info, true));
|
| -
|
| - decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get()));
|
| - if (!decoder_.get())
|
| - return EGL_NO_SURFACE;
|
| -
|
| - executor_.reset(
|
| - new gpu::CommandExecutor(command_buffer.get(), decoder_.get(), NULL));
|
| -
|
| - decoder_->set_engine(executor_.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;
|
| + scoped_refptr<gfx::GLSurface> gl_surface;
|
| + gl_surface = gfx::GLSurface::CreateViewGLSurface(win);
|
| + if (!gl_surface)
|
| + return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
|
| + surfaces_.emplace_back(new Surface(gl_surface.get(), config));
|
| + return ts->ReturnSuccess(surfaces_.back().get());
|
| +}
|
| +
|
| +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(), nullptr,
|
| + nullptr);
|
| + accr.SetCurrent(nullptr, nullptr);
|
| }
|
| -
|
| - command_buffer->SetPutOffsetChangeCallback(base::Bind(
|
| - &gpu::CommandExecutor::PutChanged, base::Unretained(executor_.get())));
|
| - command_buffer->SetGetBufferChangeCallback(base::Bind(
|
| - &gpu::CommandExecutor::SetGetBuffer, base::Unretained(executor_.get())));
|
| -
|
| - std::unique_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper(
|
| - new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
|
| - if (!cmd_helper->Initialize(kCommandBufferSize))
|
| - return NULL;
|
| -
|
| - std::unique_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();
|
| -}
|
| -
|
| -void Display::DestroySurface(EGLSurface surface) {
|
| - DCHECK(IsValidSurface(surface));
|
| - executor_.reset();
|
| - if (decoder_.get()) {
|
| - decoder_->Destroy(true);
|
| - }
|
| - 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 : nullptr,
|
| + new_context, new_context ? new_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);
|
| + if (!ts->current_context()->SwapBuffers(surface))
|
| + ts->ReturnError(EGL_CONTEXT_LOST, EGL_FALSE);
|
| + 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::SharedMemoryLimits::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;
|
| -}
|
| -
|
| -void Display::SetGpuControlClient(gpu::GpuControlClient*) {
|
| - // The client is not currently called, so don't store it.
|
| -}
|
| -
|
| -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();
|
| -}
|
| -
|
| -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);
|
| + (*it)->MarkDestroyed();
|
| + 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_;
|
| }
|
|
|
| @@ -389,13 +362,41 @@ 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() {
|
| + lock_.AssertAcquired();
|
| + 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].reset(new Config(EGL_WINDOW_BIT));
|
| + configs_[1].reset(new Config(EGL_PBUFFER_BIT));
|
| + }
|
| +}
|
| +
|
| +const Config* Display::GetConfig(EGLConfig cfg) {
|
| + lock_.AssertAcquired();
|
| + for (const auto& config : configs_) {
|
| + if (config.get() == cfg)
|
| + return config.get();
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| +Surface* Display::GetSurface(EGLSurface surface) {
|
| + lock_.AssertAcquired();
|
| + 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) {
|
| + lock_.AssertAcquired();
|
| + auto it = std::find(contexts_.begin(), contexts_.end(), context);
|
| + if (it == contexts_.end())
|
| + return nullptr;
|
| + return it->get();
|
| }
|
|
|
| } // namespace egl
|
|
|