Bug 1163908 - Export GL draw data to layerscope for drawing heat-map view. r=:djg
authorCJKu <cku@mozilla.com>
Fri, 22 May 2015 11:36:00 +0200
changeset 245649 f4dcd8361800b3d83c4448de0684fbc5c07ea93e
parent 245648 5e3736bd6c332aa0a0233d89720d326dadedb08a
child 245650 0431f570160df1497943b8d7039b5f70c4b45e74
push id13177
push userkwierso@gmail.com
push dateTue, 26 May 2015 23:26:28 +0000
treeherderfx-team@b991cd5a0ad1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1163908
milestone41.0a1
Bug 1163908 - Export GL draw data to layerscope for drawing heat-map view. r=:djg
gfx/layers/LayerScope.cpp
gfx/layers/LayerScope.h
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/protobuf/LayerScopePacket.pb.cc
gfx/layers/protobuf/LayerScopePacket.pb.h
gfx/layers/protobuf/LayerScopePacket.proto
--- a/gfx/layers/LayerScope.cpp
+++ b/gfx/layers/LayerScope.cpp
@@ -221,105 +221,91 @@ StaticAutoPtr<LayerScopeWebSocketManager
 class DebugGLData: public LinkedListElement<DebugGLData> {
 public:
     explicit DebugGLData(Packet::DataType aDataType)
         : mDataType(aDataType)
     { }
 
     virtual ~DebugGLData() { }
 
-    Packet::DataType GetDataType() const { return mDataType; }
-
     virtual bool Write() = 0;
 
+protected:
     static bool WriteToStream(Packet& aPacket) {
         if (!WebSocketHelper::GetSocketManager())
             return true;
 
         uint32_t size = aPacket.ByteSize();
         auto data = MakeUnique<uint8_t[]>(size);
         aPacket.SerializeToArray(data.get(), size);
         return WebSocketHelper::GetSocketManager()->WriteAll(data.get(), size);
     }
 
-protected:
     Packet::DataType mDataType;
 };
 
-class DebugGLFrameStatusData : public DebugGLData
+class DebugGLFrameStatusData final: public DebugGLData
 {
 public:
     DebugGLFrameStatusData(Packet::DataType aDataType,
                            int64_t aValue)
         : DebugGLData(aDataType),
           mFrameStamp(aValue)
     { }
 
     explicit DebugGLFrameStatusData(Packet::DataType aDataType)
         : DebugGLData(aDataType),
           mFrameStamp(0)
     { }
 
-    int64_t GetFrameStamp() const { return mFrameStamp; }
-
     virtual bool Write() override {
         Packet packet;
         packet.set_type(mDataType);
 
         FramePacket* fp = packet.mutable_frame();
         fp->set_value(static_cast<uint64_t>(mFrameStamp));
 
-        if (!WriteToStream(packet))
-            return false;
-        return true;
+        return WriteToStream(packet);
     }
 
 protected:
     int64_t mFrameStamp;
 };
 
