Bug 739648 - add mFlags field to TextureImage; introduce GetSrcTileRect flipping tile y-coords as needed; use it in DirectUpdate() to fix WebGL compositing bug - r=bgirard
authorBenoit Jacob <bjacob@mozilla.com>
Wed, 09 May 2012 16:55:31 -0400
changeset 93625 6d551fea3297099963df21c3c816371e89a22c61
parent 93624 157bf3e3ccde0c1f02d481cc44fda4a06828e1c1
child 93626 65b5a34ffb7f432eb546e281de0c459dab4435d9
push id9236
push userbjacob@mozilla.com
push dateWed, 09 May 2012 20:56:31 +0000
treeherdermozilla-inbound@6d551fea3297 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgirard
bugs739648
milestone15.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 739648 - add mFlags field to TextureImage; introduce GetSrcTileRect flipping tile y-coords as needed; use it in DirectUpdate() to fix WebGL compositing bug - r=bgirard
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderCGL.mm
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
widget/cocoa/nsChildView.mm
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -736,33 +736,34 @@ GLContext::ListHasExtension(const GLubyt
     }
     return false;
 }
 
 already_AddRefed<TextureImage>
 GLContext::CreateTextureImage(const nsIntSize& aSize,
                               TextureImage::ContentType aContentType,
                               GLenum aWrapMode,
-                              bool aUseNearestFilter)
+                              TextureImage::Flags aFlags)
 {
+    bool useNearestFilter = aFlags & TextureImage::UseNearestFilter;
     MakeCurrent();
 
     GLuint texture;
     fGenTextures(1, &texture);
 
     fActiveTexture(LOCAL_GL_TEXTURE0);
     fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
 
-    GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
+    GLint texfilter = useNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
 
-    return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this);
+    return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this, aFlags);
 }
 
 void GLContext::ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter)
 {
     if (aFilter == gfxPattern::FILTER_NEAREST) {
         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
     } else {
@@ -935,24 +936,23 @@ BasicTextureImage::Resize(const nsIntSiz
 
     mTextureState = Allocated;
     mSize = aSize;
 }
 
 TiledTextureImage::TiledTextureImage(GLContext* aGL,
                                      nsIntSize aSize,
                                      TextureImage::ContentType aContentType,
-                                     bool aUseNearestFilter)
-    : TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aUseNearestFilter)
+                                     TextureImage::Flags aFlags)
+    : TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aFlags)
     , mCurrentImage(0)
     , mInUpdate(false)
     , mRows(0)
     , mColumns(0)
     , mGL(aGL)
-    , mUseNearestFilter(aUseNearestFilter)
     , mTextureState(Created)
     , mIterationCallback(nsnull)
 {
     mTileSize = mGL->WantsSmallTiles() ? 256 : mGL->GetMaxTextureSize();
     if (aSize != nsIntSize(0,0)) {
         Resize(aSize);
     }
 }
@@ -972,17 +972,17 @@ TiledTextureImage::DirectUpdate(gfxASurf
     } else {
         region = aRegion;
     }
 
     bool result = true;
     int oldCurrentImage = mCurrentImage;
     BeginTileIteration();
     do {
-        nsIntRect tileRect = GetTileRect();
+        nsIntRect tileRect = GetSrcTileRect();
         int xPos = tileRect.x;
         int yPos = tileRect.y;
 
         nsIntRegion tileRegion;
         tileRegion.And(region, tileRect); // intersect with tile
 
         if (tileRegion.IsEmpty())
             continue;
@@ -1184,16 +1184,25 @@ nsIntRect TiledTextureImage::GetTileRect
 {
     nsIntRect rect = mImages[mCurrentImage]->GetTileRect();
     unsigned int xPos = (mCurrentImage % mColumns) * mTileSize;
     unsigned int yPos = (mCurrentImage / mColumns) * mTileSize;
     rect.MoveBy(xPos, yPos);
     return rect;
 }
 
+nsIntRect TiledTextureImage::GetSrcTileRect()
+{
+    nsIntRect rect = GetTileRect();
+    unsigned int srcY = mFlags & NeedsYFlip
+                        ? mSize.height - rect.height - rect.y
+                        : rect.y;
+    return nsIntRect(rect.x, srcY, rect.width, rect.height);
+}
+
 void
 TiledTextureImage::BindTexture(GLenum aTextureUnit)
 {
     mImages[mCurrentImage]->BindTexture(aTextureUnit);
 }
 
 void
 TiledTextureImage::ApplyFilter()
@@ -1264,17 +1273,17 @@ void TiledTextureImage::Resize(const nsI
                     // Width hasn't changed, reuse existing tile.
                     i++;
                     continue;
                 }
             }
 
             // Create a new tile.
             nsRefPtr<TextureImage> teximg =
