Disable skipValidation when context is lost.

Lost no-error contexts should gracefully handle GetProgramiv, etc.

Includes test that a lost no-error context doesn't crash on getProgramiv.
Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1601703

Bug: angleproject:4244
Change-Id: I8c37df37e83308ab85ad958df6dab46b0ab348e1
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2003239
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jeff Gilbert 2019-12-26 20:58:48 -08:00 коммит произвёл Commit Bot
Родитель 13c44dfeb0
Коммит 05e08edf70
3 изменённых файлов: 57 добавлений и 9 удалений

Просмотреть файл

@ -2777,7 +2777,16 @@ void Context::markContextLost(GraphicsResetStatus status)
mResetStatus = status;
mContextLostForced = true;
}
setContextLost();
}
void Context::setContextLost()
{
mContextLost = true;
// Stop skipping validation, since many implementation entrypoint assume they can't
// be called when lost, or with null object arguments, etc.
mSkipValidation = false;
}
GLenum Context::getGraphicsResetStatus()
@ -2786,9 +2795,9 @@ GLenum Context::getGraphicsResetStatus()
// as it will allow us to skip all the calls.
if (mResetStrategy == GL_NO_RESET_NOTIFICATION_EXT)
{
if (!mContextLost && mImplementation->getResetStatus() != GraphicsResetStatus::NoError)
if (!isContextLost() && mImplementation->getResetStatus() != GraphicsResetStatus::NoError)
{
mContextLost = true;
setContextLost();
}
// EXT_robustness, section 2.6: If the reset notification behavior is
@ -2800,14 +2809,14 @@ GLenum Context::getGraphicsResetStatus()
// The GL_EXT_robustness spec says that if a reset is encountered, a reset
// status should be returned at least once, and GL_NO_ERROR should be returned
// once the device has finished resetting.
if (!mContextLost)
if (!isContextLost())
{
ASSERT(mResetStatus == GraphicsResetStatus::NoError);
mResetStatus = mImplementation->getResetStatus();
if (mResetStatus != GraphicsResetStatus::NoError)
{
mContextLost = true;
setContextLost();
}
}
else if (!mContextLostForced && mResetStatus != GraphicsResetStatus::NoError)
@ -5717,7 +5726,7 @@ void Context::framebufferTexture2DMultisample(GLenum target,
void Context::getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
{
const Sync *syncObject = nullptr;
if (!mContextLost)
if (!isContextLost())
{
syncObject = getSync(sync);
}
@ -6430,7 +6439,7 @@ void Context::getIntegervRobust(GLenum pname, GLsizei bufSize, GLsizei *length,
void Context::getProgramiv(ShaderProgramID program, GLenum pname, GLint *params)
{
Program *programObject = nullptr;
if (!mContextLost)
if (!isContextLost())
{
// Don't resolve link if checking the link completion status.
programObject = (pname == GL_COMPLETION_STATUS_KHR ? getProgramNoResolveLink(program)
@ -6485,7 +6494,7 @@ void Context::getProgramPipelineInfoLog(ProgramPipelineID pipeline,
void Context::getShaderiv(ShaderProgramID shader, GLenum pname, GLint *params)
{
Shader *shaderObject = nullptr;
if (!mContextLost)
if (!isContextLost())
{
shaderObject = getShader(shader);
ASSERT(shaderObject);

Просмотреть файл

@ -453,6 +453,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
void markContextLost(GraphicsResetStatus status);
bool isContextLost() const { return mContextLost; }
void setContextLost();
GLenum getGraphicsResetStrategy() const { return mResetStrategy; }
bool isResetNotificationEnabled();
@ -512,9 +513,16 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
const TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
const Extensions &getExtensions() const { return mState.getExtensions(); }
const Limitations &getLimitations() const { return mState.getLimitations(); }
bool skipValidation() const { return mSkipValidation; }
bool isGLES1() const;
bool skipValidation() const
{
// Ensure we don't skip validation when context becomes lost, since implementations
// generally assume a non-lost context, non-null objects, etc.
ASSERT(!isContextLost() || !mSkipValidation);
return mSkipValidation;
}
// Specific methods needed for validation.
bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const;
bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) const;
@ -680,7 +688,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
// Current/lost context flags
bool mHasBeenCurrent;
bool mContextLost;
bool mContextLost; // Set with setContextLost so that we also set mSkipValidation=false.
GraphicsResetStatus mResetStatus;
bool mContextLostForced;
GLenum mResetStrategy;

Просмотреть файл

@ -103,6 +103,29 @@ TEST_P(ContextLostTest, ParallelCompileReadyQuery)
EXPECT_GLENUM_EQ(linkStatus, 0xBADF00D);
}
class ContextLostSkipValidationTest : public ANGLETest
{
protected:
ContextLostSkipValidationTest()
{
setContextResetStrategy(EGL_LOSE_CONTEXT_ON_RESET_EXT);
setNoErrorEnabled(true);
}
};
// Use GL_CHROMIUM_lose_context to lose a context and verify
TEST_P(ContextLostSkipValidationTest, LostNoErrorGetProgram)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_lose_context"));
GLuint program = glCreateProgram();
glLoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET, GL_INNOCENT_CONTEXT_RESET);
GLint val = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &val); // Should not crash.
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(ContextLostTest,
@ -113,4 +136,12 @@ ANGLE_INSTANTIATE_TEST(ContextLostTest,
ES2_VULKAN(),
ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(ContextLostSkipValidationTest,
ES2_NULL(),
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_VULKAN(),
ES3_VULKAN());
} // namespace angle