Bug 739679 - Part 4: TiledLayerBufferOGL. r=mwoodrow,roc
authorBenoit Girard <b56girard@gmail.com>
Mon, 16 Apr 2012 19:04:24 -0400
changeset 92203 a8f489c62eb06e32c7ae90918cbfd7477664ed29
parent 92202 6aac1347aa358aba72753df5d366d84e87505cc8
child 92204 baffceac44f944700133e2e3cf72bb2eb6dcbaf2
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmwoodrow, roc
bugs739679
milestone14.0a1
Bug 739679 - Part 4: TiledLayerBufferOGL. r=mwoodrow,roc
gfx/layers/Makefile.in
gfx/layers/basic/BasicTiledThebesLayer.cpp
gfx/layers/basic/BasicTiledThebesLayer.h
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/layers/opengl/TiledThebesLayerOGL.cpp
gfx/layers/opengl/TiledThebesLayerOGL.h
gfx/thebes/gfxReusableSurfaceWrapper.cpp
gfx/thebes/gfxReusableSurfaceWrapper.h
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -56,16 +56,18 @@ FORCE_STATIC_LIB = 1
 
 DEFINES += -DIMPL_THEBES
 ifdef MOZ_DEBUG
 DEFINES += -DD3D_DEBUG_INFO
 endif
 
 EXPORTS = \
         BasicLayers.h \
+        BasicTiledThebesLayer.h \
+        BasicImplData.h \
         ImageLayers.h \
         Layers.h \
         LayerManagerOGL.h \
         LayerManagerOGLProgram.h \
         ReadbackLayer.h \
         LayerSorter.h \
         $(NULL)
 
@@ -78,16 +80,17 @@ CPPSRCS = \
         ReadbackProcessor.cpp \
         ThebesLayerBuffer.cpp \
         CanvasLayerOGL.cpp \
         ColorLayerOGL.cpp \
         ContainerLayerOGL.cpp \
         ImageLayerOGL.cpp \
         LayerManagerOGL.cpp \
         ThebesLayerOGL.cpp \
+        TiledThebesLayerOGL.cpp \
         LayerSorter.cpp \
         ImageLayers.cpp \
         $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 ifdef MOZ_ENABLE_D3D9_LAYER
 EXPORTS += \
         LayerManagerD3D9.h \
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -49,16 +49,26 @@ static void DrawDebugOverlay(gfxImageSur
 
 }
 
 #endif
 
 namespace mozilla {
 namespace layers {
 
+gfxASurface::gfxImageFormat
+BasicTiledLayerBuffer::GetFormat() const
+{
+  if (mThebesLayer->CanUseOpaqueSurface()) {
+    return gfxASurface::ImageFormatRGB16_565;
+  } else {
+    return gfxASurface::ImageFormatARGB32;
+  }
+}
+
 void
 BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
                                    const nsIntRegion& aNewValidRegion,
                                    const nsIntRegion& aPaintRegion,
                                    LayerManager::DrawThebesLayerCallback aCallback,
                                    void* aCallbackData)
 {
   mThebesLayer = aLayer;
@@ -66,17 +76,17 @@ BasicTiledLayerBuffer::PaintThebes(Basic
   mCallbackData = aCallbackData;
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   long start = PR_IntervalNow();
 #endif
   if (UseSinglePaintBuffer()) {
     SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBuffer");
     const nsIntRect bounds = aPaintRegion.GetBounds();
-    mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ImageFormatRGB16_565);
+    mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), GetFormat());
     mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
     nsRefPtr<gfxContext> ctxt = new gfxContext(mSinglePaintBuffer);
     ctxt->NewPath();
     ctxt->Translate(gfxPoint(-bounds.x, -bounds.y));
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
     if (PR_IntervalNow() - start > 3) {
       printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
     }
@@ -117,36 +127,39 @@ BasicTiledLayerBuffer::PaintThebes(Basic
 }
 
 BasicTiledLayerTile
 BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
                                             const nsIntPoint& aTileOrigin,
                                             const nsIntRect& aDirtyRect)
 {
   if (aTile == GetPlaceholderTile()) {
-    gfxImageSurface* tmpTile = new gfxImageSurface(gfxIntSize(GetTileLength(), GetTileLength()), gfxASurface::ImageFormatRGB16_565);
+    gfxImageSurface* tmpTile = new gfxImageSurface(gfxIntSize(GetTileLength(), GetTileLength()),
+                                                   GetFormat());
     aTile = BasicTiledLayerTile(tmpTile);
   }
 
   gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
                    aDirtyRect.width, aDirtyRect.height);
 
   // Use the gfxReusableSurfaceWrapper, which will reuse the surface
   // if the compositor no longer has a read lock, otherwise the surface
   // will be copied into a new writable surface.
   gfxImageSurface* writableSurface;
   aTile.mSurface = aTile.mSurface->GetWritable(&writableSurface);
 
   // Bug 742100, this gfxContext really should live on the stack.
   nsRefPtr<gfxContext> ctxt = new gfxContext(writableSurface);
