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 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 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#pragma once
27
28#include "WebGLContextObject.h"
29#include "WebGLSharedObject.h"
30#include <wtf/RefCounted.h>
31
32namespace WebCore {
33
34class WebGLRenderbuffer;
35class WebGLTexture;
36
37class WebGLFramebuffer final : public WebGLContextObject {
38public:
39 class WebGLAttachment : public RefCounted<WebGLAttachment> {
40 public:
41 virtual ~WebGLAttachment();
42
43 virtual GC3Dsizei getWidth() const = 0;
44 virtual GC3Dsizei getHeight() const = 0;
45 virtual GC3Denum getFormat() const = 0;
46 virtual WebGLSharedObject* getObject() const = 0;
47 virtual bool isSharedObject(WebGLSharedObject*) const = 0;
48 virtual bool isValid() const = 0;
49 virtual bool isInitialized() const = 0;
50 virtual void setInitialized() = 0;
51 virtual void onDetached(GraphicsContext3D*) = 0;
52 virtual void attach(GraphicsContext3D*, GC3Denum attachment) = 0;
53 virtual void unattach(GraphicsContext3D*, GC3Denum attachment) = 0;
54
55 protected:
56 WebGLAttachment();
57 };
58
59 virtual ~WebGLFramebuffer();
60
61 static Ref<WebGLFramebuffer> create(WebGLRenderingContextBase&);
62
63 void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level);
64 void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*);
65 // If an object is attached to the currently bound framebuffer, remove it.
66 void removeAttachmentFromBoundFramebuffer(WebGLSharedObject*);
67 // If a given attachment point for the currently bound framebuffer is not null, remove the attached object.
68 void removeAttachmentFromBoundFramebuffer(GC3Denum);
69 WebGLSharedObject* getAttachmentObject(GC3Denum) const;
70
71 GC3Denum getColorBufferFormat() const;
72 GC3Dsizei getColorBufferWidth() const;
73 GC3Dsizei getColorBufferHeight() const;
74
75 // This should always be called before drawArray, drawElements, clear,
76 // readPixels, copyTexImage2D, copyTexSubImage2D if this framebuffer is
77 // currently bound.
78 // Return false if the framebuffer is incomplete; otherwise initialize
79 // the buffers if they haven't been initialized and
80 // needToInitializeAttachments is true.
81 bool onAccess(GraphicsContext3D*, const char** reason);
82
83 // Software version of glCheckFramebufferStatus(), except that when
84 // FRAMEBUFFER_COMPLETE is returned, it is still possible for
85 // glCheckFramebufferStatus() to return FRAMEBUFFER_UNSUPPORTED,
86 // depending on hardware implementation.
87 GC3Denum checkStatus(const char** reason) const;
88
89 bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; }
90
91 void setHasEverBeenBound() { m_hasEverBeenBound = true; }
92
93 bool hasStencilBuffer() const;
94
95 // Wrapper for drawBuffersEXT/drawBuffersARB to work around a driver bug.
96 void drawBuffers(const Vector<GC3Denum>& bufs);
97
98 GC3Denum getDrawBuffer(GC3Denum);
99
100protected:
101 WebGLFramebuffer(WebGLRenderingContextBase&);
102
103 void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override;
104
105private:
106 WebGLAttachment* getAttachment(GC3Denum) const;
107
108 // Return false if framebuffer is incomplete.
109 bool initializeAttachments(GraphicsContext3D*, const char** reason);
110
111 // Check if the framebuffer is currently bound.
112 bool isBound() const;
113
114 // attach 'attachment' at 'attachmentPoint'.
115 void attach(GC3Denum attachment, GC3Denum attachmentPoint);
116
117 // Check if a new drawBuffers call should be issued. This is called when we add or remove an attachment.
118 void drawBuffersIfNecessary(bool force);
119
120 typedef WTF::HashMap<GC3Denum, RefPtr<WebGLAttachment>> AttachmentMap;
121
122 AttachmentMap m_attachments;
123
124 bool m_hasEverBeenBound;
125
126 Vector<GC3Denum> m_drawBuffers;
127 Vector<GC3Denum> m_filteredDrawBuffers;
128};
129
130} // namespace WebCore
131