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