xref: /aosp_15_r20/external/angle/src/libANGLE/Buffer.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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