| Index: gpu/command_buffer/tests/egl_test.cc
 | 
| diff --git a/gpu/command_buffer/tests/egl_test.cc b/gpu/command_buffer/tests/egl_test.cc
 | 
| index bf7e30e5f81610aafbdf6fa9072756a2f277ea3a..fceffdfbc4e6ba54e2f08eff22f976249948d078 100644
 | 
| --- a/gpu/command_buffer/tests/egl_test.cc
 | 
| +++ b/gpu/command_buffer/tests/egl_test.cc
 | 
| @@ -6,31 +6,621 @@
 | 
|  #include "testing/gtest/include/gtest/gtest.h"
 | 
|  
 | 
|  #include <EGL/egl.h>
 | 
| +#include <GLES2/gl2.h>
 | 
| +
 | 
| +#include "base/bind.h"
 | 
| +#include "base/synchronization/waitable_event.h"
 | 
| +#include "base/threading/thread.h"
 | 
| +#include "gpu/gles2_conform_support/egl/test_support.h"
 | 
|  
 | 
|  // This file tests EGL basic interface for command_buffer_gles2, the mode of
 | 
|  // command buffer where the code is compiled as a standalone dynamic library and
 | 
|  // exposed through EGL API.
 | 
|  namespace gpu {
 | 
|  
 | 
| -using testing::Test;
 | 
| +class EGLTest : public testing::Test {
 | 
| + public:
 | 
| +  void TearDown() override;
 | 
| +};
 | 
| +
 | 
| +void EGLTest::TearDown() {
 | 
| +  EXPECT_TRUE(eglReleaseThread());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, OnlyReleaseThread) {}
 | 
| +
 | 
| +TEST_F(EGLTest, GetDisplay) {
 | 
| +  EGLDisplay display1 = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display1, EGL_NO_DISPLAY);
 | 
| +
 | 
| +  EGLDisplay display2 = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_EQ(display1, display2);
 | 
| +
 | 
| +  EGLNativeDisplayType invalid_display_type =
 | 
| +      reinterpret_cast<EGLNativeDisplayType>(0x1);
 | 
| +  EXPECT_NE(invalid_display_type, EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_EQ(EGL_NO_DISPLAY, eglGetDisplay(invalid_display_type));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  // eglTerminate can be called with uninitialized display.
 | 
| +  EXPECT_TRUE(eglTerminate(display1));
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, GetError) {
 | 
| +  // GetError returns success.
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  // "calling eglGetError twice without any other intervening EGL calls will
 | 
| +  // always return EGL_SUCCESS on the second call"
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(display, EGL_EXTENSIONS));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  EXPECT_TRUE(eglTerminate(display));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +}
 | 
|  
 | 
| -TEST_F(Test, BasicEGLInitialization) {
 | 
| +TEST_F(EGLTest, Initialize) {
 | 
|    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| -  ASSERT_NE(display, EGL_NO_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
|  
 | 
|    // Test for no crash even though passing nullptrs for major, minor.
 | 
| -  EGLBoolean success = eglInitialize(display, nullptr, nullptr);
 | 
| -  ASSERT_TRUE(success);
 | 
| +  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 | 
|  
 | 
|    EGLint major = 0;
 | 
|    EGLint minor = 0;
 | 
| -  success = eglInitialize(display, &major, &minor);
 | 
| -  ASSERT_TRUE(success);
 | 
| -  ASSERT_EQ(major, 1);
 | 
| -  ASSERT_EQ(minor, 4);
 | 
| +  EXPECT_TRUE(eglInitialize(display, &major, &minor));
 | 
| +  EXPECT_EQ(major, 1);
 | 
| +  EXPECT_EQ(minor, 4);
 | 
| +
 | 
| +  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
 | 
| +  EXPECT_FALSE(eglInitialize(invalid_display, nullptr, nullptr));
 | 
| +  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, Terminate) {
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
| +
 | 
| +  // eglTerminate can be called multiple times without initialization.
 | 
| +  EXPECT_TRUE(eglTerminate(display));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +  EXPECT_TRUE(eglTerminate(display));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 | 
| +
 | 
| +  // eglTerminate can be called multiple times.
 | 
| +  EXPECT_TRUE(eglTerminate(display));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +  EXPECT_TRUE(eglTerminate(display));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  // After Terminate, an egl call returns not initialized.
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(display, EGL_EXTENSIONS));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +
 | 
| +  // Re-initialization of same display.
 | 
| +  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 | 
| +  EXPECT_NE(nullptr, eglQueryString(display, EGL_EXTENSIONS));
 | 
| +  EXPECT_TRUE(eglTerminate(display));
 | 
| +
 | 
| +  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
 | 
| +  EXPECT_FALSE(eglTerminate(invalid_display));
 | 
| +  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, QueryString) {
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(display, EGL_EXTENSIONS));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +  EXPECT_STREQ("", eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
 | 
| +
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(display, EGL_VERSION));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +  EXPECT_STREQ("1.4", eglQueryString(EGL_NO_DISPLAY, EGL_VERSION));
 | 
| +
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(display, EGL_CLIENT_APIS));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(EGL_NO_DISPLAY, EGL_CLIENT_APIS));
 | 
