Implement dirty bits for Framebuffer.

The dirty bits set the stage for performance improvements in D3D, but
don't actually reduce any of the redundant work just yet.

BUG=angleproject:1260

Change-Id: Ib84e6a9b7aa40c37c41790f492361b22faaf4742
Reviewed-on: https://chromium-review.googlesource.com/318730
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index 5be3c16..2f89ca1 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -8,6 +8,7 @@
 
 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
 
+#include "common/BitSetIterator.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
@@ -84,10 +85,8 @@
 
 }
 
-FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data)
-    : FramebufferImpl(data),
-      mColorAttachmentsForRender(mData.getColorAttachments().size(), nullptr),
-      mInvalidateColorAttachmentCache(true)
+FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
+    : FramebufferImpl(data), mRenderer(renderer)
 {
 }
 
@@ -95,32 +94,6 @@
 {
 }
 
-void FramebufferD3D::onUpdateColorAttachment(size_t /*index*/)
-{
-    mInvalidateColorAttachmentCache = true;
-}
-
-void FramebufferD3D::onUpdateDepthAttachment()
-{
-}
-
-void FramebufferD3D::onUpdateStencilAttachment()
-{
-}
-
-void FramebufferD3D::onUpdateDepthStencilAttachment()
-{
-}
-
-void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
-{
-    mInvalidateColorAttachmentCache = true;
-}
-
-void FramebufferD3D::setReadBuffer(GLenum)
-{
-}
-
 gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
 {
     const gl::State &state = *data.state;
@@ -354,19 +327,36 @@
     return true;
 }
 
-const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(
-    const WorkaroundsD3D &workarounds) const
+void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
 {
-    if (!mInvalidateColorAttachmentCache)
+    bool invalidateColorAttachmentCache = false;
+
+    if (!mColorAttachmentsForRender.valid())
     {
-        return mColorAttachmentsForRender;
+        invalidateColorAttachmentCache = true;
+    }
+
+    for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+    {
+        if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
+             dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
+            dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
+        {
+            invalidateColorAttachmentCache = true;
+        }
+    }
+
+    if (!invalidateColorAttachmentCache)
+    {
+        return;
     }
 
     // Does not actually free memory
-    mColorAttachmentsForRender.clear();
+    gl::AttachmentList colorAttachmentsForRender;
 
     const auto &colorAttachments = mData.getColorAttachments();
     const auto &drawBufferStates = mData.getDrawBufferStates();
+    const auto &workarounds      = mRenderer->getWorkarounds();
 
     for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
     {
@@ -376,16 +366,21 @@
         if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
         {
             ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
-            mColorAttachmentsForRender.push_back(&colorAttachment);
+            colorAttachmentsForRender.push_back(&colorAttachment);
         }
         else if (!workarounds.mrtPerfWorkaround)
         {
-            mColorAttachmentsForRender.push_back(nullptr);
+            colorAttachmentsForRender.push_back(nullptr);
         }
     }
 
-    mInvalidateColorAttachmentCache = false;
-    return mColorAttachmentsForRender;
+    mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
 }
 
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
+{
+    ASSERT(mColorAttachmentsForRender.valid());
+    return mColorAttachmentsForRender.value();
 }
+
+}  // namespace rx