Generate pixel shader output to match the bound framebuffer.

Only generate pixel shader output variables for render targets that are
currently bound.  Fixes some performance issues with D3D10 cards that were
slow to discard unused outputs.

Fixed memory leaks in ProgramBinary by refactoring the freeing of the
current state into a reset function.

BUG=angle:670

Change-Id: I40f83e15724fb9a1a9ae61363a056999f1fa26d2
Reviewed-on: https://chromium-review.googlesource.com/202977
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/ProgramBinary.h b/src/libGLESv2/ProgramBinary.h
index 839923b..88e5637 100644
--- a/src/libGLESv2/ProgramBinary.h
+++ b/src/libGLESv2/ProgramBinary.h
@@ -25,6 +25,7 @@
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Constants.h"
 #include "libGLESv2/renderer/VertexDataManager.h"
+#include "libGLESv2/DynamicHLSL.h"
 
 namespace rx
 {
@@ -32,7 +33,6 @@
 class Renderer;
 struct TranslatedAttribute;
 class UniformStorage;
-class DynamicHLSL;
 }
 
 namespace gl
@@ -42,6 +42,7 @@
 class InfoLog;
 class AttributeBindings;
 class Buffer;
+class Framebuffer;
 
 // Struct used for correlating uniforms/elements of uniform arrays to handles
 struct VariableLocation
@@ -82,7 +83,8 @@
     explicit ProgramBinary(rx::Renderer *renderer);
     ~ProgramBinary();
 
-    rx::ShaderExecutable *getPixelExecutable() const;
+    rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo);
+    rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
     rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]);
     rx::ShaderExecutable *getGeometryExecutable() const;
 
@@ -177,6 +179,8 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
 
+    void reset();
+
     bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader);
     bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
 
@@ -217,8 +221,7 @@
     class VertexExecutable
     {
       public:
-        VertexExecutable(rx::Renderer *const renderer,
-                         const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
+        VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
                          const GLenum signature[MAX_VERTEX_ATTRIBS],
                          rx::ShaderExecutable *shaderExecutable);
         ~VertexExecutable();
@@ -235,14 +238,35 @@
         rx::ShaderExecutable *mShaderExecutable;
     };
 
+    class PixelExecutable
+    {
+      public:
+        PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable);
+        ~PixelExecutable();
+
+        bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
+        const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
+        rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+
+      private:
+        std::vector<GLenum> mOutputSignature;
+        rx::ShaderExecutable *mShaderExecutable;
+    };
+
     rx::Renderer *const mRenderer;
     DynamicHLSL *mDynamicHLSL;
 
     std::string mVertexHLSL;
     rx::D3DWorkaroundType mVertexWorkarounds;
     std::vector<VertexExecutable *> mVertexExecutables;
+
+    std::string mPixelHLSL;
+    rx::D3DWorkaroundType mPixelWorkarounds;
+    bool mUsesFragDepth;
+    std::vector<PixelShaderOuputVariable> mPixelShaderKey;
+    std::vector<PixelExecutable *> mPixelExecutables;
+
     rx::ShaderExecutable *mGeometryExecutable;
-    rx::ShaderExecutable *mPixelExecutable;
 
     Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
     Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS];