//
// Copyright 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/Context.h"
#include "libANGLE/Image.h"
#include "libANGLE/renderer/d3d/ContextD3D.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"

namespace rx
{
RenderbufferD3D::RenderbufferD3D(const gl::RenderbufferState &state, RendererD3D *renderer)
    : RenderbufferImpl(state), mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr)
{}

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

void RenderbufferD3D::onDestroy(const gl::Context *context)
{
    SafeDelete(mRenderTarget);
}

angle::Result RenderbufferD3D::setStorage(const gl::Context *context,
                                          GLenum internalformat,
                                          size_t width,
                                          size_t height)
{
    return setStorageMultisample(context, 0, internalformat, width, height);
}

angle::Result RenderbufferD3D::setStorageMultisample(const gl::Context *context,
                                                     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);
    ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), samples <= formatCaps.getMaxSamples());

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

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

    return angle::Result::Continue;
}

angle::Result RenderbufferD3D::setStorageEGLImageTarget(const gl::Context *context,
                                                        egl::Image *image)
{
    mImage = GetImplAs<EGLImageD3D>(image);
    SafeDelete(mRenderTarget);

    return angle::Result::Continue;
}

angle::Result RenderbufferD3D::getRenderTarget(const gl::Context *context,
                                               RenderTargetD3D **outRenderTarget)
{
    if (mImage)
    {
        return mImage->getRenderTarget(context, outRenderTarget);
    }
    else
    {
        *outRenderTarget = mRenderTarget;
        return angle::Result::Continue;
    }
}

angle::Result RenderbufferD3D::getAttachmentRenderTarget(const gl::Context *context,
                                                         GLenum binding,
                                                         const gl::ImageIndex &imageIndex,
                                                         GLsizei samples,
                                                         FramebufferAttachmentRenderTarget **rtOut)
{
    return getRenderTarget(context, reinterpret_cast<RenderTargetD3D **>(rtOut));
}

angle::Result RenderbufferD3D::initializeContents(const gl::Context *context,
                                                  const gl::ImageIndex &imageIndex)
{
    RenderTargetD3D *renderTarget = nullptr;
    ANGLE_TRY(getRenderTarget(context, &renderTarget));
    return mRenderer->initRenderTarget(context, renderTarget);
}

}  // namespace rx