| +  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(display, EGL_VENDOR));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +  EXPECT_EQ(nullptr, eglQueryString(EGL_NO_DISPLAY, EGL_VENDOR));
 | 
| +  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
 | 
| +
 | 
| +  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  EXPECT_STREQ("", eglQueryString(display, EGL_EXTENSIONS));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +  EXPECT_STREQ("1.4", eglQueryString(display, EGL_VERSION));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +  EXPECT_STREQ("OpenGL_ES", eglQueryString(display, EGL_CLIENT_APIS));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +  EXPECT_STREQ("Google Inc.", eglQueryString(display, EGL_VENDOR));
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, GetConfigsUninitialized) {
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
| +
 | 
| +  EGLint num_config = 0;
 | 
| +  const int kConfigsSize = 5;
 | 
| +  EGLConfig configs[kConfigsSize] = {
 | 
| +      0,
 | 
| +  };
 | 
| +
 | 
| +  EXPECT_FALSE(eglGetConfigs(display, configs, kConfigsSize, &num_config));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +
 | 
| +  EXPECT_FALSE(eglGetConfigs(display, configs, kConfigsSize, nullptr));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, ChooseConfigUninitialized) {
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
| +
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_NONE};
 | 
| +  const int kConfigsSize = 5;
 | 
| +  EGLConfig configs[kConfigsSize] = {
 | 
| +      0,
 | 
| +  };
 | 
| +
 | 
| +  EXPECT_FALSE(eglChooseConfig(display, attrib_list, configs, kConfigsSize,
 | 
| +                               &num_config));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +
 | 
| +  EXPECT_FALSE(
 | 
| +      eglChooseConfig(display, attrib_list, configs, kConfigsSize, nullptr));
 | 
| +  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
 | 
| +}
 | 
| +
 | 
| +class EGLConfigTest : public EGLTest {
 | 
| + public:
 | 
| +  void SetUp() override;
 | 
| +
 | 
| + protected:
 | 
| +  void CheckConfigsExist(EGLint num_config);
 | 
| +
 | 
| +  enum { kConfigsSize = 5 };
 | 
| +  EGLDisplay display_;
 | 
| +  EGLConfig configs_[kConfigsSize];
 | 
| +};
 | 
| +
 | 
| +void EGLConfigTest::SetUp() {
 | 
| +  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  ASSERT_NE(display_, EGL_NO_DISPLAY);
 | 
| +  EXPECT_TRUE(eglInitialize(display_, nullptr, nullptr));
 | 
| +  memset(configs_, 0, sizeof(configs_));
 | 
| +}
 | 
| +
 | 
