Bug 944172 - Move DecomposeIntoNoRepeatTriangles out of GLContext - r=BenWa
authorBenoit Jacob <bjacob@mozilla.com>
Thu, 28 Nov 2013 15:57:19 -0500
changeset 157994 f613b88f489bde3a7981de3e24c2f033d2721430
parent 157993 2ca245caad6d5bac6ca2e6f03f78ab93779b643d
child 157995 843b0a943af7de85d990d831d09788fc9fedefd4
push id36900
push userbjacob@mozilla.com
push dateThu, 28 Nov 2013 20:57:35 +0000
treeherdermozilla-inbound@129bf6f1933c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa
bugs944172
milestone28.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 944172 - Move DecomposeIntoNoRepeatTriangles out of GLContext - r=BenWa
gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
gfx/gl/DecomposeIntoNoRepeatTriangles.h
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/moz.build
gfx/layers/opengl/CompositorOGL.cpp
new file mode 100644
--- /dev/null
+++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DecomposeIntoNoRepeatTriangles.h"
+
+namespace mozilla {
+namespace gl {
+
+void
+RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
+                       GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
+                       bool flip_y /* = false */)
+{
+    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);
+
+    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);
+    }
+}
+
+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,
+    // the result we need is 0.25, so we add 1.0f.
+    if (v < 0.0f) {
+        return 1.0f + fmodf(v, 1.0f);
+    }
+
+    return fmodf(v, 1.0f);
+}
+
+void
+DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
+                               const nsIntSize& aTexSize,
+                               RectTriangles& aRects,
+                               bool aFlipY /* = false */)
+{
+    // normalize this
+    nsIntRect tcr(aTexCoordRect);
+    while (tcr.x >= aTexSize.width)
+        tcr.x -= aTexSize.width;
+    while (tcr.y >= aTexSize.height)
+        tcr.y -= aTexSize.height;
+
+    // Compute top left and bottom right tex coordinates
+    GLfloat tl[2] =
+        { GLfloat(tcr.x) / GLfloat(aTexSize.width),
+          GLfloat(tcr.y) / GLfloat(aTexSize.height) };
+    GLfloat br[2] =
+        { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width),
+          GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) };
+
+    // then check if we wrap in either the x or y axis; if we do,
+    // then also use fmod to figure out the "true" non-wrapping
+    // texture coordinates.
+
+    bool xwrap = false, ywrap = false;
+    if (tcr.x < 0 || tcr.x > aTexSize.width ||
+        tcr.XMost() < 0 || tcr.XMost() > aTexSize.width)
+    {
+        xwrap = true;
+        tl[0] = WrapTexCoord(tl[0]);
+        br[0] = WrapTexCoord(br[0]);
+    }
+
+    if (tcr.y < 0 || tcr.y > aTexSize.height ||
+        tcr.YMost() < 0 || tcr.YMost() > aTexSize.height)
+    {
+        ywrap = true;
+        tl[1] = WrapTexCoord(tl[1]);
+        br[1] = WrapTexCoord(br[1]);
+    }
+
+    NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f &&
+                 tl[1] >= 0.0f && tl[1] <= 1.0f &&
+                 br[0] >= 0.0f && br[0] <= 1.0f &&
+                 br[1] >= 0.0f && br[1] <= 1.0f,
+                 "Somehow generated invalid texture coordinates");
+
+    // If xwrap is false, the texture will be sampled from tl[0]
+    // .. br[0].  If xwrap is true, then it will be split into tl[0]
+    // .. 1.0, and 0.0 .. br[0].  Same for the Y axis.  The
+    // destination rectangle is also split appropriately, according
+    // to the calculated xmid/ymid values.
+
+    // There isn't a 1:1 mapping between tex coords and destination coords;
+    // when computing midpoints, we have to take that into account.  We
+    // need to map the texture coords, which are (in the wrap case):
+    // |tl->1| and |0->br| to the |0->1| range of the vertex coords.  So
+    // we have the length (1-tl)+(br) that needs to map into 0->1.
+    // These are only valid if there is wrap involved, they won't be used
+    // otherwise.
+    GLfloat xlen = (1.0f - tl[0]) + br[0];
+    GLfloat ylen = (1.0f - tl[1]) + br[1];
+
+    NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?");
+    NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?");
+    NS_ASSERTION(aTexCoordRect.width <= aTexSize.width &&
+                 aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!");
+
+    if (!xwrap && !ywrap) {
+        aRects.addRect(0.0f, 0.0f,
+                       1.0f, 1.0f,
+                       tl[0], tl[1],
+                       br[0], br[1],
+                       aFlipY);
+    } else if (!xwrap && ywrap) {
+        GLfloat ymid = (1.0f - tl[1]) / ylen;
+        aRects.addRect(0.0f, 0.0f,
+                       1.0f, ymid,
+                       tl[0], tl[1],
+                       br[0], 1.0f,
+                       aFlipY);
+        aRects.addRect(0.0f, ymid,
+                       1.0f, 1.0f,
+                       tl[0], 0.0f,
+                       br[0], br[1],
+                       aFlipY);
+    } else if (xwrap && !ywrap) {
+        GLfloat xmid = (1.0f - tl[0]) / xlen;
+        aRects.addRect(0.0f, 0.0f,
+                       xmid, 1.0f,
+                       tl[0], tl[1],
+                       1.0f, br[1],
+                       aFlipY);
+        aRects.addRect(xmid, 0.0f,
+                       1.0f, 1.0f,
+                       0.0f, tl[1],
+                       br[0], br[1],
+                       aFlipY);
+    } else {
+        GLfloat xmid = (1.0f - tl[0]) / xlen;
+        GLfloat ymid = (1.0f - tl[1]) / ylen;
+        aRects.addRect(0.0f, 0.0f,
+                       xmid, ymid,
+                       tl[0], tl[1],
+                       1.0f, 1.0f,
+                       aFlipY);
+        aRects.addRect(xmid, 0.0f,
+                       1.0f, ymid,
+                       0.0f, tl[1],
+                       br[0], 1.0f,
+                       aFlipY);
+        aRects.addRect(0.0f, ymid,
+                       xmid, 1.0f,
+                       tl[0], 0.0f,
+                       1.0f, br[1],
+                       aFlipY);
+        aRects.addRect(xmid, ymid,
+                       1.0f, 1.0f,
+                       0.0f, 0.0f,
+                       br[0], br[1],
+                       aFlipY);
+    }
+}
+
+}
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DecomposeIntoNoRepeatTriangles_h_
+#define DecomposeIntoNoRepeatTriangles_h_
+
+#include "GLTypes.h"
+#include "nsRect.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace gl {
+
+/** Helper for DecomposeIntoNoRepeatTriangles
+  */
+class RectTriangles {
+public:
+    RectTriangles() { }
+
+    // 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);
+
+    /**
+      * 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;
+    }
+
+    float* texCoordPointer() {
+        return &texCoords[0].u;
+    }
+
+    unsigned int elements() {
+        return vertexCoords.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;
+};
+
+/**
+  * 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.
+  *
+  * The resulting triangle vertex coordinates will be in the space of
+  * (0.0, 0.0) to (1.0, 1.0) -- transform the coordinates appropriately
+  * if you need a different space.
+  *
+  * The resulting vertex coordinates should be drawn using GL_TRIANGLES,
+  * and rects.numRects * 3 * 6
+  */
+void DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
+                                    const nsIntSize& aTexSize,
+                                    RectTriangles& aRects,
+                                    bool aFlipY = false);
+
+}
+}
+
+#endif // DecomposeIntoNoRepeatTriangles_h_
\ No newline at end of file
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2964,208 +2964,16 @@ GLContext::TexSubImage2DWithoutUnpackSub
                     format,
                     type,
                     newPixels);
     delete [] newPixels;
     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
 }
 
 void
