/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/ganesh/gl/GrGLAttachment.h"

#include "include/core/SkString.h"
#include "include/core/SkTraceMemoryDump.h"
#include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "include/gpu/ganesh/gl/GrGLFunctions.h"
#include "include/gpu/ganesh/gl/GrGLInterface.h"
#include "src/gpu/ganesh/gl/GrGLCaps.h"
#include "src/gpu/ganesh/gl/GrGLDefines.h"
#include "src/gpu/ganesh/gl/GrGLGpu.h"
#include "src/gpu/ganesh/gl/GrGLUtil.h"

#include <string>

#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)

#define GL_ALLOC_CALL(call)                                   \
    [&] {                                                     \
        if (gpu->glCaps().skipErrorChecks()) {               \
            GR_GL_CALL(gpu->glInterface(), call);            \
            return static_cast<GrGLenum>(GR_GL_NO_ERROR);     \
        } else {                                              \
            gpu->clearErrorsAndCheckForOOM();                \
            GR_GL_CALL_NOERRCHECK(gpu->glInterface(), call); \
            return gpu->getErrorAndCheckForOOM();            \
        }                                                     \
    }()

static bool renderbuffer_storage_msaa(GrGLGpu* gpu,
                                      int sampleCount,
                                      GrGLenum format,
                                      int width,
                                      int height) {
    SkASSERT(GrGLCaps::kNone_MSFBOType != gpu->glCaps().msFBOType());
    GrGLenum error;
    switch (gpu->glCaps().msFBOType()) {
        case GrGLCaps::kStandard_MSFBOType:
            error = GL_ALLOC_CALL(RenderbufferStorageMultisample(
                    GR_GL_RENDERBUFFER, sampleCount, format, width, height));
            break;
        case GrGLCaps::kES_Apple_MSFBOType:
            error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2APPLE(
                    GR_GL_RENDERBUFFER, sampleCount, format, width, height));
            break;
        case GrGLCaps::kES_EXT_MsToTexture_MSFBOType:
        case GrGLCaps::kES_IMG_MsToTexture_MSFBOType:
            error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2EXT(
                    GR_GL_RENDERBUFFER, sampleCount, format, width, height));
            break;
        case GrGLCaps::kNone_MSFBOType:
            SkUNREACHABLE;
    }
    return error == GR_GL_NO_ERROR;
}

sk_sp<GrGLAttachment> GrGLAttachment::MakeStencil(GrGLGpu* gpu,
                                                  SkISize dimensions,
                                                  int sampleCnt,
                                                  GrGLFormat format) {
    GrGLuint rbID = 0;

    GL_CALL(GenRenderbuffers(1, &rbID));
    if (!rbID) {
        return nullptr;
    }
    GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID));
    GrGLenum glFmt = GrGLFormatToEnum(format);
    // we do this "if" so that we don't call the multisample
    // version on a GL that doesn't have an MSAA extension.
    if (sampleCnt > 1) {
        if (!renderbuffer_storage_msaa(gpu, sampleCnt, glFmt, dimensions.width(),
                                       dimensions.height())) {
            GL_CALL(DeleteRenderbuffers(1, &rbID));
            return nullptr;
        }
    } else {
        GrGLenum error = GL_ALLOC_CALL(RenderbufferStorage(
                GR_GL_RENDERBUFFER, glFmt, dimensions.width(), dimensions.height()));
        if (error != GR_GL_NO_ERROR) {
            GL_CALL(DeleteRenderbuffers(1, &rbID));
            return nullptr;
        }
    }

    return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu,
                                                    rbID,
                                                    dimensions,
                                                    GrAttachment::UsageFlags::kStencilAttachment,
                                                    sampleCnt,
                                                    format,
                                                    /*label=*/"GLAttachmentMakeStencil"));
}

sk_sp<GrGLAttachment> GrGLAttachment::MakeMSAA(GrGLGpu* gpu,
                                               SkISize dimensions,
                                               int sampleCnt,
                                               GrGLFormat format) {
    GrGLuint rbID = 0;

    GL_CALL(GenRenderbuffers(1, &rbID));
    if (!rbID) {
        return nullptr;
    }
    GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID));
    GrGLenum glFmt = gpu->glCaps().getRenderbufferInternalFormat(format);
    if (!renderbuffer_storage_msaa(
            gpu, sampleCnt, glFmt, dimensions.width(), dimensions.height())) {
        GL_CALL(DeleteRenderbuffers(1, &rbID));
        return nullptr;
    }

    return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu,
                                                    rbID,
                                                    dimensions,
                                                    GrAttachment::UsageFlags::kColorAttachment,
                                                    sampleCnt,
                                                    format,
                                                    /*label=*/"GLAttachmentMakeMSAA"));
}


void GrGLAttachment::onRelease() {
    if (0 != fRenderbufferID) {
        GrGLGpu* gpuGL = (GrGLGpu*)this->getGpu();
        const GrGLInterface* gl = gpuGL->glInterface();
        GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID));
        fRenderbufferID = 0;
    }

    INHERITED::onRelease();
}

void GrGLAttachment::onAbandon() {
    fRenderbufferID = 0;

    INHERITED::onAbandon();
}

GrBackendFormat GrGLAttachment::backendFormat() const {
    return GrBackendFormats::MakeGL(GrGLFormatToEnum(fFormat), GR_GL_TEXTURE_NONE);
}

void GrGLAttachment::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
                                      const SkString& dumpName) const {
    SkString renderbuffer_id;
    renderbuffer_id.appendU32(this->renderbufferID());
    traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer", renderbuffer_id.c_str());
}

void GrGLAttachment::onSetLabel() {
    SkASSERT(fRenderbufferID);
    if (!this->getLabel().empty()) {
        const std::string label = "_Skia_" + this->getLabel();
        GrGLGpu* glGpu = static_cast<GrGLGpu*>(this->getGpu());
        if (glGpu->glCaps().debugSupport()) {
            GR_GL_CALL(glGpu->glInterface(),
                       ObjectLabel(GR_GL_TEXTURE, fRenderbufferID, -1, label.c_str()));
        }
    }
}
