//
// Copyright (c) 2014 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.
//

// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl


#include "libANGLE/renderer/d3d/RenderbufferD3D.h"

#include "libANGLE/Image.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"

namespace rx
{
RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer)
    : mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr)
{
}

RenderbufferD3D::~RenderbufferD3D()
{
    SafeDelete(mRenderTarget);
    mImage = nullptr;
}

gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height)
{
    return setStorageMultisample(0, internalformat, width, height);
}

gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
{
    // If the renderbuffer parameters are queried, the calling function
    // will expect one of the valid renderbuffer formats for use in
    // glRenderbufferStorage, but we should create depth and stencil buffers
    // as DEPTH24_STENCIL8
    GLenum creationFormat = internalformat;
    if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8)
    {
        creationFormat = GL_DEPTH24_STENCIL8_OES;
    }

    // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
    // the specified storage.
    // Because ES 3.0 already knows the exact number of supported samples, it would already have been
    // validated and generated GL_INVALID_VALUE.
    const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat);
    if (samples > formatCaps.getMaxSamples())
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.",
                         samples, formatCaps.getMaxSamples());
    }

    RenderTargetD3D *newRT = nullptr;
    ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
                                            creationFormat, static_cast<GLsizei>(samples), &newRT));

    SafeDelete(mRenderTarget);
    mImage        = nullptr;
    mRenderTarget = newRT;

    return gl::NoError();
}

gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image)
{
    mImage = GetImplAs<EGLImageD3D>(image);
    SafeDelete(mRenderTarget);

    return gl::NoError();
}

gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
{
    if (mImage)
    {
        return mImage->getRenderTarget(outRenderTarget);
    }
    else
    {
        *outRenderTarget = mRenderTarget;
        return gl::NoError();
    }
}

gl::Error RenderbufferD3D::getAttachmentRenderTarget(GLenum /*binding*/,
                                                     const gl::ImageIndex & /*imageIndex*/,
                                                     FramebufferAttachmentRenderTarget **rtOut)
{
    return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut));
}

}
