Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc

Issue 1095893002: gpu: Fix some context lost marking glitches+leaks and add UMA stats (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix GLManager and fix another resource leak (comment #15) Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6988a0a4ba0a5d24004854925ad45cbaba2f7879
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
@@ -0,0 +1,267 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#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/gl_surface_mock.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_mock.h"
+
+using ::gfx::MockGLInterface;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::MatcherCast;
+using ::testing::Mock;
+using ::testing::Pointee;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::SetArrayArgument;
+using ::testing::SetArgumentPointee;
+using ::testing::SetArgPointee;
+using ::testing::StrEq;
+using ::testing::StrictMock;
+
+namespace gpu {
+namespace gles2 {
+
+using namespace cmds;
+
+class GLES2DecoderDrawOOMTest : public GLES2DecoderManualInitTest {
+ protected:
+ void Init(bool has_robustness) {
+ InitState init;
+ init.lose_context_when_out_of_memory = true;
+ if (has_robustness)
+ init.extensions = "GL_ARB_robustness";
+ InitDecoder(init);
+ SetupDefaultProgram();
+ }
+
+ void Draw(GLenum reset_status,
+ error::ContextLostReason expected_other_reason) {
+ const GLsizei kFakeLargeCount = 0x1234;
+ SetupTexture();
+ if (context_->WasAllocatedUsingRobustnessExtension()) {
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB())
+ .WillOnce(Return(reset_status));
+ }
+ AddExpectationsForSimulatedAttrib0WithError(kFakeLargeCount, 0,
+ GL_OUT_OF_MEMORY);
+ EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation();
+ // Other contexts in the group should be lost also.
+ EXPECT_CALL(*mock_decoder_, MarkContextLost(expected_other_reason))
+ .Times(1)
+ .RetiresOnSaturation();
+ DrawArrays cmd;
+ cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount);
+ EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd));
+ }
+};
+
+// Test that we lose context.
+TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonOOM) {
+ Init(false); // without robustness
+ const error::ContextLostReason expected_reason_for_other_contexts =
+ error::kOutOfMemory;
+ Draw(GL_NO_ERROR, expected_reason_for_other_contexts);
+ EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_EQ(error::kOutOfMemory, decoder_->GetContextLostReason());
+}
+
+TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonWhenStatusIsNoError) {
+ Init(true); // with robustness
+ // If the reset status is NO_ERROR, we should be signaling kOutOfMemory.
+ const error::ContextLostReason expected_reason_for_other_contexts =
+ error::kOutOfMemory;
+ Draw(GL_NO_ERROR, expected_reason_for_other_contexts);
+ EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_EQ(error::kOutOfMemory, decoder_->GetContextLostReason());
+}
+
+TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonWhenStatusIsGuilty) {
+ Init(true);
+ // If there was a reset, it should override kOutOfMemory.
+ const error::ContextLostReason expected_reason_for_other_contexts =
+ error::kUnknown;
+ Draw(GL_GUILTY_CONTEXT_RESET_ARB, expected_reason_for_other_contexts);
+ EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_EQ(error::kGuilty, decoder_->GetContextLostReason());
+}
+
+TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonWhenStatusIsUnknown) {
+ Init(true);
+ // If there was a reset, it should override kOutOfMemory.
+ const error::ContextLostReason expected_reason_for_other_contexts =
+ error::kUnknown;
+ Draw(GL_UNKNOWN_CONTEXT_RESET_ARB, expected_reason_for_other_contexts);
+ EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_EQ(error::kUnknown, decoder_->GetContextLostReason());
+}
+
+INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderDrawOOMTest, ::testing::Bool());
+
+class GLES2DecoderLostContextTest : public GLES2DecoderManualInitTest {
+ protected:
+ void Init(bool has_robustness) {
+ InitState init;
+ init.gl_version = "opengl es 2.0";
+ if (has_robustness)
+ init.extensions = "GL_KHR_robustness";
+ InitDecoder(init);
+ }
+
+ void InitWithVirtualContextsAndRobustness() {
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitchASCII(
+ switches::kGpuDriverBugWorkarounds,
+ base::IntToString(USE_VIRTUALIZED_GL_CONTEXTS));
+ InitState init;
+ init.gl_version = "opengl es 2.0";
+ init.extensions = "GL_KHR_robustness";
+ InitDecoderWithCommandLine(init, &command_line);
+ }
+
+ void DoGetErrorWithContextLost(GLenum reset_status) {
+ DCHECK(context_->HasExtension("GL_KHR_robustness"));
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_CONTEXT_LOST_KHR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB())
+ .WillOnce(Return(reset_status));
+ cmds::GetError cmd;
+ cmd.Init(shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd));
+ EXPECT_EQ(static_cast<GLuint>(GL_NO_ERROR), *GetSharedMemoryAs<GLenum*>());
+ }
+
+ void ClearCurrentDecoderError() {
+ DCHECK(decoder_->WasContextLost());
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_CONTEXT_LOST_KHR))
+ .RetiresOnSaturation();
+ cmds::GetError cmd;
+ cmd.Init(shared_memory_id_, shared_memory_offset_);
+ EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd));
+ }
+};
+
+TEST_P(GLES2DecoderLostContextTest, LostFromMakeCurrent) {
+ Init(false); // without robustness
+ EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false));
+ decoder_->MakeCurrent();
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_EQ(error::kMakeCurrentFailed, decoder_->GetContextLostReason());
+
+ // We didn't process commands, so we need to clear the decoder error,
+ // so that we can shut down cleanly.
+ ClearCurrentDecoderError();
Ken Russell (switch to Gerrit) 2015/04/27 22:35:33 Will this happen in the normal operation of the co
no sievers 2015/04/27 23:24:41 FWIU there are multiple ways we detect a decoder e
+}
+
+TEST_P(GLES2DecoderLostContextTest, LostFromMakeCurrentWithRobustness) {
+ Init(true); // with robustness
+ // If we can't make the context current, we cannot query the robustness
+ // extension.
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()).Times(0);
+ EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false));
+ decoder_->MakeCurrent();
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_FALSE(decoder_->WasContextLostByRobustnessExtension());
+ EXPECT_EQ(error::kMakeCurrentFailed, decoder_->GetContextLostReason());
+
+ // We didn't process commands, so we need to clear the decoder error,
+ // so that we can shut down cleanly.
+ ClearCurrentDecoderError();
+}
+
+TEST_P(GLES2DecoderLostContextTest, LostFromResetAfterMakeCurrent) {
+ Init(true); // with robustness
+ InSequence seq;
+ EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(true));
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB())
+ .WillOnce(Return(GL_GUILTY_CONTEXT_RESET_KHR));
+ decoder_->MakeCurrent();
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension());
+ EXPECT_EQ(error::kGuilty, decoder_->GetContextLostReason());
+
+ // We didn't process commands, so we need to clear the decoder error,
+ // so that we can shut down cleanly.
+ ClearCurrentDecoderError();
+}
+
+TEST_P(GLES2DecoderLostContextTest, LoseGuiltyFromGLError) {
+ Init(true);
+ // Always expect other contexts to be signaled as 'kUnknown' since we can't
+ // query their status without making them current.
+ EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown))
+ .Times(1);
+ DoGetErrorWithContextLost(GL_GUILTY_CONTEXT_RESET_KHR);
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension());
+ EXPECT_EQ(error::kGuilty, decoder_->GetContextLostReason());
+}
+
+TEST_P(GLES2DecoderLostContextTest, LoseInnocentFromGLError) {
+ Init(true);
+ // Always expect other contexts to be signaled as 'kUnknown' since we can't
+ // query their status without making them current.
+ EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown))
+ .Times(1);
+ DoGetErrorWithContextLost(GL_INNOCENT_CONTEXT_RESET_KHR);
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension());
+ EXPECT_EQ(error::kInnocent, decoder_->GetContextLostReason());
+}
+
+TEST_P(GLES2DecoderLostContextTest, LoseVirtualContextWithRobustness) {
+ InitWithVirtualContextsAndRobustness();
+ EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown))
+ .Times(1);
+ // Signal guilty....
+ DoGetErrorWithContextLost(GL_GUILTY_CONTEXT_RESET_KHR);
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension());
+ // ...but make sure we don't pretend, since for virtual contexts we don't
+ // know if this was really the guilty client.
+ EXPECT_EQ(error::kUnknown, decoder_->GetContextLostReason());
+}
+
+TEST_P(GLES2DecoderLostContextTest, LoseGroupFromRobustness) {
+ // If one context in a group is lost through robustness,
+ // the other ones should also get lost and query the reset status.
+ Init(true);
+ EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown))
+ .Times(1);
+ // There should be no GL calls, since we might not have a current context.
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()).Times(0);
+ LoseContexts(error::kUnknown);
+ EXPECT_TRUE(decoder_->WasContextLost());
+ EXPECT_EQ(error::kUnknown, decoder_->GetContextLostReason());
+
+ // We didn't process commands, so we need to clear the decoder error,
+ // so that we can shut down cleanly.
+ ClearCurrentDecoderError();
+}
+
+INSTANTIATE_TEST_CASE_P(Service,
+ GLES2DecoderLostContextTest,
+ ::testing::Bool());
+
+} // namespace gles2
+} // namespace gpu

Powered by Google App Engine
This is Rietveld 408576698