1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/init/gl_initializer.h"
#include "base/apple/bundle_locations.h"
#include "base/apple/foundation_util.h"
#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/threading/thread_restrictions.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_display.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/gpu_switching_manager.h"
#include "ui/gl/init/gl_display_initializer.h"
#include "ui/gl/startup_trace.h"
namespace gl {
namespace init {
namespace {
#if !BUILDFLAG(USE_STATIC_ANGLE)
const char kGLESv2ANGLELibraryName[] = "libGLESv2.dylib";
const char kEGLANGLELibraryName[] = "libEGL.dylib";
bool InitializeStaticEGLInternalFromLibrary() {
// Some unit test targets depend on Angle/SwiftShader but aren't built
// as app bundles. In that case, the .dylib is next to the executable.
base::FilePath base_dir;
if (base::apple::AmIBundled()) {
base_dir = base::apple::FrameworkBundlePath().Append("Libraries");
} else {
if (!base::PathService::Get(base::FILE_EXE, &base_dir)) {
LOG(ERROR) << "PathService::Get failed.";
return false;
}
base_dir = base_dir.DirName();
}
base::FilePath glesv2_path = base_dir.Append(kGLESv2ANGLELibraryName);
base::NativeLibrary gles_library;
{
GPU_STARTUP_TRACE_EVENT("Load gles_library");
gles_library = LoadLibraryAndPrintError(glesv2_path);
}
if (!gles_library) {
return false;
}
base::FilePath egl_path = base_dir.Append(kEGLANGLELibraryName);
base::NativeLibrary egl_library;
{
GPU_STARTUP_TRACE_EVENT("Load egl_library");
egl_library = LoadLibraryAndPrintError(egl_path);
}
if (!egl_library) {
base::UnloadNativeLibrary(gles_library);
return false;
}
GLGetProcAddressProc get_proc_address =
reinterpret_cast<GLGetProcAddressProc>(
base::GetFunctionPointerFromNativeLibrary(egl_library,
"eglGetProcAddress"));
if (!get_proc_address) {
LOG(ERROR) << "eglGetProcAddress not found.";
base::UnloadNativeLibrary(egl_library);
base::UnloadNativeLibrary(gles_library);
return false;
}
SetGLGetProcAddressProc(get_proc_address);
// FIXME: SwiftShader must load symbols from libGLESv2 before libEGL on MacOS
// currently
AddGLNativeLibrary(gles_library);
AddGLNativeLibrary(egl_library);
return true;
}
#endif // !BUILDFLAG(USE_STATIC_ANGLE)
bool InitializeStaticEGLInternal(GLImplementationParts implementation) {
DCHECK(implementation.gl == kGLImplementationEGLANGLE);
#if BUILDFLAG(USE_STATIC_ANGLE)
if (!InitializeStaticANGLEEGL()) {
return false;
}
#else
if (!InitializeStaticEGLInternalFromLibrary()) {
return false;
}
#endif // !BUILDFLAG(USE_STATIC_ANGLE)
SetGLImplementationParts(implementation);
InitializeStaticGLBindingsGL();
InitializeStaticGLBindingsEGL();
return true;
}
} // namespace
GLDisplay* InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) {
GLDisplayEGL* display = GetDisplayEGL(gpu_preference);
switch (GetGLImplementation()) {
case kGLImplementationEGLGLES2:
case kGLImplementationEGLANGLE:
if (!InitializeDisplay(display, EGLDisplayPlatform(0))) {
LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
return nullptr;
}
break;
default:
break;
}
return display;
}
bool InitializeStaticGLBindings(GLImplementationParts implementation) {
// Prevent reinitialization with a different implementation. Once the gpu
// unit tests have initialized with kGLImplementationMock, we don't want to
// later switch to another GL implementation.
DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
// Allow the main thread or another to initialize these bindings
// after instituting restrictions on I/O. Going forward they will
// likely be used in the browser process on most platforms. The
// one-time initialization cost is small, between 2 and 5 ms.
base::ScopedAllowBlocking allow_blocking;
switch (implementation.gl) {
case kGLImplementationEGLGLES2:
case kGLImplementationEGLANGLE:
return InitializeStaticEGLInternal(implementation);
case kGLImplementationMockGL:
case kGLImplementationStubGL:
SetGLImplementationParts(implementation);
InitializeStaticGLBindingsGL();
return true;
default:
NOTREACHED();
}
}
void ShutdownGLPlatform(GLDisplay* display) {
ClearBindingsGL();
if (display)
display->Shutdown();
ClearBindingsEGL();
}
} // namespace init
} // namespace gl
|