Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/libANGLE/Buffer.cpp
1693 views
1
//
2
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
7
// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
8
// index data. Implements GL buffer objects and related functionality.
9
// [OpenGL ES 2.0.24] section 2.9 page 21.
10
11
#include "libANGLE/Buffer.h"
12
13
#include "libANGLE/Context.h"
14
#include "libANGLE/renderer/BufferImpl.h"
15
#include "libANGLE/renderer/GLImplFactory.h"
16
17
namespace gl
18
{
19
namespace
20
{
21
constexpr angle::SubjectIndex kImplementationSubjectIndex = 0;
22
} // anonymous namespace
23
24
BufferState::BufferState()
25
: mLabel(),
26
mUsage(BufferUsage::StaticDraw),
27
mSize(0),
28
mAccessFlags(0),
29
mAccess(GL_WRITE_ONLY_OES),
30
mMapped(GL_FALSE),
31
mMapPointer(nullptr),
32
mMapOffset(0),
33
mMapLength(0),
34
mBindingCount(0),
35
mTransformFeedbackIndexedBindingCount(0),
36
mTransformFeedbackGenericBindingCount(0),
37
mImmutable(GL_FALSE),
38
mStorageExtUsageFlags(0),
39
mExternal(GL_FALSE)
40
{}
41
42
BufferState::~BufferState() {}
43
44
Buffer::Buffer(rx::GLImplFactory *factory, BufferID id)
45
: RefCountObject(factory->generateSerial(), id),
46
mImpl(factory->createBuffer(mState)),
47
mImplObserver(this, kImplementationSubjectIndex)
48
{
49
mImplObserver.bind(mImpl);
50
}
51
52
Buffer::~Buffer()
53
{
54
SafeDelete(mImpl);
55
}
56
57
void Buffer::onDestroy(const Context *context)
58
{
59
// In tests, mImpl might be null.
60
if (mImpl)
61
mImpl->destroy(context);
62
}
63
64
void Buffer::setLabel(const Context *context, const std::string &label)
65
{
66
mState.mLabel = label;
67
}
68
69
const std::string &Buffer::getLabel() const
70
{
71
return mState.mLabel;
72
}
73
74
angle::Result Buffer::bufferStorageExternal(Context *context,
75
BufferBinding target,
76
GLsizeiptr size,
77
GLeglClientBufferEXT clientBuffer,
78
GLbitfield flags)
79
{
80
return bufferExternalDataImpl(context, target, clientBuffer, size, flags);
81
}
82
83
angle::Result Buffer::bufferStorage(Context *context,
84
BufferBinding target,
85
GLsizeiptr size,
86
const void *data,
87
GLbitfield flags)
88
{
89
return bufferDataImpl(context, target, data, size, BufferUsage::InvalidEnum, flags);
90
}
91
92
angle::Result Buffer::bufferData(Context *context,
93
BufferBinding target,
94
const void *data,
95
GLsizeiptr size,
96
BufferUsage usage)
97
{
98
GLbitfield flags = (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT_EXT);
99
return bufferDataImpl(context, target, data, size, usage, flags);
100
}
101
102
angle::Result Buffer::bufferDataImpl(Context *context,
103
BufferBinding target,
104
const void *data,
105
GLsizeiptr size,
106
BufferUsage usage,
107
GLbitfield flags)
108
{
109
const void *dataForImpl = data;
110
111
if (mState.isMapped())
112
{
113
// Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
114
// BufferData happens on a mapped buffer:
115
//
116
// If any portion of the buffer object is mapped in the current context or any context
117
// current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
118
// executed in each such context prior to deleting the existing data store.
119
//
120
GLboolean dontCare = GL_FALSE;
121
ANGLE_TRY(unmap(context, &dontCare));
122
}
123
124
// If we are using robust resource init, make sure the buffer starts cleared.
125
// Note: the Context is checked for nullptr because of some testing code.
126
// TODO(jmadill): Investigate lazier clearing.
127
if (context && context->getState().isRobustResourceInitEnabled() && !data && size > 0)
128
{
129
angle::MemoryBuffer *scratchBuffer = nullptr;
130
ANGLE_CHECK_GL_ALLOC(
131
context, context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
132
dataForImpl = scratchBuffer->data();
133
}
134
135
if (mImpl->setDataWithUsageFlags(context, target, nullptr, dataForImpl, size, usage, flags) ==
136
angle::Result::Stop)
137
{
138
// If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
139
mIndexRangeCache.clear();
140
mState.mSize = 0;
141
142
// Notify when storage changes.
143
onStateChange(angle::SubjectMessage::SubjectChanged);
144
145
return angle::Result::Stop;
146
}
147
148
mIndexRangeCache.clear();
149
mState.mUsage = usage;
150
mState.mSize = size;
151
mState.mImmutable = (usage == BufferUsage::InvalidEnum);
152
mState.mStorageExtUsageFlags = flags;
153
154
// Notify when storage changes.
155
onStateChange(angle::SubjectMessage::SubjectChanged);
156
157
return angle::Result::Continue;
158
}
159
160
angle::Result Buffer::bufferExternalDataImpl(Context *context,
161
BufferBinding target,
162
GLeglClientBufferEXT clientBuffer,
163
GLsizeiptr size,
164
GLbitfield flags)
165
{
166
if (mState.isMapped())
167
{
168
// Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
169
// BufferData happens on a mapped buffer:
170
//
171
// If any portion of the buffer object is mapped in the current context or any context
172
// current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
173
// executed in each such context prior to deleting the existing data store.
174
//
175
GLboolean dontCare = GL_FALSE;
176
ANGLE_TRY(unmap(context, &dontCare));
177
}
178
179
if (mImpl->setDataWithUsageFlags(context, target, clientBuffer, nullptr, size,
180
BufferUsage::InvalidEnum, flags) == angle::Result::Stop)
181
{
182
// If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
183
mIndexRangeCache.clear();
184
mState.mSize = 0;
185
186
// Notify when storage changes.
187
onStateChange(angle::SubjectMessage::SubjectChanged);
188
189
return angle::Result::Stop;
190
}
191
192
mIndexRangeCache.clear();
193
mState.mUsage = BufferUsage::InvalidEnum;
194
mState.mSize = size;
195
mState.mImmutable = GL_TRUE;
196
mState.mStorageExtUsageFlags = flags;
197
mState.mExternal = GL_TRUE;
198
199
// Notify when storage changes.
200
onStateChange(angle::SubjectMessage::SubjectChanged);
201
202
return angle::Result::Continue;
203
}
204
205
angle::Result Buffer::bufferSubData(const Context *context,
206
BufferBinding target,
207
const void *data,
208
GLsizeiptr size,
209
GLintptr offset)
210
{
211
ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));
212
213
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
214
static_cast<unsigned int>(size));
215
216
// Notify when data changes.
217
onStateChange(angle::SubjectMessage::ContentsChanged);
218
219
return angle::Result::Continue;
220
}
221
222
angle::Result Buffer::copyBufferSubData(const Context *context,
223
Buffer *source,
224
GLintptr sourceOffset,
225
GLintptr destOffset,
226
GLsizeiptr size)
227
{
228
ANGLE_TRY(
229
mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));
230
231
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset),
232
static_cast<unsigned int>(size));
233
234
// Notify when data changes.
235
onStateChange(angle::SubjectMessage::ContentsChanged);
236
237
return angle::Result::Continue;
238
}
239
240
angle::Result Buffer::map(const Context *context, GLenum access)
241
{
242
ASSERT(!mState.mMapped);
243
244
mState.mMapPointer = nullptr;
245
ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));
246
247
ASSERT(access == GL_WRITE_ONLY_OES);
248
249
mState.mMapped = GL_TRUE;
250
mState.mMapOffset = 0;
251
mState.mMapLength = mState.mSize;
252
mState.mAccess = access;
253
mState.mAccessFlags = GL_MAP_WRITE_BIT;
254
mIndexRangeCache.clear();
255
256
// Notify when state changes.
257
onStateChange(angle::SubjectMessage::SubjectMapped);
258
259
return angle::Result::Continue;
260
}
261
262
angle::Result Buffer::mapRange(const Context *context,
263
GLintptr offset,
264
GLsizeiptr length,
265
GLbitfield access)
266
{
267
ASSERT(!mState.mMapped);
268
ASSERT(offset + length <= mState.mSize);
269
270
mState.mMapPointer = nullptr;
271
ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));
272
273
mState.mMapped = GL_TRUE;
274
mState.mMapOffset = static_cast<GLint64>(offset);
275
mState.mMapLength = static_cast<GLint64>(length);
276
mState.mAccess = GL_WRITE_ONLY_OES;
277
mState.mAccessFlags = access;
278
279
// The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
280
// value for GL_BUFFER_ACCESS_OES because it was written against ES2. Since there is
281
// no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
282
// we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
283
284
if ((access & GL_MAP_WRITE_BIT) > 0)
285
{
286
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
287
static_cast<unsigned int>(length));
288
}
289
290
// Notify when state changes.
291
onStateChange(angle::SubjectMessage::SubjectMapped);
292
293
return angle::Result::Continue;
294
}
295
296
angle::Result Buffer::unmap(const Context *context, GLboolean *result)
297
{
298
ASSERT(mState.mMapped);
299
300
*result = GL_FALSE;
301
ANGLE_TRY(mImpl->unmap(context, result));
302
303
mState.mMapped = GL_FALSE;
304
mState.mMapPointer = nullptr;
305
mState.mMapOffset = 0;
306
mState.mMapLength = 0;
307
mState.mAccess = GL_WRITE_ONLY_OES;
308
mState.mAccessFlags = 0;
309
310
// Notify when data changes.
311
onStateChange(angle::SubjectMessage::SubjectUnmapped);
312
313
return angle::Result::Continue;
314
}
315
316
void Buffer::onDataChanged()
317
{
318
mIndexRangeCache.clear();
319
320
// Notify when data changes.
321
onStateChange(angle::SubjectMessage::ContentsChanged);
322
323
mImpl->onDataChanged();
324
}
325
326
angle::Result Buffer::getIndexRange(const gl::Context *context,
327
DrawElementsType type,
328
size_t offset,
329
size_t count,
330
bool primitiveRestartEnabled,
331
IndexRange *outRange) const
332
{
333
if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
334
{
335
return angle::Result::Continue;
336
}
337
338
ANGLE_TRY(
339
mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));
340
341
mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
342
343
return angle::Result::Continue;
344
}
345
346
GLint64 Buffer::getMemorySize() const
347
{
348
GLint64 implSize = mImpl->getMemorySize();
349
return implSize > 0 ? implSize : mState.mSize;
350
}
351
352
bool Buffer::isDoubleBoundForTransformFeedback() const
353
{
354
return mState.mTransformFeedbackIndexedBindingCount > 1;
355
}
356
357
void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed)
358
{
359
ASSERT(bound || mState.mBindingCount > 0);
360
mState.mBindingCount += bound ? 1 : -1;
361
if (indexed)
362
{
363
ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0);
364
mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1;
365
366
onStateChange(angle::SubjectMessage::BindingChanged);
367
}
368
else
369
{
370
mState.mTransformFeedbackGenericBindingCount += bound ? 1 : -1;
371
}
372
}
373
374
angle::Result Buffer::getSubData(const gl::Context *context,
375
GLintptr offset,
376
GLsizeiptr size,
377
void *outData)
378
{
379
return mImpl->getSubData(context, offset, size, outData);
380
}
381
382
void Buffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
383
{
384
// Pass it along!
385
ASSERT(index == kImplementationSubjectIndex);
386
ASSERT(message == angle::SubjectMessage::SubjectChanged);
387
onStateChange(angle::SubjectMessage::SubjectChanged);
388
}
389
} // namespace gl
390
391