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/GLES1Renderer.h"
15 #include "libANGLE/renderer/ContextImpl.h"
16
17 #define ANGLE_HANDLE_ERR(X) \
18 (void)(X); \
19 return;
20 #define ANGLE_CONTEXT_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_ERR)
21
22 namespace gl
23 {
24 constexpr angle::PackedEnumMap<PrimitiveMode, GLsizei> kMinimumPrimitiveCounts = {{
25 {PrimitiveMode::Points, 1},
26 {PrimitiveMode::Lines, 2},
27 {PrimitiveMode::LineLoop, 2},
28 {PrimitiveMode::LineStrip, 2},
29 {PrimitiveMode::Triangles, 3},
30 {PrimitiveMode::TriangleStrip, 3},
31 {PrimitiveMode::TriangleFan, 3},
32 {PrimitiveMode::LinesAdjacency, 2},
33 {PrimitiveMode::LineStripAdjacency, 2},
34 {PrimitiveMode::TrianglesAdjacency, 3},
35 {PrimitiveMode::TriangleStripAdjacency, 3},
36 }};
37
MarkTransformFeedbackBufferUsage(const Context * context,GLsizei count,GLsizei instanceCount)38 ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context,
39 GLsizei count,
40 GLsizei instanceCount)
41 {
42 if (context->getStateCache().isTransformFeedbackActiveUnpaused())
43 {
44 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
45 transformFeedback->onVerticesDrawn(context, count, instanceCount);
46 }
47 }
48
MarkShaderStorageBufferUsage(const Context * context)49 ANGLE_INLINE void MarkShaderStorageBufferUsage(const Context *context)
50 {
51 for (size_t index : context->getStateCache().getActiveShaderStorageBufferIndices())
52 {
53 gl::Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get();
54 if (buffer)
55 {
56 buffer->onDataChanged();
57 }
58 }
59 }
60
61 // Return true if the draw is a no-op, else return false.
62 // A no-op draw occurs if the count of vertices is less than the minimum required to
63 // have a valid primitive for this mode (0 for points, 0-1 for lines, 0-2 for tris).
noopDraw(PrimitiveMode mode,GLsizei count)64 ANGLE_INLINE bool Context::noopDraw(PrimitiveMode mode, GLsizei count)
65 {
66 return count < kMinimumPrimitiveCounts[mode];
67 }
68
syncDirtyBits()69 ANGLE_INLINE angle::Result Context::syncDirtyBits()
70 {
71 const State::DirtyBits &dirtyBits = mState.getDirtyBits();
72 ANGLE_TRY(mImplementation->syncState(this, dirtyBits, mAllDirtyBits));
73 mState.clearDirtyBits();
74 return angle::Result::Continue;
75 }
76
syncDirtyBits(const State::DirtyBits & bitMask)77 ANGLE_INLINE angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask)
78 {
79 const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask);
80 ANGLE_TRY(mImplementation->syncState(this, dirtyBits, bitMask));
81 mState.clearDirtyBits(dirtyBits);
82 return angle::Result::Continue;
83 }
84
syncDirtyObjects(const State::DirtyObjects & objectMask)85 ANGLE_INLINE angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask)
86 {
87 return mState.syncDirtyObjects(this, objectMask);
88 }
89
prepareForDraw(PrimitiveMode mode)90 ANGLE_INLINE angle::Result Context::prepareForDraw(PrimitiveMode mode)
91 {
92 if (mGLES1Renderer)
93 {
94 ANGLE_TRY(mGLES1Renderer->prepareForDraw(mode, this, &mState));
95 }
96
97 ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects));
98 ASSERT(!isRobustResourceInitEnabled() ||
99 !mState.getDrawFramebuffer()->hasResourceThatNeedsInit());
100 return syncDirtyBits();
101 }
102
drawArrays(PrimitiveMode mode,GLint first,GLsizei count)103 ANGLE_INLINE void Context::drawArrays(PrimitiveMode mode, GLint first, GLsizei count)
104 {
105 // No-op if count draws no primitives for given mode
106 if (noopDraw(mode, count))
107 {
108 return;
109 }
110
111 ANGLE_CONTEXT_TRY(prepareForDraw(mode));
112 ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count));
113 MarkTransformFeedbackBufferUsage(this, count, 1);
114 }
115
drawElements(PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices)116 ANGLE_INLINE void Context::drawElements(PrimitiveMode mode,
117 GLsizei count,
118 DrawElementsType type,
119 const void *indices)
120 {
121 // No-op if count draws no primitives for given mode
122 if (noopDraw(mode, count))
123 {
124 return;
125 }
126
127 ANGLE_CONTEXT_TRY(prepareForDraw(mode));
128 ANGLE_CONTEXT_TRY(mImplementation->drawElements(this, mode, count, type, indices));
129 }
130
onBufferBindingChange(Context * context)131 ANGLE_INLINE void StateCache::onBufferBindingChange(Context *context)
132 {
133 updateBasicDrawStatesError();
134 updateBasicDrawElementsError();
135 }
136
bindBuffer(BufferBinding target,BufferID buffer)137 ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer)
138 {
139 Buffer *bufferObject =
140 mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer);
141 mState.setBufferBinding(this, target, bufferObject);
142 mStateCache.onBufferBindingChange(this);
143 }
144
145 } // namespace gl
146
147 #endif // LIBANGLE_CONTEXT_INL_H_
148