| // 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 "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" |
| |
| #include <algorithm> |
| #include <string> |
| #include <vector> |
| |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| #include "gpu/command_buffer/common/value_state.h" |
| #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| #include "gpu/command_buffer/service/context_group.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/test_helper.h" |
| #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gl/gl_implementation.h" |
| #include "ui/gl/gl_mock.h" |
| #include "ui/gl/gl_surface.h" |
| |
| using ::gfx::MockGLInterface; |
| using ::testing::_; |
| using ::testing::DoAll; |
| using ::testing::InSequence; |
| using ::testing::Invoke; |
| using ::testing::InvokeWithoutArgs; |
| using ::testing::MatcherCast; |
| using ::testing::Pointee; |
| using ::testing::Return; |
| using ::testing::SetArrayArgument; |
| using ::testing::SetArgPointee; |
| using ::testing::SetArgumentPointee; |
| using ::testing::StrEq; |
| using ::testing::StrictMock; |
| using ::testing::WithArg; |
| |
| namespace { |
| |
| void NormalizeInitState(gpu::gles2::GLES2DecoderTestBase::InitState* init) { |
| CHECK(init); |
| const char* kVAOExtensions[] = { |
| "GL_OES_vertex_array_object", |
| "GL_ARB_vertex_array_object", |
| "GL_APPLE_vertex_array_object" |
| }; |
| bool contains_vao_extension = false; |
| for (size_t ii = 0; ii < arraysize(kVAOExtensions); ++ii) { |
| if (init->extensions.find(kVAOExtensions[ii]) != std::string::npos) { |
| contains_vao_extension = true; |
| break; |
| } |
| } |
| |
| if (init->use_native_vao) { |
| if (contains_vao_extension) |
| return; |
| if (!init->extensions.empty()) |
| init->extensions += " "; |
| if (StartsWithASCII(init->gl_version, "opengl es", false)) { |
| init->extensions += kVAOExtensions[0]; |
| } else { |
| #if !defined(OS_MACOSX) |
| init->extensions += kVAOExtensions[1]; |
| #else |
| init->extensions += kVAOExtensions[2]; |
| #endif // OS_MACOSX |
| } |
| } else { |
| // Make sure we don't set up an invalid InitState. |
| CHECK(!contains_vao_extension); |
| } |
| |
| if (!init->extensions.empty()) |
| init->extensions += " "; |
| init->extensions += "GL_EXT_framebuffer_object "; |
| } |
| |
| } // namespace Anonymous |
| |
| namespace gpu { |
| namespace gles2 { |
| |
| GLES2DecoderTestBase::GLES2DecoderTestBase() |
| : surface_(NULL), |
| context_(NULL), |
| memory_tracker_(NULL), |
| client_buffer_id_(100), |
| client_framebuffer_id_(101), |
| client_program_id_(102), |
| client_renderbuffer_id_(103), |
| client_sampler_id_(104), |
| client_shader_id_(105), |
| client_texture_id_(106), |
| client_element_buffer_id_(107), |
| client_vertex_shader_id_(121), |
| client_fragment_shader_id_(122), |
| client_query_id_(123), |
| client_vertexarray_id_(124), |
| client_valuebuffer_id_(125), |
| client_transformfeedback_id_(126), |
| client_sync_id_(127), |
| service_renderbuffer_id_(0), |
| service_renderbuffer_valid_(false), |
| ignore_cached_state_for_test_(GetParam()), |
| cached_color_mask_red_(true), |
| cached_color_mask_green_(true), |
| cached_color_mask_blue_(true), |
| cached_color_mask_alpha_(true), |
| cached_depth_mask_(true), |
| cached_stencil_front_mask_(static_cast<GLuint>(-1)), |
| cached_stencil_back_mask_(static_cast<GLuint>(-1)) { |
| memset(immediate_buffer_, 0xEE, sizeof(immediate_buffer_)); |
| } |
| |
| GLES2DecoderTestBase::~GLES2DecoderTestBase() {} |
| |
| void GLES2DecoderTestBase::SetUp() { |
| InitState init; |
| // Autogenerated tests do not overwrite version or extension string, |
| // so we have to pick something that supports everything here. |
| init.gl_version = "4.4"; |
| init.has_alpha = true; |
| init.has_depth = true; |
| init.request_alpha = true; |
| init.request_depth = true; |
| init.bind_generates_resource = true; |
| InitDecoder(init); |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForVertexAttribManager() { |
| for (GLint ii = 0; ii < kNumVertexAttribs; ++ii) { |
| EXPECT_CALL(*gl_, VertexAttrib4f(ii, 0.0f, 0.0f, 0.0f, 1.0f)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| GLES2DecoderTestBase::InitState::InitState() |
| : extensions("GL_EXT_framebuffer_object"), |
| gl_version("2.1"), |
| has_alpha(false), |
| has_depth(false), |
| has_stencil(false), |
| request_alpha(false), |
| request_depth(false), |
| request_stencil(false), |
| bind_generates_resource(false), |
| lose_context_when_out_of_memory(false), |
| use_native_vao(true) { |
| } |
| |
| void GLES2DecoderTestBase::InitDecoder(const InitState& init) { |
| InitDecoderWithCommandLine(init, NULL); |
| } |
| |
| void GLES2DecoderTestBase::InitDecoderWithCommandLine( |
| const InitState& init, |
| const base::CommandLine* command_line) { |
| InitState normalized_init = init; |
| NormalizeInitState(&normalized_init); |
| // For easier substring/extension matching |
| DCHECK(normalized_init.extensions.empty() || |
| *normalized_init.extensions.rbegin() == ' '); |
| Framebuffer::ClearFramebufferCompleteComboMap(); |
| |
| gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress); |
| gfx::GLSurface::InitializeOneOffWithMockBindingsForTests(); |
| |
| gl_.reset(new StrictMock<MockGLInterface>()); |
| ::gfx::MockGLInterface::SetGLInterface(gl_.get()); |
| |
| SetupMockGLBehaviors(); |
| |
| scoped_refptr<FeatureInfo> feature_info; |
| if (command_line) |
| feature_info = new FeatureInfo(*command_line); |
| group_ = scoped_refptr<ContextGroup>( |
| new ContextGroup(NULL, |
| memory_tracker_, |
| new ShaderTranslatorCache, |
| feature_info.get(), |
| new SubscriptionRefSet, |
| new ValueStateMap, |
| normalized_init.bind_generates_resource)); |
| bool use_default_textures = normalized_init.bind_generates_resource; |
| |
| InSequence sequence; |
| |
| surface_ = new gfx::GLSurfaceStub; |
| surface_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight)); |
| |
| // Context needs to be created before initializing ContextGroup, which will |
| // in turn initialize FeatureInfo, which needs a context to determine |
| // extension support. |
| context_ = new gfx::GLContextStubWithExtensions; |
| context_->AddExtensionsString(normalized_init.extensions.c_str()); |
| context_->SetGLVersionString(normalized_init.gl_version.c_str()); |
| |
| context_->MakeCurrent(surface_.get()); |
| gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_.get()); |
| |
| TestHelper::SetupContextGroupInitExpectations( |
| gl_.get(), |
| DisallowedFeatures(), |
| normalized_init.extensions.c_str(), |
| normalized_init.gl_version.c_str(), |
| normalized_init.bind_generates_resource); |
| |
| // 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()); |
| |
| // Install FakeDoCommands handler so we can use individual DoCommand() |
| // expectations. |
| EXPECT_CALL(*mock_decoder_, DoCommands(_, _, _, _)).WillRepeatedly( |
| Invoke(mock_decoder_.get(), &MockGLES2Decoder::FakeDoCommands)); |
| |
| EXPECT_TRUE( |
| group_->Initialize(mock_decoder_.get(), DisallowedFeatures())); |
| |
| if (group_->feature_info()->feature_flags().native_vertex_array_object) { |
| EXPECT_CALL(*gl_, GenVertexArraysOES(1, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceVertexArrayId)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindVertexArrayOES(_)).Times(1).RetiresOnSaturation(); |
| } |
| |
| if (group_->feature_info()->workarounds().init_vertex_attributes) |
| AddExpectationsForVertexAttribManager(); |
| |
| AddExpectationsForBindVertexArrayOES(); |
| |
| EXPECT_CALL(*gl_, EnableVertexAttribArray(0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| static GLuint attrib_0_id[] = { |
| kServiceAttrib0BufferId, |
| }; |
| static GLuint fixed_attrib_buffer_id[] = { |
| kServiceFixedAttribBufferId, |
| }; |
| EXPECT_CALL(*gl_, GenBuffersARB(arraysize(attrib_0_id), _)) |
| .WillOnce(SetArrayArgument<1>(attrib_0_id, |
| attrib_0_id + arraysize(attrib_0_id))) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, kServiceAttrib0BufferId)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, VertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GenBuffersARB(arraysize(fixed_attrib_buffer_id), _)) |
| .WillOnce(SetArrayArgument<1>( |
| fixed_attrib_buffer_id, |
| fixed_attrib_buffer_id + arraysize(fixed_attrib_buffer_id))) |
| .RetiresOnSaturation(); |
| |
| for (GLint tt = 0; tt < TestHelper::kNumTextureUnits; ++tt) { |
| EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0 + tt)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| if (group_->feature_info()->feature_flags().oes_egl_image_external) { |
| EXPECT_CALL(*gl_, |
| BindTexture(GL_TEXTURE_EXTERNAL_OES, |
| use_default_textures |
| ? TestHelper::kServiceDefaultExternalTextureId |
| : 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| if (group_->feature_info()->feature_flags().arb_texture_rectangle) { |
| EXPECT_CALL( |
| *gl_, |
| BindTexture(GL_TEXTURE_RECTANGLE_ARB, |
| use_default_textures |
| ? TestHelper::kServiceDefaultRectangleTextureId |
| : 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_CALL(*gl_, |
| BindTexture(GL_TEXTURE_CUBE_MAP, |
| use_default_textures |
| ? TestHelper::kServiceDefaultTextureCubemapId |
| : 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL( |
| *gl_, |
| BindTexture( |
| GL_TEXTURE_2D, |
| use_default_textures ? TestHelper::kServiceDefaultTexture2dId : 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) |
| .WillOnce(SetArgumentPointee<1>(normalized_init.has_alpha ? 8 : 0)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _)) |
| .WillOnce(SetArgumentPointee<1>(normalized_init.has_depth ? 24 : 0)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _)) |
| .WillOnce(SetArgumentPointee<1>(normalized_init.has_stencil ? 8 : 0)) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, Enable(GL_VERTEX_PROGRAM_POINT_SIZE)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, Enable(GL_POINT_SPRITE)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| static GLint max_viewport_dims[] = { |
| kMaxViewportWidth, |
| kMaxViewportHeight |
| }; |
| EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_VIEWPORT_DIMS, _)) |
| .WillOnce(SetArrayArgument<1>( |
| max_viewport_dims, max_viewport_dims + arraysize(max_viewport_dims))) |
| .RetiresOnSaturation(); |
| |
| SetupInitCapabilitiesExpectations(); |
| SetupInitStateExpectations(); |
| |
| EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindRenderbufferEXT(GL_RENDERBUFFER, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| // TODO(boliu): Remove OS_ANDROID once crbug.com/259023 is fixed and the |
| // workaround has been reverted. |
| #if !defined(OS_ANDROID) |
| EXPECT_CALL(*gl_, Clear( |
| GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| #endif |
| |
| engine_.reset(new StrictMock<MockCommandBufferEngine>()); |
| scoped_refptr<gpu::Buffer> buffer = |
| engine_->GetSharedMemoryBuffer(kSharedMemoryId); |
| shared_memory_offset_ = kSharedMemoryOffset; |
| shared_memory_address_ = |
| reinterpret_cast<int8*>(buffer->memory()) + shared_memory_offset_; |
| shared_memory_id_ = kSharedMemoryId; |
| shared_memory_base_ = buffer->memory(); |
| |
| static const int32 kLoseContextWhenOutOfMemory = 0x10002; |
| |
| int32 attributes[] = { |
| EGL_ALPHA_SIZE, |
| normalized_init.request_alpha ? 8 : 0, |
| EGL_DEPTH_SIZE, |
| normalized_init.request_depth ? 24 : 0, |
| EGL_STENCIL_SIZE, |
| normalized_init.request_stencil ? 8 : 0, |
| kLoseContextWhenOutOfMemory, |
| normalized_init.lose_context_when_out_of_memory ? 1 : 0, }; |
| std::vector<int32> attribs(attributes, attributes + arraysize(attributes)); |
| |
| decoder_.reset(GLES2Decoder::Create(group_.get())); |
| decoder_->SetIgnoreCachedStateForTest(ignore_cached_state_for_test_); |
| decoder_->GetLogger()->set_log_synthesized_gl_errors(false); |
| decoder_->Initialize(surface_, |
| context_, |
| false, |
| surface_->GetSize(), |
| DisallowedFeatures(), |
| attribs); |
| decoder_->MakeCurrent(); |
| decoder_->set_engine(engine_.get()); |
| decoder_->BeginDecoding(); |
| |
| EXPECT_CALL(*gl_, GenBuffersARB(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceBufferId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenBuffersImmediate>(client_buffer_id_); |
| EXPECT_CALL(*gl_, GenFramebuffersEXT(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceFramebufferId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenFramebuffersImmediate>(client_framebuffer_id_); |
| EXPECT_CALL(*gl_, GenRenderbuffersEXT(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceRenderbufferId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenRenderbuffersImmediate>(client_renderbuffer_id_); |
| EXPECT_CALL(*gl_, GenTextures(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceTextureId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenTexturesImmediate>(client_texture_id_); |
| EXPECT_CALL(*gl_, GenBuffersARB(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceElementBufferId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenBuffersImmediate>(client_element_buffer_id_); |
| |
| DoCreateProgram(client_program_id_, kServiceProgramId); |
| DoCreateShader(GL_VERTEX_SHADER, client_shader_id_, kServiceShaderId); |
| |
| // Unsafe commands. |
| bool reset_unsafe_es3_apis_enabled = false; |
| if (!decoder_->unsafe_es3_apis_enabled()) { |
| decoder_->set_unsafe_es3_apis_enabled(true); |
| reset_unsafe_es3_apis_enabled = true; |
| } |
| |
| const gfx::GLVersionInfo* version = context_->GetVersionInfo(); |
| if (version->IsAtLeastGL(3, 3) || version->IsAtLeastGLES(3, 0)) { |
| EXPECT_CALL(*gl_, GenSamplers(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceSamplerId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenSamplersImmediate>(client_sampler_id_); |
| } |
| if (version->IsAtLeastGL(4, 0) || version->IsAtLeastGLES(3, 0)) { |
| EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceTransformFeedbackId)) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::GenTransformFeedbacksImmediate>( |
| client_transformfeedback_id_); |
| } |
| |
| if (init.extensions.find("GL_ARB_sync ") != std::string::npos || |
| version->IsAtLeastGL(3, 2) || version->IsAtLeastGLES(3, 0)) { |
| DoFenceSync(client_sync_id_, kServiceSyncId); |
| } |
| |
| if (reset_unsafe_es3_apis_enabled) { |
| decoder_->set_unsafe_es3_apis_enabled(false); |
| } |
| |
| EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| } |
| |
| void GLES2DecoderTestBase::ResetDecoder() { |
| if (!decoder_.get()) |
| return; |
| // All Tests should have read all their GLErrors before getting here. |
| EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| |
| EXPECT_CALL(*gl_, DeleteBuffersARB(1, _)) |
| .Times(2) |
| .RetiresOnSaturation(); |
| if (group_->feature_info()->feature_flags().native_vertex_array_object) { |
| EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, Pointee(kServiceVertexArrayId))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| decoder_->EndDecoding(); |
| decoder_->Destroy(true); |
| decoder_.reset(); |
| group_->Destroy(mock_decoder_.get(), false); |
| engine_.reset(); |
| ::gfx::MockGLInterface::SetGLInterface(NULL); |
| gl_.reset(); |
| gfx::ClearGLBindings(); |
| } |
| |
| void GLES2DecoderTestBase::TearDown() { |
| ResetDecoder(); |
| } |
| |
| void GLES2DecoderTestBase::ExpectEnableDisable(GLenum cap, bool enable) { |
| if (enable) { |
| EXPECT_CALL(*gl_, Enable(cap)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl_, Disable(cap)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| |
| GLint GLES2DecoderTestBase::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*>()); |
| } |
| |
| void GLES2DecoderTestBase::DoCreateShader( |
| GLenum shader_type, GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, CreateShader(shader_type)) |
| .Times(1) |
| .WillOnce(Return(service_id)) |
| .RetiresOnSaturation(); |
| cmds::CreateShader cmd; |
| cmd.Init(shader_type, client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| bool GLES2DecoderTestBase::DoIsShader(GLuint client_id) { |
| return IsObjectHelper<cmds::IsShader, cmds::IsShader::Result>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoDeleteShader( |
| GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, DeleteShader(service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::DeleteShader cmd; |
| cmd.Init(client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoCreateProgram( |
| GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, CreateProgram()) |
| .Times(1) |
| .WillOnce(Return(service_id)) |
| .RetiresOnSaturation(); |
| cmds::CreateProgram cmd; |
| cmd.Init(client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| bool GLES2DecoderTestBase::DoIsProgram(GLuint client_id) { |
| return IsObjectHelper<cmds::IsProgram, cmds::IsProgram::Result>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoDeleteProgram( |
| GLuint client_id, GLuint /* service_id */) { |
| cmds::DeleteProgram cmd; |
| cmd.Init(client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoFenceSync( |
| GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) |
| .Times(1) |
| .WillOnce(Return(reinterpret_cast<GLsync>(service_id))) |
| .RetiresOnSaturation(); |
| cmds::FenceSync cmd; |
| cmd.Init(client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::SetBucketData( |
| uint32_t bucket_id, const void* data, uint32_t data_size) { |
| DCHECK(data || data_size == 0); |
| cmd::SetBucketSize cmd1; |
| cmd1.Init(bucket_id, data_size); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); |
| if (data) { |
| memcpy(shared_memory_address_, data, data_size); |
| cmd::SetBucketData cmd2; |
| cmd2.Init(bucket_id, 0, data_size, kSharedMemoryId, kSharedMemoryOffset); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); |
| ClearSharedMemory(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetBucketAsCString( |
| uint32 bucket_id, const char* str) { |
| SetBucketData(bucket_id, str, str ? (strlen(str) + 1) : 0); |
| } |
| |
| void GLES2DecoderTestBase::SetBucketAsCStrings( |
| uint32 bucket_id, GLsizei count, const char** str, |
| GLsizei count_in_header, char str_end) { |
| uint32_t header_size = sizeof(GLint) * (count + 1); |
| uint32_t total_size = header_size; |
| scoped_ptr<GLint[]> header(new GLint[count + 1]); |
| header[0] = static_cast<GLint>(count_in_header); |
| for (GLsizei ii = 0; ii < count; ++ii) { |
| header[ii + 1] = str && str[ii] ? strlen(str[ii]) : 0; |
| total_size += header[ii + 1] + 1; |
| } |
| cmd::SetBucketSize cmd1; |
| cmd1.Init(bucket_id, total_size); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1)); |
| memcpy(shared_memory_address_, header.get(), header_size); |
| uint32_t offset = header_size; |
| for (GLsizei ii = 0; ii < count; ++ii) { |
| if (str && str[ii]) { |
| size_t str_len = strlen(str[ii]); |
| memcpy(reinterpret_cast<char*>(shared_memory_address_) + offset, |
| str[ii], str_len); |
| offset += str_len; |
| } |
| memcpy(reinterpret_cast<char*>(shared_memory_address_) + offset, |
| &str_end, 1); |
| offset += 1; |
| } |
| cmd::SetBucketData cmd2; |
| cmd2.Init(bucket_id, 0, total_size, kSharedMemoryId, kSharedMemoryOffset); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); |
| ClearSharedMemory(); |
| } |
| |
| void GLES2DecoderTestBase::SetupClearTextureExpectations( |
| GLuint service_id, |
| GLuint old_service_id, |
| GLenum bind_target, |
| GLenum target, |
| GLint level, |
| GLenum internal_format, |
| GLenum format, |
| GLenum type, |
| GLsizei width, |
| GLsizei height) { |
| EXPECT_CALL(*gl_, BindTexture(bind_target, service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, TexImage2D( |
| target, level, internal_format, width, height, 0, format, type, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindTexture(bind_target, old_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearing( |
| GLenum target, |
| GLuint clear_bits, |
| GLclampf restore_red, |
| GLclampf restore_green, |
| GLclampf restore_blue, |
| GLclampf restore_alpha, |
| GLuint restore_stencil, |
| GLclampf restore_depth, |
| bool restore_scissor_test) { |
| SetupExpectationsForFramebufferClearingMulti( |
| 0, |
| 0, |
| target, |
| clear_bits, |
| restore_red, |
| restore_green, |
| restore_blue, |
| restore_alpha, |
| restore_stencil, |
| restore_depth, |
| restore_scissor_test); |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForRestoreClearState( |
| GLclampf restore_red, |
| GLclampf restore_green, |
| GLclampf restore_blue, |
| GLclampf restore_alpha, |
| GLuint restore_stencil, |
| GLclampf restore_depth, |
| bool restore_scissor_test) { |
| EXPECT_CALL(*gl_, ClearColor( |
| restore_red, restore_green, restore_blue, restore_alpha)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, ClearStencil(restore_stencil)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, ClearDepth(restore_depth)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| if (restore_scissor_test) { |
| EXPECT_CALL(*gl_, Enable(GL_SCISSOR_TEST)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForFramebufferClearingMulti( |
| GLuint read_framebuffer_service_id, |
| GLuint draw_framebuffer_service_id, |
| GLenum target, |
| GLuint clear_bits, |
| GLclampf restore_red, |
| GLclampf restore_green, |
| GLclampf restore_blue, |
| GLclampf restore_alpha, |
| GLuint restore_stencil, |
| GLclampf restore_depth, |
| bool restore_scissor_test) { |
| // TODO(gman): Figure out why InSequence stopped working. |
| // InSequence sequence; |
| EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(target)) |
| .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) |
| .RetiresOnSaturation(); |
| if (target == GL_READ_FRAMEBUFFER_EXT) { |
| EXPECT_CALL(*gl_, BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindFramebufferEXT( |
| GL_DRAW_FRAMEBUFFER_EXT, read_framebuffer_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0) { |
| EXPECT_CALL(*gl_, ClearColor(0.0f, 0.0f, 0.0f, 0.0f)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| SetupExpectationsForColorMask(true, true, true, true); |
| } |
| if ((clear_bits & GL_STENCIL_BUFFER_BIT) != 0) { |
| EXPECT_CALL(*gl_, ClearStencil(0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, StencilMask(static_cast<GLuint>(-1))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| if ((clear_bits & GL_DEPTH_BUFFER_BIT) != 0) { |
| EXPECT_CALL(*gl_, ClearDepth(1.0f)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| SetupExpectationsForDepthMask(true); |
| } |
| SetupExpectationsForEnableDisable(GL_SCISSOR_TEST, false); |
| EXPECT_CALL(*gl_, Clear(clear_bits)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| SetupExpectationsForRestoreClearState( |
| restore_red, restore_green, restore_blue, restore_alpha, |
| restore_stencil, restore_depth, restore_scissor_test); |
| if (target == GL_READ_FRAMEBUFFER_EXT) { |
| EXPECT_CALL(*gl_, BindFramebufferEXT( |
| GL_READ_FRAMEBUFFER_EXT, read_framebuffer_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindFramebufferEXT( |
| GL_DRAW_FRAMEBUFFER_EXT, draw_framebuffer_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupShaderForUniform(GLenum uniform_type) { |
| static AttribInfo attribs[] = { |
| { "foo", 1, GL_FLOAT, 1, }, |
| { "goo", 1, GL_FLOAT, 2, }, |
| }; |
| UniformInfo uniforms[] = { |
| { "bar", 1, uniform_type, 0, 2, -1, }, |
| { "car", 4, uniform_type, 1, 1, -1, }, |
| }; |
| const GLuint kClientVertexShaderId = 5001; |
| const GLuint kServiceVertexShaderId = 6001; |
| const GLuint kClientFragmentShaderId = 5002; |
| const GLuint kServiceFragmentShaderId = 6002; |
| SetupShader(attribs, arraysize(attribs), uniforms, arraysize(uniforms), |
| client_program_id_, kServiceProgramId, |
| kClientVertexShaderId, kServiceVertexShaderId, |
| kClientFragmentShaderId, kServiceFragmentShaderId); |
| |
| EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::UseProgram cmd; |
| cmd.Init(client_program_id_); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoBindBuffer( |
| GLenum target, GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, BindBuffer(target, service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::BindBuffer cmd; |
| cmd.Init(target, client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| bool GLES2DecoderTestBase::DoIsBuffer(GLuint client_id) { |
| return IsObjectHelper<cmds::IsBuffer, cmds::IsBuffer::Result>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoDeleteBuffer( |
| GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, DeleteBuffersARB(1, Pointee(service_id))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::DeleteBuffersImmediate>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForColorMask(bool red, |
| bool green, |
| bool blue, |
| bool alpha) { |
| if (ignore_cached_state_for_test_ || cached_color_mask_red_ != red || |
| cached_color_mask_green_ != green || cached_color_mask_blue_ != blue || |
| cached_color_mask_alpha_ != alpha) { |
| cached_color_mask_red_ = red; |
| cached_color_mask_green_ = green; |
| cached_color_mask_blue_ = blue; |
| cached_color_mask_alpha_ = alpha; |
| EXPECT_CALL(*gl_, ColorMask(red, green, blue, alpha)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForDepthMask(bool mask) { |
| if (ignore_cached_state_for_test_ || cached_depth_mask_ != mask) { |
| cached_depth_mask_ = mask; |
| EXPECT_CALL(*gl_, DepthMask(mask)).Times(1).RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForStencilMask(GLuint front_mask, |
| GLuint back_mask) { |
| if (ignore_cached_state_for_test_ || |
| cached_stencil_front_mask_ != front_mask) { |
| cached_stencil_front_mask_ = front_mask; |
| EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, front_mask)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| if (ignore_cached_state_for_test_ || |
| cached_stencil_back_mask_ != back_mask) { |
| cached_stencil_back_mask_ = back_mask; |
| EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, back_mask)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForEnableDisable(GLenum cap, |
| bool enable) { |
| switch (cap) { |
| case GL_BLEND: |
| if (enable_flags_.cached_blend == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_blend = enable; |
| break; |
| case GL_CULL_FACE: |
| if (enable_flags_.cached_cull_face == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_cull_face = enable; |
| break; |
| case GL_DEPTH_TEST: |
| if (enable_flags_.cached_depth_test == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_depth_test = enable; |
| break; |
| case GL_DITHER: |
| if (enable_flags_.cached_dither == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_dither = enable; |
| break; |
| case GL_POLYGON_OFFSET_FILL: |
| if (enable_flags_.cached_polygon_offset_fill == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_polygon_offset_fill = enable; |
| break; |
| case GL_SAMPLE_ALPHA_TO_COVERAGE: |
| if (enable_flags_.cached_sample_alpha_to_coverage == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_sample_alpha_to_coverage = enable; |
| break; |
| case GL_SAMPLE_COVERAGE: |
| if (enable_flags_.cached_sample_coverage == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_sample_coverage = enable; |
| break; |
| case GL_SCISSOR_TEST: |
| if (enable_flags_.cached_scissor_test == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_scissor_test = enable; |
| break; |
| case GL_STENCIL_TEST: |
| if (enable_flags_.cached_stencil_test == enable && |
| !ignore_cached_state_for_test_) |
| return; |
| enable_flags_.cached_stencil_test = enable; |
| break; |
| default: |
| NOTREACHED(); |
| return; |
| } |
| if (enable) { |
| EXPECT_CALL(*gl_, Enable(cap)).Times(1).RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl_, Disable(cap)).Times(1).RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForApplyingDirtyState( |
| bool framebuffer_is_rgb, |
| bool framebuffer_has_depth, |
| bool framebuffer_has_stencil, |
| GLuint color_bits, |
| bool depth_mask, |
| bool depth_enabled, |
| GLuint front_stencil_mask, |
| GLuint back_stencil_mask, |
| bool stencil_enabled) { |
| bool color_mask_red = (color_bits & 0x1000) != 0; |
| bool color_mask_green = (color_bits & 0x0100) != 0; |
| bool color_mask_blue = (color_bits & 0x0010) != 0; |
| bool color_mask_alpha = (color_bits & 0x0001) && !framebuffer_is_rgb; |
| |
| SetupExpectationsForColorMask( |
| color_mask_red, color_mask_green, color_mask_blue, color_mask_alpha); |
| SetupExpectationsForDepthMask(depth_mask); |
| SetupExpectationsForStencilMask(front_stencil_mask, back_stencil_mask); |
| SetupExpectationsForEnableDisable(GL_DEPTH_TEST, |
| framebuffer_has_depth && depth_enabled); |
| SetupExpectationsForEnableDisable(GL_STENCIL_TEST, |
| framebuffer_has_stencil && stencil_enabled); |
| } |
| |
| void GLES2DecoderTestBase::SetupExpectationsForApplyingDefaultDirtyState() { |
| SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB |
| false, // Framebuffer has depth |
| false, // Framebuffer has stencil |
| 0x1111, // color bits |
| true, // depth mask |
| false, // depth enabled |
| 0, // front stencil mask |
| 0, // back stencil mask |
| false); // stencil enabled |
| } |
| |
| GLES2DecoderTestBase::EnableFlags::EnableFlags() |
| : cached_blend(false), |
| cached_cull_face(false), |
| cached_depth_test(false), |
| cached_dither(true), |
| cached_polygon_offset_fill(false), |
| cached_sample_alpha_to_coverage(false), |
| cached_sample_coverage(false), |
| cached_scissor_test(false), |
| cached_stencil_test(false) { |
| } |
| |
| void GLES2DecoderTestBase::DoBindFramebuffer( |
| GLenum target, GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, BindFramebufferEXT(target, service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::BindFramebuffer cmd; |
| cmd.Init(target, client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| bool GLES2DecoderTestBase::DoIsFramebuffer(GLuint client_id) { |
| return IsObjectHelper<cmds::IsFramebuffer, cmds::IsFramebuffer::Result>( |
| client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoDeleteFramebuffer( |
| GLuint client_id, GLuint service_id, |
| bool reset_draw, GLenum draw_target, GLuint draw_id, |
| bool reset_read, GLenum read_target, GLuint read_id) { |
| if (reset_draw) { |
| EXPECT_CALL(*gl_, BindFramebufferEXT(draw_target, draw_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| if (reset_read) { |
| EXPECT_CALL(*gl_, BindFramebufferEXT(read_target, read_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, Pointee(service_id))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::DeleteFramebuffersImmediate>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoBindRenderbuffer( |
| GLenum target, GLuint client_id, GLuint service_id) { |
| service_renderbuffer_id_ = service_id; |
| service_renderbuffer_valid_ = true; |
| EXPECT_CALL(*gl_, BindRenderbufferEXT(target, service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::BindRenderbuffer cmd; |
| cmd.Init(target, client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoRenderbufferStorageMultisampleCHROMIUM( |
| GLenum target, |
| GLsizei samples, |
| GLenum internal_format, |
| GLenum gl_format, |
| GLsizei width, |
| GLsizei height) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, |
| RenderbufferStorageMultisampleEXT( |
| target, samples, gl_format, width, height)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| cmds::RenderbufferStorageMultisampleCHROMIUM cmd; |
| cmd.Init(target, samples, internal_format, width, height); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| } |
| |
| void GLES2DecoderTestBase::RestoreRenderbufferBindings() { |
| GetDecoder()->RestoreRenderbufferBindings(); |
| service_renderbuffer_valid_ = false; |
| } |
| |
| void GLES2DecoderTestBase::EnsureRenderbufferBound(bool expect_bind) { |
| EXPECT_NE(expect_bind, service_renderbuffer_valid_); |
| |
| if (expect_bind) { |
| service_renderbuffer_valid_ = true; |
| EXPECT_CALL(*gl_, |
| BindRenderbufferEXT(GL_RENDERBUFFER, service_renderbuffer_id_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl_, BindRenderbufferEXT(_, _)).Times(0); |
| } |
| } |
| |
| bool GLES2DecoderTestBase::DoIsRenderbuffer(GLuint client_id) { |
| return IsObjectHelper<cmds::IsRenderbuffer, cmds::IsRenderbuffer::Result>( |
| client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoDeleteRenderbuffer( |
| GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, DeleteRenderbuffersEXT(1, Pointee(service_id))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::DeleteRenderbuffersImmediate>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoBindTexture( |
| GLenum target, GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, BindTexture(target, service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::BindTexture cmd; |
| cmd.Init(target, client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| bool GLES2DecoderTestBase::DoIsTexture(GLuint client_id) { |
| return IsObjectHelper<cmds::IsTexture, cmds::IsTexture::Result>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoDeleteTexture( |
| GLuint client_id, GLuint service_id) { |
| EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(service_id))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| GenHelper<cmds::DeleteTexturesImmediate>(client_id); |
| } |
| |
| void GLES2DecoderTestBase::DoBindTexImage2DCHROMIUM(GLenum target, |
| GLint image_id) { |
| cmds::BindTexImage2DCHROMIUM bind_tex_image_2d_cmd; |
| bind_tex_image_2d_cmd.Init(target, image_id); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd)); |
| EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| } |
| |
| void GLES2DecoderTestBase::DoTexImage2D( |
| GLenum target, GLint level, GLenum internal_format, |
| GLsizei width, GLsizei height, GLint border, |
| GLenum format, GLenum type, |
| uint32 shared_memory_id, uint32 shared_memory_offset) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, TexImage2D(target, level, internal_format, |
| width, height, border, format, type, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| cmds::TexImage2D cmd; |
| cmd.Init(target, level, internal_format, width, height, format, |
| type, shared_memory_id, shared_memory_offset); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoTexImage2DConvertInternalFormat( |
| GLenum target, GLint level, GLenum requested_internal_format, |
| GLsizei width, GLsizei height, GLint border, |
| GLenum format, GLenum type, |
| uint32 shared_memory_id, uint32 shared_memory_offset, |
| GLenum expected_internal_format) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, TexImage2D(target, level, expected_internal_format, |
| width, height, border, format, type, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| cmds::TexImage2D cmd; |
| cmd.Init(target, level, requested_internal_format, width, height, |
| format, type, shared_memory_id, shared_memory_offset); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoCompressedTexImage2D( |
| GLenum target, GLint level, GLenum format, |
| GLsizei width, GLsizei height, GLint border, |
| GLsizei size, uint32 bucket_id) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, CompressedTexImage2D( |
| target, level, format, width, height, border, size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| CommonDecoder::Bucket* bucket = decoder_->CreateBucket(bucket_id); |
| bucket->SetSize(size); |
| cmds::CompressedTexImage2DBucket cmd; |
| cmd.Init( |
| target, level, format, width, height, |
| bucket_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoRenderbufferStorage( |
| GLenum target, GLenum internal_format, GLenum actual_format, |
| GLsizei width, GLsizei height, GLenum error) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, RenderbufferStorageEXT( |
| target, actual_format, width, height)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(error)) |
| .RetiresOnSaturation(); |
| cmds::RenderbufferStorage cmd; |
| cmd.Init(target, internal_format, width, height); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoFramebufferTexture2D( |
| GLenum target, GLenum attachment, GLenum textarget, |
| GLuint texture_client_id, GLuint texture_service_id, GLint level, |
| GLenum error) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, FramebufferTexture2DEXT( |
| target, attachment, textarget, texture_service_id, level)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(error)) |
| .RetiresOnSaturation(); |
| cmds::FramebufferTexture2D cmd; |
| cmd.Init(target, attachment, textarget, texture_client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoFramebufferRenderbuffer( |
| GLenum target, |
| GLenum attachment, |
| GLenum renderbuffer_target, |
| GLuint renderbuffer_client_id, |
| GLuint renderbuffer_service_id, |
| GLenum error) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, FramebufferRenderbufferEXT( |
| target, attachment, renderbuffer_target, renderbuffer_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(error)) |
| .RetiresOnSaturation(); |
| cmds::FramebufferRenderbuffer cmd; |
| cmd.Init(target, attachment, renderbuffer_target, renderbuffer_client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoVertexAttribPointer( |
| GLuint index, GLint size, GLenum type, GLsizei stride, GLuint offset) { |
| EXPECT_CALL(*gl_, |
| VertexAttribPointer(index, size, type, GL_FALSE, stride, |
| BufferOffset(offset))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::VertexAttribPointer cmd; |
| cmd.Init(index, size, GL_FLOAT, GL_FALSE, stride, offset); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoVertexAttribDivisorANGLE( |
| GLuint index, GLuint divisor) { |
| EXPECT_CALL(*gl_, |
| VertexAttribDivisorANGLE(index, divisor)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::VertexAttribDivisorANGLE cmd; |
| cmd.Init(index, divisor); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForGenVertexArraysOES(){ |
| if (group_->feature_info()->feature_flags().native_vertex_array_object) { |
| EXPECT_CALL(*gl_, GenVertexArraysOES(1, _)) |
| .WillOnce(SetArgumentPointee<1>(kServiceVertexArrayId)) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForDeleteVertexArraysOES(){ |
| if (group_->feature_info()->feature_flags().native_vertex_array_object) { |
| EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForDeleteBoundVertexArraysOES() { |
| // Expectations are the same as a delete, followed by binding VAO 0. |
| AddExpectationsForDeleteVertexArraysOES(); |
| AddExpectationsForBindVertexArrayOES(); |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForBindVertexArrayOES() { |
| if (group_->feature_info()->feature_flags().native_vertex_array_object) { |
| EXPECT_CALL(*gl_, BindVertexArrayOES(_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else { |
| for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) { |
| AddExpectationsForRestoreAttribState(vv); |
| } |
| |
| EXPECT_CALL(*gl_, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForRestoreAttribState(GLuint attrib) { |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, VertexAttribPointer(attrib, _, _, _, _, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(attrib, _)) |
| .Times(testing::AtMost(1)) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| if (attrib != 0 || |
| gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { |
| |
| // TODO(bajones): Not sure if I can tell which of these will be called |
| EXPECT_CALL(*gl_, EnableVertexAttribArray(attrib)) |
| .Times(testing::AtMost(1)) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, DisableVertexAttribArray(attrib)) |
| .Times(testing::AtMost(1)) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| // GCC requires these declarations, but MSVC requires they not be present |
| #ifndef COMPILER_MSVC |
| const int GLES2DecoderTestBase::kBackBufferWidth; |
| const int GLES2DecoderTestBase::kBackBufferHeight; |
| |
| const GLint GLES2DecoderTestBase::kMaxTextureSize; |
| const GLint GLES2DecoderTestBase::kMaxCubeMapTextureSize; |
| const GLint GLES2DecoderTestBase::kNumVertexAttribs; |
| const GLint GLES2DecoderTestBase::kNumTextureUnits; |
| const GLint GLES2DecoderTestBase::kMaxTextureImageUnits; |
| const GLint GLES2DecoderTestBase::kMaxVertexTextureImageUnits; |
| const GLint GLES2DecoderTestBase::kMaxFragmentUniformVectors; |
| const GLint GLES2DecoderTestBase::kMaxVaryingVectors; |
| const GLint GLES2DecoderTestBase::kMaxVertexUniformVectors; |
| const GLint GLES2DecoderTestBase::kMaxViewportWidth; |
| const GLint GLES2DecoderTestBase::kMaxViewportHeight; |
| |
| const GLint GLES2DecoderTestBase::kViewportX; |
| const GLint GLES2DecoderTestBase::kViewportY; |
| const GLint GLES2DecoderTestBase::kViewportWidth; |
| const GLint GLES2DecoderTestBase::kViewportHeight; |
| |
| const GLuint GLES2DecoderTestBase::kServiceAttrib0BufferId; |
| const GLuint GLES2DecoderTestBase::kServiceFixedAttribBufferId; |
| |
| const GLuint GLES2DecoderTestBase::kServiceBufferId; |
| const GLuint GLES2DecoderTestBase::kServiceFramebufferId; |
| const GLuint GLES2DecoderTestBase::kServiceRenderbufferId; |
| const GLuint GLES2DecoderTestBase::kServiceSamplerId; |
| const GLuint GLES2DecoderTestBase::kServiceTextureId; |
| const GLuint GLES2DecoderTestBase::kServiceProgramId; |
| const GLuint GLES2DecoderTestBase::kServiceShaderId; |
| const GLuint GLES2DecoderTestBase::kServiceElementBufferId; |
| const GLuint GLES2DecoderTestBase::kServiceQueryId; |
| const GLuint GLES2DecoderTestBase::kServiceVertexArrayId; |
| const GLuint GLES2DecoderTestBase::kServiceTransformFeedbackId; |
| const GLuint GLES2DecoderTestBase::kServiceSyncId; |
| |
| const int32 GLES2DecoderTestBase::kSharedMemoryId; |
| const size_t GLES2DecoderTestBase::kSharedBufferSize; |
| const uint32 GLES2DecoderTestBase::kSharedMemoryOffset; |
| const int32 GLES2DecoderTestBase::kInvalidSharedMemoryId; |
| const uint32 GLES2DecoderTestBase::kInvalidSharedMemoryOffset; |
| const uint32 GLES2DecoderTestBase::kInitialResult; |
| const uint8 GLES2DecoderTestBase::kInitialMemoryValue; |
| |
| const uint32 GLES2DecoderTestBase::kNewClientId; |
| const uint32 GLES2DecoderTestBase::kNewServiceId; |
| const uint32 GLES2DecoderTestBase::kInvalidClientId; |
| |
| const GLuint GLES2DecoderTestBase::kServiceVertexShaderId; |
| const GLuint GLES2DecoderTestBase::kServiceFragmentShaderId; |
| |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumShaderId; |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumProgramId; |
| |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumTextureBufferId; |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumVertexBufferId; |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumFBOId; |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumPositionAttrib; |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumTexAttrib; |
| const GLuint GLES2DecoderTestBase::kServiceCopyTextureChromiumSamplerLocation; |
| |
| const GLsizei GLES2DecoderTestBase::kNumVertices; |
| const GLsizei GLES2DecoderTestBase::kNumIndices; |
| const int GLES2DecoderTestBase::kValidIndexRangeStart; |
| const int GLES2DecoderTestBase::kValidIndexRangeCount; |
| const int GLES2DecoderTestBase::kInvalidIndexRangeStart; |
| const int GLES2DecoderTestBase::kInvalidIndexRangeCount; |
| const int GLES2DecoderTestBase::kOutOfRangeIndexRangeEnd; |
| const GLuint GLES2DecoderTestBase::kMaxValidIndex; |
| |
| const GLint GLES2DecoderTestBase::kMaxAttribLength; |
| const GLint GLES2DecoderTestBase::kAttrib1Size; |
| const GLint GLES2DecoderTestBase::kAttrib2Size; |
| const GLint GLES2DecoderTestBase::kAttrib3Size; |
| const GLint GLES2DecoderTestBase::kAttrib1Location; |
| const GLint GLES2DecoderTestBase::kAttrib2Location; |
| const GLint GLES2DecoderTestBase::kAttrib3Location; |
| const GLenum GLES2DecoderTestBase::kAttrib1Type; |
| const GLenum GLES2DecoderTestBase::kAttrib2Type; |
| const GLenum GLES2DecoderTestBase::kAttrib3Type; |
| const GLint GLES2DecoderTestBase::kInvalidAttribLocation; |
| const GLint GLES2DecoderTestBase::kBadAttribIndex; |
| |
| const GLint GLES2DecoderTestBase::kMaxUniformLength; |
| const GLint GLES2DecoderTestBase::kUniform1Size; |
| const GLint GLES2DecoderTestBase::kUniform2Size; |
| const GLint GLES2DecoderTestBase::kUniform3Size; |
| const GLint GLES2DecoderTestBase::kUniform1RealLocation; |
| const GLint GLES2DecoderTestBase::kUniform2RealLocation; |
| const GLint GLES2DecoderTestBase::kUniform2ElementRealLocation; |
| const GLint GLES2DecoderTestBase::kUniform3RealLocation; |
| const GLint GLES2DecoderTestBase::kUniform1FakeLocation; |
| const GLint GLES2DecoderTestBase::kUniform2FakeLocation; |
| const GLint GLES2DecoderTestBase::kUniform2ElementFakeLocation; |
| const GLint GLES2DecoderTestBase::kUniform3FakeLocation; |
| const GLint GLES2DecoderTestBase::kUniform1DesiredLocation; |
| const GLint GLES2DecoderTestBase::kUniform2DesiredLocation; |
| const GLint GLES2DecoderTestBase::kUniform3DesiredLocation; |
| const GLenum GLES2DecoderTestBase::kUniform1Type; |
| const GLenum GLES2DecoderTestBase::kUniform2Type; |
| const GLenum GLES2DecoderTestBase::kUniform3Type; |
| const GLenum GLES2DecoderTestBase::kUniformCubemapType; |
| const GLint GLES2DecoderTestBase::kInvalidUniformLocation; |
| const GLint GLES2DecoderTestBase::kBadUniformIndex; |
| |
| #endif |
| |
| const char* GLES2DecoderTestBase::kAttrib1Name = "attrib1"; |
| const char* GLES2DecoderTestBase::kAttrib2Name = "attrib2"; |
| const char* GLES2DecoderTestBase::kAttrib3Name = "attrib3"; |
| const char* GLES2DecoderTestBase::kUniform1Name = "uniform1"; |
| const char* GLES2DecoderTestBase::kUniform2Name = "uniform2[0]"; |
| const char* GLES2DecoderTestBase::kUniform3Name = "uniform3[0]"; |
| |
| void GLES2DecoderTestBase::SetupDefaultProgram() { |
| { |
| static AttribInfo attribs[] = { |
| { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, |
| { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, |
| { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, |
| }; |
| static UniformInfo uniforms[] = { |
| { kUniform1Name, kUniform1Size, kUniform1Type, |
| kUniform1FakeLocation, kUniform1RealLocation, |
| kUniform1DesiredLocation }, |
| { kUniform2Name, kUniform2Size, kUniform2Type, |
| kUniform2FakeLocation, kUniform2RealLocation, |
| kUniform2DesiredLocation }, |
| { kUniform3Name, kUniform3Size, kUniform3Type, |
| kUniform3FakeLocation, kUniform3RealLocation, |
| kUniform3DesiredLocation }, |
| }; |
| SetupShader(attribs, arraysize(attribs), uniforms, arraysize(uniforms), |
| client_program_id_, kServiceProgramId, |
| client_vertex_shader_id_, kServiceVertexShaderId, |
| client_fragment_shader_id_, kServiceFragmentShaderId); |
| } |
| |
| { |
| EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::UseProgram cmd; |
| cmd.Init(client_program_id_); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupCubemapProgram() { |
| { |
| static AttribInfo attribs[] = { |
| { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, |
| { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, |
| { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, |
| }; |
| static UniformInfo uniforms[] = { |
| { kUniform1Name, kUniform1Size, kUniformCubemapType, |
| kUniform1FakeLocation, kUniform1RealLocation, |
| kUniform1DesiredLocation, }, |
| { kUniform2Name, kUniform2Size, kUniform2Type, |
| kUniform2FakeLocation, kUniform2RealLocation, |
| kUniform2DesiredLocation, }, |
| { kUniform3Name, kUniform3Size, kUniform3Type, |
| kUniform3FakeLocation, kUniform3RealLocation, |
| kUniform3DesiredLocation, }, |
| }; |
| SetupShader(attribs, arraysize(attribs), uniforms, arraysize(uniforms), |
| client_program_id_, kServiceProgramId, |
| client_vertex_shader_id_, kServiceVertexShaderId, |
| client_fragment_shader_id_, kServiceFragmentShaderId); |
| } |
| |
| { |
| EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::UseProgram cmd; |
| cmd.Init(client_program_id_); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| } |
| |
| void GLES2DecoderTestBase::SetupSamplerExternalProgram() { |
| { |
| static AttribInfo attribs[] = { |
| { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, |
| { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, |
| { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, |
| }; |
| static UniformInfo uniforms[] = { |
| { kUniform1Name, kUniform1Size, kUniformSamplerExternalType, |
| kUniform1FakeLocation, kUniform1RealLocation, |
| kUniform1DesiredLocation, }, |
| { kUniform2Name, kUniform2Size, kUniform2Type, |
| kUniform2FakeLocation, kUniform2RealLocation, |
| kUniform2DesiredLocation, }, |
| { kUniform3Name, kUniform3Size, kUniform3Type, |
| kUniform3FakeLocation, kUniform3RealLocation, |
| kUniform3DesiredLocation, }, |
| }; |
| SetupShader(attribs, arraysize(attribs), uniforms, arraysize(uniforms), |
| client_program_id_, kServiceProgramId, |
| client_vertex_shader_id_, kServiceVertexShaderId, |
| client_fragment_shader_id_, kServiceFragmentShaderId); |
| } |
| |
| { |
| EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::UseProgram cmd; |
| cmd.Init(client_program_id_); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| } |
| |
| void GLES2DecoderWithShaderTestBase::TearDown() { |
| GLES2DecoderTestBase::TearDown(); |
| } |
| |
| void GLES2DecoderTestBase::SetupShader( |
| GLES2DecoderTestBase::AttribInfo* attribs, size_t num_attribs, |
| GLES2DecoderTestBase::UniformInfo* uniforms, size_t num_uniforms, |
| GLuint program_client_id, GLuint program_service_id, |
| GLuint vertex_shader_client_id, GLuint vertex_shader_service_id, |
| GLuint fragment_shader_client_id, GLuint fragment_shader_service_id) { |
| { |
| InSequence s; |
| |
| EXPECT_CALL(*gl_, |
| AttachShader(program_service_id, vertex_shader_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, |
| AttachShader(program_service_id, fragment_shader_service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| TestHelper::SetupShader( |
| gl_.get(), attribs, num_attribs, uniforms, num_uniforms, |
| program_service_id); |
| } |
| |
| DoCreateShader( |
| GL_VERTEX_SHADER, vertex_shader_client_id, vertex_shader_service_id); |
| DoCreateShader( |
| GL_FRAGMENT_SHADER, fragment_shader_client_id, |
| fragment_shader_service_id); |
| |
| TestHelper::SetShaderStates( |
| gl_.get(), GetShader(vertex_shader_client_id), true); |
| TestHelper::SetShaderStates( |
| gl_.get(), GetShader(fragment_shader_client_id), true); |
| |
| cmds::AttachShader attach_cmd; |
| attach_cmd.Init(program_client_id, vertex_shader_client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(attach_cmd)); |
| |
| attach_cmd.Init(program_client_id, fragment_shader_client_id); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(attach_cmd)); |
| |
| cmds::LinkProgram link_cmd; |
| link_cmd.Init(program_client_id); |
| |
| EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoEnableDisable(GLenum cap, bool enable) { |
| SetupExpectationsForEnableDisable(cap, enable); |
| if (enable) { |
| cmds::Enable cmd; |
| cmd.Init(cap); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } else { |
| cmds::Disable cmd; |
| cmd.Init(cap); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| } |
| |
| void GLES2DecoderTestBase::DoEnableVertexAttribArray(GLint index) { |
| EXPECT_CALL(*gl_, EnableVertexAttribArray(index)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| cmds::EnableVertexAttribArray cmd; |
| cmd.Init(index); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoBufferData(GLenum target, GLsizei size) { |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BufferData(target, size, _, GL_STREAM_DRAW)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| cmds::BufferData cmd; |
| cmd.Init(target, size, 0, 0, GL_STREAM_DRAW); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::DoBufferSubData( |
| GLenum target, GLint offset, GLsizei size, const void* data) { |
| EXPECT_CALL(*gl_, BufferSubData(target, offset, size, |
| shared_memory_address_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| memcpy(shared_memory_address_, data, size); |
| cmds::BufferSubData cmd; |
| cmd.Init(target, offset, size, shared_memory_id_, shared_memory_offset_); |
| EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| } |
| |
| void GLES2DecoderTestBase::SetupVertexBuffer() { |
| DoEnableVertexAttribArray(1); |
| DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); |
| DoBufferData(GL_ARRAY_BUFFER, kNumVertices * 2 * sizeof(GLfloat)); |
| } |
| |
| void GLES2DecoderTestBase::SetupAllNeededVertexBuffers() { |
| DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); |
| DoBufferData(GL_ARRAY_BUFFER, kNumVertices * 16 * sizeof(float)); |
| DoEnableVertexAttribArray(0); |
| DoEnableVertexAttribArray(1); |
| DoEnableVertexAttribArray(2); |
| DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0); |
| DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0); |
| DoVertexAttribPointer(2, 2, GL_FLOAT, 0, 0); |
| } |
| |
| void GLES2DecoderTestBase::SetupIndexBuffer() { |
| DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, |
| client_element_buffer_id_, |
| kServiceElementBufferId); |
| static const GLshort indices[] = {100, 1, 2, 3, 4, 5, 6, 7, 100, 9}; |
| static_assert(arraysize(indices) == kNumIndices, |
| "indices should have kNumIndices elements"); |
| DoBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices)); |
| DoBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 2, indices); |
| DoBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2, sizeof(indices) - 2, &indices[1]); |
| } |
| |
| void GLES2DecoderTestBase::SetupTexture() { |
| DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); |
| DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| kSharedMemoryId, kSharedMemoryOffset); |
| }; |
| |
| void GLES2DecoderTestBase::DeleteVertexBuffer() { |
| DoDeleteBuffer(client_buffer_id_, kServiceBufferId); |
| } |
| |
| void GLES2DecoderTestBase::DeleteIndexBuffer() { |
| DoDeleteBuffer(client_element_buffer_id_, kServiceElementBufferId); |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForSimulatedAttrib0WithError( |
| GLsizei num_vertices, GLuint buffer_id, GLenum error) { |
| if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { |
| return; |
| } |
| |
| EXPECT_CALL(*gl_, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .WillOnce(Return(error)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, kServiceAttrib0BufferId)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BufferData(GL_ARRAY_BUFFER, |
| num_vertices * sizeof(GLfloat) * 4, |
| _, GL_DYNAMIC_DRAW)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| if (error == GL_NO_ERROR) { |
| EXPECT_CALL(*gl_, BufferSubData( |
| GL_ARRAY_BUFFER, 0, num_vertices * sizeof(GLfloat) * 4, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, VertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, buffer_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| |
| void GLES2DecoderTestBase::AddExpectationsForSimulatedAttrib0( |
| GLsizei num_vertices, GLuint buffer_id) { |
| AddExpectationsForSimulatedAttrib0WithError( |
| num_vertices, buffer_id, GL_NO_ERROR); |
| } |
| |
| void GLES2DecoderTestBase::SetupMockGLBehaviors() { |
| ON_CALL(*gl_, BindVertexArrayOES(_)) |
| .WillByDefault(Invoke( |
| &gl_states_, |
| &GLES2DecoderTestBase::MockGLStates::OnBindVertexArrayOES)); |
| ON_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, _)) |
| .WillByDefault(WithArg<1>(Invoke( |
| &gl_states_, |
| &GLES2DecoderTestBase::MockGLStates::OnBindArrayBuffer))); |
| ON_CALL(*gl_, VertexAttribPointer(_, _, _, _, _, NULL)) |
| .WillByDefault(InvokeWithoutArgs( |
| &gl_states_, |
| &GLES2DecoderTestBase::MockGLStates::OnVertexAttribNullPointer)); |
| } |
| |
| GLES2DecoderWithShaderTestBase::MockCommandBufferEngine:: |
| MockCommandBufferEngine() { |
| |
| scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); |
| shm->CreateAndMapAnonymous(kSharedBufferSize); |
| valid_buffer_ = MakeBufferFromSharedMemory(shm.Pass(), kSharedBufferSize); |
| |
| ClearSharedMemory(); |
| } |
| |
| GLES2DecoderWithShaderTestBase::MockCommandBufferEngine:: |
| ~MockCommandBufferEngine() {} |
| |
| scoped_refptr<gpu::Buffer> |
| GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::GetSharedMemoryBuffer( |
| int32 shm_id) { |
| return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_; |
| } |
| |
| void GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::set_token( |
| int32 token) { |
| DCHECK(false); |
| } |
| |
| bool GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::SetGetBuffer( |
| int32 /* transfer_buffer_id */) { |
| DCHECK(false); |
| return false; |
| } |
| |
| bool GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::SetGetOffset( |
| int32 offset) { |
| DCHECK(false); |
| return false; |
| } |
| |
| int32 GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::GetGetOffset() { |
| DCHECK(false); |
| return 0; |
| } |
| |
| void GLES2DecoderWithShaderTestBase::SetUp() { |
| GLES2DecoderTestBase::SetUp(); |
| SetupDefaultProgram(); |
| } |
| |
| // Include the auto-generated part of this file. We split this because it means |
| // we can easily edit the non-auto generated parts right here in this file |
| // instead of having to edit some template or the code generator. |
| #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h" |
| |
| } // namespace gles2 |
| } // namespace gpu |