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"
18 #include "ui/gl/gpu_timing.h"
23 base::LazyInstance
<base::ThreadLocalPointer
<GLContext
> >::Leaky
24 current_context_
= LAZY_INSTANCE_INITIALIZER
;
26 base::LazyInstance
<base::ThreadLocalPointer
<GLContext
> >::Leaky
27 current_real_context_
= LAZY_INSTANCE_INITIALIZER
;
30 GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
32 GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
33 if (!canceled_
&& GetCurrent()) {
34 GetCurrent()->ReleaseCurrent(NULL
);
38 void GLContext::ScopedReleaseCurrent::Cancel() {
42 GLContext::GLContext(GLShareGroup
* share_group
) :
43 share_group_(share_group
),
45 force_swap_interval_zero_(false) {
46 if (!share_group_
.get())
47 share_group_
= new GLShareGroup
;
49 share_group_
->AddContext(this);
52 GLContext::~GLContext() {
53 share_group_
->RemoveContext(this);
54 if (GetCurrent() == this) {
59 bool GLContext::GetTotalGpuMemory(size_t* bytes
) {
65 void GLContext::SetSafeToForceGpuSwitch() {
68 bool GLContext::ForceGpuSwitchIfNeeded() {
72 void GLContext::SetUnbindFboOnMakeCurrent() {
76 std::string
GLContext::GetExtensions() {
77 DCHECK(IsCurrent(NULL
));
78 const char* ext
= reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS
));
79 return std::string(ext
? ext
: "");
82 std::string
GLContext::GetGLVersion() {
83 DCHECK(IsCurrent(NULL
));
85 reinterpret_cast<const char*>(glGetString(GL_VERSION
));
86 return std::string(version
? version
: "");
89 std::string
GLContext::GetGLRenderer() {
90 DCHECK(IsCurrent(NULL
));
91 const char *renderer
=
92 reinterpret_cast<const char*>(glGetString(GL_RENDERER
));
93 return std::string(renderer
? renderer
: "");
96 bool GLContext::HasExtension(const char* name
) {
97 std::string extensions
= GetExtensions();
100 std::string
delimited_name(name
);
101 delimited_name
+= " ";
103 return extensions
.find(delimited_name
) != std::string::npos
;
106 const GLVersionInfo
* GLContext::GetVersionInfo() {
108 std::string version
= GetGLVersion();
109 std::string renderer
= GetGLRenderer();
111 make_scoped_ptr(new GLVersionInfo(version
.c_str(), renderer
.c_str()));
113 return version_info_
.get();
116 GLShareGroup
* GLContext::share_group() {
117 return share_group_
.get();
120 bool GLContext::LosesAllContextsOnContextLost() {
121 switch (GetGLImplementation()) {
122 case kGLImplementationDesktopGL
:
124 case kGLImplementationEGLGLES2
:
126 case kGLImplementationOSMesaGL
:
127 case kGLImplementationAppleGL
:
129 case kGLImplementationMockGL
:
137 GLContext
* GLContext::GetCurrent() {
138 return current_context_
.Pointer()->Get();
141 GLContext
* GLContext::GetRealCurrent() {
142 return current_real_context_
.Pointer()->Get();
145 void GLContext::SetCurrent(GLSurface
* surface
) {
146 current_context_
.Pointer()->Set(surface
? this : NULL
);
147 GLSurface::SetCurrent(surface
);
148 // Leave the real GL api current so that unit tests work correctly.
149 // TODO(sievers): Remove this, but needs all gpu_unittest classes
150 // to create and make current a context.
151 if (!surface
&& GetGLImplementation() != kGLImplementationMockGL
) {
152 SetGLApiToNoContext();
156 GLStateRestorer
* GLContext::GetGLStateRestorer() {
157 return state_restorer_
.get();
160 void GLContext::SetGLStateRestorer(GLStateRestorer
* state_restorer
) {
161 state_restorer_
= make_scoped_ptr(state_restorer
);
164 void GLContext::SetSwapInterval(int interval
) {
165 swap_interval_
= interval
;
166 OnSetSwapInterval(force_swap_interval_zero_
? 0 : swap_interval_
);
169 void GLContext::ForceSwapIntervalZero(bool force
) {
170 force_swap_interval_zero_
= force
;
171 OnSetSwapInterval(force_swap_interval_zero_
? 0 : swap_interval_
);
174 bool GLContext::WasAllocatedUsingRobustnessExtension() {
178 bool GLContext::InitializeDynamicBindings() {
179 DCHECK(IsCurrent(NULL
));
180 static bool initialized
= false;
183 initialized
= InitializeDynamicGLBindings(GetGLImplementation(), this);
185 LOG(ERROR
) << "Could not initialize dynamic bindings.";
189 void GLContext::SetupForVirtualization() {
190 if (!virtual_gl_api_
) {
191 virtual_gl_api_
.reset(new VirtualGLApi());
192 virtual_gl_api_
->Initialize(&g_driver_gl
, this);
196 bool GLContext::MakeVirtuallyCurrent(
197 GLContext
* virtual_context
, GLSurface
* surface
) {
198 DCHECK(virtual_gl_api_
);
199 if (!ForceGpuSwitchIfNeeded())
201 return virtual_gl_api_
->MakeCurrent(virtual_context
, surface
);
204 void GLContext::OnReleaseVirtuallyCurrent(GLContext
* virtual_context
) {
206 virtual_gl_api_
->OnReleaseVirtuallyCurrent(virtual_context
);
209 void GLContext::SetRealGLApi() {
213 GLContextReal::GLContextReal(GLShareGroup
* share_group
)
214 : GLContext(share_group
) {}
216 scoped_refptr
<gfx::GPUTimingClient
> GLContextReal::CreateGPUTimingClient() {
218 gpu_timing_
.reset(new gfx::GPUTiming(this));
220 return gpu_timing_
->CreateGPUTimingClient();
223 GLContextReal::~GLContextReal() {}
225 void GLContextReal::SetCurrent(GLSurface
* surface
) {
226 GLContext::SetCurrent(surface
);
227 current_real_context_
.Pointer()->Set(surface
? this : NULL
);