// // Copyright 2019 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. // // validationESEXT.cpp: Validation functions for OpenGL ES extension entry points.
GLenum implType = obj->getImplementationColorReadType(context); if (!ValidES3Type(type) && (type != implType || type == GL_NONE))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType); returnfalse;
}
// Format/type combinations are not yet validated.
returntrue;
}
bool IsValidImageLayout(ImageLayout layout)
{ switch (layout)
{ case ImageLayout::Undefined: case ImageLayout::General: case ImageLayout::ColorAttachment: case ImageLayout::DepthStencilAttachment: case ImageLayout::DepthStencilReadOnlyAttachment: case ImageLayout::ShaderReadOnly: case ImageLayout::TransferSrc: case ImageLayout::TransferDst: case ImageLayout::DepthReadOnlyStencilAttachment: case ImageLayout::DepthAttachmentStencilReadOnly: returntrue;
if (texture->isCompressedFormatEmulated(context, target, level))
{ // TODO (anglebug.com/7464): We can't currently read back from an emulated format
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidEmulatedFormat); returnfalse;
}
// Skip range checks for no-op calls. if (count <= 0)
{ returntrue;
}
// Note that resolving the index range is a bit slow. We should probably optimize this.
IndexRange indexRange;
ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count,
indices, &indexRange));
if (indexRange.end > end || indexRange.start < start)
{ // GL spec says that behavior in this case is undefined - generating an error is fine.
context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsElementRange); returnfalse;
} returntrue;
}
const State &state = context->getState();
TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); if (!ValidateDrawElementsIndirect(context, entryPoint, modePacked, typePacked, indirect))
{ returnfalse;
}
if (curTransformFeedback && curTransformFeedback->isActive() &&
!curTransformFeedback->isPaused())
{ // EXT_geometry_shader allows transform feedback to work with all draw commands. // [EXT_geometry_shader] Section 12.1, "Transform Feedback" if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2)
{ if (!ValidateTransformFeedbackPrimitiveMode(
context, entryPoint, curTransformFeedback->getPrimitiveMode(), modePacked))
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
kInvalidDrawModeTransformFeedback); returnfalse;
}
} else
{ // An INVALID_OPERATION error is generated if transform feedback is active and not // paused.
context->validationError(entryPoint, GL_INVALID_OPERATION,
kUnsupportedDrawModeForTransformFeedback); returnfalse;
}
}
// Skip range checks for no-op calls. if (count <= 0)
{ returntrue;
}
// Note that resolving the index range is a bit slow. We should probably optimize this.
IndexRange indexRange;
ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count,
indices, &indexRange));
if (indexRange.end > end || indexRange.start < start)
{ // GL spec says that behavior in this case is undefined - generating an error is fine.
context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsElementRange); returnfalse;
} returntrue;
}
for (GLuint i = 0; i < numBufferBarriers; ++i)
{ if (!context->getBuffer(buffers[i]))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidBufferName); returnfalse;
}
}
for (GLuint i = 0; i < numTextureBarriers; ++i)
{ if (!context->getTexture(textures[i]))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName); returnfalse;
} if (!IsValidImageLayout(FromGLenum<ImageLayout>(dstLayouts[i])))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageLayout); returnfalse;
}
}
for (GLuint i = 0; i < numBufferBarriers; ++i)
{ if (!context->getBuffer(buffers[i]))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidBufferName); returnfalse;
}
}
for (GLuint i = 0; i < numTextureBarriers; ++i)
{ if (!context->getTexture(textures[i]))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName); returnfalse;
} if (!IsValidImageLayout(FromGLenum<ImageLayout>(srcLayouts[i])))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageLayout); returnfalse;
}
}
namespace
{ enumclass PLSExpectedStatus : bool
{
Inactive,
Active
};
bool ValidatePLSCommon(const Context *context,
angle::EntryPoint entryPoint,
PLSExpectedStatus expectedStatus)
{ // Check that the pixel local storage extension is enabled at all. if (!context->getExtensions().shaderPixelLocalStorageANGLE)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSExtensionNotEnabled); returnfalse;
}
// INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is // bound to DRAW_FRAMEBUFFER. if (context->getState().getDrawFramebuffer()->id().value == 0)
{
context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
kPLSDefaultFramebufferBound); returnfalse;
}
if (expectedStatus == PLSExpectedStatus::Inactive)
{ // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE is TRUE. if (context->getState().getPixelLocalStorageActive())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSActive); returnfalse;
}
} else
{
ASSERT(expectedStatus == PLSExpectedStatus::Active);
// INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE is FALSE. if (!context->getState().getPixelLocalStorageActive())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSInactive); returnfalse;
}
}
// INVALID_VALUE is generated if <plane> < 0 or <plane> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE. if (plane < 0)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlaneLessThanZero); returnfalse;
} if (plane >= static_cast<GLint>(context->getCaps().maxPixelLocalStoragePlanes))
{
context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlaneOutOfRange); returnfalse;
}
returntrue;
}
bool ValidatePLSInternalformat(const Context *context,
angle::EntryPoint entryPoint,
GLenum internalformat)
{ // INVALID_ENUM is generated if <internalformat> is not one of the acceptable values in Table // X.2, or NONE. switch (internalformat)
{ case GL_RGBA8: case GL_RGBA8I: case GL_RGBA8UI: case GL_R32F: case GL_R32UI: returntrue; default:
context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidInternalformat); returnfalse;
}
}
bool ValidatePLSTextureType(const Context *context,
angle::EntryPoint entryPoint,
Texture *tex,
size_t *textureDepth)
{ // INVALID_ENUM is generated if <backingtexture> is nonzero and not of type GL_TEXTURE_2D, // GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY, or GL_TEXTURE_3D. switch (tex->getType())
{ case TextureType::_2D:
*textureDepth = 1; returntrue; case TextureType::CubeMap:
*textureDepth = 6; returntrue; case TextureType::_2DArray:
*textureDepth = tex->getDepth(TextureTarget::_2DArray, 0); returntrue; case TextureType::_3D:
*textureDepth = tex->getDepth(TextureTarget::_3D, 0); returntrue; default:
context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidTextureType); returnfalse;
}
}
bool ValidatePLSLoadOperation(const Context *context, angle::EntryPoint entryPoint, GLenum loadop)
{ // INVALID_ENUM is generated if <loadops>[0..<planes>-1] is not one of the Load Operations // enumerated in Table X.1. switch (loadop)
{ case GL_ZERO: case GL_CLEAR_ANGLE: case GL_KEEP: case GL_DONT_CARE: case GL_DISABLE_ANGLE: returntrue; default:
context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidLoadOperation); returnfalse;
}
}
} // namespace
// INVALID_ENUM is generated if <internalformat> is not one of the acceptable values in Table // X.2, or NONE. if (internalformat != GL_NONE)
{ if (!ValidatePLSInternalformat(context, entryPoint, internalformat))
{ returnfalse;
}
}
if (backingtexture.value != 0)
{
Texture *tex = context->getTexture(backingtexture);
// INVALID_OPERATION is generated if <backingtexture> is not the name of an existing // immutable texture object, or zero. if (!tex)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName); returnfalse;
} if (!tex->getImmutableFormat())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsNotImmutable); returnfalse;
}
// INVALID_ENUM is generated if <backingtexture> is nonzero and not of type GL_TEXTURE_2D, // GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY, or GL_TEXTURE_3D.
size_t textureDepth; if (!ValidatePLSTextureType(context, entryPoint, tex, &textureDepth))
{ returnfalse;
}
// INVALID_VALUE is generated if <backingtexture> is nonzero and <level> < 0. if (level < 0)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLevel); returnfalse;
}
// INVALID_VALUE is generated if <backingtexture> is nonzero and <level> >= the // immutable number of mipmap levels in <backingtexture>. if (static_cast<GLuint>(level) >= tex->getImmutableLevels())
{
context->validationError(entryPoint, GL_INVALID_VALUE, kTextureLevelOutOfRange); returnfalse;
}
// INVALID_VALUE is generated if <backingtexture> is nonzero and <layer> < 0. if (layer < 0)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLayer); returnfalse;
}
// INVALID_VALUE is generated if <backingtexture> is nonzero and <layer> >= the immutable // number of texture layers in <backingtexture>. if ((size_t)layer >= textureDepth)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kTextureLayerOutOfRange); returnfalse;
}
// INVALID_ENUM is generated if <backingtexture> is nonzero and its internalformat is not // one of the acceptable values in Table X.2.
ASSERT(tex->getImmutableFormat());
GLenum internalformat = tex->getState().getBaseLevelDesc().format.info->internalFormat; if (!ValidatePLSInternalformat(context, entryPoint, internalformat))
{ returnfalse;
}
}
const State &state = context->getState(); const Framebuffer *framebuffer = state.getDrawFramebuffer();
// INVALID_OPERATION is generated if the value of SAMPLE_BUFFERS is 1 (i.e., if rendering to a // multisampled framebuffer). if (framebuffer->getSamples(context) != 0)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSMultisamplingEnabled); returnfalse;
}
// INVALID_OPERATION is generated if DITHER is enabled. if (state.isDitherEnabled())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSDitherEnabled); returnfalse;
}
// INVALID_OPERATION is generated if RASTERIZER_DISCARD is enabled. if (state.isRasterizerDiscardEnabled())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSRasterizerDiscardEnabled); returnfalse;
}
// INVALID_OPERATION is generated if SAMPLE_ALPHA_TO_COVERAGE is enabled. if (state.isSampleAlphaToCoverageEnabled())
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.27 Sekunden
(vorverarbeitet)
¤
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.