-                    mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
+                    mGL->TileGenFunc(size, mContentType, mFlags);
             if (replace)
                 mImages.ReplaceElementAt(i, teximg.forget());
             else
                 mImages.InsertElementAt(i, teximg.forget());
             i++;
         }
 
         // Prune any unused tiles on the end of the column.
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -123,16 +123,22 @@ class TextureImage
 public:
     enum TextureState
     {
       Created, // Texture created, but has not had glTexImage called to initialize it.
       Allocated,  // Texture memory exists, but contents are invalid.
       Valid  // Texture fully ready to use.
     };
 
+    enum Flags {
+        NoFlags          = 0x0,
+        UseNearestFilter = 0x1,
+        NeedsYFlip       = 0x2
+    };
+
     typedef gfxASurface::gfxContentType ContentType;
 
     virtual ~TextureImage() {}
 
     /**
      * Returns a gfxASurface for updating |aRegion| of the client's
      * image if successul, NULL if not.  |aRegion|'s bounds must fit
      * within Size(); its coordinate space (if any) is ignored.  If
@@ -314,28 +320,34 @@ protected:
     /**
      * After the ctor, the TextureImage is invalid.  Implementations
      * must allocate resources successfully before returning the new
      * TextureImage from GLContext::CreateTextureImage().  That is,
      * clients must not be given partially-constructed TextureImages.
      */
     TextureImage(const nsIntSize& aSize,
                  GLenum aWrapMode, ContentType aContentType,
-                 bool aIsRGB = false)
+                 Flags aFlags = NoFlags)
         : mSize(aSize)
         , mWrapMode(aWrapMode)
         , mContentType(aContentType)
         , mFilter(gfxPattern::FILTER_GOOD)
+        , mFlags(aFlags)
     {}
 
+    virtual nsIntRect GetSrcTileRect() {
+        return nsIntRect(nsIntPoint(0,0), mSize);
+    };
+
     nsIntSize mSize;
     GLenum mWrapMode;
     ContentType mContentType;
     ShaderProgramType mShaderType;
     gfxPattern::GraphicsFilter mFilter;
+    Flags mFlags;
 };
 
 /**
  * BasicTextureImage is the baseline TextureImage implementation ---
  * it updates its texture by allocating a scratch buffer for the
  * client to draw into, then using glTexSubImage2D() to upload the new
  * pixels.  Platforms must provide the code to create a new surface
  * into which the updated pixels will be drawn, and the code to
@@ -348,18 +360,19 @@ class BasicTextureImage
 public:
     typedef gfxASurface::gfxImageFormat ImageFormat;
     virtual ~BasicTextureImage();
 
     BasicTextureImage(GLuint aTexture,
                       const nsIntSize& aSize,
                       GLenum aWrapMode,
                       ContentType aContentType,
-                      GLContext* aContext)
-        : TextureImage(aSize, aWrapMode, aContentType)
+                      GLContext* aContext,
+                      TextureImage::Flags aFlags = TextureImage::NoFlags)
+        : TextureImage(aSize, aWrapMode, aContentType, aFlags)
         , mTexture(aTexture)
         , mTextureState(Created)
         , mGLContext(aContext)
         , mUpdateOffset(0, 0)
     {}
 
     virtual void BindTexture(GLenum aTextureUnit);
 
@@ -404,17 +417,17 @@ protected:
  * Aims to behave just like the real thing.
  */
 
 class TiledTextureImage
     : public TextureImage
 {
 public:
     TiledTextureImage(GLContext* aGL, nsIntSize aSize,
-        TextureImage::ContentType, bool aUseNearestFilter = false);
+        TextureImage::ContentType, TextureImage::Flags aFlags = TextureImage::NoFlags);
     ~TiledTextureImage();
     void DumpDiv();
     virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual void Resize(const nsIntSize& aSize);
     virtual PRUint32 GetTileCount();
     virtual void BeginTileIteration();
