Bug 1345849 - Part 1: Use DrawTriangles() instead of DrawTriangle() in OpenGL compositor backend draft
authorMiko Mynttinen <mikokm@gmail.com>
Mon, 27 Mar 2017 13:59:15 -0400
changeset 551974 5cd00831c5d58cb7145bf9f89814a9b4c0a95dad
parent 551789 9577ddeaafd85554c2a855f385a87472a089d5c0
child 551975 9baf24ddf53db7c17e2aec69e837214ef5694553
push id51215
push userbmo:mikokm@gmail.com
push dateMon, 27 Mar 2017 20:25:50 +0000
bugs1345849
milestone55.0a1
Bug 1345849 - Part 1: Use DrawTriangles() instead of DrawTriangle() in OpenGL compositor backend MozReview-Commit-ID: H11vFsMlIaA
gfx/layers/Compositor.cpp
gfx/layers/Compositor.h
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
gfx/layers/opengl/OGLShaderProgram.cpp
--- a/gfx/layers/Compositor.cpp
+++ b/gfx/layers/Compositor.cpp
@@ -306,16 +306,34 @@ GenerateTexturedTriangles(const gfx::Pol
       UpdateTextureCoordinates(t, rect, intersection, texRect);
       texturedTriangles.AppendElement(Move(t));
     }
   }
 
   return texturedTriangles;
 }
 
+nsTArray<TexturedVertex>
+TexturedTrianglesToVertexArray(const nsTArray<gfx::TexturedTriangle>& aTriangles)
+{
+  const auto VertexFromPoints = [](const gfx::Point& p, const gfx::Point& t) {
+    return TexturedVertex { { p.x, p.y }, { t.x, t.y } };
+  };
+
+  nsTArray<TexturedVertex> vertices;
+
+  for (const gfx::TexturedTriangle& t : aTriangles) {
+    vertices.AppendElement(VertexFromPoints(t.p1, t.textureCoords.p1));
+    vertices.AppendElement(VertexFromPoints(t.p2, t.textureCoords.p2));
+    vertices.AppendElement(VertexFromPoints(t.p3, t.textureCoords.p3));
+  }
+
+  return vertices;
+}
+
 void
 Compositor::DrawPolygon(const gfx::Polygon& aPolygon,
                         const gfx::Rect& aRect,
                         const gfx::IntRect& aClipRect,
                         const EffectChain& aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4& aTransform,
                         const gfx::Rect& aVisibleRect)
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -644,12 +644,21 @@ BlendOpIsMixBlendMode(gfx::CompositionOp
   case gfx::CompositionOp::OP_COLOR:
   case gfx::CompositionOp::OP_LUMINOSITY:
     return true;
   default:
     return false;
   }
 }
 
+struct TexturedVertex
+{
+  float position[2];
+  float texCoords[2];
+};
+
+nsTArray<TexturedVertex>
+TexturedTrianglesToVertexArray(const nsTArray<gfx::TexturedTriangle>& aTriangles);
+
 } // namespace layers
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_COMPOSITOR_H */
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -41,22 +41,16 @@ namespace layers {
 
 static bool CanUsePartialPresents(ID3D11Device* aDevice);
 
 struct Vertex
 {
     float position[2];
 };
 
-struct TexturedVertex
-{
-    float position[2];
-    float texCoords[2];
-};
-
 // {1E4D7BEB-D8EC-4A0B-BF0A-63E6DE129425}
 static const GUID sDeviceAttachmentsD3D11 =
 { 0x1e4d7beb, 0xd8ec, 0x4a0b, { 0xbf, 0xa, 0x63, 0xe6, 0xde, 0x12, 0x94, 0x25 } };
 // {88041664-C835-4AA8-ACB8-7EC832357ED8}
 static const GUID sLayerManagerCount =
 { 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } };
 
 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 };
@@ -238,27 +232,18 @@ CompositorD3D11::UpdateDynamicVertexBuff
   D3D11_MAPPED_SUBRESOURCE resource {};
   hr = mContext->Map(mAttachments->mDynamicVertexBuffer, 0,
                      D3D11_MAP_WRITE_DISCARD, 0, &resource);
 
   if (Failed(hr, "map dynamic vertex buffer")) {
     return false;
   }
 
