Commit 4e1fd371 by Doug Horn Committed by Angle LUCI CQ

Ensure GLES1 state is cleared on context switch.

GLES1 support in multi-context D3D mode is broken prior to this change as state in the GLES1Renderer is not being properly dirtied on context switch. The immediate result is a crash on draw commands due to a null program. Introduce a new dirty bit to specify that the program is dirty and should be re-initialized. Test: GLES1 applications work with the D3D11 backend in multi-context mode. Bug: b/191158936 Change-Id: Ib53c1471514ff2cf36ef9fc0d6bfb99a8bb7cf66 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2969789Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Doug Horn <doughorn@google.com>
parent d5e86bb0
...@@ -9006,6 +9006,7 @@ void Context::dirtyAllState() ...@@ -9006,6 +9006,7 @@ void Context::dirtyAllState()
{ {
mState.setAllDirtyBits(); mState.setAllDirtyBits();
mState.setAllDirtyObjects(); mState.setAllDirtyObjects();
mState.gles1().setAllDirty();
} }
// ErrorSet implementation. // ErrorSet implementation.
......
...@@ -618,6 +618,14 @@ angle::Result GLES1Renderer::initializeRendererProgram(Context *context, State * ...@@ -618,6 +618,14 @@ angle::Result GLES1Renderer::initializeRendererProgram(Context *context, State *
{ {
if (mRendererProgramInitialized) if (mRendererProgramInitialized)
{ {
// If we're already done the initialization/compilation, but there has been some
// state change, just reload the compiled program.
GLES1State &gles1State = glState->gles1();
if (gles1State.shouldHandleDirtyProgram())
{
Program *programObject = getProgram(mProgramState.program);
ANGLE_TRY(glState->setProgram(context, programObject));
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -219,6 +219,13 @@ const angle::Vector3 &GLES1State::getCurrentNormal() const ...@@ -219,6 +219,13 @@ const angle::Vector3 &GLES1State::getCurrentNormal() const
return mCurrentNormal; return mCurrentNormal;
} }
bool GLES1State::shouldHandleDirtyProgram()
{
bool ret = isDirty(DIRTY_GLES1_PROGRAM);
clearDirtyBits(DIRTY_GLES1_PROGRAM);
return ret;
}
void GLES1State::setCurrentTextureCoords(unsigned int unit, const TextureCoordF &coords) void GLES1State::setCurrentTextureCoords(unsigned int unit, const TextureCoordF &coords)
{ {
setDirty(DIRTY_GLES1_CURRENT_VECTOR); setDirty(DIRTY_GLES1_CURRENT_VECTOR);
...@@ -565,24 +572,4 @@ GLenum GLES1State::getHint(GLenum target) const ...@@ -565,24 +572,4 @@ GLenum GLES1State::getHint(GLenum target) const
} }
} }
void GLES1State::setDirty(DirtyGles1Type type)
{
mDirtyBits.set(type);
}
void GLES1State::setAllDirty()
{
mDirtyBits.set();
}
void GLES1State::clearDirty()
{
mDirtyBits.reset();
}
bool GLES1State::isDirty(DirtyGles1Type type) const
{
return mDirtyBits.test(type);
}
} // namespace gl } // namespace gl
...@@ -218,16 +218,11 @@ class GLES1State final : angle::NonCopyable ...@@ -218,16 +218,11 @@ class GLES1State final : angle::NonCopyable
AttributesMask getVertexArraysAttributeMask() const; AttributesMask getVertexArraysAttributeMask() const;
AttributesMask getActiveAttributesMask() const; AttributesMask getActiveAttributesMask() const;
bool shouldHandleDirtyProgram();
void setHint(GLenum target, GLenum mode); void setHint(GLenum target, GLenum mode);
GLenum getHint(GLenum target) const; GLenum getHint(GLenum target) const;
private:
friend class State;
friend class GLES1Renderer;
// Back pointer for reading from State.
const State *mGLState;
enum DirtyGles1Type enum DirtyGles1Type
{ {
DIRTY_GLES1_TEXTURE_UNIT_ENABLE = 0, DIRTY_GLES1_TEXTURE_UNIT_ENABLE = 0,
...@@ -246,15 +241,26 @@ class GLES1State final : angle::NonCopyable ...@@ -246,15 +241,26 @@ class GLES1State final : angle::NonCopyable
DIRTY_GLES1_LOGIC_OP, DIRTY_GLES1_LOGIC_OP,
DIRTY_GLES1_CLIP_PLANES, DIRTY_GLES1_CLIP_PLANES,
DIRTY_GLES1_HINT_SETTING, DIRTY_GLES1_HINT_SETTING,
DIRTY_GLES1_PROGRAM,
DIRTY_GLES1_MAX, DIRTY_GLES1_MAX,
}; };
void setAllDirty() { mDirtyBits.set(); }
private:
friend class State;
friend class GLES1Renderer;
// Back pointer for reading from State.
const State *mGLState;
using DirtyBits = angle::BitSet<DIRTY_GLES1_MAX>; using DirtyBits = angle::BitSet<DIRTY_GLES1_MAX>;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
void setDirty(DirtyGles1Type type); void setDirty(DirtyGles1Type type) { mDirtyBits.set(type); }
void setAllDirty(); void clearDirty() { mDirtyBits.reset(); }
void clearDirty(); void clearDirtyBits(const DirtyGles1Type &bitset) { mDirtyBits &= ~bitset; }
bool isDirty(DirtyGles1Type type) const; bool isDirty(DirtyGles1Type type) const { return mDirtyBits.test(type); }
// All initial state values come from the // All initial state values come from the
// OpenGL ES 1.1 spec. // OpenGL ES 1.1 spec.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment