Bug 975772 - Cleanup RectTriangles and allow DrawQuads to take triangles or triangle strips. r=bjacob
authorAndreas Gal <gal@uci.edu>
Wed, 05 Mar 2014 14:18:38 -0500
changeset 172102 ac4f9ca4fb27e57db7b27108ab6664130da9357f
parent 172101 4ac5c87912d059a8803937f31c8447f8ecec04c8
child 172103 6cc5a05281c35d02cc198d6056dda8f259893ff5
push id26349
push userkwierso@gmail.com
push dateThu, 06 Mar 2014 02:08:58 +0000
treeherderautoland@c7d401d189e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs975772
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 975772 - Cleanup RectTriangles and allow DrawQuads to take triangles or triangle strips. r=bjacob
gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
gfx/gl/DecomposeIntoNoRepeatTriangles.h
gfx/gl/GLBlitTextureImageHelper.cpp
gfx/layers/opengl/CompositorOGL.cpp
--- a/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
+++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
@@ -6,79 +6,59 @@
 
 #include "DecomposeIntoNoRepeatTriangles.h"
 #include "gfxMatrix.h"
 
 namespace mozilla {
 namespace gl {
 
 void
+RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array,
+                                      GLfloat x0, GLfloat y0,
+                                      GLfloat x1, GLfloat y1)
+{
+    coord* v = array.AppendElements(6);
+
+    v[0].x = x0; v[0].y = y0;
+    v[1].x = x1; v[1].y = y0;
+    v[2].x = x0; v[2].y = y1;
+    v[3].x = x0; v[3].y = y1;
+    v[4].x = x1; v[4].y = y0;
+    v[5].x = x1; v[5].y = y1;
+}
+
+void
 RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
                        GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
                        bool flip_y /* = false */)
 {
-    if (vertexCoords.IsEmpty() &&
-        x0 == 0.0f && y0 == 0.0f && x1 == 1.0f && y1 == 1.0f) {
-      mIsSimpleQuad = true;
-      if (flip_y) {
-        mTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty0 - ty1, tx0, ty1));
-      } else {
-        mTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0));
-      }
-    } else if (mIsSimpleQuad) {
-      mIsSimpleQuad = false;
-      mTextureTransform = gfx3DMatrix();
+    if (flip_y) {
+        std::swap(ty0, ty1);
     }
-
-    vert_coord v;
-    v.x = x0; v.y = y0;
-    vertexCoords.AppendElement(v);
-    v.x = x1; v.y = y0;
-    vertexCoords.AppendElement(v);
-    v.x = x0; v.y = y1;
-    vertexCoords.AppendElement(v);
-
-    v.x = x0; v.y = y1;
-    vertexCoords.AppendElement(v);
-    v.x = x1; v.y = y0;
-    vertexCoords.AppendElement(v);
-    v.x = x1; v.y = y1;
-    vertexCoords.AppendElement(v);
+    AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1);
+    AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1);
+}
 
-    if (flip_y) {
-        tex_coord t;
-        t.u = tx0; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx0; t.v = ty0;
-        texCoords.AppendElement(t);
-
-        t.u = tx0; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty0;
-        texCoords.AppendElement(t);
-    } else {
-        tex_coord t;
-        t.u = tx0; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx0; t.v = ty1;
-        texCoords.AppendElement(t);
-
-        t.u = tx0; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty1;
-        texCoords.AppendElement(t);
+bool
+RectTriangles::isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const
+{
+    if (mVertexCoords.Length() == 6 &&
+        mVertexCoords[0].x == 0.0f &&
+        mVertexCoords[0].y == 0.0f &&
+        mVertexCoords[5].x == 1.0f &&
+        mVertexCoords[5].y == 1.0f)
+    {
+        GLfloat tx0 = mTexCoords[0].x;
+        GLfloat ty0 = mTexCoords[0].y;
+        GLfloat tx1 = mTexCoords[5].x;
+        GLfloat ty1 = mTexCoords[5].y;
+        aOutTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0));
+        return true;
     }
+    return false;
 }
 
 static GLfloat
 WrapTexCoord(GLfloat v)
 {
     // fmodf gives negative results for negative numbers;
     // that is, fmodf(0.75, 1.0) == 0.75, but
     // fmodf(-0.75, 1.0) == -0.75.  For the negative case,
@@ -211,9 +191,9 @@ DecomposeIntoNoRepeatTriangles(const nsI
                        1.0f, 1.0f,
                        0.0f, 0.0f,
                        br[0], br[1],
                        aFlipY);
     }
 }
 
 }