| +void EGLConfigTest::CheckConfigsExist(EGLint num_config) {
 | 
| +  EGLint i;
 | 
| +  if (num_config > kConfigsSize)
 | 
| +    num_config = static_cast<EGLint>(kConfigsSize);
 | 
| +  for (i = 0; i < num_config; ++i)
 | 
| +    EXPECT_NE(nullptr, configs_[i]);
 | 
| +  for (; i < kConfigsSize; ++i)
 | 
| +    EXPECT_EQ(nullptr, configs_[i]);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, GetConfigsBadNumConfigs) {
 | 
| +  EXPECT_FALSE(eglGetConfigs(display_, configs_, kConfigsSize, nullptr));
 | 
| +  EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, GetConfigsNullConfigs) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EXPECT_TRUE(eglGetConfigs(display_, nullptr, 55, &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, GetConfigsZeroConfigsSize) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EXPECT_TRUE(eglGetConfigs(display_, configs_, 0, &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +  EXPECT_EQ(nullptr, configs_[0]);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, GetConfigs) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EXPECT_TRUE(eglGetConfigs(display_, configs_, kConfigsSize, &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +  CheckConfigsExist(num_config);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigBadNumConfigs) {
 | 
| +  EGLint attrib_list[] = {EGL_NONE};
 | 
| +  EXPECT_FALSE(
 | 
| +      eglChooseConfig(display_, attrib_list, configs_, kConfigsSize, nullptr));
 | 
| +  EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigNullConfigs) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_NONE};
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, nullptr, 55, &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigZeroConfigsSize) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_NONE};
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, 0, &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +  EXPECT_EQ(nullptr, configs_[0]);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfig) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_NONE};
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
 | 
| +                              &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +  CheckConfigsExist(num_config);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigInvalidAttrib) {
 | 
| +  const EGLint kNotModified = 55;
 | 
| +  EGLint num_config = kNotModified;
 | 
| +  EGLint invalid_attrib_list[] = {0xABCD};
 | 
| +  EXPECT_FALSE(eglChooseConfig(display_, invalid_attrib_list, configs_,
 | 
| +                               kConfigsSize, &num_config));
 | 
| +  EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
 | 
| +  EXPECT_EQ(kNotModified, num_config);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigWindow) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE};
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
 | 
| +                              &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +  for (int i = 0; i < num_config; ++i) {
 | 
| +    EGLint value = EGL_NONE;
 | 
| +    eglGetConfigAttrib(display_, configs_[i], EGL_SURFACE_TYPE, &value);
 | 
| +    EXPECT_NE(0, value & EGL_WINDOW_BIT);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigPBuffer) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_NONE};
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
 | 
| +                              &num_config));
 | 
| +  EXPECT_GT(num_config, 0);
 | 
| +  for (int i = 0; i < num_config; ++i) {
 | 
| +    EGLint value = EGL_NONE;
 | 
| +    eglGetConfigAttrib(display_, configs_[0], EGL_SURFACE_TYPE, &value);
 | 
| +    EXPECT_NE(0, value & EGL_PBUFFER_BIT);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigWindowPBufferNotPossible) {
 | 
| +  EGLint num_config = 0;
 | 
| +  EGLint attrib_list[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
 | 
| +                          EGL_NONE};
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
 | 
| +                              &num_config));
 | 
| +  EXPECT_EQ(0, num_config);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLConfigTest, ChooseConfigBugExample) {
 | 
| +  static const EGLint kConfigAttribs[] = {
 | 
| +      EGL_RED_SIZE,       8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE,    8,
 | 
| +      EGL_ALPHA_SIZE,     8, EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
 | 
| +      EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES,    4, EGL_NONE};
 | 
| +  EGLint num_config = 0;
 | 
| +  EXPECT_TRUE(eglChooseConfig(display_, kConfigAttribs, configs_, kConfigsSize,
 | 
| +                              &num_config));
 | 
| +
 | 
| +  // The EGL attribs are not really implemented at the moment.
 | 
| +  EGLint value = EGL_NONE;
 | 
| +  EXPECT_TRUE(eglGetConfigAttrib(display_, configs_[0], EGL_RED_SIZE, &value));
 | 
| +  EXPECT_EQ(0, value);
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, MakeCurrent) {
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_NE(display, EGL_NO_DISPLAY);
 | 
| +  // "This is the only case where an uninitialized display may be passed to
 | 
| +  //  eglMakeCurrent."
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
 | 
| +  EXPECT_FALSE(eglMakeCurrent(invalid_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
 | 
| +                              EGL_NO_CONTEXT));
 | 
| +  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
 | 
| +
 | 
| +  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +  EXPECT_FALSE(eglMakeCurrent(invalid_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
 | 
| +                              EGL_NO_CONTEXT));
 | 
| +}
 | 