-class DebugGLTextureData : public DebugGLData {
+class DebugGLTextureData final: public DebugGLData {
 public:
     DebugGLTextureData(GLContext* cx,
                        void* layerRef,
                        GLenum target,
                        GLuint name,
                        DataSourceSurface* img)
         : DebugGLData(Packet::TEXTURE),
-          mLayerRef(layerRef),
+          mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
           mTarget(target),
           mName(name),
           mContextAddress(reinterpret_cast<intptr_t>(cx)),
           mDatasize(0)
     {
         // pre-packing
         // DataSourceSurface may have locked buffer,
         // so we should compress now, and then it could
         // be unlocked outside.
         pack(img);
     }
 
-    const void* GetLayerRef() const { return mLayerRef; }
-    GLuint GetName() const { return mName; }
-    GLenum GetTextureTarget() const { return mTarget; }
-    intptr_t GetContextAddress() const { return mContextAddress; }
-    uint32_t GetDataSize() const { return mDatasize; }
-
     virtual bool Write() override {
-        if (!WriteToStream(mPacket))
-            return false;
-        return true;
+        return WriteToStream(mPacket);
     }
 
 private:
     void pack(DataSourceSurface* aImage) {
         mPacket.set_type(mDataType);
 
         TexturePacket* tp = mPacket.mutable_texture();
-        tp->set_layerref(reinterpret_cast<uint64_t>(mLayerRef));
+        tp->set_layerref(mLayerRef);
         tp->set_name(mName);
         tp->set_target(mTarget);
         tp->set_dataformat(LOCAL_GL_RGBA);
         tp->set_glcontext(static_cast<uint64_t>(mContextAddress));
 
         if (aImage) {
             tp->set_width(aImage->GetSize().width);
             tp->set_height(aImage->GetSize().height);
@@ -347,83 +333,74 @@ private:
         } else {
             tp->set_width(0);
             tp->set_height(0);
             tp->set_stride(0);
         }
     }
 
 protected:
-    void* mLayerRef;
+    uint64_t mLayerRef;
     GLenum mTarget;
     GLuint mName;
     intptr_t mContextAddress;
     uint32_t mDatasize;
 
     // Packet data
     Packet mPacket;
 };
 
-class DebugGLColorData : public DebugGLData {
+class DebugGLColorData final: public DebugGLData {
 public:
     DebugGLColorData(void* layerRef,
                      const gfxRGBA& color,
                      int width,
                      int height)
         : DebugGLData(Packet::COLOR),
-          mLayerRef(layerRef),
+          mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
           mColor(color.Packed()),
           mSize(width, height)
     { }
 
-    const void* GetLayerRef() const { return mLayerRef; }
-    uint32_t GetColor() const { return mColor; }
-    const nsIntSize& GetSize() const { return mSize; }
-
     virtual bool Write() override {
         Packet packet;
         packet.set_type(mDataType);
 
         ColorPacket* cp = packet.mutable_color();
-        cp->set_layerref(reinterpret_cast<uint64_t>(mLayerRef));
+        cp->set_layerref(mLayerRef);
         cp->set_color(mColor);
         cp->set_width(mSize.width);
         cp->set_height(mSize.height);
 
-        if (!WriteToStream(packet))
-            return false;
-        return true;
+        return WriteToStream(packet);
     }
 
 protected:
-    void* mLayerRef;
+    uint64_t mLayerRef;
     uint32_t mColor;
     nsIntSize mSize;
 };
 
-class DebugGLLayersData : public DebugGLData {
+class DebugGLLayersData final: public DebugGLData {
 public:
     explicit DebugGLLayersData(UniquePtr<Packet> aPacket)
         : DebugGLData(Packet::LAYERS),
           mPacket(Move(aPacket))
     { }
 
     virtual bool Write() override {
         mPacket->set_type(mDataType);
-
-        if (!WriteToStream(*mPacket))
-            return false;
-        return true;
+        return WriteToStream(*mPacket);
     }
 
 protected:
     UniquePtr<Packet> mPacket;
 };
 
-class DebugGLMetaData : public DebugGLData
+class DebugGLMetaData final: public DebugGLData
 {
 public:
     DebugGLMetaData(Packet::DataType aDataType,
                     bool aValue)
         : DebugGLData(aDataType),
           mComposedByHwc(aValue)
     { }
 
@@ -434,25 +411,79 @@ public:
 
     virtual bool Write() override {
         Packet packet;
         packet.set_type(mDataType);
 
         MetaPacket* mp = packet.mutable_meta();
         mp->set_composedbyhwc(mComposedByHwc);
 
-        if (!WriteToStream(packet))
-            return false;
-        return true;
+        return WriteToStream(packet);
     }
 
 protected:
     bool mComposedByHwc;
 };
 
+class DebugGLDrawData final: public DebugGLData {
+public:
+    DebugGLDrawData(float aOffsetX,
+                    float aOffsetY,
+                    const gfx::Matrix4x4& aMVMatrix,
+                    size_t aRects,
+                    const gfx::Rect* aLayerRects,
+                    void* aLayerRef)
+        : DebugGLData(Packet::DRAW),
+          mOffsetX(aOffsetX),
+          mOffsetY(aOffsetY),
+          mMVMatrix(aMVMatrix),
+          mRects(aRects),
+          mLayerRef(reinterpret_cast<uint64_t>(aLayerRef))
+    {
+        for (size_t i = 0; i < mRects; i++){
+            mLayerRects[i] = aLayerRects[i];
+        }
+    }
+
+    virtual bool Write() override {
+        Packet packet;
+        packet.set_type(mDataType);
+
+        DrawPacket* dp = packet.mutable_draw();
+        dp->set_layerref(mLayerRef);
+
+        dp->set_offsetx(mOffsetX);
+        dp->set_offsety(mOffsetY);
+
+        auto element = reinterpret_cast<Float *>(&mMVMatrix);
+        for (int i = 0; i < 16; i++) {
+          dp->add_mvmatrix(*element++);
+        }
+        dp->set_totalrects(mRects);
+
+        MOZ_ASSERT(mRects > 0 && mRects < 4);
+        for (size_t i = 0; i < mRects; i++) {
+            layerscope::DrawPacket::Rect* pRect = dp->add_layerrect();
+            pRect->set_x(mLayerRects[i].x);
+            pRect->set_y(mLayerRects[i].y);
+            pRect->set_w(mLayerRects[i].width);
+            pRect->set_h(mLayerRects[i].height);
+        }
+
+        return WriteToStream(packet);
+    }
+
+protected:
+    float mOffsetX;
+    float mOffsetY;
+    gfx::Matrix4x4 mMVMatrix;
+    size_t mRects;
+    gfx::Rect mLayerRects[4];
+    uint64_t mLayerRef;
+};
 
 class DebugListener : public nsIServerSocketListener
 {
     virtual ~DebugListener() { }
 
 public:
 
     NS_DECL_THREADSAFE_ISUPPORTS
@@ -798,17 +829,16 @@ SenderHelper::SendEffectChain(GLContext*
         default:
             break;
     }
 
     //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK];
     // TODO:
 }
 
-
 // ----------------------------------------------
 // LayerScopeWebSocketHandler implementation
 // ----------------------------------------------
 void
 LayerScopeWebSocketHandler::OpenStream(nsISocketTransport* aTransport)
 {
     MOZ_ASSERT(aTransport);
 
@@ -1291,26 +1321,117 @@ LayerScope::Init()
             return;
         }
         DebugOnly<nsresult> rv = NS_DispatchToMainThread(new CreateServerSocketRunnable());
         MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch WebSocket Creation to main thread");
         dispatched = true;
     }
 }
 
+class DrawSession {
+public:
+    NS_INLINE_DECL_REFCOUNTING(DrawSession)
+
+    DrawSession()
+      : mOffsetX(0.0),
+        mOffsetY(0.0),
+        mRects(0)
+    { }
+
+    float mOffsetX;
+    float mOffsetY;
+    gfx::Matrix4x4 mMVMatrix;
+    size_t mRects;
+    gfx::Rect mLayerRects[4];
+private:
+    ~DrawSession() {}
+};
+
+class DrawSessionHolder {
+public:
+    static void setSession(DrawSession *aSession) {
+        mSession = aSession;
+    }
+
+    static DrawSession& current() {
+        return *mSession;
+    }
+
+private:
+    static nsRefPtr<DrawSession> mSession;
+};
+
+nsRefPtr<DrawSession> DrawSessionHolder::mSession;
+
 void
-LayerScope::SendEffectChain(gl::GLContext* aGLContext,
-                            const EffectChain& aEffectChain,
-                            int aWidth,
-                            int aHeight)
+LayerScope::DrawBegin()
+{
+    if (!CheckSendable()) {
+        return;
+    }
+
+    DrawSessionHolder::setSession(new DrawSession());
+}
+
+void LayerScope::SetRenderOffset(float aX, float aY)
+{
+    if (!CheckSendable()) {
+        return;
+    }
+
+    DrawSessionHolder::current().mOffsetX = aX;
+    DrawSessionHolder::current().mOffsetY = aY;
+}
+
+void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
+{
+    if (!CheckSendable()) {
+        return;
+    }
+
+    DrawSessionHolder::current().mMVMatrix = aMatrix;
+}
+
+void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
+{
+    if (!CheckSendable()) {
+        return;
+    }
+
+    MOZ_ASSERT(aRects > 0 && aRects <= 4);
+    MOZ_ASSERT(aLayerRects);
+
+    DrawSessionHolder::current().mRects = aRects;
+
+    for (size_t i = 0; i < aRects; i++){
+        DrawSessionHolder::current().mLayerRects[i] = aLayerRects[i];
+    }
+}
+
+void
+LayerScope::DrawEnd(gl::GLContext* aGLContext,
+                    const EffectChain& aEffectChain,
+                    int aWidth,
+                    int aHeight)
 {
     // Protect this public function
     if (!CheckSendable()) {
         return;
     }
+
+    // 1. Send parameters of draw call, such as uniforms and attributes of
+    // vertex adnd fragment shader.
+    DrawSession& draws = DrawSessionHolder::current();
+    WebSocketHelper::GetSocketManager()->AppendDebugData(
+        new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY,
+                            draws.mMVMatrix, draws.mRects,
+                            draws.mLayerRects,
+                            aEffectChain.mLayerRef));
+
+    // 2. Send textures.
     SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight);
 }
 
 void
 LayerScope::SendLayer(LayerComposite* aLayer,
                       int aWidth,
                       int aHeight)
 {
@@ -1354,17 +1475,16 @@ LayerScope::CheckSendable()
 void
 LayerScope::CleanLayer()
 {
     if (CheckSendable()) {
         WebSocketHelper::GetSocketManager()->CleanDebugData();
     }
 }
 
-
 void
 LayerScope::SetHWComposed()
 {
     if (CheckSendable()) {
         WebSocketHelper::GetSocketManager()->AppendDebugData(
             new DebugGLMetaData(Packet::META, true));
     }
 }
--- a/gfx/layers/LayerScope.h
+++ b/gfx/layers/LayerScope.h
@@ -18,20 +18,25 @@ namespace layers {
 
 namespace layerscope { class Packet; }
 
 struct EffectChain;
 class LayerComposite;
 
 class LayerScope {
 public:
-    static void SendEffectChain(gl::GLContext* aGLContext,
-                                const EffectChain& aEffectChain,
-                                int aWidth,
-                                int aHeight);
+    static void DrawBegin();
+    static void SetRenderOffset(float aX, float aY);
+    static void SetLayerTransform(const gfx::Matrix4x4& aMatrix);
+    static void SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects);
+    static void DrawEnd(gl::GLContext* aGLContext,
+                        const EffectChain& aEffectChain,
+                        int aWidth,
+                        int aHeight);
+
     static void SendLayer(LayerComposite* aLayer,
                           int aWidth,
                           int aHeight);
     static void SendLayerDump(UniquePtr<layerscope::Packet> aPacket);
     static bool CheckSendable();
     static void CleanLayer();
     static void SetHWComposed();
 
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -427,16 +427,17 @@ CompositorOGL::BindAndDrawQuadWithTextur
                                               TextureSource *aTexture)
 {
   Rect layerRects[4];
   Rect textureRects[4];
   size_t rects = DecomposeIntoNoRepeatRects(aRect,
                                             aTexCoordRect,
                                             &layerRects,
                                             &textureRects);
+
   BindAndDrawQuads(aProg, rects, layerRects, textureRects);
 }
 
 void
 CompositorOGL::PrepareViewport(const gfx::IntSize& aSize)
 {
   // Set the viewport correctly.
   mGLContext->fViewport(0, 0, aSize.width, aSize.height);
@@ -914,34 +915,32 @@ CompositorOGL::DrawQuad(const Rect& aRec
 
   MOZ_ASSERT(mFrameInProgress, "frame not started");
   MOZ_ASSERT(mCurrentRenderTarget, "No destination");
 
   if (aEffectChain.mPrimaryEffect->mType == EffectTypes::VR_DISTORTION) {
     DrawVRDistortion(aRect, aClipRect, aEffectChain, aOpacity, aTransform);
     return;
   }
+  LayerScope::DrawBegin();
 
   Rect clipRect = aClipRect;
   // aClipRect is in destination coordinate space (after all
   // transforms and offsets have been applied) so if our
   // drawing is going to be shifted by mRenderOffset then we need
   // to shift the clip rect by the same amount.
   if (!mTarget && mCurrentRenderTarget->IsWindow()) {
     clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y);
   }
   IntRect intClipRect;
   clipRect.ToIntRect(&intClipRect);
 
   gl()->fScissor(intClipRect.x, FlipY(intClipRect.y + intClipRect.height),
                  intClipRect.width, intClipRect.height);
 
-  LayerScope::SendEffectChain(mGLContext, aEffectChain,
-                              aRect.width, aRect.height);
-
   MaskType maskType;
   EffectMask* effectMask;
   TextureSourceOGL* sourceMask = nullptr;
   gfx::Matrix4x4 maskQuadTransform;
   if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
     effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
     sourceMask = effectMask->mMaskTexture->AsSourceOGL();
 
@@ -1004,25 +1003,27 @@ CompositorOGL::DrawQuad(const Rect& aRec
 
   bool colorMatrix = aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX];
   ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType, blendMode, colorMatrix);
   config.SetOpacity(aOpacity != 1.f);
   ShaderProgramOGL *program = GetShaderProgramFor(config);
   ActivateProgram(program);
   program->SetProjectionMatrix(mProjMatrix);
   program->SetLayerTransform(aTransform);
-
+  LayerScope::SetLayerTransform(aTransform);
   if (colorMatrix) {
       EffectColorMatrix* effectColorMatrix =
         static_cast<EffectColorMatrix*>(aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX].get());
       program->SetColorMatrix(effectColorMatrix->mColorMatrix);
   }
 
   IntPoint offset = mCurrentRenderTarget->GetOrigin();
   program->SetRenderOffset(offset.x, offset.y);
