| Index: gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
|
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9b28bd6364d4de343036cf836b79e85abf6cb1b4
|
| --- /dev/null
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
|
| @@ -0,0 +1,2164 @@
|
| +// Copyright (c) 2014 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/common/id_allocator.h"
|
| +#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h"
|
| +#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
|
| +#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h"
|
| +#include "gpu/command_buffer/service/cmd_buffer_engine.h"
|
| +#include "gpu/command_buffer/service/context_group.h"
|
| +#include "gpu/command_buffer/service/context_state.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/image_manager.h"
|
| +#include "gpu/command_buffer/service/mailbox_manager.h"
|
| +#include "gpu/command_buffer/service/mocks.h"
|
| +#include "gpu/command_buffer/service/program_manager.h"
|
| +#include "gpu/command_buffer/service/test_helper.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_stub.h"
|
| +
|
| +#if !defined(GL_DEPTH24_STENCIL8)
|
| +#define GL_DEPTH24_STENCIL8 0x88F0
|
| +#endif
|
| +
|
| +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 GLES2DecoderGeometryInstancingTest : public GLES2DecoderWithShaderTest {
|
| + public:
|
| + GLES2DecoderGeometryInstancingTest() : GLES2DecoderWithShaderTest() {}
|
| +
|
| + virtual void SetUp() {
|
| + InitState init;
|
| + init.extensions = "GL_ANGLE_instanced_arrays";
|
| + init.gl_version = "opengl es 2.0";
|
| + init.has_alpha = true;
|
| + init.has_depth = true;
|
| + init.request_alpha = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + SetupDefaultProgram();
|
| + }
|
| +};
|
| +
|
| +// Test that with an RGB backbuffer if we set the color mask to 1,1,1,1 it is
|
| +// set to 1,1,1,0 at Draw time but is 1,1,1,1 at query time.
|
| +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMask) {
|
| + ColorMask cmd;
|
| + cmd.Init(true, true, true, true);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_COLOR_WRITEMASK, result->GetData()))
|
| + .Times(0);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_COLOR_WRITEMASK, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(
|
| + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_COLOR_WRITEMASK),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(1, result->GetData()[0]);
|
| + EXPECT_EQ(1, result->GetData()[1]);
|
| + EXPECT_EQ(1, result->GetData()[2]);
|
| + EXPECT_EQ(1, result->GetData()[3]);
|
| +}
|
| +
|
| +// Test that with no depth if we set DepthMask true that it's set to false at
|
| +// draw time but querying it returns true.
|
| +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferDepthMask) {
|
| + EXPECT_CALL(*gl_, DepthMask(true)).Times(0).RetiresOnSaturation();
|
| + DepthMask cmd;
|
| + cmd.Init(true);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_WRITEMASK, result->GetData()))
|
| + .Times(0);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_DEPTH_WRITEMASK, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(
|
| + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_WRITEMASK),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(1, result->GetData()[0]);
|
| +}
|
| +
|
| +// Test that with no stencil if we set the stencil mask it's still set to 0 at
|
| +// draw time but gets our value if we query.
|
| +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferStencilMask) {
|
| + const GLint kMask = 123;
|
| + EXPECT_CALL(*gl_, StencilMask(kMask)).Times(0).RetiresOnSaturation();
|
| + StencilMask cmd;
|
| + cmd.Init(kMask);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_WRITEMASK, result->GetData()))
|
| + .Times(0);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_WRITEMASK, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(
|
| + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_WRITEMASK),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(kMask, result->GetData()[0]);
|
| +}
|
| +
|
| +// Test that if an FBO is bound we get the correct masks.
|
| +TEST_F(GLES2DecoderRGBBackbufferTest, RGBBackbufferColorMaskFBO) {
|
| + ColorMask cmd;
|
| + cmd.Init(true, true, true, true);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + DoEnableVertexAttribArray(2);
|
| + DoVertexAttribPointer(2, 2, GL_FLOAT, 0, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Check that no extra calls are made on the next draw.
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Setup Frame buffer.
|
| + // needs to be 1x1 or else it's not renderable.
|
| + const GLsizei kWidth = 1;
|
| + const GLsizei kHeight = 1;
|
| + const GLenum kFormat = GL_RGB;
|
| + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
|
| + // Pass some data so the texture will be marked as cleared.
|
| + DoTexImage2D(GL_TEXTURE_2D,
|
| + 0,
|
| + kFormat,
|
| + kWidth,
|
| + kHeight,
|
| + 0,
|
| + kFormat,
|
| + GL_UNSIGNED_BYTE,
|
| + kSharedMemoryId,
|
| + kSharedMemoryOffset);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + client_texture_id_,
|
| + kServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
|
| + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
|
| + .RetiresOnSaturation();
|
| +
|
| + // This time state needs to be set.
|
| + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Check that no extra calls are made on the next draw.
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Unbind
|
| + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0);
|
| +
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, DepthEnableWithDepth) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_depth = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + Enable cmd;
|
| + cmd.Init(GL_DEPTH_TEST);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupDefaultProgram();
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + true, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + true, // depth mask
|
| + true, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(1, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + Enable cmd;
|
| + cmd.Init(GL_DEPTH_TEST);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupDefaultProgram();
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_TEST, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_DEPTH_TEST, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_TEST),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(1, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, StencilEnableWithStencil) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_stencil = true;
|
| + init.request_stencil = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + Enable cmd;
|
| + cmd.Init(GL_STENCIL_TEST);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupDefaultProgram();
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + true, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + -1, // front stencil mask
|
| + -1, // back stencil mask
|
| + true, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(1, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_stencil = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + Enable cmd;
|
| + cmd.Init(GL_STENCIL_TEST);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + SetupDefaultProgram();
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(true, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1110, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays draw_cmd;
|
| + draw_cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(draw_cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_TEST, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_TEST, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_TEST),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(1, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) {
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// Tests when the math overflows (0x40000000 * sizeof GLfloat)
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OverflowFails) {
|
| + const GLsizei kLargeCount = 0x40000000;
|
| + SetupTexture();
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kLargeCount);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| + EXPECT_FALSE(GetDecoder()->WasContextLost());
|
| +}
|
| +
|
| +// Tests when the math overflows (0x7FFFFFFF + 1 = 0x8000000 verts)
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0PosToNegFails) {
|
| + const GLsizei kLargeCount = 0x7FFFFFFF;
|
| + SetupTexture();
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kLargeCount);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| + EXPECT_FALSE(GetDecoder()->WasContextLost());
|
| +}
|
| +
|
| +// Tests when the driver returns an error
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysSimulatedAttrib0OOMFails) {
|
| + const GLsizei kFakeLargeCount = 0x1234;
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0WithError(
|
| + kFakeLargeCount, 0, GL_OUT_OF_MEMORY);
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| + EXPECT_FALSE(GetDecoder()->WasContextLost());
|
| +}
|
| +
|
| +// Test that we lose context.
|
| +TEST_F(GLES2DecoderManualInitTest, LoseContextWhenOOM) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_alpha = true;
|
| + init.has_depth = true;
|
| + init.request_alpha = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + init.lose_context_when_out_of_memory = true;
|
| + InitDecoder(init);
|
| + SetupDefaultProgram();
|
| +
|
| + const GLsizei kFakeLargeCount = 0x1234;
|
| + SetupTexture();
|
| + 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_, LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount);
|
| + // This context should be lost.
|
| + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| + EXPECT_TRUE(decoder_->WasContextLost());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysBadTextureUsesBlack) {
|
| + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
|
| + // This is an NPOT texture. As the default filtering requires mips
|
| + // this should trigger replacing with black textures before rendering.
|
| + DoTexImage2D(GL_TEXTURE_2D,
|
| + 0,
|
| + GL_RGBA,
|
| + 3,
|
| + 1,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + kSharedMemoryId,
|
| + kSharedMemoryOffset);
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + {
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(
|
| + *gl_, BindTexture(GL_TEXTURE_2D, TestHelper::kServiceBlackTexture2dId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + }
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysMissingAttributesFails) {
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0);
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + DrawArraysMissingAttributesZeroCountSucceeds) {
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0);
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysValidAttributesSucceeds) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// Same as DrawArraysValidAttributesSucceeds, but with workaround
|
| +// |init_vertex_attributes|.
|
| +TEST_F(GLES2DecoderManualInitTest, InitVertexAttributes) {
|
| + CommandLine command_line(0, NULL);
|
| + command_line.AppendSwitchASCII(
|
| + switches::kGpuDriverBugWorkarounds,
|
| + base::IntToString(gpu::INIT_VERTEX_ATTRIBUTES));
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_alpha = true;
|
| + init.has_depth = true;
|
| + init.request_alpha = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoderWithCommandLine(init, &command_line);
|
| + SetupDefaultProgram();
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysDeletedBufferFails) {
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + DeleteVertexBuffer();
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0);
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysDeletedProgramSucceeds) {
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoDeleteProgram(client_program_id_, kServiceProgramId);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)).Times(1);
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysWithInvalidModeFails) {
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0);
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_QUADS, 0, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| + cmd.Init(GL_POLYGON, 0, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysInvalidCountFails) {
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + // Try start > 0
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0);
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 1, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Try with count > size
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Try with attrib offset > 0
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 4);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Try with size > 2 (ie, vec3 instead of vec2)
|
| + DoVertexAttribPointer(1, 3, GL_FLOAT, 0, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Try with stride > 8 (vec2 + vec2 byte)
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, sizeof(GLfloat) * 3, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysInstancedANGLEFails) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLENoAttributesFails) {
|
| + SetupTexture();
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLESimulatedAttrib0) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 3))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 3);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLEMissingAttributesFails) {
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0);
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLEMissingAttributesZeroCountSucceeds) {
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0);
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, 0, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLEValidAttributesSucceeds) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLEWithInvalidModeFails) {
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0);
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_QUADS, 0, 1, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| + cmd.Init(GL_POLYGON, 0, 1, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLEInvalidPrimcountFails) {
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _)).Times(0);
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, 1, -1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| +}
|
| +
|
| +// Per-instance data is twice as large, but number of instances is half
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLELargeInstanceSucceeds) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, kNumVertices / 2))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices / 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// Per-instance data is twice as large, but divisor is twice
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLELargeDivisorSucceeds) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 2);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest, DrawArraysInstancedANGLELargeFails) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, kNumVertices + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices + 1, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// Per-index data is twice as large, but number of indices is half
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLELargeIndexSucceeds) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoVertexAttribPointer(1, 4, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices / 2, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices / 2, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawArraysInstancedANGLENoDivisor0Fails) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + DoVertexAttribDivisorANGLE(1, 1);
|
| + EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(_, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawArraysInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsNoAttributesSucceeds) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + EXPECT_CALL(*gl_,
|
| + DrawElements(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2)))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsMissingAttributesFails) {
|
| + SetupIndexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + DrawElementsMissingAttributesZeroCountSucceeds) {
|
| + SetupIndexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsExtraAttributesFails) {
|
| + SetupIndexBuffer();
|
| + DoEnableVertexAttribArray(6);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsValidAttributesSucceeds) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(*gl_,
|
| + DrawElements(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2)))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsDeletedBufferFails) {
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + DeleteIndexBuffer();
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsDeletedProgramSucceeds) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, 0);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoDeleteProgram(client_program_id_, kServiceProgramId);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1);
|
| + EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)).Times(1);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsWithInvalidModeFails) {
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_QUADS,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| + cmd.Init(GL_POLYGON,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsInvalidCountFails) {
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + // Try start > 0
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES, kNumIndices, GL_UNSIGNED_SHORT, 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // Try with count > size
|
| + cmd.Init(GL_TRIANGLES, kNumIndices + 1, GL_UNSIGNED_SHORT, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsOutOfRangeIndicesFails) {
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kInvalidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kInvalidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsOddOffsetForUint16Fails) {
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES, kInvalidIndexRangeCount, GL_UNSIGNED_SHORT, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsInstancedANGLEFails) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLENoAttributesFails) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| +
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLESimulatedAttrib0) {
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + SetupIndexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawElementsInstancedANGLE(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2),
|
| + 3))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 3);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLEMissingAttributesFails) {
|
| + SetupIndexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)).Times(0);
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLEMissingAttributesZeroCountSucceeds) {
|
| + SetupIndexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)).Times(0);
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, kValidIndexRangeStart * 2, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLEValidAttributesSucceeds) {
|
| + SetupIndexBuffer();
|
| + SetupTexture();
|
| + SetupVertexBuffer();
|
| + DoEnableVertexAttribArray(1);
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| + AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawElementsInstancedANGLE(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2),
|
| + 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLEWithInvalidModeFails) {
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _)).Times(0);
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_QUADS,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| + cmd.Init(GL_INVALID_ENUM,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| +}
|
| +
|
| +// Per-instance data is twice as large, but number of instances is half
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLELargeInstanceSucceeds) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + // Add offset so we're sure we're accessing data near the end of the buffer.
|
| + DoVertexAttribPointer(
|
| + 1,
|
| + 2,
|
| + GL_FLOAT,
|
| + 0,
|
| + (kNumVertices - kMaxValidIndex - 1) * 2 * sizeof(GLfloat));
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawElementsInstancedANGLE(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2),
|
| + kNumVertices / 2))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + kNumVertices / 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// Per-instance data is twice as large, but divisor is twice
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLELargeDivisorSucceeds) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 4, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 2);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawElementsInstancedANGLE(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2),
|
| + kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLELargeFails) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + kNumVertices + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + cmd.Init(GL_TRIANGLES,
|
| + kInvalidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kInvalidIndexRangeStart * 2,
|
| + kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLEInvalidPrimcountFails) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + -1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// Per-index data is twice as large, but values of indices are smaller
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLELargeIndexSucceeds) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoVertexAttribPointer(1, 4, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + DrawElementsInstancedANGLE(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2),
|
| + kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderGeometryInstancingTest,
|
| + DrawElementsInstancedANGLENoDivisor0Fails) {
|
| + SetupTexture();
|
| + SetupIndexBuffer();
|
| + SetupVertexBuffer();
|
| + DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
|
| +
|
| + DoEnableVertexAttribArray(0);
|
| + DoVertexAttribPointer(0, 2, GL_FLOAT, 0, 0);
|
| + DoVertexAttribDivisorANGLE(0, 1);
|
| + DoVertexAttribDivisorANGLE(1, 1);
|
| + EXPECT_CALL(*gl_, DrawElementsInstancedANGLE(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + DrawElementsInstancedANGLE cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2,
|
| + kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawArraysClearsAfterTexImage2DNULL) {
|
| + SetupAllNeededVertexBuffers();
|
| + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
|
| + // Create an uncleared texture with 2 levels.
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + // Expect 2 levels will be cleared.
|
| + SetupClearTextureExpectations(kServiceTextureId,
|
| + kServiceTextureId,
|
| + GL_TEXTURE_2D,
|
| + GL_TEXTURE_2D,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + 2,
|
| + 2);
|
| + SetupClearTextureExpectations(kServiceTextureId,
|
| + kServiceTextureId,
|
| + GL_TEXTURE_2D,
|
| + GL_TEXTURE_2D,
|
| + 1,
|
| + GL_RGBA,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + 1,
|
| + 1);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // But not again
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawElementsClearsAfterTexImage2DNULL) {
|
| + SetupAllNeededVertexBuffers();
|
| + SetupIndexBuffer();
|
| + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
|
| + // Create an uncleared texture with 2 levels.
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + // Expect 2 levels will be cleared.
|
| + SetupClearTextureExpectations(kServiceTextureId,
|
| + kServiceTextureId,
|
| + GL_TEXTURE_2D,
|
| + GL_TEXTURE_2D,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + 2,
|
| + 2);
|
| + SetupClearTextureExpectations(kServiceTextureId,
|
| + kServiceTextureId,
|
| + GL_TEXTURE_2D,
|
| + GL_TEXTURE_2D,
|
| + 1,
|
| + GL_RGBA,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + 1,
|
| + 1);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| +
|
| + EXPECT_CALL(*gl_,
|
| + DrawElements(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2)))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawElements cmd;
|
| + cmd.Init(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + kValidIndexRangeStart * 2);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // But not again
|
| + EXPECT_CALL(*gl_,
|
| + DrawElements(GL_TRIANGLES,
|
| + kValidIndexRangeCount,
|
| + GL_UNSIGNED_SHORT,
|
| + BufferOffset(kValidIndexRangeStart * 2)))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawClearsAfterTexImage2DNULLInFBO) {
|
| + const GLuint kFBOClientTextureId = 4100;
|
| + const GLuint kFBOServiceTextureId = 4101;
|
| +
|
| + SetupAllNeededVertexBuffers();
|
| + // Register a texture id.
|
| + EXPECT_CALL(*gl_, GenTextures(_, _))
|
| + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
|
| + .RetiresOnSaturation();
|
| + GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
|
| +
|
| + // Setup "render to" texture.
|
| + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId);
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kFBOClientTextureId,
|
| + kFBOServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| +
|
| + // Setup "render from" texture.
|
| + SetupTexture();
|
| +
|
| + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target
|
| + GL_COLOR_BUFFER_BIT, // clear bits
|
| + 0,
|
| + 0,
|
| + 0,
|
| + 0, // color
|
| + 0, // stencil
|
| + 1.0f, // depth
|
| + false); // scissor test
|
| +
|
| + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1111, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // But not again.
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawWitFBOThatCantClearDoesNotDraw) {
|
| + const GLuint kFBOClientTextureId = 4100;
|
| + const GLuint kFBOServiceTextureId = 4101;
|
| +
|
| + // Register a texture id.
|
| + EXPECT_CALL(*gl_, GenTextures(_, _))
|
| + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
|
| + .RetiresOnSaturation();
|
| + GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
|
| +
|
| + // Setup "render to" texture.
|
| + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId);
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kFBOClientTextureId,
|
| + kFBOServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| +
|
| + // Setup "render from" texture.
|
| + SetupTexture();
|
| +
|
| + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
|
| + .WillOnce(Return(GL_FRAMEBUFFER_UNSUPPORTED))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, DrawClearsAfterRenderbufferStorageInFBO) {
|
| + SetupTexture();
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoRenderbufferStorage(
|
| + GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 100, 50, GL_NO_ERROR);
|
| + DoFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_,
|
| + kServiceRenderbufferId,
|
| + GL_NO_ERROR);
|
| +
|
| + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target
|
| + GL_COLOR_BUFFER_BIT, // clear bits
|
| + 0,
|
| + 0,
|
| + 0,
|
| + 0, // color
|
| + 0, // stencil
|
| + 1.0f, // depth
|
| + false); // scissor test
|
| +
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1111, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, DrawArraysClearsAfterTexImage2DNULLCubemap) {
|
| + InitState init;
|
| + init.gl_version = "opengl es 2.0";
|
| + init.has_alpha = true;
|
| + init.has_depth = true;
|
| + init.request_alpha = true;
|
| + init.request_depth = true;
|
| + InitDecoder(init);
|
| +
|
| + static const GLenum faces[] = {
|
| + GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
| + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
| + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
| + };
|
| + SetupCubemapProgram();
|
| + DoBindTexture(GL_TEXTURE_CUBE_MAP, client_texture_id_, kServiceTextureId);
|
| + // Fill out all the faces for 2 levels, leave 2 uncleared.
|
| + for (int ii = 0; ii < 6; ++ii) {
|
| + GLenum face = faces[ii];
|
| + int32 shm_id =
|
| + (face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ? 0 : kSharedMemoryId;
|
| + uint32 shm_offset =
|
| + (face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ? 0 : kSharedMemoryOffset;
|
| + DoTexImage2D(face,
|
| + 0,
|
| + GL_RGBA,
|
| + 2,
|
| + 2,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + shm_id,
|
| + shm_offset);
|
| + DoTexImage2D(face,
|
| + 1,
|
| + GL_RGBA,
|
| + 1,
|
| + 1,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + shm_id,
|
| + shm_offset);
|
| + }
|
| + // Expect 2 levels will be cleared.
|
| + SetupClearTextureExpectations(kServiceTextureId,
|
| + kServiceTextureId,
|
| + GL_TEXTURE_CUBE_MAP,
|
| + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + 2,
|
| + 2);
|
| + SetupClearTextureExpectations(kServiceTextureId,
|
| + kServiceTextureId,
|
| + GL_TEXTURE_CUBE_MAP,
|
| + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
| + 1,
|
| + GL_RGBA,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + 1,
|
| + 1);
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + DrawClearsAfterRenderbuffersWithMultipleAttachments) {
|
| + const GLuint kFBOClientTextureId = 4100;
|
| + const GLuint kFBOServiceTextureId = 4101;
|
| +
|
| + // Register a texture id.
|
| + EXPECT_CALL(*gl_, GenTextures(_, _))
|
| + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
|
| + .RetiresOnSaturation();
|
| + GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
|
| +
|
| + // Setup "render to" texture.
|
| + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId);
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kFBOClientTextureId,
|
| + kFBOServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| +
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoRenderbufferStorage(GL_RENDERBUFFER,
|
| + GL_DEPTH_COMPONENT16,
|
| + GL_DEPTH_COMPONENT,
|
| + 1,
|
| + 1,
|
| + GL_NO_ERROR);
|
| + DoFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
| + GL_DEPTH_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_,
|
| + kServiceRenderbufferId,
|
| + GL_NO_ERROR);
|
| +
|
| + SetupTexture();
|
| + SetupExpectationsForFramebufferClearing(
|
| + GL_FRAMEBUFFER, // target
|
| + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, // clear bits
|
| + 0,
|
| + 0,
|
| + 0,
|
| + 0, // color
|
| + 0, // stencil
|
| + 1.0f, // depth
|
| + false); // scissor test
|
| +
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB
|
| + true, // 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
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + DrawingWithFBOTwiceChecksForFBOCompleteOnce) {
|
| + const GLuint kFBOClientTextureId = 4100;
|
| + const GLuint kFBOServiceTextureId = 4101;
|
| +
|
| + SetupAllNeededVertexBuffers();
|
| +
|
| + // Register a texture id.
|
| + EXPECT_CALL(*gl_, GenTextures(_, _))
|
| + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
|
| + .RetiresOnSaturation();
|
| + GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
|
| +
|
| + // Setup "render to" texture that is cleared.
|
| + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId);
|
| + DoTexImage2D(GL_TEXTURE_2D,
|
| + 0,
|
| + GL_RGBA,
|
| + 1,
|
| + 1,
|
| + 0,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + kSharedMemoryId,
|
| + kSharedMemoryOffset);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kFBOClientTextureId,
|
| + kFBOServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| +
|
| + // Setup "render from" texture.
|
| + SetupTexture();
|
| +
|
| + // Make sure we check for framebuffer complete.
|
| + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
|
| + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
|
| + .RetiresOnSaturation();
|
| +
|
| + SetupExpectationsForApplyingDirtyState(false, // Framebuffer is RGB
|
| + false, // Framebuffer has depth
|
| + false, // Framebuffer has stencil
|
| + 0x1111, // color bits
|
| + false, // depth mask
|
| + false, // depth enabled
|
| + 0, // front stencil mask
|
| + 0, // back stencil mask
|
| + false, // stencil enabled
|
| + false, // cull_face_enabled
|
| + false, // scissor_test_enabled
|
| + false); // blend_enabled
|
| +
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + // But not again.
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, DrawClearsDepthTexture) {
|
| + InitState init;
|
| + init.extensions = "GL_ANGLE_depth_texture";
|
| + init.gl_version = "opengl es 2.0";
|
| + init.has_alpha = true;
|
| + init.has_depth = true;
|
| + init.request_alpha = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + SetupDefaultProgram();
|
| + SetupAllNeededVertexBuffers();
|
| + const GLenum attachment = GL_DEPTH_ATTACHMENT;
|
| + const GLenum target = GL_TEXTURE_2D;
|
| + const GLint level = 0;
|
| + DoBindTexture(target, client_texture_id_, kServiceTextureId);
|
| +
|
| + // Create a depth texture.
|
| + DoTexImage2D(target,
|
| + level,
|
| + GL_DEPTH_COMPONENT,
|
| + 1,
|
| + 1,
|
| + 0,
|
| + GL_DEPTH_COMPONENT,
|
| + GL_UNSIGNED_INT,
|
| + 0,
|
| + 0);
|
| +
|
| + EXPECT_CALL(*gl_, GenFramebuffersEXT(1, _)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| +
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT,
|
| + attachment,
|
| + target,
|
| + kServiceTextureId,
|
| + level))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT))
|
| + .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
|
| + .RetiresOnSaturation();
|
| +
|
| + EXPECT_CALL(*gl_, ClearStencil(0)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, StencilMask(-1)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, ClearDepth(1.0f)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, DepthMask(true)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, Disable(GL_SCISSOR_TEST)).Times(1).RetiresOnSaturation();
|
| +
|
| + EXPECT_CALL(*gl_, Clear(GL_DEPTH_BUFFER_BIT)).Times(1).RetiresOnSaturation();
|
| +
|
| + SetupExpectationsForRestoreClearState(0.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, false);
|
| +
|
| + EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| +
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DrawArrays cmd;
|
| + cmd.Init(GL_TRIANGLES, 0, kNumVertices);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +} // namespace gles2
|
| +} // namespace gpu
|
|
|