Extension syncing: Introduce a NeedsSync pref
[chromium-blink-merge.git] / ui / gl / gl_context.cc
blob20984117ce5ffb9340bfa3a592b50fc7293e04a5
1 // Copyright (c) 2012 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.
5 #include <string>
7 #include "base/bind.h"
8 #include "base/cancelable_callback.h"
9 #include "base/command_line.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13 #include "base/threading/thread_local.h"
14 #include "ui/gl/gl_bindings.h"
15 #include "ui/gl/gl_context.h"
16 #include "ui/gl/gl_gl_api_implementation.h"
17 #include "ui/gl/gl_implementation.h"
18 #include "ui/gl/gl_surface.h"
19 #include "ui/gl/gl_switches.h"
20 #include "ui/gl/gl_version_info.h"
21 #include "ui/gl/gpu_timing.h"
23 namespace gfx {
25 namespace {
26 base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky
27 current_context_ = LAZY_INSTANCE_INITIALIZER;
29 base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky
30 current_real_context_ = LAZY_INSTANCE_INITIALIZER;
31 } // namespace
33 GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
35 GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
36 if (!canceled_ && GetCurrent()) {
37 GetCurrent()->ReleaseCurrent(nullptr);
41 void GLContext::ScopedReleaseCurrent::Cancel() {
42 canceled_ = true;
45 GLContext::GLContext(GLShareGroup* share_group) :
46 share_group_(share_group),
47 state_dirtied_externally_(false),
48 swap_interval_(1),
49 force_swap_interval_zero_(false),
50 state_dirtied_callback_(
51 base::Bind(&GLContext::SetStateWasDirtiedExternally,
52 // Note that if this is not unretained, it will create a cycle (and
53 // will never be freed.
54 base::Unretained(this),
55 true)) {
56 if (!share_group_.get())
57 share_group_ = new GLShareGroup;
59 share_group_->AddContext(this);
62 GLContext::~GLContext() {
63 share_group_->RemoveContext(this);
64 if (GetCurrent() == this) {
65 SetCurrent(nullptr);
69 bool GLContext::GetTotalGpuMemory(size_t* bytes) {
70 DCHECK(bytes);
71 *bytes = 0;
72 return false;
75 void GLContext::SetSafeToForceGpuSwitch() {
78 bool GLContext::ForceGpuSwitchIfNeeded() {
79 return true;
82 void GLContext::SetUnbindFboOnMakeCurrent() {
83 NOTIMPLEMENTED();
86 std::string GLContext::GetExtensions() {
87 DCHECK(IsCurrent(nullptr));
88 if (gfx::GetGLImplementation() !=
89 gfx::kGLImplementationDesktopGLCoreProfile) {
90 const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
91 return std::string(ext ? ext : "");
94 std::vector<std::string> exts;
95 GLint num_extensions = 0;
96 glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
97 for (GLint i = 0; i < num_extensions; ++i) {
98 const char* extension = reinterpret_cast<const char*>(
99 glGetStringi(GL_EXTENSIONS, i));
100 DCHECK(extension != nullptr);
101 exts.push_back(extension);
103 return base::JoinString(exts, " ");
106 std::string GLContext::GetGLVersion() {
107 DCHECK(IsCurrent(nullptr));
108 const char *version =
109 reinterpret_cast<const char*>(glGetString(GL_VERSION));
110 return std::string(version ? version : "");
113 std::string GLContext::GetGLRenderer() {
114 DCHECK(IsCurrent(nullptr));
115 const char *renderer =
116 reinterpret_cast<const char*>(glGetString(GL_RENDERER));
117 return std::string(renderer ? renderer : "");
120 base::Closure GLContext::GetStateWasDirtiedExternallyCallback() {
121 return state_dirtied_callback_.callback();
124 void GLContext::RestoreStateIfDirtiedExternally() {
125 NOTREACHED();
128 bool GLContext::GetStateWasDirtiedExternally() const {
129 DCHECK(virtual_gl_api_);
130 return state_dirtied_externally_;
133 void GLContext::SetStateWasDirtiedExternally(bool dirtied_externally) {
134 DCHECK(virtual_gl_api_);
135 state_dirtied_externally_ = dirtied_externally;
138 bool GLContext::HasExtension(const char* name) {
139 std::string extensions = GetExtensions();
140 extensions += " ";
142 std::string delimited_name(name);
143 delimited_name += " ";
145 return extensions.find(delimited_name) != std::string::npos;
148 const GLVersionInfo* GLContext::GetVersionInfo() {
149 if(!version_info_) {
150 std::string version = GetGLVersion();
151 std::string renderer = GetGLRenderer();
152 version_info_ =
153 make_scoped_ptr(new GLVersionInfo(
154 version.c_str(), renderer.c_str(),
155 GetExtensions().c_str()));
157 return version_info_.get();
160 GLShareGroup* GLContext::share_group() {
161 return share_group_.get();
164 bool GLContext::LosesAllContextsOnContextLost() {
165 switch (GetGLImplementation()) {
166 case kGLImplementationDesktopGL:
167 return false;
168 case kGLImplementationEGLGLES2:
169 return true;
170 case kGLImplementationOSMesaGL:
171 case kGLImplementationAppleGL:
172 return false;
173 case kGLImplementationMockGL:
174 return false;
175 default:
176 NOTREACHED();
177 return true;
181 GLContext* GLContext::GetCurrent() {
182 return current_context_.Pointer()->Get();
185 GLContext* GLContext::GetRealCurrent() {
186 return current_real_context_.Pointer()->Get();
189 void GLContext::SetCurrent(GLSurface* surface) {
190 current_context_.Pointer()->Set(surface ? this : nullptr);
191 GLSurface::SetCurrent(surface);
192 // Leave the real GL api current so that unit tests work correctly.
193 // TODO(sievers): Remove this, but needs all gpu_unittest classes
194 // to create and make current a context.
195 if (!surface && GetGLImplementation() != kGLImplementationMockGL) {
196 SetGLApiToNoContext();
200 GLStateRestorer* GLContext::GetGLStateRestorer() {
201 return state_restorer_.get();
204 void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) {
205 state_restorer_ = make_scoped_ptr(state_restorer);
208 void GLContext::SetSwapInterval(int interval) {
209 swap_interval_ = interval;
210 OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
213 void GLContext::ForceSwapIntervalZero(bool force) {
214 force_swap_interval_zero_ = force;
215 OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
218 bool GLContext::WasAllocatedUsingRobustnessExtension() {
219 return false;
222 bool GLContext::InitializeDynamicBindings() {
223 DCHECK(IsCurrent(nullptr));
224 static bool initialized = false;
225 if (initialized)
226 return initialized;
227 initialized = InitializeDynamicGLBindings(GetGLImplementation(), this);
228 if (!initialized)
229 LOG(ERROR) << "Could not initialize dynamic bindings.";
230 return initialized;
233 void GLContext::SetupForVirtualization() {
234 if (!virtual_gl_api_) {
235 virtual_gl_api_.reset(new VirtualGLApi());
236 virtual_gl_api_->Initialize(&g_driver_gl, this);
240 bool GLContext::MakeVirtuallyCurrent(
241 GLContext* virtual_context, GLSurface* surface) {
242 DCHECK(virtual_gl_api_);
243 if (!ForceGpuSwitchIfNeeded())
244 return false;
245 return virtual_gl_api_->MakeCurrent(virtual_context, surface);
248 void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) {
249 if (virtual_gl_api_)
250 virtual_gl_api_->OnReleaseVirtuallyCurrent(virtual_context);
253 void GLContext::SetRealGLApi() {
254 SetGLToRealGLApi();
257 GLContextReal::GLContextReal(GLShareGroup* share_group)
258 : GLContext(share_group) {}
260 scoped_refptr<gfx::GPUTimingClient> GLContextReal::CreateGPUTimingClient() {
261 if (!gpu_timing_) {
262 gpu_timing_.reset(GPUTiming::CreateGPUTiming(this));
264 return gpu_timing_->CreateGPUTimingClient();
267 GLContextReal::~GLContextReal() {}
269 void GLContextReal::SetCurrent(GLSurface* surface) {
270 GLContext::SetCurrent(surface);
271 current_real_context_.Pointer()->Set(surface ? this : nullptr);
274 } // namespace gfx