// // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or // index data. Implements GL buffer objects and related functionality. // [OpenGL ES 2.0.24] section 2.9 page 21. #ifndef LIBANGLE_BUFFER_H_ #define LIBANGLE_BUFFER_H_ #include "common/PackedEnums.h" #include "common/angleutils.h" #include "libANGLE/Debug.h" #include "libANGLE/Error.h" #include "libANGLE/IndexRangeCache.h" #include "libANGLE/Observer.h" #include "libANGLE/RefCountObject.h" namespace rx { class BufferImpl; class GLImplFactory; } // namespace rx namespace gl { class Buffer; class Context; class BufferState final : angle::NonCopyable { public: BufferState(); ~BufferState(); BufferUsage getUsage() const { return mUsage; } GLbitfield getAccessFlags() const { return mAccessFlags; } GLenum getAccess() const { return mAccess; } GLboolean isMapped() const { return mMapped; } void *getMapPointer() const { return mMapPointer; } GLint64 getMapOffset() const { return mMapOffset; } GLint64 getMapLength() const { return mMapLength; } GLint64 getSize() const { return mSize; } bool isBoundForTransformFeedback() const { return mTransformFeedbackIndexedBindingCount != 0; } private: friend class Buffer; std::string mLabel; BufferUsage mUsage; GLint64 mSize; GLbitfield mAccessFlags; GLenum mAccess; GLboolean mMapped; void *mMapPointer; GLint64 mMapOffset; GLint64 mMapLength; int mBindingCount; int mTransformFeedbackIndexedBindingCount; int mTransformFeedbackGenericBindingCount; }; class Buffer final : public RefCountObject, public LabeledObject, public angle::ObserverInterface, public angle::Subject { public: Buffer(rx::GLImplFactory *factory, GLuint id); ~Buffer() override; void onDestroy(const Context *context) override; void setLabel(const Context *context, const std::string &label) override; const std::string &getLabel() const override; angle::Result bufferData(Context *context, BufferBinding target, const void *data, GLsizeiptr size, BufferUsage usage); angle::Result bufferSubData(const Context *context, BufferBinding target, const void *data, GLsizeiptr size, GLintptr offset); angle::Result copyBufferSubData(const Context *context, Buffer *source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); angle::Result map(const Context *context, GLenum access); angle::Result mapRange(const Context *context, GLintptr offset, GLsizeiptr length, GLbitfield access); angle::Result unmap(const Context *context, GLboolean *result); // These are called when another operation changes Buffer data. void onTransformFeedback(); void onPixelPack(); angle::Result getIndexRange(const gl::Context *context, DrawElementsType type, size_t offset, size_t count, bool primitiveRestartEnabled, IndexRange *outRange) const; BufferUsage getUsage() const { return mState.mUsage; } GLbitfield getAccessFlags() const { return mState.mAccessFlags; } GLenum getAccess() const { return mState.mAccess; } GLboolean isMapped() const { return mState.mMapped; } void *getMapPointer() const { return mState.mMapPointer; } GLint64 getMapOffset() const { return mState.mMapOffset; } GLint64 getMapLength() const { return mState.mMapLength; } GLint64 getSize() const { return mState.mSize; } GLint64 getMemorySize() const; rx::BufferImpl *getImplementation() const { return mImpl; } ANGLE_INLINE bool isBound() const { return mState.mBindingCount > 0; } ANGLE_INLINE bool isBoundForTransformFeedbackAndOtherUse() const { // The transform feedback generic binding point is not an indexed binding point but it also // does not count as a non-transform-feedback use of the buffer, so we subtract it from the // binding count when checking if the buffer is bound to a non-transform-feedback location. // See https://crbug.com/853978 return mState.mTransformFeedbackIndexedBindingCount > 0 && mState.mTransformFeedbackIndexedBindingCount != mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount; } bool isDoubleBoundForTransformFeedback() const; void onTFBindingChanged(const Context *context, bool bound, bool indexed); void onNonTFBindingChanged(int incr) { mState.mBindingCount += incr; } // angle::ObserverInterface implementation. void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; private: BufferState mState; rx::BufferImpl *mImpl; angle::ObserverBinding mImplObserver; mutable IndexRangeCache mIndexRangeCache; }; } // namespace gl #endif // LIBANGLE_BUFFER_H_