1/*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef WebGLFramebuffer_h
27#define WebGLFramebuffer_h
28
29#include "bindings/v8/ScriptWrappable.h"
30#include "core/html/canvas/WebGLContextObject.h"
31#include "core/html/canvas/WebGLSharedObject.h"
32#include "wtf/PassRefPtr.h"
33#include "wtf/RefCounted.h"
34
35namespace WebCore {
36
37class WebGLRenderbuffer;
38class WebGLTexture;
39
40class WebGLFramebuffer : public WebGLContextObject, public ScriptWrappable {
41public:
42    class WebGLAttachment : public RefCounted<WebGLAttachment> {
43    public:
44        virtual ~WebGLAttachment();
45
46        virtual GC3Dsizei width() const = 0;
47        virtual GC3Dsizei height() const = 0;
48        virtual GC3Denum format() const = 0;
49        // For texture attachment, type() returns the type of the attached texture.
50        // For renderbuffer attachment, the type of the renderbuffer may vary with GL implementation.
51        // To avoid confusion, it would be better to not implement type() for renderbuffer attachment and
52        // we should always use the internalformat of the renderbuffer and avoid using type() API.
53        virtual GC3Denum type() const = 0;
54        virtual WebGLSharedObject* object() const = 0;
55        virtual bool isSharedObject(WebGLSharedObject*) const = 0;
56        virtual bool valid() const = 0;
57        virtual bool initialized() const = 0;
58        virtual void setInitialized() = 0;
59        virtual void onDetached(GraphicsContext3D*) = 0;
60        virtual void attach(GraphicsContext3D*, GC3Denum attachment) = 0;
61        virtual void unattach(GraphicsContext3D*, GC3Denum attachment) = 0;
62
63    protected:
64        WebGLAttachment();
65    };
66
67    virtual ~WebGLFramebuffer();
68
69    static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*);
70
71    void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level);
72    void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*);
73    // If an object is attached to the currently bound framebuffer, remove it.
74    void removeAttachmentFromBoundFramebuffer(WebGLSharedObject*);
75    // If a given attachment point for the currently bound framebuffer is not null, remove the attached object.
76    void removeAttachmentFromBoundFramebuffer(GC3Denum);
77    WebGLSharedObject* getAttachmentObject(GC3Denum) const;
78
79    GC3Denum colorBufferFormat() const;
80    GC3Dsizei colorBufferWidth() const;
81    GC3Dsizei colorBufferHeight() const;
82
83    // This should always be called before drawArray, drawElements, clear,
84    // readPixels, copyTexImage2D, copyTexSubImage2D if this framebuffer is
85    // currently bound.
86    // Return false if the framebuffer is incomplete; otherwise initialize
87    // the buffers if they haven't been initialized and
88    // needToInitializeAttachments is true.
89    bool onAccess(GraphicsContext3D*, const char** reason);
90
91    // Software version of glCheckFramebufferStatus(), except that when
92    // FRAMEBUFFER_COMPLETE is returned, it is still possible for
93    // glCheckFramebufferStatus() to return FRAMEBUFFER_UNSUPPORTED,
94    // depending on hardware implementation.
95    GC3Denum checkStatus(const char** reason) const;
96
97    bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; }
98
99    void setHasEverBeenBound() { m_hasEverBeenBound = true; }
100
101    bool hasStencilBuffer() const;
102
103    // Wrapper for drawBuffersEXT/drawBuffersARB to work around a driver bug.
104    void drawBuffers(const Vector<GC3Denum>& bufs);
105
106    GC3Denum getDrawBuffer(GC3Denum);
107
108protected:
109    WebGLFramebuffer(WebGLRenderingContext*);
110
111    virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject);
112
113private:
114    virtual bool isFramebuffer() const { return true; }
115
116    WebGLAttachment* getAttachment(GC3Denum) const;
117    bool isAttachmentComplete(WebGLAttachment* attachedObject, GC3Denum attachment, const char** reason) const;
118
119    // Check if the framebuffer is currently bound.
120    bool isBound() const;
121
122    // attach 'attachment' at 'attachmentPoint'.
123    void attach(GC3Denum attachment, GC3Denum attachmentPoint);
124
125    // Check if a new drawBuffers call should be issued. This is called when we add or remove an attachment.
126    void drawBuffersIfNecessary(bool force);
127
128    typedef WTF::HashMap<GC3Denum, RefPtr<WebGLAttachment> > AttachmentMap;
129
130    AttachmentMap m_attachments;
131
132    bool m_hasEverBeenBound;
133
134    Vector<GC3Denum> m_drawBuffers;
135    Vector<GC3Denum> m_filteredDrawBuffers;
136};
137
138} // namespace WebCore
139
140#endif // WebGLFramebuffer_h
141