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. 4 5 #include <string> 6 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 19 namespace gfx { 20 21 namespace { 22 base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky 23 current_context_ = LAZY_INSTANCE_INITIALIZER; 24 25 base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky 26 current_real_context_ = LAZY_INSTANCE_INITIALIZER; 27 } // namespace 28 ScopedReleaseCurrent()29GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {} 30 ~ScopedReleaseCurrent()31GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() { 32 if (!canceled_ && GetCurrent()) { 33 GetCurrent()->ReleaseCurrent(NULL); 34 } 35 } 36 Cancel()37void GLContext::ScopedReleaseCurrent::Cancel() { 38 canceled_ = true; 39 } 40 FlushEvent()41GLContext::FlushEvent::FlushEvent() { 42 } 43 ~FlushEvent()44GLContext::FlushEvent::~FlushEvent() { 45 } 46 Signal()47void GLContext::FlushEvent::Signal() { 48 flag_.Set(); 49 } 50 IsSignaled()51bool GLContext::FlushEvent::IsSignaled() { 52 return flag_.IsSet(); 53 } 54 GLContext(GLShareGroup * share_group)55GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) { 56 if (!share_group_.get()) 57 share_group_ = new GLShareGroup; 58 59 share_group_->AddContext(this); 60 } 61 ~GLContext()62GLContext::~GLContext() { 63 share_group_->RemoveContext(this); 64 if (GetCurrent() == this) { 65 SetCurrent(NULL); 66 } 67 } 68 SignalFlush()69scoped_refptr<GLContext::FlushEvent> GLContext::SignalFlush() { 70 DCHECK(IsCurrent(NULL)); 71 scoped_refptr<FlushEvent> flush_event = new FlushEvent(); 72 flush_events_.push_back(flush_event); 73 return flush_event; 74 } 75 GetTotalGpuMemory(size_t * bytes)76bool GLContext::GetTotalGpuMemory(size_t* bytes) { 77 DCHECK(bytes); 78 *bytes = 0; 79 return false; 80 } 81 SetSafeToForceGpuSwitch()82void GLContext::SetSafeToForceGpuSwitch() { 83 } 84 SetUnbindFboOnMakeCurrent()85void GLContext::SetUnbindFboOnMakeCurrent() { 86 NOTIMPLEMENTED(); 87 } 88 GetExtensions()89std::string GLContext::GetExtensions() { 90 DCHECK(IsCurrent(NULL)); 91 const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); 92 return std::string(ext ? ext : ""); 93 } 94 GetGLVersion()95std::string GLContext::GetGLVersion() { 96 DCHECK(IsCurrent(NULL)); 97 const char *version = 98 reinterpret_cast<const char*>(glGetString(GL_VERSION)); 99 return std::string(version ? version : ""); 100 } 101 GetGLRenderer()102std::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 : ""); 107 } 108 HasExtension(const char * name)109bool GLContext::HasExtension(const char* name) { 110 std::string extensions = GetExtensions(); 111 extensions += " "; 112 113 std::string delimited_name(name); 114 delimited_name += " "; 115 116 return extensions.find(delimited_name) != std::string::npos; 117 } 118 GetVersionInfo()119const GLVersionInfo* GLContext::GetVersionInfo() { 120 if(!version_info_) { 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())); 125 } 126 return version_info_.get(); 127 } 128 share_group()129GLShareGroup* GLContext::share_group() { 130 return share_group_.get(); 131 } 132 LosesAllContextsOnContextLost()133bool GLContext::LosesAllContextsOnContextLost() { 134 switch (GetGLImplementation()) { 135 case kGLImplementationDesktopGL: 136 return false; 137 case kGLImplementationEGLGLES2: 138 return true; 139 case kGLImplementationOSMesaGL: 140 case kGLImplementationAppleGL: 141 return false; 142 case kGLImplementationMockGL: 143 return false; 144 default: 145 NOTREACHED(); 146 return true; 147 } 148 } 149 GetCurrent()150GLContext* GLContext::GetCurrent() { 151 return current_context_.Pointer()->Get(); 152 } 153 GetRealCurrent()154GLContext* GLContext::GetRealCurrent() { 155 return current_real_context_.Pointer()->Get(); 156 } 157 SetCurrent(GLSurface * surface)158void 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(); 166 } 167 } 168 GetGLStateRestorer()169GLStateRestorer* GLContext::GetGLStateRestorer() { 170 return state_restorer_.get(); 171 } 172 SetGLStateRestorer(GLStateRestorer * state_restorer)173void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) { 174 state_restorer_ = make_scoped_ptr(state_restorer); 175 } 176 WasAllocatedUsingRobustnessExtension()177bool GLContext::WasAllocatedUsingRobustnessExtension() { 178 return false; 179 } 180 InitializeDynamicBindings()181bool GLContext::InitializeDynamicBindings() { 182 DCHECK(IsCurrent(NULL)); 183 static bool initialized = false; 184 if (initialized) 185 return initialized; 186 initialized = InitializeDynamicGLBindings(GetGLImplementation(), this); 187 if (!initialized) 188 LOG(ERROR) << "Could not initialize dynamic bindings."; 189 return initialized; 190 } 191 SetupForVirtualization()192void GLContext::SetupForVirtualization() { 193 if (!virtual_gl_api_) { 194 virtual_gl_api_.reset(new VirtualGLApi()); 195 virtual_gl_api_->Initialize(&g_driver_gl, this); 196 } 197 } 198 MakeVirtuallyCurrent(GLContext * virtual_context,GLSurface * surface)199bool GLContext::MakeVirtuallyCurrent( 200 GLContext* virtual_context, GLSurface* surface) { 201 DCHECK(virtual_gl_api_); 202 return virtual_gl_api_->MakeCurrent(virtual_context, surface); 203 } 204 OnReleaseVirtuallyCurrent(GLContext * virtual_context)205void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) { 206 if (virtual_gl_api_) 207 virtual_gl_api_->OnReleaseVirtuallyCurrent(virtual_context); 208 } 209 SetRealGLApi()210void GLContext::SetRealGLApi() { 211 SetGLToRealGLApi(); 212 } 213 OnFlush()214void GLContext::OnFlush() { 215 for (size_t n = 0; n < flush_events_.size(); n++) 216 flush_events_[n]->Signal(); 217 flush_events_.clear(); 218 } 219 GLContextReal(GLShareGroup * share_group)220GLContextReal::GLContextReal(GLShareGroup* share_group) 221 : GLContext(share_group) {} 222 ~GLContextReal()223GLContextReal::~GLContextReal() {} 224 SetCurrent(GLSurface * surface)225void GLContextReal::SetCurrent(GLSurface* surface) { 226 GLContext::SetCurrent(surface); 227 current_real_context_.Pointer()->Set(surface ? this : NULL); 228 } 229 230 } // namespace gfx 231