Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(805)

Unified Diff: gpu/gles2_conform_support/egl/thread_state.cc

Issue 1714883002: command_buffer_gles2: Implement EGL default Display as a global object (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@command_buffer_gles2-multiple-contexts
Patch Set: rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/gles2_conform_support/egl/thread_state.h ('k') | gpu/gles2_conform_support/gles2_conform_support.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/gles2_conform_support/egl/thread_state.cc
diff --git a/gpu/gles2_conform_support/egl/thread_state.cc b/gpu/gles2_conform_support/egl/thread_state.cc
new file mode 100644
index 0000000000000000000000000000000000000000..41593cb1d4a1dc3d2ba1aa2a567b9cf9ff52ffeb
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/thread_state.cc
@@ -0,0 +1,198 @@
+// 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/thread_state.h"
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/lazy_instance.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/common/thread_local.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_util.h"
+#include "gpu/gles2_conform_support/egl/context.h"
+#include "gpu/gles2_conform_support/egl/display.h"
+#include "gpu/gles2_conform_support/egl/surface.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+
+// Thread local key for ThreadState instance. Accessed when holding g_egl_lock
+// only, since the initialization can not be Guaranteed otherwise. Not in
+// anonymous namespace due to Mac OS X 10.6 linker. See gles2_lib.cc.
+static gpu::ThreadLocalKey g_egl_thread_state_key;
+
+namespace {
+base::LazyInstance<base::Lock>::Leaky g_egl_lock;
+int g_egl_active_thread_count;
+
+egl::Display* g_egl_default_display;
+
+#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.
+base::AtExitManager* g_exit_manager;
+#endif
+} // namespace
+
+namespace egl {
+
+egl::ThreadState* ThreadState::Get() {
+ base::AutoLock lock(g_egl_lock.Get());
+ if (g_egl_active_thread_count == 0) {
+#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+#if defined(COMPONENT_BUILD)
+ if (!g_command_buffer_gles_has_atexit_manager)
+ g_exit_manager = new base::AtExitManager;
+#else
+ g_exit_manager = new base::AtExitManager;
+#endif
+#endif
+ gles2::Initialize();
+
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
+ base::CommandLine::StringVector argv;
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ std::string env_string;
+ env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string);
+#if defined(OS_WIN)
+ argv = base::SplitString(base::UTF8ToUTF16(env_string),
+ base::kWhitespaceUTF16, base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
+ argv.insert(argv.begin(), base::UTF8ToUTF16("dummy"));
+#else
+ argv =
+ base::SplitString(env_string, base::kWhitespaceASCII,
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ argv.insert(argv.begin(), "dummy");
+#endif
+ base::CommandLine::Init(0, nullptr);
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // Need to call both Init and InitFromArgv, since Windows does not use
+ // argc, argv in CommandLine::Init(argc, argv).
+ command_line->InitFromArgv(argv);
+ if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
+ gpu::GPUInfo gpu_info;
+ gpu::CollectBasicGraphicsInfo(&gpu_info);
+ gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line);
+ }
+
+ gfx::GLSurface::InitializeOneOff();
+ }
+
+ g_egl_default_display = new egl::Display();
+ g_egl_thread_state_key = gpu::ThreadLocalAlloc();
+ }
+ egl::ThreadState* thread_state = static_cast<egl::ThreadState*>(
+ gpu::ThreadLocalGetValue(g_egl_thread_state_key));
+ if (!thread_state) {
+ thread_state = new egl::ThreadState;
+ gpu::ThreadLocalSetValue(g_egl_thread_state_key, thread_state);
+ ++g_egl_active_thread_count;
+ }
+ return thread_state;
+}
+
+void ThreadState::ReleaseThread() {
+ base::AutoLock lock(g_egl_lock.Get());
+ if (g_egl_active_thread_count == 0)
+ return;
+
+ egl::ThreadState* thread_state = static_cast<egl::ThreadState*>(
+ gpu::ThreadLocalGetValue(g_egl_thread_state_key));
+ if (!thread_state)
+ return;
+
+ --g_egl_active_thread_count;
+ if (g_egl_active_thread_count > 0) {
+ g_egl_default_display->ReleaseCurrent(thread_state);
+ delete thread_state;
+ } else {
+ gpu::ThreadLocalFree(g_egl_thread_state_key);
+
+ // First delete the display object, so that it drops the possible refs to
+ // current context.
+ delete g_egl_default_display;
+ g_egl_default_display = nullptr;
+
+ // We can use Surface and Context without lock, since there's no threads
+ // left anymore. Destroy the current context explicitly, in an attempt to
+ // reduce the number of error messages abandoned context would produce.
+ if (thread_state->current_context()) {
+ Context::MakeCurrent(thread_state->current_context(),
+ thread_state->current_surface(), nullptr, nullptr);
+ }
+ delete thread_state;
+
+ gles2::Terminate();
+#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+#if defined(COMPONENT_BUILD)
+ if (g_command_buffer_gles_has_atexit_manager)
+ delete g_exit_manager;
+#else
+ delete g_exit_manager;
+#endif
+ g_exit_manager = nullptr;
+#endif
+ }
+}
+
+ThreadState::ThreadState() : error_code_(EGL_SUCCESS) {}
+
+ThreadState::~ThreadState() {}
+
+EGLint ThreadState::ConsumeErrorCode() {
+ EGLint current_error_code = error_code_;
+ error_code_ = EGL_SUCCESS;
+ return current_error_code;
+}
+
+Display* ThreadState::GetDisplay(EGLDisplay dpy) {
+ if (dpy == g_egl_default_display)
+ return g_egl_default_display;
+ return nullptr;
+}
+
+Display* ThreadState::GetDefaultDisplay() {
+ return g_egl_default_display;
+}
+
+void ThreadState::SetCurrent(Surface* surface, Context* context) {
+ DCHECK((surface == nullptr) == (context == nullptr));
+ if (current_context_) {
+ current_context_->set_is_current_in_some_thread(false);
+ current_surface_->set_is_current_in_some_thread(false);
+ }
+ current_surface_ = surface;
+ current_context_ = context;
+ if (current_context_) {
+ current_context_->set_is_current_in_some_thread(true);
+ current_surface_->set_is_current_in_some_thread(true);
+ }
+}
+
+ThreadState::AutoCurrentContextRestore::AutoCurrentContextRestore(
+ ThreadState* thread_state)
+ : thread_state_(thread_state) {}
+
+ThreadState::AutoCurrentContextRestore::~AutoCurrentContextRestore() {
+ if (Context* current_context = thread_state_->current_context()) {
+ current_context->ApplyCurrentContext(
+ thread_state_->current_surface()->gl_surface());
+ } else {
+ Context::ApplyContextReleased();
+ }
+}
+
+void ThreadState::AutoCurrentContextRestore::SetCurrent(Surface* surface,
+ Context* context) {
+ thread_state_->SetCurrent(surface, context);
+}
+
+} // namespace egl
« no previous file with comments | « gpu/gles2_conform_support/egl/thread_state.h ('k') | gpu/gles2_conform_support/gles2_conform_support.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698