xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/BufferGL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 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 // BufferGL.cpp: Implements the class methods for BufferGL.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/BufferGL.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/ContextGL.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/FunctionsGL.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/StateManagerGL.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/renderergl_utils.h"
20*8975f5c5SAndroid Build Coastguard Worker 
21*8975f5c5SAndroid Build Coastguard Worker namespace rx
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker 
24*8975f5c5SAndroid Build Coastguard Worker namespace
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker 
KeepBufferShadowCopy(const gl::Context * context,gl::WebGLBufferType webglType)27*8975f5c5SAndroid Build Coastguard Worker bool KeepBufferShadowCopy(const gl::Context *context, gl::WebGLBufferType webglType)
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker     // Always keep a shadow copy if the feature is enabled. This usually means there is no other way
30*8975f5c5SAndroid Build Coastguard Worker     // to read back the data.
31*8975f5c5SAndroid Build Coastguard Worker     const angle::FeaturesGL &features = GetFeaturesGL(context);
32*8975f5c5SAndroid Build Coastguard Worker     if (features.keepBufferShadowCopy.enabled)
33*8975f5c5SAndroid Build Coastguard Worker     {
34*8975f5c5SAndroid Build Coastguard Worker         return true;
35*8975f5c5SAndroid Build Coastguard Worker     }
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker     // Shadow WebGL index buffers when the driver is unable to provide robust access.
38*8975f5c5SAndroid Build Coastguard Worker     // WebGL element array buffers cannot be bound to other binding points or written to on the GPU
39*8975f5c5SAndroid Build Coastguard Worker     // so the shadowed data will never be invalidated.
40*8975f5c5SAndroid Build Coastguard Worker     if (context->isWebGL() && context->isBufferAccessValidationEnabled() &&
41*8975f5c5SAndroid Build Coastguard Worker         webglType == gl::WebGLBufferType::ElementArray)
42*8975f5c5SAndroid Build Coastguard Worker     {
43*8975f5c5SAndroid Build Coastguard Worker         return true;
44*8975f5c5SAndroid Build Coastguard Worker     }
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker     return false;
47*8975f5c5SAndroid Build Coastguard Worker }
48*8975f5c5SAndroid Build Coastguard Worker 
49*8975f5c5SAndroid Build Coastguard Worker }  // namespace
50*8975f5c5SAndroid Build Coastguard Worker 
51*8975f5c5SAndroid Build Coastguard Worker // Use the GL_COPY_READ_BUFFER binding when two buffers need to be bound simultaneously.
52*8975f5c5SAndroid Build Coastguard Worker // GL_ELEMENT_ARRAY_BUFFER is supported on more versions but can modify the state of the currently
53*8975f5c5SAndroid Build Coastguard Worker // bound VAO.  Two simultaneous buffer bindings are only needed for glCopyBufferSubData which also
54*8975f5c5SAndroid Build Coastguard Worker // adds the GL_COPY_READ_BUFFER binding.
55*8975f5c5SAndroid Build Coastguard Worker static constexpr gl::BufferBinding SourceBufferOperationTarget = gl::BufferBinding::CopyRead;
56*8975f5c5SAndroid Build Coastguard Worker 
57*8975f5c5SAndroid Build Coastguard Worker // Use the GL_ELEMENT_ARRAY_BUFFER binding for most operations since it's available on all
58*8975f5c5SAndroid Build Coastguard Worker // supported GL versions and doesn't affect any current state when it changes.
59*8975f5c5SAndroid Build Coastguard Worker static constexpr gl::BufferBinding DestBufferOperationTarget = gl::BufferBinding::Array;
60*8975f5c5SAndroid Build Coastguard Worker 
BufferGL(const gl::BufferState & state,GLuint buffer)61*8975f5c5SAndroid Build Coastguard Worker BufferGL::BufferGL(const gl::BufferState &state, GLuint buffer)
62*8975f5c5SAndroid Build Coastguard Worker     : BufferImpl(state),
63*8975f5c5SAndroid Build Coastguard Worker       mIsMapped(false),
64*8975f5c5SAndroid Build Coastguard Worker       mMapOffset(0),
65*8975f5c5SAndroid Build Coastguard Worker       mMapSize(0),
66*8975f5c5SAndroid Build Coastguard Worker       mShadowCopy(),
67*8975f5c5SAndroid Build Coastguard Worker       mBufferSize(0),
68*8975f5c5SAndroid Build Coastguard Worker       mBufferID(buffer)
69*8975f5c5SAndroid Build Coastguard Worker {}
70*8975f5c5SAndroid Build Coastguard Worker 
~BufferGL()71*8975f5c5SAndroid Build Coastguard Worker BufferGL::~BufferGL()
72*8975f5c5SAndroid Build Coastguard Worker {
73*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBufferID == 0);
74*8975f5c5SAndroid Build Coastguard Worker }
75*8975f5c5SAndroid Build Coastguard Worker 
destroy(const gl::Context * context)76*8975f5c5SAndroid Build Coastguard Worker void BufferGL::destroy(const gl::Context *context)
77*8975f5c5SAndroid Build Coastguard Worker {
78*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
79*8975f5c5SAndroid Build Coastguard Worker     stateManager->deleteBuffer(mBufferID);
80*8975f5c5SAndroid Build Coastguard Worker     mBufferID = 0;
81*8975f5c5SAndroid Build Coastguard Worker }
82*8975f5c5SAndroid Build Coastguard Worker 
setData(const gl::Context * context,gl::BufferBinding target,const void * data,size_t size,gl::BufferUsage usage)83*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::setData(const gl::Context *context,
84*8975f5c5SAndroid Build Coastguard Worker                                 gl::BufferBinding target,
85*8975f5c5SAndroid Build Coastguard Worker                                 const void *data,
86*8975f5c5SAndroid Build Coastguard Worker                                 size_t size,
87*8975f5c5SAndroid Build Coastguard Worker                                 gl::BufferUsage usage)
88*8975f5c5SAndroid Build Coastguard Worker {
89*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
90*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
91*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
92*8975f5c5SAndroid Build Coastguard Worker 
93*8975f5c5SAndroid Build Coastguard Worker     stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
94*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_TRY(context, functions->bufferData(gl::ToGLenum(DestBufferOperationTarget), size, data,
95*8975f5c5SAndroid Build Coastguard Worker                                                 ToGLenum(usage)));
96*8975f5c5SAndroid Build Coastguard Worker 
97*8975f5c5SAndroid Build Coastguard Worker     // Initialize the shadow buffer if needed. Don't delete existing shadow data. WebGL allows users
98*8975f5c5SAndroid Build Coastguard Worker     // to bind as an element array buffer first and then copy source/dest later (but not the other
99*8975f5c5SAndroid Build Coastguard Worker     // way around).
100*8975f5c5SAndroid Build Coastguard Worker     if (KeepBufferShadowCopy(context, mState.getWebGLType()) && !mShadowCopy.has_value())
101*8975f5c5SAndroid Build Coastguard Worker     {
102*8975f5c5SAndroid Build Coastguard Worker         mShadowCopy = angle::MemoryBuffer();
103*8975f5c5SAndroid Build Coastguard Worker     }
104*8975f5c5SAndroid Build Coastguard Worker 
105*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value())
106*8975f5c5SAndroid Build Coastguard Worker     {
107*8975f5c5SAndroid Build Coastguard Worker         ANGLE_CHECK_GL_ALLOC(contextGL, mShadowCopy->resize(size));
108*8975f5c5SAndroid Build Coastguard Worker 
109*8975f5c5SAndroid Build Coastguard Worker         if (size > 0 && data != nullptr)
110*8975f5c5SAndroid Build Coastguard Worker         {
111*8975f5c5SAndroid Build Coastguard Worker             memcpy(mShadowCopy->data(), data, size);
112*8975f5c5SAndroid Build Coastguard Worker         }
113*8975f5c5SAndroid Build Coastguard Worker     }
114*8975f5c5SAndroid Build Coastguard Worker 
115*8975f5c5SAndroid Build Coastguard Worker     mBufferSize = size;
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
118*8975f5c5SAndroid Build Coastguard Worker 
119*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
120*8975f5c5SAndroid Build Coastguard Worker }
121*8975f5c5SAndroid Build Coastguard Worker 
setSubData(const gl::Context * context,gl::BufferBinding target,const void * data,size_t size,size_t offset)122*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::setSubData(const gl::Context *context,
123*8975f5c5SAndroid Build Coastguard Worker                                    gl::BufferBinding target,
124*8975f5c5SAndroid Build Coastguard Worker                                    const void *data,
125*8975f5c5SAndroid Build Coastguard Worker                                    size_t size,
126*8975f5c5SAndroid Build Coastguard Worker                                    size_t offset)
127*8975f5c5SAndroid Build Coastguard Worker {
128*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
129*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
130*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
131*8975f5c5SAndroid Build Coastguard Worker 
132*8975f5c5SAndroid Build Coastguard Worker     stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
133*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_TRY(context, functions->bufferSubData(gl::ToGLenum(DestBufferOperationTarget), offset,
134*8975f5c5SAndroid Build Coastguard Worker                                                    size, data));
135*8975f5c5SAndroid Build Coastguard Worker 
136*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value() && size > 0)
137*8975f5c5SAndroid Build Coastguard Worker     {
138*8975f5c5SAndroid Build Coastguard Worker         memcpy(mShadowCopy->data() + offset, data, size);
139*8975f5c5SAndroid Build Coastguard Worker     }
140*8975f5c5SAndroid Build Coastguard Worker 
141*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
142*8975f5c5SAndroid Build Coastguard Worker 
143*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
144*8975f5c5SAndroid Build Coastguard Worker }
145*8975f5c5SAndroid Build Coastguard Worker 
copySubData(const gl::Context * context,BufferImpl * source,GLintptr sourceOffset,GLintptr destOffset,GLsizeiptr size)146*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::copySubData(const gl::Context *context,
147*8975f5c5SAndroid Build Coastguard Worker                                     BufferImpl *source,
148*8975f5c5SAndroid Build Coastguard Worker                                     GLintptr sourceOffset,
149*8975f5c5SAndroid Build Coastguard Worker                                     GLintptr destOffset,
150*8975f5c5SAndroid Build Coastguard Worker                                     GLsizeiptr size)
151*8975f5c5SAndroid Build Coastguard Worker {
152*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
153*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
154*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
155*8975f5c5SAndroid Build Coastguard Worker 
156*8975f5c5SAndroid Build Coastguard Worker     BufferGL *sourceGL = GetAs<BufferGL>(source);
157*8975f5c5SAndroid Build Coastguard Worker 
158*8975f5c5SAndroid Build Coastguard Worker     stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
159*8975f5c5SAndroid Build Coastguard Worker     stateManager->bindBuffer(SourceBufferOperationTarget, sourceGL->getBufferID());
160*8975f5c5SAndroid Build Coastguard Worker 
161*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_TRY(context, functions->copyBufferSubData(gl::ToGLenum(SourceBufferOperationTarget),
162*8975f5c5SAndroid Build Coastguard Worker                                                        gl::ToGLenum(DestBufferOperationTarget),
163*8975f5c5SAndroid Build Coastguard Worker                                                        sourceOffset, destOffset, size));
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value() && size > 0)
166*8975f5c5SAndroid Build Coastguard Worker     {
167*8975f5c5SAndroid Build Coastguard Worker         // WebGL only allows copying between buffers that are marked as the same type. Both buffers
168*8975f5c5SAndroid Build Coastguard Worker         // would have to be element array buffers and have shadow data.
169*8975f5c5SAndroid Build Coastguard Worker         ASSERT(sourceGL->mShadowCopy.has_value());
170*8975f5c5SAndroid Build Coastguard Worker 
171*8975f5c5SAndroid Build Coastguard Worker         ASSERT(sourceGL->mShadowCopy->size() >= static_cast<size_t>(sourceOffset + size));
172*8975f5c5SAndroid Build Coastguard Worker         memcpy(mShadowCopy->data() + destOffset, sourceGL->mShadowCopy->data() + sourceOffset,
173*8975f5c5SAndroid Build Coastguard Worker                size);
174*8975f5c5SAndroid Build Coastguard Worker     }
175*8975f5c5SAndroid Build Coastguard Worker 
176*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
179*8975f5c5SAndroid Build Coastguard Worker }
180*8975f5c5SAndroid Build Coastguard Worker 
map(const gl::Context * context,GLenum access,void ** mapPtr)181*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::map(const gl::Context *context, GLenum access, void **mapPtr)
182*8975f5c5SAndroid Build Coastguard Worker {
183*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
184*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
185*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value())
188*8975f5c5SAndroid Build Coastguard Worker     {
189*8975f5c5SAndroid Build Coastguard Worker         *mapPtr = mShadowCopy->data();
190*8975f5c5SAndroid Build Coastguard Worker     }
191*8975f5c5SAndroid Build Coastguard Worker     else
192*8975f5c5SAndroid Build Coastguard Worker     {
193*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
194*8975f5c5SAndroid Build Coastguard Worker         if (functions->mapBuffer)
195*8975f5c5SAndroid Build Coastguard Worker         {
196*8975f5c5SAndroid Build Coastguard Worker             *mapPtr = ANGLE_GL_TRY(
197*8975f5c5SAndroid Build Coastguard Worker                 context, functions->mapBuffer(gl::ToGLenum(DestBufferOperationTarget), access));
198*8975f5c5SAndroid Build Coastguard Worker         }
199*8975f5c5SAndroid Build Coastguard Worker         else
200*8975f5c5SAndroid Build Coastguard Worker         {
201*8975f5c5SAndroid Build Coastguard Worker             ASSERT(functions->mapBufferRange && access == GL_WRITE_ONLY_OES);
202*8975f5c5SAndroid Build Coastguard Worker             *mapPtr = ANGLE_GL_TRY(
203*8975f5c5SAndroid Build Coastguard Worker                 context, functions->mapBufferRange(gl::ToGLenum(DestBufferOperationTarget), 0,
204*8975f5c5SAndroid Build Coastguard Worker                                                    mBufferSize, GL_MAP_WRITE_BIT));
205*8975f5c5SAndroid Build Coastguard Worker         }
206*8975f5c5SAndroid Build Coastguard Worker 
207*8975f5c5SAndroid Build Coastguard Worker         // Unbind the mapped buffer from the array buffer binding. Some drivers generate errors if
208*8975f5c5SAndroid Build Coastguard Worker         // any mapped buffer is bound to array buffer bindings.
209*8975f5c5SAndroid Build Coastguard Worker         // crbug.com/1345777
210*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, 0);
211*8975f5c5SAndroid Build Coastguard Worker     }
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker     mIsMapped  = true;
214*8975f5c5SAndroid Build Coastguard Worker     mMapOffset = 0;
215*8975f5c5SAndroid Build Coastguard Worker     mMapSize   = mBufferSize;
216*8975f5c5SAndroid Build Coastguard Worker 
217*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
218*8975f5c5SAndroid Build Coastguard Worker 
219*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
220*8975f5c5SAndroid Build Coastguard Worker }
221*8975f5c5SAndroid Build Coastguard Worker 
mapRange(const gl::Context * context,size_t offset,size_t length,GLbitfield access,void ** mapPtr)222*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::mapRange(const gl::Context *context,
223*8975f5c5SAndroid Build Coastguard Worker                                  size_t offset,
224*8975f5c5SAndroid Build Coastguard Worker                                  size_t length,
225*8975f5c5SAndroid Build Coastguard Worker                                  GLbitfield access,
226*8975f5c5SAndroid Build Coastguard Worker                                  void **mapPtr)
227*8975f5c5SAndroid Build Coastguard Worker {
228*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
229*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
230*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value())
233*8975f5c5SAndroid Build Coastguard Worker     {
234*8975f5c5SAndroid Build Coastguard Worker         *mapPtr = mShadowCopy->data() + offset;
235*8975f5c5SAndroid Build Coastguard Worker     }
236*8975f5c5SAndroid Build Coastguard Worker     else
237*8975f5c5SAndroid Build Coastguard Worker     {
238*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
239*8975f5c5SAndroid Build Coastguard Worker         *mapPtr =
240*8975f5c5SAndroid Build Coastguard Worker             ANGLE_GL_TRY(context, functions->mapBufferRange(gl::ToGLenum(DestBufferOperationTarget),
241*8975f5c5SAndroid Build Coastguard Worker                                                             offset, length, access));
242*8975f5c5SAndroid Build Coastguard Worker 
243*8975f5c5SAndroid Build Coastguard Worker         // Unbind the mapped buffer from the array buffer binding. Some drivers generate errors if
244*8975f5c5SAndroid Build Coastguard Worker         // any mapped buffer is bound to array buffer bindings.
245*8975f5c5SAndroid Build Coastguard Worker         // crbug.com/1345777
246*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, 0);
247*8975f5c5SAndroid Build Coastguard Worker     }
248*8975f5c5SAndroid Build Coastguard Worker 
249*8975f5c5SAndroid Build Coastguard Worker     mIsMapped  = true;
250*8975f5c5SAndroid Build Coastguard Worker     mMapOffset = offset;
251*8975f5c5SAndroid Build Coastguard Worker     mMapSize   = length;
252*8975f5c5SAndroid Build Coastguard Worker 
253*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
254*8975f5c5SAndroid Build Coastguard Worker 
255*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
256*8975f5c5SAndroid Build Coastguard Worker }
257*8975f5c5SAndroid Build Coastguard Worker 
unmap(const gl::Context * context,GLboolean * result)258*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::unmap(const gl::Context *context, GLboolean *result)
259*8975f5c5SAndroid Build Coastguard Worker {
260*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
261*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
262*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     ASSERT(result);
265*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mIsMapped);
266*8975f5c5SAndroid Build Coastguard Worker 
267*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value())
268*8975f5c5SAndroid Build Coastguard Worker     {
269*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
270*8975f5c5SAndroid Build Coastguard Worker         ANGLE_GL_TRY(context,
271*8975f5c5SAndroid Build Coastguard Worker                      functions->bufferSubData(gl::ToGLenum(DestBufferOperationTarget), mMapOffset,
272*8975f5c5SAndroid Build Coastguard Worker                                               mMapSize, mShadowCopy->data() + mMapOffset));
273*8975f5c5SAndroid Build Coastguard Worker         *result = GL_TRUE;
274*8975f5c5SAndroid Build Coastguard Worker     }
275*8975f5c5SAndroid Build Coastguard Worker     else
276*8975f5c5SAndroid Build Coastguard Worker     {
277*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
278*8975f5c5SAndroid Build Coastguard Worker         *result =
279*8975f5c5SAndroid Build Coastguard Worker             ANGLE_GL_TRY(context, functions->unmapBuffer(gl::ToGLenum(DestBufferOperationTarget)));
280*8975f5c5SAndroid Build Coastguard Worker     }
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker     mIsMapped = false;
283*8975f5c5SAndroid Build Coastguard Worker 
284*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
285*8975f5c5SAndroid Build Coastguard Worker 
286*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
287*8975f5c5SAndroid Build Coastguard Worker }
288*8975f5c5SAndroid Build Coastguard Worker 
getIndexRange(const gl::Context * context,gl::DrawElementsType type,size_t offset,size_t count,bool primitiveRestartEnabled,gl::IndexRange * outRange)289*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferGL::getIndexRange(const gl::Context *context,
290*8975f5c5SAndroid Build Coastguard Worker                                       gl::DrawElementsType type,
291*8975f5c5SAndroid Build Coastguard Worker                                       size_t offset,
292*8975f5c5SAndroid Build Coastguard Worker                                       size_t count,
293*8975f5c5SAndroid Build Coastguard Worker                                       bool primitiveRestartEnabled,
294*8975f5c5SAndroid Build Coastguard Worker                                       gl::IndexRange *outRange)
295*8975f5c5SAndroid Build Coastguard Worker {
296*8975f5c5SAndroid Build Coastguard Worker     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
297*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *functions = GetFunctionsGL(context);
298*8975f5c5SAndroid Build Coastguard Worker     StateManagerGL *stateManager = GetStateManagerGL(context);
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mIsMapped);
301*8975f5c5SAndroid Build Coastguard Worker 
302*8975f5c5SAndroid Build Coastguard Worker     if (mShadowCopy.has_value())
303*8975f5c5SAndroid Build Coastguard Worker     {
304*8975f5c5SAndroid Build Coastguard Worker         *outRange = gl::ComputeIndexRange(type, mShadowCopy->data() + offset, count,
305*8975f5c5SAndroid Build Coastguard Worker                                           primitiveRestartEnabled);
306*8975f5c5SAndroid Build Coastguard Worker     }
307*8975f5c5SAndroid Build Coastguard Worker     else
308*8975f5c5SAndroid Build Coastguard Worker     {
309*8975f5c5SAndroid Build Coastguard Worker         stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
310*8975f5c5SAndroid Build Coastguard Worker 
311*8975f5c5SAndroid Build Coastguard Worker         const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
312*8975f5c5SAndroid Build Coastguard Worker         const uint8_t *bufferData =
313*8975f5c5SAndroid Build Coastguard Worker             MapBufferRangeWithFallback(functions, gl::ToGLenum(DestBufferOperationTarget), offset,
314*8975f5c5SAndroid Build Coastguard Worker                                        count * typeBytes, GL_MAP_READ_BIT);
315*8975f5c5SAndroid Build Coastguard Worker         if (bufferData)
316*8975f5c5SAndroid Build Coastguard Worker         {
317*8975f5c5SAndroid Build Coastguard Worker             *outRange = gl::ComputeIndexRange(type, bufferData, count, primitiveRestartEnabled);
318*8975f5c5SAndroid Build Coastguard Worker             ANGLE_GL_TRY(context, functions->unmapBuffer(gl::ToGLenum(DestBufferOperationTarget)));
319*8975f5c5SAndroid Build Coastguard Worker         }
320*8975f5c5SAndroid Build Coastguard Worker         else
321*8975f5c5SAndroid Build Coastguard Worker         {
322*8975f5c5SAndroid Build Coastguard Worker             // Workaround the null driver not having map support.
323*8975f5c5SAndroid Build Coastguard Worker             *outRange = gl::IndexRange(0, 0, 1);
324*8975f5c5SAndroid Build Coastguard Worker         }
325*8975f5c5SAndroid Build Coastguard Worker     }
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker     contextGL->markWorkSubmitted();
328*8975f5c5SAndroid Build Coastguard Worker 
329*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
330*8975f5c5SAndroid Build Coastguard Worker }
331*8975f5c5SAndroid Build Coastguard Worker 
getBufferSize() const332*8975f5c5SAndroid Build Coastguard Worker size_t BufferGL::getBufferSize() const
333*8975f5c5SAndroid Build Coastguard Worker {
334*8975f5c5SAndroid Build Coastguard Worker     return mBufferSize;
335*8975f5c5SAndroid Build Coastguard Worker }
336*8975f5c5SAndroid Build Coastguard Worker 
getBufferID() const337*8975f5c5SAndroid Build Coastguard Worker GLuint BufferGL::getBufferID() const
338*8975f5c5SAndroid Build Coastguard Worker {
339*8975f5c5SAndroid Build Coastguard Worker     return mBufferID;
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
342