• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 // TransformFeedbackGL.cpp: Implements the class methods for TransformFeedbackGL.
8 
9 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
10 
11 #include "common/debug.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/State.h"
14 #include "libANGLE/renderer/gl/BufferGL.h"
15 #include "libANGLE/renderer/gl/FunctionsGL.h"
16 #include "libANGLE/renderer/gl/ProgramGL.h"
17 #include "libANGLE/renderer/gl/StateManagerGL.h"
18 #include "libANGLE/renderer/gl/renderergl_utils.h"
19 
20 namespace rx
21 {
22 
TransformFeedbackGL(const gl::TransformFeedbackState & state,const FunctionsGL * functions,StateManagerGL * stateManager)23 TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state,
24                                          const FunctionsGL *functions,
25                                          StateManagerGL *stateManager)
26     : TransformFeedbackImpl(state),
27       mFunctions(functions),
28       mStateManager(stateManager),
29       mTransformFeedbackID(0),
30       mIsActive(false),
31       mIsPaused(false),
32       mActiveProgram(0)
33 {
34     mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
35 }
36 
~TransformFeedbackGL()37 TransformFeedbackGL::~TransformFeedbackGL()
38 {
39     mStateManager->deleteTransformFeedback(mTransformFeedbackID);
40     mTransformFeedbackID = 0;
41 }
42 
begin(const gl::Context * context,gl::PrimitiveMode primitiveMode)43 angle::Result TransformFeedbackGL::begin(const gl::Context *context,
44                                          gl::PrimitiveMode primitiveMode)
45 {
46     mStateManager->onTransformFeedbackStateChange();
47     return angle::Result::Continue;
48 }
49 
end(const gl::Context * context)50 angle::Result TransformFeedbackGL::end(const gl::Context *context)
51 {
52     mStateManager->onTransformFeedbackStateChange();
53 
54     // Immediately end the transform feedback so that the results are visible.
55     syncActiveState(context, false, gl::PrimitiveMode::InvalidEnum);
56     return angle::Result::Continue;
57 }
58 
pause(const gl::Context * context)59 angle::Result TransformFeedbackGL::pause(const gl::Context *context)
60 {
61     mStateManager->onTransformFeedbackStateChange();
62 
63     syncPausedState(true);
64     return angle::Result::Continue;
65 }
66 
resume(const gl::Context * context)67 angle::Result TransformFeedbackGL::resume(const gl::Context *context)
68 {
69     mStateManager->onTransformFeedbackStateChange();
70     return angle::Result::Continue;
71 }
72 
bindIndexedBuffer(const gl::Context * context,size_t index,const gl::OffsetBindingPointer<gl::Buffer> & binding)73 angle::Result TransformFeedbackGL::bindIndexedBuffer(
74     const gl::Context *context,
75     size_t index,
76     const gl::OffsetBindingPointer<gl::Buffer> &binding)
77 {
78     const angle::FeaturesGL &features = GetFeaturesGL(context);
79 
80     // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
81     // tracked per transform feedback object
82     mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
83     if (binding.get() != nullptr)
84     {
85         const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
86 
87         if (features.bindTransformFeedbackBufferBeforeBindBufferRange.enabled)
88         {
89             // Generic binding will be overwritten by the bindRange/bindBase below.
90             ANGLE_GL_TRY(context, mFunctions->bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,
91                                                          bufferGL->getBufferID()));
92         }
93 
94         if (binding.getSize() != 0)
95         {
96             ANGLE_GL_TRY(context,
97                          mFunctions->bindBufferRange(
98                              GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
99                              bufferGL->getBufferID(), binding.getOffset(), binding.getSize()));
100         }
101         else
102         {
103             ANGLE_GL_TRY(context, mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,
104                                                              static_cast<GLuint>(index),
105                                                              bufferGL->getBufferID()));
106         }
107     }
108     else
109     {
110         ANGLE_GL_TRY(context, mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,
111                                                          static_cast<GLuint>(index), 0));
112     }
113     return angle::Result::Continue;
114 }
115 
getTransformFeedbackID() const116 GLuint TransformFeedbackGL::getTransformFeedbackID() const
117 {
118     return mTransformFeedbackID;
119 }
120 
syncActiveState(const gl::Context * context,bool active,gl::PrimitiveMode primitiveMode) const121 void TransformFeedbackGL::syncActiveState(const gl::Context *context,
122                                           bool active,
123                                           gl::PrimitiveMode primitiveMode) const
124 {
125     if (mIsActive != active)
126     {
127         mIsActive = active;
128         mIsPaused = false;
129 
130         mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
131         if (mIsActive)
132         {
133             ASSERT(primitiveMode != gl::PrimitiveMode::InvalidEnum);
134             mActiveProgram = GetImplAs<ProgramGL>(mState.getBoundProgram())->getProgramID();
135             mStateManager->useProgram(mActiveProgram);
136             mFunctions->beginTransformFeedback(gl::ToGLenum(primitiveMode));
137         }
138         else
139         {
140             // Implementations disagree about what should happen if a different program is bound
141             // when calling EndTransformFeedback. We avoid the ambiguity by always re-binding the
142             // program associated with this transform feedback.
143             GLuint previousProgram = mStateManager->getProgramID();
144             mStateManager->useProgram(mActiveProgram);
145             mFunctions->endTransformFeedback();
146             // Restore the current program if we changed it.
147             mStateManager->useProgram(previousProgram);
148         }
149     }
150 }
151 
syncPausedState(bool paused) const152 void TransformFeedbackGL::syncPausedState(bool paused) const
153 {
154     if (mIsActive && mIsPaused != paused)
155     {
156         mIsPaused = paused;
157 
158         mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
159         if (mIsPaused)
160         {
161             mFunctions->pauseTransformFeedback();
162         }
163         else
164         {
165             mFunctions->resumeTransformFeedback();
166         }
167     }
168 }
169 }  // namespace rx
170