-  const auto vertexFromPoints = [](const gfx::Point& p, const gfx::Point& t) {
-    return TexturedVertex { { p.x, p.y }, { t.x, t.y } };
-  };
-
-  nsTArray<TexturedVertex> vertices;
-
-  for (const gfx::TexturedTriangle& t : aTriangles) {
-    vertices.AppendElement(vertexFromPoints(t.p1, t.textureCoords.p1));
-    vertices.AppendElement(vertexFromPoints(t.p2, t.textureCoords.p2));
-    vertices.AppendElement(vertexFromPoints(t.p3, t.textureCoords.p3));
-  }
+  const nsTArray<TexturedVertex> vertices =
+    TexturedTrianglesToVertexArray(aTriangles);
 
   memcpy(resource.pData, vertices.Elements(),
          vertices.Length() * sizeof(TexturedVertex));
 
   mContext->Unmap(mAttachments->mDynamicVertexBuffer, 0);
 
   return true;
 }
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -990,57 +990,59 @@ CompositorOGL::DrawQuad(const Rect& aRec
                         const EffectChain &aEffectChain,
                         Float aOpacity,
                         const gfx::Matrix4x4& aTransform,
                         const gfx::Rect& aVisibleRect)
 {
   PROFILER_LABEL("CompositorOGL", "DrawQuad",
     js::ProfileEntry::Category::GRAPHICS);
 
-  DrawGeometry(aRect, aClipRect, aEffectChain,
+  DrawGeometry(aRect, aRect, aClipRect, aEffectChain,
                aOpacity, aTransform, aVisibleRect);
 }
 
 void
-CompositorOGL::DrawTriangle(const gfx::TexturedTriangle& aTriangle,
-                            const gfx::IntRect& aClipRect,
-                            const EffectChain& aEffectChain,
-                            gfx::Float aOpacity,
-                            const gfx::Matrix4x4& aTransform,
-                            const gfx::Rect& aVisibleRect)
+CompositorOGL::DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                             const gfx::Rect& aRect,
+                             const gfx::IntRect& aClipRect,
+                             const EffectChain& aEffectChain,
+                             gfx::Float aOpacity,
+                             const gfx::Matrix4x4& aTransform,
+                             const gfx::Rect& aVisibleRect)
 {
-  PROFILER_LABEL("CompositorOGL", "DrawTriangle",
+  PROFILER_LABEL("CompositorOGL", "DrawTriangles",
     js::ProfileEntry::Category::GRAPHICS);
 
-  DrawGeometry(aTriangle, aClipRect, aEffectChain,
+  DrawGeometry(aTriangles, aRect, aClipRect, aEffectChain,
                aOpacity, aTransform, aVisibleRect);
 }
 
 template<typename Geometry>
 void
 CompositorOGL::DrawGeometry(const Geometry& aGeometry,
-                            const IntRect& aClipRect,
-                            const EffectChain &aEffectChain,
-                            Float aOpacity,
+                            const gfx::Rect& aRect,
+                            const gfx::IntRect& aClipRect,
+                            const EffectChain& aEffectChain,
+                            gfx::Float aOpacity,
                             const gfx::Matrix4x4& aTransform,
                             const gfx::Rect& aVisibleRect)
 {
   MOZ_ASSERT(mFrameInProgress, "frame not started");
   MOZ_ASSERT(mCurrentRenderTarget, "No destination");
 
   MakeCurrent();
 
   IntPoint offset = mCurrentRenderTarget->GetOrigin();
   IntSize size = mCurrentRenderTarget->GetSize();
 
   Rect renderBound(0, 0, size.width, size.height);
   renderBound.IntersectRect(renderBound, Rect(aClipRect));
   renderBound.MoveBy(offset);
 
-  Rect destRect = aTransform.TransformAndClipBounds(aGeometry, renderBound);
+  Rect destRect = aTransform.TransformAndClipBounds(aRect, renderBound);
 
   // XXX: This doesn't handle 3D transforms. It also doesn't handled rotated
   //      quads. Fix me.
   mPixelsFilled += destRect.width * destRect.height;
 
   // Do a simple culling if this rect is out of target buffer.
   // Inflate a small size to avoid some numerical imprecision issue.
   destRect.Inflate(1, 1);
@@ -1155,17 +1157,17 @@ CompositorOGL::DrawGeometry(const Geomet
     if (gl()->IsExtensionSupported(GLContext::NV_texture_barrier)) {
       // The NV_texture_barrier extension lets us read directly from the
       // backbuffer. Let's do that.
       // We need to tell OpenGL about this, so that it can make sure everything
       // on the GPU is happening in the right order.
       gl()->fTextureBarrier();
       mixBlendBackdrop = mCurrentRenderTarget->GetTextureHandle();
     } else {
-      gfx::IntRect rect = ComputeBackdropCopyRect(aGeometry, aClipRect,
+      gfx::IntRect rect = ComputeBackdropCopyRect(aRect, aClipRect,
                                                   aTransform, &backdropTransform);
       mixBlendBackdrop = CreateTexture(rect, true, mCurrentRenderTarget->GetFBO());
       createdMixBlendBackdropTexture = true;
     }
     program->SetBackdropTransform(backdropTransform);
   }
 
   program->SetRenderOffset(offset.x, offset.y);
@@ -1469,55 +1471,45 @@ CompositorOGL::DrawGeometry(const Geomet
   if (createdMixBlendBackdropTexture) {
     gl()->fDeleteTextures(1, &mixBlendBackdrop);
   }
 
   // in case rendering has used some other GL context
   MakeCurrent();
 
   LayerScope::DrawEnd(mGLContext, aEffectChain,
-                      aGeometry.width, aGeometry.height);
+                      aRect.width, aRect.height);
 }
 
 void
 CompositorOGL::BindAndDrawGeometry(ShaderProgramOGL* aProgram,
-                                   const gfx::Rect& aRect,
-                                   const gfx::Rect& aTextureRect)
+                                   const gfx::Rect& aRect)
 {
-  BindAndDrawQuad(aProgram, aRect, aTextureRect);
+  BindAndDrawQuad(aProgram, aRect);
 }
 
 void
 CompositorOGL::BindAndDrawGeometry(ShaderProgramOGL* aProgram,
-                                   const gfx::TexturedTriangle& aTriangle,
-                                   const gfx::Rect& aTextureRect)
+                                   const nsTArray<gfx::TexturedTriangle>& aTriangles)
 {
   NS_ASSERTION(aProgram->HasInitialized(), "Shader program not correctly initialized");
 
-  const gfx::TexturedTriangle& t = aTriangle;
-  const gfx::Triangle& tex = t.textureCoords;
+  const nsTArray<TexturedVertex> vertices = TexturedTrianglesToVertexArray(aTriangles);
 
-  GLfloat vertices[] = {
-    t.p1.x, t.p1.y, 0.0f, 1.0f, tex.p1.x, tex.p1.y,
-    t.p2.x, t.p2.y, 0.0f, 1.0f, tex.p2.x, tex.p2.y,
-    t.p3.x, t.p3.y, 0.0f, 1.0f, tex.p3.x, tex.p3.y
-  };
-
-  HeapCopyOfStackArray<GLfloat> verticesOnHeap(vertices);
   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTriangleVBO);
   mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER,
-                          verticesOnHeap.ByteLength(),
-                          verticesOnHeap.Data(),
+                          vertices.Length() * sizeof(TexturedVertex),
+                          vertices.Elements(),
                           LOCAL_GL_STREAM_DRAW);
 
