| // Copyright 2018 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/raster_decoder_unittest_base.h" |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <algorithm> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/callback_helpers.h" |
| #include "base/command_line.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "components/viz/common/resources/resource_format_utils.h" |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| #include "gpu/command_buffer/common/raster_cmd_format.h" |
| #include "gpu/command_buffer/common/shared_image_usage.h" |
| #include "gpu/command_buffer/service/context_group.h" |
| #include "gpu/command_buffer/service/context_state_test_helpers.h" |
| #include "gpu/command_buffer/service/copy_texture_chromium_mock.h" |
| #include "gpu/command_buffer/service/gpu_switches.h" |
| #include "gpu/command_buffer/service/logger.h" |
| #include "gpu/command_buffer/service/mailbox_manager.h" |
| #include "gpu/command_buffer/service/program_manager.h" |
| #include "gpu/command_buffer/service/service_utils.h" |
| #include "gpu/command_buffer/service/shared_context_state.h" |
| #include "gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.h" |
| #include "gpu/command_buffer/service/test_helper.h" |
| #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gl/gl_mock.h" |
| #include "ui/gl/init/gl_factory.h" |
| #include "ui/gl/test/gl_surface_test_support.h" |
| |
| using ::gl::MockGLInterface; |
| using ::testing::_; |
| using ::testing::AnyNumber; |
| using ::testing::AtMost; |
| using ::testing::Between; |
| using ::testing::InSequence; |
| using ::testing::Ne; |
| using ::testing::Pointee; |
| using ::testing::Return; |
| using ::testing::SetArgPointee; |
| using ::testing::StrictMock; |
| |
| namespace gpu { |
| namespace raster { |
| |
| RasterDecoderTestBase::InitState::InitState() = default; |
| RasterDecoderTestBase::InitState::~InitState() = default; |
| |
| RasterDecoderTestBase::RasterDecoderTestBase() |
| : surface_(nullptr), |
| context_(nullptr), |
| shared_memory_id_(0), |
| shared_memory_offset_(0), |
| shared_memory_address_(nullptr), |
| shared_memory_base_(nullptr), |
| ignore_cached_state_for_test_(GetParam()), |
| memory_tracker_(nullptr), |
| copy_texture_manager_(nullptr) { |
| memset(immediate_buffer_, 0xEE, sizeof(immediate_buffer_)); |
| } |
| |
| RasterDecoderTestBase::~RasterDecoderTestBase() = default; |
| |
| void RasterDecoderTestBase::OnConsoleMessage(int32_t id, |
| const std::string& message) {} |
| void RasterDecoderTestBase::CacheShader(const std::string& key, |
| const std::string& shader) {} |
| void RasterDecoderTestBase::OnFenceSyncRelease(uint64_t release) {} |
| void RasterDecoderTestBase::OnDescheduleUntilFinished() {} |
| void RasterDecoderTestBase::OnRescheduleAfterFinished() {} |
| void RasterDecoderTestBase::OnSwapBuffers(uint64_t swap_id, uint32_t flags) {} |
| |
| void RasterDecoderTestBase::SetUp() { |
| InitDecoder(InitState()); |
| } |
| |
| void RasterDecoderTestBase::AddExpectationsForGetCapabilities() { |
| EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_TEXTURE_SIZE, _)) |
| .WillOnce(SetArgPointee<1>(8192u)) |
| .RetiresOnSaturation(); |
| } |
| |
| void RasterDecoderTestBase::InitDecoder(const InitState& init) { |
| std::string all_extensions; |
| for (const std::string& extension : init.extensions) { |
| all_extensions += extension + " "; |
| } |
| const ContextType context_type = init.context_type; |
| |
| // For easier substring/extension matching |
| gl::SetGLGetProcAddressProc(gl::MockGLInterface::GetGLProcAddress); |
| display_ = gl::GLSurfaceTestSupport::InitializeOneOffWithMockBindings(); |
| |
| gl_ = std::make_unique<StrictMock<MockGLInterface>>(); |
| ::gl::MockGLInterface::SetGLInterface(gl_.get()); |
| |
| InSequence sequence; |
| |
| surface_ = new gl::GLSurfaceStub; |
| |
| // Context needs to be created before initializing ContextGroup, which willxo |
| // in turn initialize FeatureInfo, which needs a context to determine |
| // extension support. |
| context_ = new StrictMock<GLContextMock>(); |
| context_->SetExtensionsString(all_extensions.c_str()); |
| context_->SetGLVersionString(init.gl_version.c_str()); |
| |
| context_->GLContextStub::MakeCurrentImpl(surface_.get()); |
| |
| GpuFeatureInfo gpu_feature_info; |
| feature_info_ = base::MakeRefCounted<gles2::FeatureInfo>(init.workarounds, |
| gpu_feature_info); |
| gles2::TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( |
| gl_.get(), all_extensions.c_str(), "", init.gl_version.c_str(), |
| context_type); |
| feature_info_->Initialize(context_type, |
| gpu_preferences_.use_passthrough_cmd_decoder && |
| gles2::PassthroughCommandDecoderSupported(), |
| gles2::DisallowedFeatures()); |
| |
| // Setup expectations for SharedContextState::InitializeGL(). |
| EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) |
| .WillOnce(SetArgPointee<1>(8u)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _)) |
| .WillOnce(SetArgPointee<1>(8u)) |
| .RetiresOnSaturation(); |
| ContextStateTestHelpers::SetupInitState(gl_.get(), feature_info(), |
| gfx::Size(1, 1)); |
| |
| if (context_->HasRobustness()) { |
| EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()) |
| .WillOnce(Return(GL_NO_ERROR)); |
| } |
| |
| shared_context_state_ = base::MakeRefCounted<SharedContextState>( |
| new gl::GLShareGroup(), surface_, context_, |
| feature_info()->workarounds().use_virtualized_gl_contexts, |
| base::DoNothing(), GpuPreferences().gr_context_type); |
| shared_context_state_->disable_check_reset_status_throttling_for_test_ = true; |
| shared_context_state_->InitializeGL(GpuPreferences(), feature_info_); |
| |
| command_buffer_service_ = std::make_unique<FakeCommandBufferServiceBase>(); |
| |
| decoder_.reset(RasterDecoder::Create( |
| this, command_buffer_service_.get(), &outputter_, gpu_feature_info, |
| gpu_preferences_, nullptr /* memory_tracker */, &shared_image_manager_, |
| /*image_factory=*/nullptr, shared_context_state_, |
| true /* is_privileged */)); |
| decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_); |
| decoder_->DisableFlushWorkaroundForTest(); |
| decoder_->GetLogger()->set_log_synthesized_gl_errors(false); |
| |
| copy_texture_manager_ = new gles2::MockCopyTextureResourceManager(); |
| decoder_->SetCopyTextureResourceManagerForTest(copy_texture_manager_); |
| |
| ContextCreationAttribs attribs; |
| attribs.lose_context_when_out_of_memory = |
| init.lose_context_when_out_of_memory; |
| attribs.context_type = context_type; |
| |
| ASSERT_EQ(decoder_->Initialize(surface_, shared_context_state_->context(), |
| true, gles2::DisallowedFeatures(), attribs), |
| gpu::ContextResult::kSuccess); |
| |
| EXPECT_CALL(*context_, MakeCurrentImpl(surface_.get())) |
| .WillOnce(Return(true)); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| if (context_->HasRobustness()) { |
| EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()) |
| .WillOnce(Return(GL_NO_ERROR)); |
| } |
| |
| decoder_->MakeCurrent(); |
| decoder_->BeginDecoding(); |
| |
| scoped_refptr<gpu::Buffer> buffer = |
| command_buffer_service_->CreateTransferBufferHelper(kSharedBufferSize, |
| &shared_memory_id_); |
| shared_memory_offset_ = kSharedMemoryOffset; |
| shared_memory_address_ = |
| static_cast<int8_t*>(buffer->memory()) + shared_memory_offset_; |
| shared_memory_base_ = buffer->memory(); |
| ClearSharedMemory(); |
| } |
| |
| void RasterDecoderTestBase::ResetDecoder() { |
| if (!decoder_.get()) |
| return; |
| // All Tests should have read all their GLErrors before getting here. |
| EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| |
| decoder_->EndDecoding(); |
| |
| if (!decoder_->WasContextLost()) { |
| EXPECT_CALL(*copy_texture_manager_, Destroy()) |
| .Times(1) |
| .RetiresOnSaturation(); |
| copy_texture_manager_ = nullptr; |
| } |
| |
| decoder_->Destroy(!decoder_->WasContextLost()); |
| decoder_.reset(); |
| command_buffer_service_.reset(); |
| context_->GLContextStub::MakeCurrentImpl(surface_.get()); |
| shared_context_state_.reset(); |
| ::gl::MockGLInterface::SetGLInterface(nullptr); |
| gl_.reset(); |
| gl::GLSurfaceTestSupport::ShutdownGL(display_); |
| } |
| |
| void RasterDecoderTestBase::TearDown() { |
| ResetDecoder(); |
| } |
| |
| GLint RasterDecoderTestBase::GetGLError() { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| cmds::GetError cmd; |
| cmd.Init(shared_memory_id_, shared_memory_offset_); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| return static_cast<GLint>(*GetSharedMemoryAs<GLenum*>()); |
| } |
| |
| // GCC requires these declarations, but MSVC requires they not be present |
| #ifndef COMPILER_MSVC |
| const size_t RasterDecoderTestBase::kSharedBufferSize; |
| const uint32_t RasterDecoderTestBase::kSharedMemoryOffset; |
| const int32_t RasterDecoderTestBase::kInvalidSharedMemoryId; |
| const uint32_t RasterDecoderTestBase::kInvalidSharedMemoryOffset; |
| const uint8_t RasterDecoderTestBase::kInitialMemoryValue; |
| |
| const uint32_t RasterDecoderTestBase::kNewClientId; |
| #endif |
| |
| } // namespace raster |
| } // namespace gpu |