/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#pragma once

#if ENABLE(WEBGL)

#include "WebGLContextObject.h"
#include "WebGLSharedObject.h"
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>

namespace WebCore {

class WebGLRenderbuffer;
class WebGLTexture;

class WebGLFramebuffer final : public WebGLContextObject {
public:
    class WebGLAttachment : public RefCounted<WebGLAttachment> {
    public:
        virtual ~WebGLAttachment();

#if !USE(ANGLE)
        virtual GCGLsizei getWidth() const = 0;
        virtual GCGLsizei getHeight() const = 0;
        virtual GCGLenum getFormat() const = 0;
#endif
        virtual WebGLSharedObject* getObject() const = 0;
        virtual bool isSharedObject(WebGLSharedObject*) const = 0;
        virtual bool isValid() const = 0;
        virtual bool isInitialized() const = 0;
        virtual void setInitialized() = 0;
        virtual void onDetached(GraphicsContextGLOpenGL*) = 0;
        virtual void attach(GraphicsContextGLOpenGL*, GCGLenum attachment) = 0;
        virtual void unattach(GraphicsContextGLOpenGL*, GCGLenum attachment) = 0;

    protected:
        WebGLAttachment();
    };

    virtual ~WebGLFramebuffer();

    static Ref<WebGLFramebuffer> create(WebGLRenderingContextBase&);

    void setAttachmentForBoundFramebuffer(GCGLenum attachment, GCGLenum texTarget, WebGLTexture*, GCGLint level);
    void setAttachmentForBoundFramebuffer(GCGLenum attachment, WebGLRenderbuffer*);
    // If an object is attached to the currently bound framebuffer, remove it.
    void removeAttachmentFromBoundFramebuffer(WebGLSharedObject*);
    // If a given attachment point for the currently bound framebuffer is not null, remove the attached object.
    void removeAttachmentFromBoundFramebuffer(GCGLenum);
    WebGLSharedObject* getAttachmentObject(GCGLenum) const;

#if !USE(ANGLE)
    GCGLenum getColorBufferFormat() const;
    GCGLsizei getColorBufferWidth() const;
    GCGLsizei getColorBufferHeight() const;

    // This should always be called before drawArray, drawElements, clear,
    // readPixels, copyTexImage2D, copyTexSubImage2D if this framebuffer is
    // currently bound.
    // Return false if the framebuffer is incomplete; otherwise initialize
    // the buffers if they haven't been initialized and
    // needToInitializeAttachments is true.
    bool onAccess(GraphicsContextGLOpenGL*, const char** reason);

    // Software version of glCheckFramebufferStatus(), except that when
    // FRAMEBUFFER_COMPLETE is returned, it is still possible for
    // glCheckFramebufferStatus() to return FRAMEBUFFER_UNSUPPORTED,
    // depending on hardware implementation.
    GCGLenum checkStatus(const char** reason) const;
#endif

    bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; }

    void setHasEverBeenBound() { m_hasEverBeenBound = true; }

    bool hasStencilBuffer() const;

    // Wrapper for drawBuffersEXT/drawBuffersARB to work around a driver bug.
    void drawBuffers(const Vector<GCGLenum>& bufs);

    GCGLenum getDrawBuffer(GCGLenum);

protected:
    WebGLFramebuffer(WebGLRenderingContextBase&);

    void deleteObjectImpl(GraphicsContextGLOpenGL*, PlatformGLObject) override;

private:
    WebGLAttachment* getAttachment(GCGLenum) const;

    // Return false if framebuffer is incomplete.
    bool initializeAttachments(GraphicsContextGLOpenGL*, const char** reason);

    // Check if the framebuffer is currently bound.
    bool isBound() const;

    // attach 'attachment' at 'attachmentPoint'.
    void attach(GCGLenum attachment, GCGLenum attachmentPoint);

    // Check if a new drawBuffers call should be issued. This is called when we add or remove an attachment.
    void drawBuffersIfNecessary(bool force);

    typedef WTF::HashMap<GCGLenum, RefPtr<WebGLAttachment>> AttachmentMap;

    AttachmentMap m_attachments;

    bool m_hasEverBeenBound;

    Vector<GCGLenum> m_drawBuffers;
    Vector<GCGLenum> m_filteredDrawBuffers;
};

} // namespace WebCore

#endif