| +
 | 
| +class EGLSurfaceTest : public EGLTest {
 | 
| + public:
 | 
| +  void SetUp() override;
 | 
| +  void CreateSurfaceAndContext(EGLSurface* surface, EGLContext* context);
 | 
| +
 | 
| + protected:
 | 
| +  EGLDisplay display_;
 | 
| +};
 | 
| +
 | 
| +void EGLSurfaceTest::SetUp() {
 | 
| +  EGLTest::SetUp();
 | 
| +  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_TRUE(eglInitialize(display_, nullptr, nullptr));
 | 
| +}
 | 
| +
 | 
| +void EGLSurfaceTest::CreateSurfaceAndContext(EGLSurface* surface,
 | 
| +                                             EGLContext* context) {
 | 
| +  static const EGLint config_attribs[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
 | 
| +                                          EGL_NONE};
 | 
| +  EGLint num_config;
 | 
| +  EGLConfig config;
 | 
| +  EXPECT_TRUE(
 | 
| +      eglChooseConfig(display_, config_attribs, &config, 1, &num_config));
 | 
| +  ASSERT_GT(num_config, 0);
 | 
| +  static const EGLint surface_attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1,
 | 
| +                                           EGL_NONE};
 | 
| +  *surface = eglCreatePbufferSurface(display_, config, surface_attribs);
 | 
| +  static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
 | 
| +                                           EGL_NONE};
 | 
| +  *context = eglCreateContext(display_, config, nullptr, context_attribs);
 | 
| +}
 | 
| +
 | 
| +class EGLMultipleSurfacesContextsTest : public EGLSurfaceTest {
 | 
| + public:
 | 
| +  void SetUp() override;
 | 
| +  void TearDown() override;
 | 
| +
 | 
| + protected:
 | 
| +  EGLSurface surface1_;
 | 
| +  EGLSurface surface2_;
 | 
| +  EGLContext context1_;
 | 
| +  EGLContext context2_;
 | 
| +};
 | 
| +
 | 
| +void EGLMultipleSurfacesContextsTest::SetUp() {
 | 
| +  EGLSurfaceTest::SetUp();
 | 
| +  CreateSurfaceAndContext(&surface1_, &context1_);
 | 
| +  CreateSurfaceAndContext(&surface2_, &context2_);
 | 
| +  EXPECT_NE(EGL_NO_SURFACE, surface1_);
 | 
| +  EXPECT_NE(EGL_NO_SURFACE, surface2_);
 | 
| +  EXPECT_NE(surface1_, surface2_);
 | 
| +  EXPECT_NE(EGL_NO_CONTEXT, context1_);
 | 
| +  EXPECT_NE(EGL_NO_CONTEXT, context2_);
 | 
| +  EXPECT_NE(context1_, context2_);
 | 
| +}
 | 
| +
 | 
| +void EGLMultipleSurfacesContextsTest::TearDown() {
 | 
| +  EXPECT_TRUE(eglDestroyContext(display_, context1_));
 | 
| +  EXPECT_TRUE(eglDestroySurface(display_, surface1_));
 | 
| +  EXPECT_TRUE(eglDestroyContext(display_, context2_));
 | 
| +  EXPECT_TRUE(eglDestroySurface(display_, surface2_));
 | 
| +  EGLTest::TearDown();
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, NoMakeCurrent) {}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSurfaces) {
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context2_));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context1_));
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSameSurface1) {
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context2_));
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSameSurface2) {
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context1_));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSurfacesAndReleases) {
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context2_));
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context1_));
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSurfaceFails) {
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, surface1_, EGL_NO_CONTEXT));
 | 
| +  EXPECT_EQ(EGL_BAD_CONTEXT, eglGetError());
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, EGL_NO_SURFACE, context1_));
 | 
| +  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, EGL_NO_SURFACE, surface1_, context1_));
 | 
| +  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
 | 
| +
 | 
