Bug 900188 - Correctly treat WebGL as being single buffered when we share it across ipdl. r=nrc
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 01 Aug 2013 21:12:15 -0400
changeset 153451 4aec4fb6cb96f8c642161c5d8ad38ddaf94c96c8
parent 153450 4b0bf28abdf2122701f105b1adbd1f717f171fa0
child 153452 8808316e03bb383df4caa77a01130a532ebc95bc
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnrc
bugs900188
milestone25.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 900188 - Correctly treat WebGL as being single buffered when we share it across ipdl. r=nrc
gfx/layers/client/CanvasClient.cpp
gfx/layers/client/CanvasClient.h
gfx/layers/client/ClientCanvasLayer.cpp
gfx/layers/client/ClientCanvasLayer.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -17,30 +17,25 @@
 #endif
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 /* static */ TemporaryRef<CanvasClient>
-CanvasClient::CreateCanvasClient(CompositableType aCompositableHostType,
+CanvasClient::CreateCanvasClient(CanvasClientType aType,
                                  CompositableForwarder* aForwarder,
                                  TextureFlags aFlags)
 {
-  if (aCompositableHostType == BUFFER_IMAGE_SINGLE) {
-    return new CanvasClient2D(aForwarder, aFlags);
+  if (aType == CanvasClientGLContext &&
+      aForwarder->GetCompositorBackendType() == LAYERS_OPENGL) {
+    return new CanvasClientSurfaceStream(aForwarder, aFlags);
   }
-  if (aCompositableHostType == BUFFER_IMAGE_BUFFERED) {
-    if (aForwarder->GetCompositorBackendType() == LAYERS_OPENGL) {
-      return new CanvasClientWebGL(aForwarder, aFlags);
-    }
-    return new CanvasClient2D(aForwarder, aFlags);
-  }
-  return nullptr;
+  return new CanvasClient2D(aForwarder, aFlags);
 }
 
 void
 CanvasClient::Updated()
 {
   mForwarder->UpdateTexture(this, 1, mDeprecatedTextureClient->GetDescriptor());
 }
 
@@ -67,38 +62,42 @@ CanvasClient2D::Update(gfx::IntSize aSiz
   mDeprecatedTextureClient->EnsureAllocated(aSize, contentType);
 
   gfxASurface* surface = mDeprecatedTextureClient->LockSurface();
   aLayer->UpdateSurface(surface);
   mDeprecatedTextureClient->Unlock();
 }
 
 void
-CanvasClientWebGL::Updated()
+CanvasClientSurfaceStream::Updated()
 {
-  mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->GetDescriptor());
+  if (mNeedsUpdate) {
+    mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->GetDescriptor());
+    mNeedsUpdate = false;
+  }
 }
 
 
-CanvasClientWebGL::CanvasClientWebGL(CompositableForwarder* aFwd,
-                                     TextureFlags aFlags)
+CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder* aFwd,
+                                                     TextureFlags aFlags)
 : CanvasClient(aFwd, aFlags)
+, mNeedsUpdate(false)
 {
-  mTextureInfo.mCompositableType = BUFFER_IMAGE_BUFFERED;
+  mTextureInfo.mCompositableType = BUFFER_IMAGE_SINGLE;
 }
 
 void
-CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
+CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
   if (!mDeprecatedTextureClient) {
     mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_STREAM_GL);
     MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
   }
 
-  NS_ASSERTION(aLayer->mGLContext, "CanvasClientWebGL should only be used with GL canvases");
+  NS_ASSERTION(aLayer->mGLContext, "CanvasClientSurfaceStream should only be used with GL canvases");
 
   // the content type won't be used
   mDeprecatedTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR);
 
   GLScreenBuffer* screen = aLayer->mGLContext->Screen();
   SurfaceStream* stream = screen->Stream();
 
   bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
@@ -117,24 +116,30 @@ CanvasClientWebGL::Update(gfx::IntSize a
     }
 
     SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
     mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
 #else
     printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
     MOZ_ASSERT(false);
 #endif
