// // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //
// State.cpp: Implements the State class, encapsulating raw GL state.
// Mapping from a buffer binding type to a dirty bit type.
constexpr angle::PackedEnumMap<BufferBinding, size_t> kBufferBindingDirtyBits = {{
{BufferBinding::AtomicCounter, State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING},
{BufferBinding::DispatchIndirect, State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING},
{BufferBinding::DrawIndirect, State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING},
{BufferBinding::PixelPack, State::DIRTY_BIT_PACK_BUFFER_BINDING},
{BufferBinding::PixelUnpack, State::DIRTY_BIT_UNPACK_BUFFER_BINDING},
{BufferBinding::ShaderStorage, State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING},
{BufferBinding::Uniform, State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS},
}};
// Returns a buffer binding function depending on if a dirty bit is set. template <BufferBinding Target>
constexpr std::pair<BufferBinding, State::BufferBindingSetter> GetBufferBindingSetter()
{ return std::make_pair(Target, kBufferBindingDirtyBits[Target] != 0
? &State::setGenericBufferBindingWithBit<Target>
: &State::setGenericBufferBinding<Target>);
}
template <typename T> using ContextStateMember = T *(State::*);
template <typename T>
T *AllocateOrGetSharedResourceManager(const State *shareContextState,
ContextStateMember<T> member,
T *shareResources = nullptr)
{ if (shareContextState)
{
T *resourceManager = (*shareContextState).*member;
ASSERT(!resourceManager || resourceManager == shareResources || !shareResources);
resourceManager->addRef(); return resourceManager;
} elseif (shareResources)
{
shareResources->addRef(); return shareResources;
} else
{ returnnew T();
}
}
// TODO(https://anglebug.com/3889): Remove this helper function after blink and chromium part // refactory done. bool IsTextureCompatibleWithSampler(TextureType texture, TextureType sampler)
{ if (sampler == texture)
{ returntrue;
}
if (sampler == TextureType::VideoImage)
{ if (texture == TextureType::VideoImage || texture == TextureType::_2D)
{ returntrue;
}
}
// These template functions must be defined before they are instantiated in kBufferSetters. template <BufferBinding Target> void State::setGenericBufferBindingWithBit(const Context *context, Buffer *buffer)
{ if (context->isWebGL())
{
UpdateNonTFBufferBindingWebGL(context, &mBoundBuffers[Target], buffer);
} else
{
mBoundBuffers[Target].set(context, buffer);
}
mDirtyBits.set(kBufferBindingDirtyBits[Target]);
}
// Set all indexes in state attributes type mask to float (default) for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
SetComponentTypeMask(ComponentType::Float, i, &mCurrentValuesTypeMask);
}
// GLES1 emulation: Initialize state for GLES1 if version applies // TODO(http://anglebug.com/3745): When on desktop client only do this in compatibility profile if (clientVersion < Version(2, 0) || mClientType == EGL_OPENGL_API)
{
mGLES1State.initialize(context, this);
}
}
void State::reset(const Context *context)
{ // Force a sync so clear doesn't end up dereferencing stale pointers.
(void)syncActiveTextures(context, Command::Other);
mActiveTexturesCache.clear();
for (TextureBindingVector &bindingVec : mSamplerTextures)
{ for (BindingPointer<Texture> &texBinding : bindingVec)
{
texBinding.set(context, nullptr);
}
} for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
{
mSamplers[samplerIdx].set(context, nullptr);
}
if (texture->hasAnyDirtyBit())
{
setTextureDirty(textureIndex);
}
if (mRobustResourceInit && texture->initState() == InitState::MayNeedInit)
{
mDirtyObjects.set(DIRTY_OBJECT_TEXTURES_INIT);
}
// This cache is updated immediately because we use the cache in the validation layer. // If we defer the update until syncState it's too late and we've already passed validation. if (texture && mExecutable)
{ // It is invalid to try to sample a non-yuv texture with a yuv sampler.
mTexturesIncompatibleWithSamplers[textureIndex] =
mExecutable->getActiveYUVSamplers().test(textureIndex) && !texture->isYUV();
bool State::allActiveDrawBufferChannelsMasked() const
{ // Compare current color mask with all-disabled color mask, while ignoring disabled draw // buffers. return (mBlendStateExt.compareColorMask(0) & mDrawFramebuffer->getDrawBufferMask()).none();
}
bool State::anyActiveDrawBufferChannelMasked() const
{ // Compare current color mask with all-enabled color mask, while ignoring disabled draw // buffers. return (mBlendStateExt.compareColorMask(mBlendStateExt.getAllColorMaskBits()) &
mDrawFramebuffer->getDrawBufferMask())
.any();
}
void State::setBlendColor(float red, float green, float blue, float alpha)
{ // In ES2 without render-to-float extensions, BlendColor clamps to [0,1] on store. // On ES3+, or with render-to-float exts enabled, it does not clamp on store. constbool isES2 = mClientVersion.major == 2; constbool hasFloatBlending =
mExtensions.colorBufferFloatEXT || mExtensions.colorBufferHalfFloatEXT ||
mExtensions.colorBufferFloatRgbCHROMIUM || mExtensions.colorBufferFloatRgbaCHROMIUM; if ((isES2 && !hasFloatBlending) || mNoUnclampedBlendColor)
{
red = clamp01(red);
green = clamp01(green);
blue = clamp01(blue);
alpha = clamp01(alpha);
}
if (mBlendColor.red != red || mBlendColor.green != green || mBlendColor.blue != blue ||
mBlendColor.alpha != alpha)
{
mBlendColor.red = red;
mBlendColor.green = green;
mBlendColor.blue = blue;
mBlendColor.alpha = alpha;
mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
}
}
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);
}
void State::setEnableFeature(GLenum feature, bool enabled)
{ switch (feature)
{ case GL_MULTISAMPLE_EXT:
setMultisampling(enabled); return; case GL_SAMPLE_ALPHA_TO_ONE_EXT:
setSampleAlphaToOne(enabled); return; case GL_CULL_FACE:
setCullFace(enabled); return; case GL_POLYGON_OFFSET_FILL:
setPolygonOffsetFill(enabled); return; case GL_SAMPLE_ALPHA_TO_COVERAGE:
setSampleAlphaToCoverage(enabled); return; case GL_SAMPLE_COVERAGE:
setSampleCoverage(enabled); return; case GL_SCISSOR_TEST:
setScissorTest(enabled); return; case GL_STENCIL_TEST:
setStencilTest(enabled); return; case GL_DEPTH_TEST:
setDepthTest(enabled); return; case GL_BLEND:
setBlend(enabled); return; case GL_DITHER:
setDither(enabled); return; case GL_COLOR_LOGIC_OP: if (mClientVersion.major == 1)
{ // Handle logicOp in GLES1 through the GLES1 state management and emulation. // Otherwise this state could be set as part of ANGLE_logic_op. break;
}
setLogicOpEnabled(enabled); return; case GL_PRIMITIVE_RESTART_FIXED_INDEX:
setPrimitiveRestart(enabled); return; case GL_RASTERIZER_DISCARD:
setRasterizerDiscard(enabled); return; case GL_SAMPLE_MASK:
setSampleMaskEnabled(enabled); return; case GL_DEBUG_OUTPUT_SYNCHRONOUS:
mDebug.setOutputSynchronous(enabled); return; case GL_DEBUG_OUTPUT:
mDebug.setOutputEnabled(enabled); return; case GL_FRAMEBUFFER_SRGB_EXT:
setFramebufferSRGB(enabled); return; case GL_TEXTURE_RECTANGLE_ANGLE:
mTextureRectangleEnabled = enabled; return; case GL_SAMPLE_SHADING:
setSampleShading(enabled); return; // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance case GL_CLIP_DISTANCE0_EXT: case GL_CLIP_DISTANCE1_EXT: case GL_CLIP_DISTANCE2_EXT: case GL_CLIP_DISTANCE3_EXT: case GL_CLIP_DISTANCE4_EXT: case GL_CLIP_DISTANCE5_EXT: case GL_CLIP_DISTANCE6_EXT: case GL_CLIP_DISTANCE7_EXT: // NOTE(hqle): These enums are conflicted with GLES1's enums, need // to do additional check here: if (mClientVersion.major >= 2)
{
setClipDistanceEnable(feature - GL_CLIP_DISTANCE0_EXT, enabled); return;
} break; case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
mShadingRatePreserveAspectRatio = enabled; return;
}
ASSERT(mClientVersion.major == 1);
// GLES1 emulation. Need to separate from main switch due to conflict enum between // GL_CLIP_DISTANCE0_EXT & GL_CLIP_PLANE0 switch (feature)
{ case GL_ALPHA_TEST:
mGLES1State.mAlphaTestEnabled = enabled; break; case GL_TEXTURE_2D:
mGLES1State.mTexUnitEnables[mActiveSampler].set(TextureType::_2D, enabled); break; case GL_TEXTURE_CUBE_MAP:
mGLES1State.mTexUnitEnables[mActiveSampler].set(TextureType::CubeMap, enabled); break; case GL_LIGHTING:
mGLES1State.mLightingEnabled = enabled; break; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: case GL_LIGHT3: case GL_LIGHT4: case GL_LIGHT5: case GL_LIGHT6: case GL_LIGHT7:
mGLES1State.mLights[feature - GL_LIGHT0].enabled = enabled; break; case GL_NORMALIZE:
mGLES1State.mNormalizeEnabled = enabled; break; case GL_RESCALE_NORMAL:
mGLES1State.mRescaleNormalEnabled = enabled; break; case GL_COLOR_MATERIAL:
mGLES1State.mColorMaterialEnabled = enabled; break; case GL_CLIP_PLANE0: case GL_CLIP_PLANE1: case GL_CLIP_PLANE2: case GL_CLIP_PLANE3: case GL_CLIP_PLANE4: case GL_CLIP_PLANE5:
mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled = enabled; break; case GL_FOG:
mGLES1State.mFogEnabled = enabled; break; case GL_POINT_SMOOTH:
mGLES1State.mPointSmoothEnabled = enabled; break; case GL_LINE_SMOOTH:
mGLES1State.mLineSmoothEnabled = enabled; break; case GL_POINT_SPRITE_OES:
mGLES1State.mPointSpriteEnabled = enabled; break; case GL_COLOR_LOGIC_OP:
mGLES1State.setLogicOpEnabled(enabled); break; default:
UNREACHABLE();
}
}
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(); case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); case GL_SCISSOR_TEST: return isScissorTestEnabled(); case GL_STENCIL_TEST: return isStencilTestEnabled(); case GL_DEPTH_TEST: return isDepthTestEnabled(); case GL_BLEND: return isBlendEnabled(); case GL_DITHER: return isDitherEnabled(); case GL_COLOR_LOGIC_OP: if (mClientVersion.major == 1)
{ // Handle logicOp in GLES1 through the GLES1 state management and emulation. break;
} return isLogicOpEnabled(); 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(); 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; case GL_TEXTURE_RECTANGLE_ANGLE: return mTextureRectangleEnabled; case GL_SAMPLE_SHADING: return isSampleShadingEnabled(); // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance case GL_CLIP_DISTANCE0_EXT: case GL_CLIP_DISTANCE1_EXT: case GL_CLIP_DISTANCE2_EXT: case GL_CLIP_DISTANCE3_EXT: case GL_CLIP_DISTANCE4_EXT: case GL_CLIP_DISTANCE5_EXT: case GL_CLIP_DISTANCE6_EXT: case GL_CLIP_DISTANCE7_EXT: if (mClientVersion.major >= 2)
{ // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as // GL_CLIP_PLANE0 instead. return mClipDistancesEnabled.test(feature - GL_CLIP_DISTANCE0_EXT);
} break; case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM: return mShadingRatePreserveAspectRatio;
}
ASSERT(mClientVersion.major == 1);
switch (feature)
{ // GLES1 emulation case GL_ALPHA_TEST: return mGLES1State.mAlphaTestEnabled; case GL_VERTEX_ARRAY: return mGLES1State.mVertexArrayEnabled; case GL_NORMAL_ARRAY: return mGLES1State.mNormalArrayEnabled; case GL_COLOR_ARRAY: return mGLES1State.mColorArrayEnabled; case GL_POINT_SIZE_ARRAY_OES: return mGLES1State.mPointSizeArrayEnabled; case GL_TEXTURE_COORD_ARRAY: return mGLES1State.mTexCoordArrayEnabled[mGLES1State.mClientActiveTexture]; case GL_TEXTURE_2D: return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::_2D); case GL_TEXTURE_CUBE_MAP: return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::CubeMap); case GL_LIGHTING: return mGLES1State.mLightingEnabled; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: case GL_LIGHT3: case GL_LIGHT4: case GL_LIGHT5: case GL_LIGHT6: case GL_LIGHT7: return mGLES1State.mLights[feature - GL_LIGHT0].enabled; case GL_NORMALIZE: return mGLES1State.mNormalizeEnabled; case GL_RESCALE_NORMAL: return mGLES1State.mRescaleNormalEnabled; case GL_COLOR_MATERIAL: return mGLES1State.mColorMaterialEnabled; case GL_CLIP_PLANE0: case GL_CLIP_PLANE1: case GL_CLIP_PLANE2: case GL_CLIP_PLANE3: case GL_CLIP_PLANE4: case GL_CLIP_PLANE5: return mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled; case GL_FOG: return mGLES1State.mFogEnabled; case GL_POINT_SMOOTH: return mGLES1State.mPointSmoothEnabled; case GL_LINE_SMOOTH: return mGLES1State.mLineSmoothEnabled; case GL_POINT_SPRITE_OES: return mGLES1State.mPointSpriteEnabled; case GL_COLOR_LOGIC_OP: return mGLES1State.mLogicOpEnabled; default:
UNREACHABLE(); returnfalse;
}
}
void State::setTextureFilteringHint(GLenum hint)
{
mTextureFilteringHint = hint; // Note: we don't add a dirty bit for this flag as it's not expected to be toggled at // runtime.
}
void State::setFragmentShaderDerivativeHint(GLenum hint)
{
mFragmentShaderDerivativeHint = hint;
mDirtyBits.set(DIRTY_BIT_EXTENDED);
mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT); // TODO: Propagate the hint to shader translator so we can write // ddx, ddx_coarse, or ddx_fine depending on the hint. // Ignore for now. It is valid for implementations to ignore hint.
}
void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{ // [OpenGL ES 2.0.25] section 2.12.1 page 45: // Viewport width and height are clamped to implementation-dependent maximums when specified.
width = std::min(width, mCaps.maxViewportWidth);
height = std::min(height, mCaps.maxViewportHeight);
// Skip if same viewport info if (mViewport.x != x || mViewport.y != y || mViewport.width != width ||
mViewport.height != height)
{
mViewport.x = x;
mViewport.y = y;
mViewport.width = width;
mViewport.height = height;
mDirtyBits.set(DIRTY_BIT_VIEWPORT);
}
}
void State::detachTexture(const Context *context, const TextureMap &zeroTextures, TextureID texture)
{ // Textures have a detach method on State rather than a simple // removeBinding, because the zero/null texture objects are managed // separately, and don't have to go through the Context's maps or // the ResourceManager.
// [OpenGL ES 2.0.24] section 3.8 page 84: // 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 (TextureType type : angle::AllEnums<TextureType>())
{
TextureBindingVector &textureVector = mSamplerTextures[type];
for (size_t bindingIndex = 0; bindingIndex < textureVector.size(); ++bindingIndex)
{
BindingPointer<Texture> &binding = textureVector[bindingIndex]; if (binding.id() == texture)
{ // Zero textures are the "default" textures instead of NULL
Texture *zeroTexture = zeroTextures[type].get();
ASSERT(zeroTexture != nullptr); if (mCompleteTextureBindings[bindingIndex].getSubject() == binding.get())
{
updateTextureBinding(context, bindingIndex, zeroTexture);
}
binding.set(context, zeroTexture);
}
}
}
// [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 && mReadFramebuffer->detachTexture(context, texture))
{
mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
}
if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture))
{
setDrawFramebufferDirty();
}
}
void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
{ for (TextureType type : angle::AllEnums<TextureType>())
{ for (size_t textureUnit = 0; textureUnit < mSamplerTextures[type].size(); ++textureUnit)
{
mSamplerTextures[type][textureUnit].set(context, zeroTextures[type].get());
}
}
}
mSamplers[textureUnit].set(context, sampler);
mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS); // This is overly conservative as it assumes the sampler has never been bound.
setSamplerDirty(textureUnit);
onActiveTextureChange(context, textureUnit);
}
void State::detachSampler(const Context *context, SamplerID 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 i = 0; i < mSamplers.size(); i++)
{ if (mSamplers[i].id() == sampler)
{
setSamplerBinding(context, static_cast<GLuint>(i), nullptr);
}
}
}
void State::detachRenderbuffer(const Context *context, RenderbufferID 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 had been executed with the target RENDERBUFFER and name of zero.
if (mRenderbuffer.id() == renderbuffer)
{
setRenderbufferBinding(context, nullptr);
}
// [OpenGL ES 2.0.24] section 4.4 page 111: // If a renderbuffer object is deleted while its image is attached to the currently bound // framebuffer, then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of // 0, for each attachment point to which this image was attached in the currently bound // framebuffer.
angle::Result State::setProgram(const Context *context, Program *newProgram)
{ if (newProgram && !newProgram->isLinked())
{ // Protect against applications that disable validation and try to use a program that was // not successfully linked.
WARN() << "Attempted to use a program that was not successfully linked"; return angle::Result::Continue;
}
if (mProgram != newProgram)
{ if (mProgram)
{
unsetActiveTextures(mExecutable->getActiveSamplersMask());
mProgram->release(context);
}
// A bound Program always overrides the ProgramPipeline, so only update the // current ProgramExecutable if there isn't currently a Program bound. if (!mProgram)
{ if (mProgramPipeline.get())
{
mExecutable = &mProgramPipeline->getExecutable();
ANGLE_TRY(onProgramPipelineExecutableChange(context));
} else
{
mExecutable = nullptr;
}
}
// A bound Program always overrides the ProgramPipeline, so only update the // current ProgramExecutable if there isn't currently a Program bound. if (!mProgram)
{
mExecutable = nullptr;
}
}
void State::getBooleanv(GLenum pname, GLboolean *params) const
{ switch (pname)
{ case GL_SAMPLE_COVERAGE_INVERT:
*params = mSampleCoverageInvert; break; case GL_DEPTH_WRITEMASK:
*params = mDepthStencil.depthMask; break; case GL_COLOR_WRITEMASK:
{ // non-indexed get returns the state of draw buffer zero bool r, g, b, a;
mBlendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
params[0] = r;
params[1] = g;
params[2] = b;
params[3] = a; 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 = mSampleAlphaToCoverage; 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; case GL_BLEND: // non-indexed get returns the state of draw buffer zero
*params = mBlendStateExt.getEnabledMask().test(0); break; case GL_DITHER:
*params = mRasterizer.dither; break; case GL_COLOR_LOGIC_OP:
ASSERT(mClientVersion.major > 1);
*params = mLogicOpEnabled; break; case GL_TRANSFORM_FEEDBACK_ACTIVE:
*params = getCurrentTransformFeedback()->isActive() ? GL_TRUE : GL_FALSE; break; case GL_TRANSFORM_FEEDBACK_PAUSED:
*params = getCurrentTransformFeedback()->isPaused() ? GL_TRUE : GL_FALSE; break; case GL_PRIMITIVE_RESTART_FIXED_INDEX:
*params = mPrimitiveRestart; break; case GL_RASTERIZER_DISCARD:
*params = isRasterizerDiscardEnabled() ? GL_TRUE : GL_FALSE; break; case GL_DEBUG_OUTPUT_SYNCHRONOUS:
*params = mDebug.isOutputSynchronous() ? GL_TRUE : GL_FALSE; break; 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; case GL_TEXTURE_RECTANGLE_ANGLE:
*params = mTextureRectangleEnabled ? GL_TRUE : GL_FALSE; break; case GL_LIGHT_MODEL_TWO_SIDE:
*params = IsLightModelTwoSided(&mGLES1State); break; case GL_SAMPLE_SHADING:
*params = mIsSampleShadingEnabled; break; case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
*params = isPrimitiveRestartEnabled() && getExtensions().tessellationShaderEXT; break; // 2.2.2 Data Conversions For State Query Commands, in GLES 3.2 spec. // If a command returning boolean data is called, such as GetBooleanv, a floating-point or // integer value converts to FALSE if and only if it is zero. Otherwise it converts to TRUE. // GL_EXT_clip_control case GL_CLIP_ORIGIN_EXT:
*params = GL_TRUE; break; case GL_CLIP_DEPTH_MODE_EXT:
*params = GL_TRUE; break; case GL_ROBUST_FRAGMENT_SHADER_OUTPUT_ANGLE:
*params = mExtensions.robustFragmentShaderOutputANGLE ? GL_TRUE : GL_FALSE; break; // GL_ANGLE_shader_pixel_local_storage case GL_PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE:
*params = mPixelLocalStorageActive ? GL_TRUE : GL_FALSE; break; default:
UNREACHABLE(); break;
}
}
void State::getFloatv(GLenum pname, GLfloat *params) const
{ // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation // because it is stored as a float, despite the fact that the GL ES 2.0 spec names // GetIntegerv as its native query function. As it would require conversion in any // case, this should make no difference to the calling application. switch (pname)
{ case GL_LINE_WIDTH:
*params = mLineWidth; break; case GL_SAMPLE_COVERAGE_VALUE:
*params = mSampleCoverageValue; break; case GL_DEPTH_CLEAR_VALUE:
*params = mDepthClearValue; break; case GL_POLYGON_OFFSET_FACTOR:
*params = mRasterizer.polygonOffsetFactor; break; case GL_POLYGON_OFFSET_UNITS:
*params = mRasterizer.polygonOffsetUnits; break; case GL_DEPTH_RANGE:
params[0] = mNearZ;
params[1] = mFarZ; break; case GL_COLOR_CLEAR_VALUE:
params[0] = mColorClearValue.red;
params[1] = mColorClearValue.green;
params[2] = mColorClearValue.blue;
params[3] = mColorClearValue.alpha; break; case GL_BLEND_COLOR:
params[0] = mBlendColor.red;
params[1] = mBlendColor.green;
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); break; case GL_COVERAGE_MODULATION_CHROMIUM:
params[0] = static_cast<GLfloat>(mCoverageModulation); break; case GL_ALPHA_TEST_REF:
*params = mGLES1State.mAlphaTestRef; break; case GL_CURRENT_COLOR:
{ constauto &color = mGLES1State.mCurrentColor;
params[0] = color.red;
params[1] = color.green;
params[2] = color.blue;
params[3] = color.alpha; break;
} case GL_CURRENT_NORMAL:
{ constauto &normal = mGLES1State.mCurrentNormal;
params[0] = normal[0];
params[1] = normal[1];
params[2] = normal[2]; break;
} case GL_CURRENT_TEXTURE_COORDS:
{ constauto &texcoord = mGLES1State.mCurrentTextureCoords[mActiveSampler];
params[0] = texcoord.s;
params[1] = texcoord.t;
params[2] = texcoord.r;
params[3] = texcoord.q; break;
} case GL_MODELVIEW_MATRIX:
memcpy(params, mGLES1State.mModelviewMatrices.back().constData(), 16 * sizeof(GLfloat)); break; case GL_PROJECTION_MATRIX:
memcpy(params, mGLES1State.mProjectionMatrices.back().constData(),
16 * sizeof(GLfloat)); break; case GL_TEXTURE_MATRIX:
memcpy(params, mGLES1State.mTextureMatrices[mActiveSampler].back().constData(),
16 * sizeof(GLfloat)); break; case GL_LIGHT_MODEL_AMBIENT:
GetLightModelParameters(&mGLES1State, pname, params); break; case GL_FOG_MODE: case GL_FOG_DENSITY: case GL_FOG_START: case GL_FOG_END: case GL_FOG_COLOR:
GetFogParameters(&mGLES1State, pname, params); break; case GL_POINT_SIZE:
GetPointSize(&mGLES1State, params); break; case GL_POINT_SIZE_MIN: case GL_POINT_SIZE_MAX: case GL_POINT_FADE_THRESHOLD_SIZE: case GL_POINT_DISTANCE_ATTENUATION:
GetPointParameter(&mGLES1State, FromGLenum<PointParameter>(pname), params); break; case GL_MIN_SAMPLE_SHADING_VALUE:
*params = mMinSampleShading; break; // 2.2.2 Data Conversions For State Query Commands, in GLES 3.2 spec. // If a command returning floating-point data is called, such as GetFloatv, ... An integer // value is coerced to floating-point. case GL_CLIP_ORIGIN_EXT:
*params = static_cast<float>(mClipControlOrigin); break; case GL_CLIP_DEPTH_MODE_EXT:
*params = static_cast<float>(mClipControlDepth); break; default:
UNREACHABLE(); break;
}
}
angle::Result State::getIntegerv(const Context *context, GLenum pname, GLint *params) const
{ if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
{
size_t drawBuffer = (pname - GL_DRAW_BUFFER0_EXT);
ASSERT(drawBuffer < static_cast<size_t>(mCaps.maxDrawBuffers));
Framebuffer *framebuffer = mDrawFramebuffer; // The default framebuffer may have fewer draw buffer states than a user-created one. The // user is always allowed to query up to GL_MAX_DRAWBUFFERS so just return GL_NONE here if // the draw buffer is out of range for this framebuffer.
*params = drawBuffer < framebuffer->getDrawbufferStateCount()
? framebuffer->getDrawBufferState(drawBuffer)
: GL_NONE; return angle::Result::Continue;
}
// Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation // because it is stored as a float, despite the fact that the GL ES 2.0 spec names // GetIntegerv as its native query function. As it would require conversion in any // case, this should make no difference to the calling application. You may find it in // State::getFloatv. switch (pname)
{ case GL_ARRAY_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::Array].id().value; break; case GL_DRAW_INDIRECT_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::DrawIndirect].id().value; break; case GL_ELEMENT_ARRAY_BUFFER_BINDING:
{
Buffer *elementArrayBuffer = getVertexArray()->getElementArrayBuffer();
*params = elementArrayBuffer ? elementArrayBuffer->id().value : 0; break;
} case GL_DRAW_FRAMEBUFFER_BINDING:
static_assert(GL_DRAW_FRAMEBUFFER_BINDING == GL_DRAW_FRAMEBUFFER_BINDING_ANGLE, "Enum mismatch");
*params = mDrawFramebuffer->id().value; break; case GL_READ_FRAMEBUFFER_BINDING:
static_assert(GL_READ_FRAMEBUFFER_BINDING == GL_READ_FRAMEBUFFER_BINDING_ANGLE, "Enum mismatch");
*params = mReadFramebuffer->id().value; break; case GL_RENDERBUFFER_BINDING:
*params = mRenderbuffer.id().value; break; case GL_VERTEX_ARRAY_BINDING:
*params = mVertexArray->id().value; break; case GL_CURRENT_PROGRAM:
*params = mProgram ? mProgram->id().value : 0; break; case GL_PACK_ALIGNMENT:
*params = mPack.alignment; break; case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
*params = mPack.reverseRowOrder; break; case GL_PACK_ROW_LENGTH:
*params = mPack.rowLength; break; case GL_PACK_SKIP_ROWS:
*params = mPack.skipRows; break; case GL_PACK_SKIP_PIXELS:
*params = mPack.skipPixels; break; case GL_UNPACK_ALIGNMENT:
*params = mUnpack.alignment; break; case GL_UNPACK_ROW_LENGTH:
*params = mUnpack.rowLength; break; case GL_UNPACK_IMAGE_HEIGHT:
*params = mUnpack.imageHeight; break; case GL_UNPACK_SKIP_IMAGES:
*params = mUnpack.skipImages; break; case GL_UNPACK_SKIP_ROWS:
*params = mUnpack.skipRows; break; case GL_UNPACK_SKIP_PIXELS:
*params = mUnpack.skipPixels; break; case GL_GENERATE_MIPMAP_HINT:
*params = mGenerateMipmapHint; break; case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
*params = mTextureFilteringHint; break; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
*params = mFragmentShaderDerivativeHint; break; case GL_ACTIVE_TEXTURE:
*params = (static_cast<GLint>(mActiveSampler) + GL_TEXTURE0); break; case GL_STENCIL_FUNC:
*params = mDepthStencil.stencilFunc; break; case GL_STENCIL_REF:
*params = mStencilRef; break; case GL_STENCIL_VALUE_MASK:
*params = CastMaskValue(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 = CastMaskValue(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; case GL_STENCIL_BACK_FAIL:
*params = mDepthStencil.stencilBackFail; break; case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
*params = mDepthStencil.stencilBackPassDepthFail; break; case GL_STENCIL_BACK_PASS_DEPTH_PASS:
*params = mDepthStencil.stencilBackPassDepthPass; break; case GL_DEPTH_FUNC:
*params = mDepthStencil.depthFunc; break; case GL_BLEND_SRC_RGB: // non-indexed get returns the state of draw buffer zero
*params = mBlendStateExt.getSrcColorIndexed(0); break; case GL_BLEND_SRC_ALPHA:
*params = mBlendStateExt.getSrcAlphaIndexed(0); break; case GL_BLEND_DST_RGB:
*params = mBlendStateExt.getDstColorIndexed(0); break; case GL_BLEND_DST_ALPHA:
*params = mBlendStateExt.getDstAlphaIndexed(0); break; case GL_BLEND_EQUATION_RGB:
*params = mBlendStateExt.getEquationColorIndexed(0); break; case GL_BLEND_EQUATION_ALPHA:
*params = mBlendStateExt.getEquationAlphaIndexed(0); break; case GL_STENCIL_WRITEMASK:
*params = CastMaskValue(mDepthStencil.stencilWritemask); break; case GL_STENCIL_BACK_WRITEMASK:
*params = CastMaskValue(mDepthStencil.stencilBackWritemask); break; case GL_STENCIL_CLEAR_VALUE:
*params = mStencilClearValue; 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:
{
Framebuffer *framebuffer = mDrawFramebuffer; if (framebuffer->isComplete(context))
{
GLint samples = framebuffer->getSamples(context); switch (pname)
{ case GL_SAMPLE_BUFFERS: if (samples != 0)
{
*params = 1;
} else
{
*params = 0;
} break; case GL_SAMPLES:
*params = samples; break;
}
} else
{
*params = 0;
}
} break; case GL_VIEWPORT:
params[0] = mViewport.x;
params[1] = mViewport.y;
params[2] = mViewport.width;
params[3] = mViewport.height; break; case GL_SCISSOR_BOX:
params[0] = mScissor.x;
params[1] = mScissor.y;
params[2] = mScissor.width;
params[3] = mScissor.height; 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:
{
Framebuffer *framebuffer = getDrawFramebuffer(); const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorAttachment();
if (colorbuffer)
{ switch (pname)
{ case GL_RED_BITS:
*params = colorbuffer->getRedSize(); break; case GL_GREEN_BITS:
*params = colorbuffer->getGreenSize(); break; case GL_BLUE_BITS:
*params = colorbuffer->getBlueSize(); break; case GL_ALPHA_BITS:
*params = colorbuffer->getAlphaSize(); break;
}
} else
{
*params = 0;
}
} break; case GL_DEPTH_BITS:
{ const Framebuffer *framebuffer = getDrawFramebuffer(); const FramebufferAttachment *depthbuffer = framebuffer->getDepthAttachment();
// GL_OES_texture_buffer case GL_TEXTURE_BINDING_BUFFER:
ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
*params =
getSamplerTextureId(static_cast<unsignedint>(mActiveSampler), TextureType::Buffer)
.value; break; case GL_TEXTURE_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::Texture].id().value; break;
case GL_UNIFORM_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::Uniform].id().value; break; case GL_TRANSFORM_FEEDBACK_BINDING:
*params = mTransformFeedback.id().value; break; case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::TransformFeedback].id().value; break; case GL_COPY_READ_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::CopyRead].id().value; break; case GL_COPY_WRITE_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::CopyWrite].id().value; break; case GL_PIXEL_PACK_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::PixelPack].id().value; break; case GL_PIXEL_UNPACK_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::PixelUnpack].id().value; break;
case GL_READ_BUFFER:
*params = mReadFramebuffer->getReadBufferState(); break; case GL_SAMPLER_BINDING:
ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
*params = getSamplerId(static_cast<GLuint>(mActiveSampler)).value; break; case GL_DEBUG_LOGGED_MESSAGES:
*params = static_cast<GLint>(mDebug.getMessageCount()); break; case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
*params = static_cast<GLint>(mDebug.getNextMessageLength()); break; 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); break; case GL_COVERAGE_MODULATION_CHROMIUM:
*params = static_cast<GLint>(mCoverageModulation); break; case GL_ATOMIC_COUNTER_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::AtomicCounter].id().value; break; case GL_SHADER_STORAGE_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::ShaderStorage].id().value; break; case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
*params = mBoundBuffers[BufferBinding::DispatchIndirect].id().value; break; case GL_ALPHA_TEST_FUNC:
*params = ToGLenum(mGLES1State.mAlphaTestFunc); break; case GL_CLIENT_ACTIVE_TEXTURE:
*params = mGLES1State.mClientActiveTexture + GL_TEXTURE0; break; case GL_MATRIX_MODE:
*params = ToGLenum(mGLES1State.mMatrixMode); break; case GL_SHADE_MODEL:
*params = ToGLenum(mGLES1State.mShadeModel); break; case GL_MODELVIEW_STACK_DEPTH: case GL_PROJECTION_STACK_DEPTH: case GL_TEXTURE_STACK_DEPTH:
*params = mGLES1State.getCurrentMatrixStackDepth(pname); break; case GL_LOGIC_OP_MODE:
*params = ToGLenum(mGLES1State.mLogicOp); break; case GL_BLEND_SRC: // non-indexed get returns the state of draw buffer zero
*params = mBlendStateExt.getSrcColorIndexed(0); break; case GL_BLEND_DST:
*params = mBlendStateExt.getDstColorIndexed(0); break; case GL_PERSPECTIVE_CORRECTION_HINT: case GL_POINT_SMOOTH_HINT: case GL_LINE_SMOOTH_HINT: case GL_FOG_HINT:
*params = mGLES1State.getHint(pname); break;
// GL_ANGLE_provoking_vertex case GL_PROVOKING_VERTEX:
*params = ToGLenum(mProvokingVertex); break;
case GL_PROGRAM_PIPELINE_BINDING:
{
ProgramPipeline *pipeline = getProgramPipeline(); if (pipeline)
{
*params = pipeline->id().value;
} else
{
*params = 0;
} break;
} case GL_PATCH_VERTICES:
*params = mPatchVertices; break;
// GL_EXT_clip_control case GL_CLIP_ORIGIN_EXT:
*params = mClipControlOrigin; break; case GL_CLIP_DEPTH_MODE_EXT:
*params = mClipControlDepth; break;
// GL_QCOM_shading_rate case GL_SHADING_RATE_QCOM:
*params = ToGLenum(mShadingRate); break;
default:
UNREACHABLE(); break;
}
return angle::Result::Continue;
}
void State::getPointerv(const Context *context, GLenum pname, void **params) const
{ switch (pname)
{ case GL_DEBUG_CALLBACK_FUNCTION:
*params = reinterpret_cast<void *>(mDebug.getCallback()); break; case GL_DEBUG_CALLBACK_USER_PARAM:
*params = const_cast<void *>(mDebug.getUserParam()); break; case GL_VERTEX_ARRAY_POINTER: case GL_NORMAL_ARRAY_POINTER: case GL_COLOR_ARRAY_POINTER: case GL_TEXTURE_COORD_ARRAY_POINTER: case GL_POINT_SIZE_ARRAY_POINTER_OES:
QueryVertexAttribPointerv(getVertexArray()->getVertexAttribute(
context->vertexArrayIndex(ParamToVertexArrayType(pname))),
GL_VERTEX_ATTRIB_ARRAY_POINTER, params); return; default:
UNREACHABLE(); break;
}
}
void State::getIntegeri_v(const Context *context, GLenum target, GLuint index, GLint *data) const
{ switch (target)
{ case GL_BLEND_SRC_RGB:
ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
*data = mBlendStateExt.getSrcColorIndexed(index); break; case GL_BLEND_SRC_ALPHA:
ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
*data = mBlendStateExt.getSrcAlphaIndexed(index); break; case GL_BLEND_DST_RGB:
ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
*data = mBlendStateExt.getDstColorIndexed(index); break; case GL_BLEND_DST_ALPHA:
ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
*data = mBlendStateExt.getDstAlphaIndexed(index); break; case GL_BLEND_EQUATION_RGB:
ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
*data = mBlendStateExt.getEquationColorIndexed(index); break; case GL_BLEND_EQUATION_ALPHA:
ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
*data = mBlendStateExt.getEquationAlphaIndexed(index); break; case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
*data = mTransformFeedback->getIndexedBuffer(index).id().value; break; case GL_UNIFORM_BUFFER_BINDING:
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
*data = mUniformBuffers[index].id().value; break; case GL_ATOMIC_COUNTER_BUFFER_BINDING:
ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
*data = mAtomicCounterBuffers[index].id().value; break; case GL_SHADER_STORAGE_BUFFER_BINDING:
ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
*data = mShaderStorageBuffers[index].id().value; break; case GL_VERTEX_BINDING_BUFFER:
ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
*data = mVertexArray->getVertexBinding(index).getBuffer().id().value; 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; case GL_IMAGE_BINDING_NAME:
ASSERT(static_cast<size_t>(index) < mImageUnits.size());
*data = mImageUnits[index].texture.id().value; break; case GL_IMAGE_BINDING_LEVEL:
ASSERT(static_cast<size_t>(index) < mImageUnits.size());
*data = mImageUnits[index].level; break; case GL_IMAGE_BINDING_LAYER:
ASSERT(static_cast<size_t>(index) < mImageUnits.size());
*data = mImageUnits[index].layer; break; case GL_IMAGE_BINDING_ACCESS:
ASSERT(static_cast<size_t>(index) < mImageUnits.size());
*data = mImageUnits[index].access; break; case GL_IMAGE_BINDING_FORMAT:
ASSERT(static_cast<size_t>(index) < mImageUnits.size());
*data = mImageUnits[index].format; break; // GL_ANGLE_shader_pixel_local_storage. case GL_PIXEL_LOCAL_FORMAT_ANGLE: case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE: case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE: case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE:
{
ASSERT(mDrawFramebuffer);
*data = mDrawFramebuffer->getPixelLocalStorage(context).getPlane(index).getIntegeri(
context, target, index); break;
} default:
UNREACHABLE(); break;
}
}
// TODO(http://anglebug.com/3889): Remove this helper function after blink and chromium part // refactor done.
Texture *State::getTextureForActiveSampler(TextureType type, size_t index)
{ if (type != TextureType::VideoImage)
{ return mSamplerTextures[type][index].get();
}
angle::Result State::syncProgram(const Context *context, Command command)
{ // There may not be a program if the calling application only uses program pipelines. if (mProgram)
{ return mProgram->syncState(context);
} return angle::Result::Continue;
}
angle::Result State::syncProgramPipelineObject(const Context *context, Command command)
{ // If a ProgramPipeline is bound, ensure it is linked. if (mProgramPipeline.get())
{
mProgramPipeline->resolveLink(context);
} return angle::Result::Continue;
}
switch (target)
{ case GL_READ_FRAMEBUFFER:
localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER); break; case GL_DRAW_FRAMEBUFFER:
localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); break; case GL_FRAMEBUFFER:
localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); break; case GL_VERTEX_ARRAY:
localSet.set(DIRTY_OBJECT_VERTEX_ARRAY); break; case GL_TEXTURE:
localSet.set(DIRTY_OBJECT_TEXTURES); break; case GL_SAMPLER:
localSet.set(DIRTY_OBJECT_SAMPLERS); break; case GL_PROGRAM:
localSet.set(DIRTY_OBJECT_PROGRAM); break;
}
void State::setObjectDirty(GLenum target)
{ switch (target)
{ case GL_READ_FRAMEBUFFER:
mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); break; case GL_DRAW_FRAMEBUFFER:
setDrawFramebufferDirty(); break; case GL_FRAMEBUFFER:
mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
setDrawFramebufferDirty(); break; case GL_VERTEX_ARRAY:
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); break; case GL_PROGRAM:
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM); break; default: break;
}
}
angle::Result State::onProgramExecutableChange(const Context *context, 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."
ASSERT(program->isLinked());
// If this Program is currently active, we need to update the State's pointer to the current // ProgramExecutable if we just changed it. if (mProgram == program)
{
mExecutable = &program->getExecutable();
}
mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
if (program->hasAnyDirtyBit())
{
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
}
// Set any bound textures. const ProgramExecutable &executable = program->getExecutable(); const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes(); for (size_t textureIndex : executable.getActiveSamplersMask())
{
TextureType type = textureTypes[textureIndex];
// This can happen if there is a conflicting texture type. if (type == TextureType::InvalidEnum) continue;
// Using individual layers of a 3d image as 2d may require that the image be respecified in // a compatible layout if (!layered && texture->getType() == TextureType::_3D)
{
texture->onBind3DTextureAs2DImage();
}
}
imageUnit.texture.set(context, texture);
imageUnit.level = level;
imageUnit.layered = layered;
imageUnit.layer = layer;
imageUnit.access = access;
imageUnit.format = format;
mDirtyBits.set(DIRTY_BIT_IMAGE_BINDINGS);
void State::onUniformBufferStateChange(size_t uniformBufferIndex)
{ // This could be represented by a different dirty bit. Using the same one keeps it simple.
mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
}
// This little kludge gets around the frame capture "constness". It should be safe because // nothing in the context is modified in a non-compatible way during capture.
Context *mutableContext = const_cast<Context *>(context);
initialize(mutableContext);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.