-GLContext::RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
-                                  GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
-                                  bool flip_y /* = false */)
-{
-    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);
-
-    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);
-    }
-}
-
-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,
-    // the result we need is 0.25, so we add 1.0f.
-    if (v < 0.0f) {
-        return 1.0f + fmodf(v, 1.0f);
-    }
-
-    return fmodf(v, 1.0f);
-}
-
-void
-GLContext::DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
-                                          const nsIntSize& aTexSize,
-                                          RectTriangles& aRects,
-                                          bool aFlipY /* = false */)
-{
-    // normalize this
-    nsIntRect tcr(aTexCoordRect);
-    while (tcr.x >= aTexSize.width)
-        tcr.x -= aTexSize.width;
-    while (tcr.y >= aTexSize.height)
-        tcr.y -= aTexSize.height;
-
-    // Compute top left and bottom right tex coordinates
-    GLfloat tl[2] =
-        { GLfloat(tcr.x) / GLfloat(aTexSize.width),
-          GLfloat(tcr.y) / GLfloat(aTexSize.height) };
-    GLfloat br[2] =
-        { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width),
-          GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) };
-
-    // then check if we wrap in either the x or y axis; if we do,
-    // then also use fmod to figure out the "true" non-wrapping
-    // texture coordinates.
-
-    bool xwrap = false, ywrap = false;
-    if (tcr.x < 0 || tcr.x > aTexSize.width ||
-        tcr.XMost() < 0 || tcr.XMost() > aTexSize.width)
-    {
-        xwrap = true;
-        tl[0] = WrapTexCoord(tl[0]);
-        br[0] = WrapTexCoord(br[0]);
-    }
-
-    if (tcr.y < 0 || tcr.y > aTexSize.height ||
-        tcr.YMost() < 0 || tcr.YMost() > aTexSize.height)
-    {
-        ywrap = true;
-        tl[1] = WrapTexCoord(tl[1]);
-        br[1] = WrapTexCoord(br[1]);
-    }
-
-    NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f &&
-                 tl[1] >= 0.0f && tl[1] <= 1.0f &&
-                 br[0] >= 0.0f && br[0] <= 1.0f &&
-                 br[1] >= 0.0f && br[1] <= 1.0f,
-                 "Somehow generated invalid texture coordinates");
-
-    // If xwrap is false, the texture will be sampled from tl[0]
-    // .. br[0].  If xwrap is true, then it will be split into tl[0]
-    // .. 1.0, and 0.0 .. br[0].  Same for the Y axis.  The
-    // destination rectangle is also split appropriately, according
-    // to the calculated xmid/ymid values.
-
-    // There isn't a 1:1 mapping between tex coords and destination coords;
-    // when computing midpoints, we have to take that into account.  We
-    // need to map the texture coords, which are (in the wrap case):
-    // |tl->1| and |0->br| to the |0->1| range of the vertex coords.  So
-    // we have the length (1-tl)+(br) that needs to map into 0->1.
-    // These are only valid if there is wrap involved, they won't be used
-    // otherwise.
-    GLfloat xlen = (1.0f - tl[0]) + br[0];
-    GLfloat ylen = (1.0f - tl[1]) + br[1];
-
-    NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?");
-    NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?");
-    NS_ASSERTION(aTexCoordRect.width <= aTexSize.width &&
-                 aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!");
-
-    if (!xwrap && !ywrap) {
-        aRects.addRect(0.0f, 0.0f,
-                       1.0f, 1.0f,
-                       tl[0], tl[1],
-                       br[0], br[1],
-                       aFlipY);
-    } else if (!xwrap && ywrap) {
-        GLfloat ymid = (1.0f - tl[1]) / ylen;
-        aRects.addRect(0.0f, 0.0f,
-                       1.0f, ymid,
-                       tl[0], tl[1],
-                       br[0], 1.0f,
-                       aFlipY);
-        aRects.addRect(0.0f, ymid,
-                       1.0f, 1.0f,
-                       tl[0], 0.0f,
-                       br[0], br[1],
-                       aFlipY);
-    } else if (xwrap && !ywrap) {
-        GLfloat xmid = (1.0f - tl[0]) / xlen;
-        aRects.addRect(0.0f, 0.0f,
-                       xmid, 1.0f,
-                       tl[0], tl[1],
-                       1.0f, br[1],
-                       aFlipY);
-        aRects.addRect(xmid, 0.0f,
-                       1.0f, 1.0f,
-                       0.0f, tl[1],
-                       br[0], br[1],
-                       aFlipY);
-    } else {
-        GLfloat xmid = (1.0f - tl[0]) / xlen;
-        GLfloat ymid = (1.0f - tl[1]) / ylen;
-        aRects.addRect(0.0f, 0.0f,
-                       xmid, ymid,
-                       tl[0], tl[1],
-                       1.0f, 1.0f,
-                       aFlipY);
-        aRects.addRect(xmid, 0.0f,
-                       1.0f, ymid,
-                       0.0f, tl[1],
-                       br[0], 1.0f,
-                       aFlipY);
-        aRects.addRect(0.0f, ymid,
-                       xmid, 1.0f,
-                       tl[0], 0.0f,
-                       1.0f, br[1],
-                       aFlipY);
-        aRects.addRect(xmid, ymid,
-                       1.0f, 1.0f,
-                       0.0f, 0.0f,
-                       br[0], br[1],
-                       aFlipY);
-    }
-}
-
-void
 GLContext::UseBlitProgram()
 {
     if (mBlitProgram) {
         fUseProgram(mBlitProgram);
         return;
     }
 
     mBlitProgram = fCreateProgram();
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2917,72 +2917,16 @@ public:
 
     void TexSubImage2DWithoutUnpackSubimage(GLenum target, GLint level,
                                             GLint xoffset, GLint yoffset,
                                             GLsizei width, GLsizei height,
                                             GLsizei stride, GLint pixelsize,
                                             GLenum format, GLenum type,
                                             const GLvoid* pixels);
 
-    /** Helper for DecomposeIntoNoRepeatTriangles
-     */
-    struct RectTriangles {
-        RectTriangles() { }
-
-        // 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);
-
-        /**
-         * 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;
-        }
-
-        float* texCoordPointer() {
-            return &texCoords[0].u;
-        }
-
-        unsigned int elements() {
-            return vertexCoords.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;
-    };
-
-    /**
-     * 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.
-     *
-     * The resulting triangle vertex coordinates will be in the space of
-     * (0.0, 0.0) to (1.0, 1.0) -- transform the coordinates appropriately
-     * if you need a different space.
-     *
-     * The resulting vertex coordinates should be drawn using GL_TRIANGLES,
-     * and rects.numRects * 3 * 6
-     */
-    static void DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
-                                               const nsIntSize& aTexSize,
-                                               RectTriangles& aRects,
-                                               bool aFlipY = false);
-
 
     // Shared code for GL extensions and GLX extensions.
     static bool ListHasExtension(const GLubyte *extensions,
                                  const char *extension);
 
     GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
     void SetFlipped(bool aFlipped) { mFlipped = aFlipped; }
 
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -21,16 +21,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'an
     gl_provider = 'EGL'
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     gl_provider = 'EGL'
 
 if CONFIG['MOZ_GL_PROVIDER']:
     gl_provider = CONFIG['MOZ_GL_PROVIDER']
 
 EXPORTS += [
+    'DecomposeIntoNoRepeatTriangles.h',
     'ForceDiscreteGPUHelperCGL.h',
     'GfxTexturesReporter.h',
     'GLConsts.h',
     'GLContext.h',
     'GLContextProvider.h',
     'GLContextProviderImpl.h',
     'GLContextSymbols.h',
     'GLContextTypes.h',
@@ -97,16 +98,17 @@ elif gl_provider == 'GLX':
         'GLContextProviderGLX.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'GLContextProvider%s.cpp' % gl_provider,
     ]
 
 UNIFIED_SOURCES += [
+    'DecomposeIntoNoRepeatTriangles.cpp',
     'GfxTexturesReporter.cpp',
     'GLContext.cpp',
     'GLContextFeatures.cpp',
     'GLContextTypes.cpp',
     'GLContextUtils.cpp',
     'GLLibraryEGL.cpp',
     'GLLibraryLoader.cpp',
     'GLScreenBuffer.cpp',
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -33,16 +33,17 @@
 #include "nsAString.h"
 #include "nsIConsoleService.h"          // for nsIConsoleService, etc
 #include "nsIWidget.h"                  // for nsIWidget
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsMathUtils.h"                // for NS_roundf
 #include "nsRect.h"                     // for nsIntRect
 #include "nsServiceManagerUtils.h"      // for do_GetService
 #include "nsString.h"                   // for nsString, nsAutoCString, etc
+#include "DecomposeIntoNoRepeatTriangles.h"
 
 #if MOZ_ANDROID_OMTC
 #include "TexturePoolOGL.h"
 #endif
 #include "GeckoProfiler.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "GfxInfo.h"
@@ -63,17 +64,17 @@ static inline IntSize ns2gfxSize(const n
 }
 
 // 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,
-          GLContext::RectTriangles &aRects)
+          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));
 
