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.
7 #include "base/command_line.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/threading/thread_local.h"
11 #include "ui/gl/gl_bindings.h"
12 #include "ui/gl/gl_context.h"
13 #include "ui/gl/gl_gl_api_implementation.h"
14 #include "ui/gl/gl_implementation.h"
15 #include "ui/gl/gl_surface.h"
16 #include "ui/gl/gl_switches.h"
17 #include "ui/gl/gl_version_info.h"
22 base::LazyInstance
<base::ThreadLocalPointer
<GLContext
> >::Leaky
23 current_context_
= LAZY_INSTANCE_INITIALIZER
;
25 base::LazyInstance
<base::ThreadLocalPointer
<GLContext
> >::Leaky
26 current_real_context_
= LAZY_INSTANCE_INITIALIZER
;
29 GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
31 GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
32 if (!canceled_
&& GetCurrent()) {
33 GetCurrent()->ReleaseCurrent(NULL
);
37 void GLContext::ScopedReleaseCurrent::Cancel() {
41 GLContext::GLContext(GLShareGroup
* share_group
) :
42 share_group_(share_group
),
44 force_swap_interval_zero_(false) {
45 if (!share_group_
.get())
46 share_group_
= new GLShareGroup
;
48 share_group_
->AddContext(this);
51 GLContext::~GLContext() {
52 share_group_
->RemoveContext(this);
53 if (GetCurrent() == this) {
58 bool GLContext::GetTotalGpuMemory(size_t* bytes
) {
64 void GLContext::SetSafeToForceGpuSwitch() {
67 bool GLContext::ForceGpuSwitchIfNeeded() {
71 void GLContext::SetUnbindFboOnMakeCurrent() {
75 std::string
GLContext::GetExtensions() {
76 DCHECK(IsCurrent(NULL
));
77 const char* ext
= reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS
));
78 return std::string(ext
? ext
: "");
81 std::string
GLContext::GetGLVersion() {
82 DCHECK(IsCurrent(NULL
));
84 reinterpret_cast<const char*>(glGetString(GL_VERSION
));
85 return std::string(version
? version
: "");
88 std::string
GLContext::GetGLRenderer() {
89 DCHECK(IsCurrent(NULL
));
90 const char *renderer
=
91 reinterpret_cast<const char*>(glGetString(GL_RENDERER
));
92 return std::string(renderer
? renderer
: "");
95 bool GLContext::HasExtension(const char* name
) {
96 std::string extensions
= GetExtensions();
99 std::string
delimited_name(name
);
100 delimited_name
+= " ";
102 return extensions
.find(delimited_name
) != std::string::npos
;
105 const GLVersionInfo
* GLContext::GetVersionInfo() {
107 std::string version
= GetGLVersion();
108 std::string renderer
= GetGLRenderer();
109 version_info_
= scoped_ptr
<GLVersionInfo
>(
110 new GLVersionInfo(version
.c_str(), renderer
.c_str()));
112 return version_info_
.get();
115 GLShareGroup
* GLContext::share_group() {
116 return share_group_
.get();
119 bool GLContext::LosesAllContextsOnContextLost() {
120 switch (GetGLImplementation()) {
121 case kGLImplementationDesktopGL
:
123 case kGLImplementationEGLGLES2
:
125 case kGLImplementationOSMesaGL
:
126 case kGLImplementationAppleGL
:
128 case kGLImplementationMockGL
:
136 GLContext
* GLContext::GetCurrent() {
137 return current_context_
.Pointer()->Get();
140 GLContext
* GLContext::GetRealCurrent() {
141 return current_real_context_
.Pointer()->Get();
144 void GLContext::SetCurrent(GLSurface
* surface
) {
145 current_context_
.Pointer()->Set(surface
? this : NULL
);
146 GLSurface::SetCurrent(surface
);
147 // Leave the real GL api current so that unit tests work correctly.
148 // TODO(sievers): Remove this, but needs all gpu_unittest classes
149 // to create and make current a context.
150 if (!surface
&& GetGLImplementation() != kGLImplementationMockGL
) {
151 SetGLApiToNoContext();
155 GLStateRestorer
* GLContext::GetGLStateRestorer() {
156 return state_restorer_
.get();
159 void GLContext::SetGLStateRestorer(GLStateRestorer
* state_restorer
) {
160 state_restorer_
= make_scoped_ptr(state_restorer
);
163 void GLContext::SetSwapInterval(int interval
) {
164 swap_interval_
= interval
;
165 OnSetSwapInterval(force_swap_interval_zero_
? 0 : swap_interval_
);
168 void GLContext::ForceSwapIntervalZero(bool force
) {
169 force_swap_interval_zero_
= force
;
170 OnSetSwapInterval(force_swap_interval_zero_
? 0 : swap_interval_
);
173 bool GLContext::WasAllocatedUsingRobustnessExtension() {
177 bool GLContext::InitializeDynamicBindings() {
178 DCHECK(IsCurrent(NULL
));
179 static bool initialized
= false;
182 initialized
= InitializeDynamicGLBindings(GetGLImplementation(), this);
184 LOG(ERROR
) << "Could not initialize dynamic bindings.";
188 void GLContext::SetupForVirtualization() {
189 if (!virtual_gl_api_
) {
190 virtual_gl_api_
.reset(new VirtualGLApi());
191 virtual_gl_api_
->Initialize(&g_driver_gl
, this);
195 bool GLContext::MakeVirtuallyCurrent(
196 GLContext
* virtual_context
, GLSurface
* surface
) {
197 DCHECK(virtual_gl_api_
);
198 if (!ForceGpuSwitchIfNeeded())
200 return virtual_gl_api_
->MakeCurrent(virtual_context
, surface
);
203 void GLContext::OnReleaseVirtuallyCurrent(GLContext
* virtual_context
) {
205 virtual_gl_api_
->OnReleaseVirtuallyCurrent(virtual_context
);
208 void GLContext::SetRealGLApi() {
212 GLContextReal::GLContextReal(GLShareGroup
* share_group
)
213 : GLContext(share_group
) {}
215 GLContextReal::~GLContextReal() {}
217 void GLContextReal::SetCurrent(GLSurface
* surface
) {
218 GLContext::SetCurrent(surface
);
219 current_real_context_
.Pointer()->Set(surface
? this : NULL
);