| Index: gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
|
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..dea7e7f584bff881d5e1d14deb7bfe16312e62c2
|
| --- /dev/null
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
|
| @@ -0,0 +1,2219 @@
|
| +// 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 GLES2DecoderTestWithExtensionsOnGLES2
|
| + : public GLES2DecoderTest,
|
| + public ::testing::WithParamInterface<const char*> {
|
| + public:
|
| + GLES2DecoderTestWithExtensionsOnGLES2() {}
|
| +
|
| + virtual void SetUp() {
|
| + InitState init;
|
| + init.extensions = GetParam();
|
| + 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);
|
| + }
|
| +};
|
| +
|
| +TEST_F(GLES2DecoderTest, CheckFramebufferStatusWithNoBoundTarget) {
|
| + EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)).Times(0);
|
| + CheckFramebufferStatus::Result* result =
|
| + static_cast<CheckFramebufferStatus::Result*>(shared_memory_address_);
|
| + *result = 0;
|
| + CheckFramebufferStatus cmd;
|
| + cmd.Init(GL_FRAMEBUFFER, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), *result);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, BindAndDeleteFramebuffer) {
|
| + SetupTexture();
|
| + AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
|
| + SetupExpectationsForApplyingDefaultDirtyState();
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoDeleteFramebuffer(client_framebuffer_id_,
|
| + kServiceFramebufferId,
|
| + true,
|
| + GL_FRAMEBUFFER,
|
| + 0,
|
| + true,
|
| + GL_FRAMEBUFFER,
|
| + 0);
|
| + 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(GLES2DecoderTest, FramebufferRenderbufferWithNoBoundTarget) {
|
| + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(_, _, _, _)).Times(0);
|
| + FramebufferRenderbuffer cmd;
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, FramebufferTexture2DWithNoBoundTarget) {
|
| + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0);
|
| + FramebufferTexture2D cmd;
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + client_texture_id_,
|
| + 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithNoBoundTarget) {
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetFramebufferAttachmentParameterivEXT(_, _, _, _))
|
| + .Times(0);
|
| + GetFramebufferAttachmentParameteriv cmd;
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithRenderbuffer) {
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + GetFramebufferAttachmentParameteriv::Result* result =
|
| + static_cast<GetFramebufferAttachmentParameteriv::Result*>(
|
| + shared_memory_address_);
|
| + result->size = 0;
|
| + const GLint* result_value = result->GetData();
|
| + FramebufferRenderbuffer fbrb_cmd;
|
| + GetFramebufferAttachmentParameteriv cmd;
|
| + fbrb_cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(static_cast<GLuint>(*result_value), client_renderbuffer_id_);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithTexture) {
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferTexture2DEXT(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kServiceTextureId,
|
| + 0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + GetFramebufferAttachmentParameteriv::Result* result =
|
| + static_cast<GetFramebufferAttachmentParameteriv::Result*>(
|
| + shared_memory_address_);
|
| + result->SetNumResults(0);
|
| + const GLint* result_value = result->GetData();
|
| + FramebufferTexture2D fbtex_cmd;
|
| + GetFramebufferAttachmentParameteriv cmd;
|
| + fbtex_cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + client_texture_id_,
|
| + 0);
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(static_cast<GLuint>(*result_value), client_texture_id_);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, GetRenderbufferParameterivWithNoBoundTarget) {
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetRenderbufferParameterivEXT(_, _, _)).Times(0);
|
| + GetRenderbufferParameteriv cmd;
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + GL_RENDERBUFFER_WIDTH,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, RenderbufferStorageWithNoBoundTarget) {
|
| + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _)).Times(0);
|
| + RenderbufferStorage cmd;
|
| + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 3, 4);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +// A class to emulate glReadPixels
|
| +class ReadPixelsEmulator {
|
| + public:
|
| + // pack_alignment is the alignment you want ReadPixels to use
|
| + // when copying. The actual data passed in pixels should be contiguous.
|
| + ReadPixelsEmulator(GLsizei width,
|
| + GLsizei height,
|
| + GLint bytes_per_pixel,
|
| + const void* src_pixels,
|
| + const void* expected_pixels,
|
| + GLint pack_alignment)
|
| + : width_(width),
|
| + height_(height),
|
| + pack_alignment_(pack_alignment),
|
| + bytes_per_pixel_(bytes_per_pixel),
|
| + src_pixels_(reinterpret_cast<const int8*>(src_pixels)),
|
| + expected_pixels_(reinterpret_cast<const int8*>(expected_pixels)) {}
|
| +
|
| + void ReadPixels(GLint x,
|
| + GLint y,
|
| + GLsizei width,
|
| + GLsizei height,
|
| + GLenum format,
|
| + GLenum type,
|
| + void* pixels) const {
|
| + DCHECK_GE(x, 0);
|
| + DCHECK_GE(y, 0);
|
| + DCHECK_LE(x + width, width_);
|
| + DCHECK_LE(y + height, height_);
|
| + for (GLint yy = 0; yy < height; ++yy) {
|
| + const int8* src = GetPixelAddress(src_pixels_, x, y + yy);
|
| + const void* dst = ComputePackAlignmentAddress(0, yy, width, pixels);
|
| + memcpy(const_cast<void*>(dst), src, width * bytes_per_pixel_);
|
| + }
|
| + }
|
| +
|
| + bool CompareRowSegment(GLint x,
|
| + GLint y,
|
| + GLsizei width,
|
| + const void* data) const {
|
| + DCHECK(x + width <= width_ || width == 0);
|
| + return memcmp(data,
|
| + GetPixelAddress(expected_pixels_, x, y),
|
| + width * bytes_per_pixel_) == 0;
|
| + }
|
| +
|
| + // Helper to compute address of pixel in pack aligned data.
|
| + const void* ComputePackAlignmentAddress(GLint x,
|
| + GLint y,
|
| + GLsizei width,
|
| + const void* address) const {
|
| + GLint unpadded_row_size = ComputeImageDataSize(width, 1);
|
| + GLint two_rows_size = ComputeImageDataSize(width, 2);
|
| + GLsizei padded_row_size = two_rows_size - unpadded_row_size;
|
| + GLint offset = y * padded_row_size + x * bytes_per_pixel_;
|
| + return static_cast<const int8*>(address) + offset;
|
| + }
|
| +
|
| + GLint ComputeImageDataSize(GLint width, GLint height) const {
|
| + GLint row_size = width * bytes_per_pixel_;
|
| + if (height > 1) {
|
| + GLint temp = row_size + pack_alignment_ - 1;
|
| + GLint padded_row_size = (temp / pack_alignment_) * pack_alignment_;
|
| + GLint size_of_all_but_last_row = (height - 1) * padded_row_size;
|
| + return size_of_all_but_last_row + row_size;
|
| + } else {
|
| + return height * row_size;
|
| + }
|
| + }
|
| +
|
| + private:
|
| + const int8* GetPixelAddress(const int8* base, GLint x, GLint y) const {
|
| + return base + (width_ * y + x) * bytes_per_pixel_;
|
| + }
|
| +
|
| + GLsizei width_;
|
| + GLsizei height_;
|
| + GLint pack_alignment_;
|
| + GLint bytes_per_pixel_;
|
| + const int8* src_pixels_;
|
| + const int8* expected_pixels_;
|
| +};
|
| +
|
| +} // anonymous namespace
|
| +
|
| +void GLES2DecoderTest::CheckReadPixelsOutOfRange(GLint in_read_x,
|
| + GLint in_read_y,
|
| + GLsizei in_read_width,
|
| + GLsizei in_read_height,
|
| + bool init) {
|
| + const GLsizei kWidth = 5;
|
| + const GLsizei kHeight = 3;
|
| + const GLint kBytesPerPixel = 3;
|
| + const GLint kPackAlignment = 4;
|
| + const GLenum kFormat = GL_RGB;
|
| + static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = {
|
| + 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13,
|
| + 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28,
|
| + 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34,
|
| + };
|
| +
|
| + ClearSharedMemory();
|
| +
|
| + // We need to setup an FBO so we can know the max size that ReadPixels will
|
| + // access
|
| + if (init) {
|
| + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
|
| + 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();
|
| + }
|
| +
|
| + ReadPixelsEmulator emu(
|
| + kWidth, kHeight, kBytesPerPixel, kSrcPixels, kSrcPixels, kPackAlignment);
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| + void* dest = &result[1];
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + // ReadPixels will be called for valid size only even though the command
|
| + // is requesting a larger size.
|
| + GLint read_x = std::max(0, in_read_x);
|
| + GLint read_y = std::max(0, in_read_y);
|
| + GLint read_end_x = std::max(0, std::min(kWidth, in_read_x + in_read_width));
|
| + GLint read_end_y = std::max(0, std::min(kHeight, in_read_y + in_read_height));
|
| + GLint read_width = read_end_x - read_x;
|
| + GLint read_height = read_end_y - read_y;
|
| + if (read_width > 0 && read_height > 0) {
|
| + for (GLint yy = read_y; yy < read_end_y; ++yy) {
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + ReadPixels(read_x, yy, read_width, 1, kFormat, GL_UNSIGNED_BYTE, _))
|
| + .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels))
|
| + .RetiresOnSaturation();
|
| + }
|
| + }
|
| + ReadPixels cmd;
|
| + cmd.Init(in_read_x,
|
| + in_read_y,
|
| + in_read_width,
|
| + in_read_height,
|
| + kFormat,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +
|
| + GLint unpadded_row_size = emu.ComputeImageDataSize(in_read_width, 1);
|
| + scoped_ptr<int8[]> zero(new int8[unpadded_row_size]);
|
| + scoped_ptr<int8[]> pack(new int8[kPackAlignment]);
|
| + memset(zero.get(), 0, unpadded_row_size);
|
| + memset(pack.get(), kInitialMemoryValue, kPackAlignment);
|
| + for (GLint yy = 0; yy < in_read_height; ++yy) {
|
| + const int8* row = static_cast<const int8*>(
|
| + emu.ComputePackAlignmentAddress(0, yy, in_read_width, dest));
|
| + GLint y = in_read_y + yy;
|
| + if (y < 0 || y >= kHeight) {
|
| + EXPECT_EQ(0, memcmp(zero.get(), row, unpadded_row_size));
|
| + } else {
|
| + // check off left.
|
| + GLint num_left_pixels = std::max(-in_read_x, 0);
|
| + GLint num_left_bytes = num_left_pixels * kBytesPerPixel;
|
| + EXPECT_EQ(0, memcmp(zero.get(), row, num_left_bytes));
|
| +
|
| + // check off right.
|
| + GLint num_right_pixels = std::max(in_read_x + in_read_width - kWidth, 0);
|
| + GLint num_right_bytes = num_right_pixels * kBytesPerPixel;
|
| + EXPECT_EQ(0,
|
| + memcmp(zero.get(),
|
| + row + unpadded_row_size - num_right_bytes,
|
| + num_right_bytes));
|
| +
|
| + // check middle.
|
| + GLint x = std::max(in_read_x, 0);
|
| + GLint num_middle_pixels =
|
| + std::max(in_read_width - num_left_pixels - num_right_pixels, 0);
|
| + EXPECT_TRUE(
|
| + emu.CompareRowSegment(x, y, num_middle_pixels, row + num_left_bytes));
|
| + }
|
| +
|
| + // check padding
|
| + if (yy != in_read_height - 1) {
|
| + GLint num_padding_bytes =
|
| + (kPackAlignment - 1) - (unpadded_row_size % kPackAlignment);
|
| + EXPECT_EQ(0,
|
| + memcmp(pack.get(), row + unpadded_row_size, num_padding_bytes));
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, ReadPixels) {
|
| + const GLsizei kWidth = 5;
|
| + const GLsizei kHeight = 3;
|
| + const GLint kBytesPerPixel = 3;
|
| + const GLint kPackAlignment = 4;
|
| + static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = {
|
| + 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13,
|
| + 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28,
|
| + 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34,
|
| + };
|
| +
|
| + surface_->SetSize(gfx::Size(INT_MAX, INT_MAX));
|
| +
|
| + ReadPixelsEmulator emu(
|
| + kWidth, kHeight, kBytesPerPixel, kSrcPixels, kSrcPixels, kPackAlignment);
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| + void* dest = &result[1];
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _))
|
| + .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels));
|
| + ReadPixels cmd;
|
| + cmd.Init(0,
|
| + 0,
|
| + kWidth,
|
| + kHeight,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + for (GLint yy = 0; yy < kHeight; ++yy) {
|
| + EXPECT_TRUE(emu.CompareRowSegment(
|
| + 0, yy, kWidth, emu.ComputePackAlignmentAddress(0, yy, kWidth, dest)));
|
| + }
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderRGBBackbufferTest, ReadPixelsNoAlphaBackbuffer) {
|
| + const GLsizei kWidth = 3;
|
| + const GLsizei kHeight = 3;
|
| + const GLint kBytesPerPixel = 4;
|
| + const GLint kPackAlignment = 4;
|
| + static const uint8 kExpectedPixels[kWidth * kHeight * kBytesPerPixel] = {
|
| + 12, 13, 14, 255, 19, 18, 19, 255, 13, 14, 18, 255,
|
| + 29, 28, 23, 255, 21, 22, 21, 255, 28, 23, 22, 255,
|
| + 31, 34, 39, 255, 32, 37, 32, 255, 34, 39, 37, 255,
|
| + };
|
| + static const uint8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = {
|
| + 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 29, 28, 23, 22, 21, 22,
|
| + 21, 29, 28, 23, 22, 21, 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32,
|
| + };
|
| +
|
| + surface_->SetSize(gfx::Size(INT_MAX, INT_MAX));
|
| +
|
| + ReadPixelsEmulator emu(kWidth,
|
| + kHeight,
|
| + kBytesPerPixel,
|
| + kSrcPixels,
|
| + kExpectedPixels,
|
| + kPackAlignment);
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| + void* dest = &result[1];
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + ReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, _))
|
| + .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels));
|
| + ReadPixels cmd;
|
| + cmd.Init(0,
|
| + 0,
|
| + kWidth,
|
| + kHeight,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + for (GLint yy = 0; yy < kHeight; ++yy) {
|
| + EXPECT_TRUE(emu.CompareRowSegment(
|
| + 0, yy, kWidth, emu.ComputePackAlignmentAddress(0, yy, kWidth, dest)));
|
| + }
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, ReadPixelsOutOfRange) {
|
| + static GLint tests[][4] = {
|
| + {
|
| + -2, -1, 9, 5,
|
| + }, // out of range on all sides
|
| + {
|
| + 2, 1, 9, 5,
|
| + }, // out of range on right, bottom
|
| + {
|
| + -7, -4, 9, 5,
|
| + }, // out of range on left, top
|
| + {
|
| + 0, -5, 9, 5,
|
| + }, // completely off top
|
| + {
|
| + 0, 3, 9, 5,
|
| + }, // completely off bottom
|
| + {
|
| + -9, 0, 9, 5,
|
| + }, // completely off left
|
| + {
|
| + 5, 0, 9, 5,
|
| + }, // completely off right
|
| + };
|
| +
|
| + for (size_t tt = 0; tt < arraysize(tests); ++tt) {
|
| + CheckReadPixelsOutOfRange(
|
| + tests[tt][0], tests[tt][1], tests[tt][2], tests[tt][3], tt == 0);
|
| + }
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, ReadPixelsInvalidArgs) {
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| + EXPECT_CALL(*gl_, ReadPixels(_, _, _, _, _, _, _)).Times(0);
|
| + ReadPixels cmd;
|
| + cmd.Init(0,
|
| + 0,
|
| + -1,
|
| + 1,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + -1,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGB,
|
| + GL_INT,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + kInvalidSharedMemoryId,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + kInvalidSharedMemoryOffset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + kInvalidSharedMemoryId,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + kInvalidSharedMemoryOffset,
|
| + false);
|
| + EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ReadPixelsAsyncError) {
|
| + InitState init;
|
| + init.extensions = "GL_ARB_sync";
|
| + init.gl_version = "opengl es 3.0";
|
| + init.has_alpha = true;
|
| + init.request_alpha = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| +
|
| + const GLsizei kWidth = 4;
|
| + const GLsizei kHeight = 4;
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + // first error check must pass to get to the test
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + // second check is after BufferData, simulate fail here
|
| + .WillOnce(Return(GL_INVALID_OPERATION))
|
| + // third error check is fall-through call to sync ReadPixels
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| +
|
| + EXPECT_CALL(*gl_,
|
| + ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _))
|
| + .Times(1);
|
| + EXPECT_CALL(*gl_, GenBuffersARB(1, _)).Times(1);
|
| + EXPECT_CALL(*gl_, BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _)).Times(2);
|
| + EXPECT_CALL(*gl_,
|
| + BufferData(GL_PIXEL_PACK_BUFFER_ARB, _, NULL, GL_STREAM_READ))
|
| + .Times(1);
|
| +
|
| + ReadPixels cmd;
|
| + cmd.Init(0,
|
| + 0,
|
| + kWidth,
|
| + kHeight,
|
| + GL_RGB,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + true);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +
|
| +// Check that if a renderbuffer is attached and GL returns
|
| +// GL_FRAMEBUFFER_COMPLETE that the buffer is cleared and state is restored.
|
| +TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearColor) {
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + ClearColor color_cmd;
|
| + ColorMask color_mask_cmd;
|
| + Enable enable_cmd;
|
| + FramebufferRenderbuffer cmd;
|
| + color_cmd.Init(0.1f, 0.2f, 0.3f, 0.4f);
|
| + color_mask_cmd.Init(0, 1, 0, 1);
|
| + enable_cmd.Init(GL_SCISSOR_TEST);
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, ClearColor(0.1f, 0.2f, 0.3f, 0.4f))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(color_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(color_mask_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(enable_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepth) {
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + ClearDepthf depth_cmd;
|
| + DepthMask depth_mask_cmd;
|
| + FramebufferRenderbuffer cmd;
|
| + depth_cmd.Init(0.5f);
|
| + depth_mask_cmd.Init(false);
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_DEPTH_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, ClearDepth(0.5f)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_DEPTH_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_mask_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearStencil) {
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + ClearStencil stencil_cmd;
|
| + StencilMaskSeparate stencil_mask_separate_cmd;
|
| + FramebufferRenderbuffer cmd;
|
| + stencil_cmd.Init(123);
|
| + stencil_mask_separate_cmd.Init(GL_BACK, 0x1234u);
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_STENCIL_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, ClearStencil(123)).Times(1).RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_STENCIL_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_mask_separate_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +
|
| +#if 0 // Turn this test on once we allow GL_DEPTH_STENCIL_ATTACHMENT
|
| +TEST_F(GLES2DecoderTest, FramebufferRenderbufferClearDepthStencil) {
|
| + DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
|
| + kServiceFramebufferId);
|
| + ClearDepthf depth_cmd;
|
| + ClearStencil stencil_cmd;
|
| + FramebufferRenderbuffer cmd;
|
| + depth_cmd.Init(0.5f);
|
| + stencil_cmd.Init(123);
|
| + cmd.Init(
|
| + GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, ClearDepth(0.5f))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, ClearStencil(123))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
|
| + GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(depth_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(stencil_cmd));
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| +}
|
| +#endif
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_alpha = true;
|
| + init.request_alpha = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + 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_ALPHA_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(8, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_alpha = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + 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_ALPHA_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_ALPHA_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(0, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_depth = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + 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_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(24))
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(24, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + 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_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(24))
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(0, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_stencil = true;
|
| + init.request_stencil = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + 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_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(8, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) {
|
| + InitState init;
|
| + init.gl_version = "3.0";
|
| + init.has_stencil = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + 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_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(0, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilReportsCorrectValues) {
|
| + InitState init;
|
| + init.extensions = "GL_OES_packed_depth_stencil";
|
| + init.gl_version = "opengl es 2.0";
|
| + init.has_depth = true;
|
| + init.has_stencil = true;
|
| + init.request_depth = true;
|
| + init.request_stencil = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(8, result->GetData()[0]);
|
| + result->size = 0;
|
| + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(24))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(24, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilNoRequestedStencil) {
|
| + InitState init;
|
| + init.extensions = "GL_OES_packed_depth_stencil";
|
| + init.gl_version = "opengl es 2.0";
|
| + init.has_depth = true;
|
| + init.has_stencil = true;
|
| + init.request_depth = true;
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(0, result->GetData()[0]);
|
| + result->size = 0;
|
| + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(24))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(24, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferDepth) {
|
| + InitState init;
|
| + init.extensions = "GL_OES_packed_depth_stencil";
|
| + init.gl_version = "opengl es 2.0";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| +
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorage cmd;
|
| + cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_DEPTH_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + FramebufferRenderbuffer fbrb_cmd;
|
| + fbrb_cmd.Init(GL_FRAMEBUFFER,
|
| + GL_DEPTH_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd));
|
| +
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(0, result->GetData()[0]);
|
| + result->size = 0;
|
| + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(24))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(24, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, PackedDepthStencilRenderbufferStencil) {
|
| + InitState init;
|
| + init.extensions = "GL_OES_packed_depth_stencil";
|
| + init.gl_version = "opengl es 2.0";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR)) // for RenderbufferStoage
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR)) // for FramebufferRenderbuffer
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR)) // for GetIntegerv
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| +
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorage cmd;
|
| + cmd.Init(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 100, 50);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_STENCIL_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + FramebufferRenderbuffer fbrb_cmd;
|
| + fbrb_cmd.Init(GL_FRAMEBUFFER,
|
| + GL_STENCIL_ATTACHMENT,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd));
|
| +
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + result->size = 0;
|
| + GetIntegerv cmd2;
|
| + cmd2.Init(GL_STENCIL_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_STENCIL_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(8))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_STENCIL_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(8, result->GetData()[0]);
|
| + result->size = 0;
|
| + cmd2.Init(GL_DEPTH_BITS, shared_memory_id_, shared_memory_offset_);
|
| + EXPECT_CALL(*gl_, GetIntegerv(GL_DEPTH_BITS, _))
|
| + .WillOnce(SetArgumentPointee<1>(24))
|
| + .RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
|
| + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_DEPTH_BITS),
|
| + result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_EQ(0, result->GetData()[0]);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, FramebufferRenderbufferGLError) {
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_OUT_OF_MEMORY))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferRenderbufferEXT(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + kServiceRenderbufferId))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + FramebufferRenderbuffer cmd;
|
| + cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, FramebufferTexture2DGLError) {
|
| + const GLsizei kWidth = 5;
|
| + const GLsizei kHeight = 3;
|
| + const GLenum kFormat = GL_RGB;
|
| + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
|
| + DoTexImage2D(GL_TEXTURE_2D,
|
| + 0,
|
| + kFormat,
|
| + kWidth,
|
| + kHeight,
|
| + 0,
|
| + kFormat,
|
| + GL_UNSIGNED_BYTE,
|
| + 0,
|
| + 0);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_OUT_OF_MEMORY))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + FramebufferTexture2DEXT(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kServiceTextureId,
|
| + 0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + FramebufferTexture2D fbtex_cmd;
|
| + fbtex_cmd.Init(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + client_texture_id_,
|
| + 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, RenderbufferStorageGLError) {
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_OUT_OF_MEMORY))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, RenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA, 100, 50))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorage cmd;
|
| + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 100, 50);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, RenderbufferStorageBadArgs) {
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + EXPECT_CALL(*gl_, RenderbufferStorageEXT(_, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorage cmd;
|
| + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, TestHelper::kMaxRenderbufferSize + 1, 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| + cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 1, TestHelper::kMaxRenderbufferSize + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest,
|
| + RenderbufferStorageMultisampleCHROMIUMGLError) {
|
| + InitState init;
|
| + init.extensions = "GL_EXT_framebuffer_multisample";
|
| + init.gl_version = "2.1";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_OUT_OF_MEMORY))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 1, GL_RGBA, 100, 50))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorageMultisampleCHROMIUM cmd;
|
| + cmd.Init(GL_RENDERBUFFER, 1, GL_RGBA4, 100, 50);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest,
|
| + RenderbufferStorageMultisampleCHROMIUMBadArgs) {
|
| + InitState init;
|
| + init.extensions = "GL_EXT_framebuffer_multisample";
|
| + init.gl_version = "2.1";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + EXPECT_CALL(*gl_, RenderbufferStorageMultisampleEXT(_, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorageMultisampleCHROMIUM cmd;
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples + 1,
|
| + GL_RGBA4,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA4,
|
| + TestHelper::kMaxRenderbufferSize + 1,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA4,
|
| + 1,
|
| + TestHelper::kMaxRenderbufferSize + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUM) {
|
| + InitState init;
|
| + init.extensions = "GL_EXT_framebuffer_multisample";
|
| + init.gl_version = "2.1";
|
| + InitDecoder(init);
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorageMultisampleCHROMIUM cmd;
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA4,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest,
|
| + RenderbufferStorageMultisampleEXTNotSupported) {
|
| + InitState init;
|
| + init.extensions = "GL_EXT_framebuffer_multisample";
|
| + init.gl_version = "2.1";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + InSequence sequence;
|
| + // GL_EXT_framebuffer_multisample uses RenderbufferStorageMultisampleCHROMIUM.
|
| + RenderbufferStorageMultisampleEXT cmd;
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA4,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +class GLES2DecoderMultisampledRenderToTextureTest
|
| + : public GLES2DecoderTestWithExtensionsOnGLES2 {};
|
| +
|
| +TEST_P(GLES2DecoderMultisampledRenderToTextureTest,
|
| + NotCompatibleWithRenderbufferStorageMultisampleCHROMIUM) {
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + RenderbufferStorageMultisampleCHROMIUM cmd;
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA4,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_P(GLES2DecoderMultisampledRenderToTextureTest,
|
| + RenderbufferStorageMultisampleEXT) {
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + InSequence sequence;
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + if (strstr(GetParam(), "GL_IMG_multisampled_render_to_texture")) {
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + RenderbufferStorageMultisampleIMG(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + } else {
|
| + EXPECT_CALL(
|
| + *gl_,
|
| + RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + }
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + RenderbufferStorageMultisampleEXT cmd;
|
| + cmd.Init(GL_RENDERBUFFER,
|
| + TestHelper::kMaxSamples,
|
| + GL_RGBA4,
|
| + TestHelper::kMaxRenderbufferSize,
|
| + 1);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +INSTANTIATE_TEST_CASE_P(
|
| + GLES2DecoderMultisampledRenderToTextureTests,
|
| + GLES2DecoderMultisampledRenderToTextureTest,
|
| + ::testing::Values("GL_EXT_multisampled_render_to_texture",
|
| + "GL_IMG_multisampled_render_to_texture"));
|
| +
|
| +TEST_F(GLES2DecoderTest, ReadPixelsGLError) {
|
| + GLenum kFormat = GL_RGBA;
|
| + GLint x = 0;
|
| + GLint y = 0;
|
| + GLsizei width = 2;
|
| + GLsizei height = 4;
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_OUT_OF_MEMORY))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_,
|
| + ReadPixels(x, y, width, height, kFormat, GL_UNSIGNED_BYTE, _))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + ReadPixels cmd;
|
| + cmd.Init(x,
|
| + y,
|
| + width,
|
| + height,
|
| + kFormat,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnClear) {
|
| + 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();
|
| +
|
| + 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_, Clear(GL_COLOR_BUFFER_BIT)).Times(1).RetiresOnSaturation();
|
| +
|
| + Clear cmd;
|
| + cmd.Init(GL_COLOR_BUFFER_BIT);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, UnClearedAttachmentsGetClearedOnReadPixels) {
|
| + 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();
|
| +
|
| + SetupExpectationsForFramebufferClearing(GL_FRAMEBUFFER, // target
|
| + GL_COLOR_BUFFER_BIT, // clear bits
|
| + 0,
|
| + 0,
|
| + 0,
|
| + 0, // color
|
| + 0, // stencil
|
| + 1.0f, // depth
|
| + false); // scissor test
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, ReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, _))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + typedef ReadPixels::Result Result;
|
| + Result* result = GetSharedMemoryAs<Result*>();
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);
|
| + ReadPixels cmd;
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest,
|
| + UnClearedAttachmentsGetClearedOnReadPixelsAndDrawBufferGetsRestored) {
|
| + InitState init;
|
| + init.extensions = "GL_EXT_framebuffer_multisample";
|
| + init.gl_version = "2.1";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| + 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 from" 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_READ_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_READ_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + kFBOClientTextureId,
|
| + kFBOServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| +
|
| + SetupExpectationsForFramebufferClearingMulti(
|
| + kServiceFramebufferId, // read framebuffer service id
|
| + 0, // backbuffer service id
|
| + GL_READ_FRAMEBUFFER, // target
|
| + GL_COLOR_BUFFER_BIT, // clear bits
|
| + 0,
|
| + 0,
|
| + 0,
|
| + 0, // color
|
| + 0, // stencil
|
| + 1.0f, // depth
|
| + false); // scissor test
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, ReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, _))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + typedef ReadPixels::Result Result;
|
| + uint32 result_shm_id = kSharedMemoryId;
|
| + uint32 result_shm_offset = kSharedMemoryOffset;
|
| + uint32 pixels_shm_id = kSharedMemoryId;
|
| + uint32 pixels_shm_offset = kSharedMemoryOffset + sizeof(Result);
|
| + ReadPixels cmd;
|
| + cmd.Init(0,
|
| + 0,
|
| + 1,
|
| + 1,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + pixels_shm_id,
|
| + pixels_shm_offset,
|
| + result_shm_id,
|
| + result_shm_offset,
|
| + false);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, CopyTexImageWithInCompleteFBOFails) {
|
| + GLenum target = GL_TEXTURE_2D;
|
| + GLint level = 0;
|
| + GLenum internal_format = GL_RGBA;
|
| + GLsizei width = 2;
|
| + GLsizei height = 4;
|
| + GLint border = 0;
|
| + SetupTexture();
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 0, 0, GL_NO_ERROR);
|
| + DoFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_,
|
| + kServiceRenderbufferId,
|
| + GL_NO_ERROR);
|
| +
|
| + EXPECT_CALL(*gl_, CopyTexImage2D(_, _, _, _, _, _, _, _))
|
| + .Times(0)
|
| + .RetiresOnSaturation();
|
| + CopyTexImage2D cmd;
|
| + cmd.Init(target, level, internal_format, 0, 0, width, height, border);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, GetGLError());
|
| +}
|
| +
|
| +void GLES2DecoderWithShaderTest::CheckRenderbufferChangesMarkFBOAsNotComplete(
|
| + bool bound_fbo) {
|
| + FramebufferManager* framebuffer_manager = group().framebuffer_manager();
|
| + SetupTexture();
|
| + DoBindRenderbuffer(
|
| + GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 1, 1, GL_NO_ERROR);
|
| + DoFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_RENDERBUFFER,
|
| + client_renderbuffer_id_,
|
| + kServiceRenderbufferId,
|
| + GL_NO_ERROR);
|
| +
|
| + if (!bound_fbo) {
|
| + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0);
|
| + }
|
| +
|
| + Framebuffer* framebuffer =
|
| + framebuffer_manager->GetFramebuffer(client_framebuffer_id_);
|
| + ASSERT_TRUE(framebuffer != NULL);
|
| + framebuffer_manager->MarkAsComplete(framebuffer);
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| +
|
| + // Test that renderbufferStorage marks fbo as not complete.
|
| + DoRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, GL_RGBA, 1, 1, GL_NO_ERROR);
|
| + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer));
|
| + framebuffer_manager->MarkAsComplete(framebuffer);
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| +
|
| + // Test deleting renderbuffer marks fbo as not complete.
|
| + DoDeleteRenderbuffer(client_renderbuffer_id_, kServiceRenderbufferId);
|
| + if (bound_fbo) {
|
| + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer));
|
| + } else {
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| + }
|
| + // Cleanup
|
| + DoDeleteFramebuffer(client_framebuffer_id_,
|
| + kServiceFramebufferId,
|
| + bound_fbo,
|
| + GL_FRAMEBUFFER,
|
| + 0,
|
| + bound_fbo,
|
| + GL_FRAMEBUFFER,
|
| + 0);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + RenderbufferChangesMarkFBOAsNotCompleteBoundFBO) {
|
| + CheckRenderbufferChangesMarkFBOAsNotComplete(true);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + RenderbufferChangesMarkFBOAsNotCompleteUnboundFBO) {
|
| + CheckRenderbufferChangesMarkFBOAsNotComplete(false);
|
| +}
|
| +
|
| +void GLES2DecoderWithShaderTest::CheckTextureChangesMarkFBOAsNotComplete(
|
| + bool bound_fbo) {
|
| + FramebufferManager* framebuffer_manager = group().framebuffer_manager();
|
| + const GLuint kFBOClientTextureId = 4100;
|
| + const GLuint kFBOServiceTextureId = 4101;
|
| +
|
| + // Register a texture id.
|
| + EXPECT_CALL(*gl_, GenTextures(_, _))
|
| + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
|
| + .RetiresOnSaturation();
|
| + GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
|
| +
|
| + SetupTexture();
|
| +
|
| + // 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);
|
| +
|
| + if (!bound_fbo) {
|
| + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0);
|
| + }
|
| +
|
| + Framebuffer* framebuffer =
|
| + framebuffer_manager->GetFramebuffer(client_framebuffer_id_);
|
| + ASSERT_TRUE(framebuffer != NULL);
|
| + framebuffer_manager->MarkAsComplete(framebuffer);
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| +
|
| + // Test TexImage2D marks fbo as not complete.
|
| + DoTexImage2D(
|
| + GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, 0, 0);
|
| + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer));
|
| + framebuffer_manager->MarkAsComplete(framebuffer);
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| +
|
| + // Test CopyImage2D marks fbo as not complete.
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1, 0))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + CopyTexImage2D cmd;
|
| + cmd.Init(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1, 0);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer));
|
| +
|
| + // Test deleting texture marks fbo as not complete.
|
| + framebuffer_manager->MarkAsComplete(framebuffer);
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| + DoDeleteTexture(kFBOClientTextureId, kFBOServiceTextureId);
|
| +
|
| + if (bound_fbo) {
|
| + EXPECT_FALSE(framebuffer_manager->IsComplete(framebuffer));
|
| + } else {
|
| + EXPECT_TRUE(framebuffer_manager->IsComplete(framebuffer));
|
| + }
|
| + // Cleanup
|
| + DoDeleteFramebuffer(client_framebuffer_id_,
|
| + kServiceFramebufferId,
|
| + bound_fbo,
|
| + GL_FRAMEBUFFER,
|
| + 0,
|
| + bound_fbo,
|
| + GL_FRAMEBUFFER,
|
| + 0);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest, TextureChangesMarkFBOAsNotCompleteBoundFBO) {
|
| + CheckTextureChangesMarkFBOAsNotComplete(true);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderWithShaderTest,
|
| + TextureChangesMarkFBOAsNotCompleteUnboundFBO) {
|
| + CheckTextureChangesMarkFBOAsNotComplete(false);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, CanChangeSurface) {
|
| + scoped_refptr<GLSurfaceMock> other_surface(new GLSurfaceMock);
|
| + EXPECT_CALL(*other_surface.get(), GetBackingFrameBufferObject())
|
| + .WillOnce(Return(7));
|
| + EXPECT_CALL(*gl_, BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 7));
|
| +
|
| + decoder_->SetSurface(other_surface);
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateSuccceeds) {
|
| + const GLsizei count = 1;
|
| + const GLenum bufs[] = {GL_COLOR_ATTACHMENT0};
|
| + DrawBuffersEXTImmediate& cmd = *GetImmediateAs<DrawBuffersEXTImmediate>();
|
| + cmd.Init(count, bufs);
|
| +
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_CALL(*gl_, DrawBuffersARB(count, _)).Times(1).RetiresOnSaturation();
|
| + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs)));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateFails) {
|
| + const GLsizei count = 1;
|
| + const GLenum bufs[] = {GL_COLOR_ATTACHMENT1_EXT};
|
| + DrawBuffersEXTImmediate& cmd = *GetImmediateAs<DrawBuffersEXTImmediate>();
|
| + cmd.Init(count, bufs);
|
| +
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs)));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, DrawBuffersEXTImmediateBackbuffer) {
|
| + const GLsizei count = 1;
|
| + const GLenum bufs[] = {GL_BACK};
|
| + DrawBuffersEXTImmediate& cmd = *GetImmediateAs<DrawBuffersEXTImmediate>();
|
| + cmd.Init(count, bufs);
|
| +
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs)));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +
|
| + DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0); // unbind
|
| +
|
| + EXPECT_CALL(*gl_, DrawBuffersARB(count, _)).Times(1).RetiresOnSaturation();
|
| +
|
| + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(bufs)));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, InvalidateFramebufferBinding) {
|
| + InitState init;
|
| + init.gl_version = "opengl es 3.0";
|
| + InitDecoder(init);
|
| +
|
| + // EXPECT_EQ can't be used to compare function pointers
|
| + EXPECT_TRUE(
|
| + gfx::MockGLInterface::GetGLProcAddress("glInvalidateFramebuffer") ==
|
| + gfx::g_driver_gl.fn.glDiscardFramebufferEXTFn);
|
| + EXPECT_TRUE(
|
| + gfx::MockGLInterface::GetGLProcAddress("glInvalidateFramebuffer") !=
|
| + gfx::MockGLInterface::GetGLProcAddress("glDiscardFramebufferEXT"));
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, DiscardFramebufferEXT) {
|
| + InitState init;
|
| + init.extensions = "GL_EXT_discard_framebuffer";
|
| + init.gl_version = "opengl es 2.0";
|
| + InitDecoder(init);
|
| +
|
| + // EXPECT_EQ can't be used to compare function pointers
|
| + EXPECT_TRUE(
|
| + gfx::MockGLInterface::GetGLProcAddress("glDiscardFramebufferEXT") ==
|
| + gfx::g_driver_gl.fn.glDiscardFramebufferEXTFn);
|
| +
|
| + const GLenum target = GL_FRAMEBUFFER;
|
| + const GLsizei count = 1;
|
| + const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
|
| +
|
| + SetupTexture();
|
| + DoBindFramebuffer(
|
| + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
|
| + DoFramebufferTexture2D(GL_FRAMEBUFFER,
|
| + GL_COLOR_ATTACHMENT0,
|
| + GL_TEXTURE_2D,
|
| + client_texture_id_,
|
| + kServiceTextureId,
|
| + 0,
|
| + GL_NO_ERROR);
|
| + FramebufferManager* framebuffer_manager = group().framebuffer_manager();
|
| + Framebuffer* framebuffer =
|
| + framebuffer_manager->GetFramebuffer(client_framebuffer_id_);
|
| + EXPECT_TRUE(framebuffer->IsCleared());
|
| +
|
| + EXPECT_CALL(*gl_, DiscardFramebufferEXT(target, count, _))
|
| + .Times(1)
|
| + .RetiresOnSaturation();
|
| + DiscardFramebufferEXTImmediate& cmd =
|
| + *GetImmediateAs<DiscardFramebufferEXTImmediate>();
|
| + cmd.Init(target, count, attachments);
|
| +
|
| + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(attachments)));
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| + EXPECT_FALSE(framebuffer->IsCleared());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderTest, DiscardFramebufferEXTUnsupported) {
|
| + const GLenum target = GL_FRAMEBUFFER;
|
| + const GLsizei count = 1;
|
| + const GLenum attachments[] = {GL_COLOR_EXT};
|
| + DiscardFramebufferEXTImmediate& cmd =
|
| + *GetImmediateAs<DiscardFramebufferEXTImmediate>();
|
| + cmd.Init(target, count, attachments);
|
| +
|
| + // Should not result into a call into GL.
|
| + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(attachments)));
|
| + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, ReadFormatExtension) {
|
| + InitState init;
|
| + init.extensions = "GL_OES_read_format";
|
| + init.gl_version = "2.1";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| + EXPECT_CALL(*gl_, GetError()).Times(6).RetiresOnSaturation();
|
| +
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + GetIntegerv cmd;
|
| + 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);
|
| +
|
| + result->size = 0;
|
| + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(1).RetiresOnSaturation();
|
| + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_FORMAT,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(1, result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + result->size = 0;
|
| + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(1).RetiresOnSaturation();
|
| + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_TYPE,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(1, result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +TEST_F(GLES2DecoderManualInitTest, NoReadFormatExtension) {
|
| + InitState init;
|
| + init.gl_version = "2.1";
|
| + init.bind_generates_resource = true;
|
| + InitDecoder(init);
|
| +
|
| + EXPECT_CALL(*gl_, GetError())
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .WillOnce(Return(GL_NO_ERROR))
|
| + .RetiresOnSaturation();
|
| +
|
| + typedef GetIntegerv::Result Result;
|
| + Result* result = static_cast<Result*>(shared_memory_address_);
|
| + GetIntegerv cmd;
|
| + 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);
|
| +
|
| + result->size = 0;
|
| + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation();
|
| + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_FORMAT,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(1, result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +
|
| + result->size = 0;
|
| + EXPECT_CALL(*gl_, GetIntegerv(_, _)).Times(0).RetiresOnSaturation();
|
| + cmd.Init(GL_IMPLEMENTATION_COLOR_READ_TYPE,
|
| + shared_memory_id_,
|
| + shared_memory_offset_);
|
| + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
|
| + EXPECT_EQ(1, result->GetNumResults());
|
| + EXPECT_EQ(GL_NO_ERROR, GetGLError());
|
| +}
|
| +
|
| +// TODO(gman): PixelStorei
|
| +
|
| +// TODO(gman): SwapBuffers
|
| +
|
| +} // namespace gles2
|
| +} // namespace gpu
|
|
|