Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / gl / gl_context.cc
blobada2127d5075d538b295dd87537076b4b2a5cd96
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 return GetGLExtensionsFromCurrentContext();
91 std::string GLContext::GetGLVersion() {
92 DCHECK(IsCurrent(nullptr));
93 const char *version =
94 reinterpret_cast<const char*>(glGetString(GL_VERSION));
95 return std::string(version ? version : "");
98 std::string GLContext::GetGLRenderer() {
99 DCHECK(IsCurrent(nullptr));
100 const char *renderer =
101 reinterpret_cast<const char*>(glGetString(GL_RENDERER));
102 return std::string(renderer ? renderer : "");
105 base::Closure GLContext::GetStateWasDirtiedExternallyCallback() {
106 return state_dirtied_callback_.callback();
109 void GLContext::RestoreStateIfDirtiedExternally() {
110 NOTREACHED();
113 bool GLContext::GetStateWasDirtiedExternally() const {
114 DCHECK(virtual_gl_api_);
115 return state_dirtied_externally_;
118 void GLContext::SetStateWasDirtiedExternally(bool dirtied_externally) {
119 DCHECK(virtual_gl_api_);
120 state_dirtied_externally_ = dirtied_externally;
123 bool GLContext::HasExtension(const char* name) {
124 std::string extensions = GetExtensions();
125 extensions += " ";
127 std::string delimited_name(name);
128 delimited_name += " ";
130 return extensions.find(delimited_name) != std::string::npos;
133 const GLVersionInfo* GLContext::GetVersionInfo() {
134 if(!version_info_) {
135 std::string version = GetGLVersion();
136 std::string renderer = GetGLRenderer();
137 version_info_ =
138 make_scoped_ptr(new GLVersionInfo(
139 version.c_str(), renderer.c_str(),
140 GetExtensions().c_str()));
142 return version_info_.get();
145 GLShareGroup* GLContext::share_group() {
146 return share_group_.get();
149 bool GLContext::LosesAllContextsOnContextLost() {
150 switch (GetGLImplementation()) {
151 case kGLImplementationDesktopGL:
152 return false;
153 case kGLImplementationEGLGLES2:
154 return true;
155 case kGLImplementationOSMesaGL:
156 case kGLImplementationAppleGL:
157 return false;
158 case kGLImplementationMockGL:
159 return false;
160 default:
161 NOTREACHED();
162 return true;
166 GLContext* GLContext::GetCurrent() {
167 return current_context_.Pointer()->Get();
170 GLContext* GLContext::GetRealCurrent() {
171 return current_real_context_.Pointer()->Get();
174 void GLContext::SetCurrent(GLSurface* surface) {
175 current_context_.Pointer()->Set(surface ? this : nullptr);
176 GLSurface::SetCurrent(surface);
177 // Leave the real GL api current so that unit tests work correctly.
178 // TODO(sievers): Remove this, but needs all gpu_unittest classes
179 // to create and make current a context.
180 if (!surface && GetGLImplementation() != kGLImplementationMockGL) {
181 SetGLApiToNoContext();
185 GLStateRestorer* GLContext::GetGLStateRestorer() {
186 return state_restorer_.get();
189 void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) {
190 state_restorer_ = make_scoped_ptr(state_restorer);
193 void GLContext::SetSwapInterval(int interval) {
194 swap_interval_ = interval;
195 OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
198 void GLContext::ForceSwapIntervalZero(bool force) {
199 force_swap_interval_zero_ = force;
200 OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
203 bool GLContext::WasAllocatedUsingRobustnessExtension() {
204 return false;
207 bool GLContext::InitializeDynamicBindings() {
208 DCHECK(IsCurrent(nullptr));
209 static bool initialized = false;
210 if (initialized)
211 return initialized;
212 initialized = InitializeDynamicGLBindings(GetGLImplementation(), this);
213 if (!initialized)
214 LOG(ERROR) << "Could not initialize dynamic bindings.";
215 return initialized;
218 void GLContext::SetupForVirtualization() {
219 if (!virtual_gl_api_) {
220 virtual_gl_api_.reset(new VirtualGLApi());
221 virtual_gl_api_->Initialize(&g_driver_gl, this);
225 bool GLContext::MakeVirtuallyCurrent(
226 GLContext* virtual_context, GLSurface* surface) {
227 DCHECK(virtual_gl_api_);
228 if (!ForceGpuSwitchIfNeeded())
229 return false;
230 return virtual_gl_api_->MakeCurrent(virtual_context, surface);
233 void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) {
234 if (virtual_gl_api_)
235 virtual_gl_api_->OnReleaseVirtuallyCurrent(virtual_context);
238 void GLContext::SetRealGLApi() {
239 SetGLToRealGLApi();
242 GLContextReal::GLContextReal(GLShareGroup* share_group)
243 : GLContext(share_group) {}
245 scoped_refptr<gfx::GPUTimingClient> GLContextReal::CreateGPUTimingClient() {
246 if (!gpu_timing_) {
247 gpu_timing_.reset(GPUTiming::CreateGPUTiming(this));
249 return gpu_timing_->CreateGPUTimingClient();
252 GLContextReal::~GLContextReal() {}
254 void GLContextReal::SetCurrent(GLSurface* surface) {
255 GLContext::SetCurrent(surface);
256 current_real_context_.Pointer()->Set(surface ? this : nullptr);
259 } // namespace gfx