blob: b42c8d6e36a7a9f898b209f5b194c59322302c4e [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// 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_factory.h"
#include <algorithm>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/init/gl_initializer.h"
namespace gl {
namespace init {
namespace {
bool ShouldFallbackToSoftwareGL() {
const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
std::string requested_implementation_name =
cmd->GetSwitchValueASCII(switches::kUseGL);
if (cmd->HasSwitch(switches::kUseGL) &&
requested_implementation_name == "any") {
return true;
} else {
return false;
}
}
GLImplementation GetRequestedGLImplementation(bool* fallback_to_software_gl) {
const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
std::string requested_implementation_name =
cmd->GetSwitchValueASCII(switches::kUseGL);
if (requested_implementation_name == kGLImplementationDisabledName) {
return gl::kGLImplementationDisabled;
}
std::vector<GLImplementation> allowed_impls = GetAllowedGLImplementations();
if (cmd->HasSwitch(switches::kDisableES3GLContext)) {
auto iter = std::find(allowed_impls.begin(), allowed_impls.end(),
kGLImplementationDesktopGLCoreProfile);
if (iter != allowed_impls.end())
allowed_impls.erase(iter);
}
if (cmd->HasSwitch(switches::kDisableES3GLContextForTesting)) {
GLVersionInfo::DisableES3ForTesting();
}
// If the passthrough command decoder is enabled, put ANGLE first if allowed
if (gl::UsePassthroughCommandDecoder(cmd)) {
auto iter = std::find(allowed_impls.begin(), allowed_impls.end(),
kGLImplementationEGLANGLE);
if (iter != allowed_impls.end()) {
allowed_impls.erase(iter);
allowed_impls.insert(allowed_impls.begin(), kGLImplementationEGLANGLE);
}
}
if (allowed_impls.empty()) {
LOG(ERROR) << "List of allowed GL implementations is empty.";
return kGLImplementationNone;
}
// The default implementation is always the first one in list.
GLImplementation impl = allowed_impls[0];
*fallback_to_software_gl = false;
if (cmd->HasSwitch(switches::kOverrideUseSoftwareGLForTests)) {
impl = GetSoftwareGLImplementation();
} else if (cmd->HasSwitch(switches::kUseGL)) {
if (requested_implementation_name == "any") {
*fallback_to_software_gl = true;
} else if ((requested_implementation_name ==
kGLImplementationSwiftShaderName) ||
(requested_implementation_name ==
kGLImplementationSwiftShaderForWebGLName)) {
impl = kGLImplementationSwiftShaderGL;
} else {
impl = GetNamedGLImplementation(requested_implementation_name);
if (!base::Contains(allowed_impls, impl)) {
LOG(ERROR) << "Requested GL implementation is not available.";
return kGLImplementationNone;
}
}
}
return impl;
}
bool InitializeGLOneOffPlatformHelper(bool init_extensions) {
TRACE_EVENT1("gpu,startup", "gl::init::InitializeGLOneOffPlatformHelper",
"init_extensions", init_extensions);
bool fallback_to_software_gl = ShouldFallbackToSoftwareGL();
const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
bool gpu_service_logging = cmd->HasSwitch(switches::kEnableGPUServiceLogging);
bool disable_gl_drawing = cmd->HasSwitch(switches::kDisableGLDrawingForTests);
return InitializeGLOneOffPlatformImplementation(
fallback_to_software_gl, gpu_service_logging, disable_gl_drawing,
init_extensions);
}
} // namespace
bool InitializeGLOneOff() {
TRACE_EVENT0("gpu,startup", "gl::init::InitializeOneOff");
if (!InitializeStaticGLBindingsOneOff())
return false;
if (GetGLImplementation() == kGLImplementationDisabled)
return true;
return InitializeGLOneOffPlatformHelper(true);
}
bool InitializeGLNoExtensionsOneOff(bool init_bindings) {
TRACE_EVENT1("gpu,startup", "gl::init::InitializeNoExtensionsOneOff",
"init_bindings", init_bindings);
if (init_bindings) {
if (!InitializeStaticGLBindingsOneOff())
return false;
if (GetGLImplementation() == kGLImplementationDisabled)
return true;
}
return InitializeGLOneOffPlatformHelper(false);
}
bool InitializeStaticGLBindingsOneOff() {
DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
bool fallback_to_software_gl = false;
GLImplementation impl =
GetRequestedGLImplementation(&fallback_to_software_gl);
if (impl == gl::kGLImplementationDisabled) {
gl::SetGLImplementation(gl::kGLImplementationDisabled);
return true;
} else if (impl == gl::kGLImplementationNone) {
return false;
}
return InitializeStaticGLBindingsImplementation(impl,
fallback_to_software_gl);
}
bool InitializeStaticGLBindingsImplementation(GLImplementation impl,
bool fallback_to_software_gl) {
if (impl == GetSoftwareGLImplementation())
fallback_to_software_gl = false;
bool initialized = InitializeStaticGLBindings(impl);
if (!initialized && fallback_to_software_gl) {
ShutdownGL(/*due_to_fallback*/ true);
initialized = InitializeStaticGLBindings(GetSoftwareGLImplementation());
}
if (!initialized) {
ShutdownGL(/*due_to_fallback*/ false);
return false;
}
return true;
}
bool InitializeGLOneOffPlatformImplementation(bool fallback_to_software_gl,
bool gpu_service_logging,
bool disable_gl_drawing,
bool init_extensions) {
if (GetGLImplementation() == GetSoftwareGLImplementation())
fallback_to_software_gl = false;
bool initialized = InitializeGLOneOffPlatform();
if (!initialized && fallback_to_software_gl) {
ShutdownGL(/*due_to_fallback*/ true);
initialized = InitializeStaticGLBindings(GetSoftwareGLImplementation()) &&
InitializeGLOneOffPlatform();
}
if (initialized && init_extensions) {
initialized = InitializeExtensionSettingsOneOffPlatform();
}
if (!initialized)
ShutdownGL(false);
if (initialized) {
DVLOG(1) << "Using " << GetGLImplementationName(GetGLImplementation())
<< " GL implementation.";
if (gpu_service_logging)
InitializeDebugGLBindings();
if (disable_gl_drawing)
InitializeNullDrawGLBindings();
}
return initialized;
}
void ShutdownGL(bool due_to_fallback) {
ShutdownGLPlatform();
UnloadGLNativeLibraries(due_to_fallback);
SetGLImplementation(kGLImplementationNone);
}
scoped_refptr<GLSurface> CreateOffscreenGLSurface(const gfx::Size& size) {
return CreateOffscreenGLSurfaceWithFormat(size, GLSurfaceFormat());
}
} // namespace init
} // namespace gl