@@ -133,17 +134,17 @@ static const float FontStride = 4.f;
 static const float FontScaleX = 2.f;
 static const float FontScaleY = 3.f;
 
 // Size of the font texture (POT).
 static const size_t FontTextureWidth = 64;
 static const size_t FontTextureHeight = 8;
 
 static void
-AddDigits(GLContext::RectTriangles &aRects,
+AddDigits(RectTriangles &aRects,
           const gfx::IntSize aViewportSize,
           unsigned int aOffset,
           unsigned int aValue)
 {
   unsigned int divisor = 100;
   for (size_t n = 0; n < 3; ++n) {
     gfxRect d(aOffset * FontWidth, 0.f, FontWidth, FontHeight);
     d.Scale(FontScaleX / aViewportSize.width, FontScaleY / aViewportSize.height);
@@ -199,17 +200,17 @@ FPSState::DrawFPS(TimeStamp aNow,
 
   GLint viewport[4];
   aContext->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
   gfx::IntSize viewportSize(viewport[2], viewport[3]);
 
   unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
   unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
 
-  GLContext::RectTriangles rects;
+  RectTriangles rects;
   AddDigits(rects, viewportSize, 0, fps);
   AddDigits(rects, viewportSize, 4, txnFps);
   AddDigits(rects, viewportSize, 8, aFillRatio);
 
   // Turn necessary features on
   aContext->fEnable(LOCAL_GL_BLEND);
   aContext->fBlendFunc(LOCAL_GL_ONE, LOCAL_GL_SRC_COLOR);
 
@@ -564,17 +565,17 @@ CompositorOGL::BindAndDrawQuadWithTextur
 {
   // Given what we know about these textures and coordinates, we can
   // compute fmod(t, 1.0f) to get the same texture coordinate out.  If
   // the texCoordRect dimension is < 0 or > width/height, then we have
   // wraparound that we need to deal with by drawing multiple quads,
   // because we can't rely on full non-power-of-two texture support
   // (which is required for the REPEAT wrap mode).
 
-  GLContext::RectTriangles rects;
+  RectTriangles rects;
 
   GLenum wrapMode = aTexture->AsSourceOGL()->GetWrapMode();
 
   IntSize realTexSize = aTexture->GetSize();
   if (!mGLContext->CanUploadNonPowerOfTwo()) {
     realTexSize = IntSize(NextPowerOfTwo(realTexSize.width),
                           NextPowerOfTwo(realTexSize.height));
   }
@@ -605,19 +606,19 @@ CompositorOGL::BindAndDrawQuadWithTextur
                   texCoordRect.x / GLfloat(realTexSize.width),
                   texCoordRect.y / GLfloat(realTexSize.height),
                   texCoordRect.XMost() / GLfloat(realTexSize.width),
                   texCoordRect.YMost() / GLfloat(realTexSize.height),
                   flipped);
   } else {
     nsIntRect tcRect(texCoordRect.x, texCoordRect.y,
                      texCoordRect.width, texCoordRect.height);
-    GLContext::DecomposeIntoNoRepeatTriangles(tcRect,
-                                              nsIntSize(realTexSize.width, realTexSize.height),
-                                              rects, flipped);
+    DecomposeIntoNoRepeatTriangles(tcRect,
+                                   nsIntSize(realTexSize.width, realTexSize.height),
+                                   rects, flipped);
   }
 
   DrawQuads(mGLContext, mVBOs, aProg, rects);
 }
 
 void
 CompositorOGL::PrepareViewport(const gfx::IntSize& aSize,
                                const gfxMatrix& aWorldTransform)