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
syncDirtyBits(Command command)88 ANGLE_INLINE angle::Result Context::syncDirtyBits(Command command)
89 {
90 const State::DirtyBits &dirtyBits = mState.getDirtyBits();
91 ANGLE_TRY(mImplementation->syncState(this, dirtyBits, mAllDirtyBits, command));
92 mState.clearDirtyBits();
93 return angle::Result::Continue;
94 }
95
syncDirtyBits(const State::DirtyBits & bitMask,Command command)96 ANGLE_INLINE angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask, Command command)
97 {
98 const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask);
99 ANGLE_TRY(mImplementation->syncState(this, dirtyBits, bitMask, command));
100 mState.clearDirtyBits(dirtyBits);
101 return angle::Result::Continue;
102 }
103
syncDirtyObjects(const State::DirtyObjects & objectMask,Command command)104 ANGLE_INLINE angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask,
105 Command command)
106 {
107 return mState.syncDirtyObjects(this, objectMask, command);
108 }
109
prepareForDraw(PrimitiveMode mode)110 ANGLE_INLINE angle::Result Context::prepareForDraw(PrimitiveMode mode)
111 {
112 if (mGLES1Renderer)
113 {
114 ANGLE_TRY(mGLES1Renderer->prepareForDraw(mode, this, &mState));
115 }
116
117 ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects, Command::Draw));
118 ASSERT(!isRobustResourceInitEnabled() ||
119 !mState.getDrawFramebuffer()->hasResourceThatNeedsInit());
120 return syncDirtyBits(Command::Draw);
121 }
122
drawArrays(PrimitiveMode mode,GLint first,GLsizei count)123 ANGLE_INLINE void Context::drawArrays(PrimitiveMode mode, GLint first, GLsizei count)
124 {
125 // No-op if count draws no primitives for given mode
126 if (noopDraw(mode, count))
127 {
128 ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
129 return;
130 }
131
132 ANGLE_CONTEXT_TRY(prepareForDraw(mode));
133 ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count));
134 MarkTransformFeedbackBufferUsage(this, count, 1);
135 }
136
drawElements(PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices)137 ANGLE_INLINE void Context::drawElements(PrimitiveMode mode,
138 GLsizei count,
139 DrawElementsType type,
140 const void *indices)
141 {
142 // No-op if count draws no primitives for given mode
143 if (noopDraw(mode, count))
144 {
145 ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
146 return;
147 }
148
149 ANGLE_CONTEXT_TRY(prepareForDraw(mode));
150 ANGLE_CONTEXT_TRY(mImplementation->drawElements(this, mode, count, type, indices));
151 }
152
onBufferBindingChange(Context * context)153 ANGLE_INLINE void StateCache::onBufferBindingChange(Context *context)
154 {
155 updateBasicDrawStatesError();
156 updateBasicDrawElementsError();
157 }
158
bindBuffer(BufferBinding target,BufferID buffer)159 ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer)
160 {
161 Buffer *bufferObject =
162 mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer);
163 mState.setBufferBinding(this, target, bufferObject);
164 mStateCache.onBufferBindingChange(this);
165 }
166
167 } // namespace gl
168
169 #endif // LIBANGLE_CONTEXT_INL_H_
170