Commit b2344801 authored by geofflang's avatar geofflang Committed by Commit bot

Add a --use-angle flag for selecting the ANGLE renderer.

 * Add support for selecting the new OpenGL renderer.
 * Remove the --use-warp flag and merge it into the --use-angle flag.

BUG=485541

Review URL: https://codereview.chromium.org/1123343004

Cr-Commit-Position: refs/heads/master@{#329436}
parent ba38d536
......@@ -412,8 +412,10 @@ void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
}
bool GpuDataManagerImplPrivate::ShouldUseWarp() const {
return use_warp_ ||
base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseWarp);
std::string angle_impl_flag =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kUseANGLE);
return use_warp_ || angle_impl_flag == gfx::kANGLEImplementationWARPName;
}
void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
......@@ -680,8 +682,10 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
gpu_info_.driver_version);
if (ShouldUseWarp())
command_line->AppendSwitch(switches::kUseWarp);
if (ShouldUseWarp() && !command_line->HasSwitch(switches::kUseANGLE)) {
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationWARPName);
}
}
void GpuDataManagerImplPrivate::AppendPluginCommandLine(
......
......@@ -62,6 +62,12 @@ extern "C" {
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
#endif /* EGL_ANGLE_platform_angle_d3d */
#ifndef EGL_ANGLE_platform_angle_opengl
#define EGL_ANGLE_platform_angle_opengl 1
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
#endif /* EGL_ANGLE_platform_angle_opengl */
using ui::GetLastEGLErrorString;
namespace gfx {
......@@ -140,19 +146,24 @@ void DeinitializeEgl() {
EGLDisplay GetPlatformANGLEDisplay(EGLNativeDisplayType native_display,
EGLenum platform_type,
EGLenum device_type) {
const EGLint display_attribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
platform_type,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
device_type,
EGL_NONE};
bool warpDevice) {
std::vector<EGLint> display_attribs;
display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
display_attribs.push_back(platform_type);
if (warpDevice) {
display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
}
display_attribs.push_back(EGL_NONE);
return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
reinterpret_cast<void*>(native_display),
display_attribs);
&display_attribs[0]);
}
enum DisplayType { DEFAULT, SWIFT_SHADER, ANGLE_WARP, ANGLE_D3D9, ANGLE_D3D11 };
EGLDisplay GetDisplayFromType(DisplayType display_type,
EGLNativeDisplayType native_display) {
switch (display_type) {
......@@ -161,16 +172,19 @@ EGLDisplay GetDisplayFromType(DisplayType display_type,
return eglGetDisplay(native_display);
case ANGLE_WARP:
return GetPlatformANGLEDisplay(native_display,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE);
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, true);
case ANGLE_D3D9:
return GetPlatformANGLEDisplay(
native_display, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
return GetPlatformANGLEDisplay(native_display,
EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, false);
case ANGLE_D3D11:
return GetPlatformANGLEDisplay(
native_display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
native_display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, false);
case ANGLE_OPENGL:
return GetPlatformANGLEDisplay(
native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, false);
case ANGLE_OPENGLES:
return GetPlatformANGLEDisplay(
native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, false);
default:
NOTREACHED();
return EGL_NO_DISPLAY;
......@@ -189,48 +203,72 @@ const char* DisplayTypeString(DisplayType display_type) {
return "D3D9";
case ANGLE_D3D11:
return "D3D11";
case ANGLE_OPENGL:
return "OpenGL";
case ANGLE_OPENGLES:
return "OpenGLES";
default:
NOTREACHED();
return "Err";
}
}
void GetInitDisplays(bool supports_angle_d3d,
std::vector<DisplayType>* init_displays) {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
bool using_swift_shader =
command_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader";
} // namespace
void GetEGLInitDisplays(bool supports_angle_d3d,
bool supports_angle_opengl,
const base::CommandLine* command_line,
std::vector<DisplayType>* init_displays) {
// SwiftShader does not use the platform extensions
if (using_swift_shader) {
if (command_line->GetSwitchValueASCII(switches::kUseGL) ==
kGLImplementationSwiftShaderName) {
init_displays->push_back(SWIFT_SHADER);
return;
}
// If we're missing the ANGLE extensions, fall back to default.
if (!supports_angle_d3d) {
init_displays->push_back(DEFAULT);
return;
}
std::string requested_renderer =
command_line->GetSwitchValueASCII(switches::kUseANGLE);
if (command_line->HasSwitch(switches::kUseWarp)) {
init_displays->push_back(ANGLE_WARP);
return;
if (supports_angle_d3d) {
bool use_angle_default =
!command_line->HasSwitch(switches::kUseANGLE) ||
requested_renderer == kANGLEImplementationDefaultName;
if (use_angle_default) {
// Default mode for ANGLE - try D3D11, else try D3D9
if (!command_line->HasSwitch(switches::kDisableD3D11)) {
init_displays->push_back(ANGLE_D3D11);
}
init_displays->push_back(ANGLE_D3D9);
} else {
if (requested_renderer == kANGLEImplementationD3D11Name) {
init_displays->push_back(ANGLE_D3D11);
}
if (requested_renderer == kANGLEImplementationD3D9Name) {
init_displays->push_back(ANGLE_D3D9);
}
if (requested_renderer == kANGLEImplementationWARPName) {
init_displays->push_back(ANGLE_WARP);
}
}
}
if (command_line->HasSwitch(switches::kDisableD3D11)) {
init_displays->push_back(ANGLE_D3D9);
return;
if (supports_angle_opengl) {
if (requested_renderer == kANGLEImplementationOpenGLName) {
init_displays->push_back(ANGLE_OPENGL);
}
if (requested_renderer == kANGLEImplementationOpenGLESName) {
init_displays->push_back(ANGLE_OPENGLES);
}
}
// Default mode for ANGLE - try D3D11, else try D3D9
init_displays->push_back(ANGLE_D3D11);
init_displays->push_back(ANGLE_D3D9);
// If no displays are available due to missing angle extensions or invalid
// flags, request the default display.
if (init_displays->empty()) {
init_displays->push_back(DEFAULT);
}
}
} // namespace
GLSurfaceEGL::GLSurfaceEGL() {
++g_num_surfaces;
if (!g_initialized) {
......@@ -418,15 +456,19 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay() {
eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
bool supports_angle_d3d = false;
bool supports_angle_opengl = false;
// Check for availability of ANGLE extensions.
if (client_extensions) {
if (client_extensions &&
ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle")) {
supports_angle_d3d =
ExtensionsContain(client_extensions, "ANGLE_platform_angle") &&
ExtensionsContain(client_extensions, "ANGLE_platform_angle_d3d");
ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_d3d");
supports_angle_opengl =
ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_opengl");
}
std::vector<DisplayType> init_displays;
GetInitDisplays(supports_angle_d3d, &init_displays);
GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
base::CommandLine::ForCurrentProcess(), &init_displays);
for (size_t disp_index = 0; disp_index < init_displays.size(); ++disp_index) {
DisplayType display_type = init_displays[disp_index];
......
......@@ -11,6 +11,7 @@
#include <string>
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/time/time.h"
#include "ui/gfx/geometry/size.h"
......@@ -23,6 +24,21 @@ namespace gfx {
// Get default EGL display for GLSurfaceEGL (differs by platform).
EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay();
enum DisplayType {
DEFAULT,
SWIFT_SHADER,
ANGLE_WARP,
ANGLE_D3D9,
ANGLE_D3D11,
ANGLE_OPENGL,
ANGLE_OPENGLES,
};
GL_EXPORT void GetEGLInitDisplays(bool supports_angle_d3d,
bool supports_angle_opengl,
const base::CommandLine* command_line,
std::vector<DisplayType>* init_displays);
// Interface for EGL surface.
class GL_EXPORT GLSurfaceEGL : public GLSurface {
public:
......
......@@ -14,6 +14,13 @@ const char kGLImplementationEGLName[] = "egl";
const char kGLImplementationSwiftShaderName[] = "swiftshader";
const char kGLImplementationMockName[] = "mock";
const char kANGLEImplementationDefaultName[] = "default";
const char kANGLEImplementationD3D9Name[] = "d3d9";
const char kANGLEImplementationD3D11Name[] = "d3d11";
const char kANGLEImplementationWARPName[] = "warp";
const char kANGLEImplementationOpenGLName[] = "gl";
const char kANGLEImplementationOpenGLESName[] = "gles";
} // namespace gfx
namespace switches {
......@@ -30,6 +37,16 @@ const char kEnableGPUServiceLogging[] = "enable-gpu-service-logging";
// Turns on calling TRACE for every GL call.
const char kEnableGPUServiceTracing[] = "enable-gpu-service-tracing";
// Select which ANGLE backend to use. Options are:
// default: Attempts several ANGLE renderers until one successfully
// initializes, varying ES support by platform.
// d3d9: Legacy D3D9 renderer, ES2 only.
// d3d11: D3D11 renderer, ES2 and ES3.
// warp: D3D11 renderer using software rasterization, ES2 and ES3.
// gl: Desktop GL renderer, ES2 and ES3.
// gles: GLES renderer, ES2 and ES3.
const char kUseANGLE[] = "use-angle";
// Select which implementation of GL the GPU process should use. Options are:
// desktop: whatever desktop OpenGL the user has installed (Linux and Mac
// default).
......@@ -55,9 +72,6 @@ const char kTestGLLib[] = "test-gl-lib";
// Use hardware gpu, if available, for tests.
const char kUseGpuInTests[] = "use-gpu-in-tests";
// On Windows only: use the WARP software rasterizer in the GPU process.
const char kUseWarp[] = "use-warp";
// Enable OpenGL ES 3 APIs without proper service side validation.
const char kEnableUnsafeES3APIs[] = "enable-unsafe-es3-apis";
......@@ -81,7 +95,7 @@ const char* kGLSwitchesCopiedFromGpuProcessHost[] = {
kGpuNoContextLost,
kDisableGLDrawingForTests,
kOverrideUseGLWithOSMesaForTests,
kUseWarp,
kUseANGLE,
};
const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches =
arraysize(kGLSwitchesCopiedFromGpuProcessHost);
......
......@@ -19,6 +19,13 @@ GL_EXPORT extern const char kGLImplementationEGLName[];
GL_EXPORT extern const char kGLImplementationSwiftShaderName[];
extern const char kGLImplementationMockName[];
GL_EXPORT extern const char kANGLEImplementationDefaultName[];
GL_EXPORT extern const char kANGLEImplementationD3D9Name[];
GL_EXPORT extern const char kANGLEImplementationD3D11Name[];
GL_EXPORT extern const char kANGLEImplementationWARPName[];
GL_EXPORT extern const char kANGLEImplementationOpenGLName[];
GL_EXPORT extern const char kANGLEImplementationOpenGLESName[];
} // namespace gfx
namespace switches {
......@@ -31,11 +38,11 @@ GL_EXPORT extern const char kGpuNoContextLost[];
GL_EXPORT extern const char kSupportsDualGpus[];
GL_EXPORT extern const char kUseANGLE[];
GL_EXPORT extern const char kUseGL[];
GL_EXPORT extern const char kSwiftShaderPath[];
GL_EXPORT extern const char kTestGLLib[];
GL_EXPORT extern const char kUseGpuInTests[];
GL_EXPORT extern const char kUseWarp[];
GL_EXPORT extern const char kEnableUnsafeES3APIs[];
// These flags are used by the test harness code, not passed in by users.
......
......@@ -24,6 +24,17 @@
'<(DEPTH)/testing/android/native_test.gyp:native_test_native_code',
],
}],
['OS in ("win", "android", "linux")', {
'sources': [
'test/egl_initialization_displays_unittest.cc',
],
'dependencies': [
'<(DEPTH)/ui/gl/gl.gyp:gl',
],
'include_dirs': [
'<(DEPTH)/third_party/khronos',
],
}],
],
}
],
......
// Copyright 2015 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 "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_surface_egl.h"
namespace {
TEST(EGLInitializationDisplaysTest, DisableD3D11) {
scoped_ptr<base::CommandLine> command_line(
new base::CommandLine(base::CommandLine::NO_PROGRAM));
std::vector<gfx::DisplayType> displays;
// using --disable-d3d11 with the default --use-angle should never return
// D3D11.
command_line->AppendSwitch(switches::kDisableD3D11);
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_EQ(std::find(displays.begin(), displays.end(), gfx::ANGLE_D3D11),
displays.end());
// Specifically requesting D3D11 should always return it if the extension is
// available
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationD3D11Name);
displays.clear();
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::ANGLE_D3D11),
displays.end());
EXPECT_EQ(displays.size(), 1u);
// Specifically requesting D3D11 should not return D3D11 if the extension is
// not available
displays.clear();
GetEGLInitDisplays(false, true, command_line.get(), &displays);
EXPECT_EQ(std::find(displays.begin(), displays.end(), gfx::ANGLE_D3D11),
displays.end());
}
TEST(EGLInitializationDisplaysTest, SwiftShader) {
scoped_ptr<base::CommandLine> command_line(
new base::CommandLine(base::CommandLine::NO_PROGRAM));
std::vector<gfx::DisplayType> displays;
// If swiftshader is requested, only SWIFT_SHADER should be returned
command_line->AppendSwitchASCII(switches::kUseGL,
gfx::kGLImplementationSwiftShaderName);
displays.clear();
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::SWIFT_SHADER),
displays.end());
EXPECT_EQ(displays.size(), 1u);
// Even if there are other flags, swiftshader should take prescedence
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationD3D11Name);
displays.clear();
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::SWIFT_SHADER),
displays.end());
EXPECT_EQ(displays.size(), 1u);
}
TEST(EGLInitializationDisplaysTest, DefaultRenderers) {
scoped_ptr<base::CommandLine> command_line(
new base::CommandLine(base::CommandLine::NO_PROGRAM));
// Default without --use-angle flag
std::vector<gfx::DisplayType> default_no_flag_displays;
GetEGLInitDisplays(true, true, command_line.get(), &default_no_flag_displays);
EXPECT_FALSE(default_no_flag_displays.empty());
// Default with --use-angle flag
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationDefaultName);
std::vector<gfx::DisplayType> default_with_flag_displays;
GetEGLInitDisplays(true, true, command_line.get(),
&default_with_flag_displays);
EXPECT_FALSE(default_with_flag_displays.empty());
// Make sure the same results are returned
EXPECT_EQ(default_no_flag_displays, default_with_flag_displays);
}
TEST(EGLInitializationDisplaysTest, NonDefaultRenderers) {
scoped_ptr<base::CommandLine> command_line(
new base::CommandLine(base::CommandLine::NO_PROGRAM));
std::vector<gfx::DisplayType> displays;
// WARP
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationWARPName);
displays.clear();
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::ANGLE_WARP),
displays.end());
EXPECT_EQ(displays.size(), 1u);
// OpenGL
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationOpenGLName);
displays.clear();
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::ANGLE_OPENGL),
displays.end());
EXPECT_EQ(displays.size(), 1u);
// OpenGLES
command_line->AppendSwitchASCII(switches::kUseANGLE,
gfx::kANGLEImplementationOpenGLESName);
displays.clear();
GetEGLInitDisplays(true, true, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::ANGLE_OPENGLES),
displays.end());
EXPECT_EQ(displays.size(), 1u);
}
TEST(EGLInitializationDisplaysTest, NoExtensions) {
scoped_ptr<base::CommandLine> command_line(
new base::CommandLine(base::CommandLine::NO_PROGRAM));
// With no angle platform extensions, only DEFAULT should be available
std::vector<gfx::DisplayType> displays;
GetEGLInitDisplays(false, false, command_line.get(), &displays);
EXPECT_NE(std::find(displays.begin(), displays.end(), gfx::DEFAULT),
displays.end());
EXPECT_EQ(displays.size(), 1u);
}
} // namespace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment