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 "ui/gl/gl_surface.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "base/command_line.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/lazy_instance.h"
     13 #include "base/logging.h"
     14 #include "base/threading/thread_local.h"
     15 #include "ui/gl/gl_context.h"
     16 #include "ui/gl/gl_implementation.h"
     17 #include "ui/gl/gl_switches.h"
     18 
     19 #if defined(USE_X11)
     20 #include <X11/Xlib.h>
     21 #endif
     22 
     23 namespace gfx {
     24 
     25 namespace {
     26 base::LazyInstance<base::ThreadLocalPointer<GLSurface> >::Leaky
     27     current_surface_ = LAZY_INSTANCE_INITIALIZER;
     28 }  // namespace
     29 
     30 // static
     31 bool GLSurface::InitializeOneOff() {
     32   DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
     33 
     34   TRACE_EVENT0("gpu", "GLSurface::InitializeOneOff");
     35 
     36   std::vector<GLImplementation> allowed_impls;
     37   GetAllowedGLImplementations(&allowed_impls);
     38   DCHECK(!allowed_impls.empty());
     39 
     40   CommandLine* cmd = CommandLine::ForCurrentProcess();
     41 
     42   // The default implementation is always the first one in list.
     43   GLImplementation impl = allowed_impls[0];
     44   bool fallback_to_osmesa = false;
     45   if (cmd->HasSwitch(switches::kOverrideUseGLWithOSMesaForTests)) {
     46     impl = kGLImplementationOSMesaGL;
     47   } else if (cmd->HasSwitch(switches::kUseGL)) {
     48     std::string requested_implementation_name =
     49         cmd->GetSwitchValueASCII(switches::kUseGL);
     50     if (requested_implementation_name == "any") {
     51       fallback_to_osmesa = true;
     52     } else if (requested_implementation_name == "swiftshader") {
     53       impl = kGLImplementationEGLGLES2;
     54     } else {
     55       impl = GetNamedGLImplementation(requested_implementation_name);
     56       if (std::find(allowed_impls.begin(),
     57                     allowed_impls.end(),
     58                     impl) == allowed_impls.end()) {
     59         LOG(ERROR) << "Requested GL implementation is not available.";
     60         return false;
     61       }
     62     }
     63   }
     64 
     65   bool gpu_service_logging = cmd->HasSwitch(switches::kEnableGPUServiceLogging);
     66   bool disable_gl_drawing = cmd->HasSwitch(switches::kDisableGLDrawingForTests);
     67 
     68   return InitializeOneOffImplementation(
     69       impl, fallback_to_osmesa, gpu_service_logging, disable_gl_drawing);
     70 }
     71 
     72 // static
     73 bool GLSurface::InitializeOneOffImplementation(GLImplementation impl,
     74                                                bool fallback_to_osmesa,
     75                                                bool gpu_service_logging,
     76                                                bool disable_gl_drawing) {
     77   bool initialized =
     78       InitializeStaticGLBindings(impl) && InitializeOneOffInternal();
     79   if (!initialized && fallback_to_osmesa) {
     80     ClearGLBindings();
     81     initialized = InitializeStaticGLBindings(kGLImplementationOSMesaGL) &&
     82                   InitializeOneOffInternal();
     83   }
     84   if (!initialized)
     85     ClearGLBindings();
     86 
     87   if (initialized) {
     88     DVLOG(1) << "Using "
     89              << GetGLImplementationName(GetGLImplementation())
     90              << " GL implementation.";
     91     if (gpu_service_logging)
     92       InitializeDebugGLBindings();
     93     if (disable_gl_drawing)
     94       InitializeNullDrawGLBindings();
     95   }
     96   return initialized;
     97 }
     98 
     99 // static
    100 void GLSurface::InitializeOneOffForTests() {
    101   DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
    102 
    103 #if defined(USE_X11)
    104   XInitThreads();
    105 #endif
    106 
    107   bool use_osmesa = true;
    108 
    109   // We usually use OSMesa as this works on all bots. The command line can
    110   // override this behaviour to use hardware GL.
    111   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGpuInTests))
    112     use_osmesa = false;
    113 
    114 #if defined(OS_ANDROID)
    115   // On Android we always use hardware GL.
    116   use_osmesa = false;
    117 #endif
    118 
    119   std::vector<GLImplementation> allowed_impls;
    120   GetAllowedGLImplementations(&allowed_impls);
    121   DCHECK(!allowed_impls.empty());
    122 
    123   GLImplementation impl = allowed_impls[0];
    124   if (use_osmesa)
    125     impl = kGLImplementationOSMesaGL;
    126 
    127   DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL))
    128       << "kUseGL has not effect in tests";
    129 
    130   bool fallback_to_osmesa = false;
    131   bool gpu_service_logging = false;
    132   bool disable_gl_drawing = true;
    133 
    134   CHECK(InitializeOneOffImplementation(
    135       impl, fallback_to_osmesa, gpu_service_logging, disable_gl_drawing));
    136 }
    137 
    138 // static
    139 void GLSurface::InitializeOneOffWithMockBindingsForTests() {
    140   DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL))
    141       << "kUseGL has not effect in tests";
    142 
    143   // This method may be called multiple times in the same process to set up
    144   // mock bindings in different ways.
    145   ClearGLBindings();
    146 
    147   bool fallback_to_osmesa = false;
    148   bool gpu_service_logging = false;
    149   bool disable_gl_drawing = false;
    150 
    151   CHECK(InitializeOneOffImplementation(kGLImplementationMockGL,
    152                                        fallback_to_osmesa,
    153                                        gpu_service_logging,
    154                                        disable_gl_drawing));
    155 }
    156 
    157 // static
    158 void GLSurface::InitializeDynamicMockBindingsForTests(GLContext* context) {
    159   CHECK(InitializeDynamicGLBindings(kGLImplementationMockGL, context));
    160 }
    161 
    162 GLSurface::GLSurface() {}
    163 
    164 bool GLSurface::Initialize() {
    165   return true;
    166 }
    167 
    168 bool GLSurface::Resize(const gfx::Size& size) {
    169   NOTIMPLEMENTED();
    170   return false;
    171 }
    172 
    173 bool GLSurface::Recreate() {
    174   NOTIMPLEMENTED();
    175   return false;
    176 }
    177 
    178 bool GLSurface::DeferDraws() {
    179   return false;
    180 }
    181 
    182 bool GLSurface::SupportsPostSubBuffer() {
    183   return false;
    184 }
    185 
    186 unsigned int GLSurface::GetBackingFrameBufferObject() {
    187   return 0;
    188 }
    189 
    190 bool GLSurface::PostSubBuffer(int x, int y, int width, int height) {
    191   return false;
    192 }
    193 
    194 bool GLSurface::OnMakeCurrent(GLContext* context) {
    195   return true;
    196 }
    197 
    198 bool GLSurface::SetBackbufferAllocation(bool allocated) {
    199   return true;
    200 }
    201 
    202 void GLSurface::SetFrontbufferAllocation(bool allocated) {
    203 }
    204 
    205 void* GLSurface::GetShareHandle() {
    206   NOTIMPLEMENTED();
    207   return NULL;
    208 }
    209 
    210 void* GLSurface::GetDisplay() {
    211   NOTIMPLEMENTED();
    212   return NULL;
    213 }
    214 
    215 void* GLSurface::GetConfig() {
    216   NOTIMPLEMENTED();
    217   return NULL;
    218 }
    219 
    220 unsigned GLSurface::GetFormat() {
    221   NOTIMPLEMENTED();
    222   return 0;
    223 }
    224 
    225 VSyncProvider* GLSurface::GetVSyncProvider() {
    226   return NULL;
    227 }
    228 
    229 GLSurface* GLSurface::GetCurrent() {
    230   return current_surface_.Pointer()->Get();
    231 }
    232 
    233 GLSurface::~GLSurface() {
    234   if (GetCurrent() == this)
    235     SetCurrent(NULL);
    236 }
    237 
    238 void GLSurface::SetCurrent(GLSurface* surface) {
    239   current_surface_.Pointer()->Set(surface);
    240 }
    241 
    242 bool GLSurface::ExtensionsContain(const char* c_extensions, const char* name) {
    243   DCHECK(name);
    244   if (!c_extensions)
    245     return false;
    246   std::string extensions(c_extensions);
    247   extensions += " ";
    248 
    249   std::string delimited_name(name);
    250   delimited_name += " ";
    251 
    252   return extensions.find(delimited_name) != std::string::npos;
    253 }
    254 
    255 GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {}
    256 
    257 bool GLSurfaceAdapter::Initialize() {
    258   return surface_->Initialize();
    259 }
    260 
    261 void GLSurfaceAdapter::Destroy() {
    262   surface_->Destroy();
    263 }
    264 
    265 bool GLSurfaceAdapter::Resize(const gfx::Size& size) {
    266   return surface_->Resize(size);
    267 }
    268 
    269 bool GLSurfaceAdapter::Recreate() {
    270   return surface_->Recreate();
    271 }
    272 
    273 bool GLSurfaceAdapter::DeferDraws() {
    274   return surface_->DeferDraws();
    275 }
    276 
    277 bool GLSurfaceAdapter::IsOffscreen() {
    278   return surface_->IsOffscreen();
    279 }
    280 
    281 bool GLSurfaceAdapter::SwapBuffers() {
    282   return surface_->SwapBuffers();
    283 }
    284 
    285 bool GLSurfaceAdapter::PostSubBuffer(int x, int y, int width, int height) {
    286   return surface_->PostSubBuffer(x, y, width, height);
    287 }
    288 
    289 bool GLSurfaceAdapter::SupportsPostSubBuffer() {
    290   return surface_->SupportsPostSubBuffer();
    291 }
    292 
    293 gfx::Size GLSurfaceAdapter::GetSize() {
    294   return surface_->GetSize();
    295 }
    296 
    297 void* GLSurfaceAdapter::GetHandle() {
    298   return surface_->GetHandle();
    299 }
    300 
    301 unsigned int GLSurfaceAdapter::GetBackingFrameBufferObject() {
    302   return surface_->GetBackingFrameBufferObject();
    303 }
    304 
    305 bool GLSurfaceAdapter::OnMakeCurrent(GLContext* context) {
    306   return surface_->OnMakeCurrent(context);
    307 }
    308 
    309 bool GLSurfaceAdapter::SetBackbufferAllocation(bool allocated) {
    310   return surface_->SetBackbufferAllocation(allocated);
    311 }
    312 
    313 void GLSurfaceAdapter::SetFrontbufferAllocation(bool allocated) {
    314   surface_->SetFrontbufferAllocation(allocated);
    315 }
    316 
    317 void* GLSurfaceAdapter::GetShareHandle() {
    318   return surface_->GetShareHandle();
    319 }
    320 
    321 void* GLSurfaceAdapter::GetDisplay() {
    322   return surface_->GetDisplay();
    323 }
    324 
    325 void* GLSurfaceAdapter::GetConfig() {
    326   return surface_->GetConfig();
    327 }
    328 
    329 unsigned GLSurfaceAdapter::GetFormat() {
    330   return surface_->GetFormat();
    331 }
    332 
    333 VSyncProvider* GLSurfaceAdapter::GetVSyncProvider() {
    334   return surface_->GetVSyncProvider();
    335 }
    336 
    337 GLSurfaceAdapter::~GLSurfaceAdapter() {}
    338 
    339 }  // namespace gfx
    340