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 19namespace gfx { 20 21namespace { 22base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky 23 current_context_ = LAZY_INSTANCE_INITIALIZER; 24 25base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky 26 current_real_context_ = LAZY_INSTANCE_INITIALIZER; 27} // namespace 28 29GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {} 30 31GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() { 32 if (!canceled_ && GetCurrent()) { 33 GetCurrent()->ReleaseCurrent(NULL); 34 } 35} 36 37void GLContext::ScopedReleaseCurrent::Cancel() { 38 canceled_ = true; 39} 40 41GLContext::FlushEvent::FlushEvent() { 42} 43 44GLContext::FlushEvent::~FlushEvent() { 45} 46 47void GLContext::FlushEvent::Signal() { 48 flag_.Set(); 49} 50 51bool GLContext::FlushEvent::IsSignaled() { 52 return flag_.IsSet(); 53} 54 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 62GLContext::~GLContext() { 63 share_group_->RemoveContext(this); 64 if (GetCurrent() == this) { 65 SetCurrent(NULL); 66 } 67} 68 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 76bool GLContext::GetTotalGpuMemory(size_t* bytes) { 77 DCHECK(bytes); 78 *bytes = 0; 79 return false; 80} 81 82void GLContext::SetSafeToForceGpuSwitch() { 83} 84 85void GLContext::SetUnbindFboOnMakeCurrent() { 86 NOTIMPLEMENTED(); 87} 88 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 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 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 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 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 129GLShareGroup* GLContext::share_group() { 130 return share_group_.get(); 131} 132 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 150GLContext* GLContext::GetCurrent() { 151 return current_context_.Pointer()->Get(); 152} 153 154GLContext* GLContext::GetRealCurrent() { 155 return current_real_context_.Pointer()->Get(); 156} 157 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 169GLStateRestorer* GLContext::GetGLStateRestorer() { 170 return state_restorer_.get(); 171} 172 173void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) { 174 state_restorer_ = make_scoped_ptr(state_restorer); 175} 176 177bool GLContext::WasAllocatedUsingRobustnessExtension() { 178 return false; 179} 180 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 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 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 205void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) { 206 if (virtual_gl_api_) 207 virtual_gl_api_->OnReleaseVirtuallyCurrent(virtual_context); 208} 209 210void GLContext::SetRealGLApi() { 211 SetGLToRealGLApi(); 212} 213 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 220GLContextReal::GLContextReal(GLShareGroup* share_group) 221 : GLContext(share_group) {} 222 223GLContextReal::~GLContextReal() {} 224 225void GLContextReal::SetCurrent(GLSurface* surface) { 226 GLContext::SetCurrent(surface); 227 current_real_context_.Pointer()->Set(surface ? this : NULL); 228} 229 230} // namespace gfx 231