diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-17 10:19:09 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-17 10:19:09 +0000 |
commit | c4485aad698e143020b8177d688005d1a1705223 (patch) | |
tree | e6fb0ddfda378597f540f5650851492e7b26b801 | |
parent | 40b2d96a694b5dcdf9883d7296c132115670e0a9 (diff) | |
download | chromium_src-c4485aad698e143020b8177d688005d1a1705223.zip chromium_src-c4485aad698e143020b8177d688005d1a1705223.tar.gz chromium_src-c4485aad698e143020b8177d688005d1a1705223.tar.bz2 |
Add a command to lose the context
BUG=166020
Review URL: https://chromiumcodereview.appspot.com/11568029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173441 0039d316-1c4b-4281-b951-d872f2087c98
37 files changed, 411 insertions, 40 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_lose_context.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_lose_context.txt new file mode 100644 index 0000000..a7ff30c --- /dev/null +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_lose_context.txt @@ -0,0 +1,55 @@ +Name + + CHROMIUM_lose_context + +Name Strings + + GL_CHROMIUM_lose_context + +Version + + Last Modifed Date: December 17, 2012 + +Dependencies + + OpenGL ES 2.0 is required. + +Overview + + This extension allows an application to force a lost context event. + This is useful for debugging that an app can correctly handle the context + becoming lost. + +Issues + + None + +New Tokens + + None + +New Procedures and Functions + + void LoseContextCHROMIUM (GLenum current, GLenum other) + + Causes the current context and all other contexts in the same share group + to become lost. <current> and <other> can each be one of: + + GL_GUILTY_CONTEXT_RESET_EXT + GL_INNOCENT_CONTEXT_RESET_EXT + GL_UNKNOWN_CONTEXT_RESET_EXT + + INVALID_ENUM is generated if <current> or <other> is not one of the values + mentioned above. + +Errors + + None. + +New State + + None. + +Revision History + + 12/17/2012 Documented the extension diff --git a/gpu/GLES2/gl2chromium.h b/gpu/GLES2/gl2chromium.h index 8598052..7cc84f0 100644 --- a/gpu/GLES2/gl2chromium.h +++ b/gpu/GLES2/gl2chromium.h @@ -227,6 +227,7 @@ #define glAsyncTexSubImage2DCHROMIUM GLES2_GET_FUN(AsyncTexSubImage2DCHROMIUM) #define glAsyncTexImage2DCHROMIUM GLES2_GET_FUN(AsyncTexImage2DCHROMIUM) #define glDiscardFramebufferEXT GLES2_GET_FUN(DiscardFramebufferEXT) +#define glLoseContextCHROMIUM GLES2_GET_FUN(LoseContextCHROMIUM) #endif // GPU_GLES2_GL2CHROMIUM_H_ diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 8ea1d3c..9babf73 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1114,6 +1114,14 @@ _ENUM_LISTS = { 'true', ], }, + 'ResetStatus': { + 'type': 'GLenum', + 'valid': [ + 'GL_GUILTY_CONTEXT_RESET_ARB', + 'GL_INNOCENT_CONTEXT_RESET_ARB', + 'GL_UNKNOWN_CONTEXT_RESET_ARB', + ], + }, } # This table specifies the different pepper interfaces that are supported for @@ -2296,6 +2304,12 @@ _FUNCTION_INFO = { 'client_test': False, 'extension': True, }, + 'LoseContextCHROMIUM': { + 'type': 'Manual', + 'impl_func': True, + 'extension': True, + 'chromium': True, + }, } @@ -3354,7 +3368,8 @@ class ManualHandler(CustomHandler): def WriteGLES2Implementation(self, func, file): """Overrriden from TypeHandler.""" - pass + if func.GetInfo('impl_func'): + super(ManualHandler, self).WriteGLES2Implementation(func, file) def WriteGLES2ImplementationHeader(self, func, file): """Overrriden from TypeHandler.""" diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index b4d8e0f..dff3135 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -715,6 +715,9 @@ void GLES2DiscardFramebufferEXT( GLenum target, GLsizei count, const GLenum* attachments) { gles2::GetGLContext()->DiscardFramebufferEXT(target, count, attachments); } +void GLES2LoseContextCHROMIUM(GLenum current, GLenum other) { + gles2::GetGLContext()->LoseContextCHROMIUM(current, other); +} namespace gles2 { @@ -1048,6 +1051,8 @@ NameToFunc g_gles2_function_table[] = { glAsyncTexImage2DCHROMIUM), }, { "glDiscardFramebufferEXT", reinterpret_cast<GLES2FunctionPointer>( glDiscardFramebufferEXT), }, + { "glLoseContextCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( + glLoseContextCHROMIUM), }, { NULL, NULL, }, }; diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 66a5c8a5..18cf105 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1980,5 +1980,12 @@ } } + void LoseContextCHROMIUM(GLenum current, GLenum other) { + gles2::LoseContextCHROMIUM* c = GetCmdSpace<gles2::LoseContextCHROMIUM>(); + if (c) { + c->Init(current, other); + } + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index b0ed75f..efaaa28 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -522,5 +522,7 @@ virtual void AsyncTexImage2DCHROMIUM( virtual void DiscardFramebufferEXT( GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE; +virtual void LoseContextCHROMIUM(GLenum current, GLenum other) OVERRIDE; + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 57aa0cd..0fc3a4d 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -1696,5 +1696,12 @@ void GLES2Implementation::DiscardFramebufferEXT( CheckGLError(); } +void GLES2Implementation::LoseContextCHROMIUM(GLenum current, GLenum other) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLoseContextCHROMIUM(" << GLES2Util::GetStringEnum(current) << ", " << GLES2Util::GetStringEnum(other) << ")"); // NOLINT + helper_->LoseContextCHROMIUM(current, other); + CheckGLError(); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_IMPL_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index f23a512..2de2e54 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -1786,5 +1786,16 @@ TEST_F(GLES2ImplementationTest, DiscardFramebufferEXT) { gl_->DiscardFramebufferEXT(1, 2, &expected.data[0][0]); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } + +TEST_F(GLES2ImplementationTest, LoseContextCHROMIUM) { + struct Cmds { + LoseContextCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(1, 2); + + gl_->LoseContextCHROMIUM(1, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_UNITTEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 163361d..f295bdf 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -301,5 +301,6 @@ virtual void AsyncTexImage2DCHROMIUM( const void* pixels) = 0; virtual void DiscardFramebufferEXT( GLenum target, GLsizei count, const GLenum* attachments) = 0; +virtual void LoseContextCHROMIUM(GLenum current, GLenum other) = 0; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index f3d51d8..80e5607 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -333,5 +333,6 @@ virtual void AsyncTexImage2DCHROMIUM( const void* pixels) OVERRIDE; virtual void DiscardFramebufferEXT( GLenum target, GLsizei count, const GLenum* attachments) OVERRIDE; +virtual void LoseContextCHROMIUM(GLenum current, GLenum other) OVERRIDE; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index cf516e3..bc55938 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -627,5 +627,8 @@ void GLES2InterfaceStub::DiscardFramebufferEXT( GLenum /* target */, GLsizei /* count */, const GLenum* /* attachments */) { } +void GLES2InterfaceStub::LoseContextCHROMIUM( + GLenum /* current */, GLenum /* other */) { +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_IMPL_AUTOGEN_H_ diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index fb53030..2664631 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -206,3 +206,6 @@ GL_APICALL void GL_APIENTRY glTraceEndCHROMIUM (void); GL_APICALL void GL_APIENTRY glAsyncTexSubImage2DCHROMIUM (GLenumTextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenumTextureFormat format, GLenumPixelType type, const void* data); GL_APICALL void GL_APIENTRY glAsyncTexImage2DCHROMIUM (GLenumTextureTarget target, GLint level, GLintTextureInternalFormat internalformat, GLsizei width, GLsizei height, GLintTextureBorder border, GLenumTextureFormat format, GLenumPixelType type, const void* pixels); GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei count, const GLenum* attachments); +GL_APICALL void GL_APIENTRY glLoseContextCHROMIUM (GLenum current, GLenum other); + + diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index d7e887d..ca9c90b 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -10830,6 +10830,44 @@ COMPILE_ASSERT(offsetof(DiscardFramebufferEXTImmediate, target) == 4, COMPILE_ASSERT(offsetof(DiscardFramebufferEXTImmediate, count) == 8, OffsetOf_DiscardFramebufferEXTImmediate_count_not_8); +struct LoseContextCHROMIUM { + typedef LoseContextCHROMIUM ValueType; + static const CommandId kCmdId = kLoseContextCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(GLenum _current, GLenum _other) { + SetHeader(); + current = _current; + other = _other; + } + + void* Set(void* cmd, GLenum _current, GLenum _other) { + static_cast<ValueType*>(cmd)->Init(_current, _other); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 current; + uint32 other; +}; + +COMPILE_ASSERT(sizeof(LoseContextCHROMIUM) == 12, + Sizeof_LoseContextCHROMIUM_is_not_12); +COMPILE_ASSERT(offsetof(LoseContextCHROMIUM, header) == 0, + OffsetOf_LoseContextCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(LoseContextCHROMIUM, current) == 4, + OffsetOf_LoseContextCHROMIUM_current_not_4); +COMPILE_ASSERT(offsetof(LoseContextCHROMIUM, other) == 8, + OffsetOf_LoseContextCHROMIUM_other_not_8); + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 54795a7..80a2768 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -4364,5 +4364,20 @@ TEST_F(GLES2FormatTest, DiscardFramebufferEXTImmediate) { // TODO(gman): Check that data was inserted; } +TEST_F(GLES2FormatTest, LoseContextCHROMIUM) { + LoseContextCHROMIUM& cmd = *GetBufferAs<LoseContextCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<GLenum>(12)); + EXPECT_EQ(static_cast<uint32>(LoseContextCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.current); + EXPECT_EQ(static_cast<GLenum>(12), cmd.other); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 0a7a577..13f6170 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -247,6 +247,7 @@ OP(AsyncTexImage2DCHROMIUM) /* 490 */ \ OP(DiscardFramebufferEXT) /* 491 */ \ OP(DiscardFramebufferEXTImmediate) /* 492 */ \ + OP(LoseContextCHROMIUM) /* 493 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index 944c16f..00e1f0ea 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h @@ -42,6 +42,7 @@ static std::string GetStringReadPixelType(uint32 value); static std::string GetStringRenderBufferFormat(uint32 value); static std::string GetStringRenderBufferParameter(uint32 value); static std::string GetStringRenderBufferTarget(uint32 value); +static std::string GetStringResetStatus(uint32 value); static std::string GetStringShaderBinaryFormat(uint32 value); static std::string GetStringShaderParameter(uint32 value); static std::string GetStringShaderPrecision(uint32 value); diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 332d321..447efff 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -1134,6 +1134,16 @@ std::string GLES2Util::GetStringRenderBufferTarget(uint32 value) { string_table, arraysize(string_table), value); } +std::string GLES2Util::GetStringResetStatus(uint32 value) { + static EnumToString string_table[] = { + { GL_GUILTY_CONTEXT_RESET_ARB, "GL_GUILTY_CONTEXT_RESET_ARB" }, + { GL_INNOCENT_CONTEXT_RESET_ARB, "GL_INNOCENT_CONTEXT_RESET_ARB" }, + { GL_UNKNOWN_CONTEXT_RESET_ARB, "GL_UNKNOWN_CONTEXT_RESET_ARB" }, + }; + return GLES2Util::GetQualifiedEnumString( + string_table, arraysize(string_table), value); +} + std::string GLES2Util::GetStringShaderBinaryFormat(uint32 value) { return GLES2Util::GetQualifiedEnumString( NULL, 0, value); diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index d8487c7..abf262d 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -36,7 +36,6 @@ ContextGroup::ContextGroup( : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager), image_manager_(image_manager ? image_manager : new ImageManager), memory_tracker_(memory_tracker), - num_contexts_(0), enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnforceGLMinimums)), bind_generates_resource_(bind_generates_resource), @@ -71,10 +70,13 @@ static void GetIntegerv(GLenum pname, uint32* var) { *var = value; } -bool ContextGroup::Initialize(const DisallowedFeatures& disallowed_features, - const char* allowed_features) { - if (num_contexts_ > 0) { - ++num_contexts_; +bool ContextGroup::Initialize( + GLES2Decoder* decoder, + const DisallowedFeatures& disallowed_features, + const char* allowed_features) { + // If we've already initialized the group just add the context. + if (HaveContexts()) { + decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder)); return true; } @@ -201,14 +203,31 @@ bool ContextGroup::Initialize(const DisallowedFeatures& disallowed_features, return false; } - ++num_contexts_; + decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder)); return true; } -void ContextGroup::Destroy(bool have_context) { - DCHECK(num_contexts_ > 0); - if (--num_contexts_ > 0) +namespace { + +bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) { + return !decoder; +} + +} // namespace anonymous + +bool ContextGroup::HaveContexts() { + decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull), + decoders_.end()); + return !decoders_.empty(); +} + +void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) { + decoders_.erase(std::remove(decoders_.begin(), decoders_.end(), decoder), + decoders_.end()); + // If we still have contexts do nothing. + if (HaveContexts()) { return; + } if (buffer_manager_ != NULL) { buffer_manager_->Destroy(have_context); @@ -263,8 +282,16 @@ uint32 ContextGroup::GetMemRepresented() const { return total; } +void ContextGroup::LoseContexts(GLenum reset_status) { + for (size_t ii = 0; ii < decoders_.size(); ++ii) { + if (decoders_[ii]) { + decoders_[ii]->LoseContext(reset_status); + } + } +} + ContextGroup::~ContextGroup() { - CHECK(num_contexts_ == 0); + CHECK(!HaveContexts()); } bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) { diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index c459c56..064e36f 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -6,11 +6,13 @@ #define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_GROUP_H_ #include <string> +#include <vector> #include "base/basictypes.h" #include "base/hash_tables.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" #include "gpu/command_buffer/service/feature_info.h" @@ -50,12 +52,14 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { // This should only be called by GLES2Decoder. This must be paired with a // call to destroy if it succeeds. - bool Initialize(const DisallowedFeatures& disallowed_features, - const char* allowed_features); + bool Initialize( + GLES2Decoder* decoder, + const DisallowedFeatures& disallowed_features, + const char* allowed_features); // Destroys all the resources when called for the last context in the group. // It should only be called by GLES2Decoder. - void Destroy(bool have_context); + void Destroy(GLES2Decoder* decoder, bool have_context); MailboxManager* mailbox_manager() const { return mailbox_manager_.get(); @@ -145,6 +149,9 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { uint32 GetMemRepresented() const; + // Loses all the context associated with this group. + void LoseContexts(GLenum reset_status); + private: friend class base::RefCounted<ContextGroup>; ~ContextGroup(); @@ -153,14 +160,13 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { bool CheckGLFeatureU(GLint min_required, uint32* v); bool QueryGLFeature(GLenum pname, GLint min_required, GLint* v); bool QueryGLFeatureU(GLenum pname, GLint min_required, uint32* v); + bool HaveContexts(); scoped_refptr<MailboxManager> mailbox_manager_; scoped_refptr<ImageManager> image_manager_; scoped_refptr<MemoryTracker> memory_tracker_; scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; - // Whether or not this context is initialized. - int num_contexts_; bool enforce_gl_minimums_; bool bind_generates_resource_; @@ -191,6 +197,8 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { FeatureInfo::Ref feature_info_; + std::vector<base::WeakPtr<gles2::GLES2Decoder> > decoders_; + DISALLOW_COPY_AND_ASSIGN(ContextGroup); }; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index 8ae1db3..983130f 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/context_group.h" #include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,6 +37,7 @@ class ContextGroupTest : public testing::Test { virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); + decoder_.reset(new MockGLES2Decoder()); group_ = ContextGroup::Ref(new ContextGroup(NULL, NULL, NULL, true)); } @@ -45,6 +47,7 @@ class ContextGroupTest : public testing::Test { } scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + scoped_ptr<MockGLES2Decoder> decoder_; ContextGroup::Ref group_; }; @@ -68,7 +71,7 @@ TEST_F(ContextGroupTest, Basic) { TEST_F(ContextGroupTest, InitializeNoExtensions) { TestHelper::SetupContextGroupInitExpectations(gl_.get(), DisallowedFeatures(), ""); - group_->Initialize(DisallowedFeatures(), ""); + group_->Initialize(decoder_.get(), DisallowedFeatures(), ""); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs), group_->max_vertex_attribs()); EXPECT_EQ(static_cast<uint32>(TestHelper::kNumTextureUnits), @@ -90,7 +93,7 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) { EXPECT_TRUE(group_->program_manager() != NULL); EXPECT_TRUE(group_->shader_manager() != NULL); - group_->Destroy(false); + group_->Destroy(decoder_.get(), false); EXPECT_TRUE(group_->buffer_manager() == NULL); EXPECT_TRUE(group_->framebuffer_manager() == NULL); EXPECT_TRUE(group_->renderbuffer_manager() == NULL); @@ -100,10 +103,11 @@ TEST_F(ContextGroupTest, InitializeNoExtensions) { } TEST_F(ContextGroupTest, MultipleContexts) { + scoped_ptr<MockGLES2Decoder> decoder2_(new MockGLES2Decoder()); TestHelper::SetupContextGroupInitExpectations(gl_.get(), DisallowedFeatures(), ""); - group_->Initialize(DisallowedFeatures(), ""); - group_->Initialize(DisallowedFeatures(), ""); + group_->Initialize(decoder_.get(), DisallowedFeatures(), ""); + group_->Initialize(decoder2_.get(), DisallowedFeatures(), ""); EXPECT_TRUE(group_->buffer_manager() != NULL); EXPECT_TRUE(group_->framebuffer_manager() != NULL); @@ -112,7 +116,7 @@ TEST_F(ContextGroupTest, MultipleContexts) { EXPECT_TRUE(group_->program_manager() != NULL); EXPECT_TRUE(group_->shader_manager() != NULL); - group_->Destroy(false); + group_->Destroy(decoder_.get(), false); EXPECT_TRUE(group_->buffer_manager() != NULL); EXPECT_TRUE(group_->framebuffer_manager() != NULL); @@ -121,7 +125,7 @@ TEST_F(ContextGroupTest, MultipleContexts) { EXPECT_TRUE(group_->program_manager() != NULL); EXPECT_TRUE(group_->shader_manager() != NULL); - group_->Destroy(false); + group_->Destroy(decoder2_.get(), false); EXPECT_TRUE(group_->buffer_manager() == NULL); EXPECT_TRUE(group_->framebuffer_manager() == NULL); diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 2a738b8..a7ca864 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -244,6 +244,7 @@ void FeatureInfo::AddFeatures(const char* desired_features) { AddExtensionString("GL_CHROMIUM_copy_texture"); AddExtensionString("GL_CHROMIUM_discard_backbuffer"); AddExtensionString("GL_CHROMIUM_get_error_query"); + AddExtensionString("GL_CHROMIUM_lose_context"); AddExtensionString("GL_CHROMIUM_pixel_transfer_buffer_object"); AddExtensionString("GL_CHROMIUM_rate_limit_offscreen_context"); AddExtensionString("GL_CHROMIUM_resize"); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index a6a3055..2d80b70 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1469,8 +1469,8 @@ class GLES2DecoderImpl : public GLES2Decoder { // the tracing system. size_t GetBackbufferMemoryTotal(); - // Returns true if the context was just lost due to e.g. GL_ARB_robustness. virtual bool WasContextLost() OVERRIDE; + virtual void LoseContext(uint32 reset_status) OVERRIDE; #if defined(OS_MACOSX) void ReleaseIOSurfaceForTexture(GLuint texture_id); @@ -2162,7 +2162,7 @@ bool GLES2DecoderImpl::Initialize( context_ = context; surface_ = surface; - if (!group_->Initialize(disallowed_features, allowed_extensions)) { + if (!group_->Initialize(this, disallowed_features, allowed_extensions)) { LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group " << "failed to initialize."; group_ = NULL; // Must not destroy ContextGroup if it is not initialized. @@ -3059,7 +3059,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) { } if (group_) { - group_->Destroy(have_context); + group_->Destroy(this, have_context); group_ = NULL; } @@ -8869,6 +8869,9 @@ error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() { } bool GLES2DecoderImpl::WasContextLost() { + if (reset_status_ != GL_NO_ERROR) { + return true; + } if (context_->WasAllocatedUsingRobustnessExtension()) { GLenum status = GL_NO_ERROR; if (has_robustness_extension_) @@ -8877,14 +8880,53 @@ bool GLES2DecoderImpl::WasContextLost() { // The graphics card was reset. Signal a lost context to the application. reset_status_ = status; LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen") - << " context lost via ARB/EXT_robustness. Reset status = 0x" - << std::hex << status << std::dec; + << " context lost via ARB/EXT_robustness. Reset status = " + << GLES2Util::GetStringEnum(status); return true; } } return false; } +void GLES2DecoderImpl::LoseContext(uint32 reset_status) { + // Only loses the context once. + if (reset_status_ != GL_NO_ERROR) { + return; + } + + // Marks this context as lost. + reset_status_ = reset_status; + current_decoder_error_ = error::kLostContext; + + // Loses the parent's context. + if (parent_) { + parent_->LoseContext(reset_status); + } + + // Loses any child contexts. + for (ChildList::iterator it = children_.begin(); + it != children_.end(); + ++it) { + (*it)->LoseContext(reset_status); + } +} + +error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM( + uint32 immediate_data_size, const gles2::LoseContextCHROMIUM& c) { + GLenum current = static_cast<GLenum>(c.current); + GLenum other = static_cast<GLenum>(c.other); + if (!validators_->reset_status.IsValid(current)) { + SetGLErrorInvalidEnum("glLoseContextCHROMIUM", current, "current"); + } + if (!validators_->reset_status.IsValid(other)) { + SetGLErrorInvalidEnum("glLoseContextCHROMIUM", other, "other"); + } + group_->LoseContexts(other); + reset_status_ = current; + current_decoder_error_ = error::kLostContext; + return error::kLostContext; +} + bool GLES2DecoderImpl::GenQueriesEXTHelper( GLsizei n, const GLuint* client_ids) { for (GLsizei ii = 0; ii < n; ++ii) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 4311198..1b36dcb0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -195,8 +195,12 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>, virtual base::TimeDelta GetTotalProcessingCommandsTime() = 0; virtual void AddProcessingCommandsTime(base::TimeDelta) = 0; + // Returns true if the context was just lost due to e.g. GL_ARB_robustness. virtual bool WasContextLost() = 0; + // Lose this context. + virtual void LoseContext(uint32 reset_status) = 0; + static bool IsAngle(); // Used for testing only diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index e92ca94..363dfcb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -85,6 +85,7 @@ class MockGLES2Decoder : public GLES2Decoder { MOCK_METHOD0(GetTotalProcessingCommandsTime, base::TimeDelta()); MOCK_METHOD1(AddProcessingCommandsTime, void(base::TimeDelta)); MOCK_METHOD0(WasContextLost, bool()); + MOCK_METHOD1(LoseContext, void(uint32 reset_status)); DISALLOW_COPY_AND_ASSIGN(MockGLES2Decoder); }; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index 983269b..f644348 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -66,5 +66,7 @@ // TODO(gman): DiscardFramebufferEXT // TODO(gman): DiscardFramebufferEXTImmediate +// TODO(gman): LoseContextCHROMIUM + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 4629284..b2c63fb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -13,6 +13,7 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/program_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/command_buffer/service/test_helper.h" @@ -97,7 +98,12 @@ void GLES2DecoderTestBase::InitDecoder( TestHelper::SetupContextGroupInitExpectations(gl_.get(), DisallowedFeatures(), extensions); - EXPECT_TRUE(group_->Initialize(DisallowedFeatures(), NULL)); + // We initialize the ContextGroup with a MockGLES2Decoder so that + // we can use the ContextGroup to figure out how the real GLES2Decoder + // will initialize itself. + mock_decoder_.reset(new MockGLES2Decoder()); + EXPECT_TRUE( + group_->Initialize(mock_decoder_.get(), DisallowedFeatures(), NULL)); AddExpectationsForVertexAttribManager(); @@ -295,7 +301,7 @@ void GLES2DecoderTestBase::TearDown() { decoder_->Destroy(true); decoder_.reset(); - group_->Destroy(false); + group_->Destroy(mock_decoder_.get(), false); engine_.reset(); ::gfx::GLInterface::SetGLInterface(NULL); gl_.reset(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 420351e..7a1f975 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -466,6 +466,7 @@ class GLES2DecoderTestBase : public testing::Test { scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<gfx::GLSurfaceStub> surface_; scoped_refptr<gfx::GLContextStub> context_; + scoped_ptr<GLES2Decoder> mock_decoder_; scoped_ptr<GLES2Decoder> decoder_; GLuint client_buffer_id_; diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index c19ba38..7e41788 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -44,6 +44,7 @@ ValueValidator<GLenum> read_pixel_type; ValueValidator<GLenum> render_buffer_format; ValueValidator<GLenum> render_buffer_parameter; ValueValidator<GLenum> render_buffer_target; +ValueValidator<GLenum> reset_status; ValueValidator<GLenum> shader_binary_format; ValueValidator<GLenum> shader_parameter; ValueValidator<GLenum> shader_precision; diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index d951e79..1f8535b 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -336,6 +336,12 @@ static GLenum valid_render_buffer_target_table[] = { GL_RENDERBUFFER, }; +static GLenum valid_reset_status_table[] = { + GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB, + GL_UNKNOWN_CONTEXT_RESET_ARB, +}; + static GLenum valid_shader_parameter_table[] = { GL_SHADER_TYPE, GL_DELETE_STATUS, @@ -597,6 +603,8 @@ Validators::Validators() render_buffer_target( valid_render_buffer_target_table, arraysize( valid_render_buffer_target_table)), + reset_status( + valid_reset_status_table, arraysize(valid_reset_status_table)), shader_binary_format(), shader_parameter( valid_shader_parameter_table, arraysize( diff --git a/gpu/command_buffer/tests/gl_lose_context_chromium_unittests.cc b/gpu/command_buffer/tests/gl_lose_context_chromium_unittests.cc new file mode 100644 index 0000000..385cc88 --- /dev/null +++ b/gpu/command_buffer/tests/gl_lose_context_chromium_unittests.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2012 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 <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include "base/logging.h" +#include "gpu/command_buffer/tests/gl_manager.h" +#include "gpu/command_buffer/tests/gl_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace gpu { + +class GLLoseContextTest : public testing::Test { + protected: + virtual void SetUp() { + GLManager::Options options; + gl2_.Initialize(options); + options.context_lost_allowed = true; + gl1a_.Initialize(options); + options.share_group_manager = &gl1a_; + gl1b_.Initialize(options); + } + + virtual void TearDown() { + gl1a_.Destroy(); + gl1b_.Destroy(); + gl2_.Destroy(); + } + + GLManager gl1a_; + GLManager gl1b_; + GLManager gl2_; +}; + +// Test that glLoseContextCHROMIUM loses context in the same +// share group but not other. +TEST_F(GLLoseContextTest, ShareGroup) { + gl1a_.MakeCurrent(); + glLoseContextCHROMIUM( + GL_GUILTY_CONTEXT_RESET_EXT, GL_INNOCENT_CONTEXT_RESET_EXT); + + uint8 expected_no_draw[] = { + GLTestHelper::kCheckClearValue, + GLTestHelper::kCheckClearValue, + GLTestHelper::kCheckClearValue, + GLTestHelper::kCheckClearValue, + }; + // Expect the read will fail. + EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_no_draw)); + gl1b_.MakeCurrent(); + // Expect the read will fail. + EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_no_draw)); + gl2_.MakeCurrent(); + uint8 expected_draw[] = { 0, 0, 0, 0, }; + // Expect the read will succeed. + EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_draw)); +} + +} // namespace gpu + diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 6ec3097..57abc34 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -29,10 +29,12 @@ GLManager::Options::Options() share_group_manager(NULL), share_mailbox_manager(NULL), virtual_manager(NULL), - bind_generates_resource(false) { + bind_generates_resource(false), + context_lost_allowed(false) { } -GLManager::GLManager() { +GLManager::GLManager() + : context_lost_allowed_(false) { } GLManager::~GLManager() { @@ -45,6 +47,8 @@ void GLManager::Initialize(const GLManager::Options& options) { const size_t kMaxTransferBufferSize = 16 * 1024 * 1024; const bool kShareResources = true; + context_lost_allowed_ = options.context_lost_allowed; + gles2::MailboxManager* mailbox_manager = NULL; if (options.share_mailbox_manager) { mailbox_manager = options.share_mailbox_manager->mailbox_manager(); @@ -198,7 +202,9 @@ void GLManager::PumpCommands() { decoder_->MakeCurrent(); gpu_scheduler_->PutChanged(); ::gpu::CommandBuffer::State state = command_buffer_->GetState(); - ASSERT_EQ(::gpu::error::kNoError, state.error); + if (!context_lost_allowed_) { + ASSERT_EQ(::gpu::error::kNoError, state.error); + } } bool GLManager::GetBufferChanged(int32 transfer_buffer_id) { diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index 5f42a36..2b24331 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h @@ -48,6 +48,8 @@ class GLManager { GLManager* virtual_manager; // Whether or not glBindXXX generates a resource. bool bind_generates_resource; + // Whether or not it's ok to lose the context. + bool context_lost_allowed; }; GLManager(); ~GLManager(); @@ -87,6 +89,7 @@ class GLManager { scoped_ptr<gles2::GLES2CmdHelper> gles2_helper_; scoped_ptr<TransferBuffer> transfer_buffer_; scoped_ptr<gles2::GLES2Implementation> gles2_implementation_; + bool context_lost_allowed_; }; } // namespace gpu diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc index f4ea96b..1a3e7c2 100644 --- a/gpu/command_buffer/tests/gl_test_utils.cc +++ b/gpu/command_buffer/tests/gl_test_utils.cc @@ -10,6 +10,11 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +// GCC requires these declarations, but MSVC requires they not be present. +#ifndef COMPILER_MSVC +const uint8 GLTestHelper::kCheckClearValue; +#endif + bool GLTestHelper::HasExtension(const char* extension) { std::string extensions( reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); @@ -108,7 +113,7 @@ bool GLTestHelper::CheckPixels( const uint8* color) { GLsizei size = width * height * 4; scoped_array<uint8> pixels(new uint8[size]); - memset(pixels.get(), 123, size); + memset(pixels.get(), kCheckClearValue, size); glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); bool same = true; for (GLint yy = 0; yy < height; ++yy) { diff --git a/gpu/command_buffer/tests/gl_test_utils.h b/gpu/command_buffer/tests/gl_test_utils.h index bd2d380..31de7cd 100644 --- a/gpu/command_buffer/tests/gl_test_utils.h +++ b/gpu/command_buffer/tests/gl_test_utils.h @@ -12,6 +12,8 @@ class GLTestHelper { public: + static const uint8 kCheckClearValue = 123u; + static bool HasExtension(const char* extension); static bool CheckGLError(const char* msg, int line); diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index e7bd419..e3ccb37 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -238,6 +238,7 @@ 'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc', 'command_buffer/tests/gl_depth_texture_unittest.cc', 'command_buffer/tests/gl_query_unittests.cc', + 'command_buffer/tests/gl_lose_context_chromium_unittests.cc', 'command_buffer/tests/gl_manager.cc', 'command_buffer/tests/gl_manager.h', 'command_buffer/tests/gl_pointcoord_unittest.cc', diff --git a/third_party/khronos/GLES2/gl2ext.h b/third_party/khronos/GLES2/gl2ext.h index 35a28cb9..6cbca97 100644 --- a/third_party/khronos/GLES2/gl2ext.h +++ b/third_party/khronos/GLES2/gl2ext.h @@ -2173,6 +2173,15 @@ typedef void (GL_APIENTRYP PFNGLRELEASETEXIMAGE2DCHROMIUM) (GLenum target, GLint #define GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM 0x84F5 #endif +/* GL_CHROMIUM_lose_context */ +#ifndef GL_CHROMIUM_lose_context +#define GL_CHROMIUM_lose_context 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glLoseContextCHROMIUM (GLenum current, GLenum other); +#endif +typedef void (GL_APIENTRYP PFNGLLOSECONTEXTCHROMIUM) (GLenum current, GLenum other); +#endif + #ifdef __cplusplus } #endif diff --git a/third_party/khronos/README.chromium b/third_party/khronos/README.chromium index 7760f41..36caefa 100644 --- a/third_party/khronos/README.chromium +++ b/third_party/khronos/README.chromium @@ -21,20 +21,21 @@ GLES2/gl2.h - Added include of gl2chromium.h GLES2/gl2ext.h - Added Chromium and Angle extensions. - - Added ANGLE_instanced_arrays + - Added GL_ANGLE_instanced_arrays - Added GL_ARB_robustness (subsetted) - Added GL_ARB_texture_rectangle (subsetted) - - Added GL_EXT_framebuffer_multisample - - Added GL_CHROMIUM_command_buffer_query + - Added GL_CHROMIUM_async_pixel_transfers + - Added GL_CHROMIUM_bind_uniform_location - Added GL_CHROMIUM_command_buffer_latency_query + - Added GL_CHROMIUM_command_buffer_query - Added GL_CHROMIUM_copy_texture - - Added GL_CHROMIUM_bind_uniform_location - Added GL_CHROMIUM_get_error_query + - Added GL_CHROMIUM_gpu_memory_manager - Added GL_CHROMIUM_iosurface - - Added GL_CHROMIUM_texture_from_image + - Added GL_CHROMIUM_lose_context - Added GL_CHROMIUM_pixel_transfer_buffer_object - - Added GL_CHROMIUM_async_pixel_transfers - - Added GL_CHROMIUM_gpu_memory_manager + - Added GL_CHROMIUM_texture_from_image + - Added GL_EXT_framebuffer_multisample - Added GL_NVX_gpu_memory_info - Added include of gl2chromium.h EGL/eglplatform.h |