-}
\ No newline at end of file
+}
--- a/gfx/gl/DecomposeIntoNoRepeatTriangles.h
+++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.h
@@ -14,60 +14,55 @@
 
 namespace mozilla {
 namespace gl {
 
 /** Helper for DecomposeIntoNoRepeatTriangles
   */
 class RectTriangles {
 public:
-    RectTriangles() : mIsSimpleQuad(false) { }
+    typedef struct { GLfloat x,y; } coord;
 
     // Always pass texture coordinates upright. If you want to flip the
     // texture coordinates emitted to the tex_coords array, set flip_y to
     // true.
     void addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
-                  GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
-                  bool flip_y = false);
+                 GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
+                 bool flip_y = false);
 
     // Returns whether this object is made of only one rect that can be drawn
     // with a pre-buffered unity quad which has 0,0,1,1 as both vertex
     // positions and texture coordinates.
     // aOutTextureTransform returns the transform that maps 0,0,1,1 texture
     // coordinates to the correct ones.
-    bool IsSimpleQuad(gfx3DMatrix& aOutTextureTransform) const {
-      aOutTextureTransform = mTextureTransform;
-      return mIsSimpleQuad;
-    }
+    bool isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const;
 
     /**
       * these return a float pointer to the start of each array respectively.
       * Use it for glVertexAttribPointer calls.
       * We can return nullptr if we choose to use Vertex Buffer Objects here.
       */
-    float* vertexPointer() {
-        return &vertexCoords[0].x;
+    InfallibleTArray<coord>& vertCoords() {
+        return mVertexCoords;
     }
 
-    float* texCoordPointer() {
-        return &texCoords[0].u;
+    InfallibleTArray<coord>& texCoords() {
+        return mTexCoords;
     }
 
     unsigned int elements() {
-        return vertexCoords.Length();
+        return mVertexCoords.Length();
     }
-
-    typedef struct { GLfloat x,y; } vert_coord;
-    typedef struct { GLfloat u,v; } tex_coord;
 private:
-    // default is 4 rectangles, each made up of 2 triangles (3 coord vertices each)
-    nsAutoTArray<vert_coord, 6> vertexCoords;
-    nsAutoTArray<tex_coord, 6>  texCoords;
-    gfx3DMatrix mTextureTransform;
-    bool mIsSimpleQuad;
+    // Reserve inline storage for one quad (2 triangles, 3 coords).
+    nsAutoTArray<coord, 6> mVertexCoords;
+    nsAutoTArray<coord, 6> mTexCoords;
+
+    static void
+    AppendRectToCoordArray(InfallibleTArray<coord>& array, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1);
 };
 
 /**
   * Decompose drawing the possibly-wrapped aTexCoordRect rectangle
   * of a texture of aTexSize into one or more rectangles (represented
   * as 2 triangles) and associated tex coordinates, such that
   * we don't have to use the REPEAT wrap mode. If aFlipY is true, the
   * texture coordinates will be specified vertically flipped.
@@ -82,9 +77,9 @@ private:
 void DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
                                     const nsIntSize& aTexSize,
                                     RectTriangles& aRects,
                                     bool aFlipY = false);
 
 }
 }
 
-#endif // DecomposeIntoNoRepeatTriangles_h_
\ No newline at end of file
+#endif // DecomposeIntoNoRepeatTriangles_h_
--- a/gfx/gl/GLBlitTextureImageHelper.cpp
+++ b/gfx/gl/GLBlitTextureImageHelper.cpp
@@ -131,31 +131,31 @@ GLBlitTextureImageHelper::BlitTextureIma
                         srcSubRect.y / float(realTexSize.height),
                         srcSubRect.XMost() / float(realTexSize.width),
                         srcSubRect.YMost() / float(realTexSize.height));
             } else {
                 DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
 
                 // now put the coords into the d[xy]0 .. d[xy]1 coordinate space
                 // from the 0..1 that it comes out of decompose
-                RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
+                InfallibleTArray<RectTriangles::coord>& coords = rects.vertCoords();
 
-                for (unsigned int i = 0; i < rects.elements(); ++i) {
-                    v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
-                    v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
+                for (unsigned int i = 0; i < coords.Length(); ++i) {
+                    coords[i].x = (coords[i].x * (dx1 - dx0)) + dx0;
+                    coords[i].y = (coords[i].y * (dy1 - dy0)) + dy0;
                 }
             }
 
             ScopedBindTextureUnit autoTexUnit(mGL, LOCAL_GL_TEXTURE0);
             ScopedBindTexture autoTex(mGL, aSrc->GetTextureID());
 
             mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 
-            mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
-            mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
+            mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertCoords().Elements());
+            mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoords().Elements());
 
             mGL->fEnableVertexAttribArray(0);
             mGL->fEnableVertexAttribArray(1);
 
             mGL->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
 
             mGL->fDisableVertexAttribArray(0);
             mGL->fDisableVertexAttribArray(1);
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -75,63 +75,63 @@ BindMaskForProgram(ShaderProgramOGL* aPr
 }
 
 // Draw the given quads with the already selected shader. Texture coordinates
 // are supplied if the shader requires them.
 static void
 DrawQuads(GLContext *aGLContext,
           VBOArena &aVBOs,
           ShaderProgramOGL *aProg,
+          GLenum aMode,
           RectTriangles &aRects)
 {
   NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
   GLuint vertAttribIndex =
     aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
   GLuint texCoordAttribIndex =
     aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
   bool texCoords = (texCoordAttribIndex != GLuint(-1));
 
-  GLsizei elements = aRects.elements();
-  GLsizei bytes = elements * 2 * sizeof(GLfloat);
+  GLsizei bytes = aRects.elements() * 2 * sizeof(GLfloat);
 
   GLsizei total = bytes;
   if (texCoords) {
     total *= 2;
   }
 
   aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER,
                           aVBOs.Allocate(aGLContext));
   aGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER,
                           total,
                           nullptr,
                           LOCAL_GL_STREAM_DRAW);
 
   aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
                              0,
                              bytes,
-                             aRects.vertexPointer());
+                             aRects.vertCoords().Elements());
   aGLContext->fEnableVertexAttribArray(vertAttribIndex);
   aGLContext->fVertexAttribPointer(vertAttribIndex,
                                    2, LOCAL_GL_FLOAT,
                                    LOCAL_GL_FALSE,
                                    0, BUFFER_OFFSET(0));
 
   if (texCoords) {
     aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
                                bytes,
                                bytes,
-                               aRects.texCoordPointer());
+                               aRects.texCoords().Elements());
     aGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
     aGLContext->fVertexAttribPointer(texCoordAttribIndex,
                                      2, LOCAL_GL_FLOAT,
                                      LOCAL_GL_FALSE,
                                      0, BUFFER_OFFSET(bytes));
   }
 
-  aGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, elements);
+  aGLContext->fDrawArrays(aMode, 0, aRects.elements());
 
   aGLContext->fDisableVertexAttribArray(vertAttribIndex);
   if (texCoords) {
     aGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
   }
 
   aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 }
@@ -484,26 +484,26 @@ CompositorOGL::BindAndDrawQuadWithTextur
     nsIntRect tcRect(texCoordRect.x, texCoordRect.y,
                      texCoordRect.width, texCoordRect.height);
     DecomposeIntoNoRepeatTriangles(tcRect,
                                    nsIntSize(realTexSize.width, realTexSize.height),
                                    rects, flipped);
   }
 
   gfx3DMatrix textureTransform;
-  if (rects.IsSimpleQuad(textureTransform)) {
+  if (rects.isSimpleQuad(textureTransform)) {
     Matrix4x4 transform;
     ToMatrix4x4(aTextureTransform * textureTransform, transform);
     aProg->SetTextureTransform(transform);
     BindAndDrawQuad(aProg, false);
   } else {
     Matrix4x4 transform;
     ToMatrix4x4(aTextureTransform, transform);
     aProg->SetTextureTransform(transform);
-    DrawQuads(mGLContext, mVBOs, aProg, rects);
+    DrawQuads(mGLContext, mVBOs, aProg, LOCAL_GL_TRIANGLES, rects);
   }
 }
 
 void
 CompositorOGL::PrepareViewport(const gfx::IntSize& aSize,
                                const Matrix& aWorldTransform)
 {
   // Set the viewport correctly.