Context.inl.h (5899B)
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 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 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). 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 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 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 104 ANGLE_INLINE angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask, 105 Command command) 106 { 107 return mState.syncDirtyObjects(this, objectMask, command); 108 } 109 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 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 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 153 ANGLE_INLINE void StateCache::onBufferBindingChange(Context *context) 154 { 155 updateBasicDrawStatesError(); 156 updateBasicDrawElementsError(); 157 } 158 159 ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer) 160 { 161 Buffer *bufferObject = 162 mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer); 163 164 // Early return if rebinding the same buffer 165 if (bufferObject == mState.getTargetBuffer(target)) 166 { 167 return; 168 } 169 170 mState.setBufferBinding(this, target, bufferObject); 171 mStateCache.onBufferBindingChange(this); 172 } 173 174 } // namespace gl 175 176 #endif // LIBANGLE_CONTEXT_INL_H_