• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 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 // State.h: Defines the State class, encapsulating raw GL state
8 
9 #ifndef LIBANGLE_STATE_H_
10 #define LIBANGLE_STATE_H_
11 
12 #include <bitset>
13 #include <memory>
14 
15 #include "common/Color.h"
16 #include "common/angleutils.h"
17 #include "common/bitset_utils.h"
18 #include "libANGLE/Debug.h"
19 #include "libANGLE/GLES1State.h"
20 #include "libANGLE/Program.h"
21 #include "libANGLE/ProgramPipeline.h"
22 #include "libANGLE/RefCountObject.h"
23 #include "libANGLE/Renderbuffer.h"
24 #include "libANGLE/Sampler.h"
25 #include "libANGLE/Texture.h"
26 #include "libANGLE/TransformFeedback.h"
27 #include "libANGLE/Version.h"
28 #include "libANGLE/VertexArray.h"
29 #include "libANGLE/angletypes.h"
30 
31 namespace gl
32 {
33 class BufferManager;
34 struct Caps;
35 class Context;
36 class FramebufferManager;
37 class MemoryObjectManager;
38 class PathManager;
39 class ProgramPipelineManager;
40 class Query;
41 class RenderbufferManager;
42 class SamplerManager;
43 class SemaphoreManager;
44 class ShaderProgramManager;
45 class SyncManager;
46 class TextureManager;
47 class VertexArray;
48 
49 static constexpr Version ES_2_0 = Version(2, 0);
50 static constexpr Version ES_3_0 = Version(3, 0);
51 static constexpr Version ES_3_1 = Version(3, 1);
52 
53 using ContextID = uintptr_t;
54 
55 class State : angle::NonCopyable
56 {
57   public:
58     State(ContextID contextIn,
59           const State *shareContextState,
60           TextureManager *shareTextures,
61           const EGLenum clientType,
62           const Version &clientVersion,
63           bool debug,
64           bool bindGeneratesResource,
65           bool clientArraysEnabled,
66           bool robustResourceInit,
67           bool programBinaryCacheEnabled);
68     ~State();
69 
70     void initialize(Context *context);
71     void reset(const Context *context);
72 
73     // Getters
getContextID()74     ContextID getContextID() const { return mContext; }
getClientType()75     EGLenum getClientType() const { return mClientType; }
getClientMajorVersion()76     GLint getClientMajorVersion() const { return mClientVersion.major; }
getClientMinorVersion()77     GLint getClientMinorVersion() const { return mClientVersion.minor; }
getClientVersion()78     const Version &getClientVersion() const { return mClientVersion; }
getCaps()79     const Caps &getCaps() const { return mCaps; }
getTextureCaps()80     const TextureCapsMap &getTextureCaps() const { return mTextureCaps; }
getExtensions()81     const Extensions &getExtensions() const { return mExtensions; }
getLimitations()82     const Limitations &getLimitations() const { return mLimitations; }
83 
isWebGL()84     bool isWebGL() const { return mExtensions.webglCompatibility; }
85 
isWebGL1()86     bool isWebGL1() const { return (isWebGL() && mClientVersion.major == 2); }
87 
getTextureCap(GLenum internalFormat)88     const TextureCaps &getTextureCap(GLenum internalFormat) const
89     {
90         return mTextureCaps.get(internalFormat);
91     }
92 
93     // State chunk getters
94     const RasterizerState &getRasterizerState() const;
getBlendState()95     const BlendState &getBlendState() const { return mBlend; }
96     const DepthStencilState &getDepthStencilState() const;
97 
98     // Clear behavior setters & state parameter block generation function
99     void setColorClearValue(float red, float green, float blue, float alpha);
100     void setDepthClearValue(float depth);
101     void setStencilClearValue(int stencil);
102 
getColorClearValue()103     const ColorF &getColorClearValue() const { return mColorClearValue; }
getDepthClearValue()104     float getDepthClearValue() const { return mDepthClearValue; }
getStencilClearValue()105     int getStencilClearValue() const { return mStencilClearValue; }
106 
107     // Write mask manipulation
108     void setColorMask(bool red, bool green, bool blue, bool alpha);
109     void setDepthMask(bool mask);
110 
111     // Discard toggle & query
isRasterizerDiscardEnabled()112     bool isRasterizerDiscardEnabled() const { return mRasterizer.rasterizerDiscard; }
113     void setRasterizerDiscard(bool enabled);
114 
115     // Primitive restart
isPrimitiveRestartEnabled()116     bool isPrimitiveRestartEnabled() const { return mPrimitiveRestart; }
117     void setPrimitiveRestart(bool enabled);
118 
119     // Face culling state manipulation
isCullFaceEnabled()120     bool isCullFaceEnabled() const { return mRasterizer.cullFace; }
121     void setCullFace(bool enabled);
122     void setCullMode(CullFaceMode mode);
123     void setFrontFace(GLenum front);
124 
125     // Depth test state manipulation
isDepthTestEnabled()126     bool isDepthTestEnabled() const { return mDepthStencil.depthTest; }
127     void setDepthTest(bool enabled);
128     void setDepthFunc(GLenum depthFunc);
129     void setDepthRange(float zNear, float zFar);
getNearPlane()130     float getNearPlane() const { return mNearZ; }
getFarPlane()131     float getFarPlane() const { return mFarZ; }
132 
133     // Blend state manipulation
isBlendEnabled()134     bool isBlendEnabled() const { return mBlend.blend; }
135     void setBlend(bool enabled);
136     void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
137     void setBlendColor(float red, float green, float blue, float alpha);
138     void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
getBlendColor()139     const ColorF &getBlendColor() const { return mBlendColor; }
140 
141     // Stencil state maniupulation
isStencilTestEnabled()142     bool isStencilTestEnabled() const { return mDepthStencil.stencilTest; }
143     void setStencilTest(bool enabled);
144     void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
145     void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
146     void setStencilWritemask(GLuint stencilWritemask);
147     void setStencilBackWritemask(GLuint stencilBackWritemask);
148     void setStencilOperations(GLenum stencilFail,
149                               GLenum stencilPassDepthFail,
150                               GLenum stencilPassDepthPass);
151     void setStencilBackOperations(GLenum stencilBackFail,
152                                   GLenum stencilBackPassDepthFail,
153                                   GLenum stencilBackPassDepthPass);
getStencilRef()154     GLint getStencilRef() const { return mStencilRef; }
getStencilBackRef()155     GLint getStencilBackRef() const { return mStencilBackRef; }
156 
157     // Depth bias/polygon offset state manipulation
isPolygonOffsetFillEnabled()158     bool isPolygonOffsetFillEnabled() const { return mRasterizer.polygonOffsetFill; }
159     void setPolygonOffsetFill(bool enabled);
160     void setPolygonOffsetParams(GLfloat factor, GLfloat units);
161 
162     // Multisample coverage state manipulation
isSampleAlphaToCoverageEnabled()163     bool isSampleAlphaToCoverageEnabled() const { return mBlend.sampleAlphaToCoverage; }
164     void setSampleAlphaToCoverage(bool enabled);
isSampleCoverageEnabled()165     bool isSampleCoverageEnabled() const { return mSampleCoverage; }
166     void setSampleCoverage(bool enabled);
167     void setSampleCoverageParams(GLclampf value, bool invert);
getSampleCoverageValue()168     GLclampf getSampleCoverageValue() const { return mSampleCoverageValue; }
getSampleCoverageInvert()169     bool getSampleCoverageInvert() const { return mSampleCoverageInvert; }
170 
171     // Multisample mask state manipulation.
isSampleMaskEnabled()172     bool isSampleMaskEnabled() const { return mSampleMask; }
173     void setSampleMaskEnabled(bool enabled);
174     void setSampleMaskParams(GLuint maskNumber, GLbitfield mask);
getSampleMaskWord(GLuint maskNumber)175     GLbitfield getSampleMaskWord(GLuint maskNumber) const
176     {
177         ASSERT(maskNumber < mMaxSampleMaskWords);
178         return mSampleMaskValues[maskNumber];
179     }
getMaxSampleMaskWords()180     GLuint getMaxSampleMaskWords() const { return mMaxSampleMaskWords; }
181 
182     // Multisampling/alpha to one manipulation.
183     void setSampleAlphaToOne(bool enabled);
isSampleAlphaToOneEnabled()184     bool isSampleAlphaToOneEnabled() const { return mSampleAlphaToOne; }
185     void setMultisampling(bool enabled);
isMultisamplingEnabled()186     bool isMultisamplingEnabled() const { return mMultiSampling; }
187 
188     // Scissor test state toggle & query
isScissorTestEnabled()189     bool isScissorTestEnabled() const { return mScissorTest; }
190     void setScissorTest(bool enabled);
191     void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
getScissor()192     const Rectangle &getScissor() const { return mScissor; }
193 
194     // Dither state toggle & query
isDitherEnabled()195     bool isDitherEnabled() const { return mBlend.dither; }
196     void setDither(bool enabled);
197 
198     // Generic state toggle & query
199     void setEnableFeature(GLenum feature, bool enabled);
200     bool getEnableFeature(GLenum feature) const;
201 
202     // Line width state setter
203     void setLineWidth(GLfloat width);
getLineWidth()204     float getLineWidth() const { return mLineWidth; }
205 
206     // Hint setters
207     void setGenerateMipmapHint(GLenum hint);
208     void setFragmentShaderDerivativeHint(GLenum hint);
209 
210     // GL_CHROMIUM_bind_generates_resource
isBindGeneratesResourceEnabled()211     bool isBindGeneratesResourceEnabled() const { return mBindGeneratesResource; }
212 
213     // GL_ANGLE_client_arrays
areClientArraysEnabled()214     bool areClientArraysEnabled() const { return mClientArraysEnabled; }
215 
216     // Viewport state setter/getter
217     void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
getViewport()218     const Rectangle &getViewport() const { return mViewport; }
219 
220     // Texture binding & active texture unit manipulation
221     void setActiveSampler(unsigned int active);
getActiveSampler()222     unsigned int getActiveSampler() const { return static_cast<unsigned int>(mActiveSampler); }
223 
224     void setSamplerTexture(const Context *context, TextureType type, Texture *texture);
225     Texture *getTargetTexture(TextureType type) const;
226 
getSamplerTexture(unsigned int sampler,TextureType type)227     Texture *getSamplerTexture(unsigned int sampler, TextureType type) const
228     {
229         ASSERT(sampler < mSamplerTextures[type].size());
230         return mSamplerTextures[type][sampler].get();
231     }
232 
233     GLuint getSamplerTextureId(unsigned int sampler, TextureType type) const;
234     void detachTexture(const Context *context, const TextureMap &zeroTextures, TextureID texture);
235     void initializeZeroTextures(const Context *context, const TextureMap &zeroTextures);
236 
237     void invalidateTexture(TextureType type);
238 
239     // Sampler object binding manipulation
240     void setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler);
getSamplerId(GLuint textureUnit)241     GLuint getSamplerId(GLuint textureUnit) const
242     {
243         ASSERT(textureUnit < mSamplers.size());
244         return mSamplers[textureUnit].id();
245     }
246 
getSampler(GLuint textureUnit)247     Sampler *getSampler(GLuint textureUnit) const { return mSamplers[textureUnit].get(); }
248 
249     using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
getSamplers()250     const SamplerBindingVector &getSamplers() const { return mSamplers; }
251 
252     void detachSampler(const Context *context, GLuint sampler);
253 
254     // Renderbuffer binding manipulation
255     void setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer);
getRenderbufferId()256     GLuint getRenderbufferId() const { return mRenderbuffer.id(); }
getCurrentRenderbuffer()257     Renderbuffer *getCurrentRenderbuffer() const { return mRenderbuffer.get(); }
258     void detachRenderbuffer(const Context *context, RenderbufferID renderbuffer);
259 
260     // Framebuffer binding manipulation
261     void setReadFramebufferBinding(Framebuffer *framebuffer);
262     void setDrawFramebufferBinding(Framebuffer *framebuffer);
263     Framebuffer *getTargetFramebuffer(GLenum target) const;
getReadFramebuffer()264     Framebuffer *getReadFramebuffer() const { return mReadFramebuffer; }
getDrawFramebuffer()265     Framebuffer *getDrawFramebuffer() const { return mDrawFramebuffer; }
266 
267     bool removeReadFramebufferBinding(GLuint framebuffer);
268     bool removeDrawFramebufferBinding(GLuint framebuffer);
269 
270     // Vertex array object binding manipulation
271     void setVertexArrayBinding(const Context *context, VertexArray *vertexArray);
272     bool removeVertexArrayBinding(const Context *context, GLuint vertexArray);
273     GLuint getVertexArrayId() const;
274 
getVertexArray()275     VertexArray *getVertexArray() const
276     {
277         ASSERT(mVertexArray != nullptr);
278         return mVertexArray;
279     }
280 
281     // Program binding manipulation
282     angle::Result setProgram(const Context *context, Program *newProgram);
283 
getProgram()284     Program *getProgram() const
285     {
286         ASSERT(!mProgram || !mProgram->isLinking());
287         return mProgram;
288     }
289 
getLinkedProgram(const Context * context)290     Program *getLinkedProgram(const Context *context) const
291     {
292         if (mProgram)
293         {
294             mProgram->resolveLink(context);
295         }
296         return mProgram;
297     }
298 
299     // Transform feedback object (not buffer) binding manipulation
300     void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
getCurrentTransformFeedback()301     TransformFeedback *getCurrentTransformFeedback() const { return mTransformFeedback.get(); }
302 
isTransformFeedbackActive()303     ANGLE_INLINE bool isTransformFeedbackActive() const
304     {
305         TransformFeedback *curTransformFeedback = mTransformFeedback.get();
306         return curTransformFeedback && curTransformFeedback->isActive();
307     }
isTransformFeedbackActiveUnpaused()308     ANGLE_INLINE bool isTransformFeedbackActiveUnpaused() const
309     {
310         TransformFeedback *curTransformFeedback = mTransformFeedback.get();
311         return curTransformFeedback && curTransformFeedback->isActive() &&
312                !curTransformFeedback->isPaused();
313     }
314 
315     bool removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback);
316 
317     // Query binding manipulation
318     bool isQueryActive(QueryType type) const;
319     bool isQueryActive(Query *query) const;
320     void setActiveQuery(const Context *context, QueryType type, Query *query);
321     GLuint getActiveQueryId(QueryType type) const;
322     Query *getActiveQuery(QueryType type) const;
323 
324     // Program Pipeline binding manipulation
325     void setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline);
326     void detachProgramPipeline(const Context *context, GLuint pipeline);
327 
328     //// Typed buffer binding point manipulation ////
setBufferBinding(const Context * context,BufferBinding target,Buffer * buffer)329     ANGLE_INLINE void setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer)
330     {
331         (this->*(kBufferSetters[target]))(context, buffer);
332     }
333 
getTargetBuffer(BufferBinding target)334     ANGLE_INLINE Buffer *getTargetBuffer(BufferBinding target) const
335     {
336         switch (target)
337         {
338             case BufferBinding::ElementArray:
339                 return getVertexArray()->getElementArrayBuffer();
340             default:
341                 return mBoundBuffers[target].get();
342         }
343     }
344 
345     angle::Result setIndexedBufferBinding(const Context *context,
346                                           BufferBinding target,
347                                           GLuint index,
348                                           Buffer *buffer,
349                                           GLintptr offset,
350                                           GLsizeiptr size);
351 
getAtomicCounterBufferCount()352     size_t getAtomicCounterBufferCount() const { return mAtomicCounterBuffers.size(); }
353 
354     const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
355     const OffsetBindingPointer<Buffer> &getIndexedAtomicCounterBuffer(size_t index) const;
356     const OffsetBindingPointer<Buffer> &getIndexedShaderStorageBuffer(size_t index) const;
357 
358     // Detach a buffer from all bindings
359     angle::Result detachBuffer(Context *context, const Buffer *buffer);
360 
361     // Vertex attrib manipulation
362     void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
363     void setVertexAttribf(GLuint index, const GLfloat values[4]);
364     void setVertexAttribu(GLuint index, const GLuint values[4]);
365     void setVertexAttribi(GLuint index, const GLint values[4]);
366 
setVertexAttribPointer(const Context * context,unsigned int attribNum,Buffer * boundBuffer,GLint size,VertexAttribType type,bool normalized,GLsizei stride,const void * pointer)367     ANGLE_INLINE void setVertexAttribPointer(const Context *context,
368                                              unsigned int attribNum,
369                                              Buffer *boundBuffer,
370                                              GLint size,
371                                              VertexAttribType type,
372                                              bool normalized,
373                                              GLsizei stride,
374                                              const void *pointer)
375     {
376         mVertexArray->setVertexAttribPointer(context, attribNum, boundBuffer, size, type,
377                                              normalized, stride, pointer);
378         mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
379     }
380 
setVertexAttribIPointer(const Context * context,unsigned int attribNum,Buffer * boundBuffer,GLint size,VertexAttribType type,GLsizei stride,const void * pointer)381     ANGLE_INLINE void setVertexAttribIPointer(const Context *context,
382                                               unsigned int attribNum,
383                                               Buffer *boundBuffer,
384                                               GLint size,
385                                               VertexAttribType type,
386                                               GLsizei stride,
387                                               const void *pointer)
388     {
389         mVertexArray->setVertexAttribIPointer(context, attribNum, boundBuffer, size, type, stride,
390                                               pointer);
391         mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
392     }
393 
394     void setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor);
getVertexAttribCurrentValue(size_t attribNum)395     const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const
396     {
397         ASSERT(attribNum < mVertexAttribCurrentValues.size());
398         return mVertexAttribCurrentValues[attribNum];
399     }
400 
getVertexAttribCurrentValues()401     const std::vector<VertexAttribCurrentValueData> &getVertexAttribCurrentValues() const
402     {
403         return mVertexAttribCurrentValues;
404     }
405 
406     const void *getVertexAttribPointer(unsigned int attribNum) const;
407 
408     void bindVertexBuffer(const Context *context,
409                           GLuint bindingIndex,
410                           Buffer *boundBuffer,
411                           GLintptr offset,
412                           GLsizei stride);
413     void setVertexAttribFormat(GLuint attribIndex,
414                                GLint size,
415                                VertexAttribType type,
416                                bool normalized,
417                                bool pureInteger,
418                                GLuint relativeOffset);
419 
setVertexAttribBinding(const Context * context,GLuint attribIndex,GLuint bindingIndex)420     void setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex)
421     {
422         mVertexArray->setVertexAttribBinding(context, attribIndex, bindingIndex);
423         mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
424     }
425 
426     void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
427 
428     // Pixel pack state manipulation
429     void setPackAlignment(GLint alignment);
getPackAlignment()430     GLint getPackAlignment() const { return mPack.alignment; }
431     void setPackReverseRowOrder(bool reverseRowOrder);
getPackReverseRowOrder()432     bool getPackReverseRowOrder() const { return mPack.reverseRowOrder; }
433     void setPackRowLength(GLint rowLength);
getPackRowLength()434     GLint getPackRowLength() const { return mPack.rowLength; }
435     void setPackSkipRows(GLint skipRows);
getPackSkipRows()436     GLint getPackSkipRows() const { return mPack.skipRows; }
437     void setPackSkipPixels(GLint skipPixels);
getPackSkipPixels()438     GLint getPackSkipPixels() const { return mPack.skipPixels; }
getPackState()439     const PixelPackState &getPackState() const { return mPack; }
getPackState()440     PixelPackState &getPackState() { return mPack; }
441 
442     // Pixel unpack state manipulation
443     void setUnpackAlignment(GLint alignment);
getUnpackAlignment()444     GLint getUnpackAlignment() const { return mUnpack.alignment; }
445     void setUnpackRowLength(GLint rowLength);
getUnpackRowLength()446     GLint getUnpackRowLength() const { return mUnpack.rowLength; }
447     void setUnpackImageHeight(GLint imageHeight);
getUnpackImageHeight()448     GLint getUnpackImageHeight() const { return mUnpack.imageHeight; }
449     void setUnpackSkipImages(GLint skipImages);
getUnpackSkipImages()450     GLint getUnpackSkipImages() const { return mUnpack.skipImages; }
451     void setUnpackSkipRows(GLint skipRows);
getUnpackSkipRows()452     GLint getUnpackSkipRows() const { return mUnpack.skipRows; }
453     void setUnpackSkipPixels(GLint skipPixels);
getUnpackSkipPixels()454     GLint getUnpackSkipPixels() const { return mUnpack.skipPixels; }
getUnpackState()455     const PixelUnpackState &getUnpackState() const { return mUnpack; }
getUnpackState()456     PixelUnpackState &getUnpackState() { return mUnpack; }
457 
458     // Debug state
getDebug()459     const Debug &getDebug() const { return mDebug; }
getDebug()460     Debug &getDebug() { return mDebug; }
461 
462     // CHROMIUM_framebuffer_mixed_samples coverage modulation
463     void setCoverageModulation(GLenum components);
getCoverageModulation()464     GLenum getCoverageModulation() const { return mCoverageModulation; }
465 
466     // CHROMIUM_path_rendering
467     void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
468     const GLfloat *getPathRenderingMatrix(GLenum which) const;
469     void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
getPathStencilFunc()470     GLenum getPathStencilFunc() const { return mPathStencilFunc; }
getPathStencilRef()471     GLint getPathStencilRef() const { return mPathStencilRef; }
getPathStencilMask()472     GLuint getPathStencilMask() const { return mPathStencilMask; }
473 
474     // GL_EXT_sRGB_write_control
475     void setFramebufferSRGB(bool sRGB);
getFramebufferSRGB()476     bool getFramebufferSRGB() const { return mFramebufferSRGB; }
477 
478     // GL_KHR_parallel_shader_compile
479     void setMaxShaderCompilerThreads(GLuint count);
getMaxShaderCompilerThreads()480     GLuint getMaxShaderCompilerThreads() const { return mMaxShaderCompilerThreads; }
481 
482     // State query functions
483     void getBooleanv(GLenum pname, GLboolean *params);
484     void getFloatv(GLenum pname, GLfloat *params);
485     angle::Result getIntegerv(const Context *context, GLenum pname, GLint *params);
486     void getPointerv(const Context *context, GLenum pname, void **params) const;
487     void getIntegeri_v(GLenum target, GLuint index, GLint *data);
488     void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
489     void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
490 
isRobustResourceInitEnabled()491     bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
492 
493     // Sets the dirty bit for the program executable.
494     angle::Result onProgramExecutableChange(const Context *context, Program *program);
495 
496     enum DirtyBitType
497     {
498         // Note: process draw framebuffer binding first, so that other dirty bits whose effect
499         // depend on the current draw framebuffer are not processed while the old framebuffer is
500         // still bound.
501         DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
502         DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
503         DIRTY_BIT_SCISSOR_TEST_ENABLED,
504         DIRTY_BIT_SCISSOR,
505         DIRTY_BIT_VIEWPORT,
506         DIRTY_BIT_DEPTH_RANGE,
507         DIRTY_BIT_BLEND_ENABLED,
508         DIRTY_BIT_BLEND_COLOR,
509         DIRTY_BIT_BLEND_FUNCS,
510         DIRTY_BIT_BLEND_EQUATIONS,
511         DIRTY_BIT_COLOR_MASK,
512         DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
513         DIRTY_BIT_SAMPLE_COVERAGE_ENABLED,
514         DIRTY_BIT_SAMPLE_COVERAGE,
515         DIRTY_BIT_SAMPLE_MASK_ENABLED,
516         DIRTY_BIT_SAMPLE_MASK,
517         DIRTY_BIT_DEPTH_TEST_ENABLED,
518         DIRTY_BIT_DEPTH_FUNC,
519         DIRTY_BIT_DEPTH_MASK,
520         DIRTY_BIT_STENCIL_TEST_ENABLED,
521         DIRTY_BIT_STENCIL_FUNCS_FRONT,
522         DIRTY_BIT_STENCIL_FUNCS_BACK,
523         DIRTY_BIT_STENCIL_OPS_FRONT,
524         DIRTY_BIT_STENCIL_OPS_BACK,
525         DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
526         DIRTY_BIT_STENCIL_WRITEMASK_BACK,
527         DIRTY_BIT_CULL_FACE_ENABLED,
528         DIRTY_BIT_CULL_FACE,
529         DIRTY_BIT_FRONT_FACE,
530         DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED,
531         DIRTY_BIT_POLYGON_OFFSET,
532         DIRTY_BIT_RASTERIZER_DISCARD_ENABLED,
533         DIRTY_BIT_LINE_WIDTH,
534         DIRTY_BIT_PRIMITIVE_RESTART_ENABLED,
535         DIRTY_BIT_CLEAR_COLOR,
536         DIRTY_BIT_CLEAR_DEPTH,
537         DIRTY_BIT_CLEAR_STENCIL,
538         DIRTY_BIT_UNPACK_STATE,
539         DIRTY_BIT_UNPACK_BUFFER_BINDING,
540         DIRTY_BIT_PACK_STATE,
541         DIRTY_BIT_PACK_BUFFER_BINDING,
542         DIRTY_BIT_DITHER_ENABLED,
543         DIRTY_BIT_GENERATE_MIPMAP_HINT,
544         DIRTY_BIT_SHADER_DERIVATIVE_HINT,
545         DIRTY_BIT_RENDERBUFFER_BINDING,
546         DIRTY_BIT_VERTEX_ARRAY_BINDING,
547         DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING,
548         DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING,
549         // TODO(jmadill): Fine-grained dirty bits for each index.
550         DIRTY_BIT_PROGRAM_BINDING,
551         DIRTY_BIT_PROGRAM_EXECUTABLE,
552         // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
553         DIRTY_BIT_TEXTURE_BINDINGS,
554         DIRTY_BIT_SAMPLER_BINDINGS,
555         DIRTY_BIT_IMAGE_BINDINGS,
556         DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING,
557         DIRTY_BIT_UNIFORM_BUFFER_BINDINGS,
558         DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
559         DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING,
560         DIRTY_BIT_MULTISAMPLING,
561         DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
562         DIRTY_BIT_COVERAGE_MODULATION,  // CHROMIUM_framebuffer_mixed_samples
563         DIRTY_BIT_PATH_RENDERING,
564         DIRTY_BIT_FRAMEBUFFER_SRGB,  // GL_EXT_sRGB_write_control
565         DIRTY_BIT_CURRENT_VALUES,
566         DIRTY_BIT_PROVOKING_VERTEX,
567         DIRTY_BIT_INVALID,
568         DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
569     };
570 
571     static_assert(DIRTY_BIT_MAX <= 64, "State dirty bits must be capped at 64");
572 
573     // TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
574     enum DirtyObjectType
575     {
576         DIRTY_OBJECT_TEXTURES_INIT,
577         DIRTY_OBJECT_IMAGES_INIT,
578         DIRTY_OBJECT_READ_ATTACHMENTS,
579         DIRTY_OBJECT_DRAW_ATTACHMENTS,
580         DIRTY_OBJECT_READ_FRAMEBUFFER,
581         DIRTY_OBJECT_DRAW_FRAMEBUFFER,
582         DIRTY_OBJECT_VERTEX_ARRAY,
583         DIRTY_OBJECT_TEXTURES,  // Top-level dirty bit. Also see mDirtyTextures.
584         DIRTY_OBJECT_SAMPLERS,  // Top-level dirty bit. Also see mDirtySamplers.
585         DIRTY_OBJECT_PROGRAM,
586         DIRTY_OBJECT_UNKNOWN,
587         DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
588     };
589 
590     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
getDirtyBits()591     const DirtyBits &getDirtyBits() const { return mDirtyBits; }
clearDirtyBits()592     void clearDirtyBits() { mDirtyBits.reset(); }
clearDirtyBits(const DirtyBits & bitset)593     void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
setAllDirtyBits()594     void setAllDirtyBits()
595     {
596         mDirtyBits.set();
597         mDirtyCurrentValues.set();
598     }
599 
600     using DirtyObjects = angle::BitSet<DIRTY_OBJECT_MAX>;
clearDirtyObjects()601     void clearDirtyObjects() { mDirtyObjects.reset(); }
setAllDirtyObjects()602     void setAllDirtyObjects() { mDirtyObjects.set(); }
603     angle::Result syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
604     angle::Result syncDirtyObject(const Context *context, GLenum target);
605     void setObjectDirty(GLenum target);
606     void setTextureDirty(size_t textureUnitIndex);
607     void setSamplerDirty(size_t samplerIndex);
608 
setReadFramebufferDirty()609     ANGLE_INLINE void setReadFramebufferDirty()
610     {
611         mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
612         mDirtyObjects.set(DIRTY_OBJECT_READ_ATTACHMENTS);
613     }
614 
setDrawFramebufferDirty()615     ANGLE_INLINE void setDrawFramebufferDirty()
616     {
617         mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
618         mDirtyObjects.set(DIRTY_OBJECT_DRAW_ATTACHMENTS);
619     }
620 
621     // This actually clears the current value dirty bits.
622     // TODO(jmadill): Pass mutable dirty bits into Impl.
623     AttributesMask getAndResetDirtyCurrentValues() const;
624 
625     void setImageUnit(const Context *context,
626                       size_t unit,
627                       Texture *texture,
628                       GLint level,
629                       GLboolean layered,
630                       GLint layer,
631                       GLenum access,
632                       GLenum format);
633 
getImageUnit(size_t unit)634     const ImageUnit &getImageUnit(size_t unit) const { return mImageUnits[unit]; }
getActiveTexturesCache()635     const ActiveTexturePointerArray &getActiveTexturesCache() const { return mActiveTexturesCache; }
getCurrentValuesTypeMask()636     ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; }
637 
638     // "onActiveTextureChange" is called when a texture binding changes.
639     void onActiveTextureChange(const Context *context, size_t textureUnit);
640 
641     // "onActiveTextureStateChange" calls when the Texture itself changed but the binding did not.
642     void onActiveTextureStateChange(const Context *context, size_t textureUnit);
643 
644     void onImageStateChange(const Context *context, size_t unit);
645 
646     void onUniformBufferStateChange(size_t uniformBufferIndex);
647 
isCurrentTransformFeedback(const TransformFeedback * tf)648     bool isCurrentTransformFeedback(const TransformFeedback *tf) const
649     {
650         return tf == mTransformFeedback.get();
651     }
isCurrentVertexArray(const VertexArray * va)652     bool isCurrentVertexArray(const VertexArray *va) const { return va == mVertexArray; }
653 
gles1()654     GLES1State &gles1() { return mGLES1State; }
gles1()655     const GLES1State &gles1() const { return mGLES1State; }
656 
657     // Helpers for setting bound buffers. They should all have the same signature.
658     // Not meant to be called externally. Used for local helpers in State.cpp.
659     template <BufferBinding Target>
660     void setGenericBufferBindingWithBit(const Context *context, Buffer *buffer);
661 
662     template <BufferBinding Target>
663     void setGenericBufferBinding(const Context *context, Buffer *buffer);
664 
665     using BufferBindingSetter = void (State::*)(const Context *, Buffer *);
666 
validateSamplerFormats()667     ANGLE_INLINE bool validateSamplerFormats() const
668     {
669         return (mTexturesIncompatibleWithSamplers & mProgram->getActiveSamplersMask()).none();
670     }
671 
getProvokingVertex()672     ProvokingVertexConvention getProvokingVertex() const { return mProvokingVertex; }
setProvokingVertex(ProvokingVertexConvention val)673     void setProvokingVertex(ProvokingVertexConvention val)
674     {
675         mDirtyBits.set(State::DIRTY_BIT_PROVOKING_VERTEX);
676         mProvokingVertex = val;
677     }
678 
679   private:
680     friend class Context;
681 
682     void unsetActiveTextures(ActiveTextureMask textureMask);
683     void updateActiveTexture(const Context *context, size_t textureIndex, Texture *texture);
684     void updateActiveTextureState(const Context *context,
685                                   size_t textureIndex,
686                                   const Sampler *sampler,
687                                   Texture *texture);
688 
689     // Functions to synchronize dirty states
690     angle::Result syncTexturesInit(const Context *context);
691     angle::Result syncImagesInit(const Context *context);
692     angle::Result syncReadAttachments(const Context *context);
693     angle::Result syncDrawAttachments(const Context *context);
694     angle::Result syncReadFramebuffer(const Context *context);
695     angle::Result syncDrawFramebuffer(const Context *context);
696     angle::Result syncVertexArray(const Context *context);
697     angle::Result syncTextures(const Context *context);
698     angle::Result syncSamplers(const Context *context);
699     angle::Result syncProgram(const Context *context);
700 
701     using DirtyObjectHandler = angle::Result (State::*)(const Context *context);
702     static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
703         &State::syncTexturesInit,    &State::syncImagesInit,      &State::syncReadAttachments,
704         &State::syncDrawAttachments, &State::syncReadFramebuffer, &State::syncDrawFramebuffer,
705         &State::syncVertexArray,     &State::syncTextures,        &State::syncSamplers,
706         &State::syncProgram,
707     };
708 
709     // Robust init must happen before Framebuffer init for the Vulkan back-end.
710     static_assert(DIRTY_OBJECT_TEXTURES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
711     static_assert(DIRTY_OBJECT_IMAGES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
712     static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
713     static_assert(DIRTY_OBJECT_READ_ATTACHMENTS < DIRTY_OBJECT_READ_FRAMEBUFFER, "init order");
714 
715     static_assert(DIRTY_OBJECT_TEXTURES_INIT == 0, "check DIRTY_OBJECT_TEXTURES_INIT index");
716     static_assert(DIRTY_OBJECT_IMAGES_INIT == 1, "check DIRTY_OBJECT_IMAGES_INIT index");
717     static_assert(DIRTY_OBJECT_READ_ATTACHMENTS == 2, "check DIRTY_OBJECT_READ_ATTACHMENTS index");
718     static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS == 3, "check DIRTY_OBJECT_DRAW_ATTACHMENTS index");
719     static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 4, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
720     static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 5, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
721     static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 6, "check DIRTY_OBJECT_VERTEX_ARRAY index");
722     static_assert(DIRTY_OBJECT_TEXTURES == 7, "check DIRTY_OBJECT_TEXTURES index");
723     static_assert(DIRTY_OBJECT_SAMPLERS == 8, "check DIRTY_OBJECT_SAMPLERS index");
724     static_assert(DIRTY_OBJECT_PROGRAM == 9, "check DIRTY_OBJECT_PROGRAM index");
725 
726     // Dispatch table for buffer update functions.
727     static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
728 
729     EGLenum mClientType;
730     Version mClientVersion;
731     ContextID mContext;
732 
733     // Caps to use for validation
734     Caps mCaps;
735     TextureCapsMap mTextureCaps;
736     Extensions mExtensions;
737     Limitations mLimitations;
738 
739     // Resource managers.
740     BufferManager *mBufferManager;
741     ShaderProgramManager *mShaderProgramManager;
742     TextureManager *mTextureManager;
743     RenderbufferManager *mRenderbufferManager;
744     SamplerManager *mSamplerManager;
745     SyncManager *mSyncManager;
746     PathManager *mPathManager;
747     FramebufferManager *mFramebufferManager;
748     ProgramPipelineManager *mProgramPipelineManager;
749     MemoryObjectManager *mMemoryObjectManager;
750     SemaphoreManager *mSemaphoreManager;
751 
752     // Cached values from Context's caps
753     GLuint mMaxDrawBuffers;
754     GLuint mMaxCombinedTextureImageUnits;
755 
756     ColorF mColorClearValue;
757     GLfloat mDepthClearValue;
758     int mStencilClearValue;
759 
760     RasterizerState mRasterizer;
761     bool mScissorTest;
762     Rectangle mScissor;
763 
764     BlendState mBlend;
765     ColorF mBlendColor;
766     bool mSampleCoverage;
767     GLfloat mSampleCoverageValue;
768     bool mSampleCoverageInvert;
769     bool mSampleMask;
770     GLuint mMaxSampleMaskWords;
771     std::array<GLbitfield, MAX_SAMPLE_MASK_WORDS> mSampleMaskValues;
772 
773     DepthStencilState mDepthStencil;
774     GLint mStencilRef;
775     GLint mStencilBackRef;
776 
777     GLfloat mLineWidth;
778 
779     GLenum mGenerateMipmapHint;
780     GLenum mFragmentShaderDerivativeHint;
781 
782     const bool mBindGeneratesResource;
783     const bool mClientArraysEnabled;
784 
785     Rectangle mViewport;
786     float mNearZ;
787     float mFarZ;
788 
789     Framebuffer *mReadFramebuffer;
790     Framebuffer *mDrawFramebuffer;
791     BindingPointer<Renderbuffer> mRenderbuffer;
792     Program *mProgram;
793     BindingPointer<ProgramPipeline> mProgramPipeline;
794 
795     // GL_ANGLE_provoking_vertex
796     ProvokingVertexConvention mProvokingVertex;
797 
798     using VertexAttribVector = std::vector<VertexAttribCurrentValueData>;
799     VertexAttribVector mVertexAttribCurrentValues;  // From glVertexAttrib
800     VertexArray *mVertexArray;
801     ComponentTypeMask mCurrentValuesTypeMask;
802 
803     // Texture and sampler bindings
804     size_t mActiveSampler;  // Active texture unit selector - GL_TEXTURE0
805 
806     using TextureBindingVector = std::vector<BindingPointer<Texture>>;
807     using TextureBindingMap    = angle::PackedEnumMap<TextureType, TextureBindingVector>;
808     TextureBindingMap mSamplerTextures;
809 
810     // Texture Completeness Caching
811     // ----------------------------
812     // The texture completeness cache uses dirty bits to avoid having to scan the list of textures
813     // each draw call. This gl::State class implements angle::Observer interface. When subject
814     // Textures have state changes, messages reach 'State' (also any observing Framebuffers) via the
815     // onSubjectStateChange method (above). This then invalidates the completeness cache.
816     //
817     // Note this requires that we also invalidate the completeness cache manually on events like
818     // re-binding textures/samplers or a change in the program. For more information see the
819     // Observer.h header and the design doc linked there.
820 
821     // A cache of complete textures. nullptr indicates unbound or incomplete.
822     // Don't use BindingPointer because this cache is only valid within a draw call.
823     // Also stores a notification channel to the texture itself to handle texture change events.
824     ActiveTexturePointerArray mActiveTexturesCache;
825     std::vector<angle::ObserverBinding> mCompleteTextureBindings;
826 
827     ActiveTextureMask mTexturesIncompatibleWithSamplers;
828 
829     SamplerBindingVector mSamplers;
830 
831     // It would be nice to merge the image and observer binding. Same for textures.
832     std::vector<ImageUnit> mImageUnits;
833 
834     using ActiveQueryMap = angle::PackedEnumMap<QueryType, BindingPointer<Query>>;
835     ActiveQueryMap mActiveQueries;
836 
837     // Stores the currently bound buffer for each binding point. It has an entry for the element
838     // array buffer but it should not be used. Instead this bind point is owned by the current
839     // vertex array object.
840     using BoundBufferMap = angle::PackedEnumMap<BufferBinding, BindingPointer<Buffer>>;
841     BoundBufferMap mBoundBuffers;
842 
843     using BufferVector = std::vector<OffsetBindingPointer<Buffer>>;
844     BufferVector mUniformBuffers;
845     BufferVector mAtomicCounterBuffers;
846     BufferVector mShaderStorageBuffers;
847 
848     BindingPointer<TransformFeedback> mTransformFeedback;
849 
850     PixelUnpackState mUnpack;
851     PixelPackState mPack;
852 
853     bool mPrimitiveRestart;
854 
855     Debug mDebug;
856 
857     bool mMultiSampling;
858     bool mSampleAlphaToOne;
859 
860     GLenum mCoverageModulation;
861 
862     // CHROMIUM_path_rendering
863     GLfloat mPathMatrixMV[16];
864     GLfloat mPathMatrixProj[16];
865     GLenum mPathStencilFunc;
866     GLint mPathStencilRef;
867     GLuint mPathStencilMask;
868 
869     // GL_EXT_sRGB_write_control
870     bool mFramebufferSRGB;
871 
872     // GL_ANGLE_robust_resource_intialization
873     const bool mRobustResourceInit;
874 
875     // GL_ANGLE_program_cache_control
876     const bool mProgramBinaryCacheEnabled;
877 
878     // GL_KHR_parallel_shader_compile
879     GLuint mMaxShaderCompilerThreads;
880 
881     // GLES1 emulation: state specific to GLES1
882     GLES1State mGLES1State;
883 
884     DirtyBits mDirtyBits;
885     DirtyObjects mDirtyObjects;
886     mutable AttributesMask mDirtyCurrentValues;
887     ActiveTextureMask mDirtyTextures;
888     ActiveTextureMask mDirtySamplers;
889     ImageUnitMask mDirtyImages;
890 };
891 
syncDirtyObjects(const Context * context,const DirtyObjects & bitset)892 ANGLE_INLINE angle::Result State::syncDirtyObjects(const Context *context,
893                                                    const DirtyObjects &bitset)
894 {
895     const DirtyObjects &dirtyObjects = mDirtyObjects & bitset;
896 
897     for (size_t dirtyObject : dirtyObjects)
898     {
899         ANGLE_TRY((this->*kDirtyObjectHandlers[dirtyObject])(context));
900     }
901 
902     mDirtyObjects &= ~dirtyObjects;
903     return angle::Result::Continue;
904 }
905 
906 }  // namespace gl
907 
908 #endif  // LIBANGLE_STATE_H_
909