1 //
2 // Copyright (c) 2002-2014 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.cpp: Implements 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 #include "libANGLE/Buffer.h"
12
13 #include "libANGLE/Context.h"
14 #include "libANGLE/renderer/BufferImpl.h"
15 #include "libANGLE/renderer/GLImplFactory.h"
16
17 namespace gl
18 {
19
BufferState()20 BufferState::BufferState()
21 : mLabel(),
22 mUsage(BufferUsage::StaticDraw),
23 mSize(0),
24 mAccessFlags(0),
25 mAccess(GL_WRITE_ONLY_OES),
26 mMapped(GL_FALSE),
27 mMapPointer(nullptr),
28 mMapOffset(0),
29 mMapLength(0)
30 {
31 }
32
~BufferState()33 BufferState::~BufferState()
34 {
35 }
36
Buffer(rx::GLImplFactory * factory,GLuint id)37 Buffer::Buffer(rx::GLImplFactory *factory, GLuint id)
38 : RefCountObject(id), mImpl(factory->createBuffer(mState))
39 {
40 }
41
~Buffer()42 Buffer::~Buffer()
43 {
44 SafeDelete(mImpl);
45 }
46
onDestroy(const Context * context)47 Error Buffer::onDestroy(const Context *context)
48 {
49 // In tests, mImpl might be null.
50 if (mImpl)
51 mImpl->destroy(context);
52 return NoError();
53 }
54
setLabel(const std::string & label)55 void Buffer::setLabel(const std::string &label)
56 {
57 mState.mLabel = label;
58 }
59
getLabel() const60 const std::string &Buffer::getLabel() const
61 {
62 return mState.mLabel;
63 }
64
bufferData(const Context * context,BufferBinding target,const void * data,GLsizeiptr size,BufferUsage usage)65 Error Buffer::bufferData(const Context *context,
66 BufferBinding target,
67 const void *data,
68 GLsizeiptr size,
69 BufferUsage usage)
70 {
71 const void *dataForImpl = data;
72
73 // If we are using robust resource init, make sure the buffer starts cleared.
74 // Note: the Context is checked for nullptr because of some testing code.
75 // TODO(jmadill): Investigate lazier clearing.
76 if (context && context->getGLState().isRobustResourceInitEnabled() && !data && size > 0)
77 {
78 angle::MemoryBuffer *scratchBuffer = nullptr;
79 ANGLE_TRY(context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
80 dataForImpl = scratchBuffer->data();
81 }
82
83 ANGLE_TRY(mImpl->setData(context, target, dataForImpl, size, usage));
84
85 mIndexRangeCache.clear();
86 mState.mUsage = usage;
87 mState.mSize = size;
88
89 return NoError();
90 }
91
bufferSubData(const Context * context,BufferBinding target,const void * data,GLsizeiptr size,GLintptr offset)92 Error Buffer::bufferSubData(const Context *context,
93 BufferBinding target,
94 const void *data,
95 GLsizeiptr size,
96 GLintptr offset)
97 {
98 ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));
99
100 mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
101
102 return NoError();
103 }
104
copyBufferSubData(const Context * context,Buffer * source,GLintptr sourceOffset,GLintptr destOffset,GLsizeiptr size)105 Error Buffer::copyBufferSubData(const Context *context,
106 Buffer *source,
107 GLintptr sourceOffset,
108 GLintptr destOffset,
109 GLsizeiptr size)
110 {
111 ANGLE_TRY(
112 mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));
113
114 mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
115
116 return NoError();
117 }
118
map(const Context * context,GLenum access)119 Error Buffer::map(const Context *context, GLenum access)
120 {
121 ASSERT(!mState.mMapped);
122
123 mState.mMapPointer = nullptr;
124 ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));
125
126 ASSERT(access == GL_WRITE_ONLY_OES);
127
128 mState.mMapped = GL_TRUE;
129 mState.mMapOffset = 0;
130 mState.mMapLength = mState.mSize;
131 mState.mAccess = access;
132 mState.mAccessFlags = GL_MAP_WRITE_BIT;
133 mIndexRangeCache.clear();
134
135 return NoError();
136 }
137
mapRange(const Context * context,GLintptr offset,GLsizeiptr length,GLbitfield access)138 Error Buffer::mapRange(const Context *context,
139 GLintptr offset,
140 GLsizeiptr length,
141 GLbitfield access)
142 {
143 ASSERT(!mState.mMapped);
144 ASSERT(offset + length <= mState.mSize);
145
146 mState.mMapPointer = nullptr;
147 ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));
148
149 mState.mMapped = GL_TRUE;
150 mState.mMapOffset = static_cast<GLint64>(offset);
151 mState.mMapLength = static_cast<GLint64>(length);
152 mState.mAccess = GL_WRITE_ONLY_OES;
153 mState.mAccessFlags = access;
154
155 // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
156 // value for GL_BUFFER_ACCESS_OES because it was written against ES2. Since there is
157 // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
158 // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
159
160 if ((access & GL_MAP_WRITE_BIT) > 0)
161 {
162 mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
163 }
164
165 return NoError();
166 }
167
unmap(const Context * context,GLboolean * result)168 Error Buffer::unmap(const Context *context, GLboolean *result)
169 {
170 ASSERT(mState.mMapped);
171
172 *result = GL_FALSE;
173 ANGLE_TRY(mImpl->unmap(context, result));
174
175 mState.mMapped = GL_FALSE;
176 mState.mMapPointer = nullptr;
177 mState.mMapOffset = 0;
178 mState.mMapLength = 0;
179 mState.mAccess = GL_WRITE_ONLY_OES;
180 mState.mAccessFlags = 0;
181
182 return NoError();
183 }
184
onTransformFeedback()185 void Buffer::onTransformFeedback()
186 {
187 mIndexRangeCache.clear();
188 }
189
onPixelUnpack()190 void Buffer::onPixelUnpack()
191 {
192 mIndexRangeCache.clear();
193 }
194
getIndexRange(const gl::Context * context,GLenum type,size_t offset,size_t count,bool primitiveRestartEnabled,IndexRange * outRange) const195 Error Buffer::getIndexRange(const gl::Context *context,
196 GLenum type,
197 size_t offset,
198 size_t count,
199 bool primitiveRestartEnabled,
200 IndexRange *outRange) const
201 {
202 if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
203 {
204 return NoError();
205 }
206
207 ANGLE_TRY(
208 mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));
209
210 mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
211
212 return NoError();
213 }
214
215 } // namespace gl
216