-  const GLsizei stride = 6 * sizeof(GLfloat);
-  InitializeVAO(kCoordinateAttributeIndex, 4, stride, 0);
-  InitializeVAO(kTexCoordinateAttributeIndex, 2, stride, 4 * sizeof(GLfloat));
+  const GLsizei stride = 4 * sizeof(GLfloat);
+  InitializeVAO(kCoordinateAttributeIndex, 2, stride, 0);
+  InitializeVAO(kTexCoordinateAttributeIndex, 2, stride, 2 * sizeof(GLfloat));
 
-  mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 3);
+  mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, vertices.Length());
 
   mGLContext->fDisableVertexAttribArray(kCoordinateAttributeIndex);
   mGLContext->fDisableVertexAttribArray(kTexCoordinateAttributeIndex);
   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 }
 
 // |aRect| is the rectangle we want to draw to. We will draw it with
 // up to 4 draw commands if necessary to avoid wrapping.
@@ -1539,22 +1531,21 @@ CompositorOGL::BindAndDrawGeometryWithTe
                                             &layerRects,
                                             &textureRects);
 
   BindAndDrawQuads(aProg, rects, layerRects, textureRects);
 }
 
 void
 CompositorOGL::BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg,
-                                                  const gfx::TexturedTriangle& aTriangle,
+                                                  const nsTArray<gfx::TexturedTriangle>& aTriangles,
                                                   const gfx::Rect& aTexCoordRect,
                                                   TextureSource *aTexture)
 {
-  BindAndDrawGeometry(aProg, aTriangle,
-                      GetTextureCoordinates(aTexCoordRect, aTexture));
+  BindAndDrawGeometry(aProg, aTriangles);
 }
 
 void
 CompositorOGL::BindAndDrawQuads(ShaderProgramOGL *aProg,
                                 int aQuads,
                                 const Rect* aLayerRects,
                                 const Rect* aTextureRects)
 {
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -160,22 +160,23 @@ public:
 
   virtual void DrawQuad(const gfx::Rect& aRect,
                         const gfx::IntRect& aClipRect,
                         const EffectChain &aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4& aTransform,
                         const gfx::Rect& aVisibleRect) override;
 
-  virtual void DrawTriangle(const gfx::TexturedTriangle& aTriangle,
-                            const gfx::IntRect& aClipRect,
-                            const EffectChain& aEffectChain,
-                            gfx::Float aOpacity,
-                            const gfx::Matrix4x4& aTransform,
-                            const gfx::Rect& aVisibleRect) override;
+  virtual void DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                             const gfx::Rect& aRect,
+                             const gfx::IntRect& aClipRect,
+                             const EffectChain& aEffectChain,
+                             gfx::Float aOpacity,
+                             const gfx::Matrix4x4& aTransform,
+                             const gfx::Rect& aVisibleRect) override;
 
   virtual bool SupportsLayerGeometry() const override;
 
   virtual void EndFrame() override;
 
   virtual bool SupportsPartialTextureUpdate() override;
 
   virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override
