15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/foundation_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/native_library.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gl/gl_context_stub_with_extensions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_gl_api_implementation.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_osmesa_api_implementation.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kOpenGLFrameworkPath[] =
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  impls->push_back(kGLImplementationDesktopGL);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  impls->push_back(kGLImplementationAppleGL);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  impls->push_back(kGLImplementationOSMesaGL);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool InitializeStaticGLBindings(GLImplementation implementation) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent reinitialization with a different implementation. Once the gpu
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unit tests have initialized with kGLImplementationMock, we don't want to
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // later switch to another GL implementation.
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the main thread or another to initialize these bindings
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after instituting restrictions on I/O. Going forward they will
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // likely be used in the browser process on most platforms. The
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one-time initialization cost is small, between 2 and 5 ms.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (implementation) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationOSMesaGL: {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // osmesa.so is located in the build directory. This code path is only
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // valid in a developer build environment.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath exe_path;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!PathService::Get(base::FILE_EXE, &exe_path)) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "PathService::Get failed.";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath bundle_path = base::mac::GetAppBundlePath(exe_path);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Some unit test targets depend on osmesa but aren't built as app
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // bundles. In that case, the .so is next to the executable.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (bundle_path.empty())
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bundle_path = exe_path;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath build_dir_path = bundle_path.DirName();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath osmesa_path = build_dir_path.Append("osmesa.so");
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When using OSMesa, just use OSMesaGetProcAddress to find entry points.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::NativeLibrary library = base::LoadNativeLibrary(osmesa_path, NULL);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!library) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "osmesa.so not found at " << osmesa_path.value();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLGetProcAddressProc get_proc_address =
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<GLGetProcAddressProc>(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::GetFunctionPointerFromNativeLibrary(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  library, "OSMesaGetProcAddress"));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!get_proc_address) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "OSMesaGetProcAddress not found.";
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::UnloadNativeLibrary(library);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetGLGetProcAddressProc(get_proc_address);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddGLNativeLibrary(library);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetGLImplementation(kGLImplementationOSMesaGL);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeStaticGLBindingsGL();
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeStaticGLBindingsOSMESA();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationDesktopGL:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationAppleGL: {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::NativeLibrary library = base::LoadNativeLibrary(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::FilePath(kOpenGLFrameworkPath), NULL);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!library) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "OpenGL framework not found";
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddGLNativeLibrary(library);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetGLImplementation(implementation);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeStaticGLBindingsGL();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationMockGL: {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetGLImplementation(kGLImplementationMockGL);
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeStaticGLBindingsGL();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool InitializeDynamicGLBindings(GLImplementation implementation,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLContext* context) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (implementation) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationOSMesaGL:
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeDynamicGLBindingsGL(context);
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeDynamicGLBindingsOSMESA(context);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationDesktopGL:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationAppleGL:
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      InitializeDynamicGLBindingsGL(context);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kGLImplementationMockGL:
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!context) {
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scoped_refptr<GLContextStubWithExtensions> mock_context(
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            new GLContextStubWithExtensions());
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        mock_context->SetGLVersionString("3.0");
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        InitializeDynamicGLBindingsGL(mock_context.get());
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        InitializeDynamicGLBindingsGL(context);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitializeDebugGLBindings() {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeDebugGLBindingsGL();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeDebugGLBindingsOSMESA();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearGLBindings() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearGLBindingsGL();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearGLBindingsOSMESA();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetGLImplementation(kGLImplementationNone);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnloadGLNativeLibraries();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) {
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return false;
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
156