@@ -424,27 +437,29 @@ public:
     virtual nsIntRect GetTileRect();
     virtual GLuint GetTextureID() {
         return mImages[mCurrentImage]->GetTextureID();
     };
     virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
     virtual bool InUpdate() const { return mInUpdate; };
     virtual void BindTexture(GLenum);
     virtual void ApplyFilter();
+
 protected:
+    virtual nsIntRect GetSrcTileRect();
+
     unsigned int mCurrentImage;
     TileIterationCallback mIterationCallback;
     void* mIterationCallbackData;
     nsTArray< nsRefPtr<TextureImage> > mImages;
     bool mInUpdate;
     nsIntSize mSize;
     unsigned int mTileSize;
     unsigned int mRows, mColumns;
     GLContext* mGL;
-    bool mUseNearestFilter;
     // A temporary surface to faciliate cross-tile updates.
     nsRefPtr<gfxASurface> mUpdateSurface;
     // The region of update requested
     nsIntRegion mUpdateRegion;
     TextureState mTextureState;
 };
 
 struct THEBES_API ContextFormat
@@ -1377,41 +1392,42 @@ public:
 
     virtual bool RenewSurface() { return false; }
 
     /**`
      * Return a valid, allocated TextureImage of |aSize| with
      * |aContentType|.  The TextureImage's texture is configured to
      * use |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by
      * default, GL_LINEAR filtering.  Specify
-     * |aUseNearestFilter=true| for GL_NEAREST filtering.  Return
+     * |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify
+     * |aFlags=NeedsYFlip| if the image is flipped. Return
      * NULL if creating the TextureImage fails.
      *
      * The returned TextureImage may only be used with this GLContext.
      * Attempting to use the returned TextureImage after this
      * GLContext is destroyed will result in undefined (and likely
      * crashy) behavior.
      */
     virtual already_AddRefed<TextureImage>
     CreateTextureImage(const nsIntSize& aSize,
                        TextureImage::ContentType aContentType,
                        GLenum aWrapMode,
-                       bool aUseNearestFilter=false);
+                       TextureImage::Flags aFlags = TextureImage::NoFlags);
 
     /**
      * In EGL we want to use Tiled Texture Images, which we return
      * from CreateTextureImage above.
      * Inside TiledTextureImage we need to create actual images and to
      * prevent infinite recursion we need to differentiate the two
      * functions.
      **/
     virtual already_AddRefed<TextureImage>
     TileGenFunc(const nsIntSize& aSize,
                 TextureImage::ContentType aContentType,
-                bool aUseNearestFilter = false)
+                TextureImage::Flags aFlags = TextureImage::NoFlags)
     {
         return nsnull;
     };
 
     /**
      * Read the image data contained in aTexture, and return it as an ImageSurface.
      * If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.
      * Not implemented yet:
@@ -1825,20 +1841,21 @@ protected:
 
     void InitExtensions();
 
     virtual already_AddRefed<TextureImage>
     CreateBasicTextureImage(GLuint aTexture,
                             const nsIntSize& aSize,
                             GLenum aWrapMode,
                             TextureImage::ContentType aContentType,
-                            GLContext* aContext)
+                            GLContext* aContext,
+                            TextureImage::Flags aFlags = TextureImage::NoFlags)
     {
         nsRefPtr<BasicTextureImage> teximage(
-            new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext));
+            new BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags));
         return teximage.forget();
     }
 
     bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const {
         PRInt32 biggerDimension = NS_MAX(aSize.width, aSize.height);
         PRInt32 maxAllowed = NS_MIN(mMaxRenderbufferSize, mMaxTextureSize);
         return biggerDimension <= maxAllowed;
     }
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -205,17 +205,18 @@ public:
     void UnbindTex2DOffscreen(GLContext *aOffscreen);
     bool ResizeOffscreen(const gfxIntSize& aNewSize);
 
     virtual already_AddRefed<TextureImage>
     CreateBasicTextureImage(GLuint aTexture,
                             const nsIntSize& aSize,
                             GLenum aWrapMode,
                             TextureImage::ContentType aContentType,
-                            GLContext* aContext);
+                            GLContext* aContext,
+                            TextureImage::Flags aFlags = TextureImage::NoFlags);
 
     NSOpenGLContext *mContext;
     NSOpenGLPixelBuffer *mPBuffer;
     GLuint mTempTextureName;
 };
 
 bool
 GLContextCGL::BindTex2DOffscreen(GLContext *aOffscreen)
@@ -310,17 +311,18 @@ GLContextCGL::ResizeOffscreen(const gfxI
 
 class TextureImageCGL : public BasicTextureImage
 {
     friend already_AddRefed<TextureImage>
     GLContextCGL::CreateBasicTextureImage(GLuint,
                                           const nsIntSize&,
                                           GLenum,
                                           TextureImage::ContentType,
-                                          GLContext*);
+                                          GLContext*,
+                                          TextureImage::Flags);
 public:
     ~TextureImageCGL()
     {
         if (mPixelBuffer) {
             mGLContext->MakeCurrent();
             mGLContext->fDeleteBuffers(1, &mPixelBuffer);
         }
     }
@@ -396,37 +398,39 @@ protected:
         }
     }
 
 private:
     TextureImageCGL(GLuint aTexture,
                     const nsIntSize& aSize,
                     GLenum aWrapMode,
                     ContentType aContentType,
-                    GLContext* aContext)
-        : BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext)
+                    GLContext* aContext,
+                    TextureImage::Flags aFlags = TextureImage::NoFlags)
+        : BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags)
         , mPixelBuffer(0)
         , mPixelBufferSize(0)
         , mBoundPixelBuffer(false)
     {}
     
     GLuint mPixelBuffer;
     PRInt32 mPixelBufferSize;
     bool mBoundPixelBuffer;
 };
 
 already_AddRefed<TextureImage>
 GLContextCGL::CreateBasicTextureImage(GLuint aTexture,
                                       const nsIntSize& aSize,
                                       GLenum aWrapMode,
                                       TextureImage::ContentType aContentType,
-                                      GLContext* aContext)
+                                      GLContext* aContext,
+                                      TextureImage::Flags aFlags)
 {
     nsRefPtr<TextureImageCGL> teximage
-        (new TextureImageCGL(aTexture, aSize, aWrapMode, aContentType, aContext));
+        (new TextureImageCGL(aTexture, aSize, aWrapMode, aContentType, aContext, aFlags));
     return teximage.forget();
 }
 
 static GLContextCGL *
 GetGlobalContextCGL()
 {
     return static_cast<GLContextCGL*>(GLContextProviderCGL::GetGlobalContext());
 }
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -519,23 +519,23 @@ public:
             return false;
         }
     }
     // GLContext interface - returns Tiled Texture Image in our case
     virtual already_AddRefed<TextureImage>
     CreateTextureImage(const nsIntSize& aSize,
                        TextureImage::ContentType aContentType,
                        GLenum aWrapMode,
-                       bool aUseNearestFilter=false);
+                       TextureImage::Flags aFlags = TextureImage::NoFlags);
 
     // a function to generate Tiles for Tiled Texture Image
     virtual already_AddRefed<TextureImage>
     TileGenFunc(const nsIntSize& aSize,
                 TextureImage::ContentType aContentType,
-                bool aUseNearestFilter = false);
+                TextureImage::Flags aFlags = TextureImage::NoFlags);
     // hold a reference to the given surface
     // for the lifetime of this context.
     void HoldSurface(gfxASurface *aSurf) {
         mThebesSurface = aSurf;
     }
 
     void SetPlatformContext(void *context) {
         mPlatformContext = context;
@@ -794,18 +794,19 @@ GLTypeForImage(gfxASurface::gfxImageForm
 class TextureImageEGL
     : public TextureImage
 {
 public:
     TextureImageEGL(GLuint aTexture,
                     const nsIntSize& aSize,
                     GLenum aWrapMode,
                     ContentType aContentType,
-                    GLContext* aContext)
-        : TextureImage(aSize, aWrapMode, aContentType)
+                    GLContext* aContext,
+                    TextureImage::Flags aFlags = TextureImage::NoFlags)
+        : TextureImage(aSize, aWrapMode, aContentType, aFlags)
         , mGLContext(aContext)
         , mUpdateFormat(gfxASurface::ImageFormatUnknown)
         , mSurface(nsnull)
         , mConfig(nsnull)
         , mTexture(aTexture)
         , mImageKHR(nsnull)
         , mTextureState(Created)
         , mBound(false)
@@ -1288,39 +1289,39 @@ protected:
         mGLContext->ApplyFilterToBoundTexture(mFilter);
     }
 };
 
 already_AddRefed<TextureImage>
 GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
                                  GLenum aWrapMode,
-                                 bool aUseNearestFilter)
+                                 TextureImage::Flags aFlags)
 {
-    nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aUseNearestFilter);
+    nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aFlags);
     return t.forget();
 }
 
 already_AddRefed<TextureImage>
 GLContextEGL::TileGenFunc(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
-                                 bool aUseNearestFilter)
+                                 TextureImage::Flags aFlags)
 {
   MakeCurrent();
 
   GLuint texture;
   fGenTextures(1, &texture);
 
   fActiveTexture(LOCAL_GL_TEXTURE0);
   fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
 
   nsRefPtr<TextureImageEGL> teximage =
-      new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, this);
+      new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, this, aFlags);
 
-  GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
+  GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
 
   return teximage.forget();
 }
 
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -844,17 +844,17 @@ TRY_AGAIN_NO_SHARING:
     {
         return sGLXLibrary.UseTextureFromPixmap();
     }
 
     virtual already_AddRefed<TextureImage>
     CreateTextureImage(const nsIntSize& aSize,
                        TextureImage::ContentType aContentType,
                        GLenum aWrapMode,
-                       bool aUseNearestFilter = false);
+                       TextureImage::Flags aFlags = TextureImage::NoFlags);
 
 private:
     friend class GLContextProviderGLX;
 
     GLContextGLX(const ContextFormat& aFormat,
                  GLContext *aShareContext,
                  Display *aDisplay,
                  GLXDrawable aDrawable,
@@ -881,17 +881,17 @@ private:
 };
 
 class TextureImageGLX : public TextureImage
 {
     friend already_AddRefed<TextureImage>
     GLContextGLX::CreateTextureImage(const nsIntSize&,
                                      ContentType,
                                      GLenum,
-                                     bool);
+                                     TextureImage::Flags);
 
 public:
     virtual ~TextureImageGLX()
     {
         mGLContext->MakeCurrent();
         mGLContext->fDeleteTextures(1, &mTexture);
         sGLXLibrary.DestroyPixmap(mPixmap);
     }
@@ -945,18 +945,19 @@ public:
 
 private:
    TextureImageGLX(GLuint aTexture,
                    const nsIntSize& aSize,
                    GLenum aWrapMode,
                    ContentType aContentType,
                    GLContext* aContext,
                    gfxASurface* aSurface,
-                   GLXPixmap aPixmap)
-        : TextureImage(aSize, aWrapMode, aContentType)
+                   GLXPixmap aPixmap,
+                   TextureImage::Flags aFlags = TextureImage::NoFlags)
+        : TextureImage(aSize, aWrapMode, aContentType, aFlags)
         , mGLContext(aContext)
         , mUpdateSurface(aSurface)
         , mPixmap(aPixmap)
         , mInUpdate(false)
         , mTexture(aTexture)
     {
         if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
             mShaderType = gl::RGBALayerProgramType;
@@ -976,23 +977,23 @@ private:
         mGLContext->ApplyFilterToBoundTexture(mFilter);
     }
 };
 
 already_AddRefed<TextureImage>
 GLContextGLX::CreateTextureImage(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
                                  GLenum aWrapMode,
-                                 bool aUseNearestFilter)
+                                 TextureImage::Flags aFlags)
 {
     if (!TextureImageSupportsGetBackingSurface()) {
         return GLContext::CreateTextureImage(aSize, 
                                              aContentType, 
                                              aWrapMode, 
-                                             aUseNearestFilter);
+                                             aFlags);
     }
 
     Display *display = DefaultXDisplay();
     int xscreen = DefaultScreen(display);
     gfxASurface::gfxImageFormat imageFormat = gfxASurface::FormatFromContent(aContentType);
 
     XRenderPictFormat* xrenderFormat =
         gfxXlibSurface::FindRenderFormat(display, imageFormat);
@@ -1017,19 +1018,19 @@ GLContextGLX::CreateTextureImage(const n
 
     GLuint texture;
     fGenTextures(1, &texture);
 
     fActiveTexture(LOCAL_GL_TEXTURE0);
     fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
 
     nsRefPtr<TextureImageGLX> teximage =
-        new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap);
+        new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap, aFlags);
 
-    GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
+    GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
 
     return teximage.forget();
 }
 
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -334,20 +334,22 @@ ShadowCanvasLayerOGL::Initialize(const D
   NS_RUNTIMEABORT("Incompatibe surface type");
 }
 
 void
 ShadowCanvasLayerOGL::Init(const CanvasSurface& aNewFront, bool needYFlip)
 {
   nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
 
+  mNeedsYFlip = needYFlip;
+
   mTexImage = gl()->CreateTextureImage(surf->GetSize(),
                                        surf->GetContentType(),
-                                       LOCAL_GL_CLAMP_TO_EDGE);
-  mNeedsYFlip = needYFlip;
+                                       LOCAL_GL_CLAMP_TO_EDGE,
+                                       mNeedsYFlip ? TextureImage::NeedsYFlip : TextureImage::NoFlags);
 }
 
 void
 ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
                            bool needYFlip,
                            CanvasSurface* aNewBack)
 {
   if (!mDestroyed) {
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1840,17 +1840,17 @@ nsChildView::DrawWindowOverlay(LayerMana
   if (!manager) {
     return;
   }
 
   if (!mResizerImage) {
     mResizerImage = manager->gl()->CreateTextureImage(nsIntSize(15, 15),
                                                       gfxASurface::CONTENT_COLOR_ALPHA,
                                                       LOCAL_GL_CLAMP_TO_EDGE,
-                                                      /* aUseNearestFilter = */ true);
+                                                      TextureImage::UseNearestFilter);
 
     // Creation of texture images can fail.
     if (!mResizerImage)
       return;
 
     nsIntRegion update(nsIntRect(0, 0, 15, 15));
     gfxASurface *asurf = mResizerImage->BeginUpdate(update);
     if (!asurf) {