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.
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"
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
;
33 GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
35 GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
36 if (!canceled_
&& GetCurrent()) {
37 GetCurrent()->ReleaseCurrent(nullptr);
41 void GLContext::ScopedReleaseCurrent::Cancel() {
45 GLContext::GLContext(GLShareGroup
* share_group
) :
46 share_group_(share_group
),
47 state_dirtied_externally_(false),
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),
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) {
69 bool GLContext::GetTotalGpuMemory(size_t* bytes
) {
75 void GLContext::SetSafeToForceGpuSwitch() {
78 bool GLContext::ForceGpuSwitchIfNeeded() {
82 void GLContext::SetUnbindFboOnMakeCurrent() {
86 std::string
GLContext::GetExtensions() {
87 DCHECK(IsCurrent(nullptr));
88 return GetGLExtensionsFromCurrentContext();
91 std::string
GLContext::GetGLVersion() {
92 DCHECK(IsCurrent(nullptr));
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() {
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();
127 std::string
delimited_name(name
);
128 delimited_name
+= " ";
130 return extensions
.find(delimited_name
) != std::string::npos
;
133 const GLVersionInfo
* GLContext::GetVersionInfo() {
135 std::string version
= GetGLVersion();
136 std::string renderer
= GetGLRenderer();
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
:
153 case kGLImplementationEGLGLES2
:
155 case kGLImplementationOSMesaGL
:
156 case kGLImplementationAppleGL
:
158 case kGLImplementationMockGL
:
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() {
207 bool GLContext::InitializeDynamicBindings() {
208 DCHECK(IsCurrent(nullptr));
209 static bool initialized
= false;
212 initialized
= InitializeDynamicGLBindings(GetGLImplementation(), this);
214 LOG(ERROR
) << "Could not initialize dynamic bindings.";
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())
230 return virtual_gl_api_
->MakeCurrent(virtual_context
, surface
);
233 void GLContext::OnReleaseVirtuallyCurrent(GLContext
* virtual_context
) {
235 virtual_gl_api_
->OnReleaseVirtuallyCurrent(virtual_context
);
238 void GLContext::SetRealGLApi() {
242 GLContextReal::GLContextReal(GLShareGroup
* share_group
)
243 : GLContext(share_group
) {}
245 scoped_refptr
<gfx::GPUTimingClient
> GLContextReal::CreateGPUTimingClient() {
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);