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 |