OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "gpu/gles2_conform_support/egl/thread_state.h" |
| 6 |
| 7 #include "base/at_exit.h" |
| 8 #include "base/command_line.h" |
| 9 #include "base/environment.h" |
| 10 #include "base/lazy_instance.h" |
| 11 #include "base/strings/string_split.h" |
| 12 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "gpu/command_buffer/client/gles2_lib.h" |
| 15 #include "gpu/command_buffer/common/thread_local.h" |
| 16 #include "gpu/command_buffer/service/gpu_switches.h" |
| 17 #include "gpu/config/gpu_info_collector.h" |
| 18 #include "gpu/config/gpu_util.h" |
| 19 #include "gpu/gles2_conform_support/egl/context.h" |
| 20 #include "gpu/gles2_conform_support/egl/display.h" |
| 21 #include "gpu/gles2_conform_support/egl/surface.h" |
| 22 #include "gpu/gles2_conform_support/egl/test_support.h" |
| 23 #include "ui/gl/gl_context.h" |
| 24 #include "ui/gl/gl_surface.h" |
| 25 |
| 26 // Not in anonymous namespace due to Mac OS X 10.6 linker. |
| 27 // See gles2_lib.cc. |
| 28 static gpu::ThreadLocalKey g_egl_thread_state_key; |
| 29 |
| 30 // egl::Display is used for comformance tests and command_buffer_gles. We only |
| 31 // need the exit manager for the command_buffer_gles library. |
| 32 namespace { |
| 33 base::LazyInstance<base::Lock>::Leaky g_egl_lock; |
| 34 int g_egl_active_thread_count; |
| 35 |
| 36 egl::Display* g_egl_default_display; |
| 37 |
| 38 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) |
| 39 base::AtExitManager* g_exit_manager; |
| 40 #endif |
| 41 } // namespace |
| 42 |
| 43 namespace egl { |
| 44 |
| 45 egl::ThreadState* ThreadState::Get() { |
| 46 base::AutoLock lock(g_egl_lock.Get()); |
| 47 if (g_egl_active_thread_count == 0) { |
| 48 #if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) |
| 49 if (!g_command_buffer_gles_has_atexit_manager) |
| 50 g_exit_manager = new base::AtExitManager; |
| 51 #endif |
| 52 gles2::Initialize(); |
| 53 |
| 54 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) { |
| 55 base::CommandLine::StringVector argv; |
| 56 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 57 std::string env_string; |
| 58 env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string); |
| 59 #if defined(OS_WIN) |
| 60 argv = base::SplitString(base::UTF8ToUTF16(env_string), |
| 61 base::kWhitespaceUTF16, base::TRIM_WHITESPACE, |
| 62 base::SPLIT_WANT_NONEMPTY); |
| 63 argv.insert(argv.begin(), base::UTF8ToUTF16("dummy")); |
| 64 #else |
| 65 argv = |
| 66 base::SplitString(env_string, base::kWhitespaceASCII, |
| 67 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 68 argv.insert(argv.begin(), "dummy"); |
| 69 #endif |
| 70 base::CommandLine::Init(0, nullptr); |
| 71 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 72 // Need to call both Init and InitFromArgv, since Windows does not use |
| 73 // argc, argv in CommandLine::Init(argc, argv). |
| 74 command_line->InitFromArgv(argv); |
| 75 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { |
| 76 gpu::GPUInfo gpu_info; |
| 77 gpu::CollectBasicGraphicsInfo(&gpu_info); |
| 78 gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line); |
| 79 } |
| 80 |
| 81 gfx::GLSurface::InitializeOneOff(); |
| 82 } |
| 83 |
| 84 g_egl_default_display = new egl::Display(); |
| 85 g_egl_thread_state_key = gpu::ThreadLocalAlloc(); |
| 86 } |
| 87 egl::ThreadState* thread_state = static_cast<egl::ThreadState*>( |
| 88 gpu::ThreadLocalGetValue(g_egl_thread_state_key)); |
| 89 if (!thread_state) { |
| 90 thread_state = new egl::ThreadState; |
| 91 gpu::ThreadLocalSetValue(g_egl_thread_state_key, thread_state); |
| 92 ++g_egl_active_thread_count; |
| 93 } |
| 94 return thread_state; |
| 95 } |
| 96 |
| 97 void ThreadState::ReleaseThread() { |
| 98 base::AutoLock lock(g_egl_lock.Get()); |
| 99 if (g_egl_active_thread_count == 0) |
| 100 return; |
| 101 |
| 102 egl::ThreadState* thread_state = static_cast<egl::ThreadState*>( |
| 103 gpu::ThreadLocalGetValue(g_egl_thread_state_key)); |
| 104 if (!thread_state) |
| 105 return; |
| 106 delete thread_state; |
| 107 gpu::ThreadLocalFree(g_egl_thread_state_key); |
| 108 |
| 109 --g_egl_active_thread_count; |
| 110 |
| 111 if (g_egl_active_thread_count == 0) { |
| 112 delete g_egl_default_display; |
| 113 g_egl_default_display = nullptr; |
| 114 gles2::Terminate(); |
| 115 #if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) |
| 116 if (g_command_buffer_gles_has_atexit_manager) { |
| 117 delete g_exit_manager; |
| 118 g_exit_manager = nullptr; |
| 119 } |
| 120 #endif |
| 121 } |
| 122 } |
| 123 |
| 124 ThreadState::ThreadState() : error_code_(EGL_SUCCESS) {} |
| 125 |
| 126 ThreadState::~ThreadState() { |
| 127 gles2::SetGLContext(nullptr); |
| 128 } |
| 129 |
| 130 EGLint ThreadState::ConsumeErrorCode() { |
| 131 EGLint current_error_code = error_code_; |
| 132 error_code_ = EGL_SUCCESS; |
| 133 return current_error_code; |
| 134 } |
| 135 |
| 136 Display* ThreadState::GetDisplay(EGLDisplay dpy) { |
| 137 if (dpy == g_egl_default_display) |
| 138 return g_egl_default_display; |
| 139 return nullptr; |
| 140 } |
| 141 |
| 142 Display* ThreadState::GetDefaultDisplay() { |
| 143 return g_egl_default_display; |
| 144 } |
| 145 |
| 146 void ThreadState::SetCurrent(Surface* surface, Context* context) { |
| 147 DCHECK((surface == nullptr) == (context == nullptr)); |
| 148 current_surface_ = surface; |
| 149 current_context_ = context; |
| 150 } |
| 151 |
| 152 void ThreadState::ApplyCurrentContext() { |
| 153 if (current_context_) { |
| 154 gles2::SetGLContext(current_context_->client_gl_context()); |
| 155 current_context_->gl_context()->MakeCurrent(current_surface_->gl_surface()); |
| 156 } else { |
| 157 gles2::SetGLContext(nullptr); |
| 158 } |
| 159 } |
| 160 |
| 161 ThreadState::AutoApplyCurrentContext::AutoApplyCurrentContext( |
| 162 ThreadState* thread_state) |
| 163 : thread_state_(thread_state) {} |
| 164 ThreadState::AutoApplyCurrentContext::~AutoApplyCurrentContext() { |
| 165 thread_state_->ApplyCurrentContext(); |
| 166 } |
| 167 } // namespace egl |
OLD | NEW |