Commit 5a6bcfe5 authored by dyen's avatar dyen Committed by Commit bot

Added switch to disable specified GL extensions.

It is now possible to remove extensions from the GL_EXTENSIONS string
by specifying "--disable-gl-extensions=extension1,extension2".

R=sievers@chromium.org
BUG=482067

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

Cr-Commit-Position: refs/heads/master@{#329752}
parent 0b93e0d3
......@@ -319,10 +319,14 @@
'../ui/base/ui_base_tests.gyp:ui_base_unittests',
'../ui/display/display.gyp:display_unittests',
'../ui/gfx/gfx_tests.gyp:gfx_unittests',
'../ui/gl/gl_tests.gyp:gl_unittests',
'../url/url.gyp:url_unittests',
],
'conditions': [
['OS!="ios"', {
'dependencies': [
'../ui/gl/gl_tests.gyp:gl_unittests',
],
}],
['OS!="ios" and OS!="mac"', {
'dependencies': [
'../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
......
......@@ -77,6 +77,7 @@ static const char* const kSwitchNames[] = {
switches::kDisableBreakpad,
switches::kDisableGpuSandbox,
switches::kDisableGpuWatchdog,
switches::kDisableGLExtensions,
switches::kDisableLogging,
switches::kDisableSeccompFilterSandbox,
#if defined(ENABLE_WEBRTC)
......
......@@ -280,6 +280,7 @@ source_set("gl_unittest_utils") {
test("gl_unittests") {
sources = [
"gl_api_unittest.cc",
"test/run_all_unittests.cc",
]
......
// 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 "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
namespace gfx {
class GLApiTest : public testing::Test {
public:
void SetUp() override {
fake_extension_string_ = "";
num_fake_extension_strings_ = 0;
fake_extension_strings_ = nullptr;
driver_.reset(new DriverGL());
api_.reset(new RealGLApi());
driver_->fn.glGetStringFn = &FakeGetString;
driver_->fn.glGetStringiFn = &FakeGetStringi;
driver_->fn.glGetIntegervFn = &FakeGetIntegervFn;
}
void TearDown() override {
api_.reset(nullptr);
driver_.reset(nullptr);
SetGLImplementation(kGLImplementationNone);
fake_extension_string_ = "";
num_fake_extension_strings_ = 0;
fake_extension_strings_ = nullptr;
}
void InitializeAPI(base::CommandLine* command_line) {
api_.reset(new RealGLApi());
if (command_line)
api_->InitializeWithCommandLine(driver_.get(), command_line);
else
api_->Initialize(driver_.get());
}
void SetFakeExtensionString(const char* fake_string) {
SetGLImplementation(kGLImplementationDesktopGL);
fake_extension_string_ = fake_string;
}
void SetFakeExtensionStrings(const char** fake_strings, uint32_t count) {
SetGLImplementation(kGLImplementationDesktopGLCoreProfile);
num_fake_extension_strings_ = count;
fake_extension_strings_ = fake_strings;
}
static const GLubyte* GL_BINDING_CALL FakeGetString(GLenum name) {
return reinterpret_cast<const GLubyte*>(fake_extension_string_);
}
static void GL_BINDING_CALL FakeGetIntegervFn(GLenum pname, GLint* params) {
*params = num_fake_extension_strings_;
}
static const GLubyte* GL_BINDING_CALL FakeGetStringi(GLenum name,
GLuint index) {
return (index < num_fake_extension_strings_) ?
reinterpret_cast<const GLubyte*>(fake_extension_strings_[index]) :
nullptr;
}
const char* GetExtensions() {
return reinterpret_cast<const char*>(api_->glGetStringFn(GL_EXTENSIONS));
}
uint32_t GetNumExtensions() {
GLint num_extensions = 0;
api_->glGetIntegervFn(GL_NUM_EXTENSIONS, &num_extensions);
return static_cast<uint32_t>(num_extensions);
}
const char* GetExtensioni(uint32_t index) {
return reinterpret_cast<const char*>(api_->glGetStringiFn(GL_EXTENSIONS,
index));
}
protected:
static const char* fake_extension_string_;
static uint32_t num_fake_extension_strings_;
static const char** fake_extension_strings_;
scoped_ptr<DriverGL> driver_;
scoped_ptr<RealGLApi> api_;
};
const char* GLApiTest::fake_extension_string_ = "";
uint32_t GLApiTest::num_fake_extension_strings_ = 0;
const char** GLApiTest::fake_extension_strings_ = nullptr;
TEST_F(GLApiTest, DisabledExtensionStringTest) {
static const char* kFakeExtensions = "GL_EXT_1 GL_EXT_2 GL_EXT_3 GL_EXT_4";
static const char* kFakeDisabledExtensions = "GL_EXT_1,GL_EXT_2,GL_FAKE";
static const char* kFilteredExtensions = "GL_EXT_3 GL_EXT_4";
SetFakeExtensionString(kFakeExtensions);
InitializeAPI(nullptr);
EXPECT_STREQ(kFakeExtensions, GetExtensions());
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
kFakeDisabledExtensions);
InitializeAPI(&command_line);
EXPECT_STREQ(kFilteredExtensions, GetExtensions());
}
TEST_F(GLApiTest, DisabledExtensionStringIndexTest) {
static const char* kFakeExtensions[] = {
"GL_EXT_1",
"GL_EXT_2",
"GL_EXT_3",
"GL_EXT_4"
};
static const char* kFakeDisabledExtensions = "GL_EXT_1,GL_EXT_2,GL_FAKE";
static const char* kFilteredExtensions[] = {
"GL_EXT_3",
"GL_EXT_4"
};
SetFakeExtensionStrings(kFakeExtensions, arraysize(kFakeExtensions));
InitializeAPI(nullptr);
EXPECT_EQ(arraysize(kFakeExtensions), GetNumExtensions());
for (uint32_t i = 0; i < arraysize(kFakeExtensions); ++i) {
EXPECT_STREQ(kFakeExtensions[i], GetExtensioni(i));
}
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
kFakeDisabledExtensions);
InitializeAPI(&command_line);
EXPECT_EQ(arraysize(kFilteredExtensions), GetNumExtensions());
for (uint32_t i = 0; i < arraysize(kFilteredExtensions); ++i) {
EXPECT_STREQ(kFilteredExtensions[i], GetExtensioni(i));
}
}
} // namespace gpu
......@@ -8,6 +8,7 @@
#include <vector>
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
......@@ -309,7 +310,7 @@ void InitializeStaticGLBindingsGL() {
}
GLApi* GetCurrentGLApi() {
return g_current_gl_context_tls->Get();
return g_current_gl_context_tls ? g_current_gl_context_tls->Get() : nullptr;
}
void SetGLApi(GLApi* api) {
......@@ -404,7 +405,76 @@ RealGLApi::~RealGLApi() {
}
void RealGLApi::Initialize(DriverGL* driver) {
InitializeWithCommandLine(driver, base::CommandLine::ForCurrentProcess());
}
void RealGLApi::InitializeWithCommandLine(DriverGL* driver,
base::CommandLine* command_line) {
DCHECK(command_line);
InitializeBase(driver);
DCHECK(filtered_exts_.empty() && filtered_exts_str_.empty());
const std::string disabled_extensions = command_line->GetSwitchValueASCII(
switches::kDisableGLExtensions);
if (!disabled_extensions.empty()) {
std::vector<std::string> disabled_extensions_vec;
Tokenize(disabled_extensions, ", ;", &disabled_extensions_vec);
// Fill in filtered_exts_ vector first.
if (gfx::GetGLImplementation() !=
gfx::kGLImplementationDesktopGLCoreProfile) {
const char* gl_extensions = reinterpret_cast<const char*>(
GLApiBase::glGetStringFn(GL_EXTENSIONS));
if (gl_extensions)
base::SplitString(gl_extensions, ' ', &filtered_exts_);
} else {
GLint num_extensions = 0;
GLApiBase::glGetIntegervFn(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; ++i) {
const char* gl_extension = reinterpret_cast<const char*>(
GLApiBase::glGetStringiFn(GL_EXTENSIONS, i));
DCHECK(gl_extension != NULL);
filtered_exts_.push_back(gl_extension);
}
}
// Filter out extensions from the command line.
for (const std::string& disabled_ext : disabled_extensions_vec) {
filtered_exts_.erase(std::remove(filtered_exts_.begin(),
filtered_exts_.end(),
disabled_ext),
filtered_exts_.end());
}
// Construct filtered extensions string for GL_EXTENSIONS string lookups.
filtered_exts_str_ = JoinString(filtered_exts_, " ");
}
}
void RealGLApi::glGetIntegervFn(GLenum pname, GLint* params) {
if (!filtered_exts_.empty() && pname == GL_NUM_EXTENSIONS) {
*params = static_cast<GLint>(filtered_exts_.size());
} else {
GLApiBase::glGetIntegervFn(pname, params);
}
}
const GLubyte* RealGLApi::glGetStringFn(GLenum name) {
if (!filtered_exts_.empty() && name == GL_EXTENSIONS) {
return reinterpret_cast<const GLubyte*>(filtered_exts_str_.c_str());
}
return GLApiBase::glGetStringFn(name);
}
const GLubyte* RealGLApi::glGetStringiFn(GLenum name, GLuint index) {
if (!filtered_exts_str_.empty() && name == GL_EXTENSIONS) {
if (index >= filtered_exts_.size()) {
return NULL;
}
return reinterpret_cast<const GLubyte*>(filtered_exts_[index].c_str());
}
return GLApiBase::glGetStringiFn(name, index);
}
void RealGLApi::glFlushFn() {
......
......@@ -5,10 +5,15 @@
#ifndef UI_GL_GL_GL_API_IMPLEMENTATION_H_
#define UI_GL_GL_GL_API_IMPLEMENTATION_H_
#include <vector>
#include "base/compiler_specific.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_export.h"
namespace base {
class CommandLine;
}
namespace gpu {
namespace gles2 {
class GLES2Decoder;
......@@ -33,7 +38,7 @@ void SetGLApi(GLApi* api);
void SetGLApiToNoContext();
const GLVersionInfo* GetGLVersionInfo();
class GLApiBase : public GLApi {
class GL_EXPORT GLApiBase : public GLApi {
public:
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
......@@ -49,15 +54,25 @@ class GLApiBase : public GLApi {
};
// Implemenents the GL API by calling directly into the driver.
class RealGLApi : public GLApiBase {
class GL_EXPORT RealGLApi : public GLApiBase {
public:
RealGLApi();
~RealGLApi() override;
void Initialize(DriverGL* driver);
void InitializeWithCommandLine(DriverGL* driver,
base::CommandLine* command_line);
void glGetIntegervFn(GLenum pname, GLint* params) override;
const GLubyte* glGetStringFn(GLenum name) override;
const GLubyte* glGetStringiFn(GLenum name, GLuint index) override;
private:
void glFinishFn() override;
void glFlushFn() override;
// Filtered GL_EXTENSIONS we return to glGetString(i) calls.
std::vector<std::string> filtered_exts_;
std::string filtered_exts_str_;
};
// Inserts a TRACE for every GL call.
......
......@@ -83,6 +83,9 @@ const char kDisableGLDrawingForTests[] = "disable-gl-drawing-for-tests";
const char kOverrideUseGLWithOSMesaForTests[] =
"override-use-gl-with-osmesa-for-tests";
// Disables specified comma separated GL Extensions if found.
const char kDisableGLExtensions[] = "disable-gl-extensions";
// This is the list of switches passed from this file that are passed from the
// GpuProcessHost to the GPU Process. Add your switch to this list if you need
// to read it in the GPU process, else don't add it.
......
......@@ -44,6 +44,7 @@ GL_EXPORT extern const char kSwiftShaderPath[];
GL_EXPORT extern const char kTestGLLib[];
GL_EXPORT extern const char kUseGpuInTests[];
GL_EXPORT extern const char kEnableUnsafeES3APIs[];
GL_EXPORT extern const char kDisableGLExtensions[];
// These flags are used by the test harness code, not passed in by users.
GL_EXPORT extern const char kDisableGLDrawingForTests[];
......
......@@ -12,11 +12,13 @@
'type': '<(gtest_target_type)',
'sources': [
'test/run_all_unittests.cc',
'gl_api_unittest.cc',
],
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/base/base.gyp:test_support_base',
'<(DEPTH)/testing/gtest.gyp:gtest',
'gl.gyp:gl',
],
'conditions': [
['OS == "android"', {
......
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