LCOV - code coverage report
Current view: top level - gfx/layers - LayerScope.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 30 761 3.9 %
Date: 2017-07-14 16:53:18 Functions: 9 148 6.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim:set ts=4 sw=4 sts=4 et: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
       8             : #include "LayerScope.h"
       9             : 
      10             : #include "nsAppRunner.h"
      11             : #include "Effects.h"
      12             : #include "mozilla/EndianUtils.h"
      13             : #include "mozilla/MathAlgorithms.h"
      14             : #include "mozilla/Preferences.h"
      15             : #include "mozilla/TimeStamp.h"
      16             : 
      17             : #include "TexturePoolOGL.h"
      18             : #include "mozilla/layers/CompositorOGL.h"
      19             : #include "mozilla/layers/CompositorThread.h"
      20             : #include "mozilla/layers/LayerManagerComposite.h"
      21             : #include "mozilla/layers/TextureHostOGL.h"
      22             : 
      23             : #include "gfxContext.h"
      24             : #include "gfxUtils.h"
      25             : #include "gfxPrefs.h"
      26             : #include "nsIWidget.h"
      27             : 
      28             : #include "GLContext.h"
      29             : #include "GLContextProvider.h"
      30             : #include "GLReadTexImageHelper.h"
      31             : 
      32             : #include "nsIServiceManager.h"
      33             : #include "nsIConsoleService.h"
      34             : 
      35             : #include <memory>
      36             : #include "mozilla/LinkedList.h"
      37             : #include "mozilla/Base64.h"
      38             : #include "mozilla/SHA1.h"
      39             : #include "mozilla/StaticPtr.h"
      40             : #include "nsThreadUtils.h"
      41             : #include "nsISocketTransport.h"
      42             : #include "nsIServerSocket.h"
      43             : #include "nsReadLine.h"
      44             : #include "nsNetCID.h"
      45             : #include "nsIOutputStream.h"
      46             : #include "nsIAsyncInputStream.h"
      47             : #include "nsIEventTarget.h"
      48             : #include "nsProxyRelease.h"
      49             : #include <list>
      50             : 
      51             : // Undo the damage done by mozzconf.h
      52             : #undef compress
      53             : #include "mozilla/Compression.h"
      54             : 
      55             : // Protocol buffer (generated automatically)
      56             : #include "protobuf/LayerScopePacket.pb.h"
      57             : 
      58             : namespace mozilla {
      59             : namespace layers {
      60             : 
      61             : using namespace mozilla::Compression;
      62             : using namespace mozilla::gfx;
      63             : using namespace mozilla::gl;
      64             : using namespace mozilla;
      65             : using namespace layerscope;
      66             : 
      67             : class DebugDataSender;
      68             : class DebugGLData;
      69             : 
      70             : /*
      71             :  * Manage Websocket connections
      72             :  */
      73             : class LayerScopeWebSocketManager {
      74             : public:
      75             :     LayerScopeWebSocketManager();
      76             :     ~LayerScopeWebSocketManager();
      77             : 
      78           0 :     void RemoveAllConnections()
      79             :     {
      80           0 :         MOZ_ASSERT(NS_IsMainThread());
      81             : 
      82           0 :         MutexAutoLock lock(mHandlerMutex);
      83           0 :         mHandlers.Clear();
      84           0 :     }
      85             : 
      86           0 :     bool WriteAll(void *ptr, uint32_t size)
      87             :     {
      88           0 :         for (int32_t i = mHandlers.Length() - 1; i >= 0; --i) {
      89           0 :             if (!mHandlers[i]->WriteToStream(ptr, size)) {
      90             :                 // Send failed, remove this handler
      91           0 :                 RemoveConnection(i);
      92             :             }
      93             :         }
      94             : 
      95           0 :         return true;
      96             :     }
      97             : 
      98           0 :     bool IsConnected()
      99             :     {
     100             :         // This funtion can be called in both main thread and compositor thread.
     101           0 :         MutexAutoLock lock(mHandlerMutex);
     102           0 :         return (mHandlers.Length() != 0) ? true : false;
     103             :     }
     104             : 
     105             :     void AppendDebugData(DebugGLData *aDebugData);
     106             :     void CleanDebugData();
     107             :     void DispatchDebugData();
     108             : 
     109             : private:
     110           0 :     void AddConnection(nsISocketTransport *aTransport)
     111             :     {
     112           0 :         MOZ_ASSERT(NS_IsMainThread());
     113           0 :         MOZ_ASSERT(aTransport);
     114             : 
     115           0 :         MutexAutoLock lock(mHandlerMutex);
     116             : 
     117           0 :         RefPtr<SocketHandler> temp = new SocketHandler();
     118           0 :         temp->OpenStream(aTransport);
     119           0 :         mHandlers.AppendElement(temp.get());
     120           0 :     }
     121             : 
     122           0 :     void RemoveConnection(uint32_t aIndex)
     123             :     {
     124             :         // TBD: RemoveConnection is executed on the compositor thread and
     125             :         // AddConntection is executed on the main thread, which might be
     126             :         // a problem if a user disconnect and connect readlly quickly at
     127             :         // viewer side.
     128             : 
     129             :         // We should dispatch RemoveConnection onto main thead.
     130           0 :         MOZ_ASSERT(aIndex < mHandlers.Length());
     131             : 
     132           0 :         MutexAutoLock lock(mHandlerMutex);
     133           0 :         mHandlers.RemoveElementAt(aIndex);
     134           0 :     }
     135             : 
     136             :     friend class SocketListener;
     137             :     class SocketListener : public nsIServerSocketListener
     138             :     {
     139             :     public:
     140             :        NS_DECL_THREADSAFE_ISUPPORTS
     141             : 
     142           0 :        SocketListener() { }
     143             : 
     144             :        /* nsIServerSocketListener */
     145             :        NS_IMETHOD OnSocketAccepted(nsIServerSocket *aServ,
     146             :                                    nsISocketTransport *aTransport) override;
     147           0 :        NS_IMETHOD OnStopListening(nsIServerSocket *aServ,
     148             :                                   nsresult aStatus) override
     149             :        {
     150           0 :            return NS_OK;
     151             :        }
     152             :     private:
     153           0 :        virtual ~SocketListener() { }
     154             :     };
     155             : 
     156             :     /*
     157             :      * This class handle websocket protocol which included
     158             :      * handshake and data frame's header
     159             :      */
     160             :     class SocketHandler : public nsIInputStreamCallback {
     161             :     public:
     162             :         NS_DECL_THREADSAFE_ISUPPORTS
     163             : 
     164           0 :         SocketHandler()
     165           0 :             : mState(NoHandshake)
     166           0 :             , mConnected(false)
     167           0 :         { }
     168             : 
     169             :         void OpenStream(nsISocketTransport* aTransport);
     170             :         bool WriteToStream(void *aPtr, uint32_t aSize);
     171             : 
     172             :         // nsIInputStreamCallback
     173             :         NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *aStream) override;
     174             : 
     175             :     private:
     176           0 :         virtual ~SocketHandler() { CloseConnection(); }
     177             : 
     178             :         void ReadInputStreamData(nsTArray<nsCString>& aProtocolString);
     179             :         bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString);
     180             :         void ApplyMask(uint32_t aMask, uint8_t *aData, uint64_t aLen);
     181             :         bool HandleDataFrame(uint8_t *aData, uint32_t aSize);
     182             :         void CloseConnection();
     183             : 
     184             :         nsresult HandleSocketMessage(nsIAsyncInputStream *aStream);
     185             :         nsresult ProcessInput(uint8_t *aBuffer, uint32_t aCount);
     186             : 
     187             :     private:
     188             :         enum SocketStateType {
     189             :             NoHandshake,
     190             :             HandshakeSuccess,
     191             :             HandshakeFailed
     192             :         };
     193             :         SocketStateType               mState;
     194             : 
     195             :         nsCOMPtr<nsIOutputStream>     mOutputStream;
     196             :         nsCOMPtr<nsIAsyncInputStream> mInputStream;
     197             :         nsCOMPtr<nsISocketTransport>  mTransport;
     198             :         bool                          mConnected;
     199             :     };
     200             : 
     201             :     nsTArray<RefPtr<SocketHandler> > mHandlers;
     202             :     nsCOMPtr<nsIThread>                   mDebugSenderThread;
     203             :     RefPtr<DebugDataSender>             mCurrentSender;
     204             :     nsCOMPtr<nsIServerSocket>             mServerSocket;
     205             : 
     206             :     // Keep mHandlers accessing thread safe.
     207             :     Mutex mHandlerMutex;
     208             : };
     209             : 
     210           0 : NS_IMPL_ISUPPORTS(LayerScopeWebSocketManager::SocketListener,
     211             :                   nsIServerSocketListener);
     212           0 : NS_IMPL_ISUPPORTS(LayerScopeWebSocketManager::SocketHandler,
     213             :                   nsIInputStreamCallback);
     214             : 
     215           0 : class DrawSession {
     216             : public:
     217           0 :     DrawSession()
     218           0 :       : mOffsetX(0.0)
     219             :       , mOffsetY(0.0)
     220           0 :       , mRects(0)
     221           0 :     { }
     222             : 
     223             :     float mOffsetX;
     224             :     float mOffsetY;
     225             :     gfx::Matrix4x4 mMVMatrix;
     226             :     size_t mRects;
     227             :     gfx::Rect mLayerRects[4];
     228             :     gfx::Rect mTextureRects[4];
     229             :     std::list<GLuint> mTexIDs;
     230             : };
     231             : 
     232           0 : class ContentMonitor {
     233             : public:
     234             :     using THArray = nsTArray<const TextureHost *>;
     235             : 
     236             :     // Notify the content of a TextureHost was changed.
     237           0 :     void SetChangedHost(const TextureHost* host) {
     238           0 :         if (THArray::NoIndex == mChangedHosts.IndexOf(host)) {
     239           0 :             mChangedHosts.AppendElement(host);
     240             :         }
     241           0 :     }
     242             : 
     243             :     // Clear changed flag of a host.
     244             :     void ClearChangedHost(const TextureHost* host) {
     245             :         if (THArray::NoIndex != mChangedHosts.IndexOf(host)) {
     246             :           mChangedHosts.RemoveElement(host);
     247             :         }
     248             :     }
     249             : 
     250             :     // Return true iff host is a new one or the content of it had been changed.
     251             :     bool IsChangedOrNew(const TextureHost* host) {
     252             :         if (THArray::NoIndex == mSeenHosts.IndexOf(host)) {
     253             :             mSeenHosts.AppendElement(host);
     254             :             return true;
     255             :         }
     256             : 
     257             :         if (decltype(mChangedHosts)::NoIndex != mChangedHosts.IndexOf(host)) {
     258             :             return true;
     259             :         }
     260             : 
     261             :         return false;
     262             :     }
     263             : 
     264           0 :     void Empty() {
     265           0 :         mSeenHosts.SetLength(0);
     266           0 :         mChangedHosts.SetLength(0);
     267           0 :     }
     268             : private:
     269             :     THArray mSeenHosts;
     270             :     THArray mChangedHosts;
     271             : };
     272             : 
     273             : /*
     274             :  * Hold all singleton objects used by LayerScope.
     275             :  */
     276           0 : class LayerScopeManager
     277             : {
     278             : public:
     279           0 :     void CreateServerSocket()
     280             :     {
     281             :         //  WebSocketManager must be created on the main thread.
     282           0 :         if (NS_IsMainThread()) {
     283           0 :             mWebSocketManager = mozilla::MakeUnique<LayerScopeWebSocketManager>();
     284             :         } else {
     285             :             // Dispatch creation to main thread, and make sure we
     286             :             // dispatch this only once after booting
     287             :             static bool dispatched = false;
     288           0 :             if (dispatched) {
     289           0 :                 return;
     290             :             }
     291             : 
     292             :             DebugOnly<nsresult> rv =
     293           0 :               NS_DispatchToMainThread(new CreateServerSocketRunnable(this));
     294           0 :             MOZ_ASSERT(NS_SUCCEEDED(rv),
     295             :                   "Failed to dispatch WebSocket Creation to main thread");
     296           0 :             dispatched = true;
     297             :         }
     298             :     }
     299             : 
     300           0 :     void DestroyServerSocket()
     301             :     {
     302             :         // Destroy Web Server Socket
     303           0 :         if (mWebSocketManager) {
     304           0 :             mWebSocketManager->RemoveAllConnections();
     305             :         }
     306           0 :     }
     307             : 
     308           0 :     LayerScopeWebSocketManager* GetSocketManager()
     309             :     {
     310           0 :         return mWebSocketManager.get();
     311             :     }
     312             : 
     313           0 :     ContentMonitor* GetContentMonitor()
     314             :     {
     315           0 :         if (!mContentMonitor.get()) {
     316           0 :             mContentMonitor = mozilla::MakeUnique<ContentMonitor>();
     317             :         }
     318             : 
     319           0 :         return mContentMonitor.get();
     320             :     }
     321             : 
     322           0 :     void NewDrawSession() {
     323           0 :         mSession = mozilla::MakeUnique<DrawSession>();
     324           0 :     }
     325             : 
     326           0 :     DrawSession& CurrentSession() {
     327           0 :         return *mSession;
     328             :     }
     329             : 
     330           1 :     void SetPixelScale(double scale) {
     331           1 :         mScale = scale;
     332           1 :     }
     333             : 
     334           0 :     double GetPixelScale() const {
     335           0 :         return mScale;
     336             :     }
     337             : 
     338           3 :     LayerScopeManager()
     339           3 :         : mScale(1.0)
     340             :     {
     341           3 :     }
     342             : private:
     343             :     friend class CreateServerSocketRunnable;
     344           0 :     class CreateServerSocketRunnable : public Runnable
     345             :     {
     346             :     public:
     347           0 :       explicit CreateServerSocketRunnable(LayerScopeManager* aLayerScopeManager)
     348           0 :         : Runnable("layers::LayerScopeManager::CreateServerSocketRunnable")
     349           0 :         , mLayerScopeManager(aLayerScopeManager)
     350             :       {
     351           0 :         }
     352           0 :         NS_IMETHOD Run() override {
     353           0 :             mLayerScopeManager->mWebSocketManager =
     354           0 :                 mozilla::MakeUnique<LayerScopeWebSocketManager>();
     355           0 :             return NS_OK;
     356             :         }
     357             :     private:
     358             :         LayerScopeManager* mLayerScopeManager;
     359             :     };
     360             : 
     361             :     mozilla::UniquePtr<LayerScopeWebSocketManager> mWebSocketManager;
     362             :     mozilla::UniquePtr<DrawSession> mSession;
     363             :     mozilla::UniquePtr<ContentMonitor> mContentMonitor;
     364             :     double mScale;
     365             : };
     366             : 
     367           3 : LayerScopeManager gLayerScopeManager;
     368             : 
     369             : /*
     370             :  * The static helper functions that set data into the packet
     371             :  * 1. DumpRect
     372             :  * 2. DumpFilter
     373             :  */
     374             : template<typename T>
     375           0 : static void DumpRect(T* aPacketRect, const Rect& aRect)
     376             : {
     377           0 :     aPacketRect->set_x(aRect.x);
     378           0 :     aPacketRect->set_y(aRect.y);
     379           0 :     aPacketRect->set_w(aRect.width);
     380           0 :     aPacketRect->set_h(aRect.height);
     381           0 : }
     382             : 
     383           0 : static void DumpFilter(TexturePacket* aTexturePacket,
     384             :                        const SamplingFilter aSamplingFilter)
     385             : {
     386           0 :     switch (aSamplingFilter) {
     387             :         case SamplingFilter::GOOD:
     388           0 :             aTexturePacket->set_mfilter(TexturePacket::GOOD);
     389           0 :             break;
     390             :         case SamplingFilter::LINEAR:
     391           0 :             aTexturePacket->set_mfilter(TexturePacket::LINEAR);
     392           0 :             break;
     393             :         case SamplingFilter::POINT:
     394           0 :             aTexturePacket->set_mfilter(TexturePacket::POINT);
     395           0 :             break;
     396             :         default:
     397           0 :             MOZ_ASSERT(false, "Can't dump unexpected mSamplingFilter to texture packet!");
     398             :             break;
     399             :     }
     400           0 : }
     401             : 
     402             : /*
     403             :  * DebugGLData is the base class of
     404             :  * 1. DebugGLFrameStatusData (Frame start/end packet)
     405             :  * 2. DebugGLColorData (Color data packet)
     406             :  * 3. DebugGLTextureData (Texture data packet)
     407             :  * 4. DebugGLLayersData (Layers Tree data packet)
     408             :  * 5. DebugGLMetaData (Meta data packet)
     409             :  */
     410             : class DebugGLData: public LinkedListElement<DebugGLData> {
     411             : public:
     412           0 :     explicit DebugGLData(Packet::DataType aDataType)
     413           0 :         : mDataType(aDataType)
     414           0 :     { }
     415             : 
     416           0 :     virtual ~DebugGLData() { }
     417             : 
     418             :     virtual bool Write() = 0;
     419             : 
     420             : protected:
     421           0 :     static bool WriteToStream(Packet& aPacket) {
     422           0 :         if (!gLayerScopeManager.GetSocketManager())
     423           0 :             return true;
     424             : 
     425           0 :         uint32_t size = aPacket.ByteSize();
     426           0 :         auto data = MakeUnique<uint8_t[]>(size);
     427           0 :         aPacket.SerializeToArray(data.get(), size);
     428           0 :         return gLayerScopeManager.GetSocketManager()->WriteAll(data.get(), size);
     429             :     }
     430             : 
     431             :     Packet::DataType mDataType;
     432             : };
     433             : 
     434           0 : class DebugGLFrameStatusData final: public DebugGLData
     435             : {
     436             : public:
     437           0 :     DebugGLFrameStatusData(Packet::DataType aDataType,
     438             :                            int64_t aValue)
     439           0 :         : DebugGLData(aDataType),
     440           0 :           mFrameStamp(aValue)
     441           0 :     { }
     442             : 
     443           0 :     explicit DebugGLFrameStatusData(Packet::DataType aDataType)
     444           0 :         : DebugGLData(aDataType),
     445           0 :           mFrameStamp(0)
     446           0 :     { }
     447             : 
     448           0 :     virtual bool Write() override {
     449           0 :         Packet packet;
     450           0 :         packet.set_type(mDataType);
     451             : 
     452           0 :         FramePacket* fp = packet.mutable_frame();
     453           0 :         fp->set_value(static_cast<uint64_t>(mFrameStamp));
     454             : 
     455           0 :         fp->set_scale(gLayerScopeManager.GetPixelScale());
     456             : 
     457           0 :         return WriteToStream(packet);
     458             :     }
     459             : 
     460             : protected:
     461             :     int64_t mFrameStamp;
     462             : };
     463             : 
     464           0 : class DebugGLTextureData final: public DebugGLData {
     465             : public:
     466           0 :     DebugGLTextureData(GLContext* cx,
     467             :                        void* layerRef,
     468             :                        GLenum target,
     469             :                        GLuint name,
     470             :                        DataSourceSurface* img,
     471             :                        bool aIsMask,
     472             :                        UniquePtr<Packet> aPacket)
     473           0 :         : DebugGLData(Packet::TEXTURE),
     474             :           mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
     475             :           mTarget(target),
     476             :           mName(name),
     477             :           mContextAddress(reinterpret_cast<intptr_t>(cx)),
     478             :           mDatasize(0),
     479             :           mIsMask(aIsMask),
     480           0 :           mPacket(Move(aPacket))
     481             :     {
     482             :         // pre-packing
     483             :         // DataSourceSurface may have locked buffer,
     484             :         // so we should compress now, and then it could
     485             :         // be unlocked outside.
     486           0 :         pack(img);
     487           0 :     }
     488             : 
     489           0 :     virtual bool Write() override {
     490           0 :         return WriteToStream(*mPacket);
     491             :     }
     492             : 
     493             : private:
     494           0 :     void pack(DataSourceSurface* aImage) {
     495           0 :         mPacket->set_type(mDataType);
     496             : 
     497           0 :         TexturePacket* tp = mPacket->mutable_texture();
     498           0 :         tp->set_layerref(mLayerRef);
     499           0 :         tp->set_name(mName);
     500           0 :         tp->set_target(mTarget);
     501           0 :         tp->set_dataformat(LOCAL_GL_RGBA);
     502           0 :         tp->set_glcontext(static_cast<uint64_t>(mContextAddress));
     503           0 :         tp->set_ismask(mIsMask);
     504             : 
     505           0 :         if (aImage) {
     506           0 :             tp->set_width(aImage->GetSize().width);
     507           0 :             tp->set_height(aImage->GetSize().height);
     508           0 :             tp->set_stride(aImage->Stride());
     509             : 
     510           0 :             mDatasize = aImage->GetSize().height * aImage->Stride();
     511             : 
     512           0 :             auto compresseddata = MakeUnique<char[]>(LZ4::maxCompressedSize(mDatasize));
     513           0 :             if (compresseddata) {
     514           0 :                 int ndatasize = LZ4::compress((char*)aImage->GetData(),
     515           0 :                                               mDatasize,
     516           0 :                                               compresseddata.get());
     517           0 :                 if (ndatasize > 0) {
     518           0 :                     mDatasize = ndatasize;
     519           0 :                     tp->set_dataformat((1 << 16 | tp->dataformat()));
     520           0 :                     tp->set_data(compresseddata.get(), mDatasize);
     521             :                 } else {
     522           0 :                     NS_WARNING("Compress data failed");
     523           0 :                     tp->set_data(aImage->GetData(), mDatasize);
     524             :                 }
     525             :             } else {
     526           0 :                 NS_WARNING("Couldn't new compressed data.");
     527           0 :                 tp->set_data(aImage->GetData(), mDatasize);
     528             :             }
     529             :         } else {
     530           0 :             tp->set_width(0);
     531           0 :             tp->set_height(0);
     532           0 :             tp->set_stride(0);
     533             :         }
     534           0 :     }
     535             : 
     536             : protected:
     537             :     uint64_t mLayerRef;
     538             :     GLenum mTarget;
     539             :     GLuint mName;
     540             :     intptr_t mContextAddress;
     541             :     uint32_t mDatasize;
     542             :     bool mIsMask;
     543             : 
     544             :     // Packet data
     545             :     UniquePtr<Packet> mPacket;
     546             : };
     547             : 
     548           0 : class DebugGLColorData final: public DebugGLData {
     549             : public:
     550           0 :     DebugGLColorData(void* layerRef,
     551             :                      const Color& color,
     552             :                      int width,
     553             :                      int height)
     554           0 :         : DebugGLData(Packet::COLOR),
     555             :           mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
     556           0 :           mColor(color.ToABGR()),
     557           0 :           mSize(width, height)
     558           0 :     { }
     559             : 
     560           0 :     virtual bool Write() override {
     561           0 :         Packet packet;
     562           0 :         packet.set_type(mDataType);
     563             : 
     564           0 :         ColorPacket* cp = packet.mutable_color();
     565           0 :         cp->set_layerref(mLayerRef);
     566           0 :         cp->set_color(mColor);
     567           0 :         cp->set_width(mSize.width);
     568           0 :         cp->set_height(mSize.height);
     569             : 
     570           0 :         return WriteToStream(packet);
     571             :     }
     572             : 
     573             : protected:
     574             :     uint64_t mLayerRef;
     575             :     uint32_t mColor;
     576             :     IntSize mSize;
     577             : };
     578             : 
     579           0 : class DebugGLLayersData final: public DebugGLData {
     580             : public:
     581           0 :     explicit DebugGLLayersData(UniquePtr<Packet> aPacket)
     582           0 :         : DebugGLData(Packet::LAYERS),
     583           0 :           mPacket(Move(aPacket))
     584           0 :     { }
     585             : 
     586           0 :     virtual bool Write() override {
     587           0 :         mPacket->set_type(mDataType);
     588           0 :         return WriteToStream(*mPacket);
     589             :     }
     590             : 
     591             : protected:
     592             :     UniquePtr<Packet> mPacket;
     593             : };
     594             : 
     595           0 : class DebugGLMetaData final: public DebugGLData
     596             : {
     597             : public:
     598           0 :     DebugGLMetaData(Packet::DataType aDataType,
     599             :                     bool aValue)
     600           0 :         : DebugGLData(aDataType),
     601           0 :           mComposedByHwc(aValue)
     602           0 :     { }
     603             : 
     604             :     explicit DebugGLMetaData(Packet::DataType aDataType)
     605             :         : DebugGLData(aDataType),
     606             :           mComposedByHwc(false)
     607             :     { }
     608             : 
     609           0 :     virtual bool Write() override {
     610           0 :         Packet packet;
     611           0 :         packet.set_type(mDataType);
     612             : 
     613           0 :         MetaPacket* mp = packet.mutable_meta();
     614           0 :         mp->set_composedbyhwc(mComposedByHwc);
     615             : 
     616           0 :         return WriteToStream(packet);
     617             :     }
     618             : 
     619             : protected:
     620             :     bool mComposedByHwc;
     621             : };
     622             : 
     623           0 : class DebugGLDrawData final: public DebugGLData {
     624             : public:
     625           0 :     DebugGLDrawData(float aOffsetX,
     626             :                     float aOffsetY,
     627             :                     const gfx::Matrix4x4& aMVMatrix,
     628             :                     size_t aRects,
     629             :                     const gfx::Rect* aLayerRects,
     630             :                     const gfx::Rect* aTextureRects,
     631             :                     const std::list<GLuint> aTexIDs,
     632             :                     void* aLayerRef)
     633           0 :         : DebugGLData(Packet::DRAW),
     634             :           mOffsetX(aOffsetX),
     635             :           mOffsetY(aOffsetY),
     636             :           mMVMatrix(aMVMatrix),
     637             :           mRects(aRects),
     638             :           mTexIDs(aTexIDs),
     639           0 :           mLayerRef(reinterpret_cast<uint64_t>(aLayerRef))
     640             :     {
     641           0 :         for (size_t i = 0; i < mRects; i++){
     642           0 :             mLayerRects[i] = aLayerRects[i];
     643           0 :             mTextureRects[i] = aTextureRects[i];
     644             :         }
     645           0 :     }
     646             : 
     647           0 :     virtual bool Write() override {
     648           0 :         Packet packet;
     649           0 :         packet.set_type(mDataType);
     650             : 
     651           0 :         DrawPacket* dp = packet.mutable_draw();
     652           0 :         dp->set_layerref(mLayerRef);
     653             : 
     654           0 :         dp->set_offsetx(mOffsetX);
     655           0 :         dp->set_offsety(mOffsetY);
     656             : 
     657           0 :         auto element = reinterpret_cast<Float *>(&mMVMatrix);
     658           0 :         for (int i = 0; i < 16; i++) {
     659           0 :           dp->add_mvmatrix(*element++);
     660             :         }
     661           0 :         dp->set_totalrects(mRects);
     662             : 
     663           0 :         MOZ_ASSERT(mRects > 0 && mRects < 4);
     664           0 :         for (size_t i = 0; i < mRects; i++) {
     665             :             // Vertex
     666           0 :             DumpRect(dp->add_layerrect(), mLayerRects[i]);
     667             :             // UV
     668           0 :             DumpRect(dp->add_texturerect(), mTextureRects[i]);
     669             :         }
     670             : 
     671           0 :         for (GLuint texId: mTexIDs) {
     672           0 :             dp->add_texids(texId);
     673             :         }
     674             : 
     675           0 :         return WriteToStream(packet);
     676             :     }
     677             : 
     678             : protected:
     679             :     float mOffsetX;
     680             :     float mOffsetY;
     681             :     gfx::Matrix4x4 mMVMatrix;
     682             :     size_t mRects;
     683             :     gfx::Rect mLayerRects[4];
     684             :     gfx::Rect mTextureRects[4];
     685             :     std::list<GLuint> mTexIDs;
     686             :     uint64_t mLayerRef;
     687             : };
     688             : 
     689             : class DebugDataSender
     690             : {
     691             : public:
     692           0 :    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DebugDataSender)
     693             : 
     694             :     // Append a DebugData into mList on mThread
     695             :     class AppendTask: public nsIRunnable
     696             :     {
     697             :     public:
     698             :         NS_DECL_THREADSAFE_ISUPPORTS
     699             : 
     700           0 :         AppendTask(DebugDataSender *host, DebugGLData *d)
     701           0 :             : mData(d),
     702           0 :               mHost(host)
     703           0 :         {  }
     704             : 
     705           0 :         NS_IMETHOD Run() override {
     706           0 :             mHost->mList.insertBack(mData);
     707           0 :             return NS_OK;
     708             :         }
     709             : 
     710             :     private:
     711           0 :         virtual ~AppendTask() { }
     712             : 
     713             :         DebugGLData *mData;
     714             :         // Keep a strong reference to DebugDataSender to prevent this object
     715             :         // accessing mHost on mThread, when it's been destroyed on the main
     716             :         // thread.
     717             :         RefPtr<DebugDataSender> mHost;
     718             :     };
     719             : 
     720             :     // Clear all DebugData in mList on mThead.
     721             :     class ClearTask: public nsIRunnable
     722             :     {
     723             :     public:
     724             :         NS_DECL_THREADSAFE_ISUPPORTS
     725           0 :         explicit ClearTask(DebugDataSender *host)
     726           0 :             : mHost(host)
     727           0 :         {  }
     728             : 
     729           0 :         NS_IMETHOD Run() override {
     730           0 :             mHost->RemoveData();
     731           0 :             return NS_OK;
     732             :         }
     733             : 
     734             :     private:
     735           0 :         virtual ~ClearTask() { }
     736             : 
     737             :         RefPtr<DebugDataSender> mHost;
     738             :     };
     739             : 
     740             :     // Send all DebugData in mList via websocket, and then, clean up
     741             :     // mList on mThread.
     742             :     class SendTask: public nsIRunnable
     743             :     {
     744             :     public:
     745             :         NS_DECL_THREADSAFE_ISUPPORTS
     746             : 
     747           0 :         explicit SendTask(DebugDataSender *host)
     748           0 :             : mHost(host)
     749           0 :         {  }
     750             : 
     751           0 :         NS_IMETHOD Run() override {
     752             :             // Sendout all appended debug data.
     753           0 :             DebugGLData *d = nullptr;
     754           0 :             while ((d = mHost->mList.popFirst()) != nullptr) {
     755           0 :                 UniquePtr<DebugGLData> cleaner(d);
     756           0 :                 if (!d->Write()) {
     757           0 :                     gLayerScopeManager.DestroyServerSocket();
     758           0 :                     break;
     759             :                 }
     760             :             }
     761             : 
     762             :             // Cleanup.
     763           0 :             mHost->RemoveData();
     764           0 :             return NS_OK;
     765             :         }
     766             :     private:
     767           0 :         virtual ~SendTask() { }
     768             : 
     769             :         RefPtr<DebugDataSender> mHost;
     770             :     };
     771             : 
     772           0 :     explicit DebugDataSender(nsIThread *thread)
     773           0 :         : mThread(thread)
     774           0 :     {  }
     775             : 
     776           0 :     void Append(DebugGLData *d) {
     777           0 :         mThread->Dispatch(new AppendTask(this, d), NS_DISPATCH_NORMAL);
     778           0 :     }
     779             : 
     780           0 :     void Cleanup() {
     781           0 :         mThread->Dispatch(new ClearTask(this), NS_DISPATCH_NORMAL);
     782           0 :     }
     783             : 
     784           0 :     void Send() {
     785           0 :         mThread->Dispatch(new SendTask(this), NS_DISPATCH_NORMAL);
     786           0 :     }
     787             : 
     788             : protected:
     789           0 :     virtual ~DebugDataSender() {}
     790           0 :     void RemoveData() {
     791           0 :         MOZ_ASSERT(mThread->SerialEventTarget()->IsOnCurrentThread());
     792           0 :         if (mList.isEmpty())
     793           0 :             return;
     794             : 
     795             :         DebugGLData *d;
     796           0 :         while ((d = mList.popFirst()) != nullptr)
     797           0 :             delete d;
     798             :     }
     799             : 
     800             :     // We can only modify or aceess mList on mThread.
     801             :     LinkedList<DebugGLData> mList;
     802             :     nsCOMPtr<nsIThread>     mThread;
     803             : };
     804             : 
     805           0 : NS_IMPL_ISUPPORTS(DebugDataSender::AppendTask, nsIRunnable);
     806           0 : NS_IMPL_ISUPPORTS(DebugDataSender::ClearTask, nsIRunnable);
     807           0 : NS_IMPL_ISUPPORTS(DebugDataSender::SendTask, nsIRunnable);
     808             : 
     809             : 
     810             : /*
     811             :  * LayerScope SendXXX Structure
     812             :  * 1. SendLayer
     813             :  * 2. SendEffectChain
     814             :  *   1. SendTexturedEffect
     815             :  *      -> SendTextureSource
     816             :  *   2. SendMaskEffect
     817             :  *      -> SendTextureSource
     818             :  *   3. SendYCbCrEffect
     819             :  *      -> SendTextureSource
     820             :  *   4. SendColor
     821             :  */
     822             : class SenderHelper
     823             : {
     824             : // Sender public APIs
     825             : public:
     826             :     static void SendLayer(LayerComposite* aLayer,
     827             :                           int aWidth,
     828             :                           int aHeight);
     829             : 
     830             :     static void SendEffectChain(gl::GLContext* aGLContext,
     831             :                                 const EffectChain& aEffectChain,
     832             :                                 int aWidth = 0,
     833             :                                 int aHeight = 0);
     834             : 
     835           0 :     static void SetLayersTreeSendable(bool aSet) {sLayersTreeSendable = aSet;}
     836             : 
     837           0 :     static void SetLayersBufferSendable(bool aSet) {sLayersBufferSendable = aSet;}
     838             : 
     839           0 :     static bool GetLayersTreeSendable() {return sLayersTreeSendable;}
     840             : 
     841             :     static void ClearSentTextureIds();
     842             : 
     843             : // Sender private functions
     844             : private:
     845             :     static void SendColor(void* aLayerRef,
     846             :                           const Color& aColor,
     847             :                           int aWidth,
     848             :                           int aHeight);
     849             :     static void SendTextureSource(GLContext* aGLContext,
     850             :                                   void* aLayerRef,
     851             :                                   TextureSourceOGL* aSource,
     852             :                                   bool aFlipY,
     853             :                                   bool aIsMask,
     854             :                                   UniquePtr<Packet> aPacket);
     855             :     static void SetAndSendTexture(GLContext* aGLContext,
     856             :                                   void* aLayerRef,
     857             :                                   TextureSourceOGL* aSource,
     858             :                                   const TexturedEffect* aEffect);
     859             :     static void SendTexturedEffect(GLContext* aGLContext,
     860             :                                    void* aLayerRef,
     861             :                                    const TexturedEffect* aEffect);
     862             :     static void SendMaskEffect(GLContext* aGLContext,
     863             :                                    void* aLayerRef,
     864             :                                    const EffectMask* aEffect);
     865             :     static void SendYCbCrEffect(GLContext* aGLContext,
     866             :                                 void* aLayerRef,
     867             :                                 const EffectYCbCr* aEffect);
     868             :     static GLuint GetTextureID(GLContext* aGLContext,
     869             :                                TextureSourceOGL* aSource);
     870             :     static bool HasTextureIdBeenSent(GLuint aTextureId);
     871             : // Data fields
     872             : private:
     873             :     static bool sLayersTreeSendable;
     874             :     static bool sLayersBufferSendable;
     875             :     static std::vector<GLuint> sSentTextureIds;
     876             : };
     877             : 
     878             : bool SenderHelper::sLayersTreeSendable = true;
     879             : bool SenderHelper::sLayersBufferSendable = true;
     880           3 : std::vector<GLuint> SenderHelper::sSentTextureIds;
     881             : 
     882             : 
     883             : // ----------------------------------------------
     884             : // SenderHelper implementation
     885             : // ----------------------------------------------
     886             : void
     887           0 : SenderHelper::ClearSentTextureIds()
     888             : {
     889           0 :     sSentTextureIds.clear();
     890           0 : }
     891             : 
     892             : bool
     893           0 : SenderHelper::HasTextureIdBeenSent(GLuint aTextureId)
     894             : {
     895           0 :     return std::find(sSentTextureIds.begin(), sSentTextureIds.end(), aTextureId) != sSentTextureIds.end();
     896             : }
     897             : 
     898             : void
     899           0 : SenderHelper::SendLayer(LayerComposite* aLayer,
     900             :                         int aWidth,
     901             :                         int aHeight)
     902             : {
     903           0 :     MOZ_ASSERT(aLayer && aLayer->GetLayer());
     904           0 :     if (!aLayer || !aLayer->GetLayer()) {
     905           0 :         return;
     906             :     }
     907             : 
     908           0 :     switch (aLayer->GetLayer()->GetType()) {
     909             :         case Layer::TYPE_COLOR: {
     910           0 :             EffectChain effect;
     911           0 :             aLayer->GenEffectChain(effect);
     912             : 
     913           0 :             LayerScope::DrawBegin();
     914           0 :             LayerScope::DrawEnd(nullptr, effect, aWidth, aHeight);
     915           0 :             break;
     916             :         }
     917             :         case Layer::TYPE_IMAGE:
     918             :         case Layer::TYPE_CANVAS:
     919             :         case Layer::TYPE_PAINTED: {
     920             :             // Get CompositableHost and Compositor
     921           0 :             CompositableHost* compHost = aLayer->GetCompositableHost();
     922           0 :             TextureSourceProvider* provider = compHost->GetTextureSourceProvider();
     923           0 :             Compositor* comp = provider->AsCompositor();
     924             :             // Send EffectChain only for CompositorOGL
     925           0 :             if (LayersBackend::LAYERS_OPENGL == comp->GetBackendType()) {
     926           0 :                 CompositorOGL* compOGL = comp->AsCompositorOGL();
     927           0 :                 EffectChain effect;
     928             :                 // Generate primary effect (lock and gen)
     929           0 :                 AutoLockCompositableHost lock(compHost);
     930           0 :                 aLayer->GenEffectChain(effect);
     931             : 
     932           0 :                 LayerScope::DrawBegin();
     933           0 :                 LayerScope::DrawEnd(compOGL->gl(), effect, aWidth, aHeight);
     934             :             }
     935           0 :             break;
     936             :         }
     937             :         case Layer::TYPE_CONTAINER:
     938             :         default:
     939           0 :             break;
     940             :     }
     941             : }
     942             : 
     943             : void
     944           0 : SenderHelper::SendColor(void* aLayerRef,
     945             :                         const Color& aColor,
     946             :                         int aWidth,
     947             :                         int aHeight)
     948             : {
     949           0 :     gLayerScopeManager.GetSocketManager()->AppendDebugData(
     950           0 :         new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
     951           0 : }
     952             : 
     953             : GLuint
     954           0 : SenderHelper::GetTextureID(GLContext* aGLContext,
     955             :                            TextureSourceOGL* aSource) {
     956           0 :     GLenum textureTarget = aSource->GetTextureTarget();
     957           0 :     aSource->BindTexture(LOCAL_GL_TEXTURE0, gfx::SamplingFilter::LINEAR);
     958             : 
     959           0 :     GLuint texID = 0;
     960             :     // This is horrid hack. It assumes that aGLContext matches the context
     961             :     // aSource has bound to.
     962           0 :     if (textureTarget == LOCAL_GL_TEXTURE_2D) {
     963           0 :         aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &texID);
     964           0 :     } else if (textureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
     965           0 :         aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &texID);
     966           0 :     } else if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
     967           0 :         aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &texID);
     968             :     }
     969             : 
     970           0 :     return texID;
     971             : }
     972             : 
     973             : void
     974           0 : SenderHelper::SendTextureSource(GLContext* aGLContext,
     975             :                                 void* aLayerRef,
     976             :                                 TextureSourceOGL* aSource,
     977             :                                 bool aFlipY,
     978             :                                 bool aIsMask,
     979             :                                 UniquePtr<Packet> aPacket)
     980             : {
     981           0 :     MOZ_ASSERT(aGLContext);
     982           0 :     if (!aGLContext) {
     983           0 :         return;
     984             :     }
     985           0 :     GLuint texID = GetTextureID(aGLContext, aSource);
     986           0 :     if (HasTextureIdBeenSent(texID)) {
     987           0 :         return;
     988             :     }
     989             : 
     990           0 :     GLenum textureTarget = aSource->GetTextureTarget();
     991             :     ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
     992           0 :                                                              aSource->GetFormat());
     993           0 :     int shaderConfig = config.mFeatures;
     994             : 
     995           0 :     gfx::IntSize size = aSource->GetSize();
     996             : 
     997             :     // By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
     998             :     // texture correctly. texID is used for tracking in DebugGLTextureData.
     999             :     RefPtr<DataSourceSurface> img =
    1000           0 :         aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
    1001             :                                                          size,
    1002           0 :                                                          shaderConfig, aFlipY);
    1003           0 :     gLayerScopeManager.GetSocketManager()->AppendDebugData(
    1004             :         new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
    1005           0 :                                texID, img, aIsMask, Move(aPacket)));
    1006             : 
    1007           0 :     sSentTextureIds.push_back(texID);
    1008           0 :     gLayerScopeManager.CurrentSession().mTexIDs.push_back(texID);
    1009             : 
    1010             : }
    1011             : 
    1012             : void
    1013           0 : SenderHelper::SetAndSendTexture(GLContext* aGLContext,
    1014             :                                 void* aLayerRef,
    1015             :                                 TextureSourceOGL* aSource,
    1016             :                                 const TexturedEffect* aEffect)
    1017             : {
    1018             :     // Expose packet creation here, so we could dump primary texture effect attributes.
    1019           0 :     auto packet = MakeUnique<layerscope::Packet>();
    1020           0 :     layerscope::TexturePacket* texturePacket = packet->mutable_texture();
    1021           0 :     texturePacket->set_mpremultiplied(aEffect->mPremultiplied);
    1022           0 :     DumpFilter(texturePacket, aEffect->mSamplingFilter);
    1023           0 :     DumpRect(texturePacket->mutable_mtexturecoords(), aEffect->mTextureCoords);
    1024           0 :     SendTextureSource(aGLContext, aLayerRef, aSource, false, false, Move(packet));
    1025           0 : }
    1026             : 
    1027             : void
    1028           0 : SenderHelper::SendTexturedEffect(GLContext* aGLContext,
    1029             :                                  void* aLayerRef,
    1030             :                                  const TexturedEffect* aEffect)
    1031             : {
    1032           0 :     TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
    1033           0 :     if (!source) {
    1034           0 :         return;
    1035             :     }
    1036             : 
    1037             :     // Fallback texture sending path.
    1038           0 :     SetAndSendTexture(aGLContext, aLayerRef, source, aEffect);
    1039             : }
    1040             : 
    1041             : void
    1042           0 : SenderHelper::SendMaskEffect(GLContext* aGLContext,
    1043             :                                  void* aLayerRef,
    1044             :                                  const EffectMask* aEffect)
    1045             : {
    1046           0 :     TextureSourceOGL* source = aEffect->mMaskTexture->AsSourceOGL();
    1047           0 :     if (!source) {
    1048           0 :         return;
    1049             :     }
    1050             : 
    1051             :     // Expose packet creation here, so we could dump secondary mask effect attributes.
    1052           0 :     auto packet = MakeUnique<layerscope::Packet>();
    1053           0 :     TexturePacket::EffectMask* mask = packet->mutable_texture()->mutable_mask();
    1054           0 :     mask->mutable_msize()->set_w(aEffect->mSize.width);
    1055           0 :     mask->mutable_msize()->set_h(aEffect->mSize.height);
    1056           0 :     auto element = reinterpret_cast<const Float *>(&(aEffect->mMaskTransform));
    1057           0 :     for (int i = 0; i < 16; i++) {
    1058           0 :         mask->mutable_mmasktransform()->add_m(*element++);
    1059             :     }
    1060             : 
    1061           0 :     SendTextureSource(aGLContext, aLayerRef, source, false, true, Move(packet));
    1062             : }
    1063             : 
    1064             : void
    1065           0 : SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
    1066             :                               void* aLayerRef,
    1067             :                               const EffectYCbCr* aEffect)
    1068             : {
    1069           0 :     TextureSource* sourceYCbCr = aEffect->mTexture;
    1070           0 :     if (!sourceYCbCr)
    1071           0 :         return;
    1072             : 
    1073           0 :     const int Y = 0, Cb = 1, Cr = 2;
    1074             :     TextureSourceOGL *sources[] = {
    1075           0 :         sourceYCbCr->GetSubSource(Y)->AsSourceOGL(),
    1076           0 :         sourceYCbCr->GetSubSource(Cb)->AsSourceOGL(),
    1077           0 :         sourceYCbCr->GetSubSource(Cr)->AsSourceOGL()
    1078           0 :     };
    1079             : 
    1080           0 :     for (auto source: sources) {
    1081           0 :         SetAndSendTexture(aGLContext, aLayerRef, source, aEffect);
    1082             :     }
    1083             : }
    1084             : 
    1085             : void
    1086           0 : SenderHelper::SendEffectChain(GLContext* aGLContext,
    1087             :                               const EffectChain& aEffectChain,
    1088             :                               int aWidth,
    1089             :                               int aHeight)
    1090             : {
    1091           0 :     if (!sLayersBufferSendable) return;
    1092             : 
    1093           0 :     const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
    1094           0 :     MOZ_ASSERT(primaryEffect);
    1095             : 
    1096           0 :     if (!primaryEffect) {
    1097           0 :       return;
    1098             :     }
    1099             : 
    1100           0 :     switch (primaryEffect->mType) {
    1101             :         case EffectTypes::RGB: {
    1102             :             const TexturedEffect* texturedEffect =
    1103           0 :                 static_cast<const TexturedEffect*>(primaryEffect);
    1104           0 :             SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
    1105           0 :             break;
    1106             :         }
    1107             :         case EffectTypes::YCBCR: {
    1108             :             const EffectYCbCr* yCbCrEffect =
    1109           0 :                 static_cast<const EffectYCbCr*>(primaryEffect);
    1110           0 :             SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
    1111           0 :             break;
    1112             :         }
    1113             :         case EffectTypes::SOLID_COLOR: {
    1114             :             const EffectSolidColor* solidColorEffect =
    1115           0 :                 static_cast<const EffectSolidColor*>(primaryEffect);
    1116           0 :             SendColor(aEffectChain.mLayerRef, solidColorEffect->mColor,
    1117           0 :                       aWidth, aHeight);
    1118           0 :             break;
    1119             :         }
    1120             :         case EffectTypes::COMPONENT_ALPHA:
    1121             :         case EffectTypes::RENDER_TARGET:
    1122             :         default:
    1123           0 :             break;
    1124             :     }
    1125             : 
    1126           0 :     if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
    1127             :         const EffectMask* effectMask =
    1128           0 :             static_cast<const EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
    1129           0 :         SendMaskEffect(aGLContext, aEffectChain.mLayerRef, effectMask);
    1130             :     }
    1131             : }
    1132             : 
    1133             : void
    1134          33 : LayerScope::ContentChanged(TextureHost *host)
    1135             : {
    1136          33 :     if (!CheckSendable()) {
    1137          33 :       return;
    1138             :     }
    1139             : 
    1140           0 :     gLayerScopeManager.GetContentMonitor()->SetChangedHost(host);
    1141             : }
    1142             : 
    1143             : // ----------------------------------------------
    1144             : // SocketHandler implementation
    1145             : // ----------------------------------------------
    1146             : void
    1147           0 : LayerScopeWebSocketManager::SocketHandler::OpenStream(nsISocketTransport* aTransport)
    1148             : {
    1149           0 :     MOZ_ASSERT(aTransport);
    1150             : 
    1151           0 :     mTransport = aTransport;
    1152           0 :     mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
    1153             :                                  0,
    1154             :                                  0,
    1155           0 :                                  getter_AddRefs(mOutputStream));
    1156             : 
    1157           0 :     nsCOMPtr<nsIInputStream> debugInputStream;
    1158           0 :     mTransport->OpenInputStream(0,
    1159             :                                 0,
    1160             :                                 0,
    1161           0 :                                 getter_AddRefs(debugInputStream));
    1162           0 :     mInputStream = do_QueryInterface(debugInputStream);
    1163           0 :     mInputStream->AsyncWait(this, 0, 0, GetCurrentThreadEventTarget());
    1164           0 : }
    1165             : 
    1166             : bool
    1167           0 : LayerScopeWebSocketManager::SocketHandler::WriteToStream(void *aPtr,
    1168             :                                           uint32_t aSize)
    1169             : {
    1170           0 :     if (mState == NoHandshake) {
    1171             :         // Not yet handshake, just return true in case of
    1172             :         // LayerScope remove this handle
    1173           0 :         return true;
    1174           0 :     } else if (mState == HandshakeFailed) {
    1175           0 :         return false;
    1176             :     }
    1177             : 
    1178           0 :     if (!mOutputStream) {
    1179           0 :         return false;
    1180             :     }
    1181             : 
    1182             :     // Generate WebSocket header
    1183             :     uint8_t wsHeader[10];
    1184           0 :     int wsHeaderSize = 0;
    1185           0 :     const uint8_t opcode = 0x2;
    1186           0 :     wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
    1187           0 :     if (aSize <= 125) {
    1188           0 :         wsHeaderSize = 2;
    1189           0 :         wsHeader[1] = aSize;
    1190           0 :     } else if (aSize < 65536) {
    1191           0 :         wsHeaderSize = 4;
    1192           0 :         wsHeader[1] = 0x7E;
    1193           0 :         NetworkEndian::writeUint16(wsHeader + 2, aSize);
    1194             :     } else {
    1195           0 :         wsHeaderSize = 10;
    1196           0 :         wsHeader[1] = 0x7F;
    1197           0 :         NetworkEndian::writeUint64(wsHeader + 2, aSize);
    1198             :     }
    1199             : 
    1200             :     // Send WebSocket header
    1201             :     nsresult rv;
    1202             :     uint32_t cnt;
    1203           0 :     rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
    1204           0 :                               wsHeaderSize, &cnt);
    1205           0 :     if (NS_FAILED(rv))
    1206           0 :         return false;
    1207             : 
    1208           0 :     uint32_t written = 0;
    1209           0 :     while (written < aSize) {
    1210             :         uint32_t cnt;
    1211           0 :         rv = mOutputStream->Write(reinterpret_cast<char*>(aPtr) + written,
    1212           0 :                                   aSize - written, &cnt);
    1213           0 :         if (NS_FAILED(rv))
    1214           0 :             return false;
    1215             : 
    1216           0 :         written += cnt;
    1217             :     }
    1218             : 
    1219           0 :     return true;
    1220             : }
    1221             : 
    1222             : NS_IMETHODIMP
    1223           0 : LayerScopeWebSocketManager::SocketHandler::OnInputStreamReady(nsIAsyncInputStream *aStream)
    1224             : {
    1225           0 :     MOZ_ASSERT(mInputStream);
    1226             : 
    1227           0 :     if (!mInputStream) {
    1228           0 :         return NS_OK;
    1229             :     }
    1230             : 
    1231           0 :     if (!mConnected) {
    1232           0 :         nsTArray<nsCString> protocolString;
    1233           0 :         ReadInputStreamData(protocolString);
    1234             : 
    1235           0 :         if (WebSocketHandshake(protocolString)) {
    1236           0 :             mState = HandshakeSuccess;
    1237           0 :             mConnected = true;
    1238           0 :             mInputStream->AsyncWait(this, 0, 0, GetCurrentThreadEventTarget());
    1239             :         } else {
    1240           0 :             mState = HandshakeFailed;
    1241             :         }
    1242           0 :         return NS_OK;
    1243             :     } else {
    1244           0 :         return HandleSocketMessage(aStream);
    1245             :     }
    1246             : }
    1247             : 
    1248             : void
    1249           0 : LayerScopeWebSocketManager::SocketHandler::ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
    1250             : {
    1251           0 :     nsLineBuffer<char> lineBuffer;
    1252           0 :     nsCString line;
    1253           0 :     bool more = true;
    1254           0 :     do {
    1255           0 :         NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
    1256             : 
    1257           0 :         if (line.Length() > 0) {
    1258           0 :             aProtocolString.AppendElement(line);
    1259             :         }
    1260           0 :     } while (more && line.Length() > 0);
    1261           0 : }
    1262             : 
    1263             : bool
    1264           0 : LayerScopeWebSocketManager::SocketHandler::WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
    1265             : {
    1266             :     nsresult rv;
    1267           0 :     bool isWebSocket = false;
    1268           0 :     nsCString version;
    1269           0 :     nsCString wsKey;
    1270           0 :     nsCString protocol;
    1271             : 
    1272             :     // Validate WebSocket client request.
    1273           0 :     if (aProtocolString.Length() == 0)
    1274           0 :         return false;
    1275             : 
    1276             :     // Check that the HTTP method is GET
    1277           0 :     const char* HTTP_METHOD = "GET ";
    1278           0 :     if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
    1279           0 :         return false;
    1280             :     }
    1281             : 
    1282           0 :     for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
    1283           0 :         const char* line = aProtocolString[i].get();
    1284           0 :         const char* prop_pos = strchr(line, ':');
    1285           0 :         if (prop_pos != nullptr) {
    1286           0 :             nsCString key(line, prop_pos - line);
    1287           0 :             nsCString value(prop_pos + 2);
    1288           0 :             if (key.EqualsIgnoreCase("upgrade") &&
    1289           0 :                 value.EqualsIgnoreCase("websocket")) {
    1290           0 :                 isWebSocket = true;
    1291           0 :             } else if (key.EqualsIgnoreCase("sec-websocket-version")) {
    1292           0 :                 version = value;
    1293           0 :             } else if (key.EqualsIgnoreCase("sec-websocket-key")) {
    1294           0 :                 wsKey = value;
    1295           0 :             } else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
    1296           0 :                 protocol = value;
    1297             :             }
    1298             :         }
    1299             :     }
    1300             : 
    1301           0 :     if (!isWebSocket) {
    1302           0 :         return false;
    1303             :     }
    1304             : 
    1305           0 :     if (!(version.EqualsLiteral("7") ||
    1306           0 :           version.EqualsLiteral("8") ||
    1307           0 :           version.EqualsLiteral("13"))) {
    1308           0 :         return false;
    1309             :     }
    1310             : 
    1311           0 :     if (!(protocol.EqualsIgnoreCase("binary"))) {
    1312           0 :         return false;
    1313             :     }
    1314             : 
    1315           0 :     if (!mOutputStream) {
    1316           0 :         return false;
    1317             :     }
    1318             : 
    1319             :     // Client request is valid. Start to generate and send server response.
    1320           0 :     nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
    1321           0 :     nsAutoCString res;
    1322           0 :     SHA1Sum sha1;
    1323           0 :     nsCString combined(wsKey + guid);
    1324           0 :     sha1.update(combined.get(), combined.Length());
    1325             :     uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
    1326           0 :     sha1.finish(digest);
    1327           0 :     nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
    1328           0 :     rv = Base64Encode(newString, res);
    1329           0 :     if (NS_FAILED(rv)) {
    1330           0 :         return false;
    1331             :     }
    1332           0 :     nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
    1333           0 :     response.AppendLiteral("Upgrade: websocket\r\n");
    1334           0 :     response.AppendLiteral("Connection: Upgrade\r\n");
    1335           0 :     response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
    1336           0 :     response.AppendLiteral("Sec-WebSocket-Protocol: binary\r\n\r\n");
    1337           0 :     uint32_t written = 0;
    1338           0 :     uint32_t size = response.Length();
    1339           0 :     while (written < size) {
    1340             :         uint32_t cnt;
    1341           0 :         rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
    1342           0 :                                   size - written, &cnt);
    1343           0 :         if (NS_FAILED(rv))
    1344           0 :             return false;
    1345             : 
    1346           0 :         written += cnt;
    1347             :     }
    1348           0 :     mOutputStream->Flush();
    1349             : 
    1350           0 :     return true;
    1351             : }
    1352             : 
    1353             : nsresult
    1354           0 : LayerScopeWebSocketManager::SocketHandler::HandleSocketMessage(nsIAsyncInputStream *aStream)
    1355             : {
    1356             :     // The reading and parsing of this input stream is customized for layer viewer.
    1357           0 :     const uint32_t cPacketSize = 1024;
    1358             :     char buffer[cPacketSize];
    1359           0 :     uint32_t count = 0;
    1360           0 :     nsresult rv = NS_OK;
    1361             : 
    1362           0 :     do {
    1363           0 :         rv = mInputStream->Read((char *)buffer, cPacketSize, &count);
    1364             : 
    1365             :         // TODO: combine packets if we have to read more than once
    1366             : 
    1367           0 :         if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
    1368           0 :             mInputStream->AsyncWait(this, 0, 0, GetCurrentThreadEventTarget());
    1369           0 :             return NS_OK;
    1370             :         }
    1371             : 
    1372           0 :         if (NS_FAILED(rv)) {
    1373           0 :             break;
    1374             :         }
    1375             : 
    1376           0 :         if (count == 0) {
    1377             :             // NS_BASE_STREAM_CLOSED
    1378           0 :             CloseConnection();
    1379           0 :             break;
    1380             :         }
    1381             : 
    1382           0 :         rv = ProcessInput(reinterpret_cast<uint8_t *>(buffer), count);
    1383           0 :     } while (NS_SUCCEEDED(rv) && mInputStream);
    1384           0 :     return rv;
    1385             : }
    1386             : 
    1387             : nsresult
    1388           0 : LayerScopeWebSocketManager::SocketHandler::ProcessInput(uint8_t *aBuffer,
    1389             :                                          uint32_t aCount)
    1390             : {
    1391           0 :     uint32_t avail = aCount;
    1392             : 
    1393             :     // Decode Websocket data frame
    1394           0 :     if (avail <= 2) {
    1395           0 :         NS_WARNING("Packet size is less than 2 bytes");
    1396           0 :         return NS_OK;
    1397             :     }
    1398             : 
    1399             :     // First byte, data type, only care the opcode
    1400             :     // rsvBits: aBuffer[0] & 0x70 (0111 0000)
    1401           0 :     uint8_t finBit = aBuffer[0] & 0x80; // 1000 0000
    1402           0 :     uint8_t opcode = aBuffer[0] & 0x0F; // 0000 1111
    1403             : 
    1404           0 :     if (!finBit) {
    1405           0 :         NS_WARNING("We cannot handle multi-fragments messages in Layerscope websocket parser.");
    1406           0 :         return NS_OK;
    1407             :     }
    1408             : 
    1409             :     // Second byte, data length
    1410           0 :     uint8_t maskBit = aBuffer[1] & 0x80; // 1000 0000
    1411           0 :     int64_t payloadLength64 = aBuffer[1] & 0x7F; // 0111 1111
    1412             : 
    1413           0 :     if (!maskBit) {
    1414           0 :         NS_WARNING("Client to Server should set the mask bit");
    1415           0 :         return NS_OK;
    1416             :     }
    1417             : 
    1418           0 :     uint32_t framingLength = 2 + 4; // 4 for masks
    1419             : 
    1420           0 :     if (payloadLength64 < 126) {
    1421           0 :         if (avail < framingLength)
    1422           0 :             return NS_OK;
    1423           0 :     } else if (payloadLength64 == 126) {
    1424             :         // 16 bit length field
    1425           0 :         framingLength += 2;
    1426           0 :         if (avail < framingLength) {
    1427           0 :             return NS_OK;
    1428             :         }
    1429             : 
    1430           0 :         payloadLength64 = aBuffer[2] << 8 | aBuffer[3];
    1431             :     } else {
    1432             :         // 64 bit length
    1433           0 :         framingLength += 8;
    1434           0 :         if (avail < framingLength) {
    1435           0 :             return NS_OK;
    1436             :         }
    1437             : 
    1438           0 :         if (aBuffer[2] & 0x80) {
    1439             :             // Section 4.2 says that the most significant bit MUST be
    1440             :             // 0. (i.e. this is really a 63 bit value)
    1441           0 :             NS_WARNING("High bit of 64 bit length set");
    1442           0 :             return NS_ERROR_ILLEGAL_VALUE;
    1443             :         }
    1444             : 
    1445             :         // copy this in case it is unaligned
    1446           0 :         payloadLength64 = NetworkEndian::readInt64(aBuffer + 2);
    1447             :     }
    1448             : 
    1449           0 :     uint8_t *payload = aBuffer + framingLength;
    1450           0 :     avail -= framingLength;
    1451             : 
    1452           0 :     uint32_t payloadLength = static_cast<uint32_t>(payloadLength64);
    1453           0 :     if (avail < payloadLength) {
    1454           0 :         NS_WARNING("Packet size mismatch the payload length");
    1455           0 :         return NS_OK;
    1456             :     }
    1457             : 
    1458             :     // Apply mask
    1459           0 :     uint32_t mask = NetworkEndian::readUint32(payload - 4);
    1460           0 :     ApplyMask(mask, payload, payloadLength);
    1461             : 
    1462           0 :     if (opcode == 0x8) {
    1463             :         // opcode == 0x8 means connection close
    1464           0 :         CloseConnection();
    1465           0 :         return NS_BASE_STREAM_CLOSED;
    1466             :     }
    1467             : 
    1468           0 :     if (!HandleDataFrame(payload, payloadLength)) {
    1469           0 :         NS_WARNING("Cannot decode payload data by the protocol buffer");
    1470             :     }
    1471             : 
    1472           0 :     return NS_OK;
    1473             : }
    1474             : 
    1475             : void
    1476           0 : LayerScopeWebSocketManager::SocketHandler::ApplyMask(uint32_t aMask,
    1477             :                                       uint8_t *aData,
    1478             :                                       uint64_t aLen)
    1479             : {
    1480           0 :     if (!aData || aLen == 0) {
    1481           0 :         return;
    1482             :     }
    1483             : 
    1484             :     // Optimally we want to apply the mask 32 bits at a time,
    1485             :     // but the buffer might not be alligned. So we first deal with
    1486             :     // 0 to 3 bytes of preamble individually
    1487           0 :     while (aLen && (reinterpret_cast<uintptr_t>(aData) & 3)) {
    1488           0 :         *aData ^= aMask >> 24;
    1489           0 :         aMask = RotateLeft(aMask, 8);
    1490           0 :         aData++;
    1491           0 :         aLen--;
    1492             :     }
    1493             : 
    1494             :     // perform mask on full words of data
    1495           0 :     uint32_t *iData = reinterpret_cast<uint32_t *>(aData);
    1496           0 :     uint32_t *end = iData + (aLen >> 2);
    1497           0 :     NetworkEndian::writeUint32(&aMask, aMask);
    1498           0 :     for (; iData < end; iData++) {
    1499           0 :         *iData ^= aMask;
    1500             :     }
    1501           0 :     aMask = NetworkEndian::readUint32(&aMask);
    1502           0 :     aData = (uint8_t *)iData;
    1503           0 :     aLen  = aLen % 4;
    1504             : 
    1505             :     // There maybe up to 3 trailing bytes that need to be dealt with
    1506             :     // individually
    1507           0 :     while (aLen) {
    1508           0 :         *aData ^= aMask >> 24;
    1509           0 :         aMask = RotateLeft(aMask, 8);
    1510           0 :         aData++;
    1511           0 :         aLen--;
    1512             :     }
    1513             : }
    1514             : 
    1515             : bool
    1516           0 : LayerScopeWebSocketManager::SocketHandler::HandleDataFrame(uint8_t *aData,
    1517             :                                             uint32_t aSize)
    1518             : {
    1519             :     // Handle payload data by protocol buffer
    1520           0 :     auto p = MakeUnique<CommandPacket>();
    1521           0 :     p->ParseFromArray(static_cast<void*>(aData), aSize);
    1522             : 
    1523           0 :     if (!p->has_type()) {
    1524           0 :         MOZ_ASSERT(false, "Protocol buffer decoding failed or cannot recongize it");
    1525             :         return false;
    1526             :     }
    1527             : 
    1528           0 :     switch (p->type()) {
    1529             :         case CommandPacket::LAYERS_TREE:
    1530           0 :             if (p->has_value()) {
    1531           0 :                 SenderHelper::SetLayersTreeSendable(p->value());
    1532             :             }
    1533           0 :             break;
    1534             : 
    1535             :         case CommandPacket::LAYERS_BUFFER:
    1536           0 :             if (p->has_value()) {
    1537           0 :                 SenderHelper::SetLayersBufferSendable(p->value());
    1538             :             }
    1539           0 :             break;
    1540             : 
    1541             :         case CommandPacket::NO_OP:
    1542             :         default:
    1543           0 :             NS_WARNING("Invalid message type");
    1544           0 :             break;
    1545             :     }
    1546           0 :     return true;
    1547             : }
    1548             : 
    1549             : void
    1550           0 : LayerScopeWebSocketManager::SocketHandler::CloseConnection()
    1551             : {
    1552           0 :     gLayerScopeManager.GetSocketManager()->CleanDebugData();
    1553           0 :     if (mInputStream) {
    1554           0 :         mInputStream->AsyncWait(nullptr, 0, 0, nullptr);
    1555           0 :         mInputStream = nullptr;
    1556             :     }
    1557           0 :     if (mOutputStream) {
    1558           0 :         mOutputStream = nullptr;
    1559             :     }
    1560           0 :     if (mTransport) {
    1561           0 :         mTransport->Close(NS_BASE_STREAM_CLOSED);
    1562           0 :         mTransport = nullptr;
    1563             :     }
    1564           0 :     mConnected = false;
    1565           0 : }
    1566             : 
    1567             : // ----------------------------------------------
    1568             : // LayerScopeWebSocketManager implementation
    1569             : // ----------------------------------------------
    1570           0 : LayerScopeWebSocketManager::LayerScopeWebSocketManager()
    1571           0 :     : mHandlerMutex("LayerScopeWebSocketManager::mHandlerMutex")
    1572             : {
    1573           0 :     NS_NewNamedThread("LayerScope", getter_AddRefs(mDebugSenderThread));
    1574             : 
    1575           0 :     mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
    1576           0 :     int port = gfxPrefs::LayerScopePort();
    1577           0 :     mServerSocket->Init(port, false, -1);
    1578           0 :     mServerSocket->AsyncListen(new SocketListener);
    1579           0 : }
    1580             : 
    1581           0 : LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
    1582             : {
    1583           0 :     mServerSocket->Close();
    1584           0 : }
    1585             : 
    1586             : void
    1587           0 : LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
    1588             : {
    1589           0 :     if (!mCurrentSender) {
    1590           0 :         mCurrentSender = new DebugDataSender(mDebugSenderThread);
    1591             :     }
    1592             : 
    1593           0 :     mCurrentSender->Append(aDebugData);
    1594           0 : }
    1595             : 
    1596             : void
    1597           0 : LayerScopeWebSocketManager::CleanDebugData()
    1598             : {
    1599           0 :     if (mCurrentSender) {
    1600           0 :         mCurrentSender->Cleanup();
    1601             :     }
    1602           0 : }
    1603             : 
    1604             : void
    1605           0 : LayerScopeWebSocketManager::DispatchDebugData()
    1606             : {
    1607           0 :     MOZ_ASSERT(mCurrentSender.get() != nullptr);
    1608             : 
    1609           0 :     mCurrentSender->Send();
    1610           0 :     mCurrentSender = nullptr;
    1611           0 : }
    1612             : 
    1613           0 : NS_IMETHODIMP LayerScopeWebSocketManager::SocketListener::OnSocketAccepted(
    1614             :                                      nsIServerSocket *aServ,
    1615             :                                      nsISocketTransport *aTransport)
    1616             : {
    1617           0 :     if (!gLayerScopeManager.GetSocketManager())
    1618           0 :         return NS_OK;
    1619             : 
    1620           0 :     printf_stderr("*** LayerScope: Accepted connection\n");
    1621           0 :     gLayerScopeManager.GetSocketManager()->AddConnection(aTransport);
    1622           0 :     gLayerScopeManager.GetContentMonitor()->Empty();
    1623           0 :     return NS_OK;
    1624             : }
    1625             : 
    1626             : // ----------------------------------------------
    1627             : // LayerScope implementation
    1628             : // ----------------------------------------------
    1629             : /*static*/
    1630             : void
    1631           0 : LayerScope::Init()
    1632             : {
    1633           0 :     if (!gfxPrefs::LayerScopeEnabled() || XRE_IsGPUProcess()) {
    1634           0 :         return;
    1635             :     }
    1636             : 
    1637           0 :     gLayerScopeManager.CreateServerSocket();
    1638             : }
    1639             : 
    1640             : /*static*/
    1641             : void
    1642           0 : LayerScope::DrawBegin()
    1643             : {
    1644           0 :     if (!CheckSendable()) {
    1645           0 :         return;
    1646             :     }
    1647             : 
    1648           0 :     gLayerScopeManager.NewDrawSession();
    1649             : }
    1650             : 
    1651             : /*static*/
    1652             : void
    1653           0 : LayerScope::SetRenderOffset(float aX, float aY)
    1654             : {
    1655           0 :     if (!CheckSendable()) {
    1656           0 :         return;
    1657             :     }
    1658             : 
    1659           0 :     gLayerScopeManager.CurrentSession().mOffsetX = aX;
    1660           0 :     gLayerScopeManager.CurrentSession().mOffsetY = aY;
    1661             : }
    1662             : 
    1663             : /*static*/
    1664             : void
    1665           0 : LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
    1666             : {
    1667           0 :     if (!CheckSendable()) {
    1668           0 :         return;
    1669             :     }
    1670             : 
    1671           0 :     gLayerScopeManager.CurrentSession().mMVMatrix = aMatrix;
    1672             : }
    1673             : 
    1674             : /*static*/
    1675             : void
    1676           0 : LayerScope::SetDrawRects(size_t aRects,
    1677             :                          const gfx::Rect* aLayerRects,
    1678             :                          const gfx::Rect* aTextureRects)
    1679             : {
    1680           0 :     if (!CheckSendable()) {
    1681           0 :         return;
    1682             :     }
    1683             : 
    1684           0 :     MOZ_ASSERT(aRects > 0 && aRects <= 4);
    1685           0 :     MOZ_ASSERT(aLayerRects);
    1686             : 
    1687           0 :     gLayerScopeManager.CurrentSession().mRects = aRects;
    1688             : 
    1689           0 :     for (size_t i = 0; i < aRects; i++){
    1690           0 :         gLayerScopeManager.CurrentSession().mLayerRects[i] = aLayerRects[i];
    1691           0 :         gLayerScopeManager.CurrentSession().mTextureRects[i] = aTextureRects[i];
    1692             :     }
    1693             : }
    1694             : 
    1695             : /*static*/
    1696             : void
    1697           0 : LayerScope::DrawEnd(gl::GLContext* aGLContext,
    1698             :                     const EffectChain& aEffectChain,
    1699             :                     int aWidth,
    1700             :                     int aHeight)
    1701             : {
    1702             :     // Protect this public function
    1703           0 :     if (!CheckSendable()) {
    1704           0 :         return;
    1705             :     }
    1706             : 
    1707             :     // 1. Send textures.
    1708           0 :     SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight);
    1709             : 
    1710             :     // 2. Send parameters of draw call, such as uniforms and attributes of
    1711             :     // vertex adnd fragment shader.
    1712           0 :     DrawSession& draws = gLayerScopeManager.CurrentSession();
    1713           0 :     gLayerScopeManager.GetSocketManager()->AppendDebugData(
    1714             :         new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY,
    1715             :                             draws.mMVMatrix, draws.mRects,
    1716             :                             draws.mLayerRects,
    1717             :                             draws.mTextureRects,
    1718             :                             draws.mTexIDs,
    1719           0 :                             aEffectChain.mLayerRef));
    1720             : 
    1721             : }
    1722             : 
    1723             : /*static*/
    1724             : void
    1725           0 : LayerScope::SendLayer(LayerComposite* aLayer,
    1726             :                       int aWidth,
    1727             :                       int aHeight)
    1728             : {
    1729             :     // Protect this public function
    1730           0 :     if (!CheckSendable()) {
    1731           0 :         return;
    1732             :     }
    1733           0 :     SenderHelper::SendLayer(aLayer, aWidth, aHeight);
    1734             : }
    1735             : 
    1736             : /*static*/
    1737             : void
    1738           0 : LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
    1739             : {
    1740             :     // Protect this public function
    1741           0 :     if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
    1742           0 :         return;
    1743             :     }
    1744           0 :     gLayerScopeManager.GetSocketManager()->AppendDebugData(
    1745           0 :         new DebugGLLayersData(Move(aPacket)));
    1746             : }
    1747             : 
    1748             : /*static*/
    1749             : bool
    1750         114 : LayerScope::CheckSendable()
    1751             : {
    1752             :     // Only compositor threads check LayerScope status
    1753         114 :     MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || gIsGtest);
    1754             : 
    1755         114 :     if (!gfxPrefs::LayerScopeEnabled()) {
    1756         114 :         return false;
    1757             :     }
    1758           0 :     if (!gLayerScopeManager.GetSocketManager()) {
    1759           0 :         Init();
    1760           0 :         return false;
    1761             :     }
    1762           0 :     if (!gLayerScopeManager.GetSocketManager()->IsConnected()) {
    1763           0 :         return false;
    1764             :     }
    1765           0 :     return true;
    1766             : }
    1767             : 
    1768             : /*static*/
    1769             : void
    1770           0 : LayerScope::CleanLayer()
    1771             : {
    1772           0 :     if (CheckSendable()) {
    1773           0 :         gLayerScopeManager.GetSocketManager()->CleanDebugData();
    1774             :     }
    1775           0 : }
    1776             : 
    1777             : /*static*/
    1778             : void
    1779           0 : LayerScope::SetHWComposed()
    1780             : {
    1781           0 :     if (CheckSendable()) {
    1782           0 :         gLayerScopeManager.GetSocketManager()->AppendDebugData(
    1783           0 :             new DebugGLMetaData(Packet::META, true));
    1784             :     }
    1785           0 : }
    1786             : 
    1787             : /*static*/
    1788             : void
    1789           1 : LayerScope::SetPixelScale(double devPixelsPerCSSPixel)
    1790             : {
    1791           1 :     gLayerScopeManager.SetPixelScale(devPixelsPerCSSPixel);
    1792           1 : }
    1793             : 
    1794             : // ----------------------------------------------
    1795             : // LayerScopeAutoFrame implementation
    1796             : // ----------------------------------------------
    1797          27 : LayerScopeAutoFrame::LayerScopeAutoFrame(int64_t aFrameStamp)
    1798             : {
    1799             :     // Do Begin Frame
    1800          27 :     BeginFrame(aFrameStamp);
    1801          27 : }
    1802             : 
    1803          27 : LayerScopeAutoFrame::~LayerScopeAutoFrame()
    1804             : {
    1805             :     // Do End Frame
    1806          27 :     EndFrame();
    1807          27 : }
    1808             : 
    1809             : void
    1810          27 : LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
    1811             : {
    1812          27 :     if (!LayerScope::CheckSendable()) {
    1813          27 :         return;
    1814             :     }
    1815           0 :     SenderHelper::ClearSentTextureIds();
    1816             : 
    1817           0 :     gLayerScopeManager.GetSocketManager()->AppendDebugData(
    1818           0 :         new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));
    1819             : }
    1820             : 
    1821             : void
    1822          27 : LayerScopeAutoFrame::EndFrame()
    1823             : {
    1824          27 :     if (!LayerScope::CheckSendable()) {
    1825          27 :         return;
    1826             :     }
    1827             : 
    1828           0 :     gLayerScopeManager.GetSocketManager()->AppendDebugData(
    1829           0 :         new DebugGLFrameStatusData(Packet::FRAMEEND));
    1830           0 :     gLayerScopeManager.GetSocketManager()->DispatchDebugData();
    1831             : }
    1832             : 
    1833             : } // namespace layers
    1834             : } // namespace mozilla

Generated by: LCOV version 1.13