//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Image_unittest.cpp : Unittets of the Image and ImageSibling classes.

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "libANGLE/Image.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Texture.h"
#include "libANGLE/renderer/ImageImpl_mock.h"
#include "libANGLE/renderer/RenderbufferImpl_mock.h"
#include "libANGLE/renderer/TextureImpl_mock.h"
#include "tests/angle_unittests_utils.h"

using ::testing::_;
using ::testing::NiceMock;
using ::testing::Return;

namespace angle
{
ACTION(CreateMockImageImpl)
{
    return new rx::MockImageImpl(arg0);
}

// Verify ref counts are maintained between images and their siblings when objects are deleted
TEST(ImageTest, RefCounting)
{
    NiceMock<rx::MockGLFactory> mockGLFactory;
    NiceMock<rx::MockEGLFactory> mockEGLFactory;

    // Create a texture and an EGL image that uses the texture as its source
    rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
    EXPECT_CALL(mockGLFactory, createTexture(_)).WillOnce(Return(textureImpl));
    gl::Texture *texture = new gl::Texture(&mockGLFactory, 1, gl::TextureType::_2D);
    texture->addRef();

    EXPECT_CALL(mockEGLFactory, createImage(_, _, _, _))
        .WillOnce(CreateMockImageImpl())
        .RetiresOnSaturation();

    egl::Image *image =
        new egl::Image(&mockEGLFactory, nullptr, EGL_GL_TEXTURE_2D, texture, egl::AttributeMap());
    rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
    image->addRef();

    // Verify that the image does not add a ref to its source so that the source may still be
    // deleted
    EXPECT_EQ(1u, texture->getRefCount());
    EXPECT_EQ(1u, image->getRefCount());

    // Create a renderbuffer and set it as a target of the EGL image
    rx::MockRenderbufferImpl *renderbufferImpl = new rx::MockRenderbufferImpl();
    EXPECT_CALL(mockGLFactory, createRenderbuffer(_)).WillOnce(Return(renderbufferImpl));
    gl::Renderbuffer *renderbuffer = new gl::Renderbuffer(&mockGLFactory, 1);
    renderbuffer->addRef();

    EXPECT_CALL(*renderbufferImpl, setStorageEGLImageTarget(_, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();
    EXPECT_EQ(angle::Result::Continue, renderbuffer->setStorageEGLImageTarget(nullptr, image));

    // Verify that the renderbuffer added a ref to the image and the image did not add a ref to
    // the renderbuffer
    EXPECT_EQ(1u, texture->getRefCount());
    EXPECT_EQ(2u, image->getRefCount());
    EXPECT_EQ(1u, renderbuffer->getRefCount());

    // Simulate deletion of the texture and verify that it is deleted but the image still exists
    EXPECT_CALL(*imageImpl, orphan(_, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();
    EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
    texture->release(nullptr);
    EXPECT_EQ(2u, image->getRefCount());
    EXPECT_EQ(1u, renderbuffer->getRefCount());

    // Simulate deletion of the image and verify that it still exists because the renderbuffer holds
    // a ref
    image->release(nullptr);
    EXPECT_EQ(1u, image->getRefCount());
    EXPECT_EQ(1u, renderbuffer->getRefCount());

    // Simulate deletion of the renderbuffer and verify that the deletion cascades to all objects
    EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
    EXPECT_CALL(*imageImpl, orphan(_, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();

    EXPECT_CALL(*renderbufferImpl, destructor()).Times(1).RetiresOnSaturation();

    renderbuffer->release(nullptr);
}

// Verify that respecifiying textures releases references to the Image.
TEST(ImageTest, RespecificationReleasesReferences)
{
    NiceMock<rx::MockGLFactory> mockGLFactory;
    NiceMock<rx::MockEGLFactory> mockEGLFactory;

    // Create a texture and an EGL image that uses the texture as its source
    rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
    EXPECT_CALL(mockGLFactory, createTexture(_)).WillOnce(Return(textureImpl));
    gl::Texture *texture = new gl::Texture(&mockGLFactory, 1, gl::TextureType::_2D);
    texture->addRef();

    gl::PixelUnpackState defaultUnpackState;

    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();
    EXPECT_EQ(angle::Result::Continue,
              texture->setImage(nullptr, defaultUnpackState, gl::TextureTarget::_2D, 0, GL_RGBA8,
                                gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));

    EXPECT_CALL(mockEGLFactory, createImage(_, _, _, _))
        .WillOnce(CreateMockImageImpl())
        .RetiresOnSaturation();

    egl::Image *image =
        new egl::Image(&mockEGLFactory, nullptr, EGL_GL_TEXTURE_2D, texture, egl::AttributeMap());
    image->addRef();

    // Verify that the image did not add a ref to it's source.
    EXPECT_EQ(1u, texture->getRefCount());
    EXPECT_EQ(1u, image->getRefCount());

    // Respecify the texture and verify that the image is orpahaned
    rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
    EXPECT_CALL(*imageImpl, orphan(_, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();
    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();

    EXPECT_EQ(angle::Result::Continue,
              texture->setImage(nullptr, defaultUnpackState, gl::TextureTarget::_2D, 0, GL_RGBA8,
                                gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));

    EXPECT_EQ(1u, texture->getRefCount());
    EXPECT_EQ(1u, image->getRefCount());

    // Delete the texture and verify that the image still exists
    EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
    texture->release(nullptr);

    EXPECT_EQ(1u, image->getRefCount());

    // Delete the image
    EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
    image->release(nullptr);
}
}  // namespace angle
