• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // Context.inl.h: Defines inline functions of gl::Context class
8 // Has to be included after libANGLE/Context.h when using one
9 // of the defined functions
10 
11 #ifndef LIBANGLE_CONTEXT_INL_H_
12 #define LIBANGLE_CONTEXT_INL_H_
13 
14 #include "libANGLE/Context.h"
15 #include "libANGLE/GLES1Renderer.h"
16 #include "libANGLE/renderer/ContextImpl.h"
17 
18 #define ANGLE_HANDLE_ERR(X) \
19     (void)(X);              \
20     return;
21 #define ANGLE_CONTEXT_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_ERR)
22 
23 namespace gl
24 {
25 constexpr angle::PackedEnumMap<PrimitiveMode, GLsizei> kMinimumPrimitiveCounts = {{
26     {PrimitiveMode::Points, 1},
27     {PrimitiveMode::Lines, 2},
28     {PrimitiveMode::LineLoop, 2},
29     {PrimitiveMode::LineStrip, 2},
30     {PrimitiveMode::Triangles, 3},
31     {PrimitiveMode::TriangleStrip, 3},
32     {PrimitiveMode::TriangleFan, 3},
33     {PrimitiveMode::LinesAdjacency, 2},
34     {PrimitiveMode::LineStripAdjacency, 2},
35     {PrimitiveMode::TrianglesAdjacency, 3},
36     {PrimitiveMode::TriangleStripAdjacency, 3},
37 }};
38 
MarkTransformFeedbackBufferUsage(const Context * context,GLsizei count,GLsizei instanceCount)39 ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context,
40                                                    GLsizei count,
41                                                    GLsizei instanceCount)
42 {
43     if (context->getStateCache().isTransformFeedbackActiveUnpaused())
44     {
45         TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
46         transformFeedback->onVerticesDrawn(context, count, instanceCount);
47     }
48 }
49 
MarkShaderStorageUsage(const Context * context)50 ANGLE_INLINE void MarkShaderStorageUsage(const Context *context)
51 {
52     for (size_t index : context->getStateCache().getActiveShaderStorageBufferIndices())
53     {
54         Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get();
55         if (buffer)
56         {
57             buffer->onDataChanged();
58         }
59     }
60 
61     for (size_t index : context->getStateCache().getActiveImageUnitIndices())
62     {
63         const ImageUnit &imageUnit = context->getState().getImageUnit(index);
64         const Texture *texture     = imageUnit.texture.get();
65         if (texture)
66         {
67             texture->onStateChange(angle::SubjectMessage::ContentsChanged);
68         }
69     }
70 }
71 
72 // Return true if the draw is a no-op, else return false.
73 //  If there is no active program for the vertex or fragment shader stages, the results of vertex
74 //  and fragment shader execution will respectively be undefined. However, this is not
75 //  an error. ANGLE will treat this as a no-op.
76 //  A no-op draw occurs if the count of vertices is less than the minimum required to
77 //  have a valid primitive for this mode (0 for points, 0-1 for lines, 0-2 for tris).
noopDraw(PrimitiveMode mode,GLsizei count)78 ANGLE_INLINE bool Context::noopDraw(PrimitiveMode mode, GLsizei count) const
79 {
80     if (!mStateCache.getCanDraw())
81     {
82         return true;
83     }
84 
85     return count < kMinimumPrimitiveCounts[mode];
86 }
87 
noopMultiDraw(GLsizei drawcount)88 ANGLE_INLINE bool Context::noopMultiDraw(GLsizei drawcount) const
89 {
90     return drawcount == 0 || !mStateCache.getCanDraw();
91 }
92 
syncAllDirtyBits(Command command)93 ANGLE_INLINE angle::Result Context::syncAllDirtyBits(Command command)
94 {
95     constexpr state::DirtyBits kAllDirtyBits                 = state::DirtyBits().set();
96     constexpr state::ExtendedDirtyBits kAllExtendedDirtyBits = state::ExtendedDirtyBits().set();
97     const state::DirtyBits dirtyBits                         = mState.getDirtyBits();
98     const state::ExtendedDirtyBits extendedDirtyBits         = mState.getExtendedDirtyBits();
99     ANGLE_TRY(mImplementation->syncState(this, dirtyBits, kAllDirtyBits, extendedDirtyBits,
100                                          kAllExtendedDirtyBits, command));
101     mState.clearDirtyBits();
102     mState.clearExtendedDirtyBits();
103     return angle::Result::Continue;
104 }
105 
syncDirtyBits(const state::DirtyBits bitMask,const state::ExtendedDirtyBits extendedBitMask,Command command)106 ANGLE_INLINE angle::Result Context::syncDirtyBits(const state::DirtyBits bitMask,
107                                                   const state::ExtendedDirtyBits extendedBitMask,
108                                                   Command command)
109 {
110     const state::DirtyBits dirtyBits = (mState.getDirtyBits() & bitMask);
111     const state::ExtendedDirtyBits extendedDirtyBits =
112         (mState.getExtendedDirtyBits() & extendedBitMask);
113     ANGLE_TRY(mImplementation->syncState(this, dirtyBits, bitMask, extendedDirtyBits,
114                                          extendedBitMask, command));
115     mState.clearDirtyBits(dirtyBits);
116     mState.clearExtendedDirtyBits(extendedDirtyBits);
117     return angle::Result::Continue;
118 }
119 
syncDirtyObjects(const state::DirtyObjects & objectMask,Command command)120 ANGLE_INLINE angle::Result Context::syncDirtyObjects(const state::DirtyObjects &objectMask,
121                                                      Command command)
122 {
123     return mState.syncDirtyObjects(this, objectMask, command);
124 }
125 
prepareForDraw(PrimitiveMode mode)126 ANGLE_INLINE angle::Result Context::prepareForDraw(PrimitiveMode mode)
127 {
128     if (mGLES1Renderer)
129     {
130         ANGLE_TRY(mGLES1Renderer->prepareForDraw(mode, this, &mState, getMutableGLES1State()));
131     }
132 
133     ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects, Command::Draw));
134     ASSERT(!isRobustResourceInitEnabled() ||
135            !mState.getDrawFramebuffer()->hasResourceThatNeedsInit());
136     return syncAllDirtyBits(Command::Draw);
137 }
138 
drawArrays(PrimitiveMode mode,GLint first,GLsizei count)139 ANGLE_INLINE void Context::drawArrays(PrimitiveMode mode, GLint first, GLsizei count)
140 {
141     // No-op if count draws no primitives for given mode
142     if (noopDraw(mode, count))
143     {
144         ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
145         return;
146     }
147 
148     ANGLE_CONTEXT_TRY(prepareForDraw(mode));
149     ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count));
150     MarkTransformFeedbackBufferUsage(this, count, 1);
151 }
152 
drawElements(PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices)153 ANGLE_INLINE void Context::drawElements(PrimitiveMode mode,
154                                         GLsizei count,
155                                         DrawElementsType type,
156                                         const void *indices)
157 {
158     // No-op if count draws no primitives for given mode
159     if (noopDraw(mode, count))
160     {
161         ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
162         return;
163     }
164 
165     ANGLE_CONTEXT_TRY(prepareForDraw(mode));
166     ANGLE_CONTEXT_TRY(mImplementation->drawElements(this, mode, count, type, indices));
167 }
168 
onBufferBindingChange(Context * context)169 ANGLE_INLINE void StateCache::onBufferBindingChange(Context *context)
170 {
171     updateBasicDrawStatesError();
172     updateBasicDrawElementsError();
173 }
174 
bindBuffer(BufferBinding target,BufferID buffer)175 ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer)
176 {
177     Buffer *bufferObject =
178         mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer);
179 
180     // Early return if rebinding the same buffer
181     if (bufferObject == mState.getTargetBuffer(target))
182     {
183         return;
184     }
185 
186     mState.setBufferBinding(this, target, bufferObject);
187     mStateCache.onBufferBindingChange(this);
188 }
189 
190 }  // namespace gl
191 
192 #endif  // LIBANGLE_CONTEXT_INL_H_
193