diff options
Diffstat (limited to 'gpu')
20 files changed, 761 insertions, 1975 deletions
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 64026a4..c3f82eb 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn @@ -55,8 +55,6 @@ shared_library("command_buffer_gles2") { # TODO(hendrikw): Move egl out of gles2_conform_support. "gles2_conform_support/egl/config.cc", "gles2_conform_support/egl/config.h", - "gles2_conform_support/egl/context.cc", - "gles2_conform_support/egl/context.h", "gles2_conform_support/egl/display.cc", "gles2_conform_support/egl/display.h", "gles2_conform_support/egl/egl.cc", @@ -64,8 +62,6 @@ shared_library("command_buffer_gles2") { "gles2_conform_support/egl/surface.h", "gles2_conform_support/egl/test_support.cc", "gles2_conform_support/egl/test_support.h", - "gles2_conform_support/egl/thread_state.cc", - "gles2_conform_support/egl/thread_state.h", ] deps = [ @@ -73,7 +69,6 @@ shared_library("command_buffer_gles2") { "//base", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", - "//gpu/command_buffer/common:gles2_utils", "//ui/gl:gl", ] diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 2d1d90a..f69be1d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -578,7 +578,6 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { const std::vector<int32_t>& attribs) override; void Destroy(bool have_context) override; void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override; - void ReleaseSurface() override; void ProduceFrontBuffer(const Mailbox& mailbox) override; bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override; void UpdateParentTextureInfo(); @@ -3605,7 +3604,6 @@ void GLES2DecoderImpl::DeleteSamplersHelper( // } // anonymous namespace bool GLES2DecoderImpl::MakeCurrent() { - DCHECK(surface_); if (!context_.get()) return false; @@ -4163,22 +4161,11 @@ void GLES2DecoderImpl::Destroy(bool have_context) { void GLES2DecoderImpl::SetSurface( const scoped_refptr<gfx::GLSurface>& surface) { DCHECK(context_->IsCurrent(NULL)); - DCHECK(surface); + DCHECK(surface_.get()); surface_ = surface; RestoreCurrentFramebufferBindings(); } -void GLES2DecoderImpl::ReleaseSurface() { - if (!context_.get()) - return; - if (WasContextLost()) { - DLOG(ERROR) << " GLES2DecoderImpl: Trying to release lost context."; - return; - } - context_->ReleaseCurrent(surface_.get()); - surface_ = nullptr; -} - void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) { if (!offscreen_saved_color_texture_.get()) { LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context"; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 43e3492..297b9cf 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -159,10 +159,6 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, // Set the surface associated with the default FBO. virtual void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) = 0; - // Releases the surface associated with the GL context. - // The decoder should not be used until a new surface is set. - virtual void ReleaseSurface() = 0; - virtual void ProduceFrontBuffer(const Mailbox& mailbox) = 0; // Resize an offscreen frame buffer. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index 636dc14..396f531 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -52,7 +52,6 @@ class MockGLES2Decoder : public GLES2Decoder { const std::vector<int32_t>& attribs)); MOCK_METHOD1(Destroy, void(bool have_context)); MOCK_METHOD1(SetSurface, void(const scoped_refptr<gfx::GLSurface>& surface)); - MOCK_METHOD0(ReleaseSurface, void()); MOCK_METHOD1(ProduceFrontBuffer, void(const Mailbox& mailbox)); MOCK_METHOD1(ResizeOffscreenFrameBuffer, bool(const gfx::Size& size)); MOCK_METHOD0(MakeCurrent, bool()); diff --git a/gpu/command_buffer/tests/egl_test.cc b/gpu/command_buffer/tests/egl_test.cc index 05465d94..bf7e30e 100644 --- a/gpu/command_buffer/tests/egl_test.cc +++ b/gpu/command_buffer/tests/egl_test.cc @@ -6,589 +6,31 @@ #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" // 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 { -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)); -} +using testing::Test; -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(EGLTest, Initialize) { +TEST_F(Test, BasicEGLInitialization) { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - EXPECT_NE(display, EGL_NO_DISPLAY); + ASSERT_NE(display, EGL_NO_DISPLAY); // Test for no crash even though passing nullptrs for major, minor. - EXPECT_TRUE(eglInitialize(display, nullptr, nullptr)); + EGLBoolean success = eglInitialize(display, nullptr, nullptr); + ASSERT_TRUE(success); EGLint major = 0; EGLint minor = 0; - 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 GL_APICALL 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()); + success = eglInitialize(display, &major, &minor); + ASSERT_TRUE(success); + ASSERT_EQ(major, 1); + ASSERT_EQ(minor, 4); - EXPECT_TRUE(eglDestroySurface(display_, surface)); - EXPECT_TRUE(eglDestroyContext(display_, context)); + success = eglTerminate(display); + ASSERT_TRUE(success); } } // namespace gpu diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn index 731237d..ee06fbf 100644 --- a/gpu/gles2_conform_support/egl/BUILD.gn +++ b/gpu/gles2_conform_support/egl/BUILD.gn @@ -8,15 +8,11 @@ source_set("egl") { sources = [ "config.cc", "config.h", - "context.cc", - "context.h", "display.cc", "display.h", "egl.cc", "surface.cc", "surface.h", - "thread_state.cc", - "thread_state.h", ] configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] @@ -30,7 +26,6 @@ source_set("egl") { "//base", "//gpu", "//gpu/command_buffer/client:gles2_implementation_no_check", - "//gpu/command_buffer/common:gles2_utils", "//gpu/command_buffer/service", "//ui/base", "//ui/gfx", diff --git a/gpu/gles2_conform_support/egl/config.cc b/gpu/gles2_conform_support/egl/config.cc index 53bd440..d6ce307 100644 --- a/gpu/gles2_conform_support/egl/config.cc +++ b/gpu/gles2_conform_support/egl/config.cc @@ -3,11 +3,10 @@ // found in the LICENSE file. #include "gpu/gles2_conform_support/egl/config.h" -#include "base/logging.h" namespace egl { -Config::Config(EGLint surface_type) +Config::Config() : buffer_size_(0), red_size_(0), green_size_(0), @@ -35,37 +34,16 @@ Config::Config(EGLint surface_type) sample_buffers_(0), samples_(0), stencil_size_(0), - surface_type_(surface_type), + surface_type_(EGL_WINDOW_BIT), transparent_type_(EGL_NONE), transparent_red_value_(EGL_DONT_CARE), transparent_green_value_(EGL_DONT_CARE), transparent_blue_value_(EGL_DONT_CARE) { - DCHECK(surface_type == EGL_WINDOW_BIT || surface_type == EGL_PBUFFER_BIT); } Config::~Config() { } -bool Config::Matches(const EGLint* attrib_list) const { - DCHECK(ValidateAttributeList(attrib_list)); - if (attrib_list) { - for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) { - switch (attrib_list[i]) { - case EGL_SURFACE_TYPE: { - EGLint requested_surface_type = attrib_list[i + 1]; - if (requested_surface_type != EGL_DONT_CARE && - (requested_surface_type & surface_type_) != - requested_surface_type) - return false; - } - default: - break; - } - } - } - return true; -} - bool Config::GetAttrib(EGLint attribute, EGLint* value) const { // TODO(alokp): Find out how to get correct values. switch (attribute) { @@ -171,52 +149,4 @@ bool Config::GetAttrib(EGLint attribute, EGLint* value) const { return true; } -bool Config::ValidateAttributeList(const EGLint* attrib_list) { - if (attrib_list) { - for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) { - switch (attrib_list[i]) { - case EGL_ALPHA_MASK_SIZE: - case EGL_ALPHA_SIZE: - case EGL_BIND_TO_TEXTURE_RGB: - case EGL_BIND_TO_TEXTURE_RGBA: - case EGL_BLUE_SIZE: - case EGL_BUFFER_SIZE: - case EGL_COLOR_BUFFER_TYPE: - case EGL_CONFIG_CAVEAT: - case EGL_CONFIG_ID: - case EGL_CONFORMANT: - case EGL_DEPTH_SIZE: - case EGL_GREEN_SIZE: - case EGL_LEVEL: - case EGL_LUMINANCE_SIZE: - case EGL_MATCH_NATIVE_PIXMAP: - case EGL_NATIVE_RENDERABLE: - case EGL_MAX_SWAP_INTERVAL: - case EGL_MIN_SWAP_INTERVAL: - case EGL_RED_SIZE: - case EGL_SAMPLE_BUFFERS: - case EGL_SAMPLES: - case EGL_STENCIL_SIZE: - case EGL_RENDERABLE_TYPE: - case EGL_SURFACE_TYPE: - case EGL_MULTISAMPLE_RESOLVE_BOX_BIT: - case EGL_PBUFFER_BIT: - case EGL_PIXMAP_BIT: - case EGL_SWAP_BEHAVIOR_PRESERVED_BIT: - case EGL_VG_ALPHA_FORMAT_PRE_BIT: - case EGL_VG_COLORSPACE_LINEAR_BIT: - case EGL_WINDOW_BIT: - case EGL_TRANSPARENT_TYPE: - case EGL_TRANSPARENT_RED_VALUE: - case EGL_TRANSPARENT_GREEN_VALUE: - case EGL_TRANSPARENT_BLUE_VALUE: - break; - default: - return false; - } - } - } - return true; -} - } // namespace egl diff --git a/gpu/gles2_conform_support/egl/config.h b/gpu/gles2_conform_support/egl/config.h index 1ce8156..53bb568 100644 --- a/gpu/gles2_conform_support/egl/config.h +++ b/gpu/gles2_conform_support/egl/config.h @@ -13,11 +13,10 @@ namespace egl { class Config { public: - explicit Config(EGLint surface_type); + Config(); ~Config(); - bool Matches(const EGLint* attrib_list) const; + bool GetAttrib(EGLint attribute, EGLint* value) const; - static bool ValidateAttributeList(const EGLint* attrib_list); private: // Total color component bits in the color buffer. diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc deleted file mode 100644 index 47ae35f..0000000 --- a/gpu/gles2_conform_support/egl/context.cc +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (c) 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 "gpu/gles2_conform_support/egl/context.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/command_buffer/client/transfer_buffer.h" -#include "gpu/command_buffer/common/value_state.h" -#include "gpu/command_buffer/service/context_group.h" -#include "gpu/command_buffer/service/mailbox_manager.h" -#include "gpu/command_buffer/service/memory_tracking.h" -#include "gpu/command_buffer/service/transfer_buffer_manager.h" -#include "gpu/command_buffer/service/valuebuffer_manager.h" -#include "gpu/gles2_conform_support/egl/config.h" -#include "gpu/gles2_conform_support/egl/display.h" -#include "gpu/gles2_conform_support/egl/surface.h" -#include "gpu/gles2_conform_support/egl/thread_state.h" - -// The slight complexification in this file comes from following properties: -// 1) Command buffer connection (context) can not be established without a -// GLSurface. EGL Context can be created independent of a surface. This is why -// the connection is created only during first MakeCurrent. -// 2) Command buffer MakeCurrent calls need the real gl context and surface be -// current. -// 3) Client can change real EGL context behind the scenes and then still expect -// command buffer MakeCurrent re-set the command buffer context. This is why all -// MakeCurrent calls must actually reset the real context, even though command -// buffer current context does not change. -// 4) EGL context can be destroyed without surface, but command buffer would -// need the surface to run various cleanups. If context is destroyed -// surfaceless, the context is marked lost before destruction. This is avoided -// if possible, since command buffer at the time of writing prints out debug -// text in this case. - -namespace { -const int32_t kCommandBufferSize = 1024 * 1024; -const int32_t kTransferBufferSize = 512 * 1024; -const bool kBindGeneratesResources = true; -const bool kLoseContextWhenOutOfMemory = false; -const bool kSupportClientSideArrays = true; -} - -namespace egl { -Context::Context(Display* display, const Config* config) - : display_(display), - config_(config), - is_current_in_some_thread_(false), - is_destroyed_(false) {} - -Context::~Context() { - // We might not have a surface, so we must lose the context. Cleanup will - // execute GL commands otherwise. TODO: if shared contexts are ever - // implemented, this will leak the GL resources. For pbuffer contexts, one - // could track the last current surface or create a surface for destroying - // purposes only. Other option would be to make the service usable without - // surface. - if (HasService()) { - if (!WasServiceContextLost()) - MarkServiceContextLost(); - DestroyService(); - } -} - -void Context::MarkDestroyed() { - is_destroyed_ = true; -} - -void Context::FlushAndSwapBuffers(gfx::GLSurface* current_surface) { - DCHECK(HasService() && is_current_in_some_thread_); - if (!Flush(current_surface)) - return; - current_surface->SwapBuffers(); -} - -bool Context::MakeCurrent(Context* current_context, - gfx::GLSurface* current_surface, - Context* new_context, - gfx::GLSurface* new_surface) { - if (!new_context && !current_context) { - return true; - } - - bool cleanup_old_current_context = false; - if (current_context) { - if (current_context->Flush(current_surface)) - cleanup_old_current_context = new_context != current_context; - } - - if (new_context) { - if (!new_context->IsCompatibleSurface(new_surface)) - return false; - - if (new_context->HasService()) { - if (new_context->WasServiceContextLost()) - return false; - if (new_context != current_context) { - // If Flush did not set the current context, set it now. Otherwise - // calling into the decoder is not ok. - if (!new_context->gl_context_->MakeCurrent(new_surface)) { - new_context->MarkServiceContextLost(); - return false; - } - } - if (new_context != current_context || new_surface != current_surface) - new_context->decoder_->SetSurface(new_surface); - if (!new_context->decoder_->MakeCurrent()) { - new_context->MarkServiceContextLost(); - return false; - } - } else { - if (!new_context->CreateService(new_surface)) { - return false; - } - } - } - - // The current_surface will be released when MakeCurrent succeeds. - // Cleanup in this case only. - if (cleanup_old_current_context) { - if (current_context->is_destroyed_ && current_surface != new_surface) { - current_context->gl_context_->MakeCurrent(current_surface); - // If we are releasing the context and we have one ref, it means that the - // ref will be lost and the object will be destroyed. Destroy the service - // explicitly here, so that cleanup can happen and client GL - // implementation does not print errors. - current_context->DestroyService(); - } else { - current_context->decoder_->ReleaseSurface(); - } - } - - return true; -} - -bool Context::ValidateAttributeList(const EGLint* attrib_list) { - if (attrib_list) { - for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) { - switch (attrib_list[i]) { - case EGL_CONTEXT_CLIENT_VERSION: - break; - default: - return false; - } - } - } - return true; -} - -gpu::Capabilities Context::GetCapabilities() { - return decoder_->GetCapabilities(); -} - -int32_t Context::CreateImage(ClientBuffer buffer, - size_t width, - size_t height, - unsigned internalformat) { - NOTIMPLEMENTED(); - return -1; -} - -void Context::DestroyImage(int32_t id) { - NOTIMPLEMENTED(); -} - -int32_t Context::CreateGpuMemoryBufferImage(size_t width, - size_t height, - unsigned internalformat, - unsigned usage) { - NOTIMPLEMENTED(); - return -1; -} - -void Context::SignalQuery(uint32_t query, const base::Closure& callback) { - NOTIMPLEMENTED(); -} - -void Context::SetLock(base::Lock*) { - NOTIMPLEMENTED(); -} - -bool Context::IsGpuChannelLost() { - NOTIMPLEMENTED(); - return false; -} - -void Context::EnsureWorkVisible() { - // This is only relevant for out-of-process command buffers. -} - -gpu::CommandBufferNamespace Context::GetNamespaceID() const { - return gpu::CommandBufferNamespace::IN_PROCESS; -} - -gpu::CommandBufferId Context::GetCommandBufferID() const { - return gpu::CommandBufferId(); -} - -int32_t Context::GetExtraCommandBufferData() const { - return 0; -} - -uint64_t Context::GenerateFenceSyncRelease() { - return display_->GenerateFenceSyncRelease(); -} - -bool Context::IsFenceSyncRelease(uint64_t release) { - return display_->IsFenceSyncRelease(release); -} - -bool Context::IsFenceSyncFlushed(uint64_t release) { - return display_->IsFenceSyncFlushed(release); -} - -bool Context::IsFenceSyncFlushReceived(uint64_t release) { - return display_->IsFenceSyncFlushReceived(release); -} - -void Context::SignalSyncToken(const gpu::SyncToken& sync_token, - const base::Closure& callback) { - NOTIMPLEMENTED(); -} - -bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { - return false; -} - -void Context::ApplyCurrentContext(gfx::GLSurface* current_surface) { - DCHECK(HasService()); - // The current_surface will be the same as - // the surface of the decoder. We can not DCHECK as there is - // no accessor. - if (!WasServiceContextLost()) { - if (!gl_context_->MakeCurrent(current_surface)) - MarkServiceContextLost(); - } - gles2::SetGLContext(client_gl_context_.get()); -} - -void Context::ApplyContextReleased() { - gles2::SetGLContext(nullptr); -} - -bool Context::CreateService(gfx::GLSurface* gl_surface) { - scoped_refptr<gpu::TransferBufferManager> transfer_buffer_manager( - new gpu::TransferBufferManager(nullptr)); - transfer_buffer_manager->Initialize(); - - scoped_ptr<gpu::CommandBufferService> command_buffer( - new gpu::CommandBufferService(transfer_buffer_manager.get())); - if (!command_buffer->Initialize()) - return false; - - scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( - NULL, NULL, new gpu::gles2::ShaderTranslatorCache, - new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); - - scoped_ptr<gpu::gles2::GLES2Decoder> decoder( - gpu::gles2::GLES2Decoder::Create(group.get())); - if (!decoder.get()) - return false; - - scoped_ptr<gpu::GpuScheduler> gpu_scheduler(new gpu::GpuScheduler( - command_buffer.get(), decoder.get(), decoder.get())); - - decoder->set_engine(gpu_scheduler.get()); - - scoped_refptr<gfx::GLContext> gl_context(gfx::GLContext::CreateGLContext( - nullptr, gl_surface, gfx::PreferDiscreteGpu)); - if (!gl_context) - return false; - - gl_context->MakeCurrent(gl_surface); - - gpu::gles2::ContextCreationAttribHelper helper; - config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size); - config_->GetAttrib(EGL_BLUE_SIZE, &helper.blue_size); - config_->GetAttrib(EGL_GREEN_SIZE, &helper.green_size); - config_->GetAttrib(EGL_RED_SIZE, &helper.red_size); - config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size); - config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size); - config_->GetAttrib(EGL_SAMPLES, &helper.samples); - config_->GetAttrib(EGL_SAMPLE_BUFFERS, &helper.sample_buffers); - - helper.buffer_preserved = false; - helper.bind_generates_resource = kBindGeneratesResources; - helper.fail_if_major_perf_caveat = false; - helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory; - helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2; - std::vector<int32_t> attribs; - helper.Serialize(&attribs); - - if (!decoder->Initialize(gl_surface, gl_context.get(), - gl_surface->IsOffscreen(), gl_surface->GetSize(), - gpu::gles2::DisallowedFeatures(), attribs)) { - return false; - } - - command_buffer->SetPutOffsetChangeCallback(base::Bind( - &gpu::GpuScheduler::PutChanged, base::Unretained(gpu_scheduler.get()))); - command_buffer->SetGetBufferChangeCallback(base::Bind( - &gpu::GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler.get()))); - - scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper( - new gpu::gles2::GLES2CmdHelper(command_buffer.get())); - if (!gles2_cmd_helper->Initialize(kCommandBufferSize)) { - decoder->Destroy(true); - return false; - } - - scoped_ptr<gpu::TransferBuffer> transfer_buffer( - new gpu::TransferBuffer(gles2_cmd_helper.get())); - - gles2_cmd_helper_.reset(gles2_cmd_helper.release()); - transfer_buffer_.reset(transfer_buffer.release()); - command_buffer_.reset(command_buffer.release()); - gpu_scheduler_.reset(gpu_scheduler.release()); - decoder_.reset(decoder.release()); - gl_context_ = gl_context.get(); - - scoped_ptr<gpu::gles2::GLES2Implementation> context( - new gpu::gles2::GLES2Implementation( - gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(), - kBindGeneratesResources, kLoseContextWhenOutOfMemory, - kSupportClientSideArrays, this)); - - if (!context->Initialize(kTransferBufferSize, kTransferBufferSize / 2, - kTransferBufferSize * 2, - gpu::gles2::GLES2Implementation::kNoLimit)) { - DestroyService(); - return false; - } - - context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); - context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); - client_gl_context_.reset(context.release()); - return true; -} - -void Context::DestroyService() { - DCHECK(HasService()); - bool have_context = !WasServiceContextLost(); - // The client gl interface might still be set to current global - // interface. This will be cleaned up in ApplyContextReleased - // with AutoCurrentContextRestore. - client_gl_context_.reset(); - gl_context_ = nullptr; - - transfer_buffer_.reset(); - gpu_scheduler_.reset(); - if (decoder_) - decoder_->Destroy(have_context); - gles2_cmd_helper_.reset(); - command_buffer_.reset(); -} - -bool Context::HasService() const { - return decoder_ != nullptr; -} - -void Context::MarkServiceContextLost() { - decoder_->MarkContextLost(gpu::error::kMakeCurrentFailed); -} - -bool Context::WasServiceContextLost() const { - return decoder_->WasContextLost(); -} - -bool Context::IsCompatibleSurface(gfx::GLSurface* gl_surface) { - EGLint value = EGL_NONE; - config_->GetAttrib(EGL_SURFACE_TYPE, &value); - bool config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0; - return gl_surface->IsOffscreen() == config_is_offscreen; -} - -bool Context::Flush(gfx::GLSurface* gl_surface) { - if (WasServiceContextLost()) - return false; - if (!gl_context_->MakeCurrent(gl_surface)) { - MarkServiceContextLost(); - return false; - } - client_gl_context_->Flush(); - return true; -} - -} // namespace egl diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h deleted file mode 100644 index 41483fb..0000000 --- a/gpu/gles2_conform_support/egl/context.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef GPU_GLES2_CONFORM_TEST_CONTEXT_H_ -#define GPU_GLES2_CONFORM_TEST_CONTEXT_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "gpu/command_buffer/client/gles2_cmd_helper.h" -#include "gpu/command_buffer/client/gpu_control.h" -#include "gpu/command_buffer/service/command_buffer_service.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder.h" -#include "gpu/command_buffer/service/gpu_scheduler.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_surface.h" -#include "ui/gl/gl_surface.h" -#include <EGL/egl.h> - -namespace gpu { -class CommandBufferService; -class GpuControl; -class GpuScheduler; -class TransferBuffer; -class TransferBufferManagerInterface; - -namespace gles2 { -class GLES2CmdHelper; -class GLES2Interface; -} // namespace gles2 -} // namespace gpu - -namespace egl { -class Display; -class Surface; -class Config; - -class Context : public base::RefCountedThreadSafe<Context>, - private gpu::GpuControl { - public: - Context(Display* display, const Config* config); - bool is_current_in_some_thread() const { return is_current_in_some_thread_; } - void set_is_current_in_some_thread(bool flag) { - is_current_in_some_thread_ = flag; - } - void MarkDestroyed(); - void FlushAndSwapBuffers(gfx::GLSurface* current_surface); - - static bool MakeCurrent(Context* current_context, - gfx::GLSurface* current_surface, - Context* new_context, - gfx::GLSurface* new_surface); - - static bool ValidateAttributeList(const EGLint* attrib_list); - - // GpuControl implementation. - gpu::Capabilities GetCapabilities() override; - int32_t CreateImage(ClientBuffer buffer, - size_t width, - size_t height, - unsigned internalformat) override; - void DestroyImage(int32_t id) override; - int32_t CreateGpuMemoryBufferImage(size_t width, - size_t height, - unsigned internalformat, - unsigned usage) override; - void SignalQuery(uint32_t query, const base::Closure& callback) override; - void SetLock(base::Lock*) override; - bool IsGpuChannelLost() override; - void EnsureWorkVisible() override; - gpu::CommandBufferNamespace GetNamespaceID() const override; - gpu::CommandBufferId GetCommandBufferID() const override; - int32_t GetExtraCommandBufferData() const override; - uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; - void SignalSyncToken(const gpu::SyncToken& sync_token, - const base::Closure& callback) override; - bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override; - - // Called by ThreadState to set the needed global variables when this context - // is current. - void ApplyCurrentContext(gfx::GLSurface* current_surface); - static void ApplyContextReleased(); - - private: - friend class base::RefCountedThreadSafe<Context>; - ~Context() override; - bool CreateService(gfx::GLSurface* gl_surface); - void DestroyService(); - // Returns true if the object has GL service, either a working one or one - // that has lost its GL context. - bool HasService() const; - void MarkServiceContextLost(); - bool WasServiceContextLost() const; - bool IsCompatibleSurface(gfx::GLSurface* gl_surface); - bool Flush(gfx::GLSurface* gl_surface); - - Display* display_; - const Config* config_; - bool is_current_in_some_thread_; - bool is_destroyed_; - scoped_ptr<gpu::CommandBufferService> command_buffer_; - scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_; - scoped_ptr<gpu::gles2::GLES2Decoder> decoder_; - scoped_ptr<gpu::GpuScheduler> gpu_scheduler_; - scoped_ptr<gpu::TransferBuffer> transfer_buffer_; - - scoped_refptr<gfx::GLContext> gl_context_; - - scoped_ptr<gpu::gles2::GLES2Interface> client_gl_context_; - DISALLOW_COPY_AND_ASSIGN(Context); -}; - -} // namespace egl - -#endif // GPU_GLES2_CONFORM_TEST_CONTEXT_H_ diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 456483f..4b010f2 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -4,104 +4,133 @@ #include "gpu/gles2_conform_support/egl/display.h" +#include <stddef.h> +#include <stdint.h> + +#include <vector> +#include "base/at_exit.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/lazy_instance.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/client/transfer_buffer.h" +#include "gpu/command_buffer/common/value_state.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/memory_tracking.h" +#include "gpu/command_buffer/service/transfer_buffer_manager.h" +#include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/gles2_conform_support/egl/config.h" -#include "gpu/gles2_conform_support/egl/context.h" #include "gpu/gles2_conform_support/egl/surface.h" -#include "gpu/gles2_conform_support/egl/thread_state.h" +#include "gpu/gles2_conform_support/egl/test_support.h" -namespace egl { +namespace { +const int32_t kCommandBufferSize = 1024 * 1024; +const int32_t kTransferBufferSize = 512 * 1024; +} -Display::Display() : is_initialized_(false) {} +namespace egl { +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) +// egl::Display is used for comformance tests and command_buffer_gles. We only +// need the exit manager for the command_buffer_gles library. +// TODO(hendrikw): Find a cleaner solution for this. +namespace { +base::LazyInstance<base::Lock>::Leaky g_exit_manager_lock; +int g_exit_manager_use_count; +base::AtExitManager* g_exit_manager; +void RefAtExitManager() { + base::AutoLock lock(g_exit_manager_lock.Get()); +#if defined(COMPONENT_BUILD) + if (g_command_buffer_gles_has_atexit_manager) { + return; + } +#endif + if (g_exit_manager_use_count == 0) { + g_exit_manager = new base::AtExitManager; + } + ++g_exit_manager_use_count; +} +void ReleaseAtExitManager() { + base::AutoLock lock(g_exit_manager_lock.Get()); +#if defined(COMPONENT_BUILD) + if (g_command_buffer_gles_has_atexit_manager) { + return; + } +#endif + --g_exit_manager_use_count; + if (g_exit_manager_use_count == 0) { + delete g_exit_manager; + g_exit_manager = nullptr; + } +} +} +#endif + +Display::Display(EGLNativeDisplayType display_id) + : display_id_(display_id), + is_initialized_(false), + create_offscreen_(false), + create_offscreen_width_(0), + create_offscreen_height_(0), + next_fence_sync_release_(1) { +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) + RefAtExitManager(); +#endif +} Display::~Display() { - surfaces_.clear(); - contexts_.clear(); + gles2::Terminate(); +#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) + ReleaseAtExitManager(); +#endif } -EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) { - base::AutoLock auto_lock(lock_); +bool Display::Initialize() { + gles2::Initialize(); is_initialized_ = true; + return true; +} + +bool Display::IsValidConfig(EGLConfig config) { + return (config != NULL) && (config == config_.get()); +} - if (major) - *major = 1; - if (minor) - *minor = 4; - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLBoolean Display::Terminate(ThreadState* ts) { - base::AutoLock auto_lock(lock_); - is_initialized_ = false; - surfaces_.clear(); - for (const auto& context : contexts_) - context->MarkDestroyed(); - contexts_.clear(); - return ts->ReturnSuccess(EGL_TRUE); -} - -const char* Display::QueryString(ThreadState* ts, EGLint name) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError<const char*>(EGL_NOT_INITIALIZED, nullptr); - switch (name) { - case EGL_CLIENT_APIS: - return ts->ReturnSuccess("OpenGL_ES"); - case EGL_EXTENSIONS: - return ts->ReturnSuccess(""); - case EGL_VENDOR: - return ts->ReturnSuccess("Google Inc."); - case EGL_VERSION: - return ts->ReturnSuccess("1.4"); - default: - return ts->ReturnError<const char*>(EGL_BAD_PARAMETER, nullptr); +bool Display::ChooseConfigs(EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + // TODO(alokp): Find out a way to find all configs. CommandBuffer currently + // does not support finding or choosing configs. + *num_config = 1; + if (configs != NULL) { + if (config_ == NULL) { + config_.reset(new Config); + } + configs[0] = config_.get(); } + return true; } -EGLBoolean Display::ChooseConfig(ThreadState* ts, - const EGLint* attrib_list, - EGLConfig* configs, - EGLint config_size, - EGLint* num_config) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - if (num_config == nullptr) - return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE); - if (!Config::ValidateAttributeList(attrib_list)) - return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - InitializeConfigsIfNeeded(); - if (!configs) - config_size = 0; - *num_config = 0; - for (size_t i = 0; i < arraysize(configs_); ++i) { - if (configs_[i]->Matches(attrib_list)) { - if (*num_config < config_size) { - configs[*num_config] = configs_[i].get(); - } - ++*num_config; +bool Display::GetConfigs(EGLConfig* configs, + EGLint config_size, + EGLint* num_config) { + // TODO(alokp): Find out a way to find all configs. CommandBuffer currently + // does not support finding or choosing configs. + *num_config = 1; + if (configs != NULL) { + if (config_ == NULL) { + config_.reset(new Config); } + configs[0] = config_.get(); } - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLBoolean Display::GetConfigs(ThreadState* ts, - EGLConfig* configs, - EGLint config_size, - EGLint* num_config) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - if (num_config == nullptr) - return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE); - InitializeConfigsIfNeeded(); - if (!configs) - config_size = 0; - *num_config = arraysize(configs_); - size_t count = - std::min(arraysize(configs_), static_cast<size_t>(config_size)); - for (size_t i = 0; i < count; ++i) - configs[i] = configs_[i].get(); - return ts->ReturnSuccess(EGL_TRUE); + return true; +} + +bool Display::GetConfigAttrib(EGLConfig config, + EGLint attribute, + EGLint* value) { + const egl::Config* cfg = static_cast<egl::Config*>(config); + return cfg->GetAttrib(attribute, value); } bool Display::IsValidNativeWindow(EGLNativeWindowType win) { @@ -113,215 +142,246 @@ bool Display::IsValidNativeWindow(EGLNativeWindowType win) { #endif // OS_WIN } -EGLBoolean Display::GetConfigAttrib(ThreadState* ts, - EGLConfig cfg, - EGLint attribute, - EGLint* value) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - const egl::Config* config = GetConfig(cfg); - if (!config) - return ts->ReturnError(EGL_BAD_CONFIG, EGL_FALSE); - if (!config->GetAttrib(attribute, value)) - return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLSurface Display::CreatePbufferSurface(ThreadState* ts, - EGLConfig cfg, - const EGLint* attrib_list) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE); - const egl::Config* config = GetConfig(cfg); - if (!config) - return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); - EGLint value = EGL_NONE; - config->GetAttrib(EGL_SURFACE_TYPE, &value); - if ((value & EGL_PBUFFER_BIT) == 0) - return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_SURFACE); - if (!egl::Surface::ValidatePbufferAttributeList(attrib_list)) - return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); - - int width = 1; - int height = 1; - if (attrib_list) { - for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) { - switch (attr[0]) { - case EGL_WIDTH: - width = attr[1]; - break; - case EGL_HEIGHT: - height = attr[1]; - break; - } - } - } - scoped_refptr<gfx::GLSurface> gl_surface; - gl_surface = - gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(width, height)); - if (!gl_surface) - return ts->ReturnError(EGL_BAD_ALLOC, nullptr); - surfaces_.emplace_back(new Surface(gl_surface.get())); - return ts->ReturnSuccess<EGLSurface>(surfaces_.back().get()); +bool Display::IsValidSurface(EGLSurface surface) { + return (surface != NULL) && (surface == surface_.get()); } -EGLSurface Display::CreateWindowSurface(ThreadState* ts, - EGLConfig cfg, +EGLSurface Display::CreateWindowSurface(EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE); - const egl::Config* config = GetConfig(cfg); - if (!config) - return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); - EGLint value = EGL_NONE; - config->GetAttrib(EGL_SURFACE_TYPE, &value); - if ((value & EGL_WINDOW_BIT) == 0) - return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE); - if (!IsValidNativeWindow(win)) - return ts->ReturnError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - if (!Surface::ValidateWindowAttributeList(attrib_list)) - return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); - scoped_refptr<gfx::GLSurface> gl_surface; - gl_surface = gfx::GLSurface::CreateViewGLSurface(win); - if (!gl_surface) - return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - surfaces_.emplace_back(new Surface(gl_surface.get())); - return ts->ReturnSuccess(surfaces_.back().get()); -} - -EGLBoolean Display::DestroySurface(ThreadState* ts, EGLSurface sfe) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - auto it = std::find(surfaces_.begin(), surfaces_.end(), sfe); - if (it == surfaces_.end()) - return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); - surfaces_.erase(it); - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLBoolean Display::ReleaseCurrent(ThreadState* ts) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnSuccess(EGL_TRUE); - ThreadState::AutoCurrentContextRestore accr(ts); - if (ts->current_context()) { - Context::MakeCurrent(ts->current_context(), - ts->current_surface()->gl_surface(), nullptr, nullptr); - accr.SetCurrent(nullptr, nullptr); + if (surface_ != NULL) { + // We do not support more than one window surface. + return EGL_NO_SURFACE; + } + + { + gpu::TransferBufferManager* manager = + new gpu::TransferBufferManager(nullptr); + transfer_buffer_manager_ = manager; + manager->Initialize(); } - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLBoolean Display::MakeCurrent(ThreadState* ts, - EGLSurface draw, - EGLSurface read, - EGLSurface ctx) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - ThreadState::AutoCurrentContextRestore accr(ts); - // Client might have called use because it changed some other gl binding - // global state. For example, the client might have called eglMakeCurrent on - // the same EGL as what command buffer uses. The client probably knows that - // this invalidates the internal state of command buffer, too. So reset the - // current context with accr in any case, regardless whether context or - // surface pointer changes. - Surface* new_surface = GetSurface(draw); - if (!new_surface) - return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); - new_surface = GetSurface(read); - if (!new_surface) - return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); - egl::Context* new_context = GetContext(ctx); - if (!new_context) - return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE); - if (draw != read) - return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE); - - Surface* current_surface = ts->current_surface(); - Context* current_context = ts->current_context(); - - if (current_context != new_context && - new_context->is_current_in_some_thread()) - return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE); - - if (current_surface != new_surface && - new_surface->is_current_in_some_thread()) - return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE); - - if (!Context::MakeCurrent( - current_context, - current_context ? current_surface->gl_surface() : nullptr, - new_context, new_context ? new_surface->gl_surface() : nullptr)) - return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE); - - accr.SetCurrent(new_surface, new_context); - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLBoolean Display::SwapBuffers(ThreadState* ts, EGLSurface sfe) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - egl::Surface* surface = GetSurface(sfe); - if (!surface) - return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); - if (ts->current_surface() != surface) - return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE); - ts->current_context()->FlushAndSwapBuffers(surface->gl_surface()); - return ts->ReturnSuccess(EGL_TRUE); -} - -EGLContext Display::CreateContext(ThreadState* ts, - EGLConfig cfg, + scoped_ptr<gpu::CommandBufferService> command_buffer( + new gpu::CommandBufferService(transfer_buffer_manager_.get())); + if (!command_buffer->Initialize()) + return NULL; + + scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( + NULL, NULL, new gpu::gles2::ShaderTranslatorCache, + new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true)); + + decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); + if (!decoder_.get()) + return EGL_NO_SURFACE; + + gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), + decoder_.get(), + NULL)); + + decoder_->set_engine(gpu_scheduler_.get()); + gfx::Size size(create_offscreen_width_, create_offscreen_height_); + if (create_offscreen_) { + gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); + create_offscreen_ = false; + create_offscreen_width_ = 0; + create_offscreen_height_ = 0; + } else { + gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); + } + if (!gl_surface_.get()) + return EGL_NO_SURFACE; + + gl_context_ = gfx::GLContext::CreateGLContext(NULL, + gl_surface_.get(), + gfx::PreferDiscreteGpu); + if (!gl_context_.get()) + return EGL_NO_SURFACE; + + gl_context_->MakeCurrent(gl_surface_.get()); + + EGLint depth_size = 0; + EGLint alpha_size = 0; + EGLint stencil_size = 0; + GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); + GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); + GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); + std::vector<int32_t> attribs; + attribs.push_back(EGL_DEPTH_SIZE); + attribs.push_back(depth_size); + attribs.push_back(EGL_ALPHA_SIZE); + attribs.push_back(alpha_size); + attribs.push_back(EGL_STENCIL_SIZE); + attribs.push_back(stencil_size); + // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null + attribs.push_back(EGL_NONE); + + if (!decoder_->Initialize(gl_surface_.get(), + gl_context_.get(), + gl_surface_->IsOffscreen(), + size, + gpu::gles2::DisallowedFeatures(), + attribs)) { + return EGL_NO_SURFACE; + } + + command_buffer->SetPutOffsetChangeCallback( + base::Bind(&gpu::GpuScheduler::PutChanged, + base::Unretained(gpu_scheduler_.get()))); + command_buffer->SetGetBufferChangeCallback( + base::Bind(&gpu::GpuScheduler::SetGetBuffer, + base::Unretained(gpu_scheduler_.get()))); + + scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper( + new gpu::gles2::GLES2CmdHelper(command_buffer.get())); + if (!cmd_helper->Initialize(kCommandBufferSize)) + return NULL; + + scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer( + cmd_helper.get())); + + command_buffer_.reset(command_buffer.release()); + transfer_buffer_.reset(transfer_buffer.release()); + gles2_cmd_helper_.reset(cmd_helper.release()); + surface_.reset(new Surface(win)); + + return surface_.get(); +} + +void Display::DestroySurface(EGLSurface surface) { + DCHECK(IsValidSurface(surface)); + gpu_scheduler_.reset(); + if (decoder_.get()) { + decoder_->Destroy(true); + } + decoder_.reset(); + gl_surface_ = NULL; + gl_context_ = NULL; + surface_.reset(); +} + +void Display::SwapBuffers(EGLSurface surface) { + DCHECK(IsValidSurface(surface)); + context_->SwapBuffers(); +} + +bool Display::IsValidContext(EGLContext ctx) { + return (ctx != NULL) && (ctx == context_.get()); +} + +EGLContext Display::CreateContext(EGLConfig config, EGLContext share_ctx, const EGLint* attrib_list) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_CONTEXT); - if (share_ctx != EGL_NO_CONTEXT) { - egl::Context* share_context = GetContext(share_ctx); - if (!share_context) - return ts->ReturnError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); - // TODO(alokp): Add support for shared contexts. - return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_CONTEXT); + DCHECK(IsValidConfig(config)); + // TODO(alokp): Add support for shared contexts. + if (share_ctx != NULL) + return EGL_NO_CONTEXT; + + DCHECK(command_buffer_ != NULL); + DCHECK(transfer_buffer_.get()); + + bool bind_generates_resources = true; + bool lose_context_when_out_of_memory = false; + bool support_client_side_arrays = true; + + context_.reset( + new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), + NULL, + transfer_buffer_.get(), + bind_generates_resources, + lose_context_when_out_of_memory, + support_client_side_arrays, + this)); + + if (!context_->Initialize( + kTransferBufferSize, + kTransferBufferSize / 2, + kTransferBufferSize * 2, + gpu::gles2::GLES2Implementation::kNoLimit)) { + return EGL_NO_CONTEXT; + } + + context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); + context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); + + return context_.get(); +} + +void Display::DestroyContext(EGLContext ctx) { + DCHECK(IsValidContext(ctx)); + context_.reset(); + transfer_buffer_.reset(); +} + +bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { + if (ctx == EGL_NO_CONTEXT) { + gles2::SetGLContext(NULL); + } else { + DCHECK(IsValidSurface(draw)); + DCHECK(IsValidSurface(read)); + DCHECK(IsValidContext(ctx)); + gles2::SetGLContext(context_.get()); + gl_context_->MakeCurrent(gl_surface_.get()); } - if (!egl::Context::ValidateAttributeList(attrib_list)) - return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); - const egl::Config* config = GetConfig(cfg); - if (!config) - return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_CONTEXT); - scoped_refptr<Context> context(new Context(this, config)); - if (!context) - return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); - contexts_.emplace_back(context.get()); - return ts->ReturnSuccess<EGLContext>(context.get()); -} - -EGLBoolean Display::DestroyContext(ThreadState* ts, EGLContext ctx) { - base::AutoLock auto_lock(lock_); - if (!is_initialized_) - return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE); - auto it = std::find(contexts_.begin(), contexts_.end(), ctx); - if (it == contexts_.end()) - return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE); - (*it)->MarkDestroyed(); - contexts_.erase(it); - return ts->ReturnSuccess(EGL_TRUE); + return true; +} + +gpu::Capabilities Display::GetCapabilities() { + return decoder_->GetCapabilities(); +} + +int32_t Display::CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) { + NOTIMPLEMENTED(); + return -1; +} + +void Display::DestroyImage(int32_t id) { + NOTIMPLEMENTED(); +} + +int32_t Display::CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) { + NOTIMPLEMENTED(); + return -1; +} + +void Display::SignalQuery(uint32_t query, const base::Closure& callback) { + NOTIMPLEMENTED(); +} + +void Display::SetLock(base::Lock*) { + NOTIMPLEMENTED(); +} + +bool Display::IsGpuChannelLost() { + NOTIMPLEMENTED(); + return false; +} + +void Display::EnsureWorkVisible() { + // This is only relevant for out-of-process command buffers. +} + +gpu::CommandBufferNamespace Display::GetNamespaceID() const { + return gpu::CommandBufferNamespace::IN_PROCESS; +} + +gpu::CommandBufferId Display::GetCommandBufferID() const { + return gpu::CommandBufferId(); +} + +int32_t Display::GetExtraCommandBufferData() const { + return 0; } uint64_t Display::GenerateFenceSyncRelease() { - base::AutoLock auto_lock(lock_); return next_fence_sync_release_++; } bool Display::IsFenceSyncRelease(uint64_t release) { - base::AutoLock auto_lock(lock_); return release > 0 && release < next_fence_sync_release_; } @@ -333,41 +393,13 @@ bool Display::IsFenceSyncFlushReceived(uint64_t release) { return IsFenceSyncRelease(release); } -void Display::InitializeConfigsIfNeeded() { - lock_.AssertAcquired(); - if (!configs_[0]) { - // The interface offers separate configs for window and pbuffer. - // This way we can record the client intention at context creation time. - // The GL implementation (gfx::GLContext and gfx::GLSurface) needs this - // distinction when creating a context. - configs_[0].reset(new Config(EGL_WINDOW_BIT)); - configs_[1].reset(new Config(EGL_PBUFFER_BIT)); - } -} - -const Config* Display::GetConfig(EGLConfig cfg) { - lock_.AssertAcquired(); - for (const auto& config : configs_) { - if (config.get() == cfg) - return config.get(); - } - return nullptr; -} - -Surface* Display::GetSurface(EGLSurface surface) { - lock_.AssertAcquired(); - auto it = std::find(surfaces_.begin(), surfaces_.end(), surface); - if (it == surfaces_.end()) - return nullptr; - return it->get(); +void Display::SignalSyncToken(const gpu::SyncToken& sync_token, + const base::Closure& callback) { + NOTIMPLEMENTED(); } -Context* Display::GetContext(EGLContext context) { - lock_.AssertAcquired(); - auto it = std::find(contexts_.begin(), contexts_.end(), context); - if (it == contexts_.end()) - return nullptr; - return it->get(); +bool Display::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) { + return false; } } // namespace egl diff --git a/gpu/gles2_conform_support/egl/display.h b/gpu/gles2_conform_support/egl/display.h index 619fed9..292d68b 100644 --- a/gpu/gles2_conform_support/egl/display.h +++ b/gpu/gles2_conform_support/egl/display.h @@ -9,87 +9,122 @@ #include <stddef.h> #include <stdint.h> -#include <vector> - #include "base/macros.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" +#include "gpu/command_buffer/client/gpu_control.h" +#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gpu_scheduler.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" + +namespace gpu { +class CommandBufferService; +class GpuControl; +class GpuScheduler; +class TransferBuffer; +class TransferBufferManagerInterface; + +namespace gles2 { +class GLES2CmdHelper; +class GLES2Implementation; +} // namespace gles2 +} // namespace gpu namespace egl { class Config; -class Context; class Surface; -class ThreadState; -class Display { +class Display : private gpu::GpuControl { public: - explicit Display(); - ~Display(); - - bool is_initialized() const { return is_initialized_; } + explicit Display(EGLNativeDisplayType display_id); + ~Display() override; - void ReleaseCurrentForReleaseThread(ThreadState*); + void SetCreateOffscreen(int width, int height) { + create_offscreen_ = true; + create_offscreen_width_ = width; + create_offscreen_height_ = height; + } - EGLBoolean Initialize(ThreadState* ts, EGLint* major, EGLint* minor); - EGLBoolean Terminate(ThreadState* ts); - const char* QueryString(ThreadState* ts, EGLint name); + bool is_initialized() const { return is_initialized_; } + bool Initialize(); // Config routines. - EGLBoolean GetConfigAttrib(ThreadState* ts, - EGLConfig cfg, - EGLint attribute, - EGLint* value); - EGLBoolean ChooseConfig(ThreadState* ts, - const EGLint* attrib_list, - EGLConfig* configs, - EGLint config_size, - EGLint* num_config); - EGLBoolean GetConfigs(ThreadState*, - EGLConfig*, - EGLint config_size, - EGLint* num_config); + bool IsValidConfig(EGLConfig config); + bool ChooseConfigs( + EGLConfig* configs, EGLint config_size, EGLint* num_config); + bool GetConfigs(EGLConfig* configs, EGLint config_size, EGLint* num_config); + bool GetConfigAttrib(EGLConfig config, EGLint attribute, EGLint* value); // Surface routines. - static bool IsValidNativeWindow(EGLNativeWindowType); - EGLSurface CreatePbufferSurface(ThreadState*, - EGLConfig, - const EGLint* attrib_list); - EGLSurface CreateWindowSurface(ThreadState*, - EGLConfig, + bool IsValidNativeWindow(EGLNativeWindowType win); + bool IsValidSurface(EGLSurface surface); + EGLSurface CreateWindowSurface(EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list); - EGLBoolean DestroySurface(ThreadState*, EGLSurface); - EGLBoolean SwapBuffers(ThreadState*, EGLSurface); + void DestroySurface(EGLSurface surface); + void SwapBuffers(EGLSurface surface); // Context routines. - EGLContext CreateContext(ThreadState*, - EGLConfig, - EGLSurface share_ctx, + bool IsValidContext(EGLContext ctx); + EGLContext CreateContext(EGLConfig config, + EGLContext share_ctx, const EGLint* attrib_list); - EGLBoolean DestroyContext(ThreadState*, EGLContext); - - EGLBoolean ReleaseCurrent(ThreadState*); - EGLBoolean MakeCurrent(ThreadState*, EGLSurface, EGLSurface, EGLContext); - - uint64_t GenerateFenceSyncRelease(); - bool IsFenceSyncRelease(uint64_t release); - bool IsFenceSyncFlushed(uint64_t release); - bool IsFenceSyncFlushReceived(uint64_t release); + void DestroyContext(EGLContext ctx); + bool MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx); + + // GpuControl implementation. + gpu::Capabilities GetCapabilities() override; + int32_t CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) override; + void DestroyImage(int32_t id) override; + int32_t CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) override; + void SignalQuery(uint32_t query, const base::Closure& callback) override; + void SetLock(base::Lock*) override; + bool IsGpuChannelLost() override; + void EnsureWorkVisible() override; + gpu::CommandBufferNamespace GetNamespaceID() const override; + gpu::CommandBufferId GetCommandBufferID() const override; + int32_t GetExtraCommandBufferData() const override; + uint64_t GenerateFenceSyncRelease() override; + bool IsFenceSyncRelease(uint64_t release) override; + bool IsFenceSyncFlushed(uint64_t release) override; + bool IsFenceSyncFlushReceived(uint64_t release) override; + void SignalSyncToken(const gpu::SyncToken& sync_token, + const base::Closure& callback) override; + bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override; private: - void InitializeConfigsIfNeeded(); - const Config* GetConfig(EGLConfig); - Surface* GetSurface(EGLSurface); - Context* GetContext(EGLContext); + EGLNativeDisplayType display_id_; - base::Lock lock_; bool is_initialized_; + + bool create_offscreen_; + int create_offscreen_width_; + int create_offscreen_height_; uint64_t next_fence_sync_release_; - std::vector<scoped_refptr<Surface>> surfaces_; - std::vector<scoped_refptr<Context>> contexts_; - scoped_ptr<Config> configs_[2]; + + scoped_refptr<gpu::TransferBufferManagerInterface> transfer_buffer_manager_; + scoped_ptr<gpu::CommandBufferService> command_buffer_; + scoped_ptr<gpu::GpuScheduler> gpu_scheduler_; + scoped_ptr<gpu::gles2::GLES2Decoder> decoder_; + scoped_refptr<gfx::GLContext> gl_context_; + scoped_refptr<gfx::GLSurface> gl_surface_; + scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_; + scoped_ptr<gpu::TransferBuffer> transfer_buffer_; + + // TODO(alokp): Support more than one config, surface, and context. + scoped_ptr<Config> config_; + scoped_ptr<Surface> surface_; + scoped_ptr<gpu::gles2::GLES2Implementation> context_; DISALLOW_COPY_AND_ASSIGN(Display); }; diff --git a/gpu/gles2_conform_support/egl/egl.cc b/gpu/gles2_conform_support/egl/egl.cc index b14479b..5a81954 100644 --- a/gpu/gles2_conform_support/egl/egl.cc +++ b/gpu/gles2_conform_support/egl/egl.cc @@ -5,58 +5,184 @@ #include <EGL/egl.h> #include <stdint.h> +#include "base/command_line.h" +#include "base/environment.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/gles2_conform_support/egl/config.h" -#include "gpu/gles2_conform_support/egl/context.h" +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/config/gpu_info_collector.h" +#include "gpu/config/gpu_util.h" #include "gpu/gles2_conform_support/egl/display.h" -#include "gpu/gles2_conform_support/egl/surface.h" -#include "gpu/gles2_conform_support/egl/thread_state.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" + +#if REGAL_STATIC_EGL +extern "C" { + +typedef EGLContext RegalSystemContext; +#define REGAL_DECL +REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx ); + +} // extern "C" +#endif + +namespace { +void SetCurrentError(EGLint error_code) { +} + +template<typename T> +T EglError(EGLint error_code, T return_value) { + SetCurrentError(error_code); + return return_value; +} + +template<typename T> +T EglSuccess(T return_value) { + SetCurrentError(EGL_SUCCESS); + return return_value; +} + +EGLint ValidateDisplay(EGLDisplay dpy) { + if (dpy == EGL_NO_DISPLAY) + return EGL_BAD_DISPLAY; + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->is_initialized()) + return EGL_NOT_INITIALIZED; + + return EGL_SUCCESS; +} + +EGLint ValidateDisplayConfig(EGLDisplay dpy, EGLConfig config) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return error_code; + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->IsValidConfig(config)) + return EGL_BAD_CONFIG; + + return EGL_SUCCESS; +} + +EGLint ValidateDisplaySurface(EGLDisplay dpy, EGLSurface surface) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return error_code; + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->IsValidSurface(surface)) + return EGL_BAD_SURFACE; + + return EGL_SUCCESS; +} + +EGLint ValidateDisplayContext(EGLDisplay dpy, EGLContext context) { + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return error_code; + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->IsValidContext(context)) + return EGL_BAD_CONTEXT; + + return EGL_SUCCESS; +} +} // namespace extern "C" { EGLAPI EGLint EGLAPIENTRY eglGetError() { - return egl::ThreadState::Get()->ConsumeErrorCode(); + // TODO(alokp): Fix me. + return EGL_SUCCESS; } EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { - if (display_id != EGL_DEFAULT_DISPLAY) - return EGL_NO_DISPLAY; - return egl::ThreadState::Get()->GetDefaultDisplay(); + return new egl::Display(display_id); } EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->Initialize(ts, major, minor); + if (dpy == EGL_NO_DISPLAY) + return EglError(EGL_BAD_DISPLAY, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->Initialize()) + return EglError(EGL_NOT_INITIALIZED, EGL_FALSE); + + // eglInitialize can be called multiple times, prevent InitializeOneOff from + // being called multiple times. + if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) { + base::CommandLine::StringVector argv; + scoped_ptr<base::Environment> env(base::Environment::Create()); + std::string env_string; + env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string); +#if defined(OS_WIN) + argv = base::SplitString(base::UTF8ToUTF16(env_string), + base::kWhitespaceUTF16, base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + argv.insert(argv.begin(), base::UTF8ToUTF16("dummy")); +#else + argv = base::SplitString(env_string, + base::kWhitespaceASCII, base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + argv.insert(argv.begin(), "dummy"); +#endif + base::CommandLine::Init(0, nullptr); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + // Need to call both Init and InitFromArgv, since Windows does not use + // argc, argv in CommandLine::Init(argc, argv). + command_line->InitFromArgv(argv); + if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { + gpu::GPUInfo gpu_info; + gpu::CollectBasicGraphicsInfo(&gpu_info); + gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line); + } + + gfx::GLSurface::InitializeOneOff(); + } + if (major) + *major = 1; + if (minor) + *minor = 4; + return EglSuccess(EGL_TRUE); } EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->Terminate(ts); + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + delete display; + + // TODO: EGL specifies that the objects are marked for deletion and they will + // remain alive as long as "contexts or surfaces associated with display is + // current to any thread". + // Currently we delete the display here, and may also call exit handlers. + + return EglSuccess(EGL_TRUE); } EGLAPI const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { - egl::ThreadState* ts = egl::ThreadState::Get(); - if (dpy == EGL_NO_DISPLAY) { - switch (name) { - case EGL_EXTENSIONS: - return ts->ReturnSuccess(""); - case EGL_VERSION: - return ts->ReturnSuccess("1.4"); - default: - break; - } + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, static_cast<const char*>(NULL)); + + switch (name) { + case EGL_CLIENT_APIS: + return EglSuccess("OpenGL_ES"); + case EGL_EXTENSIONS: + return EglSuccess(""); + case EGL_VENDOR: + return EglSuccess("Google Inc."); + case EGL_VERSION: + return EglSuccess("1.4"); + default: + return EglError(EGL_BAD_PARAMETER, static_cast<const char*>(NULL)); } - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError<const char*>(EGL_BAD_DISPLAY, nullptr); - return display->QueryString(ts, name); } EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, @@ -64,57 +190,103 @@ EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->ChooseConfig(ts, attrib_list, configs, config_size, - num_config); + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + if (num_config == NULL) + return EglError(EGL_BAD_PARAMETER, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->ChooseConfigs(configs, config_size, num_config)) + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + + return EglSuccess(EGL_TRUE); } EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->GetConfigs(ts, configs, config_size, num_config); + EGLint error_code = ValidateDisplay(dpy); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + if (num_config == NULL) + return EglError(EGL_BAD_PARAMETER, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->GetConfigs(configs, config_size, num_config)) + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + + return EglSuccess(EGL_TRUE); } EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, - EGLConfig cfg, + EGLConfig config, EGLint attribute, EGLint* value) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->GetConfigAttrib(ts, cfg, attribute, value); + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->GetConfigAttrib(config, attribute, value)) + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + + return EglSuccess(EGL_TRUE); } EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, - EGLConfig cfg, + EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - return display->CreateWindowSurface(ts, cfg, win, attrib_list); + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_SURFACE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->IsValidNativeWindow(win)) + return EglError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + + EGLSurface surface = display->CreateWindowSurface(config, win, attrib_list); + if (surface == EGL_NO_SURFACE) + return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + + return EglSuccess(surface); } EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, - EGLConfig cfg, + EGLConfig config, const EGLint* attrib_list) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - return display->CreatePbufferSurface(ts, cfg, attrib_list); + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_SURFACE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + int width = 1; + int height = 1; + if (attrib_list) { + for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) { + switch (attr[0]) { + case EGL_WIDTH: + width = attr[1]; + break; + case EGL_HEIGHT: + height = attr[1]; + break; + } + } + } + display->SetCreateOffscreen(width, height); + + EGLSurface surface = display->CreateWindowSurface(config, 0, attrib_list); + if (surface == EGL_NO_SURFACE) + return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + + return EglSuccess(surface); } EGLAPI EGLSurface EGLAPIENTRY @@ -126,12 +298,14 @@ eglCreatePixmapSurface(EGLDisplay dpy, } EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, - EGLSurface sfe) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->DestroySurface(ts, sfe); + EGLSurface surface) { + EGLint error_code = ValidateDisplaySurface(dpy, surface); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + display->DestroySurface(surface); + return EglSuccess(EGL_TRUE); } EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, @@ -154,8 +328,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void) { } EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) { - egl::ThreadState::ReleaseThread(); - return EGL_TRUE; + return EGL_FALSE; } EGLAPI EGLSurface EGLAPIENTRY @@ -191,42 +364,64 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) { } EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, - EGLConfig cfg, - EGLContext share_ctx, + EGLConfig config, + EGLContext share_context, const EGLint* attrib_list) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_CONTEXT); - return display->CreateContext(ts, cfg, share_ctx, attrib_list); + EGLint error_code = ValidateDisplayConfig(dpy, config); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_CONTEXT); + + if (share_context != EGL_NO_CONTEXT) { + error_code = ValidateDisplayContext(dpy, share_context); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_NO_CONTEXT); + } + + egl::Display* display = static_cast<egl::Display*>(dpy); + EGLContext context = display->CreateContext( + config, share_context, attrib_list); + if (context == EGL_NO_CONTEXT) + return EglError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + + return EglSuccess(context); } EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->DestroyContext(ts, ctx); + EGLint error_code = ValidateDisplayContext(dpy, ctx); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + display->DestroyContext(ctx); + return EGL_TRUE; } EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { - egl::ThreadState* ts = egl::ThreadState::Get(); - if (draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && - ctx == EGL_NO_CONTEXT) { - egl::Display* display = - dpy == EGL_NO_DISPLAY ? ts->GetDefaultDisplay() : ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->ReleaseCurrent(ts); + if (ctx != EGL_NO_CONTEXT) { + EGLint error_code = ValidateDisplaySurface(dpy, draw); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + error_code = ValidateDisplaySurface(dpy, read); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + error_code = ValidateDisplayContext(dpy, ctx); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); } - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->MakeCurrent(ts, draw, read, ctx); + + egl::Display* display = static_cast<egl::Display*>(dpy); + if (!display->MakeCurrent(draw, read, ctx)) + return EglError(EGL_CONTEXT_LOST, EGL_FALSE); + +#if REGAL_STATIC_EGL + RegalMakeCurrent(ctx); +#endif + + return EGL_TRUE; } EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext() { @@ -256,12 +451,15 @@ EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { return EGL_FALSE; } -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sfe) { - egl::ThreadState* ts = egl::ThreadState::Get(); - egl::Display* display = ts->GetDisplay(dpy); - if (!display) - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE); - return display->SwapBuffers(ts, sfe); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, + EGLSurface surface) { + EGLint error_code = ValidateDisplaySurface(dpy, surface); + if (error_code != EGL_SUCCESS) + return EglError(error_code, EGL_FALSE); + + egl::Display* display = static_cast<egl::Display*>(dpy); + display->SwapBuffers(surface); + return EglSuccess(EGL_TRUE); } EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, diff --git a/gpu/gles2_conform_support/egl/surface.cc b/gpu/gles2_conform_support/egl/surface.cc index 9899cb3..423fe27 100644 --- a/gpu/gles2_conform_support/egl/surface.cc +++ b/gpu/gles2_conform_support/egl/surface.cc @@ -3,40 +3,13 @@ // found in the LICENSE file. #include "gpu/gles2_conform_support/egl/surface.h" -#include "ui/gl/gl_surface.h" namespace egl { -Surface::Surface(gfx::GLSurface* gl_surface) - : is_current_in_some_thread_(false), gl_surface_(gl_surface) {} - -Surface::~Surface() { -} - -gfx::GLSurface* Surface::gl_surface() const { - return gl_surface_.get(); +Surface::Surface(EGLNativeWindowType win) : window_(win) { } -bool Surface::ValidatePbufferAttributeList(const EGLint* attrib_list) { - if (attrib_list) { - for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) { - switch (attrib_list[i]) { - case EGL_WIDTH: - case EGL_HEIGHT: - break; - default: - return false; - } - } - } - return true; +Surface::~Surface() { } -bool Surface::ValidateWindowAttributeList(const EGLint* attrib_list) { - if (attrib_list) { - if (attrib_list[0] != EGL_NONE) - return false; - } - return true; -} } // namespace egl diff --git a/gpu/gles2_conform_support/egl/surface.h b/gpu/gles2_conform_support/egl/surface.h index 84ba0aa..3db553e 100644 --- a/gpu/gles2_conform_support/egl/surface.h +++ b/gpu/gles2_conform_support/egl/surface.h @@ -8,28 +8,19 @@ #include <EGL/egl.h> #include "base/macros.h" -#include "base/memory/ref_counted.h" -namespace gfx { -class GLSurface; -} + namespace egl { -class Surface : public base::RefCountedThreadSafe<Surface> { +class Surface { public: - explicit Surface(gfx::GLSurface* gl_surface); - void set_is_current_in_some_thread(bool flag) { - is_current_in_some_thread_ = flag; - } - bool is_current_in_some_thread() const { return is_current_in_some_thread_; } - gfx::GLSurface* gl_surface() const; - static bool ValidatePbufferAttributeList(const EGLint* attrib_list); - static bool ValidateWindowAttributeList(const EGLint* attrib_list); + explicit Surface(EGLNativeWindowType win); + ~Surface(); + + EGLNativeWindowType window() { return window_; } private: - friend class base::RefCountedThreadSafe<Surface>; - ~Surface(); - bool is_current_in_some_thread_; - scoped_refptr<gfx::GLSurface> gl_surface_; + EGLNativeWindowType window_; + DISALLOW_COPY_AND_ASSIGN(Surface); }; diff --git a/gpu/gles2_conform_support/egl/thread_state.cc b/gpu/gles2_conform_support/egl/thread_state.cc deleted file mode 100644 index 5f2e691..0000000 --- a/gpu/gles2_conform_support/egl/thread_state.cc +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 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 "gpu/gles2_conform_support/egl/thread_state.h" - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/environment.h" -#include "base/lazy_instance.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "gpu/command_buffer/client/gles2_lib.h" -#include "gpu/command_buffer/common/thread_local.h" -#include "gpu/command_buffer/service/gpu_switches.h" -#include "gpu/config/gpu_info_collector.h" -#include "gpu/config/gpu_util.h" -#include "gpu/gles2_conform_support/egl/context.h" -#include "gpu/gles2_conform_support/egl/display.h" -#include "gpu/gles2_conform_support/egl/surface.h" -#include "gpu/gles2_conform_support/egl/test_support.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_surface.h" - -// Thread local key for ThreadState instance. Accessed when holding g_egl_lock -// only, since the initialization can not be Guaranteed otherwise. Not in -// anonymous namespace due to Mac OS X 10.6 linker. See gles2_lib.cc. -static gpu::ThreadLocalKey g_egl_thread_state_key; - -namespace { -base::LazyInstance<base::Lock>::Leaky g_egl_lock; -int g_egl_active_thread_count; - -egl::Display* g_egl_default_display; - -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) -// egl::Display is used for comformance tests and command_buffer_gles. We only -// need the exit manager for the command_buffer_gles library. -base::AtExitManager* g_exit_manager; -#endif -} // namespace - -namespace egl { - -egl::ThreadState* ThreadState::Get() { - base::AutoLock lock(g_egl_lock.Get()); - if (g_egl_active_thread_count == 0) { -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) -#if defined(COMPONENT_BUILD) - if (!g_command_buffer_gles_has_atexit_manager) - g_exit_manager = new base::AtExitManager; -#else - g_exit_manager = new base::AtExitManager; -#endif -#endif - gles2::Initialize(); - - if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) { - base::CommandLine::StringVector argv; - scoped_ptr<base::Environment> env(base::Environment::Create()); - std::string env_string; - env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string); -#if defined(OS_WIN) - argv = base::SplitString(base::UTF8ToUTF16(env_string), - base::kWhitespaceUTF16, base::TRIM_WHITESPACE, - base::SPLIT_WANT_NONEMPTY); - argv.insert(argv.begin(), base::UTF8ToUTF16("dummy")); -#else - argv = - base::SplitString(env_string, base::kWhitespaceASCII, - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - argv.insert(argv.begin(), "dummy"); -#endif - base::CommandLine::Init(0, nullptr); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - // Need to call both Init and InitFromArgv, since Windows does not use - // argc, argv in CommandLine::Init(argc, argv). - command_line->InitFromArgv(argv); - if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { - gpu::GPUInfo gpu_info; - gpu::CollectBasicGraphicsInfo(&gpu_info); - gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line); - } - - gfx::GLSurface::InitializeOneOff(); - } - - g_egl_default_display = new egl::Display(); - g_egl_thread_state_key = gpu::ThreadLocalAlloc(); - } - egl::ThreadState* thread_state = static_cast<egl::ThreadState*>( - gpu::ThreadLocalGetValue(g_egl_thread_state_key)); - if (!thread_state) { - thread_state = new egl::ThreadState; - gpu::ThreadLocalSetValue(g_egl_thread_state_key, thread_state); - ++g_egl_active_thread_count; - } - return thread_state; -} - -void ThreadState::ReleaseThread() { - base::AutoLock lock(g_egl_lock.Get()); - if (g_egl_active_thread_count == 0) - return; - - egl::ThreadState* thread_state = static_cast<egl::ThreadState*>( - gpu::ThreadLocalGetValue(g_egl_thread_state_key)); - if (!thread_state) - return; - - --g_egl_active_thread_count; - if (g_egl_active_thread_count > 0) { - g_egl_default_display->ReleaseCurrent(thread_state); - delete thread_state; - } else { - gpu::ThreadLocalFree(g_egl_thread_state_key); - - // First delete the display object, so that it drops the possible refs to - // current context. - delete g_egl_default_display; - g_egl_default_display = nullptr; - - // We can use Surface and Context without lock, since there's no threads - // left anymore. Destroy the current context explicitly, in an attempt to - // reduce the number of error messages abandoned context would produce. - if (thread_state->current_context()) { - Context::MakeCurrent(thread_state->current_context(), - thread_state->current_surface()->gl_surface(), - nullptr, nullptr); - } - delete thread_state; - - gles2::Terminate(); -#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY) -#if defined(COMPONENT_BUILD) - if (g_command_buffer_gles_has_atexit_manager) - delete g_exit_manager; -#else - delete g_exit_manager; -#endif - g_exit_manager = nullptr; -#endif - } -} - -ThreadState::ThreadState() : error_code_(EGL_SUCCESS) {} - -ThreadState::~ThreadState() {} - -EGLint ThreadState::ConsumeErrorCode() { - EGLint current_error_code = error_code_; - error_code_ = EGL_SUCCESS; - return current_error_code; -} - -Display* ThreadState::GetDisplay(EGLDisplay dpy) { - if (dpy == g_egl_default_display) - return g_egl_default_display; - return nullptr; -} - -Display* ThreadState::GetDefaultDisplay() { - return g_egl_default_display; -} - -void ThreadState::SetCurrent(Surface* surface, Context* context) { - DCHECK((surface == nullptr) == (context == nullptr)); - if (current_context_) { - current_context_->set_is_current_in_some_thread(false); - current_surface_->set_is_current_in_some_thread(false); - } - current_surface_ = surface; - current_context_ = context; - if (current_context_) { - current_context_->set_is_current_in_some_thread(true); - current_surface_->set_is_current_in_some_thread(true); - } -} - -ThreadState::AutoCurrentContextRestore::AutoCurrentContextRestore( - ThreadState* thread_state) - : thread_state_(thread_state) {} - -ThreadState::AutoCurrentContextRestore::~AutoCurrentContextRestore() { - if (Context* current_context = thread_state_->current_context()) { - current_context->ApplyCurrentContext( - thread_state_->current_surface()->gl_surface()); - } else { - Context::ApplyContextReleased(); - } -} - -void ThreadState::AutoCurrentContextRestore::SetCurrent(Surface* surface, - Context* context) { - thread_state_->SetCurrent(surface, context); -} - -} // namespace egl diff --git a/gpu/gles2_conform_support/egl/thread_state.h b/gpu/gles2_conform_support/egl/thread_state.h deleted file mode 100644 index 963ac5c..0000000 --- a/gpu/gles2_conform_support/egl/thread_state.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 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. - -#ifndef GPU_GLES2_CONFORM_SUPPORT_EGL_STATE_H_ -#define GPU_GLES2_CONFORM_SUPPORT_EGL_STATE_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include <EGL/egl.h> - -namespace egl { - -class Context; -class Display; -class Surface; - -// Thread-local API state of EGL. -class ThreadState { - public: - // Factory getter for the class. Should only be called by the API layer, and - // then passed through Display in order to avoid lock issues. - static ThreadState* Get(); - static void ReleaseThread(); - - Surface* current_surface() const { return current_surface_.get(); } - Context* current_context() const { return current_context_.get(); } - - template <typename T> - T ReturnError(EGLint error, T return_value) { - error_code_ = error; - return return_value; - } - template <typename T> - T ReturnSuccess(T return_value) { - error_code_ = EGL_SUCCESS; - return return_value; - } - EGLint ConsumeErrorCode(); - - Display* GetDefaultDisplay(); - Display* GetDisplay(EGLDisplay); - - // RAII class for ensuring that ThreadState current context - // is reflected in the gfx:: and gles:: global variables. - class AutoCurrentContextRestore { - public: - AutoCurrentContextRestore(ThreadState*); - ~AutoCurrentContextRestore(); - void SetCurrent(Surface*, Context*); - - private: - ThreadState* thread_state_; - DISALLOW_COPY_AND_ASSIGN(AutoCurrentContextRestore); - }; - - private: - ThreadState(); - ~ThreadState(); - void SetCurrent(Surface*, Context*); - - EGLint error_code_; - scoped_refptr<Surface> current_surface_; - scoped_refptr<Context> current_context_; - DISALLOW_COPY_AND_ASSIGN(ThreadState); -}; - -} // namespace egl - -#endif diff --git a/gpu/gles2_conform_support/gles2_conform_support.gyp b/gpu/gles2_conform_support/gles2_conform_support.gyp index 681aa1f..f585d92 100644 --- a/gpu/gles2_conform_support/gles2_conform_support.gyp +++ b/gpu/gles2_conform_support/gles2_conform_support.gyp @@ -27,7 +27,6 @@ 'type': 'static_library', 'dependencies': [ '../../base/base.gyp:base', - '../../gpu/command_buffer/command_buffer.gyp:gles2_utils', '../../gpu/gpu.gyp:command_buffer_service', '../../gpu/gpu.gyp:gles2_implementation_no_check', '../../gpu/gpu.gyp:gpu', @@ -39,15 +38,11 @@ 'sources': [ 'egl/config.cc', 'egl/config.h', - 'egl/context.cc', - 'egl/context.h', 'egl/display.cc', 'egl/display.h', 'egl/egl.cc', 'egl/surface.cc', 'egl/surface.h', - 'egl/thread_state.cc', - 'egl/thread_state.h', ], 'defines': [ 'EGLAPI=', diff --git a/gpu/gles2_conform_support/native/egl_native_windowless.cc b/gpu/gles2_conform_support/native/egl_native_windowless.cc index 077883e..222e4f6 100644 --- a/gpu/gles2_conform_support/native/egl_native_windowless.cc +++ b/gpu/gles2_conform_support/native/egl_native_windowless.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "gpu/gles2_conform_support/egl/display.h" + extern "C" { #if defined(GLES2_CONFORM_SUPPORT_ONLY) #include "gpu/gles2_conform_support/gtf/gtf_stubs.h" @@ -22,8 +24,9 @@ GTFbool GTFNativeCreateWindow(EGLNativeDisplayType nativeDisplay, EGLDisplay eglDisplay, EGLConfig eglConfig, const char* title, int width, int height, EGLNativeWindowType *pNativeWindow) { - // GTF should use EGL pbuffer interface directly. - return GTFfalse; + egl::Display* display = static_cast<egl::Display*>(eglDisplay); + display->SetCreateOffscreen(width, height); + return GTFtrue; } void GTFNativeDestroyWindow(EGLNativeDisplayType nativeDisplay, diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 5f95bc5..2ad775d 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -427,7 +427,6 @@ '../gpu/gpu.gyp:command_buffer_service', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', - 'command_buffer/command_buffer.gyp:gles2_utils', 'gles2_c_lib', 'gles2_implementation', ], @@ -436,8 +435,6 @@ # TODO(hendrikw): Move egl out of gles2_conform_support. 'gles2_conform_support/egl/config.cc', 'gles2_conform_support/egl/config.h', - 'gles2_conform_support/egl/context.cc', - 'gles2_conform_support/egl/context.h', 'gles2_conform_support/egl/display.cc', 'gles2_conform_support/egl/display.h', 'gles2_conform_support/egl/egl.cc', @@ -445,8 +442,6 @@ 'gles2_conform_support/egl/surface.h', 'gles2_conform_support/egl/test_support.cc', 'gles2_conform_support/egl/test_support.h', - 'gles2_conform_support/egl/thread_state.cc', - 'gles2_conform_support/egl/thread_state.h', ], 'defines': [ 'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY', |