-  ctxt->NewPath();
-  ctxt->SetOperator(gfxContext::OPERATOR_CLEAR);
-  ctxt->Rectangle(drawRect, true);
-  ctxt->Fill();
-  ctxt->SetOperator(gfxContext::OPERATOR_OVER);
+ if (!mThebesLayer->CanUseOpaqueSurface()) {
+    ctxt->NewPath();
+    ctxt->SetOperator(gfxContext::OPERATOR_CLEAR);
+    ctxt->Rectangle(drawRect, true);
+    ctxt->Fill();
+    ctxt->SetOperator(gfxContext::OPERATOR_OVER);
+  }
   if (mSinglePaintBuffer) {
     ctxt->NewPath();
     ctxt->SetSource(mSinglePaintBuffer.get(),
                     gfxPoint(mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x,
                              mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y));
     ctxt->Rectangle(drawRect, true);
     ctxt->Fill();
   } else {
--- a/gfx/layers/basic/BasicTiledThebesLayer.h
+++ b/gfx/layers/basic/BasicTiledThebesLayer.h
@@ -116,16 +116,17 @@ protected:
 
   void ReleaseTile(BasicTiledLayerTile aTile) { /* No-op. */ }
 
   void SwapTiles(BasicTiledLayerTile& aTileA, BasicTiledLayerTile& aTileB) {
     std::swap(aTileA, aTileB);
   }
 
 private:
+  gfxASurface::gfxImageFormat GetFormat() const;
   BasicTiledThebesLayer* mThebesLayer;
   LayerManager::DrawThebesLayerCallback mCallback;
   void* mCallbackData;
 
   // The buffer we use when UseSinglePaintBuffer() above is true.
   nsRefPtr<gfxImageSurface>     mSinglePaintBuffer;
   nsIntPoint                    mSinglePaintBufferOffset;
 
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -43,16 +43,17 @@
 #include "mozilla/Util.h"
 
 #include "LayerManagerOGL.h"
 #include "ThebesLayerOGL.h"
 #include "ContainerLayerOGL.h"
 #include "ImageLayerOGL.h"
 #include "ColorLayerOGL.h"
 #include "CanvasLayerOGL.h"
+#include "TiledThebesLayerOGL.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Preferences.h"
 
 #include "LayerManagerOGLShaders.h"
 
 #include "gfxContext.h"
 #include "gfxUtils.h"
 #include "gfxPlatform.h"
@@ -1259,17 +1260,21 @@ LayerManagerOGL::CreateFBOWithTexture(co
 
 already_AddRefed<ShadowThebesLayer>
 LayerManagerOGL::CreateShadowThebesLayer()
 {
   if (LayerManagerOGL::mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return nsnull;
   }
+#ifdef FORCE_BASICTILEDTHEBESLAYER
+  return nsRefPtr<ShadowThebesLayer>(new TiledThebesLayerOGL(this)).forget();
+#else
   return nsRefPtr<ShadowThebesLayerOGL>(new ShadowThebesLayerOGL(this)).forget();
+#endif
 }
 
 already_AddRefed<ShadowContainerLayer>
 LayerManagerOGL::CreateShadowContainerLayer()
 {
   if (LayerManagerOGL::mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return nsnull;
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -32,16 +32,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/layers/PLayers.h"
+#include "TiledLayerBuffer.h"
 
 /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
 #include "mozilla/Util.h"
 
 #include "mozilla/layers/ShadowLayers.h"
 
 #include "ThebesLayerBuffer.h"
 #include "ThebesLayerOGL.h"
@@ -981,16 +982,19 @@ ShadowBufferOGL::Upload(gfxASurface* aUp
   mBufferRotation = aRotation;
 }
 
 ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
   : ShadowThebesLayer(aManager, nsnull)
   , LayerOGL(aManager)
   , mUploadTask(nsnull)
 {
+#ifdef FORCE_BASICTILEDTHEBESLAYER
+  NS_ABORT();
+#endif
   mImplData = static_cast<LayerOGL*>(this);
 }
 
 ShadowThebesLayerOGL::~ShadowThebesLayerOGL()
 {}
 
 bool
 ShadowThebesLayerOGL::ShouldDoubleBuffer()
new file mode 100644
--- /dev/null
+++ b/gfx/layers/opengl/TiledThebesLayerOGL.cpp
@@ -0,0 +1,197 @@
+/* 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 "mozilla/layers/PLayersChild.h"
+#include "TiledThebesLayerOGL.h"
+#include "BasicTiledThebesLayer.h"
+#include "gfxImageSurface.h"
+
+namespace mozilla {
+namespace layers {
+
+using mozilla::gl::GLContext;
+
+TiledLayerBufferOGL::~TiledLayerBufferOGL()
+{
+  if (mRetainedTiles.Length() == 0)
+    return;
+
+  mContext->MakeCurrent();
+  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
+    if (mRetainedTiles[i] == GetPlaceholderTile())
+      continue;
+    mContext->fDeleteTextures(1, &mRetainedTiles[i].mTextureHandle);
+  }
+}
+
+void
+TiledLayerBufferOGL::ReleaseTile(TiledTexture aTile)
+{
+  // We've made current prior to calling TiledLayerBufferOGL::Update
+  if (aTile == GetPlaceholderTile())
+    return;
+  mContext->fDeleteTextures(1, &aTile.mTextureHandle);
+}
+
+void
+TiledLayerBufferOGL::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
+                            const nsIntRegion& aNewValidRegion,
+                            const nsIntRegion& aInvalidateRegion)
+{
+#ifdef GFX_TILEDLAYER_PREF_WARNINGS
+  printf_stderr("Upload %i, %i, %i, %i\n", aInvalidateRegion.GetBounds().x, aInvalidateRegion.GetBounds().y, aInvalidateRegion.GetBounds().width, aInvalidateRegion.GetBounds().height);
+  long start = PR_IntervalNow();
+#endif
+  mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
+  mContext->MakeCurrent();
+  Update(aNewValidRegion, aInvalidateRegion);
+  mMainMemoryTiledBuffer = nsnull;
+#ifdef GFX_TILEDLAYER_PREF_WARNINGS
+  if (PR_IntervalNow() - start > 10) {
+    printf_stderr("Time to upload %i\n", PR_IntervalNow() - start);
+  }
+#endif
+}
+
+void
+TiledLayerBufferOGL::GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
+                                                    GLenum& aOutFormat,
+                                                    GLenum& aOutType)
+{
+  if (aFormat == gfxASurface::ImageFormatRGB16_565) {
+    aOutFormat = LOCAL_GL_RGB;
+    aOutType = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
+  } else {
+    aOutFormat = LOCAL_GL_RGBA;
+    aOutType = LOCAL_GL_UNSIGNED_BYTE;
+  }
+}
+
+TiledTexture
+TiledLayerBufferOGL::ValidateTile(TiledTexture aTile,
+                                  const nsIntPoint& aTileOrigin,
+                                  const nsIntRegion& aDirtyRect)
+{
+#ifdef GFX_TILEDLAYER_PREF_WARNINGS
+  printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y);
+  long start = PR_IntervalNow();
+#endif
+  if (aTile == GetPlaceholderTile()) {
+    mContext->fGenTextures(1, &aTile.mTextureHandle);
+    mContext->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
+    mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+    mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+    mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
+    mContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
+  } else {
+    mContext->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
+  }
+
+  nsRefPtr<gfxReusableSurfaceWrapper> reusableSurface = mMainMemoryTiledBuffer->GetTile(aTileOrigin).mSurface.get();
+  GLenum format, type;
+  GetFormatAndTileForImageFormat(reusableSurface->Format(), format, type);
+
+  const unsigned char* buf = reusableSurface->GetReadOnlyData();
+  mContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format,
+                       GetTileLength(), GetTileLength(), 0,
+                       format, type, buf);
+
+  aTile.mFormat = format;
+
+#ifdef GFX_TILEDLAYER_PREF_WARNINGS
+  if (PR_IntervalNow() - start > 1) {
+    printf_stderr("Tile Time to upload %i\n", PR_IntervalNow() - start);
+  }
+#endif
+  return aTile;
+}
+
+TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
+  : ShadowThebesLayer(aManager, nsnull)
+  , LayerOGL(aManager)
+  , mVideoMemoryTiledBuffer(aManager->gl())
+{
+  mImplData = static_cast<LayerOGL*>(this);
+}
+
+void
+TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
+{
+  mMainMemoryTiledBuffer = *mTiledBuffer;
+  mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetLastPaintRegion());
+
+  gl()->MakeCurrent();
+
+  ProcessUploadQueue(); // TODO: Remove me; this should be unnecessary.
+}
+
+void
+TiledThebesLayerOGL::ProcessUploadQueue()
+{
+  if (mRegionToUpload.IsEmpty())
+    return;
+
+  mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer, mMainMemoryTiledBuffer.GetValidRegion(), mRegionToUpload);
+  mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
+
+  mMainMemoryTiledBuffer.ReadUnlock();
+  mRegionToUpload = nsIntRegion();
+
+}
+
+void
+TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
+{
+  gl()->MakeCurrent();
+  ProcessUploadQueue();
+
+  const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
+  const nsIntRect visibleRect = visibleRegion.GetBounds();
+  unsigned int rowCount = 0;
+  int tileX = 0;
+  for (size_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
+    rowCount++;
+    uint16_t tileStartX = x % mVideoMemoryTiledBuffer.GetTileLength();
+    uint16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
+    if (x + w > visibleRect.x + visibleRect.width)
+      w = visibleRect.x + visibleRect.width - x;
+    int tileY = 0;
+    for( size_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
+      uint16_t tileStartY = y % mVideoMemoryTiledBuffer.GetTileLength();
+      uint16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
+      if (y + h > visibleRect.y + visibleRect.height)
+        h = visibleRect.y + visibleRect.height - y;
+
+      TiledTexture tileTexture = mVideoMemoryTiledBuffer.
+        GetTile(nsIntPoint(mVideoMemoryTiledBuffer.RoundDownToTileEdge(x),
+                           mVideoMemoryTiledBuffer.RoundDownToTileEdge(y)));
+      if (tileTexture != mVideoMemoryTiledBuffer.GetPlaceholderTile()) {
+
+        gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, tileTexture.mTextureHandle);
+        ColorTextureLayerProgram *program;
+        if (tileTexture.mFormat == LOCAL_GL_RGB) {
+          program = mOGLManager->GetRGBXLayerProgram();
+        } else {
+          program = mOGLManager->GetBGRALayerProgram();
+        }
+        program->Activate();
+        program->SetTextureUnit(0);
+        program->SetLayerOpacity(GetEffectiveOpacity());
+        program->SetLayerTransform(GetEffectiveTransform());
+        program->SetRenderOffset(aOffset);
+        program->SetLayerQuadRect(nsIntRect(x,y,w,h)); // screen
+        mOGLManager->BindAndDrawQuadWithTextureRect(program, nsIntRect(tileStartX, tileStartY, w, h), nsIntSize(mVideoMemoryTiledBuffer.GetTileLength(), mVideoMemoryTiledBuffer.GetTileLength())); // texture bounds
+
+      }
+      tileY++;
+      y += h;
+    }
+    tileX++;
+    x += w;
+  }
+
+}
+
+} // mozilla
+} // layers
new file mode 100644
--- /dev/null
+++ b/gfx/layers/opengl/TiledThebesLayerOGL.h
@@ -0,0 +1,138 @@
+/* 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 GFX_TILEDTHEBESLAYEROGL_H
+#define GFX_TILEDTHEBESLAYEROGL_H
+
+#include "mozilla/layers/ShadowLayers.h"
+#include "TiledLayerBuffer.h"
+#include "Layers.h"
+#include "LayerManagerOGL.h"
+#include "BasicTiledThebesLayer.h"
+#include <algorithm>
+
+namespace mozilla {
+
+namespace gl {
+class GLContext;
+}
+
+namespace layers {
+
+class TiledTexture {
+public:
+  // Constructs a placeholder TiledTexture. See the comments above
+  // TiledLayerBuffer for more information on what this is used for;
+  // essentially, this is a sentinel used to represent an invalid or blank
+  // tile.
+  //
+  // Note that we assume that zero is not a valid GL texture handle here.
+  TiledTexture()
+    : mTextureHandle(0)
+    , mFormat(0)
+  {}
+
+  // Constructs a TiledTexture from a GL texture handle and an image format.
+  TiledTexture(GLuint aTextureHandle, GLenum aFormat)
+    : mTextureHandle(aTextureHandle)
+    , mFormat(aFormat)
+  {}
+
+  TiledTexture(const TiledTexture& o) {
+    mTextureHandle = o.mTextureHandle;
+    mFormat = o.mFormat;
+  }
+  TiledTexture& operator=(const TiledTexture& o) {
+    if (this == &o) return *this;
+    mTextureHandle = o.mTextureHandle;
+    mFormat = o.mFormat;
+    return *this;
+  }
+  bool operator== (const TiledTexture& o) const {
+    return mTextureHandle == o.mTextureHandle;
+  }
+  bool operator!= (const TiledTexture& o) const {
+    return mTextureHandle != o.mTextureHandle;
+  }
+
+  GLuint mTextureHandle;
+  GLenum mFormat;
+};
+
+class TiledLayerBufferOGL : public TiledLayerBuffer<TiledLayerBufferOGL, TiledTexture>
+{
+  friend class TiledLayerBuffer<TiledLayerBufferOGL, TiledTexture>;
+
+public:
+  TiledLayerBufferOGL(gl::GLContext* aContext)
+    : mContext(aContext)
+  {}
+
+  ~TiledLayerBufferOGL();
+
+  void Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
+              const nsIntRegion& aNewValidRegion,
+              const nsIntRegion& aInvalidateRegion);
+
+  TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
+
+protected:
+  TiledTexture ValidateTile(TiledTexture aTile,
+                            const nsIntPoint& aTileRect,
+                            const nsIntRegion& dirtyRect);
+
+  void ReleaseTile(TiledTexture aTile);
+
+  void SwapTiles(TiledTexture& aTileA, TiledTexture& aTileB) {
+    std::swap(aTileA, aTileB);
+  }
+
+private:
+  nsRefPtr<gl::GLContext> mContext;
+  const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
+
+  void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
+                                      GLenum& aOutFormat,
+                                      GLenum& aOutType);
+};
+
+class TiledThebesLayerOGL : public ShadowThebesLayer,
+                            public LayerOGL,
+                            public TiledLayerComposer
+{
+public:
+  TiledThebesLayerOGL(LayerManagerOGL *aManager);
+  virtual ~TiledThebesLayerOGL()
+  {
+    mMainMemoryTiledBuffer.ReadUnlock();
+  }
+
+  // LayerOGL impl
+  void Destroy() {}
+  Layer* GetLayer() { return this; }
+  virtual void RenderLayer(int aPreviousFrameBuffer,
+                           const nsIntPoint& aOffset);
+  virtual void CleanupResources() { }
+
+  // Shadow
+  virtual TiledLayerComposer* AsTiledLayerComposer() { return this; }
+  virtual void DestroyFrontBuffer() {}
+  void Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
+       OptionalThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
+       OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion)
+  {
+    NS_ABORT_IF_FALSE(false, "Not supported");
+  }
+  void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
+  void ProcessUploadQueue();
+private:
+  nsIntRegion                  mRegionToUpload;
+  BasicTiledLayerBuffer        mMainMemoryTiledBuffer;
+  TiledLayerBufferOGL          mVideoMemoryTiledBuffer;
+};
+
+} // layers
+} // mozilla
+
+#endif
--- a/gfx/thebes/gfxReusableSurfaceWrapper.cpp
+++ b/gfx/thebes/gfxReusableSurfaceWrapper.cpp
@@ -4,16 +4,17 @@
 
 #include "gfxReusableSurfaceWrapper.h"
 #include "gfxImageSurface.h"
 #include "pratom.h"
 
 gfxReusableSurfaceWrapper::gfxReusableSurfaceWrapper(gfxImageSurface* aSurface)
   : mSurface(aSurface)
   , mSurfaceData(aSurface->Data())
+  , mFormat(aSurface->Format())
   , mReadCount(0)
 {
   MOZ_COUNT_CTOR(gfxReusableSurfaceWrapper);
 }
 
 gfxReusableSurfaceWrapper::~gfxReusableSurfaceWrapper()
 {
   NS_ABORT_IF_FALSE(mReadCount == 0, "Should not be locked when released");
--- a/gfx/thebes/gfxReusableSurfaceWrapper.h
+++ b/gfx/thebes/gfxReusableSurfaceWrapper.h
@@ -1,15 +1,16 @@
 /* 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 GFXCOWSURFACEWRAPPER
 #define GFXCOWSURFACEWRAPPER
 
+#include "gfxASurface.h"
 #include "nsISupportsImpl.h"
 #include "nsAutoPtr.h"
 
 class gfxImageSurface;
 
 /**
  * Provides a cross thread wrapper for a gfxImageSurface
  * that has copy-on-write schemantics.
@@ -38,16 +39,18 @@ public:
 
   ~gfxReusableSurfaceWrapper();
 
   const unsigned char* GetReadOnlyData() const {
     NS_ABORT_IF_FALSE(mReadCount > 0, "Should have read lock");
     return mSurfaceData;
   }
 
+  const gfxASurface::gfxImageFormat& Format() { return mFormat; }
+
   /**
    * Get a writable copy of the image.
    * If necessary this will copy the wrapper. If there are no contention
    * the same wrapper will be returned.
    */
   gfxReusableSurfaceWrapper* GetWritable(gfxImageSurface** aSurface);
 
   /**
@@ -55,14 +58,15 @@ public:
    * call GetWritable() while this count is positive will
    * create a new surface/wrapper pair.
    */
   void ReadLock();
   void ReadUnlock();
 
 private:
   NS_DECL_OWNINGTHREAD
-  nsRefPtr<gfxImageSurface>   mSurface;
-  const unsigned char*        mSurfaceData;
-  PRInt32                     mReadCount;
+  nsRefPtr<gfxImageSurface>         mSurface;
+  const gfxASurface::gfxImageFormat mFormat;
+  const unsigned char*              mSurfaceData;
+  PRInt32                           mReadCount;
 };
 
 #endif // GFXCOWSURFACEWRAPPER