• 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     // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
79     // tracked per transform feedback object
80     mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
81     if (binding.get() != nullptr)
82     {
83         const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
84         if (binding.getSize() != 0)
85         {
86             mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
87                                         bufferGL->getBufferID(), binding.getOffset(),
88                                         binding.getSize());
89         }
90         else
91         {
92             mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
93                                        bufferGL->getBufferID());
94         }
95     }
96     else
97     {
98         mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0);
99     }
100     return angle::Result::Continue;
101 }
102 
getTransformFeedbackID() const103 GLuint TransformFeedbackGL::getTransformFeedbackID() const
104 {
105     return mTransformFeedbackID;
106 }
107 
syncActiveState(const gl::Context * context,bool active,gl::PrimitiveMode primitiveMode) const108 void TransformFeedbackGL::syncActiveState(const gl::Context *context,
109                                           bool active,
110                                           gl::PrimitiveMode primitiveMode) const
111 {
112     if (mIsActive != active)
113     {
114         mIsActive = active;
115         mIsPaused = false;
116 
117         mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
118         if (mIsActive)
119         {
120             ASSERT(primitiveMode != gl::PrimitiveMode::InvalidEnum);
121             mActiveProgram = GetImplAs<ProgramGL>(mState.getBoundProgram())->getProgramID();
122             mStateManager->useProgram(mActiveProgram);
123             mFunctions->beginTransformFeedback(gl::ToGLenum(primitiveMode));
124         }
125         else
126         {
127             // Implementations disagree about what should happen if a different program is bound
128             // when calling EndTransformFeedback. We avoid the ambiguity by always re-binding the
129             // program associated with this transform feedback.
130             GLuint previousProgram = mStateManager->getProgramID();
131             mStateManager->useProgram(mActiveProgram);
132             mFunctions->endTransformFeedback();
133             // Restore the current program if we changed it.
134             mStateManager->useProgram(previousProgram);
135         }
136     }
137 }
138 
syncPausedState(bool paused) const139 void TransformFeedbackGL::syncPausedState(bool paused) const
140 {
141     if (mIsActive && mIsPaused != paused)
142     {
143         mIsPaused = paused;
144 
145         mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
146         if (mIsPaused)
147         {
148             mFunctions->pauseTransformFeedback();
149         }
150         else
151         {
152             mFunctions->resumeTransformFeedback();
153         }
154     }
155 }
156 }  // namespace rx
157