1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
8 // index data. Implements GL buffer objects and related functionality.
9 // [OpenGL ES 2.0.24] section 2.9 page 21.
10 
11 #ifndef LIBANGLE_BUFFER_H_
12 #define LIBANGLE_BUFFER_H_
13 
14 #include "common/PackedEnums.h"
15 #include "common/angleutils.h"
16 #include "libANGLE/Debug.h"
17 #include "libANGLE/Error.h"
18 #include "libANGLE/IndexRangeCache.h"
19 #include "libANGLE/Observer.h"
20 #include "libANGLE/RefCountObject.h"
21 #include "libANGLE/angletypes.h"
22 
23 namespace rx
24 {
25 class BufferImpl;
26 class GLImplFactory;
27 }  // namespace rx
28 
29 namespace gl
30 {
31 class Buffer;
32 class Context;
33 
34 class BufferState final : angle::NonCopyable
35 {
36   public:
37     BufferState();
38     ~BufferState();
39 
getUsage()40     BufferUsage getUsage() const { return mUsage; }
getAccessFlags()41     GLbitfield getAccessFlags() const { return mAccessFlags; }
getAccess()42     GLenum getAccess() const { return mAccess; }
isMapped()43     GLboolean isMapped() const { return mMapped; }
getMapPointer()44     void *getMapPointer() const { return mMapPointer; }
getMapOffset()45     GLint64 getMapOffset() const { return mMapOffset; }
getMapLength()46     GLint64 getMapLength() const { return mMapLength; }
getSize()47     GLint64 getSize() const { return mSize; }
isBoundForTransformFeedback()48     bool isBoundForTransformFeedback() const { return mTransformFeedbackIndexedBindingCount != 0; }
getLabel()49     std::string getLabel() const { return mLabel; }
50 
51   private:
52     friend class Buffer;
53 
54     std::string mLabel;
55 
56     BufferUsage mUsage;
57     GLint64 mSize;
58     GLbitfield mAccessFlags;
59     GLenum mAccess;
60     GLboolean mMapped;
61     void *mMapPointer;
62     GLint64 mMapOffset;
63     GLint64 mMapLength;
64     int mBindingCount;
65     int mTransformFeedbackIndexedBindingCount;
66     int mTransformFeedbackGenericBindingCount;
67     GLboolean mImmutable;
68     GLbitfield mStorageExtUsageFlags;
69     GLboolean mExternal;
70 };
71 
72 class Buffer final : public RefCountObject<BufferID>,
73                      public LabeledObject,
74                      public angle::ObserverInterface,
75                      public angle::Subject
76 {
77   public:
78     Buffer(rx::GLImplFactory *factory, BufferID id);
79     ~Buffer() override;
80     void onDestroy(const Context *context) override;
81 
82     void setLabel(const Context *context, const std::string &label) override;
83     const std::string &getLabel() const override;
84 
85     angle::Result bufferStorageExternal(Context *context,
86                                         BufferBinding target,
87                                         GLsizeiptr size,
88                                         GLeglClientBufferEXT clientBuffer,
89                                         GLbitfield flags);
90     angle::Result bufferStorage(Context *context,
91                                 BufferBinding target,
92                                 GLsizeiptr size,
93                                 const void *data,
94                                 GLbitfield flags);
95     angle::Result bufferData(Context *context,
96                              BufferBinding target,
97                              const void *data,
98                              GLsizeiptr size,
99                              BufferUsage usage);
100     angle::Result bufferSubData(const Context *context,
101                                 BufferBinding target,
102                                 const void *data,
103                                 GLsizeiptr size,
104                                 GLintptr offset);
105     angle::Result copyBufferSubData(const Context *context,
106                                     Buffer *source,
107                                     GLintptr sourceOffset,
108                                     GLintptr destOffset,
109                                     GLsizeiptr size);
110     angle::Result map(const Context *context, GLenum access);
111     angle::Result mapRange(const Context *context,
112                            GLintptr offset,
113                            GLsizeiptr length,
114                            GLbitfield access);
115     angle::Result unmap(const Context *context, GLboolean *result);
116 
117     // These are called when another operation changes Buffer data.
118     void onDataChanged();
119 
120     angle::Result getIndexRange(const gl::Context *context,
121                                 DrawElementsType type,
122                                 size_t offset,
123                                 size_t count,
124                                 bool primitiveRestartEnabled,
125                                 IndexRange *outRange) const;
getState()126     const BufferState &getState() const { return mState; }
getUsage()127     BufferUsage getUsage() const { return mState.mUsage; }
getAccessFlags()128     GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
getAccess()129     GLenum getAccess() const { return mState.mAccess; }
isMapped()130     GLboolean isMapped() const { return mState.mMapped; }
getMapPointer()131     void *getMapPointer() const { return mState.mMapPointer; }
getMapOffset()132     GLint64 getMapOffset() const { return mState.mMapOffset; }
getMapLength()133     GLint64 getMapLength() const { return mState.mMapLength; }
getSize()134     GLint64 getSize() const { return mState.mSize; }
135     GLint64 getMemorySize() const;
isImmutable()136     GLboolean isImmutable() const { return mState.mImmutable; }
getStorageExtUsageFlags()137     GLbitfield getStorageExtUsageFlags() const { return mState.mStorageExtUsageFlags; }
138 
139     // Buffers are always initialized immediately when allocated
initState()140     InitState initState() const { return InitState::Initialized; }
141 
getImplementation()142     rx::BufferImpl *getImplementation() const { return mImpl; }
143 
isBound()144     ANGLE_INLINE bool isBound() const { return mState.mBindingCount > 0; }
145 
isBoundForTransformFeedbackAndOtherUse()146     ANGLE_INLINE bool isBoundForTransformFeedbackAndOtherUse() const
147     {
148         // The transform feedback generic binding point is not an indexed binding point but it also
149         // does not count as a non-transform-feedback use of the buffer, so we subtract it from the
150         // binding count when checking if the buffer is bound to a non-transform-feedback location.
151         // See https://crbug.com/853978
152         return mState.mTransformFeedbackIndexedBindingCount > 0 &&
153                mState.mTransformFeedbackIndexedBindingCount !=
154                    mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount;
155     }
156 
157     bool isDoubleBoundForTransformFeedback() const;
158     void onTFBindingChanged(const Context *context, bool bound, bool indexed);
onNonTFBindingChanged(int incr)159     void onNonTFBindingChanged(int incr) { mState.mBindingCount += incr; }
160     angle::Result getSubData(const gl::Context *context,
161                              GLintptr offset,
162                              GLsizeiptr size,
163                              void *outData);
164 
165     // angle::ObserverInterface implementation.
166     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
167 
168   private:
169     angle::Result bufferDataImpl(Context *context,
170                                  BufferBinding target,
171                                  const void *data,
172                                  GLsizeiptr size,
173                                  BufferUsage usage,
174                                  GLbitfield flags);
175     angle::Result bufferExternalDataImpl(Context *context,
176                                          BufferBinding target,
177                                          GLeglClientBufferEXT clientBuffer,
178                                          GLsizeiptr size,
179                                          GLbitfield flags);
180 
181     BufferState mState;
182     rx::BufferImpl *mImpl;
183     angle::ObserverBinding mImplObserver;
184 
185     mutable IndexRangeCache mIndexRangeCache;
186 };
187 
188 }  // namespace gl
189 
190 #endif  // LIBANGLE_BUFFER_H_
191