| 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 2e2e349ac301a45427e27241e9eacd7b57011b98..db8a237d0434c6a0c3b842eb2e7f260dce535993 100644
|
| --- a/gpu/gles2_conform_support/egl/display.cc
|
| +++ b/gpu/gles2_conform_support/egl/display.cc
|
| @@ -4,115 +4,134 @@
|
|
|
| #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/thread_state.h"
|
| +#include "gpu/gles2_conform_support/egl/test_support.h"
|
| +
|
| +namespace {
|
| +const int32_t kCommandBufferSize = 1024 * 1024;
|
| +const int32_t kTransferBufferSize = 512 * 1024;
|
| +}
|
|
|
| namespace egl {
|
| -
|
| -Display::Display()
|
| - : is_initialized_(false),
|
| - next_create_window_surface_creates_pbuffer_(false),
|
| - window_surface_pbuffer_width_(0),
|
| - window_surface_pbuffer_height_(0) {
|
| +#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() {
|
| - surfaces_.clear();
|
| - contexts_.clear();
|
| -}
|
| -void Display::SetNextCreateWindowSurfaceCreatesPBuffer(EGLint width,
|
| - EGLint height) {
|
| - next_create_window_surface_creates_pbuffer_ = true;
|
| - window_surface_pbuffer_width_ = width;
|
| - window_surface_pbuffer_height_ = height;
|
| -}
|
| -
|
| -EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) {
|
| - base::AutoLock auto_lock(lock_);
|
| + gles2::Terminate();
|
| +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
|
| + ReleaseAtExitManager();
|
| +#endif
|
| +}
|
| +
|
| +bool Display::Initialize() {
|
| + gles2::Initialize();
|
| is_initialized_ = true;
|
| -
|
| - 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);
|
| - }
|
| -}
|
| -
|
| -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;
|
| + 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);
|
| }
|
| - }
|
| - 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);
|
| + configs[0] = config_.get();
|
| + }
|
| + 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);
|
| + }
|
| + 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);
|
| }
|
|
|
| bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
|
| @@ -124,232 +143,248 @@
|
| #endif // OS_WIN
|
| }
|
|
|
| -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(ThreadState* ts,
|
| - EGLConfig cfg,
|
| +bool Display::IsValidSurface(EGLSurface surface) {
|
| + return (surface != NULL) && (surface == surface_.get());
|
| +}
|
| +
|
| +EGLSurface Display::CreateWindowSurface(EGLConfig config,
|
| 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 (!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;
|
| - }
|
| - 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);
|
| - }
|
| - 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,
|
| + 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();
|
| + }
|
| + std::unique_ptr<gpu::CommandBufferService> command_buffer(
|
| + new gpu::CommandBufferService(transfer_buffer_manager_.get()));
|
| + if (!command_buffer->Initialize())
|
| + return NULL;
|
| +
|
| + 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;
|
| + }
|
| +
|
| + 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,
|
| EGLContext share_ctx,
|
| const EGLint* attrib_list) {
|
| - 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);
|
| - }
|
| - 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);
|
| + 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());
|
| + }
|
| + 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();
|
| +}
|
| +
|
| +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;
|
| }
|
|
|
| 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_;
|
| }
|
|
|
| @@ -361,41 +396,13 @@
|
| return IsFenceSyncRelease(release);
|
| }
|
|
|
| -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();
|
| -}
|
| -
|
| -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();
|
| +void Display::SignalSyncToken(const gpu::SyncToken& sync_token,
|
| + const base::Closure& callback) {
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +bool Display::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) {
|
| + return false;
|
| }
|
|
|
| } // namespace egl
|
|
|