1 //
2 // Copyright (c) 2014 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 #include "libANGLE/TransformFeedback.h"
8 
9 #include "libANGLE/Buffer.h"
10 #include "libANGLE/Caps.h"
11 #include "libANGLE/ContextState.h"
12 #include "libANGLE/Program.h"
13 #include "libANGLE/renderer/GLImplFactory.h"
14 #include "libANGLE/renderer/TransformFeedbackImpl.h"
15 
16 namespace gl
17 {
18 
TransformFeedbackState(size_t maxIndexedBuffers)19 TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
20     : mLabel(),
21       mActive(false),
22       mPrimitiveMode(GL_NONE),
23       mPaused(false),
24       mProgram(nullptr),
25       mGenericBuffer(),
26       mIndexedBuffers(maxIndexedBuffers)
27 {
28 }
29 
~TransformFeedbackState()30 TransformFeedbackState::~TransformFeedbackState()
31 {
32 }
33 
getGenericBuffer() const34 const BindingPointer<Buffer> &TransformFeedbackState::getGenericBuffer() const
35 {
36     return mGenericBuffer;
37 }
38 
getIndexedBuffer(size_t idx) const39 const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
40 {
41     return mIndexedBuffers[idx];
42 }
43 
getIndexedBuffers() const44 const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
45 {
46     return mIndexedBuffers;
47 }
48 
TransformFeedback(rx::GLImplFactory * implFactory,GLuint id,const Caps & caps)49 TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps)
50     : RefCountObject(id),
51       mState(caps.maxTransformFeedbackSeparateAttributes),
52       mImplementation(implFactory->createTransformFeedback(mState))
53 {
54     ASSERT(mImplementation != nullptr);
55 }
56 
onDestroy(const Context * context)57 Error TransformFeedback::onDestroy(const Context *context)
58 {
59     if (mState.mProgram)
60     {
61         mState.mProgram->release(context);
62         mState.mProgram = nullptr;
63     }
64 
65     ASSERT(!mState.mProgram);
66     mState.mGenericBuffer.set(context, nullptr);
67     for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
68     {
69         mState.mIndexedBuffers[i].set(context, nullptr);
70     }
71 
72     return NoError();
73 }
74 
~TransformFeedback()75 TransformFeedback::~TransformFeedback()
76 {
77     SafeDelete(mImplementation);
78 }
79 
setLabel(const std::string & label)80 void TransformFeedback::setLabel(const std::string &label)
81 {
82     mState.mLabel = label;
83 }
84 
getLabel() const85 const std::string &TransformFeedback::getLabel() const
86 {
87     return mState.mLabel;
88 }
89 
begin(const Context * context,GLenum primitiveMode,Program * program)90 void TransformFeedback::begin(const Context *context, GLenum primitiveMode, Program *program)
91 {
92     mState.mActive        = true;
93     mState.mPrimitiveMode = primitiveMode;
94     mState.mPaused        = false;
95     mImplementation->begin(primitiveMode);
96     bindProgram(context, program);
97 }
98 
end(const Context * context)99 void TransformFeedback::end(const Context *context)
100 {
101     mState.mActive        = false;
102     mState.mPrimitiveMode = GL_NONE;
103     mState.mPaused        = false;
104     mImplementation->end();
105     if (mState.mProgram)
106     {
107         mState.mProgram->release(context);
108         mState.mProgram = nullptr;
109     }
110 }
111 
pause()112 void TransformFeedback::pause()
113 {
114     mState.mPaused = true;
115     mImplementation->pause();
116 }
117 
resume()118 void TransformFeedback::resume()
119 {
120     mState.mPaused = false;
121     mImplementation->resume();
122 }
123 
isActive() const124 bool TransformFeedback::isActive() const
125 {
126     return mState.mActive;
127 }
128 
isPaused() const129 bool TransformFeedback::isPaused() const
130 {
131     return mState.mPaused;
132 }
133 
getPrimitiveMode() const134 GLenum TransformFeedback::getPrimitiveMode() const
135 {
136     return mState.mPrimitiveMode;
137 }
138 
bindProgram(const Context * context,Program * program)139 void TransformFeedback::bindProgram(const Context *context, Program *program)
140 {
141     if (mState.mProgram != program)
142     {
143         if (mState.mProgram != nullptr)
144         {
145             mState.mProgram->release(context);
146         }
147         mState.mProgram = program;
148         if (mState.mProgram != nullptr)
149         {
150             mState.mProgram->addRef();
151         }
152     }
153 }
154 
hasBoundProgram(GLuint program) const155 bool TransformFeedback::hasBoundProgram(GLuint program) const
156 {
157     return mState.mProgram != nullptr && mState.mProgram->id() == program;
158 }
159 
bindGenericBuffer(const Context * context,Buffer * buffer)160 void TransformFeedback::bindGenericBuffer(const Context *context, Buffer *buffer)
161 {
162     mState.mGenericBuffer.set(context, buffer);
163     mImplementation->bindGenericBuffer(mState.mGenericBuffer);
164 }
165 
detachBuffer(const Context * context,GLuint bufferName)166 void TransformFeedback::detachBuffer(const Context *context, GLuint bufferName)
167 {
168     for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
169     {
170         if (mState.mIndexedBuffers[index].id() == bufferName)
171         {
172             mState.mIndexedBuffers[index].set(context, nullptr);
173             mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
174         }
175     }
176 
177     if (mState.mGenericBuffer.id() == bufferName)
178     {
179         mState.mGenericBuffer.set(context, nullptr);
180         mImplementation->bindGenericBuffer(mState.mGenericBuffer);
181     }
182 }
183 
getGenericBuffer() const184 const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
185 {
186     return mState.mGenericBuffer;
187 }
188 
bindIndexedBuffer(const Context * context,size_t index,Buffer * buffer,size_t offset,size_t size)189 void TransformFeedback::bindIndexedBuffer(const Context *context,
190                                           size_t index,
191                                           Buffer *buffer,
192                                           size_t offset,
193                                           size_t size)
194 {
195     ASSERT(index < mState.mIndexedBuffers.size());
196     mState.mIndexedBuffers[index].set(context, buffer, offset, size);
197     mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
198 }
199 
getIndexedBuffer(size_t index) const200 const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
201 {
202     ASSERT(index < mState.mIndexedBuffers.size());
203     return mState.mIndexedBuffers[index];
204 }
205 
getIndexedBufferCount() const206 size_t TransformFeedback::getIndexedBufferCount() const
207 {
208     return mState.mIndexedBuffers.size();
209 }
210 
getImplementation()211 rx::TransformFeedbackImpl *TransformFeedback::getImplementation()
212 {
213     return mImplementation;
214 }
215 
getImplementation() const216 const rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const
217 {
218     return mImplementation;
219 }
220 
221 }
222