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 void GLContext::SetUnbindFboOnMakeCurrent() {
89 std::string
GLContext::GetExtensions() {
90 DCHECK(IsCurrent(NULL
));
91 const char* ext
= reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS
));
92 return std::string(ext
? ext
: "");
95 std::string
GLContext::GetGLVersion() {
96 DCHECK(IsCurrent(NULL
));
98 reinterpret_cast<const char*>(glGetString(GL_VERSION
));
99 return std::string(version
? version
: "");
102 std::string
GLContext::GetGLRenderer() {
103 DCHECK(IsCurrent(NULL
));
104 const char *renderer
=
105 reinterpret_cast<const char*>(glGetString(GL_RENDERER
));
106 return std::string(renderer
? renderer
: "");
109 bool GLContext::HasExtension(const char* name
) {
110 std::string extensions
= GetExtensions();
113 std::string
delimited_name(name
);
114 delimited_name
+= " ";
116 return extensions
.find(delimited_name
) != std::string::npos
;
119 const GLVersionInfo
* GLContext::GetVersionInfo() {
121 std::string version
= GetGLVersion();
122 std::string renderer
= GetGLRenderer();
123 version_info_
= scoped_ptr
<GLVersionInfo
>(
124 new GLVersionInfo(version
.c_str(), renderer
.c_str()));
126 return version_info_
.get();
129 GLShareGroup
* GLContext::share_group() {
130 return share_group_
.get();
133 bool GLContext::LosesAllContextsOnContextLost() {
134 switch (GetGLImplementation()) {
135 case kGLImplementationDesktopGL
:
137 case kGLImplementationEGLGLES2
:
139 case kGLImplementationOSMesaGL
:
140 case kGLImplementationAppleGL
:
142 case kGLImplementationMockGL
:
150 GLContext
* GLContext::GetCurrent() {
151 return current_context_
.Pointer()->Get();
154 GLContext
* GLContext::GetRealCurrent() {
155 return current_real_context_
.Pointer()->Get();
158 void GLContext::SetCurrent(GLSurface
* surface
) {
159 current_context_
.Pointer()->Set(surface
? this : NULL
);
160 GLSurface::SetCurrent(surface
);
161 // Leave the real GL api current so that unit tests work correctly.
162 // TODO(sievers): Remove this, but needs all gpu_unittest classes
163 // to create and make current a context.
164 if (!surface
&& GetGLImplementation() != kGLImplementationMockGL
) {
165 SetGLApiToNoContext();
169 GLStateRestorer
* GLContext::GetGLStateRestorer() {
170 return state_restorer_
.get();
173 void GLContext::SetGLStateRestorer(GLStateRestorer
* state_restorer
) {
174 state_restorer_
= make_scoped_ptr(state_restorer
);
177 bool GLContext::WasAllocatedUsingRobustnessExtension() {
181 bool GLContext::InitializeDynamicBindings() {
182 DCHECK(IsCurrent(NULL
));
183 static bool initialized
= false;
186 initialized
= InitializeDynamicGLBindings(GetGLImplementation(), this);
188 LOG(ERROR
) << "Could not initialize dynamic bindings.";
192 void GLContext::SetupForVirtualization() {
193 if (!virtual_gl_api_
) {
194 virtual_gl_api_
.reset(new VirtualGLApi());
195 virtual_gl_api_
->Initialize(&g_driver_gl
, this);
199 bool GLContext::MakeVirtuallyCurrent(
200 GLContext
* virtual_context
, GLSurface
* surface
) {
201 DCHECK(virtual_gl_api_
);
202 return virtual_gl_api_
->MakeCurrent(virtual_context
, surface
);
205 void GLContext::OnReleaseVirtuallyCurrent(GLContext
* virtual_context
) {
207 virtual_gl_api_
->OnReleaseVirtuallyCurrent(virtual_context
);
210 void GLContext::SetRealGLApi() {
214 void GLContext::OnFlush() {
215 for (size_t n
= 0; n
< flush_events_
.size(); n
++)
216 flush_events_
[n
]->Signal();
217 flush_events_
.clear();
220 GLContextReal::GLContextReal(GLShareGroup
* share_group
)
221 : GLContext(share_group
) {}
223 GLContextReal::~GLContextReal() {}
225 void GLContextReal::SetCurrent(GLSurface
* surface
) {
226 GLContext::SetCurrent(surface
);
227 current_real_context_
.Pointer()->Set(surface
? this : NULL
);