Commit 878c8b1e by Martin Radev Committed by Commit Bot

Handle viewport and scissor state changes for side-by-side framebuffers

Side-by-side framebuffers have viewport offsets as part of their state which have to be applied to the viewport and scissor rectangles to generate the final viewport and scissor rectangles of each view. Whenever there is a transition to or from a side-by-side framebuffer, viewport and scissor state has to be synced. Also, because rendering is done on the same 2D texture the scissor test has to be always enabled to guarantee that no fragments leak to a neighboring view. The patch addresses this by extending the viewport and scissor state in StateManagerGL to be a vector of rectangles instead of a single rectangle. Two new dirty bits are added to cover changes in the viewport offsets and whether the framebuffer has a side-by-side layout. BUG=angleproject:2062 TEST=angle_end2end_tests Change-Id: I8107d7ba97d06b20cf24358f19963fa494844592 Reviewed-on: https://chromium-review.googlesource.com/585012 Commit-Queue: Martin Radev <mradev@nvidia.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent ffe754b7
......@@ -1564,16 +1564,6 @@ GLint Framebuffer::getDefaultSamples() const
return mState.getDefaultSamples();
}
GLenum Framebuffer::getMultiviewLayout() const
{
const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
if (firstAttachment == nullptr)
{
return GL_NONE;
}
return firstAttachment->getMultiviewLayout();
}
GLboolean Framebuffer::getDefaultFixedSampleLocations() const
{
return mState.getDefaultFixedSampleLocations();
......@@ -1624,4 +1614,24 @@ GLsizei Framebuffer::getNumViews() const
return attachment->getNumViews();
}
const std::vector<Offset> *Framebuffer::getViewportOffsets() const
{
const FramebufferAttachment *attachment = getFirstNonNullAttachment();
if (attachment == nullptr)
{
return nullptr;
}
return &attachment->getMultiviewViewportOffsets();
}
GLenum Framebuffer::getMultiviewLayout() const
{
const FramebufferAttachment *attachment = getFirstNonNullAttachment();
if (attachment == nullptr)
{
return GL_NONE;
}
return attachment->getMultiviewLayout();
}
} // namespace gl
......@@ -172,7 +172,9 @@ class Framebuffer final : public LabeledObject, public OnAttachmentDirtyReceiver
const FramebufferAttachment *getFirstNonNullAttachment() const;
const FramebufferAttachment *getAttachment(GLenum attachment) const;
GLenum getMultiviewLayout() const;
GLsizei getNumViews() const;
const std::vector<Offset> *getViewportOffsets() const;
size_t getDrawbufferStateCount() const;
GLenum getDrawBufferState(size_t drawBuffer) const;
......@@ -291,7 +293,6 @@ class Framebuffer final : public LabeledObject, public OnAttachmentDirtyReceiver
bool formsCopyingFeedbackLoopWith(GLuint copyTextureID,
GLint copyTextureLevel,
GLint copyTextureLayer) const;
GLenum getMultiviewLayout() const;
private:
void detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
......
......@@ -21,6 +21,24 @@
namespace gl
{
namespace
{
std::vector<Offset> TransformViewportOffsetArrayToVectorOfOffsets(const GLint *viewportOffsets,
GLsizei numViews)
{
const size_t numViewsAsSizeT = static_cast<size_t>(numViews);
std::vector<Offset> offsetVector;
offsetVector.reserve(numViewsAsSizeT);
for (size_t i = 0u; i < numViewsAsSizeT; ++i)
{
offsetVector.emplace_back(Offset(viewportOffsets[i * 2u], viewportOffsets[i * 2u + 1u], 0));
}
return offsetVector;
}
} // namespace
////// FramebufferAttachment::Target Implementation //////
const GLsizei FramebufferAttachment::kDefaultNumViews = 1;
......@@ -28,6 +46,12 @@ const GLenum FramebufferAttachment::kDefaultMultiviewLayout = GL_NONE;
const GLint FramebufferAttachment::kDefaultBaseViewIndex = 0;
const GLint FramebufferAttachment::kDefaultViewportOffsets[2] = {0};
std::vector<Offset> FramebufferAttachment::GetDefaultViewportOffsetVector()
{
return TransformViewportOffsetArrayToVectorOfOffsets(
FramebufferAttachment::kDefaultViewportOffsets, FramebufferAttachment::kDefaultNumViews);
}
FramebufferAttachment::Target::Target()
: mBinding(GL_NONE),
mTextureIndex(ImageIndex::MakeInvalid())
......@@ -61,7 +85,7 @@ FramebufferAttachment::FramebufferAttachment()
mNumViews(kDefaultNumViews),
mMultiviewLayout(kDefaultMultiviewLayout),
mBaseViewIndex(kDefaultBaseViewIndex),
mViewportOffsets(1u)
mViewportOffsets(GetDefaultViewportOffsetVector())
{
}
......@@ -110,8 +134,7 @@ void FramebufferAttachment::detach(const Context *context)
mNumViews = kDefaultNumViews;
mMultiviewLayout = kDefaultMultiviewLayout;
mBaseViewIndex = kDefaultBaseViewIndex;
mViewportOffsets.resize(1u);
mViewportOffsets[0] = Offset();
mViewportOffsets = GetDefaultViewportOffsetVector();
// not technically necessary, could omit for performance
mTarget = Target();
......@@ -138,11 +161,7 @@ void FramebufferAttachment::attach(const Context *context,
mNumViews = numViews;
mBaseViewIndex = baseViewIndex;
mMultiviewLayout = multiviewLayout;
mViewportOffsets.resize(numViews);
for (size_t i = 0u; i < mViewportOffsets.size(); ++i)
{
mViewportOffsets[i] = Offset(viewportOffsets[i * 2u], viewportOffsets[i * 2u + 1u], 0);
}
mViewportOffsets = TransformViewportOffsetArrayToVectorOfOffsets(viewportOffsets, numViews);
resource->onAttach(context);
if (mResource != nullptr)
......
......@@ -129,6 +129,7 @@ class FramebufferAttachment final
bool operator==(const FramebufferAttachment &other) const;
bool operator!=(const FramebufferAttachment &other) const;
static std::vector<Offset> GetDefaultViewportOffsetVector();
static const GLsizei kDefaultNumViews;
static const GLenum kDefaultMultiviewLayout;
static const GLint kDefaultBaseViewIndex;
......
......@@ -33,53 +33,12 @@ using angle::CheckedNumeric;
namespace rx
{
FramebufferGL::FramebufferGL(const FramebufferState &state,
const FunctionsGL *functions,
StateManagerGL *stateManager,
const WorkaroundsGL &workarounds,
BlitGL *blitter,
bool isDefault)
: FramebufferImpl(state),
mFunctions(functions),
mStateManager(stateManager),
mWorkarounds(workarounds),
mBlitter(blitter),
mFramebufferID(0),
mIsDefault(isDefault),
mAppliedEnabledDrawBuffers(1)
namespace
{
if (!mIsDefault)
{
mFunctions->genFramebuffers(1, &mFramebufferID);
}
}
FramebufferGL::FramebufferGL(GLuint id,
const FramebufferState &state,
const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
BlitGL *blitter,
StateManagerGL *stateManager)
: FramebufferImpl(state),
mFunctions(functions),
mStateManager(stateManager),
mWorkarounds(workarounds),
mBlitter(blitter),
mFramebufferID(id),
mIsDefault(true),
mAppliedEnabledDrawBuffers(1)
{
}
FramebufferGL::~FramebufferGL()
{
mStateManager->deleteFramebuffer(mFramebufferID);
mFramebufferID = 0;
}
static void BindFramebufferAttachment(const FunctionsGL *functions,
GLenum attachmentPoint,
const FramebufferAttachment *attachment)
void BindFramebufferAttachment(const FunctionsGL *functions,
GLenum attachmentPoint,
const FramebufferAttachment *attachment)
{
if (attachment)
{
......@@ -133,6 +92,63 @@ static void BindFramebufferAttachment(const FunctionsGL *functions,
}
}
void RetrieveMultiviewFieldsFromAttachment(const gl::FramebufferAttachment *attachment,
const std::vector<gl::Offset> **viewportOffsets,
GLenum *multiviewLayout)
{
if (attachment)
{
*viewportOffsets = &attachment->getMultiviewViewportOffsets();
*multiviewLayout = attachment->getMultiviewLayout();
}
}
} // namespace
FramebufferGL::FramebufferGL(const FramebufferState &state,
const FunctionsGL *functions,
StateManagerGL *stateManager,
const WorkaroundsGL &workarounds,
BlitGL *blitter,
bool isDefault)
: FramebufferImpl(state),
mFunctions(functions),
mStateManager(stateManager),
mWorkarounds(workarounds),
mBlitter(blitter),
mFramebufferID(0),
mIsDefault(isDefault),
mAppliedEnabledDrawBuffers(1)
{
if (!mIsDefault)
{
mFunctions->genFramebuffers(1, &mFramebufferID);
}
}
FramebufferGL::FramebufferGL(GLuint id,
const FramebufferState &state,
const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
BlitGL *blitter,
StateManagerGL *stateManager)
: FramebufferImpl(state),
mFunctions(functions),
mStateManager(stateManager),
mWorkarounds(workarounds),
mBlitter(blitter),
mFramebufferID(id),
mIsDefault(true),
mAppliedEnabledDrawBuffers(1)
{
}
FramebufferGL::~FramebufferGL()
{
mStateManager->deleteFramebuffer(mFramebufferID);
mFramebufferID = 0;
}
Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
{
// glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
......@@ -467,6 +483,10 @@ void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::Dir
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
const std::vector<gl::Offset> *attachmentViewportOffsets = nullptr;
GLenum multiviewLayout = GL_NONE;
bool isAttachmentModified = false;
for (auto dirtyBit : dirtyBits)
{
switch (dirtyBit)
......@@ -474,10 +494,16 @@ void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::Dir
case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
mState.getDepthAttachment());
RetrieveMultiviewFieldsFromAttachment(mState.getDepthAttachment(),
&attachmentViewportOffsets, &multiviewLayout);
isAttachmentModified = true;
break;
case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
mState.getStencilAttachment());
RetrieveMultiviewFieldsFromAttachment(mState.getStencilAttachment(),
&attachmentViewportOffsets, &multiviewLayout);
isAttachmentModified = true;
break;
case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
{
......@@ -516,10 +542,30 @@ void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::Dir
BindFramebufferAttachment(mFunctions,
static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
mState.getColorAttachment(index));
RetrieveMultiviewFieldsFromAttachment(mState.getColorAttachment(index),
&attachmentViewportOffsets, &multiviewLayout);
isAttachmentModified = true;
break;
}
}
}
if (isAttachmentModified)
{
const bool isSideBySide = multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
mStateManager->setSideBySide(isSideBySide);
mStateManager->setScissorTestEnabled(isSideBySide ||
context->getGLState().isScissorTestEnabled());
if (attachmentViewportOffsets != nullptr)
{
mStateManager->setViewportOffsets(*attachmentViewportOffsets);
}
else
{
mStateManager->setViewportOffsets(
FramebufferAttachment::GetDefaultViewportOffsetVector());
}
}
}
GLuint FramebufferGL::getFramebufferID() const
......
......@@ -174,7 +174,7 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at
{
ASSERT(mFunctions);
nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
mStateManager = new StateManagerGL(mFunctions, getNativeCaps());
mStateManager = new StateManagerGL(mFunctions, getNativeCaps(), getNativeExtensions());
mBlitter = new BlitGL(functions, mWorkarounds, mStateManager);
bool hasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
......
......@@ -35,7 +35,9 @@ class QueryGL;
class StateManagerGL final : angle::NonCopyable
{
public:
StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps);
StateManagerGL(const FunctionsGL *functions,
const gl::Caps &rendererCaps,
const gl::Extensions &extensions);
void deleteProgram(GLuint program);
void deleteVertexArray(GLuint vao);
......@@ -74,10 +76,15 @@ class StateManagerGL final : angle::NonCopyable
void setScissorTestEnabled(bool enabled);
void setScissor(const gl::Rectangle &scissor);
void setScissorArrayv(GLuint first, const std::vector<gl::Rectangle> &viewports);
void setViewport(const gl::Rectangle &viewport);
void setViewportArrayv(GLuint first, const std::vector<gl::Rectangle> &viewports);
void setDepthRange(float near, float far);
void setViewportOffsets(const std::vector<gl::Offset> &kviewportOffsets);
void setSideBySide(bool isSideBySide);
void setBlendEnabled(bool enabled);
void setBlendColor(const gl::ColorF &blendColor);
void setBlendFuncs(GLenum sourceBlendRGB,
......@@ -180,6 +187,18 @@ class StateManagerGL final : angle::NonCopyable
void setTextureCubemapSeamlessEnabled(bool enabled);
void applyViewportOffsetsAndSetScissors(const gl::Rectangle &scissor,
const gl::Framebuffer &drawFramebuffer);
void applyViewportOffsetsAndSetViewports(const gl::Rectangle &viewport,
const gl::Framebuffer &drawFramebuffer);
enum MultiviewDirtyBitType
{
MULTIVIEW_DIRTY_BIT_SIDE_BY_SIDE_LAYOUT,
MULTIVIEW_DIRTY_BIT_VIEWPORT_OFFSETS,
MULTIVIEW_DIRTY_BIT_MAX
};
const FunctionsGL *mFunctions;
GLuint mProgram;
......@@ -244,9 +263,9 @@ class StateManagerGL final : angle::NonCopyable
GLuint mRenderbuffer;
bool mScissorTestEnabled;
gl::Rectangle mScissor;
gl::Rectangle mViewport;
std::vector<gl::Rectangle> mScissors;
std::vector<gl::Rectangle> mViewports;
std::vector<gl::Offset> mViewportOffsets;
float mNear;
float mFar;
......@@ -316,7 +335,13 @@ class StateManagerGL final : angle::NonCopyable
GLint mPathStencilRef;
GLuint mPathStencilMask;
bool mIsSideBySideDrawFramebuffer;
const bool mIsMultiviewEnabled;
gl::State::DirtyBits mLocalDirtyBits;
// ANGLE_multiview dirty bits.
angle::BitSet<MULTIVIEW_DIRTY_BIT_MAX> mMultiviewDirtyBits;
};
}
......
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