+  LayerScope::SetRenderOffset(offset.x, offset.y);
+
   if (aOpacity != 1.f)
     program->SetLayerOpacity(aOpacity);
   if (config.mFeatures & ENABLE_TEXTURE_RECT) {
     TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
     TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL();
     // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1.
     program->SetTexCoordMultiplier(source->GetSize().width, source->GetSize().height);
@@ -1211,16 +1212,17 @@ CompositorOGL::DrawQuad(const Rect& aRec
 
   if (didSetBlendMode) {
     gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                              LOCAL_GL_ONE, LOCAL_GL_ONE);
   }
 
   // in case rendering has used some other GL context
   MakeCurrent();
+  LayerScope::DrawEnd(mGLContext, aEffectChain, aRect.width, aRect.height);
 }
 
 void
 CompositorOGL::EndFrame()
 {
   PROFILER_LABEL("CompositorOGL", "EndFrame",
     js::ProfileEntry::Category::GRAPHICS);
 
@@ -1472,16 +1474,17 @@ CompositorOGL::BindAndDrawQuads(ShaderPr
   aProg->SetLayerRects(aLayerRects);
   if (aProg->GetTextureCount() > 0) {
     aProg->SetTextureRects(aTextureRects);
   }
 
   // We are using GL_TRIANGLES here because the Mac Intel drivers fail to properly
   // process uniform arrays with GL_TRIANGLE_STRIP. Go figure.
   mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 6 * aQuads);
+  LayerScope::SetLayerRects(aQuads, aLayerRects);
 }
 
 GLBlitTextureImageHelper*
 CompositorOGL::BlitTextureImageHelper()
 {
     if (!mBlitTextureImageHelper) {
         mBlitTextureImageHelper = MakeUnique<GLBlitTextureImageHelper>(this);
     }
--- a/gfx/layers/protobuf/LayerScopePacket.pb.cc
+++ b/gfx/layers/protobuf/LayerScopePacket.pb.cc
@@ -21,16 +21,18 @@ void protobuf_ShutdownFile_LayerScopePac
   delete LayersPacket::default_instance_;
   delete LayersPacket_Layer::default_instance_;
   delete LayersPacket_Layer_Size::default_instance_;
   delete LayersPacket_Layer_Rect::default_instance_;
   delete LayersPacket_Layer_Region::default_instance_;
   delete LayersPacket_Layer_Matrix::default_instance_;
   delete LayersPacket_Layer_Shadow::default_instance_;
   delete MetaPacket::default_instance_;
+  delete DrawPacket::default_instance_;
+  delete DrawPacket_Rect::default_instance_;
   delete Packet::default_instance_;
   delete CommandPacket::default_instance_;
 }
 
 void protobuf_AddDesc_LayerScopePacket_2eproto() {
   static bool already_here = false;
   if (already_here) return;
   already_here = true;
@@ -42,29 +44,33 @@ void protobuf_AddDesc_LayerScopePacket_2
   LayersPacket::default_instance_ = new LayersPacket();
   LayersPacket_Layer::default_instance_ = new LayersPacket_Layer();
   LayersPacket_Layer_Size::default_instance_ = new LayersPacket_Layer_Size();
   LayersPacket_Layer_Rect::default_instance_ = new LayersPacket_Layer_Rect();
   LayersPacket_Layer_Region::default_instance_ = new LayersPacket_Layer_Region();
   LayersPacket_Layer_Matrix::default_instance_ = new LayersPacket_Layer_Matrix();
   LayersPacket_Layer_Shadow::default_instance_ = new LayersPacket_Layer_Shadow();
   MetaPacket::default_instance_ = new MetaPacket();
+  DrawPacket::default_instance_ = new DrawPacket();
+  DrawPacket_Rect::default_instance_ = new DrawPacket_Rect();
   Packet::default_instance_ = new Packet();
   CommandPacket::default_instance_ = new CommandPacket();
   FramePacket::default_instance_->InitAsDefaultInstance();
   ColorPacket::default_instance_->InitAsDefaultInstance();
   TexturePacket::default_instance_->InitAsDefaultInstance();
   LayersPacket::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Size::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Rect::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Region::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Matrix::default_instance_->InitAsDefaultInstance();
   LayersPacket_Layer_Shadow::default_instance_->InitAsDefaultInstance();
   MetaPacket::default_instance_->InitAsDefaultInstance();
+  DrawPacket::default_instance_->InitAsDefaultInstance();
+  DrawPacket_Rect::default_instance_->InitAsDefaultInstance();
   Packet::default_instance_->InitAsDefaultInstance();
   CommandPacket::default_instance_->InitAsDefaultInstance();
   ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_LayerScopePacket_2eproto);
 }
 
 // Force AddDescriptors() to be called at static initialization time.
 struct StaticDescriptorInitializer_LayerScopePacket_2eproto {
   StaticDescriptorInitializer_LayerScopePacket_2eproto() {
@@ -3187,91 +3193,688 @@ void MetaPacket::Swap(MetaPacket* other)
 
 ::std::string MetaPacket::GetTypeName() const {
   return "mozilla.layers.layerscope.MetaPacket";
 }
 
 
 // ===================================================================
 
+#ifndef _MSC_VER
+const int DrawPacket_Rect::kXFieldNumber;
+const int DrawPacket_Rect::kYFieldNumber;
+const int DrawPacket_Rect::kWFieldNumber;
+const int DrawPacket_Rect::kHFieldNumber;
+#endif  // !_MSC_VER
+
+DrawPacket_Rect::DrawPacket_Rect()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+}
+
+void DrawPacket_Rect::InitAsDefaultInstance() {
+}
+
+DrawPacket_Rect::DrawPacket_Rect(const DrawPacket_Rect& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void DrawPacket_Rect::SharedCtor() {
+  _cached_size_ = 0;
+  x_ = 0;
+  y_ = 0;
+  w_ = 0;
+  h_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DrawPacket_Rect::~DrawPacket_Rect() {
+  SharedDtor();
+}
+
+void DrawPacket_Rect::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void DrawPacket_Rect::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const DrawPacket_Rect& DrawPacket_Rect::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto();  return *default_instance_;
+}
+
+DrawPacket_Rect* DrawPacket_Rect::default_instance_ = NULL;
+
+DrawPacket_Rect* DrawPacket_Rect::New() const {
+  return new DrawPacket_Rect;
+}
+
+void DrawPacket_Rect::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    x_ = 0;
+    y_ = 0;
+    w_ = 0;
+    h_ = 0;
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+bool DrawPacket_Rect::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required float x = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &x_)));
+          set_has_x();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(21)) goto parse_y;
+        break;
+      }
+      
+      // required float y = 2;
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_y:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &y_)));
+          set_has_y();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(29)) goto parse_w;
+        break;
+      }
+      
+      // required float w = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_w:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &w_)));
+          set_has_w();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(37)) goto parse_h;
+        break;
+      }
+      
+      // required float h = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_h:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &h_)));
+          set_has_h();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void DrawPacket_Rect::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // required float x = 1;
+  if (has_x()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output);
+  }
+  
+  // required float y = 2;
+  if (has_y()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output);
+  }
+  
+  // required float w = 3;
+  if (has_w()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->w(), output);
+  }
+  
+  // required float h = 4;
+  if (has_h()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->h(), output);
+  }
+  
+}
+
+int DrawPacket_Rect::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required float x = 1;
+    if (has_x()) {
+      total_size += 1 + 4;
+    }
+    
+    // required float y = 2;
+    if (has_y()) {
+      total_size += 1 + 4;
+    }
+    
+    // required float w = 3;
+    if (has_w()) {
+      total_size += 1 + 4;
+    }
+    
+    // required float h = 4;
+    if (has_h()) {
+      total_size += 1 + 4;
+    }
+    
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void DrawPacket_Rect::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const DrawPacket_Rect*>(&from));
+}
+
+void DrawPacket_Rect::MergeFrom(const DrawPacket_Rect& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_x()) {
+      set_x(from.x());
+    }
+    if (from.has_y()) {
+      set_y(from.y());
+    }
+    if (from.has_w()) {
+      set_w(from.w());
+    }
+    if (from.has_h()) {
+      set_h(from.h());
+    }
+  }
+}
+
+void DrawPacket_Rect::CopyFrom(const DrawPacket_Rect& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DrawPacket_Rect::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false;
+  
+  return true;
+}
+
+void DrawPacket_Rect::Swap(DrawPacket_Rect* other) {
+  if (other != this) {
+    std::swap(x_, other->x_);
+    std::swap(y_, other->y_);
+    std::swap(w_, other->w_);
+    std::swap(h_, other->h_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string DrawPacket_Rect::GetTypeName() const {
+  return "mozilla.layers.layerscope.DrawPacket.Rect";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int DrawPacket::kOffsetXFieldNumber;
+const int DrawPacket::kOffsetYFieldNumber;
+const int DrawPacket::kMvMatrixFieldNumber;
+const int DrawPacket::kTotalRectsFieldNumber;
+const int DrawPacket::kLayerRectFieldNumber;
+const int DrawPacket::kLayerrefFieldNumber;
+#endif  // !_MSC_VER
+
+DrawPacket::DrawPacket()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+}
+
+void DrawPacket::InitAsDefaultInstance() {
+}
+
+DrawPacket::DrawPacket(const DrawPacket& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void DrawPacket::SharedCtor() {
+  _cached_size_ = 0;
+  offsetx_ = 0;
+  offsety_ = 0;
+  totalrects_ = 0u;
+  layerref_ = GOOGLE_ULONGLONG(0);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DrawPacket::~DrawPacket() {
+  SharedDtor();
+}
+
+void DrawPacket::SharedDtor() {
+  if (this != default_instance_) {
+  }
+}
+
+void DrawPacket::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const DrawPacket& DrawPacket::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto();  return *default_instance_;
+}
+
+DrawPacket* DrawPacket::default_instance_ = NULL;
+
+DrawPacket* DrawPacket::New() const {
+  return new DrawPacket;
+}
+
+void DrawPacket::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    offsetx_ = 0;
+    offsety_ = 0;
+    totalrects_ = 0u;
+    layerref_ = GOOGLE_ULONGLONG(0);
+  }
+  mvmatrix_.Clear();
+  layerrect_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+bool DrawPacket::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required float offsetX = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &offsetx_)));
+          set_has_offsetx();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(21)) goto parse_offsetY;
+        break;
+      }
+      
+      // required float offsetY = 2;
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_offsetY:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &offsety_)));
+          set_has_offsety();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(29)) goto parse_mvMatrix;
+        break;
+      }
+      
+      // repeated float mvMatrix = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_mvMatrix:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 1, 29, input, this->mutable_mvmatrix())));
+        } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+                   == ::google::protobuf::internal::WireFormatLite::
+                      WIRETYPE_LENGTH_DELIMITED) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, this->mutable_mvmatrix())));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(29)) goto parse_mvMatrix;
+        if (input->ExpectTag(32)) goto parse_totalRects;
+        break;
+      }
+      
+      // required uint32 totalRects = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_totalRects:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &totalrects_)));
+          set_has_totalrects();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(42)) goto parse_layerRect;
+        break;
+      }
+      
+      // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5;
+      case 5: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_layerRect:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_layerrect()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(42)) goto parse_layerRect;
+        if (input->ExpectTag(48)) goto parse_layerref;
+        break;
+      }
+      
+      // required uint64 layerref = 6;
+      case 6: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_layerref:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &layerref_)));
+          set_has_layerref();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void DrawPacket::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // required float offsetX = 1;
+  if (has_offsetx()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->offsetx(), output);
+  }
+  
+  // required float offsetY = 2;
+  if (has_offsety()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->offsety(), output);
+  }
+  
+  // repeated float mvMatrix = 3;
+  for (int i = 0; i < this->mvmatrix_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(
+      3, this->mvmatrix(i), output);
+  }
+  
+  // required uint32 totalRects = 4;
+  if (has_totalrects()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->totalrects(), output);
+  }
+  
+  // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5;
+  for (int i = 0; i < this->layerrect_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      5, this->layerrect(i), output);
+  }
+  
+  // required uint64 layerref = 6;
+  if (has_layerref()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(6, this->layerref(), output);
+  }
+  
+}
+
+int DrawPacket::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required float offsetX = 1;
+    if (has_offsetx()) {
+      total_size += 1 + 4;
+    }
+    
+    // required float offsetY = 2;
+    if (has_offsety()) {
+      total_size += 1 + 4;
+    }
+    
+    // required uint32 totalRects = 4;
+    if (has_totalrects()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->totalrects());
+    }
+    
+    // required uint64 layerref = 6;
+    if (has_layerref()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->layerref());
+    }
+    
+  }
+  // repeated float mvMatrix = 3;
+  {
+    int data_size = 0;
+    data_size = 4 * this->mvmatrix_size();
+    total_size += 1 * this->mvmatrix_size() + data_size;
+  }
+  
+  // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5;
+  total_size += 1 * this->layerrect_size();
+  for (int i = 0; i < this->layerrect_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->layerrect(i));
+  }
+  
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void DrawPacket::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const DrawPacket*>(&from));
+}
+
+void DrawPacket::MergeFrom(const DrawPacket& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  mvmatrix_.MergeFrom(from.mvmatrix_);
+  layerrect_.MergeFrom(from.layerrect_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_offsetx()) {
+      set_offsetx(from.offsetx());
+    }
+    if (from.has_offsety()) {
+      set_offsety(from.offsety());
+    }
+    if (from.has_totalrects()) {
+      set_totalrects(from.totalrects());
+    }
+    if (from.has_layerref()) {
+      set_layerref(from.layerref());
+    }
+  }
+}
+
+void DrawPacket::CopyFrom(const DrawPacket& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DrawPacket::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000002b) != 0x0000002b) return false;
+  
+  for (int i = 0; i < layerrect_size(); i++) {
+    if (!this->layerrect(i).IsInitialized()) return false;
+  }
+  return true;
+}
+
+void DrawPacket::Swap(DrawPacket* other) {
+  if (other != this) {
+    std::swap(offsetx_, other->offsetx_);
+    std::swap(offsety_, other->offsety_);
+    mvmatrix_.Swap(&other->mvmatrix_);
+    std::swap(totalrects_, other->totalrects_);
+    layerrect_.Swap(&other->layerrect_);
+    std::swap(layerref_, other->layerref_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string DrawPacket::GetTypeName() const {
+  return "mozilla.layers.layerscope.DrawPacket";
+}
+
+
+// ===================================================================
+
 bool Packet_DataType_IsValid(int value) {
   switch(value) {
     case 1:
     case 2:
     case 3:
     case 4:
     case 5:
     case 6:
+    case 7:
       return true;
     default:
       return false;
   }
 }
 
 #ifndef _MSC_VER
 const Packet_DataType Packet::FRAMESTART;
 const Packet_DataType Packet::FRAMEEND;
 const Packet_DataType Packet::COLOR;
 const Packet_DataType Packet::TEXTURE;
 const Packet_DataType Packet::LAYERS;
 const Packet_DataType Packet::META;
+const Packet_DataType Packet::DRAW;
 const Packet_DataType Packet::DataType_MIN;
 const Packet_DataType Packet::DataType_MAX;
 const int Packet::DataType_ARRAYSIZE;
 #endif  // _MSC_VER
 #ifndef _MSC_VER
 const int Packet::kTypeFieldNumber;
 const int Packet::kFrameFieldNumber;
 const int Packet::kColorFieldNumber;
 const int Packet::kTextureFieldNumber;
 const int Packet::kLayersFieldNumber;
 const int Packet::kMetaFieldNumber;
+const int Packet::kDrawFieldNumber;
 #endif  // !_MSC_VER
 
 Packet::Packet()
   : ::google::protobuf::MessageLite() {
   SharedCtor();
 }
 
 void Packet::InitAsDefaultInstance() {
   frame_ = const_cast< ::mozilla::layers::layerscope::FramePacket*>(&::mozilla::layers::layerscope::FramePacket::default_instance());
   color_ = const_cast< ::mozilla::layers::layerscope::ColorPacket*>(&::mozilla::layers::layerscope::ColorPacket::default_instance());
   texture_ = const_cast< ::mozilla::layers::layerscope::TexturePacket*>(&::mozilla::layers::layerscope::TexturePacket::default_instance());
   layers_ = const_cast< ::mozilla::layers::layerscope::LayersPacket*>(&::mozilla::layers::layerscope::LayersPacket::default_instance());
   meta_ = const_cast< ::mozilla::layers::layerscope::MetaPacket*>(&::mozilla::layers::layerscope::MetaPacket::default_instance());
+  draw_ = const_cast< ::mozilla::layers::layerscope::DrawPacket*>(&::mozilla::layers::layerscope::DrawPacket::default_instance());
 }
 
 Packet::Packet(const Packet& from)
   : ::google::protobuf::MessageLite() {
   SharedCtor();
   MergeFrom(from);
 }
 
 void Packet::SharedCtor() {
   _cached_size_ = 0;
   type_ = 1;
   frame_ = NULL;
   color_ = NULL;
   texture_ = NULL;
   layers_ = NULL;
   meta_ = NULL;
+  draw_ = NULL;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
 Packet::~Packet() {
   SharedDtor();
 }
 
 void Packet::SharedDtor() {
   if (this != default_instance_) {
     delete frame_;
     delete color_;
     delete texture_;
     delete layers_;
     delete meta_;
+    delete draw_;
   }
 }
 
 void Packet::SetCachedSize(int size) const {
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = size;
   GOOGLE_SAFE_CONCURRENT_WRITES_END();
 }
@@ -3298,16 +3901,19 @@ void Packet::Clear() {
       if (texture_ != NULL) texture_->::mozilla::layers::layerscope::TexturePacket::Clear();
     }
     if (has_layers()) {
       if (layers_ != NULL) layers_->::mozilla::layers::layerscope::LayersPacket::Clear();
     }
     if (has_meta()) {
       if (meta_ != NULL) meta_->::mozilla::layers::layerscope::MetaPacket::Clear();
     }
+    if (has_draw()) {
+      if (draw_ != NULL) draw_->::mozilla::layers::layerscope::DrawPacket::Clear();
+    }
   }
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
 bool Packet::MergePartialFromCodedStream(
     ::google::protobuf::io::CodedInputStream* input) {
 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false
   ::google::protobuf::uint32 tag;
@@ -3392,16 +3998,30 @@ bool Packet::MergePartialFromCodedStream
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
          parse_meta:
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_meta()));
         } else {
           goto handle_uninterpreted;
         }
+        if (input->ExpectTag(58)) goto parse_draw;
+        break;
+      }
+      
+      // optional .mozilla.layers.layerscope.DrawPacket draw = 7;
+      case 7: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_draw:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_draw()));
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
       
       default: {
       handle_uninterpreted:
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
@@ -3449,16 +4069,22 @@ void Packet::SerializeWithCachedSizes(
   }
   
   // optional .mozilla.layers.layerscope.MetaPacket meta = 6;
   if (has_meta()) {
     ::google::protobuf::internal::WireFormatLite::WriteMessage(
       6, this->meta(), output);
   }
   
+  // optional .mozilla.layers.layerscope.DrawPacket draw = 7;
+  if (has_draw()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      7, this->draw(), output);
+  }
+  
 }
 
 int Packet::ByteSize() const {
   int total_size = 0;
   
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
     // required .mozilla.layers.layerscope.Packet.DataType type = 1;
     if (has_type()) {
@@ -3496,16 +4122,23 @@ int Packet::ByteSize() const {
     
     // optional .mozilla.layers.layerscope.MetaPacket meta = 6;
     if (has_meta()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
           this->meta());
     }
     
+    // optional .mozilla.layers.layerscope.DrawPacket draw = 7;
+    if (has_draw()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->draw());
+    }
+    
   }
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = total_size;
   GOOGLE_SAFE_CONCURRENT_WRITES_END();
   return total_size;
 }
 
 void Packet::CheckTypeAndMergeFrom(
@@ -3529,16 +4162,19 @@ void Packet::MergeFrom(const Packet& fro
       mutable_texture()->::mozilla::layers::layerscope::TexturePacket::MergeFrom(from.texture());
     }
     if (from.has_layers()) {
       mutable_layers()->::mozilla::layers::layerscope::LayersPacket::MergeFrom(from.layers());
     }
     if (from.has_meta()) {
       mutable_meta()->::mozilla::layers::layerscope::MetaPacket::MergeFrom(from.meta());
     }
+    if (from.has_draw()) {
+      mutable_draw()->::mozilla::layers::layerscope::DrawPacket::MergeFrom(from.draw());
+    }
   }
 }
 
 void Packet::CopyFrom(const Packet& from) {
   if (&from == this) return;
   Clear();
   MergeFrom(from);
 }