| +  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
 | 
| +  EGLSurface invalid_surface = reinterpret_cast<EGLSurface>(0x1);
 | 
| +  EGLSurface invalid_context = reinterpret_cast<EGLContext>(0x1);
 | 
| +  EXPECT_FALSE(
 | 
| +      eglMakeCurrent(invalid_display, surface1_, surface1_, context1_));
 | 
| +  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, surface1_, invalid_context));
 | 
| +  EXPECT_EQ(EGL_BAD_CONTEXT, eglGetError());
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, invalid_surface, context1_));
 | 
| +  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, invalid_surface, surface1_, context1_));
 | 
| +  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
 | 
| +
 | 
| +  // Command buffer limitation:
 | 
| +  // Different read and draw surfaces fail.
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, surface2_, context1_));
 | 
| +  EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLMultipleSurfacesContextsTest, CallGLOnMultipleContextNoCrash) {
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
 | 
| +
 | 
| +  typedef void(GL_APIENTRY * glEnableProc)(GLenum);
 | 
| +  glEnableProc glEnable =
 | 
| +      reinterpret_cast<glEnableProc>(eglGetProcAddress("glEnable"));
 | 
| +  EXPECT_NE(nullptr, glEnable);
 | 
| +
 | 
| +  glEnable(GL_BLEND);
 | 
| +
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
 | 
| +  glEnable(GL_BLEND);
 | 
| +}
 | 
| +
 | 
| +class EGLThreadTest : public EGLSurfaceTest {
 | 
| + public:
 | 
| +  EGLThreadTest();
 | 
| +  void SetUp() override;
 | 
| +  void TearDown() override;
 | 
| +  void OtherThreadTearDown(base::WaitableEvent*);
 | 
| +  void OtherThreadMakeCurrent(EGLSurface surface,
 | 
| +                              EGLContext context,
 | 
| +                              EGLBoolean* result,
 | 
| +                              base::WaitableEvent*);
 | 
| +  void OtherThreadGetError(EGLint* result, base::WaitableEvent*);
 | 
| +
 | 
| + protected:
 | 
| +  base::Thread other_thread_;
 | 
| +};
 | 
| +
 | 
| +EGLThreadTest::EGLThreadTest()
 | 
| +    : EGLSurfaceTest(), other_thread_("EGLThreadTest thread") {}
 | 
| +void EGLThreadTest::SetUp() {
 | 
| +  EGLSurfaceTest::SetUp();
 | 
| +  other_thread_.Start();
 | 
| +}
 | 
| +
 | 
| +void EGLThreadTest::TearDown() {
 | 
| +  base::WaitableEvent completion(true, false);
 | 
| +  other_thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE, base::Bind(&EGLThreadTest::OtherThreadTearDown,
 | 
| +                            base::Unretained(this), &completion));
 | 
| +  completion.Wait();
 | 
| +  other_thread_.Stop();
 | 
| +  EGLSurfaceTest::TearDown();
 | 
| +}
 | 
| +
 | 
| +void EGLThreadTest::OtherThreadTearDown(base::WaitableEvent* completion) {
 | 
| +  EXPECT_TRUE(eglReleaseThread());
 | 
| +  completion->Signal();
 | 
| +}
 | 
| +
 | 
| +void EGLThreadTest::OtherThreadMakeCurrent(EGLSurface surface,
 | 
| +                                           EGLContext context,
 | 
| +                                           EGLBoolean* result,
 | 
| +                                           base::WaitableEvent* completion) {
 | 
| +  *result = eglMakeCurrent(display_, surface, surface, context);
 | 
| +  completion->Signal();
 | 
| +}
 | 
| +
 | 
| +void EGLThreadTest::OtherThreadGetError(EGLint* result,
 | 
| +                                        base::WaitableEvent* completion) {
 | 
| +  *result = eglGetError();
 | 
| +  completion->Signal();
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLThreadTest, OnlyReleaseThreadInOther) {}
 | 
| +
 | 
