1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 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 #include "libANGLE/TransformFeedback.h"
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h"
11*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Caps.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/State.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/TransformFeedbackImpl.h"
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker #include <limits>
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker namespace gl
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker
GetVerticesNeededForDraw(PrimitiveMode primitiveMode,GLsizei count,GLsizei primcount)23*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<GLsizeiptr> GetVerticesNeededForDraw(PrimitiveMode primitiveMode,
24*8975f5c5SAndroid Build Coastguard Worker GLsizei count,
25*8975f5c5SAndroid Build Coastguard Worker GLsizei primcount)
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker if (count < 0 || primcount < 0)
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker return 0;
30*8975f5c5SAndroid Build Coastguard Worker }
31*8975f5c5SAndroid Build Coastguard Worker // Transform feedback only outputs complete primitives, so we need to round down to the nearest
32*8975f5c5SAndroid Build Coastguard Worker // complete primitive before multiplying by the number of instances.
33*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<GLsizeiptr> checkedCount = count;
34*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<GLsizeiptr> checkedPrimcount = primcount;
35*8975f5c5SAndroid Build Coastguard Worker switch (primitiveMode)
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker case PrimitiveMode::Triangles:
38*8975f5c5SAndroid Build Coastguard Worker return checkedPrimcount * (checkedCount - checkedCount % 3);
39*8975f5c5SAndroid Build Coastguard Worker case PrimitiveMode::Lines:
40*8975f5c5SAndroid Build Coastguard Worker return checkedPrimcount * (checkedCount - checkedCount % 2);
41*8975f5c5SAndroid Build Coastguard Worker case PrimitiveMode::Points:
42*8975f5c5SAndroid Build Coastguard Worker return checkedPrimcount * checkedCount;
43*8975f5c5SAndroid Build Coastguard Worker default:
44*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
45*8975f5c5SAndroid Build Coastguard Worker return checkedPrimcount * checkedCount;
46*8975f5c5SAndroid Build Coastguard Worker }
47*8975f5c5SAndroid Build Coastguard Worker }
48*8975f5c5SAndroid Build Coastguard Worker
TransformFeedbackState(size_t maxIndexedBuffers)49*8975f5c5SAndroid Build Coastguard Worker TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
50*8975f5c5SAndroid Build Coastguard Worker : mLabel(),
51*8975f5c5SAndroid Build Coastguard Worker mActive(false),
52*8975f5c5SAndroid Build Coastguard Worker mPrimitiveMode(PrimitiveMode::InvalidEnum),
53*8975f5c5SAndroid Build Coastguard Worker mPaused(false),
54*8975f5c5SAndroid Build Coastguard Worker mVerticesDrawn(0),
55*8975f5c5SAndroid Build Coastguard Worker mVertexCapacity(0),
56*8975f5c5SAndroid Build Coastguard Worker mProgram(nullptr),
57*8975f5c5SAndroid Build Coastguard Worker mIndexedBuffers(maxIndexedBuffers)
58*8975f5c5SAndroid Build Coastguard Worker {}
59*8975f5c5SAndroid Build Coastguard Worker
~TransformFeedbackState()60*8975f5c5SAndroid Build Coastguard Worker TransformFeedbackState::~TransformFeedbackState() {}
61*8975f5c5SAndroid Build Coastguard Worker
getIndexedBuffer(size_t idx) const62*8975f5c5SAndroid Build Coastguard Worker const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
63*8975f5c5SAndroid Build Coastguard Worker {
64*8975f5c5SAndroid Build Coastguard Worker return mIndexedBuffers[idx];
65*8975f5c5SAndroid Build Coastguard Worker }
66*8975f5c5SAndroid Build Coastguard Worker
getIndexedBuffers() const67*8975f5c5SAndroid Build Coastguard Worker const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
68*8975f5c5SAndroid Build Coastguard Worker {
69*8975f5c5SAndroid Build Coastguard Worker return mIndexedBuffers;
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker
getPrimitivesDrawn() const72*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr TransformFeedbackState::getPrimitivesDrawn() const
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker switch (mPrimitiveMode)
75*8975f5c5SAndroid Build Coastguard Worker {
76*8975f5c5SAndroid Build Coastguard Worker case gl::PrimitiveMode::Points:
77*8975f5c5SAndroid Build Coastguard Worker return mVerticesDrawn;
78*8975f5c5SAndroid Build Coastguard Worker case gl::PrimitiveMode::Lines:
79*8975f5c5SAndroid Build Coastguard Worker return mVerticesDrawn / 2;
80*8975f5c5SAndroid Build Coastguard Worker case gl::PrimitiveMode::Triangles:
81*8975f5c5SAndroid Build Coastguard Worker return mVerticesDrawn / 3;
82*8975f5c5SAndroid Build Coastguard Worker default:
83*8975f5c5SAndroid Build Coastguard Worker return 0;
84*8975f5c5SAndroid Build Coastguard Worker }
85*8975f5c5SAndroid Build Coastguard Worker }
86*8975f5c5SAndroid Build Coastguard Worker
TransformFeedback(rx::GLImplFactory * implFactory,TransformFeedbackID id,const Caps & caps)87*8975f5c5SAndroid Build Coastguard Worker TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory,
88*8975f5c5SAndroid Build Coastguard Worker TransformFeedbackID id,
89*8975f5c5SAndroid Build Coastguard Worker const Caps &caps)
90*8975f5c5SAndroid Build Coastguard Worker : RefCountObject(implFactory->generateSerial(), id),
91*8975f5c5SAndroid Build Coastguard Worker mState(caps.maxTransformFeedbackSeparateAttributes),
92*8975f5c5SAndroid Build Coastguard Worker mImplementation(implFactory->createTransformFeedback(mState))
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImplementation != nullptr);
95*8975f5c5SAndroid Build Coastguard Worker }
96*8975f5c5SAndroid Build Coastguard Worker
onDestroy(const Context * context)97*8975f5c5SAndroid Build Coastguard Worker void TransformFeedback::onDestroy(const Context *context)
98*8975f5c5SAndroid Build Coastguard Worker {
99*8975f5c5SAndroid Build Coastguard Worker ASSERT(!context || !context->isCurrentTransformFeedback(this));
100*8975f5c5SAndroid Build Coastguard Worker if (mState.mProgram)
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker mState.mProgram->release(context);
103*8975f5c5SAndroid Build Coastguard Worker mState.mProgram = nullptr;
104*8975f5c5SAndroid Build Coastguard Worker }
105*8975f5c5SAndroid Build Coastguard Worker
106*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mProgram);
107*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
108*8975f5c5SAndroid Build Coastguard Worker {
109*8975f5c5SAndroid Build Coastguard Worker mState.mIndexedBuffers[i].set(context, nullptr, 0, 0);
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker
112*8975f5c5SAndroid Build Coastguard Worker if (mImplementation)
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker mImplementation->onDestroy(context);
115*8975f5c5SAndroid Build Coastguard Worker }
116*8975f5c5SAndroid Build Coastguard Worker }
117*8975f5c5SAndroid Build Coastguard Worker
~TransformFeedback()118*8975f5c5SAndroid Build Coastguard Worker TransformFeedback::~TransformFeedback()
119*8975f5c5SAndroid Build Coastguard Worker {
120*8975f5c5SAndroid Build Coastguard Worker SafeDelete(mImplementation);
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker
setLabel(const Context * context,const std::string & label)123*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::setLabel(const Context *context, const std::string &label)
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker mState.mLabel = label;
126*8975f5c5SAndroid Build Coastguard Worker
127*8975f5c5SAndroid Build Coastguard Worker if (mImplementation)
128*8975f5c5SAndroid Build Coastguard Worker {
129*8975f5c5SAndroid Build Coastguard Worker return mImplementation->onLabelUpdate(context);
130*8975f5c5SAndroid Build Coastguard Worker }
131*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
132*8975f5c5SAndroid Build Coastguard Worker }
133*8975f5c5SAndroid Build Coastguard Worker
getLabel() const134*8975f5c5SAndroid Build Coastguard Worker const std::string &TransformFeedback::getLabel() const
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker return mState.mLabel;
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker
begin(const Context * context,PrimitiveMode primitiveMode,Program * program)139*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::begin(const Context *context,
140*8975f5c5SAndroid Build Coastguard Worker PrimitiveMode primitiveMode,
141*8975f5c5SAndroid Build Coastguard Worker Program *program)
142*8975f5c5SAndroid Build Coastguard Worker {
143*8975f5c5SAndroid Build Coastguard Worker // TODO: http://anglebug.com/42264023: This method should take in as parameter a
144*8975f5c5SAndroid Build Coastguard Worker // ProgramExecutable instead of a Program.
145*8975f5c5SAndroid Build Coastguard Worker
146*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImplementation->begin(context, primitiveMode));
147*8975f5c5SAndroid Build Coastguard Worker mState.mActive = true;
148*8975f5c5SAndroid Build Coastguard Worker mState.mPrimitiveMode = primitiveMode;
149*8975f5c5SAndroid Build Coastguard Worker mState.mPaused = false;
150*8975f5c5SAndroid Build Coastguard Worker mState.mVerticesDrawn = 0;
151*8975f5c5SAndroid Build Coastguard Worker bindProgram(context, program);
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker // In one of the angle_unittests - "TransformFeedbackTest.SideEffectsOfStartAndStop"
154*8975f5c5SAndroid Build Coastguard Worker // there is a code path where <context> is a nullptr, account for that possiblity.
155*8975f5c5SAndroid Build Coastguard Worker const ProgramExecutable *programExecutable =
156*8975f5c5SAndroid Build Coastguard Worker context ? context->getState().getLinkedProgramExecutable(context) : nullptr;
157*8975f5c5SAndroid Build Coastguard Worker if (programExecutable)
158*8975f5c5SAndroid Build Coastguard Worker {
159*8975f5c5SAndroid Build Coastguard Worker // Compute the number of vertices we can draw before overflowing the bound buffers.
160*8975f5c5SAndroid Build Coastguard Worker auto strides = programExecutable->getTransformFeedbackStrides();
161*8975f5c5SAndroid Build Coastguard Worker ASSERT(strides.size() <= mState.mIndexedBuffers.size() && !strides.empty());
162*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr minCapacity = std::numeric_limits<GLsizeiptr>::max();
163*8975f5c5SAndroid Build Coastguard Worker for (size_t index = 0; index < strides.size(); index++)
164*8975f5c5SAndroid Build Coastguard Worker {
165*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr capacity =
166*8975f5c5SAndroid Build Coastguard Worker GetBoundBufferAvailableSize(mState.mIndexedBuffers[index]) / strides[index];
167*8975f5c5SAndroid Build Coastguard Worker minCapacity = std::min(minCapacity, capacity);
168*8975f5c5SAndroid Build Coastguard Worker }
169*8975f5c5SAndroid Build Coastguard Worker mState.mVertexCapacity = minCapacity;
170*8975f5c5SAndroid Build Coastguard Worker }
171*8975f5c5SAndroid Build Coastguard Worker else
172*8975f5c5SAndroid Build Coastguard Worker {
173*8975f5c5SAndroid Build Coastguard Worker mState.mVertexCapacity = 0;
174*8975f5c5SAndroid Build Coastguard Worker }
175*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
176*8975f5c5SAndroid Build Coastguard Worker }
177*8975f5c5SAndroid Build Coastguard Worker
end(const Context * context)178*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::end(const Context *context)
179*8975f5c5SAndroid Build Coastguard Worker {
180*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImplementation->end(context));
181*8975f5c5SAndroid Build Coastguard Worker mState.mActive = false;
182*8975f5c5SAndroid Build Coastguard Worker mState.mPrimitiveMode = PrimitiveMode::InvalidEnum;
183*8975f5c5SAndroid Build Coastguard Worker mState.mPaused = false;
184*8975f5c5SAndroid Build Coastguard Worker mState.mVerticesDrawn = 0;
185*8975f5c5SAndroid Build Coastguard Worker mState.mVertexCapacity = 0;
186*8975f5c5SAndroid Build Coastguard Worker if (mState.mProgram)
187*8975f5c5SAndroid Build Coastguard Worker {
188*8975f5c5SAndroid Build Coastguard Worker mState.mProgram->release(context);
189*8975f5c5SAndroid Build Coastguard Worker mState.mProgram = nullptr;
190*8975f5c5SAndroid Build Coastguard Worker }
191*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker
pause(const Context * context)194*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::pause(const Context *context)
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImplementation->pause(context));
197*8975f5c5SAndroid Build Coastguard Worker mState.mPaused = true;
198*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker
resume(const Context * context)201*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::resume(const Context *context)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImplementation->resume(context));
204*8975f5c5SAndroid Build Coastguard Worker mState.mPaused = false;
205*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
206*8975f5c5SAndroid Build Coastguard Worker }
207*8975f5c5SAndroid Build Coastguard Worker
isPaused() const208*8975f5c5SAndroid Build Coastguard Worker bool TransformFeedback::isPaused() const
209*8975f5c5SAndroid Build Coastguard Worker {
210*8975f5c5SAndroid Build Coastguard Worker return mState.mPaused;
211*8975f5c5SAndroid Build Coastguard Worker }
212*8975f5c5SAndroid Build Coastguard Worker
getPrimitiveMode() const213*8975f5c5SAndroid Build Coastguard Worker PrimitiveMode TransformFeedback::getPrimitiveMode() const
214*8975f5c5SAndroid Build Coastguard Worker {
215*8975f5c5SAndroid Build Coastguard Worker return mState.mPrimitiveMode;
216*8975f5c5SAndroid Build Coastguard Worker }
217*8975f5c5SAndroid Build Coastguard Worker
checkBufferSpaceForDraw(GLsizei count,GLsizei primcount) const218*8975f5c5SAndroid Build Coastguard Worker bool TransformFeedback::checkBufferSpaceForDraw(GLsizei count, GLsizei primcount) const
219*8975f5c5SAndroid Build Coastguard Worker {
220*8975f5c5SAndroid Build Coastguard Worker auto vertices =
221*8975f5c5SAndroid Build Coastguard Worker mState.mVerticesDrawn + GetVerticesNeededForDraw(mState.mPrimitiveMode, count, primcount);
222*8975f5c5SAndroid Build Coastguard Worker return vertices.IsValid() && vertices.ValueOrDie() <= mState.mVertexCapacity;
223*8975f5c5SAndroid Build Coastguard Worker }
224*8975f5c5SAndroid Build Coastguard Worker
onVerticesDrawn(const Context * context,GLsizei count,GLsizei primcount)225*8975f5c5SAndroid Build Coastguard Worker void TransformFeedback::onVerticesDrawn(const Context *context, GLsizei count, GLsizei primcount)
226*8975f5c5SAndroid Build Coastguard Worker {
227*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.mActive && !mState.mPaused);
228*8975f5c5SAndroid Build Coastguard Worker // All draws should be validated with checkBufferSpaceForDraw so ValueOrDie should never fail.
229*8975f5c5SAndroid Build Coastguard Worker mState.mVerticesDrawn =
230*8975f5c5SAndroid Build Coastguard Worker (mState.mVerticesDrawn + GetVerticesNeededForDraw(mState.mPrimitiveMode, count, primcount))
231*8975f5c5SAndroid Build Coastguard Worker .ValueOrDie();
232*8975f5c5SAndroid Build Coastguard Worker
233*8975f5c5SAndroid Build Coastguard Worker for (auto &buffer : mState.mIndexedBuffers)
234*8975f5c5SAndroid Build Coastguard Worker {
235*8975f5c5SAndroid Build Coastguard Worker if (buffer.get() != nullptr)
236*8975f5c5SAndroid Build Coastguard Worker {
237*8975f5c5SAndroid Build Coastguard Worker buffer->onDataChanged();
238*8975f5c5SAndroid Build Coastguard Worker }
239*8975f5c5SAndroid Build Coastguard Worker }
240*8975f5c5SAndroid Build Coastguard Worker }
241*8975f5c5SAndroid Build Coastguard Worker
bindProgram(const Context * context,Program * program)242*8975f5c5SAndroid Build Coastguard Worker void TransformFeedback::bindProgram(const Context *context, Program *program)
243*8975f5c5SAndroid Build Coastguard Worker {
244*8975f5c5SAndroid Build Coastguard Worker if (mState.mProgram != program)
245*8975f5c5SAndroid Build Coastguard Worker {
246*8975f5c5SAndroid Build Coastguard Worker if (mState.mProgram != nullptr)
247*8975f5c5SAndroid Build Coastguard Worker {
248*8975f5c5SAndroid Build Coastguard Worker mState.mProgram->release(context);
249*8975f5c5SAndroid Build Coastguard Worker }
250*8975f5c5SAndroid Build Coastguard Worker mState.mProgram = program;
251*8975f5c5SAndroid Build Coastguard Worker if (mState.mProgram != nullptr)
252*8975f5c5SAndroid Build Coastguard Worker {
253*8975f5c5SAndroid Build Coastguard Worker mState.mProgram->addRef();
254*8975f5c5SAndroid Build Coastguard Worker }
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker }
257*8975f5c5SAndroid Build Coastguard Worker
hasBoundProgram(ShaderProgramID program) const258*8975f5c5SAndroid Build Coastguard Worker bool TransformFeedback::hasBoundProgram(ShaderProgramID program) const
259*8975f5c5SAndroid Build Coastguard Worker {
260*8975f5c5SAndroid Build Coastguard Worker return mState.mProgram != nullptr && mState.mProgram->id().value == program.value;
261*8975f5c5SAndroid Build Coastguard Worker }
262*8975f5c5SAndroid Build Coastguard Worker
detachBuffer(const Context * context,BufferID bufferID)263*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::detachBuffer(const Context *context, BufferID bufferID)
264*8975f5c5SAndroid Build Coastguard Worker {
265*8975f5c5SAndroid Build Coastguard Worker bool isBound = context->isCurrentTransformFeedback(this);
266*8975f5c5SAndroid Build Coastguard Worker for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker if (mState.mIndexedBuffers[index].id() == bufferID)
269*8975f5c5SAndroid Build Coastguard Worker {
270*8975f5c5SAndroid Build Coastguard Worker if (isBound)
271*8975f5c5SAndroid Build Coastguard Worker {
272*8975f5c5SAndroid Build Coastguard Worker mState.mIndexedBuffers[index]->onTFBindingChanged(context, false, true);
273*8975f5c5SAndroid Build Coastguard Worker }
274*8975f5c5SAndroid Build Coastguard Worker mState.mIndexedBuffers[index].set(context, nullptr, 0, 0);
275*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
276*8975f5c5SAndroid Build Coastguard Worker mImplementation->bindIndexedBuffer(context, index, mState.mIndexedBuffers[index]));
277*8975f5c5SAndroid Build Coastguard Worker }
278*8975f5c5SAndroid Build Coastguard Worker }
279*8975f5c5SAndroid Build Coastguard Worker
280*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
281*8975f5c5SAndroid Build Coastguard Worker }
282*8975f5c5SAndroid Build Coastguard Worker
bindIndexedBuffer(const Context * context,size_t index,Buffer * buffer,size_t offset,size_t size)283*8975f5c5SAndroid Build Coastguard Worker angle::Result TransformFeedback::bindIndexedBuffer(const Context *context,
284*8975f5c5SAndroid Build Coastguard Worker size_t index,
285*8975f5c5SAndroid Build Coastguard Worker Buffer *buffer,
286*8975f5c5SAndroid Build Coastguard Worker size_t offset,
287*8975f5c5SAndroid Build Coastguard Worker size_t size)
288*8975f5c5SAndroid Build Coastguard Worker {
289*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < mState.mIndexedBuffers.size());
290*8975f5c5SAndroid Build Coastguard Worker bool isBound = context && context->isCurrentTransformFeedback(this);
291*8975f5c5SAndroid Build Coastguard Worker if (isBound && mState.mIndexedBuffers[index].get())
292*8975f5c5SAndroid Build Coastguard Worker {
293*8975f5c5SAndroid Build Coastguard Worker mState.mIndexedBuffers[index]->onTFBindingChanged(context, false, true);
294*8975f5c5SAndroid Build Coastguard Worker }
295*8975f5c5SAndroid Build Coastguard Worker mState.mIndexedBuffers[index].set(context, buffer, offset, size);
296*8975f5c5SAndroid Build Coastguard Worker if (isBound && buffer)
297*8975f5c5SAndroid Build Coastguard Worker {
298*8975f5c5SAndroid Build Coastguard Worker buffer->onTFBindingChanged(context, true, true);
299*8975f5c5SAndroid Build Coastguard Worker }
300*8975f5c5SAndroid Build Coastguard Worker
301*8975f5c5SAndroid Build Coastguard Worker return mImplementation->bindIndexedBuffer(context, index, mState.mIndexedBuffers[index]);
302*8975f5c5SAndroid Build Coastguard Worker }
303*8975f5c5SAndroid Build Coastguard Worker
getIndexedBuffer(size_t index) const304*8975f5c5SAndroid Build Coastguard Worker const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
305*8975f5c5SAndroid Build Coastguard Worker {
306*8975f5c5SAndroid Build Coastguard Worker ASSERT(index < mState.mIndexedBuffers.size());
307*8975f5c5SAndroid Build Coastguard Worker return mState.mIndexedBuffers[index];
308*8975f5c5SAndroid Build Coastguard Worker }
309*8975f5c5SAndroid Build Coastguard Worker
getIndexedBufferCount() const310*8975f5c5SAndroid Build Coastguard Worker size_t TransformFeedback::getIndexedBufferCount() const
311*8975f5c5SAndroid Build Coastguard Worker {
312*8975f5c5SAndroid Build Coastguard Worker return mState.mIndexedBuffers.size();
313*8975f5c5SAndroid Build Coastguard Worker }
314*8975f5c5SAndroid Build Coastguard Worker
buffersBoundForOtherUseInWebGL() const315*8975f5c5SAndroid Build Coastguard Worker bool TransformFeedback::buffersBoundForOtherUseInWebGL() const
316*8975f5c5SAndroid Build Coastguard Worker {
317*8975f5c5SAndroid Build Coastguard Worker for (auto &buffer : mState.mIndexedBuffers)
318*8975f5c5SAndroid Build Coastguard Worker {
319*8975f5c5SAndroid Build Coastguard Worker if (buffer.get() && buffer->hasWebGLXFBBindingConflict(true))
320*8975f5c5SAndroid Build Coastguard Worker {
321*8975f5c5SAndroid Build Coastguard Worker return true;
322*8975f5c5SAndroid Build Coastguard Worker }
323*8975f5c5SAndroid Build Coastguard Worker }
324*8975f5c5SAndroid Build Coastguard Worker return false;
325*8975f5c5SAndroid Build Coastguard Worker }
326*8975f5c5SAndroid Build Coastguard Worker
getImplementation() const327*8975f5c5SAndroid Build Coastguard Worker rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const
328*8975f5c5SAndroid Build Coastguard Worker {
329*8975f5c5SAndroid Build Coastguard Worker return mImplementation;
330*8975f5c5SAndroid Build Coastguard Worker }
331*8975f5c5SAndroid Build Coastguard Worker
onBindingChanged(const Context * context,bool bound)332*8975f5c5SAndroid Build Coastguard Worker void TransformFeedback::onBindingChanged(const Context *context, bool bound)
333*8975f5c5SAndroid Build Coastguard Worker {
334*8975f5c5SAndroid Build Coastguard Worker for (auto &buffer : mState.mIndexedBuffers)
335*8975f5c5SAndroid Build Coastguard Worker {
336*8975f5c5SAndroid Build Coastguard Worker if (buffer.get())
337*8975f5c5SAndroid Build Coastguard Worker {
338*8975f5c5SAndroid Build Coastguard Worker buffer->onTFBindingChanged(context, bound, true);
339*8975f5c5SAndroid Build Coastguard Worker }
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker }
342*8975f5c5SAndroid Build Coastguard Worker
getIndexedBuffers() const343*8975f5c5SAndroid Build Coastguard Worker const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedback::getIndexedBuffers() const
344*8975f5c5SAndroid Build Coastguard Worker {
345*8975f5c5SAndroid Build Coastguard Worker return mState.mIndexedBuffers;
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
348