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

Side by Side 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: win fixes Created 4 years, 10 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 unified diff | Download patch
OLDNEW
(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 // Thread local key for ThreadState instance. Accessed when holding g_egl_lock
27 // only, since the initialization can not be Guaranteed otherwise. Not in
28 // anonymous namespace due to Mac OS X 10.6 linker. See gles2_lib.cc.
29 static gpu::ThreadLocalKey g_egl_thread_state_key;
30
31 namespace {
32 base::LazyInstance<base::Lock>::Leaky g_egl_lock;
33 int g_egl_active_thread_count;
34
35 egl::Display* g_egl_default_display;
36
37 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
38 // egl::Display is used for comformance tests and command_buffer_gles. We only
39 // need the exit manager for the command_buffer_gles library.
40 base::AtExitManager* g_exit_manager;
41 #endif
42 } // namespace
43
44 namespace egl {
45
46 egl::ThreadState* ThreadState::Get() {
47 base::AutoLock lock(g_egl_lock.Get());
48 if (g_egl_active_thread_count == 0) {
49 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
50 #if defined(COMPONENT_BUILD)
51 if (!g_command_buffer_gles_has_atexit_manager)
52 g_exit_manager = new base::AtExitManager;
53 #else
54 g_exit_manager = new base::AtExitManager;
55 #endif
56 #endif
57 gles2::Initialize();
58
59 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
60 base::CommandLine::StringVector argv;
61 scoped_ptr<base::Environment> env(base::Environment::Create());
62 std::string env_string;
63 env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string);
64 #if defined(OS_WIN)
65 argv = base::SplitString(base::UTF8ToUTF16(env_string),
66 base::kWhitespaceUTF16, base::TRIM_WHITESPACE,
67 base::SPLIT_WANT_NONEMPTY);
68 argv.insert(argv.begin(), base::UTF8ToUTF16("dummy"));
69 #else
70 argv =
71 base::SplitString(env_string, base::kWhitespaceASCII,
72 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
73 argv.insert(argv.begin(), "dummy");
74 #endif
75 base::CommandLine::Init(0, nullptr);
76 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
77 // Need to call both Init and InitFromArgv, since Windows does not use
78 // argc, argv in CommandLine::Init(argc, argv).
79 command_line->InitFromArgv(argv);
80 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
81 gpu::GPUInfo gpu_info;
82 gpu::CollectBasicGraphicsInfo(&gpu_info);
83 gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line);
84 }
85
86 gfx::GLSurface::InitializeOneOff();
87 }
88
89 g_egl_default_display = new egl::Display();
90 g_egl_thread_state_key = gpu::ThreadLocalAlloc();
91 }
92 egl::ThreadState* thread_state = static_cast<egl::ThreadState*>(
93 gpu::ThreadLocalGetValue(g_egl_thread_state_key));
94 if (!thread_state) {
95 thread_state = new egl::ThreadState;
96 gpu::ThreadLocalSetValue(g_egl_thread_state_key, thread_state);
97 ++g_egl_active_thread_count;
98 }
99 return thread_state;
100 }
101
102 void ThreadState::ReleaseThread() {
103 base::AutoLock lock(g_egl_lock.Get());
104 if (g_egl_active_thread_count == 0)
105 return;
106
107 egl::ThreadState* thread_state = static_cast<egl::ThreadState*>(
108 gpu::ThreadLocalGetValue(g_egl_thread_state_key));
109 if (!thread_state)
110 return;
111 gpu::ThreadLocalFree(g_egl_thread_state_key);
piman 2016/02/23 23:37:17 This should only happen once all the threads have
Kimmo Kinnunen 2016/02/24 07:33:27 Done.
112
113 --g_egl_active_thread_count;
114 if (g_egl_active_thread_count > 0) {
115 g_egl_default_display->ReleaseCurrent(thread_state);
116 delete thread_state;
117 } else {
118 // First delete the display object, so that it drops the possible refs to
119 // current context.
120 delete g_egl_default_display;
121 g_egl_default_display = nullptr;
122
123 // We can use Surface and Context without lock, since there's no threads
124 // left anymore. Destroy the current context explicitly, in an attempt to
125 // reduce the number of error messages abandoned context would produce.
126 if (thread_state->current_context())
piman 2016/02/23 23:37:17 nit: {} per style
Kimmo Kinnunen 2016/02/24 07:33:27 Done.
127 Context::MakeCurrent(thread_state->current_context(),
128 thread_state->current_surface()->gl_surface(),
129 nullptr, nullptr);
130 delete thread_state;
131
132 gles2::Terminate();
133 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
134 #if defined(COMPONENT_BUILD)
135 if (g_command_buffer_gles_has_atexit_manager)
136 delete g_exit_manager;
137 #else
138 delete g_exit_manager;
139 #endif
140 g_exit_manager = nullptr;
141 #endif
142 }
143 }
144
145 ThreadState::ThreadState() : error_code_(EGL_SUCCESS) {}
146
147 ThreadState::~ThreadState() {}
148
149 EGLint ThreadState::ConsumeErrorCode() {
150 EGLint current_error_code = error_code_;
151 error_code_ = EGL_SUCCESS;
152 return current_error_code;
153 }
154
155 Display* ThreadState::GetDisplay(EGLDisplay dpy) {
156 if (dpy == g_egl_default_display)
157 return g_egl_default_display;
158 return nullptr;
159 }
160
161 Display* ThreadState::GetDefaultDisplay() {
162 return g_egl_default_display;
163 }
164
165 void ThreadState::SetCurrent(Surface* surface, Context* context) {
166 DCHECK((surface == nullptr) == (context == nullptr));
167 if (current_context_) {
168 current_context_->set_is_current_in_some_thread(false);
169 current_surface_->set_is_current_in_some_thread(false);
170 }
171 current_surface_ = surface;
172 current_context_ = context;
173 if (current_context_) {
174 current_context_->set_is_current_in_some_thread(true);
175 current_surface_->set_is_current_in_some_thread(true);
176 }
177 }
178
179 ThreadState::AutoCurrentContextRestore::AutoCurrentContextRestore(
180 ThreadState* thread_state)
181 : thread_state_(thread_state) {}
182
183 ThreadState::AutoCurrentContextRestore::~AutoCurrentContextRestore() {
184 if (Context* current_context = thread_state_->current_context())
piman 2016/02/23 23:37:17 nit: needs {} per style (and then so does the else
Kimmo Kinnunen 2016/02/24 07:33:27 Done.
185 current_context->ApplyCurrentContext(
186 thread_state_->current_surface()->gl_surface());
187 else
188 Context::ApplyContextReleased();
189 }
190
191 void ThreadState::AutoCurrentContextRestore::SetCurrent(Surface* surface,
192 Context* context) {
193 thread_state_->SetCurrent(surface, context);
194 }
195
196 } // namespace egl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698