@@ -245,18 +246,19 @@ public:
 
   const ScreenPoint& GetScreenRenderOffset() const {
     return mRenderOffset;
   }
 
 private:
   template<typename Geometry>
   void DrawGeometry(const Geometry& aGeometry,
+                    const gfx::Rect& aRect,
                     const gfx::IntRect& aClipRect,
-                    const EffectChain &aEffectChain,
+                    const EffectChain& aEffectChain,
                     gfx::Float aOpacity,
                     const gfx::Matrix4x4& aTransform,
                     const gfx::Rect& aVisibleRect);
 
   void PrepareViewport(CompositingRenderTargetOGL *aRenderTarget);
 
   /** Widget associated with this compositor */
   LayoutDeviceIntSize mWidgetSize;
@@ -331,17 +333,17 @@ private:
 
   void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig,
                             const gfx::Rect&)
   {
     aConfig.SetDynamicGeometry(false);
   }
 
   void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig,
-                            const gfx::TexturedTriangle&)
+                            const nsTArray<gfx::TexturedTriangle>&)
   {
     aConfig.SetDynamicGeometry(true);
   }
 
   /**
    * Create a FBO backed by a texture.
    * Note that the texture target type will be
    * of the type returned by FBOTextureTarget; different
@@ -377,34 +379,30 @@ private:
     gfx::Rect layerRects[4];
     gfx::Rect textureRects[4];
     layerRects[0] = aLayerRect;
     textureRects[0] = aTextureRect;
     BindAndDrawQuads(aProg, 1, layerRects, textureRects);
   }
 
   void BindAndDrawGeometry(ShaderProgramOGL* aProgram,
-                           const gfx::Rect& aRect,
-                           const gfx::Rect& aTextureRect =
-                             gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f));
+                           const gfx::Rect& aRect);
 
   void BindAndDrawGeometry(ShaderProgramOGL* aProgram,
-                           const gfx::TexturedTriangle& aTriangle,
-                           const gfx::Rect& aTextureRect =
-                             gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f));
+                           const nsTArray<gfx::TexturedTriangle>& aTriangles);
 
   void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg,
                                           const gfx::Rect& aRect,
                                           const gfx::Rect& aTexCoordRect,
                                           TextureSource *aTexture);
 
   void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg,
-                                         const gfx::TexturedTriangle& aTriangle,
-                                         const gfx::Rect& aTexCoordRect,
-                                         TextureSource *aTexture);
+                                          const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                                          const gfx::Rect& aTexCoordRect,
+                                          TextureSource *aTexture);
 
   void InitializeVAO(const GLuint aAttribIndex, const GLint aComponents,
                      const GLsizei aStride, const size_t aOffset);
 
   gfx::Rect GetTextureCoordinates(gfx::Rect textureRect,
                                   TextureSource* aTexture);
 
   /**
--- a/gfx/layers/opengl/OGLShaderProgram.cpp
+++ b/gfx/layers/opengl/OGLShaderProgram.cpp
@@ -189,17 +189,23 @@ ProgramProfileOGL::GetProfileFor(ShaderC
   vs << "uniform mat4 uLayerTransform;" << endl;
   if (aConfig.mFeatures & ENABLE_DEAA) {
     vs << "uniform mat4 uLayerTransformInverse;" << endl;
     vs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
     vs << "uniform vec2 uVisibleCenter;" << endl;
     vs << "uniform vec2 uViewportSize;" << endl;
   }
   vs << "uniform vec2 uRenderTargetOffset;" << endl;
-  vs << "attribute vec4 aCoord;" << endl;
+
+  if (!(aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY)) {
+    vs << "attribute vec4 aCoord;" << endl;
+  } else {
+    vs << "attribute vec2 aCoord;" << endl;
+  }
+
   result.mAttributes.AppendElement(Pair<nsCString, GLuint> {"aCoord", 0});
 
   if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
     vs << "uniform mat4 uTextureTransform;" << endl;
     vs << "uniform vec4 uTextureRects[4];" << endl;
     vs << "varying vec2 vTexCoord;" << endl;
 
     if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) {