Home | History | Annotate | Download | only in gl
      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 
     29 GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
     30 
     31 GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
     32   if (!canceled_ && GetCurrent()) {
     33     GetCurrent()->ReleaseCurrent(NULL);
     34   }
     35 }
     36 
     37 void GLContext::ScopedReleaseCurrent::Cancel() {
     38   canceled_ = true;
     39 }
     40 
     41 GLContext::FlushEvent::FlushEvent() {
     42 }
     43 
     44 GLContext::FlushEvent::~FlushEvent() {
     45 }
     46 
     47 void GLContext::FlushEvent::Signal() {
     48   flag_.Set();
     49 }
     50 
     51 bool GLContext::FlushEvent::IsSignaled() {
     52   return flag_.IsSet();
     53 }
     54 
     55 GLContext::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 
     62 GLContext::~GLContext() {
     63   share_group_->RemoveContext(this);
     64   if (GetCurrent() == this) {
     65     SetCurrent(NULL);
     66   }
     67 }
     68 
     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);
     73   return flush_event;
     74 }
     75 
     76 bool GLContext::GetTotalGpuMemory(size_t* bytes) {
     77   DCHECK(bytes);
     78   *bytes = 0;
     79   return false;
     80 }
     81 
     82 void GLContext::SetSafeToForceGpuSwitch() {
     83 }
     84 
     85 void GLContext::SetUnbindFboOnMakeCurrent() {
     86   NOTIMPLEMENTED();
     87 }
     88 
     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 : "");
     93 }
     94 
     95 std::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 
    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 : "");
    107 }
    108 
    109 bool 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 
    119 const 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 
    129 GLShareGroup* GLContext::share_group() {
    130   return share_group_.get();
    131 }
    132 
    133 bool 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 
    150 GLContext* GLContext::GetCurrent() {
    151   return current_context_.Pointer()->Get();
    152 }
    153 
    154 GLContext* GLContext::GetRealCurrent() {
    155   return current_real_context_.Pointer()->Get();
    156 }
    157 
    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();
    166   }
    167 }
    168 
    169 GLStateRestorer* GLContext::GetGLStateRestorer() {
    170   return state_restorer_.get();
    171 }
    172 
    173 void GLContext::SetGLStateRestorer(GLStateRestorer* state_restorer) {
    174   state_restorer_ = make_scoped_ptr(state_restorer);
    175 }
    176 
    177 bool GLContext::WasAllocatedUsingRobustnessExtension() {
    178   return false;
    179 }
    180 
    181 bool 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 
    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);
    196   }
    197 }
    198 
    199 bool GLContext::MakeVirtuallyCurrent(
    200     GLContext* virtual_context, GLSurface* surface) {
    201   DCHECK(virtual_gl_api_);
    202   return virtual_gl_api_->MakeCurrent(virtual_context, surface);
    203 }
    204 
    205 void GLContext::OnReleaseVirtuallyCurrent(GLContext* virtual_context) {
    206   if (virtual_gl_api_)
    207     virtual_gl_api_->OnReleaseVirtuallyCurrent(virtual_context);
    208 }
    209 
    210 void GLContext::SetRealGLApi() {
    211   SetGLToRealGLApi();
    212 }
    213 
    214 void GLContext::OnFlush() {
    215   for (size_t n = 0; n < flush_events_.size(); n++)
    216     flush_events_[n]->Signal();
    217   flush_events_.clear();
    218 }
    219 
    220 GLContextReal::GLContextReal(GLShareGroup* share_group)
    221     : GLContext(share_group) {}
    222 
    223 GLContextReal::~GLContextReal() {}
    224 
    225 void GLContextReal::SetCurrent(GLSurface* surface) {
    226   GLContext::SetCurrent(surface);
    227   current_real_context_.Pointer()->Set(surface ? this : NULL);
    228 }
    229 
    230 }  // namespace gfx
    231