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::FlushEvent::FlushEvent() {
44 GLContext::FlushEvent::~FlushEvent() {
47 void GLContext::FlushEvent::Signal() {
51 bool GLContext::FlushEvent::IsSignaled() {
55 GLContext::GLContext(GLShareGroup
* share_group
) : share_group_(share_group
) {
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 scoped_refptr
<GLContext::FlushEvent
> GLContext::SignalFlush() {
70 DCHECK(IsCurrent(NULL
));
71 scoped_refptr
<FlushEvent
> flush_event
= new FlushEvent();
72 flush_events_
.push_back(flush_event
);
76 bool GLContext::GetTotalGpuMemory(size_t* bytes
) {
82 void GLContext::SetSafeToForceGpuSwitch() {
85 bool GLContext::ForceGpuSwitchIfNeeded() {
89 void GLContext::SetUnbindFboOnMakeCurrent() {
93 std::string
GLContext::GetExtensions() {
94 DCHECK(IsCurrent(NULL
));
95 const char* ext
= reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS
));
96 return std::string(ext
? ext
: "");
99 std::string
GLContext::GetGLVersion() {
100 DCHECK(IsCurrent(NULL
));
101 const char *version
=
102 reinterpret_cast<const char*>(glGetString(GL_VERSION
));
103 return std::string(version
? version
: "");
106 std::string
GLContext::GetGLRenderer() {
107 DCHECK(IsCurrent(NULL
));
108 const char *renderer
=
109 reinterpret_cast<const char*>(glGetString(GL_RENDERER
));
110 return std::string(renderer
? renderer
: "");
113 bool GLContext::HasExtension(const char* name
) {
114 std::string extensions
= GetExtensions();
117 std::string
delimited_name(name
);
118 delimited_name
+= " ";
120 return extensions
.find(delimited_name
) != std::string::npos
;
123 const GLVersionInfo
* GLContext::GetVersionInfo() {
125 std::string version
= GetGLVersion();
126 std::string renderer
= GetGLRenderer();
127 version_info_
= scoped_ptr
<GLVersionInfo
>(
128 new GLVersionInfo(version
.c_str(), renderer
.c_str()));
130 return version_info_
.get();
133 GLShareGroup
* GLContext::share_group() {
134 return share_group_
.get();
137 bool GLContext::LosesAllContextsOnContextLost() {
138 switch (GetGLImplementation()) {
139 case kGLImplementationDesktopGL
:
141 case kGLImplementationEGLGLES2
:
143 case kGLImplementationOSMesaGL
:
144 case kGLImplementationAppleGL
:
146 case kGLImplementationMockGL
:
154 GLContext
* GLContext::GetCurrent() {
155 return current_context_
.Pointer()->Get();
158 GLContext
* GLContext::GetRealCurrent() {
159 return current_real_context_
.Pointer()->Get();
162 void GLContext::SetCurrent(GLSurface
* surface
) {
163 current_context_
.Pointer()->Set(surface
? this : NULL
);
164 GLSurface::SetCurrent(surface
);
165 // Leave the real GL api current so that unit tests work correctly.
166 // TODO(sievers): Remove this, but needs all gpu_unittest classes
167 // to create and make current a context.
168 if (!surface
&& GetGLImplementation() != kGLImplementationMockGL
) {
169 SetGLApiToNoContext();
173 GLStateRestorer
* GLContext::GetGLStateRestorer() {
174 return state_restorer_
.get();
177 void GLContext::SetGLStateRestorer(GLStateRestorer
* state_restorer
) {
178 state_restorer_
= make_scoped_ptr(state_restorer
);
181 bool GLContext::WasAllocatedUsingRobustnessExtension() {
185 bool GLContext::InitializeDynamicBindings() {
186 DCHECK(IsCurrent(NULL
));
187 static bool initialized
= false;
190 initialized
= InitializeDynamicGLBindings(GetGLImplementation(), this);
192 LOG(ERROR
) << "Could not initialize dynamic bindings.";
196 void GLContext::SetupForVirtualization() {
197 if (!virtual_gl_api_
) {
198 virtual_gl_api_
.reset(new VirtualGLApi());
199 virtual_gl_api_
->Initialize(&g_driver_gl
, this);
203 bool GLContext::MakeVirtuallyCurrent(
204 GLContext
* virtual_context
, GLSurface
* surface
) {
205 DCHECK(virtual_gl_api_
);
206 if (!ForceGpuSwitchIfNeeded())
208 return virtual_gl_api_
->MakeCurrent(virtual_context
, surface
);
211 void GLContext::OnReleaseVirtuallyCurrent(GLContext
* virtual_context
) {
213 virtual_gl_api_
->OnReleaseVirtuallyCurrent(virtual_context
);
216 void GLContext::SetRealGLApi() {
220 void GLContext::OnFlush() {
221 for (size_t n
= 0; n
< flush_events_
.size(); n
++)
222 flush_events_
[n
]->Signal();
223 flush_events_
.clear();
226 GLContextReal::GLContextReal(GLShareGroup
* share_group
)
227 : GLContext(share_group
) {}
229 GLContextReal::~GLContextReal() {}
231 void GLContextReal::SetCurrent(GLSurface
* surface
) {
232 GLContext::SetCurrent(surface
);
233 current_real_context_
.Pointer()->Set(surface
? this : NULL
);