@@ -3550,27 +4186,31 @@ bool Packet::IsInitialized() const {
     if (!this->color().IsInitialized()) return false;
   }
   if (has_texture()) {
     if (!this->texture().IsInitialized()) return false;
   }
   if (has_layers()) {
     if (!this->layers().IsInitialized()) return false;
   }
+  if (has_draw()) {
+    if (!this->draw().IsInitialized()) return false;
+  }
   return true;
 }
 
 void Packet::Swap(Packet* other) {
   if (other != this) {
     std::swap(type_, other->type_);
     std::swap(frame_, other->frame_);
     std::swap(color_, other->color_);
     std::swap(texture_, other->texture_);
     std::swap(layers_, other->layers_);
     std::swap(meta_, other->meta_);
+    std::swap(draw_, other->draw_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     std::swap(_cached_size_, other->_cached_size_);
   }
 }
 
 ::std::string Packet::GetTypeName() const {
   return "mozilla.layers.layerscope.Packet";
 }
--- a/gfx/layers/protobuf/LayerScopePacket.pb.h
+++ b/gfx/layers/protobuf/LayerScopePacket.pb.h
@@ -39,16 +39,18 @@ class TexturePacket;
 class LayersPacket;
 class LayersPacket_Layer;
 class LayersPacket_Layer_Size;
 class LayersPacket_Layer_Rect;
 class LayersPacket_Layer_Region;
 class LayersPacket_Layer_Matrix;
 class LayersPacket_Layer_Shadow;
 class MetaPacket;
+class DrawPacket;
+class DrawPacket_Rect;
 class Packet;
 class CommandPacket;
 
 enum LayersPacket_Layer_LayerType {
   LayersPacket_Layer_LayerType_UnknownLayer = 0,
   LayersPacket_Layer_LayerType_LayerManager = 1,
   LayersPacket_Layer_LayerType_ContainerLayer = 2,
   LayersPacket_Layer_LayerType_PaintedLayer = 3,
@@ -87,21 +89,22 @@ const LayersPacket_Layer_Filter LayersPa
 const int LayersPacket_Layer_Filter_Filter_ARRAYSIZE = LayersPacket_Layer_Filter_Filter_MAX + 1;
 
 enum Packet_DataType {
   Packet_DataType_FRAMESTART = 1,
   Packet_DataType_FRAMEEND = 2,
   Packet_DataType_COLOR = 3,
   Packet_DataType_TEXTURE = 4,
   Packet_DataType_LAYERS = 5,
-  Packet_DataType_META = 6
+  Packet_DataType_META = 6,
+  Packet_DataType_DRAW = 7
 };
 bool Packet_DataType_IsValid(int value);
 const Packet_DataType Packet_DataType_DataType_MIN = Packet_DataType_FRAMESTART;
-const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_META;
+const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_DRAW;
 const int Packet_DataType_DataType_ARRAYSIZE = Packet_DataType_DataType_MAX + 1;
 
 enum CommandPacket_CmdType {
   CommandPacket_CmdType_NO_OP = 0,
   CommandPacket_CmdType_LAYERS_TREE = 1,
   CommandPacket_CmdType_LAYERS_BUFFER = 2
 };
 bool CommandPacket_CmdType_IsValid(int value);
@@ -1306,16 +1309,242 @@ class MetaPacket : public ::google::prot
   friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
   friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
   
   void InitAsDefaultInstance();
   static MetaPacket* default_instance_;
 };
 // -------------------------------------------------------------------
 
+class DrawPacket_Rect : public ::google::protobuf::MessageLite {
+ public:
+  DrawPacket_Rect();
+  virtual ~DrawPacket_Rect();
+  
+  DrawPacket_Rect(const DrawPacket_Rect& from);
+  
+  inline DrawPacket_Rect& operator=(const DrawPacket_Rect& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  static const DrawPacket_Rect& default_instance();
+  
+  void Swap(DrawPacket_Rect* other);
+  
+  // implements Message ----------------------------------------------
+  
+  DrawPacket_Rect* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const DrawPacket_Rect& from);
+  void MergeFrom(const DrawPacket_Rect& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::std::string GetTypeName() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // required float x = 1;
+  inline bool has_x() const;
+  inline void clear_x();
+  static const int kXFieldNumber = 1;
+  inline float x() const;
+  inline void set_x(float value);
+  
+  // required float y = 2;
+  inline bool has_y() const;
+  inline void clear_y();
+  static const int kYFieldNumber = 2;
+  inline float y() const;
+  inline void set_y(float value);
+  
+  // required float w = 3;
+  inline bool has_w() const;
+  inline void clear_w();
+  static const int kWFieldNumber = 3;
+  inline float w() const;
+  inline void set_w(float value);
+  
+  // required float h = 4;
+  inline bool has_h() const;
+  inline void clear_h();
+  static const int kHFieldNumber = 4;
+  inline float h() const;
+  inline void set_h(float value);
+  
+  // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.DrawPacket.Rect)
+ private:
+  inline void set_has_x();
+  inline void clear_has_x();
+  inline void set_has_y();
+  inline void clear_has_y();
+  inline void set_has_w();
+  inline void clear_has_w();
+  inline void set_has_h();
+  inline void clear_has_h();
+  
+  float x_;
+  float y_;
+  float w_;
+  float h_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+  
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
+  friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
+  friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
+  
+  void InitAsDefaultInstance();
+  static DrawPacket_Rect* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class DrawPacket : public ::google::protobuf::MessageLite {
+ public:
+  DrawPacket();
+  virtual ~DrawPacket();
+  
+  DrawPacket(const DrawPacket& from);
+  
+  inline DrawPacket& operator=(const DrawPacket& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  static const DrawPacket& default_instance();
+  
+  void Swap(DrawPacket* other);
+  
+  // implements Message ----------------------------------------------
+  
+  DrawPacket* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const DrawPacket& from);
+  void MergeFrom(const DrawPacket& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::std::string GetTypeName() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef DrawPacket_Rect Rect;
+  
+  // accessors -------------------------------------------------------
+  
+  // required float offsetX = 1;
+  inline bool has_offsetx() const;
+  inline void clear_offsetx();
+  static const int kOffsetXFieldNumber = 1;
+  inline float offsetx() const;
+  inline void set_offsetx(float value);
+  
+  // required float offsetY = 2;
+  inline bool has_offsety() const;
+  inline void clear_offsety();
+  static const int kOffsetYFieldNumber = 2;
+  inline float offsety() const;
+  inline void set_offsety(float value);
+  
+  // repeated float mvMatrix = 3;
+  inline int mvmatrix_size() const;
+  inline void clear_mvmatrix();
+  static const int kMvMatrixFieldNumber = 3;
+  inline float mvmatrix(int index) const;
+  inline void set_mvmatrix(int index, float value);
+  inline void add_mvmatrix(float value);
+  inline const ::google::protobuf::RepeatedField< float >&
+      mvmatrix() const;
+  inline ::google::protobuf::RepeatedField< float >*
+      mutable_mvmatrix();
+  
+  // required uint32 totalRects = 4;
+  inline bool has_totalrects() const;
+  inline void clear_totalrects();
+  static const int kTotalRectsFieldNumber = 4;
+  inline ::google::protobuf::uint32 totalrects() const;
+  inline void set_totalrects(::google::protobuf::uint32 value);
+  
+  // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5;
+  inline int layerrect_size() const;
+  inline void clear_layerrect();
+  static const int kLayerRectFieldNumber = 5;
+  inline const ::mozilla::layers::layerscope::DrawPacket_Rect& layerrect(int index) const;
+  inline ::mozilla::layers::layerscope::DrawPacket_Rect* mutable_layerrect(int index);
+  inline ::mozilla::layers::layerscope::DrawPacket_Rect* add_layerrect();
+  inline const ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >&
+      layerrect() const;
+  inline ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >*
+      mutable_layerrect();
+  
+  // required uint64 layerref = 6;
+  inline bool has_layerref() const;
+  inline void clear_layerref();
+  static const int kLayerrefFieldNumber = 6;
+  inline ::google::protobuf::uint64 layerref() const;
+  inline void set_layerref(::google::protobuf::uint64 value);
+  
+  // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.DrawPacket)
+ private:
+  inline void set_has_offsetx();
+  inline void clear_has_offsetx();
+  inline void set_has_offsety();
+  inline void clear_has_offsety();
+  inline void set_has_totalrects();
+  inline void clear_has_totalrects();
+  inline void set_has_layerref();
+  inline void clear_has_layerref();
+  
+  float offsetx_;
+  float offsety_;
+  ::google::protobuf::RepeatedField< float > mvmatrix_;
+  ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect > layerrect_;
+  ::google::protobuf::uint64 layerref_;
+  ::google::protobuf::uint32 totalrects_;
+  
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
+  
+  friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
+  friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
+  friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
+  
+  void InitAsDefaultInstance();
+  static DrawPacket* default_instance_;
+};
+// -------------------------------------------------------------------
+
 class Packet : public ::google::protobuf::MessageLite {
  public:
   Packet();
   virtual ~Packet();
   
   Packet(const Packet& from);
   
   inline Packet& operator=(const Packet& from) {
@@ -1354,16 +1583,17 @@ class Packet : public ::google::protobuf
   
   typedef Packet_DataType DataType;
   static const DataType FRAMESTART = Packet_DataType_FRAMESTART;
   static const DataType FRAMEEND = Packet_DataType_FRAMEEND;
   static const DataType COLOR = Packet_DataType_COLOR;
   static const DataType TEXTURE = Packet_DataType_TEXTURE;
   static const DataType LAYERS = Packet_DataType_LAYERS;
   static const DataType META = Packet_DataType_META;
+  static const DataType DRAW = Packet_DataType_DRAW;
   static inline bool DataType_IsValid(int value) {
     return Packet_DataType_IsValid(value);
   }
   static const DataType DataType_MIN =
     Packet_DataType_DataType_MIN;
   static const DataType DataType_MAX =
     Packet_DataType_DataType_MAX;
   static const int DataType_ARRAYSIZE =
@@ -1413,40 +1643,51 @@ class Packet : public ::google::protobuf
   // optional .mozilla.layers.layerscope.MetaPacket meta = 6;
   inline bool has_meta() const;
   inline void clear_meta();
   static const int kMetaFieldNumber = 6;
   inline const ::mozilla::layers::layerscope::MetaPacket& meta() const;
   inline ::mozilla::layers::layerscope::MetaPacket* mutable_meta();
   inline ::mozilla::layers::layerscope::MetaPacket* release_meta();
   
+  // optional .mozilla.layers.layerscope.DrawPacket draw = 7;
+  inline bool has_draw() const;
+  inline void clear_draw();
+  static const int kDrawFieldNumber = 7;
+  inline const ::mozilla::layers::layerscope::DrawPacket& draw() const;
+  inline ::mozilla::layers::layerscope::DrawPacket* mutable_draw();
+  inline ::mozilla::layers::layerscope::DrawPacket* release_draw();
+  
   // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.Packet)
  private:
   inline void set_has_type();
   inline void clear_has_type();
   inline void set_has_frame();
   inline void clear_has_frame();
   inline void set_has_color();
   inline void clear_has_color();
   inline void set_has_texture();
   inline void clear_has_texture();
   inline void set_has_layers();
   inline void clear_has_layers();
   inline void set_has_meta();
   inline void clear_has_meta();
+  inline void set_has_draw();
+  inline void clear_has_draw();
   
   ::mozilla::layers::layerscope::FramePacket* frame_;
   ::mozilla::layers::layerscope::ColorPacket* color_;
   ::mozilla::layers::layerscope::TexturePacket* texture_;
   ::mozilla::layers::layerscope::LayersPacket* layers_;
   ::mozilla::layers::layerscope::MetaPacket* meta_;
+  ::mozilla::layers::layerscope::DrawPacket* draw_;
   int type_;
   
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
+  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
   
   friend void  protobuf_AddDesc_LayerScopePacket_2eproto();
   friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
   friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
   
   void InitAsDefaultInstance();
   static Packet* default_instance_;
 };
@@ -2732,16 +2973,250 @@ inline bool MetaPacket::composedbyhwc() 
 }
 inline void MetaPacket::set_composedbyhwc(bool value) {
   set_has_composedbyhwc();
   composedbyhwc_ = value;
 }
 
 // -------------------------------------------------------------------
 
+// DrawPacket_Rect
+
+// required float x = 1;
+inline bool DrawPacket_Rect::has_x() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DrawPacket_Rect::set_has_x() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DrawPacket_Rect::clear_has_x() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void DrawPacket_Rect::clear_x() {
+  x_ = 0;
+  clear_has_x();
+}
+inline float DrawPacket_Rect::x() const {
+  return x_;
+}
+inline void DrawPacket_Rect::set_x(float value) {
+  set_has_x();
+  x_ = value;
+}
+
+// required float y = 2;
+inline bool DrawPacket_Rect::has_y() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DrawPacket_Rect::set_has_y() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void DrawPacket_Rect::clear_has_y() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void DrawPacket_Rect::clear_y() {
+  y_ = 0;
+  clear_has_y();
+}
+inline float DrawPacket_Rect::y() const {
+  return y_;
+}
+inline void DrawPacket_Rect::set_y(float value) {
+  set_has_y();
+  y_ = value;
+}
+
+// required float w = 3;
+inline bool DrawPacket_Rect::has_w() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void DrawPacket_Rect::set_has_w() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void DrawPacket_Rect::clear_has_w() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void DrawPacket_Rect::clear_w() {
+  w_ = 0;
+  clear_has_w();
+}
+inline float DrawPacket_Rect::w() const {
+  return w_;
+}
+inline void DrawPacket_Rect::set_w(float value) {
+  set_has_w();
+  w_ = value;
+}
+
+// required float h = 4;
+inline bool DrawPacket_Rect::has_h() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void DrawPacket_Rect::set_has_h() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void DrawPacket_Rect::clear_has_h() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void DrawPacket_Rect::clear_h() {
+  h_ = 0;
+  clear_has_h();
+}
+inline float DrawPacket_Rect::h() const {
+  return h_;
+}
+inline void DrawPacket_Rect::set_h(float value) {
+  set_has_h();
+  h_ = value;
+}
+
+// -------------------------------------------------------------------
+
+// DrawPacket
+
+// required float offsetX = 1;
+inline bool DrawPacket::has_offsetx() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DrawPacket::set_has_offsetx() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DrawPacket::clear_has_offsetx() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void DrawPacket::clear_offsetx() {
+  offsetx_ = 0;
+  clear_has_offsetx();
+}
+inline float DrawPacket::offsetx() const {
+  return offsetx_;
+}
+inline void DrawPacket::set_offsetx(float value) {
+  set_has_offsetx();
+  offsetx_ = value;
+}
+
+// required float offsetY = 2;
+inline bool DrawPacket::has_offsety() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DrawPacket::set_has_offsety() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void DrawPacket::clear_has_offsety() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void DrawPacket::clear_offsety() {
+  offsety_ = 0;
+  clear_has_offsety();
+}
+inline float DrawPacket::offsety() const {
+  return offsety_;
+}
+inline void DrawPacket::set_offsety(float value) {
+  set_has_offsety();
+  offsety_ = value;
+}
+
+// repeated float mvMatrix = 3;
+inline int DrawPacket::mvmatrix_size() const {
+  return mvmatrix_.size();
+}
+inline void DrawPacket::clear_mvmatrix() {
+  mvmatrix_.Clear();
+}
+inline float DrawPacket::mvmatrix(int index) const {
+  return mvmatrix_.Get(index);
+}
+inline void DrawPacket::set_mvmatrix(int index, float value) {
+  mvmatrix_.Set(index, value);
+}
+inline void DrawPacket::add_mvmatrix(float value) {
+  mvmatrix_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< float >&
+DrawPacket::mvmatrix() const {
+  return mvmatrix_;
+}
+inline ::google::protobuf::RepeatedField< float >*
+DrawPacket::mutable_mvmatrix() {
+  return &mvmatrix_;
+}
+
+// required uint32 totalRects = 4;
+inline bool DrawPacket::has_totalrects() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void DrawPacket::set_has_totalrects() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void DrawPacket::clear_has_totalrects() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void DrawPacket::clear_totalrects() {
+  totalrects_ = 0u;
+  clear_has_totalrects();
+}
+inline ::google::protobuf::uint32 DrawPacket::totalrects() const {
+  return totalrects_;
+}
+inline void DrawPacket::set_totalrects(::google::protobuf::uint32 value) {
+  set_has_totalrects();
+  totalrects_ = value;
+}
+
+// repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5;
+inline int DrawPacket::layerrect_size() const {
+  return layerrect_.size();
+}
+inline void DrawPacket::clear_layerrect() {
+  layerrect_.Clear();
+}
+inline const ::mozilla::layers::layerscope::DrawPacket_Rect& DrawPacket::layerrect(int index) const {
+  return layerrect_.Get(index);
+}
+inline ::mozilla::layers::layerscope::DrawPacket_Rect* DrawPacket::mutable_layerrect(int index) {
+  return layerrect_.Mutable(index);
+}
+inline ::mozilla::layers::layerscope::DrawPacket_Rect* DrawPacket::add_layerrect() {
+  return layerrect_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >&
+DrawPacket::layerrect() const {
+  return layerrect_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >*
+DrawPacket::mutable_layerrect() {
+  return &layerrect_;
+}
+
+// required uint64 layerref = 6;
+inline bool DrawPacket::has_layerref() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void DrawPacket::set_has_layerref() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void DrawPacket::clear_has_layerref() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void DrawPacket::clear_layerref() {
+  layerref_ = GOOGLE_ULONGLONG(0);
+  clear_has_layerref();
+}
+inline ::google::protobuf::uint64 DrawPacket::layerref() const {
+  return layerref_;
+}
+inline void DrawPacket::set_layerref(::google::protobuf::uint64 value) {
+  set_has_layerref();
+  layerref_ = value;
+}
+
+// -------------------------------------------------------------------
+
 // Packet
 
 // required .mozilla.layers.layerscope.Packet.DataType type = 1;
 inline bool Packet::has_type() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
 inline void Packet::set_has_type() {
   _has_bits_[0] |= 0x00000001u;
@@ -2902,16 +3377,45 @@ inline ::mozilla::layers::layerscope::Me
 }
 inline ::mozilla::layers::layerscope::MetaPacket* Packet::release_meta() {
   clear_has_meta();
   ::mozilla::layers::layerscope::MetaPacket* temp = meta_;
   meta_ = NULL;
   return temp;
 }
 
+// optional .mozilla.layers.layerscope.DrawPacket draw = 7;
+inline bool Packet::has_draw() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void Packet::set_has_draw() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void Packet::clear_has_draw() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void Packet::clear_draw() {
+  if (draw_ != NULL) draw_->::mozilla::layers::layerscope::DrawPacket::Clear();
+  clear_has_draw();
+}
+inline const ::mozilla::layers::layerscope::DrawPacket& Packet::draw() const {
+  return draw_ != NULL ? *draw_ : *default_instance_->draw_;
+}
+inline ::mozilla::layers::layerscope::DrawPacket* Packet::mutable_draw() {
+  set_has_draw();
+  if (draw_ == NULL) draw_ = new ::mozilla::layers::layerscope::DrawPacket;
+  return draw_;
+}
+inline ::mozilla::layers::layerscope::DrawPacket* Packet::release_draw() {
+  clear_has_draw();
+  ::mozilla::layers::layerscope::DrawPacket* temp = draw_;
+  draw_ = NULL;
+  return temp;
+}
+
 // -------------------------------------------------------------------
 
 // CommandPacket
 
 // required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1;
 inline bool CommandPacket::has_type() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
--- a/gfx/layers/protobuf/LayerScopePacket.proto
+++ b/gfx/layers/protobuf/LayerScopePacket.proto
@@ -112,34 +112,52 @@ message LayersPacket {
   }
   repeated Layer layer = 1;
 }
 
 message MetaPacket {
   optional bool composedByHwc = 1;
 }
 
+message DrawPacket {
+  message Rect {
+    required float x = 1;
+    required float y = 2;
+    required float w = 3;
+    required float h = 4;
+  }
+
+  required float  offsetX = 1;
+  required float  offsetY = 2;
+  repeated float  mvMatrix = 3;
+  required uint32 totalRects = 4;
+  repeated Rect   layerRect = 5;
+  required uint64 layerref = 6;
+}
+
 // We only need to use this Packet.
 // Other packet definitions are just type defines
 message Packet {
   enum DataType {
     FRAMESTART = 1;
     FRAMEEND = 2;
     COLOR = 3;
     TEXTURE = 4;
     LAYERS = 5;
     META = 6;
+    DRAW = 7;
   }
   required DataType type = 1;
 
   optional FramePacket frame = 2;
   optional ColorPacket color = 3;
   optional TexturePacket texture = 4;
   optional LayersPacket layers = 5;
   optional MetaPacket meta = 6;
+  optional DrawPacket draw = 7;
 }
 
 
 // ===============================
 // Client to Server messages
 // ===============================
 message CommandPacket {
   enum CmdType {