1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
8*8975f5c5SAndroid Build Coastguard Worker // index data. Implements GL buffer objects and related functionality.
9*8975f5c5SAndroid Build Coastguard Worker // [OpenGL ES 2.0.24] section 2.9 page 21.
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h"
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/BufferImpl.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker namespace gl
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker namespace
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker constexpr angle::SubjectIndex kImplementationSubjectIndex = 0;
22*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kInvalidContentsObserverIndex = std::numeric_limits<size_t>::max();
23*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
24*8975f5c5SAndroid Build Coastguard Worker
BufferState()25*8975f5c5SAndroid Build Coastguard Worker BufferState::BufferState()
26*8975f5c5SAndroid Build Coastguard Worker : mLabel(),
27*8975f5c5SAndroid Build Coastguard Worker mUsage(BufferUsage::StaticDraw),
28*8975f5c5SAndroid Build Coastguard Worker mSize(0),
29*8975f5c5SAndroid Build Coastguard Worker mAccessFlags(0),
30*8975f5c5SAndroid Build Coastguard Worker mAccess(GL_WRITE_ONLY_OES),
31*8975f5c5SAndroid Build Coastguard Worker mMapped(GL_FALSE),
32*8975f5c5SAndroid Build Coastguard Worker mMapPointer(nullptr),
33*8975f5c5SAndroid Build Coastguard Worker mMapOffset(0),
34*8975f5c5SAndroid Build Coastguard Worker mMapLength(0),
35*8975f5c5SAndroid Build Coastguard Worker mBindingCount(0),
36*8975f5c5SAndroid Build Coastguard Worker mTransformFeedbackIndexedBindingCount(0),
37*8975f5c5SAndroid Build Coastguard Worker mTransformFeedbackGenericBindingCount(0),
38*8975f5c5SAndroid Build Coastguard Worker mImmutable(GL_FALSE),
39*8975f5c5SAndroid Build Coastguard Worker mStorageExtUsageFlags(0),
40*8975f5c5SAndroid Build Coastguard Worker mExternal(GL_FALSE),
41*8975f5c5SAndroid Build Coastguard Worker mWebGLType(WebGLBufferType::Undefined)
42*8975f5c5SAndroid Build Coastguard Worker {}
43*8975f5c5SAndroid Build Coastguard Worker
~BufferState()44*8975f5c5SAndroid Build Coastguard Worker BufferState::~BufferState() {}
45*8975f5c5SAndroid Build Coastguard Worker
Buffer(rx::GLImplFactory * factory,BufferID id)46*8975f5c5SAndroid Build Coastguard Worker Buffer::Buffer(rx::GLImplFactory *factory, BufferID id)
47*8975f5c5SAndroid Build Coastguard Worker : RefCountObject(factory->generateSerial(), id),
48*8975f5c5SAndroid Build Coastguard Worker mImpl(factory->createBuffer(mState)),
49*8975f5c5SAndroid Build Coastguard Worker mImplObserver(this, kImplementationSubjectIndex)
50*8975f5c5SAndroid Build Coastguard Worker {
51*8975f5c5SAndroid Build Coastguard Worker mImplObserver.bind(mImpl);
52*8975f5c5SAndroid Build Coastguard Worker }
53*8975f5c5SAndroid Build Coastguard Worker
~Buffer()54*8975f5c5SAndroid Build Coastguard Worker Buffer::~Buffer()
55*8975f5c5SAndroid Build Coastguard Worker {
56*8975f5c5SAndroid Build Coastguard Worker SafeDelete(mImpl);
57*8975f5c5SAndroid Build Coastguard Worker }
58*8975f5c5SAndroid Build Coastguard Worker
onDestroy(const Context * context)59*8975f5c5SAndroid Build Coastguard Worker void Buffer::onDestroy(const Context *context)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker mContentsObservers.clear();
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard Worker // In tests, mImpl might be null.
64*8975f5c5SAndroid Build Coastguard Worker if (mImpl)
65*8975f5c5SAndroid Build Coastguard Worker mImpl->destroy(context);
66*8975f5c5SAndroid Build Coastguard Worker }
67*8975f5c5SAndroid Build Coastguard Worker
onBind(const Context * context,BufferBinding target)68*8975f5c5SAndroid Build Coastguard Worker void Buffer::onBind(const Context *context, BufferBinding target)
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker // Note: this function is called from glBindBuffer, which does not hold the share group lock.
71*8975f5c5SAndroid Build Coastguard Worker // However, it only affects webgl contexts, where browsers already guarantees thread safety.
72*8975f5c5SAndroid Build Coastguard Worker if (!context->isWebGL())
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker return;
75*8975f5c5SAndroid Build Coastguard Worker }
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Worker if (mState.mWebGLType == WebGLBufferType::Undefined)
78*8975f5c5SAndroid Build Coastguard Worker {
79*8975f5c5SAndroid Build Coastguard Worker if (target == BufferBinding::ElementArray)
80*8975f5c5SAndroid Build Coastguard Worker {
81*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLType = WebGLBufferType::ElementArray;
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker else
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLType = WebGLBufferType::OtherData;
86*8975f5c5SAndroid Build Coastguard Worker }
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker }
89*8975f5c5SAndroid Build Coastguard Worker
setLabel(const Context * context,const std::string & label)90*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::setLabel(const Context *context, const std::string &label)
91*8975f5c5SAndroid Build Coastguard Worker {
92*8975f5c5SAndroid Build Coastguard Worker mState.mLabel = label;
93*8975f5c5SAndroid Build Coastguard Worker if (mImpl)
94*8975f5c5SAndroid Build Coastguard Worker {
95*8975f5c5SAndroid Build Coastguard Worker return mImpl->onLabelUpdate(context);
96*8975f5c5SAndroid Build Coastguard Worker }
97*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
98*8975f5c5SAndroid Build Coastguard Worker }
99*8975f5c5SAndroid Build Coastguard Worker
getLabel() const100*8975f5c5SAndroid Build Coastguard Worker const std::string &Buffer::getLabel() const
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker return mState.mLabel;
103*8975f5c5SAndroid Build Coastguard Worker }
104*8975f5c5SAndroid Build Coastguard Worker
bufferStorageExternal(Context * context,BufferBinding target,GLsizeiptr size,GLeglClientBufferEXT clientBuffer,GLbitfield flags)105*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::bufferStorageExternal(Context *context,
106*8975f5c5SAndroid Build Coastguard Worker BufferBinding target,
107*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
108*8975f5c5SAndroid Build Coastguard Worker GLeglClientBufferEXT clientBuffer,
109*8975f5c5SAndroid Build Coastguard Worker GLbitfield flags)
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker return bufferExternalDataImpl(context, target, clientBuffer, size, flags);
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker
bufferStorage(Context * context,BufferBinding target,GLsizeiptr size,const void * data,GLbitfield flags)114*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::bufferStorage(Context *context,
115*8975f5c5SAndroid Build Coastguard Worker BufferBinding target,
116*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
117*8975f5c5SAndroid Build Coastguard Worker const void *data,
118*8975f5c5SAndroid Build Coastguard Worker GLbitfield flags)
119*8975f5c5SAndroid Build Coastguard Worker {
120*8975f5c5SAndroid Build Coastguard Worker return bufferDataImpl(context, target, data, size, BufferUsage::InvalidEnum, flags);
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker
bufferData(Context * context,BufferBinding target,const void * data,GLsizeiptr size,BufferUsage usage)123*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::bufferData(Context *context,
124*8975f5c5SAndroid Build Coastguard Worker BufferBinding target,
125*8975f5c5SAndroid Build Coastguard Worker const void *data,
126*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
127*8975f5c5SAndroid Build Coastguard Worker BufferUsage usage)
128*8975f5c5SAndroid Build Coastguard Worker {
129*8975f5c5SAndroid Build Coastguard Worker GLbitfield flags = (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT_EXT);
130*8975f5c5SAndroid Build Coastguard Worker return bufferDataImpl(context, target, data, size, usage, flags);
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker
bufferDataImpl(Context * context,BufferBinding target,const void * data,GLsizeiptr size,BufferUsage usage,GLbitfield flags)133*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::bufferDataImpl(Context *context,
134*8975f5c5SAndroid Build Coastguard Worker BufferBinding target,
135*8975f5c5SAndroid Build Coastguard Worker const void *data,
136*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
137*8975f5c5SAndroid Build Coastguard Worker BufferUsage usage,
138*8975f5c5SAndroid Build Coastguard Worker GLbitfield flags)
139*8975f5c5SAndroid Build Coastguard Worker {
140*8975f5c5SAndroid Build Coastguard Worker const void *dataForImpl = data;
141*8975f5c5SAndroid Build Coastguard Worker
142*8975f5c5SAndroid Build Coastguard Worker if (mState.isMapped())
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
145*8975f5c5SAndroid Build Coastguard Worker // BufferData happens on a mapped buffer:
146*8975f5c5SAndroid Build Coastguard Worker //
147*8975f5c5SAndroid Build Coastguard Worker // If any portion of the buffer object is mapped in the current context or any context
148*8975f5c5SAndroid Build Coastguard Worker // current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
149*8975f5c5SAndroid Build Coastguard Worker // executed in each such context prior to deleting the existing data store.
150*8975f5c5SAndroid Build Coastguard Worker //
151*8975f5c5SAndroid Build Coastguard Worker GLboolean dontCare = GL_FALSE;
152*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(unmap(context, &dontCare));
153*8975f5c5SAndroid Build Coastguard Worker }
154*8975f5c5SAndroid Build Coastguard Worker
155*8975f5c5SAndroid Build Coastguard Worker // If we are using robust resource init, make sure the buffer starts cleared.
156*8975f5c5SAndroid Build Coastguard Worker // Note: the Context is checked for nullptr because of some testing code.
157*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Investigate lazier clearing.
158*8975f5c5SAndroid Build Coastguard Worker if (context && context->isRobustResourceInitEnabled() && !data && size > 0)
159*8975f5c5SAndroid Build Coastguard Worker {
160*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer *scratchBuffer = nullptr;
161*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_ALLOC(
162*8975f5c5SAndroid Build Coastguard Worker context, context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
163*8975f5c5SAndroid Build Coastguard Worker dataForImpl = scratchBuffer->data();
164*8975f5c5SAndroid Build Coastguard Worker }
165*8975f5c5SAndroid Build Coastguard Worker
166*8975f5c5SAndroid Build Coastguard Worker if (mImpl->setDataWithUsageFlags(context, target, nullptr, dataForImpl, size, usage, flags) ==
167*8975f5c5SAndroid Build Coastguard Worker angle::Result::Stop)
168*8975f5c5SAndroid Build Coastguard Worker {
169*8975f5c5SAndroid Build Coastguard Worker // If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
170*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.clear();
171*8975f5c5SAndroid Build Coastguard Worker mState.mSize = 0;
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker // Notify when storage changes.
174*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
175*8975f5c5SAndroid Build Coastguard Worker
176*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
177*8975f5c5SAndroid Build Coastguard Worker }
178*8975f5c5SAndroid Build Coastguard Worker
179*8975f5c5SAndroid Build Coastguard Worker bool wholeBuffer = size == mState.mSize;
180*8975f5c5SAndroid Build Coastguard Worker
181*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.clear();
182*8975f5c5SAndroid Build Coastguard Worker mState.mUsage = usage;
183*8975f5c5SAndroid Build Coastguard Worker mState.mSize = size;
184*8975f5c5SAndroid Build Coastguard Worker mState.mImmutable = (usage == BufferUsage::InvalidEnum);
185*8975f5c5SAndroid Build Coastguard Worker mState.mStorageExtUsageFlags = flags;
186*8975f5c5SAndroid Build Coastguard Worker
187*8975f5c5SAndroid Build Coastguard Worker // Notify when storage changes.
188*8975f5c5SAndroid Build Coastguard Worker if (wholeBuffer)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker onContentsChange();
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker else
193*8975f5c5SAndroid Build Coastguard Worker {
194*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
195*8975f5c5SAndroid Build Coastguard Worker }
196*8975f5c5SAndroid Build Coastguard Worker
197*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker
bufferExternalDataImpl(Context * context,BufferBinding target,GLeglClientBufferEXT clientBuffer,GLsizeiptr size,GLbitfield flags)200*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::bufferExternalDataImpl(Context *context,
201*8975f5c5SAndroid Build Coastguard Worker BufferBinding target,
202*8975f5c5SAndroid Build Coastguard Worker GLeglClientBufferEXT clientBuffer,
203*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
204*8975f5c5SAndroid Build Coastguard Worker GLbitfield flags)
205*8975f5c5SAndroid Build Coastguard Worker {
206*8975f5c5SAndroid Build Coastguard Worker if (mState.isMapped())
207*8975f5c5SAndroid Build Coastguard Worker {
208*8975f5c5SAndroid Build Coastguard Worker // Per the OpenGL ES 3.0 spec, buffers are implicitly unmapped when a call to
209*8975f5c5SAndroid Build Coastguard Worker // BufferData happens on a mapped buffer:
210*8975f5c5SAndroid Build Coastguard Worker //
211*8975f5c5SAndroid Build Coastguard Worker // If any portion of the buffer object is mapped in the current context or any context
212*8975f5c5SAndroid Build Coastguard Worker // current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
213*8975f5c5SAndroid Build Coastguard Worker // executed in each such context prior to deleting the existing data store.
214*8975f5c5SAndroid Build Coastguard Worker //
215*8975f5c5SAndroid Build Coastguard Worker GLboolean dontCare = GL_FALSE;
216*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(unmap(context, &dontCare));
217*8975f5c5SAndroid Build Coastguard Worker }
218*8975f5c5SAndroid Build Coastguard Worker
219*8975f5c5SAndroid Build Coastguard Worker if (mImpl->setDataWithUsageFlags(context, target, clientBuffer, nullptr, size,
220*8975f5c5SAndroid Build Coastguard Worker BufferUsage::InvalidEnum, flags) == angle::Result::Stop)
221*8975f5c5SAndroid Build Coastguard Worker {
222*8975f5c5SAndroid Build Coastguard Worker // If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
223*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.clear();
224*8975f5c5SAndroid Build Coastguard Worker mState.mSize = 0;
225*8975f5c5SAndroid Build Coastguard Worker
226*8975f5c5SAndroid Build Coastguard Worker // Notify when storage changes.
227*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
228*8975f5c5SAndroid Build Coastguard Worker
229*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
230*8975f5c5SAndroid Build Coastguard Worker }
231*8975f5c5SAndroid Build Coastguard Worker
232*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.clear();
233*8975f5c5SAndroid Build Coastguard Worker mState.mUsage = BufferUsage::InvalidEnum;
234*8975f5c5SAndroid Build Coastguard Worker mState.mSize = size;
235*8975f5c5SAndroid Build Coastguard Worker mState.mImmutable = GL_TRUE;
236*8975f5c5SAndroid Build Coastguard Worker mState.mStorageExtUsageFlags = flags;
237*8975f5c5SAndroid Build Coastguard Worker mState.mExternal = GL_TRUE;
238*8975f5c5SAndroid Build Coastguard Worker
239*8975f5c5SAndroid Build Coastguard Worker // Notify when storage changes.
240*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
241*8975f5c5SAndroid Build Coastguard Worker
242*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
243*8975f5c5SAndroid Build Coastguard Worker }
244*8975f5c5SAndroid Build Coastguard Worker
bufferSubData(const Context * context,BufferBinding target,const void * data,GLsizeiptr size,GLintptr offset)245*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::bufferSubData(const Context *context,
246*8975f5c5SAndroid Build Coastguard Worker BufferBinding target,
247*8975f5c5SAndroid Build Coastguard Worker const void *data,
248*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
249*8975f5c5SAndroid Build Coastguard Worker GLintptr offset)
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));
252*8975f5c5SAndroid Build Coastguard Worker
253*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
254*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(size));
255*8975f5c5SAndroid Build Coastguard Worker
256*8975f5c5SAndroid Build Coastguard Worker // Notify when data changes.
257*8975f5c5SAndroid Build Coastguard Worker onContentsChange();
258*8975f5c5SAndroid Build Coastguard Worker
259*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
260*8975f5c5SAndroid Build Coastguard Worker }
261*8975f5c5SAndroid Build Coastguard Worker
copyBufferSubData(const Context * context,Buffer * source,GLintptr sourceOffset,GLintptr destOffset,GLsizeiptr size)262*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::copyBufferSubData(const Context *context,
263*8975f5c5SAndroid Build Coastguard Worker Buffer *source,
264*8975f5c5SAndroid Build Coastguard Worker GLintptr sourceOffset,
265*8975f5c5SAndroid Build Coastguard Worker GLintptr destOffset,
266*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
269*8975f5c5SAndroid Build Coastguard Worker mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));
270*8975f5c5SAndroid Build Coastguard Worker
271*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset),
272*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(size));
273*8975f5c5SAndroid Build Coastguard Worker
274*8975f5c5SAndroid Build Coastguard Worker // Notify when data changes.
275*8975f5c5SAndroid Build Coastguard Worker onContentsChange();
276*8975f5c5SAndroid Build Coastguard Worker
277*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
278*8975f5c5SAndroid Build Coastguard Worker }
279*8975f5c5SAndroid Build Coastguard Worker
map(const Context * context,GLenum access)280*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::map(const Context *context, GLenum access)
281*8975f5c5SAndroid Build Coastguard Worker {
282*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mMapped);
283*8975f5c5SAndroid Build Coastguard Worker
284*8975f5c5SAndroid Build Coastguard Worker mState.mMapPointer = nullptr;
285*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));
286*8975f5c5SAndroid Build Coastguard Worker
287*8975f5c5SAndroid Build Coastguard Worker ASSERT(access == GL_WRITE_ONLY_OES);
288*8975f5c5SAndroid Build Coastguard Worker
289*8975f5c5SAndroid Build Coastguard Worker mState.mMapped = GL_TRUE;
290*8975f5c5SAndroid Build Coastguard Worker mState.mMapOffset = 0;
291*8975f5c5SAndroid Build Coastguard Worker mState.mMapLength = mState.mSize;
292*8975f5c5SAndroid Build Coastguard Worker mState.mAccess = access;
293*8975f5c5SAndroid Build Coastguard Worker mState.mAccessFlags = GL_MAP_WRITE_BIT;
294*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.clear();
295*8975f5c5SAndroid Build Coastguard Worker
296*8975f5c5SAndroid Build Coastguard Worker // Notify when state changes.
297*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectMapped);
298*8975f5c5SAndroid Build Coastguard Worker
299*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker
mapRange(const Context * context,GLintptr offset,GLsizeiptr length,GLbitfield access)302*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::mapRange(const Context *context,
303*8975f5c5SAndroid Build Coastguard Worker GLintptr offset,
304*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr length,
305*8975f5c5SAndroid Build Coastguard Worker GLbitfield access)
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mMapped);
308*8975f5c5SAndroid Build Coastguard Worker ASSERT(offset + length <= mState.mSize);
309*8975f5c5SAndroid Build Coastguard Worker
310*8975f5c5SAndroid Build Coastguard Worker mState.mMapPointer = nullptr;
311*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));
312*8975f5c5SAndroid Build Coastguard Worker
313*8975f5c5SAndroid Build Coastguard Worker mState.mMapped = GL_TRUE;
314*8975f5c5SAndroid Build Coastguard Worker mState.mMapOffset = static_cast<GLint64>(offset);
315*8975f5c5SAndroid Build Coastguard Worker mState.mMapLength = static_cast<GLint64>(length);
316*8975f5c5SAndroid Build Coastguard Worker mState.mAccess = GL_WRITE_ONLY_OES;
317*8975f5c5SAndroid Build Coastguard Worker mState.mAccessFlags = access;
318*8975f5c5SAndroid Build Coastguard Worker
319*8975f5c5SAndroid Build Coastguard Worker // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
320*8975f5c5SAndroid Build Coastguard Worker // value for GL_BUFFER_ACCESS_OES because it was written against ES2. Since there is
321*8975f5c5SAndroid Build Coastguard Worker // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
322*8975f5c5SAndroid Build Coastguard Worker // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
323*8975f5c5SAndroid Build Coastguard Worker
324*8975f5c5SAndroid Build Coastguard Worker if ((access & GL_MAP_WRITE_BIT) > 0)
325*8975f5c5SAndroid Build Coastguard Worker {
326*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
327*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(length));
328*8975f5c5SAndroid Build Coastguard Worker }
329*8975f5c5SAndroid Build Coastguard Worker
330*8975f5c5SAndroid Build Coastguard Worker // Notify when state changes.
331*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectMapped);
332*8975f5c5SAndroid Build Coastguard Worker
333*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
334*8975f5c5SAndroid Build Coastguard Worker }
335*8975f5c5SAndroid Build Coastguard Worker
unmap(const Context * context,GLboolean * result)336*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::unmap(const Context *context, GLboolean *result)
337*8975f5c5SAndroid Build Coastguard Worker {
338*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.mMapped);
339*8975f5c5SAndroid Build Coastguard Worker
340*8975f5c5SAndroid Build Coastguard Worker *result = GL_FALSE;
341*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->unmap(context, result));
342*8975f5c5SAndroid Build Coastguard Worker
343*8975f5c5SAndroid Build Coastguard Worker mState.mMapped = GL_FALSE;
344*8975f5c5SAndroid Build Coastguard Worker mState.mMapPointer = nullptr;
345*8975f5c5SAndroid Build Coastguard Worker mState.mMapOffset = 0;
346*8975f5c5SAndroid Build Coastguard Worker mState.mMapLength = 0;
347*8975f5c5SAndroid Build Coastguard Worker mState.mAccess = GL_WRITE_ONLY_OES;
348*8975f5c5SAndroid Build Coastguard Worker mState.mAccessFlags = 0;
349*8975f5c5SAndroid Build Coastguard Worker
350*8975f5c5SAndroid Build Coastguard Worker // Notify when data changes.
351*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectUnmapped);
352*8975f5c5SAndroid Build Coastguard Worker
353*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker
onDataChanged()356*8975f5c5SAndroid Build Coastguard Worker void Buffer::onDataChanged()
357*8975f5c5SAndroid Build Coastguard Worker {
358*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.clear();
359*8975f5c5SAndroid Build Coastguard Worker
360*8975f5c5SAndroid Build Coastguard Worker // Notify when data changes.
361*8975f5c5SAndroid Build Coastguard Worker onContentsChange();
362*8975f5c5SAndroid Build Coastguard Worker
363*8975f5c5SAndroid Build Coastguard Worker mImpl->onDataChanged();
364*8975f5c5SAndroid Build Coastguard Worker }
365*8975f5c5SAndroid Build Coastguard Worker
getIndexRange(const gl::Context * context,DrawElementsType type,size_t offset,size_t count,bool primitiveRestartEnabled,IndexRange * outRange) const366*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::getIndexRange(const gl::Context *context,
367*8975f5c5SAndroid Build Coastguard Worker DrawElementsType type,
368*8975f5c5SAndroid Build Coastguard Worker size_t offset,
369*8975f5c5SAndroid Build Coastguard Worker size_t count,
370*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartEnabled,
371*8975f5c5SAndroid Build Coastguard Worker IndexRange *outRange) const
372*8975f5c5SAndroid Build Coastguard Worker {
373*8975f5c5SAndroid Build Coastguard Worker if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
374*8975f5c5SAndroid Build Coastguard Worker {
375*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
376*8975f5c5SAndroid Build Coastguard Worker }
377*8975f5c5SAndroid Build Coastguard Worker
378*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
379*8975f5c5SAndroid Build Coastguard Worker mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));
380*8975f5c5SAndroid Build Coastguard Worker
381*8975f5c5SAndroid Build Coastguard Worker mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
382*8975f5c5SAndroid Build Coastguard Worker
383*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
384*8975f5c5SAndroid Build Coastguard Worker }
385*8975f5c5SAndroid Build Coastguard Worker
getMemorySize() const386*8975f5c5SAndroid Build Coastguard Worker GLint64 Buffer::getMemorySize() const
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker GLint64 implSize = mImpl->getMemorySize();
389*8975f5c5SAndroid Build Coastguard Worker return implSize > 0 ? implSize : mState.mSize;
390*8975f5c5SAndroid Build Coastguard Worker }
391*8975f5c5SAndroid Build Coastguard Worker
isDoubleBoundForTransformFeedback() const392*8975f5c5SAndroid Build Coastguard Worker bool Buffer::isDoubleBoundForTransformFeedback() const
393*8975f5c5SAndroid Build Coastguard Worker {
394*8975f5c5SAndroid Build Coastguard Worker return mState.mTransformFeedbackIndexedBindingCount > 1;
395*8975f5c5SAndroid Build Coastguard Worker }
396*8975f5c5SAndroid Build Coastguard Worker
onTFBindingChanged(const Context * context,bool bound,bool indexed)397*8975f5c5SAndroid Build Coastguard Worker void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed)
398*8975f5c5SAndroid Build Coastguard Worker {
399*8975f5c5SAndroid Build Coastguard Worker ASSERT(bound || mState.mBindingCount > 0);
400*8975f5c5SAndroid Build Coastguard Worker mState.mBindingCount += bound ? 1 : -1;
401*8975f5c5SAndroid Build Coastguard Worker if (indexed)
402*8975f5c5SAndroid Build Coastguard Worker {
403*8975f5c5SAndroid Build Coastguard Worker ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0);
404*8975f5c5SAndroid Build Coastguard Worker mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1;
405*8975f5c5SAndroid Build Coastguard Worker
406*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::BindingChanged);
407*8975f5c5SAndroid Build Coastguard Worker }
408*8975f5c5SAndroid Build Coastguard Worker else
409*8975f5c5SAndroid Build Coastguard Worker {
410*8975f5c5SAndroid Build Coastguard Worker mState.mTransformFeedbackGenericBindingCount += bound ? 1 : -1;
411*8975f5c5SAndroid Build Coastguard Worker }
412*8975f5c5SAndroid Build Coastguard Worker }
413*8975f5c5SAndroid Build Coastguard Worker
getSubData(const gl::Context * context,GLintptr offset,GLsizeiptr size,void * outData)414*8975f5c5SAndroid Build Coastguard Worker angle::Result Buffer::getSubData(const gl::Context *context,
415*8975f5c5SAndroid Build Coastguard Worker GLintptr offset,
416*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size,
417*8975f5c5SAndroid Build Coastguard Worker void *outData)
418*8975f5c5SAndroid Build Coastguard Worker {
419*8975f5c5SAndroid Build Coastguard Worker return mImpl->getSubData(context, offset, size, outData);
420*8975f5c5SAndroid Build Coastguard Worker }
421*8975f5c5SAndroid Build Coastguard Worker
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)422*8975f5c5SAndroid Build Coastguard Worker void Buffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
423*8975f5c5SAndroid Build Coastguard Worker {
424*8975f5c5SAndroid Build Coastguard Worker // Pass it along!
425*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == kImplementationSubjectIndex);
426*8975f5c5SAndroid Build Coastguard Worker ASSERT(message == angle::SubjectMessage::SubjectChanged ||
427*8975f5c5SAndroid Build Coastguard Worker message == angle::SubjectMessage::InternalMemoryAllocationChanged);
428*8975f5c5SAndroid Build Coastguard Worker onStateChange(message);
429*8975f5c5SAndroid Build Coastguard Worker }
430*8975f5c5SAndroid Build Coastguard Worker
getContentsObserverIndex(void * observer,uint32_t bufferIndex) const431*8975f5c5SAndroid Build Coastguard Worker size_t Buffer::getContentsObserverIndex(void *observer, uint32_t bufferIndex) const
432*8975f5c5SAndroid Build Coastguard Worker {
433*8975f5c5SAndroid Build Coastguard Worker ContentsObserver contentsObserver{bufferIndex, observer};
434*8975f5c5SAndroid Build Coastguard Worker for (size_t observerIndex = 0; observerIndex < mContentsObservers.size(); ++observerIndex)
435*8975f5c5SAndroid Build Coastguard Worker {
436*8975f5c5SAndroid Build Coastguard Worker if (mContentsObservers[observerIndex] == contentsObserver)
437*8975f5c5SAndroid Build Coastguard Worker {
438*8975f5c5SAndroid Build Coastguard Worker return observerIndex;
439*8975f5c5SAndroid Build Coastguard Worker }
440*8975f5c5SAndroid Build Coastguard Worker }
441*8975f5c5SAndroid Build Coastguard Worker
442*8975f5c5SAndroid Build Coastguard Worker return kInvalidContentsObserverIndex;
443*8975f5c5SAndroid Build Coastguard Worker }
444*8975f5c5SAndroid Build Coastguard Worker
addContentsObserver(VertexArray * vertexArray,uint32_t bufferIndex)445*8975f5c5SAndroid Build Coastguard Worker void Buffer::addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex)
446*8975f5c5SAndroid Build Coastguard Worker {
447*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferIndex != ContentsObserver::kBufferTextureIndex);
448*8975f5c5SAndroid Build Coastguard Worker if (getContentsObserverIndex(vertexArray, bufferIndex) == kInvalidContentsObserverIndex)
449*8975f5c5SAndroid Build Coastguard Worker {
450*8975f5c5SAndroid Build Coastguard Worker mContentsObservers.push_back({bufferIndex, vertexArray});
451*8975f5c5SAndroid Build Coastguard Worker }
452*8975f5c5SAndroid Build Coastguard Worker }
453*8975f5c5SAndroid Build Coastguard Worker
removeContentsObserverImpl(void * observer,uint32_t bufferIndex)454*8975f5c5SAndroid Build Coastguard Worker void Buffer::removeContentsObserverImpl(void *observer, uint32_t bufferIndex)
455*8975f5c5SAndroid Build Coastguard Worker {
456*8975f5c5SAndroid Build Coastguard Worker size_t foundObserver = getContentsObserverIndex(observer, bufferIndex);
457*8975f5c5SAndroid Build Coastguard Worker if (foundObserver != kInvalidContentsObserverIndex)
458*8975f5c5SAndroid Build Coastguard Worker {
459*8975f5c5SAndroid Build Coastguard Worker size_t lastObserverIndex = mContentsObservers.size() - 1;
460*8975f5c5SAndroid Build Coastguard Worker if (foundObserver != lastObserverIndex)
461*8975f5c5SAndroid Build Coastguard Worker {
462*8975f5c5SAndroid Build Coastguard Worker mContentsObservers[foundObserver] = mContentsObservers[lastObserverIndex];
463*8975f5c5SAndroid Build Coastguard Worker }
464*8975f5c5SAndroid Build Coastguard Worker mContentsObservers.pop_back();
465*8975f5c5SAndroid Build Coastguard Worker }
466*8975f5c5SAndroid Build Coastguard Worker }
467*8975f5c5SAndroid Build Coastguard Worker
removeContentsObserver(VertexArray * vertexArray,uint32_t bufferIndex)468*8975f5c5SAndroid Build Coastguard Worker void Buffer::removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex)
469*8975f5c5SAndroid Build Coastguard Worker {
470*8975f5c5SAndroid Build Coastguard Worker removeContentsObserverImpl(vertexArray, bufferIndex);
471*8975f5c5SAndroid Build Coastguard Worker }
472*8975f5c5SAndroid Build Coastguard Worker
addContentsObserver(Texture * texture)473*8975f5c5SAndroid Build Coastguard Worker void Buffer::addContentsObserver(Texture *texture)
474*8975f5c5SAndroid Build Coastguard Worker {
475*8975f5c5SAndroid Build Coastguard Worker if (!hasContentsObserver(texture))
476*8975f5c5SAndroid Build Coastguard Worker {
477*8975f5c5SAndroid Build Coastguard Worker mContentsObservers.push_back({ContentsObserver::kBufferTextureIndex, texture});
478*8975f5c5SAndroid Build Coastguard Worker }
479*8975f5c5SAndroid Build Coastguard Worker }
480*8975f5c5SAndroid Build Coastguard Worker
removeContentsObserver(Texture * texture)481*8975f5c5SAndroid Build Coastguard Worker void Buffer::removeContentsObserver(Texture *texture)
482*8975f5c5SAndroid Build Coastguard Worker {
483*8975f5c5SAndroid Build Coastguard Worker removeContentsObserverImpl(texture, ContentsObserver::kBufferTextureIndex);
484*8975f5c5SAndroid Build Coastguard Worker }
485*8975f5c5SAndroid Build Coastguard Worker
hasContentsObserver(Texture * texture) const486*8975f5c5SAndroid Build Coastguard Worker bool Buffer::hasContentsObserver(Texture *texture) const
487*8975f5c5SAndroid Build Coastguard Worker {
488*8975f5c5SAndroid Build Coastguard Worker return getContentsObserverIndex(texture, ContentsObserver::kBufferTextureIndex) !=
489*8975f5c5SAndroid Build Coastguard Worker kInvalidContentsObserverIndex;
490*8975f5c5SAndroid Build Coastguard Worker }
491*8975f5c5SAndroid Build Coastguard Worker
onContentsChange()492*8975f5c5SAndroid Build Coastguard Worker void Buffer::onContentsChange()
493*8975f5c5SAndroid Build Coastguard Worker {
494*8975f5c5SAndroid Build Coastguard Worker for (const ContentsObserver &contentsObserver : mContentsObservers)
495*8975f5c5SAndroid Build Coastguard Worker {
496*8975f5c5SAndroid Build Coastguard Worker if (contentsObserver.bufferIndex != ContentsObserver::kBufferTextureIndex)
497*8975f5c5SAndroid Build Coastguard Worker {
498*8975f5c5SAndroid Build Coastguard Worker static_cast<VertexArray *>(contentsObserver.observer)
499*8975f5c5SAndroid Build Coastguard Worker ->onBufferContentsChange(contentsObserver.bufferIndex);
500*8975f5c5SAndroid Build Coastguard Worker }
501*8975f5c5SAndroid Build Coastguard Worker else
502*8975f5c5SAndroid Build Coastguard Worker {
503*8975f5c5SAndroid Build Coastguard Worker static_cast<Texture *>(contentsObserver.observer)->onBufferContentsChange();
504*8975f5c5SAndroid Build Coastguard Worker }
505*8975f5c5SAndroid Build Coastguard Worker }
506*8975f5c5SAndroid Build Coastguard Worker }
507*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
508