+    mNeedsUpdate = true;
   } else {
     SurfaceStreamHandle handle = stream->GetShareHandle();
-    mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
+    SurfaceDescriptor *desc = mDeprecatedTextureClient->GetDescriptor();
+    if (desc->type() != SurfaceDescriptor::TSurfaceStreamDescriptor ||
+        desc->get_SurfaceStreamDescriptor().handle() != handle) {
+      *desc = SurfaceStreamDescriptor(handle, false);
 
-    // Bug 894405
-    //
-    // Ref this so the SurfaceStream doesn't disappear unexpectedly. The
-    // Compositor will need to unref it when finished.
-    aLayer->mGLContext->AddRef();
+      // Bug 894405
+      //
+      // Ref this so the SurfaceStream doesn't disappear unexpectedly. The
+      // Compositor will need to unref it when finished.
+      aLayer->mGLContext->AddRef();
+      mNeedsUpdate = true;
+    }
   }
 
   aLayer->Painted();
 }
 
 }
 }
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -21,17 +21,21 @@ class ClientCanvasLayer;
 class CanvasClient : public CompositableClient
 {
 public:
   /**
    * Creates, configures, and returns a new canvas client. If necessary, a
    * message will be sent to the compositor to create a corresponding image
    * host.
    */
-  static TemporaryRef<CanvasClient> CreateCanvasClient(CompositableType aImageHostType,
+  enum CanvasClientType {
+    CanvasClientSurface,
+    CanvasClientGLContext,
+  };
+  static TemporaryRef<CanvasClient> CreateCanvasClient(CanvasClientType aType,
                                                        CompositableForwarder* aFwd,
                                                        TextureFlags aFlags);
 
   CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
     : CompositableClient(aFwd)
   {
     mTextureInfo.mTextureFlags = aFlags;
   }
@@ -64,27 +68,30 @@ public:
     return mTextureInfo;
   }
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
 };
 
 // Used for GL canvases where we don't need to do any readback, i.e., with a
 // GL backend.
-class CanvasClientWebGL : public CanvasClient
+class CanvasClientSurfaceStream : public CanvasClient
 {
 public:
-  CanvasClientWebGL(CompositableForwarder* aFwd,
-                    TextureFlags aFlags);
+  CanvasClientSurfaceStream(CompositableForwarder* aFwd,
+                            TextureFlags aFlags);
 
   TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     return mTextureInfo;
   }
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
   virtual void Updated() MOZ_OVERRIDE;
+
+private:
+  bool mNeedsUpdate;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -89,17 +89,17 @@ ClientCanvasLayer::RenderLayer()
     bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
     //Append TEXTURE_DEALLOCATE_CLIENT flag for streaming buffer under OOPC case
     if (isCrossProcess && mGLContext) {
       GLScreenBuffer* screen = mGLContext->Screen();
       if (screen && screen->Stream()) {
         flags |= TEXTURE_DEALLOCATE_CLIENT;
       }
     }
-    mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
+    mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                                                      ClientManager(), flags);
     if (!mCanvasClient) {
       return;
     }
     if (HasShadow()) {
       mCanvasClient->Connect();
       ClientManager()->Attach(mCanvasClient, this);
     }
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -20,16 +20,17 @@ namespace mozilla {
 namespace layers {
 
 class CanvasClient2D;
 class CanvasClientWebGL;
 
 class ClientCanvasLayer : public CopyableCanvasLayer,
                           public ClientLayer
 {
+  typedef CanvasClient::CanvasClientType CanvasClientType;
 public:
   ClientCanvasLayer(ClientLayerManager* aLayerManager) :
     CopyableCanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
   {
     MOZ_COUNT_CTOR(ClientCanvasLayer);
   }
   virtual ~ClientCanvasLayer()
   {
@@ -70,25 +71,25 @@ public:
     return mCanvasClient;
   }
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
   
-  CompositableType GetCompositableClientType()
+  CanvasClientType GetCanvasClientType()
   {
     if (mGLContext) {
-      return BUFFER_IMAGE_BUFFERED;
+      return CanvasClient::CanvasClientGLContext;
     }
-    return BUFFER_IMAGE_SINGLE;
+    return CanvasClient::CanvasClientSurface;
   }
 
   RefPtr<CanvasClient> mCanvasClient;
 
   friend class CanvasClient2D;
-  friend class CanvasClientWebGL;
+  friend class CanvasClientSurfaceStream;
 };
 }
 }
 
 #endif
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -587,59 +587,48 @@ SurfaceStreamHostOGL::DeleteTextures()
     mGL->MakeCurrent();
     mGL->fDeleteTextures(1, &mUploadTexture);
     mUploadTexture = 0;
     mTextureHandle = 0;
   }
 }
 
 void
-SurfaceStreamHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage,
-                                       nsIntRegion* aRegion)
+SurfaceStreamHostOGL::UpdateImpl(const SurfaceDescriptor& aImage,
+                                 nsIntRegion* aRegion,
+                                 nsIntPoint* aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceStreamDescriptor,
              "Invalid descriptor");
 
-  mStreamGL = nullptr;
+  // Bug 894405
+  //
+  // The SurfaceStream's GLContext was refed before being passed up to us, so
+  // we need to ensure it gets unrefed when we are finished.
+  const SurfaceStreamDescriptor& streamDesc =
+      aImage.get_SurfaceStreamDescriptor();
 
-  if (aImage.type() == SurfaceDescriptor::TSurfaceStreamDescriptor) {
-    // Bug 894405
-    //
-    // The SurfaceStream's GLContext was refed before being passed up to us, so
-    // we need to ensure it gets unrefed when we are finished.
-    const SurfaceStreamDescriptor& streamDesc =
-        aImage.get_SurfaceStreamDescriptor();
-
-    SurfaceStream* surfStream = SurfaceStream::FromHandle(streamDesc.handle());
-    if (surfStream) {
-      mStreamGL = dont_AddRef(surfStream->GLContext());
-    }
-  } 
+  mStream = SurfaceStream::FromHandle(streamDesc.handle());
+  MOZ_ASSERT(mStream);
+  mStreamGL = dont_AddRef(mStream->GLContext());
 }
 
 void
 SurfaceStreamHostOGL::Unlock()
 {
   // We don't know what this is unless we're locked
   mFormat = gfx::FORMAT_UNKNOWN;
 }
 
 bool
 SurfaceStreamHostOGL::Lock()
 {
   mGL->MakeCurrent();
-  SurfaceStream* surfStream = nullptr;
-  SharedSurface* sharedSurf = nullptr;
-  const SurfaceStreamDescriptor& streamDesc =
-    mBuffer->get_SurfaceStreamDescriptor();
 
-  surfStream = SurfaceStream::FromHandle(streamDesc.handle());
-  MOZ_ASSERT(surfStream);
-
-  sharedSurf = surfStream->SwapConsumer();
+  SharedSurface* sharedSurf = mStream->SwapConsumer();
   if (!sharedSurf) {
     // We don't have a valid surf to show yet.
     return false;
   }
 
   mGL->MakeCurrent();
 
   mSize = IntSize(sharedSurf->Size().width, sharedSurf->Size().height);
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -647,17 +647,16 @@ class SurfaceStreamHostOGL : public Depr
 public:
   typedef gfxASurface::gfxContentType ContentType;
   typedef mozilla::gl::GLContext GLContext;
   typedef mozilla::gl::TextureImage TextureImage;
 
   virtual ~SurfaceStreamHostOGL()
   {
     DeleteTextures();
-    *mBuffer = SurfaceDescriptor();
   }
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual GLuint GetTextureHandle()
   {
     return mTextureHandle;
   }
@@ -667,18 +666,19 @@ public:
     return DeprecatedTextureHost::GetFormat();
   }
 
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
 
   bool IsValid() const MOZ_OVERRIDE { return true; }
 
   // override from DeprecatedTextureHost
-  virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
-                                nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
+  virtual void UpdateImpl(const SurfaceDescriptor& aImage,
+                          nsIntRegion* aRegion,
+                          nsIntPoint* aOffset);
   virtual bool Lock() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE {
     return mWrapMode;
   }
   virtual void SetWrapMode(GLenum aMode) {
     mWrapMode = aMode;
@@ -715,28 +715,30 @@ public:
 #endif
 
   SurfaceStreamHostOGL()
     : mGL(nullptr)
     , mTextureHandle(0)
     , mTextureTarget(LOCAL_GL_TEXTURE_2D)
     , mUploadTexture(0)
     , mWrapMode(LOCAL_GL_CLAMP_TO_EDGE)
+    , mStream(nullptr)
   {}
 
 protected:
   void DeleteTextures();
 
   gfx::IntSize mSize;
   nsRefPtr<GLContext> mGL;
   GLuint mTextureHandle;
   GLenum mTextureTarget;
   GLuint mUploadTexture;
   GLenum mWrapMode;
   nsRefPtr<GLContext> mStreamGL;
+  gfx::SurfaceStream *mStream;
 };
 
 class TiledDeprecatedTextureHostOGL : public DeprecatedTextureHost
                           , public TextureSourceOGL
 {
 public:
   TiledDeprecatedTextureHostOGL()
     : mTextureHandle(0)