summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/State.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/State.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/State.cpp1260
1 files changed, 926 insertions, 334 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp
index a1437b838b..f87e963710 100644
--- a/src/3rdparty/angle/src/libANGLE/State.cpp
+++ b/src/3rdparty/angle/src/libANGLE/State.cpp
@@ -8,15 +8,32 @@
#include "libANGLE/State.h"
-#include "common/BitSetIterator.h"
-#include "libANGLE/Context.h"
+#include <limits>
+#include <string.h>
+
+#include "common/bitset_utils.h"
+#include "common/mathutil.h"
+#include "common/matrix_utils.h"
#include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Query.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace
+{
+
+GLenum ActiveQueryType(const GLenum type)
+{
+ return (type == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) ? GL_ANY_SAMPLES_PASSED : type;
+}
+
+} // anonymous namepace
namespace gl
{
@@ -30,11 +47,15 @@ State::State()
mSampleCoverage(false),
mSampleCoverageValue(0),
mSampleCoverageInvert(false),
+ mSampleMask(false),
+ mMaxSampleMaskWords(0),
mStencilRef(0),
mStencilBackRef(0),
mLineWidth(0),
mGenerateMipmapHint(GL_NONE),
mFragmentShaderDerivativeHint(GL_NONE),
+ mBindGeneratesResource(true),
+ mClientArraysEnabled(true),
mNearZ(0),
mFarZ(0),
mReadFramebuffer(nullptr),
@@ -42,49 +63,31 @@ State::State()
mProgram(nullptr),
mVertexArray(nullptr),
mActiveSampler(0),
- mPrimitiveRestart(false)
-{
- // Initialize dirty bit masks
- // TODO(jmadill): additional ES3 state
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ALIGNMENT);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
-
- mPackStateBitMask.set(DIRTY_BIT_PACK_ALIGNMENT);
- mPackStateBitMask.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
- mPackStateBitMask.set(DIRTY_BIT_PACK_ROW_LENGTH);
- mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_ROWS);
- mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_PIXELS);
-
- mClearStateBitMask.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
- mClearStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
- mClearStateBitMask.set(DIRTY_BIT_SCISSOR);
- mClearStateBitMask.set(DIRTY_BIT_VIEWPORT);
- mClearStateBitMask.set(DIRTY_BIT_CLEAR_COLOR);
- mClearStateBitMask.set(DIRTY_BIT_CLEAR_DEPTH);
- mClearStateBitMask.set(DIRTY_BIT_CLEAR_STENCIL);
- mClearStateBitMask.set(DIRTY_BIT_COLOR_MASK);
- mClearStateBitMask.set(DIRTY_BIT_DEPTH_MASK);
- mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
- mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
-
- mBlitStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
- mBlitStateBitMask.set(DIRTY_BIT_SCISSOR);
+ mPrimitiveRestart(false),
+ mMultiSampling(false),
+ mSampleAlphaToOne(false),
+ mFramebufferSRGB(true),
+ mRobustResourceInit(false),
+ mProgramBinaryCacheEnabled(false)
+{
}
State::~State()
{
- reset();
}
-void State::initialize(const Caps &caps,
- const Extensions &extensions,
- GLuint clientVersion,
- bool debug)
+void State::initialize(const Context *context,
+ bool debug,
+ bool bindGeneratesResource,
+ bool clientArraysEnabled,
+ bool robustResourceInit,
+ bool programBinaryCacheEnabled)
{
+ const Caps &caps = context->getCaps();
+ const Extensions &extensions = context->getExtensions();
+ const Extensions &nativeExtensions = context->getImplementation()->getNativeExtensions();
+ const Version &clientVersion = context->getClientVersion();
+
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
@@ -93,62 +96,34 @@ void State::initialize(const Caps &caps,
mDepthClearValue = 1.0f;
mStencilClearValue = 0;
- mRasterizer.rasterizerDiscard = false;
- mRasterizer.cullFace = false;
- mRasterizer.cullMode = GL_BACK;
- mRasterizer.frontFace = GL_CCW;
- mRasterizer.polygonOffsetFill = false;
- mRasterizer.polygonOffsetFactor = 0.0f;
- mRasterizer.polygonOffsetUnits = 0.0f;
- mRasterizer.pointDrawMode = false;
- mRasterizer.multiSample = false;
mScissorTest = false;
mScissor.x = 0;
mScissor.y = 0;
mScissor.width = 0;
mScissor.height = 0;
- mBlend.blend = false;
- mBlend.sourceBlendRGB = GL_ONE;
- mBlend.sourceBlendAlpha = GL_ONE;
- mBlend.destBlendRGB = GL_ZERO;
- mBlend.destBlendAlpha = GL_ZERO;
- mBlend.blendEquationRGB = GL_FUNC_ADD;
- mBlend.blendEquationAlpha = GL_FUNC_ADD;
- mBlend.sampleAlphaToCoverage = false;
- mBlend.dither = true;
-
mBlendColor.red = 0;
mBlendColor.green = 0;
mBlendColor.blue = 0;
mBlendColor.alpha = 0;
- mDepthStencil.depthTest = false;
- mDepthStencil.depthFunc = GL_LESS;
- mDepthStencil.depthMask = true;
- mDepthStencil.stencilTest = false;
- mDepthStencil.stencilFunc = GL_ALWAYS;
- mDepthStencil.stencilMask = static_cast<GLuint>(-1);
- mDepthStencil.stencilWritemask = static_cast<GLuint>(-1);
- mDepthStencil.stencilBackFunc = GL_ALWAYS;
- mDepthStencil.stencilBackMask = static_cast<GLuint>(-1);
- mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-1);
- mDepthStencil.stencilFail = GL_KEEP;
- mDepthStencil.stencilPassDepthFail = GL_KEEP;
- mDepthStencil.stencilPassDepthPass = GL_KEEP;
- mDepthStencil.stencilBackFail = GL_KEEP;
- mDepthStencil.stencilBackPassDepthFail = GL_KEEP;
- mDepthStencil.stencilBackPassDepthPass = GL_KEEP;
-
mStencilRef = 0;
mStencilBackRef = 0;
mSampleCoverage = false;
mSampleCoverageValue = 1.0f;
mSampleCoverageInvert = false;
+
+ mMaxSampleMaskWords = caps.maxSampleMaskWords;
+ mSampleMask = false;
+ mSampleMaskValues.fill(~GLbitfield(0));
+
mGenerateMipmapHint = GL_DONT_CARE;
mFragmentShaderDerivativeHint = GL_DONT_CARE;
+ mBindGeneratesResource = bindGeneratesResource;
+ mClientArraysEnabled = clientArraysEnabled;
+
mLineWidth = 1.0f;
mViewport.x = 0;
@@ -167,23 +142,48 @@ void State::initialize(const Caps &caps,
mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
- mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
+ mUniformBuffers.resize(caps.maxUniformBufferBindings);
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
- if (clientVersion >= 3)
+ if (clientVersion >= Version(3, 0))
{
// TODO: These could also be enabled via extension
mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits);
}
+ if (clientVersion >= Version(3, 1))
+ {
+ mSamplerTextures[GL_TEXTURE_2D_MULTISAMPLE].resize(caps.maxCombinedTextureImageUnits);
+
+ mAtomicCounterBuffers.resize(caps.maxAtomicCounterBufferBindings);
+ mShaderStorageBuffers.resize(caps.maxShaderStorageBufferBindings);
+ mImageUnits.resize(caps.maxImageUnits);
+ }
+ if (nativeExtensions.textureRectangle)
+ {
+ mSamplerTextures[GL_TEXTURE_RECTANGLE_ANGLE].resize(caps.maxCombinedTextureImageUnits);
+ }
+ if (nativeExtensions.eglImageExternal || nativeExtensions.eglStreamConsumerExternal)
+ {
+ mSamplerTextures[GL_TEXTURE_EXTERNAL_OES].resize(caps.maxCombinedTextureImageUnits);
+ }
+ mCompleteTextureCache.resize(caps.maxCombinedTextureImageUnits, nullptr);
+ mCompleteTextureBindings.reserve(caps.maxCombinedTextureImageUnits);
+ mCachedTexturesInitState = InitState::MayNeedInit;
+ for (uint32_t textureIndex = 0; textureIndex < caps.maxCombinedTextureImageUnits;
+ ++textureIndex)
+ {
+ mCompleteTextureBindings.emplace_back(OnAttachmentDirtyBinding(this, textureIndex));
+ }
mSamplers.resize(caps.maxCombinedTextureImageUnits);
- mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr);
- mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr);
- mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr);
- mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr);
+ mActiveQueries[GL_ANY_SAMPLES_PASSED].set(context, nullptr);
+ mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(context, nullptr);
+ mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(context, nullptr);
+ mActiveQueries[GL_TIME_ELAPSED_EXT].set(context, nullptr);
+ mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(context, nullptr);
mProgram = nullptr;
@@ -194,52 +194,89 @@ void State::initialize(const Caps &caps,
mDebug.setOutputEnabled(debug);
mDebug.setMaxLoggedMessages(extensions.maxDebugLoggedMessages);
+
+ mMultiSampling = true;
+ mSampleAlphaToOne = false;
+
+ mCoverageModulation = GL_NONE;
+
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+ mPathStencilFunc = GL_ALWAYS;
+ mPathStencilRef = 0;
+ mPathStencilMask = std::numeric_limits<GLuint>::max();
+
+ mRobustResourceInit = robustResourceInit;
+ mProgramBinaryCacheEnabled = programBinaryCacheEnabled;
}
-void State::reset()
+void State::reset(const Context *context)
{
- for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+ for (auto &bindingVec : mSamplerTextures)
{
- TextureBindingVector &textureVector = bindingVec->second;
+ TextureBindingVector &textureVector = bindingVec.second;
for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
{
- textureVector[textureIdx].set(NULL);
+ textureVector[textureIdx].set(context, nullptr);
}
}
for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
{
- mSamplers[samplerIdx].set(NULL);
+ mSamplers[samplerIdx].set(context, nullptr);
}
- mArrayBuffer.set(NULL);
- mRenderbuffer.set(NULL);
+ for (auto &imageUnit : mImageUnits)
+ {
+ imageUnit.texture.set(context, nullptr);
+ imageUnit.level = 0;
+ imageUnit.layered = false;
+ imageUnit.layer = 0;
+ imageUnit.access = GL_READ_ONLY;
+ imageUnit.format = GL_R32UI;
+ }
+
+ mRenderbuffer.set(context, nullptr);
+
+ for (auto type : angle::AllEnums<BufferBinding>())
+ {
+ mBoundBuffers[type].set(context, nullptr);
+ }
if (mProgram)
{
- mProgram->release();
+ mProgram->release(context);
}
- mProgram = NULL;
+ mProgram = nullptr;
+
+ mProgramPipeline.set(context, nullptr);
- mTransformFeedback.set(NULL);
+ mTransformFeedback.set(context, nullptr);
for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
{
- i->second.set(NULL);
+ i->second.set(context, nullptr);
}
- mGenericUniformBuffer.set(NULL);
- for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
+ for (auto &buf : mUniformBuffers)
{
- bufItr->set(NULL);
+ buf.set(context, nullptr);
}
- mCopyReadBuffer.set(NULL);
- mCopyWriteBuffer.set(NULL);
+ for (auto &buf : mAtomicCounterBuffers)
+ {
+ buf.set(context, nullptr);
+ }
- mPack.pixelBuffer.set(NULL);
- mUnpack.pixelBuffer.set(NULL);
+ for (auto &buf : mShaderStorageBuffers)
+ {
+ buf.set(context, nullptr);
+ }
- mProgram = NULL;
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+ mPathStencilFunc = GL_ALWAYS;
+ mPathStencilRef = 0;
+ mPathStencilMask = std::numeric_limits<GLuint>::max();
// TODO(jmadill): Is this necessary?
setAllDirtyBits();
@@ -318,7 +355,7 @@ void State::setCullFace(bool enabled)
mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED);
}
-void State::setCullMode(GLenum mode)
+void State::setCullMode(CullFaceMode mode)
{
mRasterizer.cullMode = mode;
mDirtyBits.set(DIRTY_BIT_CULL_FACE);
@@ -528,6 +565,58 @@ bool State::getSampleCoverageInvert() const
return mSampleCoverageInvert;
}
+bool State::isSampleMaskEnabled() const
+{
+ return mSampleMask;
+}
+
+void State::setSampleMaskEnabled(bool enabled)
+{
+ mSampleMask = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK_ENABLED);
+}
+
+void State::setSampleMaskParams(GLuint maskNumber, GLbitfield mask)
+{
+ ASSERT(maskNumber < mMaxSampleMaskWords);
+ mSampleMaskValues[maskNumber] = mask;
+ // TODO(jmadill): Use a child dirty bit if we ever use more than two words.
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);
+}
+
+GLbitfield State::getSampleMaskWord(GLuint maskNumber) const
+{
+ ASSERT(maskNumber < mMaxSampleMaskWords);
+ return mSampleMaskValues[maskNumber];
+}
+
+GLuint State::getMaxSampleMaskWords() const
+{
+ return mMaxSampleMaskWords;
+}
+
+void State::setSampleAlphaToOne(bool enabled)
+{
+ mSampleAlphaToOne = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+}
+
+bool State::isSampleAlphaToOneEnabled() const
+{
+ return mSampleAlphaToOne;
+}
+
+void State::setMultisampling(bool enabled)
+{
+ mMultiSampling = enabled;
+ mDirtyBits.set(DIRTY_BIT_MULTISAMPLING);
+}
+
+bool State::isMultisamplingEnabled() const
+{
+ return mMultiSampling;
+}
+
bool State::isScissorTestEnabled() const
{
return mScissorTest;
@@ -579,6 +668,8 @@ void State::setEnableFeature(GLenum feature, bool enabled)
{
switch (feature)
{
+ case GL_MULTISAMPLE_EXT: setMultisampling(enabled); break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT: setSampleAlphaToOne(enabled); break;
case GL_CULL_FACE: setCullFace(enabled); break;
case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break;
case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break;
@@ -590,20 +681,28 @@ void State::setEnableFeature(GLenum feature, bool enabled)
case GL_DITHER: setDither(enabled); break;
case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break;
case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break;
+ case GL_SAMPLE_MASK:
+ setSampleMaskEnabled(enabled);
+ break;
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
mDebug.setOutputSynchronous(enabled);
break;
case GL_DEBUG_OUTPUT:
mDebug.setOutputEnabled(enabled);
break;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ setFramebufferSRGB(enabled);
+ break;
default: UNREACHABLE();
}
}
-bool State::getEnableFeature(GLenum feature)
+bool State::getEnableFeature(GLenum feature) const
{
switch (feature)
{
+ case GL_MULTISAMPLE_EXT: return isMultisamplingEnabled();
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT: return isSampleAlphaToOneEnabled();
case GL_CULL_FACE: return isCullFaceEnabled();
case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled();
case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled();
@@ -615,11 +714,26 @@ bool State::getEnableFeature(GLenum feature)
case GL_DITHER: return isDitherEnabled();
case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled();
case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled();
+ case GL_SAMPLE_MASK:
+ return isSampleMaskEnabled();
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
return mDebug.isOutputSynchronous();
case GL_DEBUG_OUTPUT:
return mDebug.isOutputEnabled();
- default: UNREACHABLE(); return false;
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ return isBindGeneratesResourceEnabled();
+ case GL_CLIENT_ARRAYS_ANGLE:
+ return areClientArraysEnabled();
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ return getFramebufferSRGB();
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return mRobustResourceInit;
+ case GL_PROGRAM_CACHE_ENABLED_ANGLE:
+ return mProgramBinaryCacheEnabled;
+
+ default:
+ UNREACHABLE();
+ return false;
}
}
@@ -649,6 +763,16 @@ void State::setFragmentShaderDerivativeHint(GLenum hint)
// Ignore for now. It is valid for implementations to ignore hint.
}
+bool State::isBindGeneratesResourceEnabled() const
+{
+ return mBindGeneratesResource;
+}
+
+bool State::areClientArraysEnabled() const
+{
+ return mClientArraysEnabled;
+}
+
void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{
mViewport.x = x;
@@ -673,9 +797,11 @@ unsigned int State::getActiveSampler() const
return static_cast<unsigned int>(mActiveSampler);
}
-void State::setSamplerTexture(GLenum type, Texture *texture)
+void State::setSamplerTexture(const Context *context, GLenum type, Texture *texture)
{
- mSamplerTextures[type][mActiveSampler].set(texture);
+ mSamplerTextures[type][mActiveSampler].set(context, texture);
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
}
Texture *State::getTargetTexture(GLenum target) const
@@ -699,7 +825,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
return it->second[sampler].id();
}
-void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
+void State::detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture)
{
// Textures have a detach method on State rather than a simple
// removeBinding, because the zero/null texture objects are managed
@@ -710,40 +836,54 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
// If a texture object is deleted, it is as if all texture units which are bound to that texture object are
// rebound to texture object zero
- for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+ for (auto &bindingVec : mSamplerTextures)
{
- GLenum textureType = bindingVec->first;
- TextureBindingVector &textureVector = bindingVec->second;
- for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+ GLenum textureType = bindingVec.first;
+ TextureBindingVector &textureVector = bindingVec.second;
+ for (BindingPointer<Texture> &binding : textureVector)
{
- BindingPointer<Texture> &binding = textureVector[textureIdx];
if (binding.id() == texture)
{
auto it = zeroTextures.find(textureType);
ASSERT(it != zeroTextures.end());
// Zero textures are the "default" textures instead of NULL
- binding.set(it->second.get());
+ binding.set(context, it->second.get());
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
}
}
}
+ for (auto &bindingImageUnit : mImageUnits)
+ {
+ if (bindingImageUnit.texture.id() == texture)
+ {
+ bindingImageUnit.texture.set(context, nullptr);
+ bindingImageUnit.level = 0;
+ bindingImageUnit.layered = false;
+ bindingImageUnit.layer = 0;
+ bindingImageUnit.access = GL_READ_ONLY;
+ bindingImageUnit.format = GL_R32UI;
+ break;
+ }
+ }
+
// [OpenGL ES 2.0.24] section 4.4 page 112:
// If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
// as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this
// image was attached in the currently bound framebuffer.
- if (mReadFramebuffer)
+ if (mReadFramebuffer && mReadFramebuffer->detachTexture(context, texture))
{
- mReadFramebuffer->detachTexture(texture);
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
}
- if (mDrawFramebuffer)
+ if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture))
{
- mDrawFramebuffer->detachTexture(texture);
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
}
}
-void State::initializeZeroTextures(const TextureMap &zeroTextures)
+void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
{
for (const auto &zeroTexture : zeroTextures)
{
@@ -751,14 +891,16 @@ void State::initializeZeroTextures(const TextureMap &zeroTextures)
for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
{
- samplerTextureArray[textureUnit].set(zeroTexture.second.get());
+ samplerTextureArray[textureUnit].set(context, zeroTexture.second.get());
}
}
}
-void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
+void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
{
- mSamplers[textureUnit].set(sampler);
+ mSamplers[textureUnit].set(context, sampler);
+ mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
}
GLuint State::getSamplerId(GLuint textureUnit) const
@@ -772,25 +914,26 @@ Sampler *State::getSampler(GLuint textureUnit) const
return mSamplers[textureUnit].get();
}
-void State::detachSampler(GLuint sampler)
+void State::detachSampler(const Context *context, GLuint sampler)
{
// [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
// If a sampler object that is currently bound to one or more texture units is
// deleted, it is as though BindSampler is called once for each texture unit to
// which the sampler is bound, with unit set to the texture unit and sampler set to zero.
- for (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++)
+ for (BindingPointer<Sampler> &samplerBinding : mSamplers)
{
- BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit];
if (samplerBinding.id() == sampler)
{
- samplerBinding.set(NULL);
+ samplerBinding.set(context, nullptr);
+ mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
}
}
}
-void State::setRenderbufferBinding(Renderbuffer *renderbuffer)
+void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer)
{
- mRenderbuffer.set(renderbuffer);
+ mRenderbuffer.set(context, renderbuffer);
+ mDirtyBits.set(DIRTY_BIT_RENDERBUFFER_BINDING);
}
GLuint State::getRenderbufferId() const
@@ -798,12 +941,12 @@ GLuint State::getRenderbufferId() const
return mRenderbuffer.id();
}
-Renderbuffer *State::getCurrentRenderbuffer()
+Renderbuffer *State::getCurrentRenderbuffer() const
{
return mRenderbuffer.get();
}
-void State::detachRenderbuffer(GLuint renderbuffer)
+void State::detachRenderbuffer(const Context *context, GLuint renderbuffer)
{
// [OpenGL ES 2.0.24] section 4.4 page 109:
// If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
@@ -811,7 +954,7 @@ void State::detachRenderbuffer(GLuint renderbuffer)
if (mRenderbuffer.id() == renderbuffer)
{
- mRenderbuffer.set(NULL);
+ setRenderbufferBinding(context, nullptr);
}
// [OpenGL ES 2.0.24] section 4.4 page 111:
@@ -822,14 +965,17 @@ void State::detachRenderbuffer(GLuint renderbuffer)
Framebuffer *readFramebuffer = mReadFramebuffer;
Framebuffer *drawFramebuffer = mDrawFramebuffer;
- if (readFramebuffer)
+ if (readFramebuffer && readFramebuffer->detachRenderbuffer(context, renderbuffer))
{
- readFramebuffer->detachRenderbuffer(renderbuffer);
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
}
if (drawFramebuffer && drawFramebuffer != readFramebuffer)
{
- drawFramebuffer->detachRenderbuffer(renderbuffer);
+ if (drawFramebuffer->detachRenderbuffer(context, renderbuffer))
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ }
}
}
@@ -873,26 +1019,16 @@ Framebuffer *State::getTargetFramebuffer(GLenum target) const
return mDrawFramebuffer;
default:
UNREACHABLE();
- return NULL;
+ return nullptr;
}
}
-Framebuffer *State::getReadFramebuffer()
+Framebuffer *State::getReadFramebuffer() const
{
return mReadFramebuffer;
}
-Framebuffer *State::getDrawFramebuffer()
-{
- return mDrawFramebuffer;
-}
-
-const Framebuffer *State::getReadFramebuffer() const
-{
- return mReadFramebuffer;
-}
-
-const Framebuffer *State::getDrawFramebuffer() const
+Framebuffer *State::getDrawFramebuffer() const
{
return mDrawFramebuffer;
}
@@ -934,13 +1070,13 @@ void State::setVertexArrayBinding(VertexArray *vertexArray)
GLuint State::getVertexArrayId() const
{
- ASSERT(mVertexArray != NULL);
+ ASSERT(mVertexArray != nullptr);
return mVertexArray->id();
}
VertexArray *State::getVertexArray() const
{
- ASSERT(mVertexArray != NULL);
+ ASSERT(mVertexArray != nullptr);
return mVertexArray;
}
@@ -948,7 +1084,7 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
{
if (mVertexArray->id() == vertexArray)
{
- mVertexArray = NULL;
+ mVertexArray = nullptr;
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
return true;
@@ -957,13 +1093,47 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
return false;
}
-void State::setProgram(Program *newProgram)
+void State::bindVertexBuffer(const Context *context,
+ GLuint bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex)
+{
+ getVertexArray()->setVertexAttribBinding(context, attribIndex, bindingIndex);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
+{
+ getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger,
+ relativeOffset);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+ getVertexArray()->setVertexBindingDivisor(bindingIndex, divisor);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setProgram(const Context *context, Program *newProgram)
{
if (mProgram != newProgram)
{
if (mProgram)
{
- mProgram->release();
+ mProgram->release(context);
}
mProgram = newProgram;
@@ -971,7 +1141,10 @@ void State::setProgram(Program *newProgram)
if (mProgram)
{
newProgram->addRef();
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
}
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING);
}
}
@@ -980,9 +1153,10 @@ Program *State::getProgram() const
return mProgram;
}
-void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
+void State::setTransformFeedbackBinding(const Context *context,
+ TransformFeedback *transformFeedback)
{
- mTransformFeedback.set(transformFeedback);
+ mTransformFeedback.set(context, transformFeedback);
}
TransformFeedback *State::getCurrentTransformFeedback() const
@@ -992,23 +1166,37 @@ TransformFeedback *State::getCurrentTransformFeedback() const
bool State::isTransformFeedbackActiveUnpaused() const
{
- gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+ TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused();
}
-void State::detachTransformFeedback(GLuint transformFeedback)
+bool State::removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback)
{
if (mTransformFeedback.id() == transformFeedback)
{
- mTransformFeedback.set(NULL);
+ mTransformFeedback.set(context, nullptr);
+ return true;
}
+
+ return false;
+}
+
+void State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline)
+{
+ mProgramPipeline.set(context, pipeline);
+}
+
+void State::detachProgramPipeline(const Context *context, GLuint pipeline)
+{
+ mProgramPipeline.set(context, nullptr);
}
-bool State::isQueryActive() const
+bool State::isQueryActive(const GLenum type) const
{
for (auto &iter : mActiveQueries)
{
- if (iter.second.get() != NULL)
+ const Query *query = iter.second.get();
+ if (query != nullptr && ActiveQueryType(query->getType()) == ActiveQueryType(type))
{
return true;
}
@@ -1030,9 +1218,9 @@ bool State::isQueryActive(Query *query) const
return false;
}
-void State::setActiveQuery(GLenum target, Query *query)
+void State::setActiveQuery(const Context *context, GLenum target, Query *query)
{
- mActiveQueries[target].set(query);
+ mActiveQueries[target].set(context, query);
}
GLuint State::getActiveQueryId(GLenum target) const
@@ -1051,24 +1239,64 @@ Query *State::getActiveQuery(GLenum target) const
return it->second.get();
}
-void State::setArrayBufferBinding(Buffer *buffer)
+void State::setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer)
{
- mArrayBuffer.set(buffer);
-}
-
-GLuint State::getArrayBufferId() const
-{
- return mArrayBuffer.id();
+ switch (target)
+ {
+ case BufferBinding::PixelPack:
+ mBoundBuffers[target].set(context, buffer);
+ mDirtyBits.set(DIRTY_BIT_PACK_BUFFER_BINDING);
+ break;
+ case BufferBinding::PixelUnpack:
+ mBoundBuffers[target].set(context, buffer);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_BUFFER_BINDING);
+ break;
+ case BufferBinding::DrawIndirect:
+ mBoundBuffers[target].set(context, buffer);
+ mDirtyBits.set(DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
+ break;
+ case BufferBinding::TransformFeedback:
+ if (mTransformFeedback.get() != nullptr)
+ {
+ mTransformFeedback->bindGenericBuffer(context, buffer);
+ }
+ break;
+ case BufferBinding::ElementArray:
+ getVertexArray()->setElementArrayBuffer(context, buffer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ break;
+ default:
+ mBoundBuffers[target].set(context, buffer);
+ break;
+ }
}
-
-void State::setGenericUniformBufferBinding(Buffer *buffer)
+void State::setIndexedBufferBinding(const Context *context,
+ BufferBinding target,
+ GLuint index,
+ Buffer *buffer,
+ GLintptr offset,
+ GLsizeiptr size)
{
- mGenericUniformBuffer.set(buffer);
-}
+ setBufferBinding(context, target, buffer);
-void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
-{
- mUniformBuffers[index].set(buffer, offset, size);
+ switch (target)
+ {
+ case BufferBinding::TransformFeedback:
+ mTransformFeedback->bindIndexedBuffer(context, index, buffer, offset, size);
+ break;
+ case BufferBinding::Uniform:
+ mUniformBuffers[index].set(context, buffer, offset, size);
+ break;
+ case BufferBinding::AtomicCounter:
+ mAtomicCounterBuffers[index].set(context, buffer, offset, size);
+ break;
+ case BufferBinding::ShaderStorage:
+ mShaderStorageBuffers[index].set(context, buffer, offset, size);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
}
const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
@@ -1077,62 +1305,48 @@ const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index)
return mUniformBuffers[index];
}
-void State::setCopyReadBufferBinding(Buffer *buffer)
+const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
{
- mCopyReadBuffer.set(buffer);
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ return mAtomicCounterBuffers[index];
}
-void State::setCopyWriteBufferBinding(Buffer *buffer)
+const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
{
- mCopyWriteBuffer.set(buffer);
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ return mShaderStorageBuffers[index];
}
-void State::setPixelPackBufferBinding(Buffer *buffer)
-{
- mPack.pixelBuffer.set(buffer);
-}
-
-void State::setPixelUnpackBufferBinding(Buffer *buffer)
-{
- mUnpack.pixelBuffer.set(buffer);
-}
-
-Buffer *State::getTargetBuffer(GLenum target) const
+Buffer *State::getTargetBuffer(BufferBinding target) const
{
switch (target)
{
- case GL_ARRAY_BUFFER: return mArrayBuffer.get();
- case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get();
- case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get();
- case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer().get();
- case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get();
- case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get();
- case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get();
- case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get();
- default: UNREACHABLE(); return NULL;
+ case BufferBinding::ElementArray:
+ return getVertexArray()->getElementArrayBuffer().get();
+ case BufferBinding::TransformFeedback:
+ return mTransformFeedback->getGenericBuffer().get();
+ default:
+ return mBoundBuffers[target].get();
}
}
-void State::detachBuffer(GLuint bufferName)
+void State::detachBuffer(const Context *context, GLuint bufferName)
{
- BindingPointer<Buffer> *buffers[] = {&mArrayBuffer, &mCopyReadBuffer,
- &mCopyWriteBuffer, &mPack.pixelBuffer,
- &mUnpack.pixelBuffer, &mGenericUniformBuffer};
- for (auto buffer : buffers)
+ for (auto &buffer : mBoundBuffers)
{
- if (buffer->id() == bufferName)
+ if (buffer.id() == bufferName)
{
- buffer->set(nullptr);
+ buffer.set(context, nullptr);
}
}
TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
if (curTransformFeedback)
{
- curTransformFeedback->detachBuffer(bufferName);
+ curTransformFeedback->detachBuffer(context, bufferName);
}
- getVertexArray()->detachBuffer(bufferName);
+ getVertexArray()->detachBuffer(context, bufferName);
}
void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
@@ -1145,46 +1359,56 @@ void State::setVertexAttribf(GLuint index, const GLfloat values[4])
{
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setFloatValues(values);
- mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
}
void State::setVertexAttribu(GLuint index, const GLuint values[4])
{
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
- mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
}
void State::setVertexAttribi(GLuint index, const GLint values[4])
{
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setIntValues(values);
- mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
+}
+
+void State::setVertexAttribPointer(const Context *context,
+ unsigned int attribNum,
+ Buffer *boundBuffer,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLsizei stride,
+ const void *pointer)
+{
+ getVertexArray()->setVertexAttribPointer(context, attribNum, boundBuffer, size, type,
+ normalized, pureInteger, stride, pointer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
-void State::setVertexAttribState(unsigned int attribNum,
- Buffer *boundBuffer,
- GLint size,
- GLenum type,
- bool normalized,
- bool pureInteger,
- GLsizei stride,
- const void *pointer)
+void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
{
- getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
+ getVertexArray()->setVertexAttribDivisor(context, index, divisor);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
-void State::setVertexAttribDivisor(GLuint index, GLuint divisor)
+const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(size_t attribNum) const
{
- getVertexArray()->setVertexAttribDivisor(index, divisor);
- mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ ASSERT(attribNum < mVertexAttribCurrentValues.size());
+ return mVertexAttribCurrentValues[attribNum];
}
-const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
+const std::vector<VertexAttribCurrentValueData> &State::getVertexAttribCurrentValues() const
{
- ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
- return mVertexAttribCurrentValues[attribNum];
+ return mVertexAttribCurrentValues;
}
const void *State::getVertexAttribPointer(unsigned int attribNum) const
@@ -1195,7 +1419,7 @@ const void *State::getVertexAttribPointer(unsigned int attribNum) const
void State::setPackAlignment(GLint alignment)
{
mPack.alignment = alignment;
- mDirtyBits.set(DIRTY_BIT_PACK_ALIGNMENT);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackAlignment() const
@@ -1206,7 +1430,7 @@ GLint State::getPackAlignment() const
void State::setPackReverseRowOrder(bool reverseRowOrder)
{
mPack.reverseRowOrder = reverseRowOrder;
- mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
bool State::getPackReverseRowOrder() const
@@ -1217,7 +1441,7 @@ bool State::getPackReverseRowOrder() const
void State::setPackRowLength(GLint rowLength)
{
mPack.rowLength = rowLength;
- mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackRowLength() const
@@ -1228,7 +1452,7 @@ GLint State::getPackRowLength() const
void State::setPackSkipRows(GLint skipRows)
{
mPack.skipRows = skipRows;
- mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackSkipRows() const
@@ -1239,7 +1463,7 @@ GLint State::getPackSkipRows() const
void State::setPackSkipPixels(GLint skipPixels)
{
mPack.skipPixels = skipPixels;
- mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackSkipPixels() const
@@ -1260,7 +1484,7 @@ PixelPackState &State::getPackState()
void State::setUnpackAlignment(GLint alignment)
{
mUnpack.alignment = alignment;
- mDirtyBits.set(DIRTY_BIT_UNPACK_ALIGNMENT);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackAlignment() const
@@ -1271,7 +1495,7 @@ GLint State::getUnpackAlignment() const
void State::setUnpackRowLength(GLint rowLength)
{
mUnpack.rowLength = rowLength;
- mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackRowLength() const
@@ -1282,7 +1506,7 @@ GLint State::getUnpackRowLength() const
void State::setUnpackImageHeight(GLint imageHeight)
{
mUnpack.imageHeight = imageHeight;
- mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackImageHeight() const
@@ -1293,7 +1517,7 @@ GLint State::getUnpackImageHeight() const
void State::setUnpackSkipImages(GLint skipImages)
{
mUnpack.skipImages = skipImages;
- mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackSkipImages() const
@@ -1304,7 +1528,7 @@ GLint State::getUnpackSkipImages() const
void State::setUnpackSkipRows(GLint skipRows)
{
mUnpack.skipRows = skipRows;
- mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackSkipRows() const
@@ -1315,7 +1539,7 @@ GLint State::getUnpackSkipRows() const
void State::setUnpackSkipPixels(GLint skipPixels)
{
mUnpack.skipPixels = skipPixels;
- mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackSkipPixels() const
@@ -1343,6 +1567,84 @@ Debug &State::getDebug()
return mDebug;
}
+void State::setCoverageModulation(GLenum components)
+{
+ mCoverageModulation = components;
+ mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
+}
+
+GLenum State::getCoverageModulation() const
+{
+ return mCoverageModulation;
+}
+
+void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+ if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM)
+ {
+ memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat));
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
+ }
+ else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM)
+ {
+ memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat));
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+const GLfloat *State::getPathRenderingMatrix(GLenum which) const
+{
+ if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM)
+ {
+ return mPathMatrixMV;
+ }
+ else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM)
+ {
+ return mPathMatrixProj;
+ }
+
+ UNREACHABLE();
+ return nullptr;
+}
+
+void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ mPathStencilFunc = func;
+ mPathStencilRef = ref;
+ mPathStencilMask = mask;
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
+}
+
+GLenum State::getPathStencilFunc() const
+{
+ return mPathStencilFunc;
+}
+
+GLint State::getPathStencilRef() const
+{
+ return mPathStencilRef;
+}
+
+GLuint State::getPathStencilMask() const
+{
+ return mPathStencilMask;
+}
+
+void State::setFramebufferSRGB(bool sRGB)
+{
+ mFramebufferSRGB = sRGB;
+ mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB);
+}
+
+bool State::getFramebufferSRGB() const
+{
+ return mFramebufferSRGB;
+}
+
void State::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
@@ -1355,10 +1657,15 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
params[2] = mBlend.colorMaskBlue;
params[3] = mBlend.colorMaskAlpha;
break;
- case GL_CULL_FACE: *params = mRasterizer.cullFace; break;
+ case GL_CULL_FACE:
+ *params = mRasterizer.cullFace;
+ break;
case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break;
case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break;
case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break;
+ case GL_SAMPLE_MASK:
+ *params = mSampleMask;
+ break;
case GL_SCISSOR_TEST: *params = mScissorTest; break;
case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break;
case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break;
@@ -1378,6 +1685,28 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_DEBUG_OUTPUT:
*params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE;
break;
+ case GL_MULTISAMPLE_EXT:
+ *params = mMultiSampling;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = mSampleAlphaToOne;
+ break;
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_CLIENT_ARRAYS_ANGLE:
+ *params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *params = mRobustResourceInit ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PROGRAM_CACHE_ENABLED_ANGLE:
+ *params = mProgramBinaryCacheEnabled ? GL_TRUE : GL_FALSE;
+ break;
+
default:
UNREACHABLE();
break;
@@ -1413,13 +1742,21 @@ void State::getFloatv(GLenum pname, GLfloat *params)
params[2] = mBlendColor.blue;
params[3] = mBlendColor.alpha;
break;
+ case GL_MULTISAMPLE_EXT:
+ *params = static_cast<GLfloat>(mMultiSampling);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = static_cast<GLfloat>(mSampleAlphaToOne);
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ params[0] = static_cast<GLfloat>(mCoverageModulation);
+ break;
default:
UNREACHABLE();
break;
}
}
-void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
+void State::getIntegerv(const Context *context, GLenum pname, GLint *params)
{
if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
{
@@ -1437,8 +1774,15 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
// State::getFloatv.
switch (pname)
{
- case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break;
- case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBuffer().id(); break;
+ case GL_ARRAY_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::Array].id();
+ break;
+ case GL_DRAW_INDIRECT_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::DrawIndirect].id();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+ *params = getVertexArray()->getElementArrayBuffer().id();
+ break;
//case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break;
case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break;
@@ -1477,10 +1821,14 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break;
case GL_STENCIL_REF: *params = mStencilRef; break;
- case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilMask);
+ break;
case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break;
case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break;
- case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilBackMask);
+ break;
case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break;
case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break;
case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break;
@@ -1494,32 +1842,40 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break;
case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break;
case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break;
- case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break;
- case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break;
+ case GL_STENCIL_WRITEMASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilWritemask);
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilBackWritemask);
+ break;
case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break;
- case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break;
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ *params = mReadFramebuffer->getImplementationColorReadType(context);
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ *params = mReadFramebuffer->getImplementationColorReadFormat(context);
+ break;
case GL_SAMPLE_BUFFERS:
case GL_SAMPLES:
{
- gl::Framebuffer *framebuffer = mDrawFramebuffer;
- if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
+ Framebuffer *framebuffer = mDrawFramebuffer;
+ if (framebuffer->checkStatus(context) == GL_FRAMEBUFFER_COMPLETE)
{
switch (pname)
{
- case GL_SAMPLE_BUFFERS:
- if (framebuffer->getSamples(data) != 0)
- {
- *params = 1;
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_SAMPLES:
- *params = framebuffer->getSamples(data);
- break;
+ case GL_SAMPLE_BUFFERS:
+ if (framebuffer->getSamples(context) != 0)
+ {
+ *params = 1;
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_SAMPLES:
+ *params = framebuffer->getSamples(context);
+ break;
}
}
else
@@ -1540,15 +1896,19 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
params[2] = mScissor.width;
params[3] = mScissor.height;
break;
- case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break;
- case GL_FRONT_FACE: *params = mRasterizer.frontFace; break;
+ case GL_CULL_FACE_MODE:
+ *params = ToGLenum(mRasterizer.cullMode);
+ break;
+ case GL_FRONT_FACE:
+ *params = mRasterizer.frontFace;
+ break;
case GL_RED_BITS:
case GL_GREEN_BITS:
case GL_BLUE_BITS:
case GL_ALPHA_BITS:
{
- gl::Framebuffer *framebuffer = getDrawFramebuffer();
- const gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer();
+ Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer();
if (colorbuffer)
{
@@ -1568,8 +1928,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_DEPTH_BITS:
{
- const gl::Framebuffer *framebuffer = getDrawFramebuffer();
- const gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
+ const Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
if (depthbuffer)
{
@@ -1583,8 +1943,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_STENCIL_BITS:
{
- const gl::Framebuffer *framebuffer = getDrawFramebuffer();
- const gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
+ const Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
if (stencilbuffer)
{
@@ -1600,6 +1960,11 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D);
break;
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_RECTANGLE_ANGLE);
+ break;
case GL_TEXTURE_BINDING_CUBE_MAP:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params =
@@ -1614,27 +1979,45 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
*params =
getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D_ARRAY);
break;
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_2D_MULTISAMPLE);
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_EXTERNAL_OES);
+ break;
case GL_UNIFORM_BUFFER_BINDING:
- *params = mGenericUniformBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::Uniform].id();
+ break;
case GL_TRANSFORM_FEEDBACK_BINDING:
*params = mTransformFeedback.id();
break;
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- *params = mTransformFeedback->getGenericBuffer().id();
- break;
+ ASSERT(mTransformFeedback.get() != nullptr);
+ *params = mTransformFeedback->getGenericBuffer().id();
+ break;
case GL_COPY_READ_BUFFER_BINDING:
- *params = mCopyReadBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::CopyRead].id();
+ break;
case GL_COPY_WRITE_BUFFER_BINDING:
- *params = mCopyWriteBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::CopyWrite].id();
+ break;
case GL_PIXEL_PACK_BUFFER_BINDING:
- *params = mPack.pixelBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::PixelPack].id();
+ break;
case GL_PIXEL_UNPACK_BUFFER_BINDING:
- *params = mUnpack.pixelBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::PixelUnpack].id();
+ break;
+ case GL_READ_BUFFER:
+ *params = mReadFramebuffer->getReadBufferState();
+ break;
+ case GL_SAMPLER_BINDING:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerId(static_cast<GLuint>(mActiveSampler));
+ break;
case GL_DEBUG_LOGGED_MESSAGES:
*params = static_cast<GLint>(mDebug.getMessageCount());
break;
@@ -1644,6 +2027,20 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
case GL_DEBUG_GROUP_STACK_DEPTH:
*params = static_cast<GLint>(mDebug.getGroupStackDepth());
break;
+ case GL_MULTISAMPLE_EXT:
+ *params = static_cast<GLint>(mMultiSampling);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = static_cast<GLint>(mSampleAlphaToOne);
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ *params = static_cast<GLint>(mCoverageModulation);
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::AtomicCounter].id();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::ShaderStorage].id();
+ break;
default:
UNREACHABLE();
break;
@@ -1666,75 +2063,111 @@ void State::getPointerv(GLenum pname, void **params) const
}
}
-bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
+void State::getIntegeri_v(GLenum target, GLuint index, GLint *data)
{
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
- {
- *data = mTransformFeedback->getIndexedBuffer(index).id();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).id();
+ break;
case GL_UNIFORM_BUFFER_BINDING:
- if (static_cast<size_t>(index) < mUniformBuffers.size())
- {
- *data = mUniformBuffers[index].id();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].id();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].id();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].id();
+ break;
+ case GL_VERTEX_BINDING_BUFFER:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getBuffer().id();
+ break;
+ case GL_VERTEX_BINDING_DIVISOR:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getDivisor();
+ break;
+ case GL_VERTEX_BINDING_OFFSET:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).getOffset());
+ break;
+ case GL_VERTEX_BINDING_STRIDE:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getStride();
+ break;
+ case GL_SAMPLE_MASK_VALUE:
+ ASSERT(static_cast<size_t>(index) < mSampleMaskValues.size());
+ *data = mSampleMaskValues[index];
+ break;
default:
- return false;
+ UNREACHABLE();
+ break;
}
-
- return true;
}
-bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
+void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
- {
- *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
+ break;
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
- {
- *data = mTransformFeedback->getIndexedBuffer(index).getSize();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).getSize();
+ break;
case GL_UNIFORM_BUFFER_START:
- if (static_cast<size_t>(index) < mUniformBuffers.size())
- {
- *data = mUniformBuffers[index].getOffset();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].getOffset();
+ break;
case GL_UNIFORM_BUFFER_SIZE:
- if (static_cast<size_t>(index) < mUniformBuffers.size())
- {
- *data = mUniformBuffers[index].getSize();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].getSize();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].getOffset();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].getSize();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].getOffset();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].getSize();
+ break;
default:
- return false;
+ UNREACHABLE();
+ break;
}
+}
- return true;
+void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ UNREACHABLE();
}
-bool State::hasMappedBuffer(GLenum target) const
+bool State::hasMappedBuffer(BufferBinding target) const
{
- if (target == GL_ARRAY_BUFFER)
+ if (target == BufferBinding::Array)
{
- const VertexArray *vao = getVertexArray();
+ const VertexArray *vao = getVertexArray();
const auto &vertexAttribs = vao->getVertexAttributes();
+ const auto &vertexBindings = vao->getVertexBindings();
size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
for (size_t attribIndex = 0; attribIndex < maxEnabledAttrib; attribIndex++)
{
- const gl::VertexAttribute &vertexAttrib = vertexAttribs[attribIndex];
- gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
+ const VertexAttribute &vertexAttrib = vertexAttribs[attribIndex];
+ auto *boundBuffer = vertexBindings[vertexAttrib.bindingIndex].getBuffer().get();
if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
{
return true;
@@ -1750,35 +2183,36 @@ bool State::hasMappedBuffer(GLenum target) const
}
}
-void State::syncDirtyObjects()
+void State::syncDirtyObjects(const Context *context)
{
if (!mDirtyObjects.any())
return;
- syncDirtyObjects(mDirtyObjects);
+ syncDirtyObjects(context, mDirtyObjects);
}
-void State::syncDirtyObjects(const DirtyObjects &bitset)
+void State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset)
{
- for (auto dirtyObject : angle::IterateBitSet(bitset))
+ for (auto dirtyObject : bitset)
{
switch (dirtyObject)
{
case DIRTY_OBJECT_READ_FRAMEBUFFER:
ASSERT(mReadFramebuffer);
- mReadFramebuffer->syncState();
+ mReadFramebuffer->syncState(context);
break;
case DIRTY_OBJECT_DRAW_FRAMEBUFFER:
ASSERT(mDrawFramebuffer);
- mDrawFramebuffer->syncState();
+ mDrawFramebuffer->syncState(context);
break;
case DIRTY_OBJECT_VERTEX_ARRAY:
ASSERT(mVertexArray);
- mVertexArray->syncImplState();
+ mVertexArray->syncState(context);
break;
- case DIRTY_OBJECT_PROGRAM:
- // TODO(jmadill): implement this
+ case DIRTY_OBJECT_PROGRAM_TEXTURES:
+ syncProgramTextures(context);
break;
+
default:
UNREACHABLE();
break;
@@ -1788,7 +2222,82 @@ void State::syncDirtyObjects(const DirtyObjects &bitset)
mDirtyObjects &= ~bitset;
}
-void State::syncDirtyObject(GLenum target)
+void State::syncProgramTextures(const Context *context)
+{
+ // TODO(jmadill): Fine-grained updates.
+ if (!mProgram)
+ {
+ return;
+ }
+
+ ASSERT(mDirtyObjects[DIRTY_OBJECT_PROGRAM_TEXTURES]);
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+
+ ActiveTextureMask newActiveTextures;
+
+ // Initialize to the 'Initialized' state and set to 'MayNeedInit' if any texture is not
+ // initialized.
+ mCachedTexturesInitState = InitState::Initialized;
+
+ for (const SamplerBinding &samplerBinding : mProgram->getSamplerBindings())
+ {
+ if (samplerBinding.unreferenced)
+ continue;
+
+ GLenum textureType = samplerBinding.textureType;
+ for (GLuint textureUnitIndex : samplerBinding.boundTextureUnits)
+ {
+ Texture *texture = getSamplerTexture(textureUnitIndex, textureType);
+ Sampler *sampler = getSampler(textureUnitIndex);
+ ASSERT(static_cast<size_t>(textureUnitIndex) < mCompleteTextureCache.size());
+ ASSERT(static_cast<size_t>(textureUnitIndex) < newActiveTextures.size());
+
+ ASSERT(texture);
+
+ // Mark the texture binding bit as dirty if the texture completeness changes.
+ // TODO(jmadill): Use specific dirty bit for completeness change.
+ if (texture->isSamplerComplete(context, sampler) &&
+ !mDrawFramebuffer->hasTextureAttachment(texture))
+ {
+ texture->syncState();
+ mCompleteTextureCache[textureUnitIndex] = texture;
+ }
+ else
+ {
+ mCompleteTextureCache[textureUnitIndex] = nullptr;
+ }
+
+ // Bind the texture unconditionally, to recieve completeness change notifications.
+ mCompleteTextureBindings[textureUnitIndex].bind(texture->getDirtyChannel());
+ mActiveTexturesMask.set(textureUnitIndex);
+ newActiveTextures.set(textureUnitIndex);
+
+ if (sampler != nullptr)
+ {
+ sampler->syncState(context);
+ }
+
+ if (texture->initState() == InitState::MayNeedInit)
+ {
+ mCachedTexturesInitState = InitState::MayNeedInit;
+ }
+ }
+ }
+
+ // Unset now missing textures.
+ ActiveTextureMask negativeMask = mActiveTexturesMask & ~newActiveTextures;
+ if (negativeMask.any())
+ {
+ for (auto textureIndex : negativeMask)
+ {
+ mCompleteTextureBindings[textureIndex].reset();
+ mCompleteTextureCache[textureIndex] = nullptr;
+ mActiveTexturesMask.reset(textureIndex);
+ }
+ }
+}
+
+void State::syncDirtyObject(const Context *context, GLenum target)
{
DirtyObjects localSet;
@@ -1807,12 +2316,14 @@ void State::syncDirtyObject(GLenum target)
case GL_VERTEX_ARRAY:
localSet.set(DIRTY_OBJECT_VERTEX_ARRAY);
break;
+ case GL_TEXTURE:
+ case GL_SAMPLER:
case GL_PROGRAM:
- localSet.set(DIRTY_OBJECT_PROGRAM);
+ localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
break;
}
- syncDirtyObjects(localSet);
+ syncDirtyObjects(context, localSet);
}
void State::setObjectDirty(GLenum target)
@@ -1832,10 +2343,91 @@ void State::setObjectDirty(GLenum target)
case GL_VERTEX_ARRAY:
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
break;
+ case GL_TEXTURE:
+ case GL_SAMPLER:
case GL_PROGRAM:
- mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
break;
}
}
+void State::onProgramExecutableChange(Program *program)
+{
+ // OpenGL Spec:
+ // "If LinkProgram or ProgramBinary successfully re-links a program object
+ // that was already in use as a result of a previous call to UseProgram, then the
+ // generated executable code will be installed as part of the current rendering state."
+ if (program->isLinked() && mProgram == program)
+ {
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+ }
+}
+
+void State::setImageUnit(const Context *context,
+ GLuint unit,
+ Texture *texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ mImageUnits[unit].texture.set(context, texture);
+ mImageUnits[unit].level = level;
+ mImageUnits[unit].layered = layered;
+ mImageUnits[unit].layer = layer;
+ mImageUnits[unit].access = access;
+ mImageUnits[unit].format = format;
+}
+
+const ImageUnit &State::getImageUnit(GLuint unit) const
+{
+ return mImageUnits[unit];
+}
+
+// Handle a dirty texture event.
+void State::signal(size_t textureIndex, InitState initState)
+{
+ // Conservatively assume all textures are dirty.
+ // TODO(jmadill): More fine-grained update.
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+
+ if (initState == InitState::MayNeedInit)
+ {
+ mCachedTexturesInitState = InitState::MayNeedInit;
+ }
+}
+
+Error State::clearUnclearedActiveTextures(const Context *context)
+{
+ ASSERT(mRobustResourceInit);
+
+ if (mCachedTexturesInitState == InitState::Initialized)
+ {
+ return NoError();
+ }
+
+ for (auto textureIndex : mActiveTexturesMask)
+ {
+ Texture *texture = mCompleteTextureCache[textureIndex];
+ if (texture)
+ {
+ ANGLE_TRY(texture->ensureInitialized(context));
+ }
+ }
+
+ mCachedTexturesInitState = InitState::Initialized;
+
+ return NoError();
+}
+
+AttributesMask State::getAndResetDirtyCurrentValues() const
+{
+ AttributesMask retVal = mDirtyCurrentValues;
+ mDirtyCurrentValues.reset();
+ return retVal;
+}
+
} // namespace gl