| +TEST_F(EGLThreadTest, Basic) {
 | 
| +  EGLSurface surface;
 | 
| +  EGLContext context;
 | 
| +  CreateSurfaceAndContext(&surface, &context);
 | 
| +  EXPECT_NE(EGL_NO_SURFACE, surface);
 | 
| +  EXPECT_NE(EGL_NO_CONTEXT, context);
 | 
| +
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display_, surface, surface, context));
 | 
| +
 | 
| +  base::WaitableEvent completion(false, false);
 | 
| +
 | 
| +  EGLBoolean result = EGL_FALSE;
 | 
| +  other_thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE,
 | 
| +      base::Bind(&EGLThreadTest::OtherThreadMakeCurrent, base::Unretained(this),
 | 
| +                 surface, context, &result, &completion));
 | 
| +  completion.Wait();
 | 
| +  EXPECT_FALSE(result);
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  EGLint error = EGL_NONE;
 | 
| +  other_thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE, base::Bind(&EGLThreadTest::OtherThreadGetError,
 | 
| +                            base::Unretained(this), &error, &completion));
 | 
| +  completion.Wait();
 | 
| +  EXPECT_EQ(EGL_BAD_ACCESS, error);
 | 
| +  EXPECT_EQ(EGL_SUCCESS, eglGetError());
 | 
| +
 | 
| +  other_thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE, base::Bind(&EGLThreadTest::OtherThreadGetError,
 | 
| +                            base::Unretained(this), &error, &completion));
 | 
| +  completion.Wait();
 | 
| +  EXPECT_EQ(EGL_SUCCESS, error);
 | 
| +
 | 
| +  EXPECT_TRUE(
 | 
| +      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 | 
| +
 | 
| +  other_thread_.task_runner()->PostTask(
 | 
| +      FROM_HERE,
 | 
| +      base::Bind(&EGLThreadTest::OtherThreadMakeCurrent, base::Unretained(this),
 | 
| +                 surface, context, &result, &completion));
 | 
| +  completion.Wait();
 | 
| +  EXPECT_TRUE(result);
 | 
| +
 | 
| +  EXPECT_FALSE(eglMakeCurrent(display_, surface, surface, context));
 | 
| +  EXPECT_EQ(EGL_BAD_ACCESS, eglGetError());
 | 
| +
 | 
| +  EXPECT_TRUE(eglDestroySurface(display_, surface));
 | 
| +  EXPECT_TRUE(eglDestroyContext(display_, context));
 | 
| +}
 | 
| +
 | 
| +TEST_F(EGLTest, WindowlessNativeWindows) {
 | 
| +  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | 
| +  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 | 
| +
 | 
| +  static const EGLint config_attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
 | 
| +                                          EGL_NONE};
 | 
| +  EGLint num_config;
 | 
| +  EGLConfig config;
 | 
| +  EXPECT_TRUE(
 | 
| +      eglChooseConfig(display, config_attribs, &config, 1, &num_config));
 | 
| +  ASSERT_GT(num_config, 0);
 | 
| +  static const EGLint surface_attribs[] = {EGL_NONE};
 | 
| +  CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(display, 100, 100);
 | 
| +  EGLNativeWindowType win = 0;
 | 
| +  EGLSurface surface =
 | 
| +      eglCreateWindowSurface(display, config, win, surface_attribs);
 | 
| +  EXPECT_NE(EGL_NO_SURFACE, surface);
 | 
| +
 | 
| +  // Test that SwapBuffers can be called on windowless window surfaces.
 | 
| +
 | 
| +  static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
 | 
| +                                           EGL_NONE};
 | 
| +  EGLContext context =
 | 
| +      eglCreateContext(display, config, nullptr, context_attribs);
 | 
| +  EXPECT_TRUE(eglMakeCurrent(display, surface, surface, context));
 | 
| +  EXPECT_TRUE(eglSwapBuffers(display, surface));
 | 
|  
 | 
| -  success = eglTerminate(display);
 | 
| -  ASSERT_TRUE(success);
 | 
| +  EXPECT_TRUE(eglDestroySurface(display, surface));
 | 
| +  EXPECT_TRUE(eglDestroyContext(display, context));
 | 
|  }
 | 
|  
 | 
|  }  // namespace gpu
 | 
| 
 |