gfx/layers/LayerScope.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
     7 #include "LayerScope.h"
     9 #include "Composer2D.h"
    10 #include "Effects.h"
    11 #include "mozilla/TimeStamp.h"
    12 #include "mozilla/Preferences.h"
    13 #include "mozilla/Endian.h"
    14 #include "TexturePoolOGL.h"
    15 #include "mozilla/layers/TextureHostOGL.h"
    17 #include "gfxColor.h"
    18 #include "gfxContext.h"
    19 #include "gfxUtils.h"
    20 #include "gfxPrefs.h"
    21 #include "nsIWidget.h"
    23 #include "GLContext.h"
    24 #include "GLContextProvider.h"
    25 #include "GLReadTexImageHelper.h"
    27 #include "nsIServiceManager.h"
    28 #include "nsIConsoleService.h"
    30 #include <memory>
    31 #include "mozilla/LinkedList.h"
    32 #include "mozilla/Base64.h"
    33 #include "mozilla/SHA1.h"
    34 #include "mozilla/StaticPtr.h"
    35 #include "nsThreadUtils.h"
    36 #include "nsISocketTransport.h"
    37 #include "nsIServerSocket.h"
    38 #include "nsReadLine.h"
    39 #include "nsNetCID.h"
    40 #include "nsIOutputStream.h"
    41 #include "nsIAsyncInputStream.h"
    42 #include "nsIEventTarget.h"
    43 #include "nsProxyRelease.h"
    45 // Undo the damage done by mozzconf.h
    46 #undef compress
    47 #include "mozilla/Compression.h"
    49 #ifdef __GNUC__
    50 #define PACKED_STRUCT __attribute__((packed))
    51 #else
    52 #define PACKED_STRUCT
    53 #endif
    55 namespace mozilla {
    56 namespace layers {
    58 using namespace mozilla::Compression;
    59 using namespace mozilla::gfx;
    60 using namespace mozilla::gl;
    61 using namespace mozilla;
    63 class DebugDataSender;
    64 class DebugGLData;
    66 /* This class handle websocket protocol which included
    67  * handshake and data frame's header
    68  */
    69 class LayerScopeWebSocketHandler : public nsIInputStreamCallback {
    70 public:
    71     NS_DECL_THREADSAFE_ISUPPORTS
    73     enum SocketStateType {
    74         NoHandshake,
    75         HandshakeSuccess,
    76         HandshakeFailed
    77     };
    79     LayerScopeWebSocketHandler()
    80         : mState(NoHandshake)
    81     { }
    83     virtual ~LayerScopeWebSocketHandler()
    84     {
    85         if (mTransport) {
    86             mTransport->Close(NS_OK);
    87         }
    88     }
    90     void OpenStream(nsISocketTransport* aTransport) {
    91         MOZ_ASSERT(aTransport);
    93         mTransport = aTransport;
    94         mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
    95                                      0,
    96                                      0,
    97                                      getter_AddRefs(mOutputStream));
    99         nsCOMPtr<nsIInputStream> debugInputStream;
   100         mTransport->OpenInputStream(0,
   101                                     0,
   102                                     0,
   103                                     getter_AddRefs(debugInputStream));
   104         mInputStream = do_QueryInterface(debugInputStream);
   105         mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
   106     }
   108     bool WriteToStream(void *ptr, uint32_t size) {
   109         if (mState == NoHandshake) {
   110             // Not yet handshake, just return true in case of
   111             // LayerScope remove this handle
   112             return true;
   113         } else if (mState == HandshakeFailed) {
   114             return false;
   115         }
   117         // Generate WebSocket header
   118         uint8_t wsHeader[10];
   119         int wsHeaderSize = 0;
   120         const uint8_t opcode = 0x2;
   121         wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
   122         if (size <= 125) {
   123             wsHeaderSize = 2;
   124             wsHeader[1] = size;
   125         } else if (size < 65536) {
   126             wsHeaderSize = 4;
   127             wsHeader[1] = 0x7E;
   128             NetworkEndian::writeUint16(wsHeader + 2, size);
   129         } else {
   130             wsHeaderSize = 10;
   131             wsHeader[1] = 0x7F;
   132             NetworkEndian::writeUint64(wsHeader + 2, size);
   133         }
   135         // Send WebSocket header
   136         nsresult rv;
   137         uint32_t cnt;
   138         rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
   139                                  wsHeaderSize, &cnt);
   140         if (NS_FAILED(rv))
   141             return false;
   143         uint32_t written = 0;
   144         while (written < size) {
   145             uint32_t cnt;
   146             rv = mOutputStream->Write(reinterpret_cast<char*>(ptr) + written,
   147                                      size - written, &cnt);
   148             if (NS_FAILED(rv))
   149                 return false;
   151             written += cnt;
   152         }
   154         return true;
   155     }
   157     // nsIInputStreamCallback
   158     NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *stream) MOZ_OVERRIDE
   159     {
   160         nsTArray<nsCString> protocolString;
   161         ReadInputStreamData(protocolString);
   163         if (WebSocketHandshake(protocolString)) {
   164             mState = HandshakeSuccess;
   165         } else {
   166             mState = HandshakeFailed;
   167         }
   168         return NS_OK;
   169     }
   170 private:
   171     void ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
   172     {
   173         nsLineBuffer<char> lineBuffer;
   174         nsCString line;
   175         bool more = true;
   176         do {
   177             NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
   179             if (line.Length() > 0) {
   180                 aProtocolString.AppendElement(line);
   181             }
   182         } while (more && line.Length() > 0);
   183     }
   185     bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
   186     {
   187         nsresult rv;
   188         bool isWebSocket = false;
   189         nsCString version;
   190         nsCString wsKey;
   191         nsCString protocol;
   193         // Validate WebSocket client request.
   194         if (aProtocolString.Length() == 0)
   195             return false;
   197         // Check that the HTTP method is GET
   198         const char* HTTP_METHOD = "GET ";
   199         if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
   200             return false;
   201         }
   203         for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
   204             const char* line = aProtocolString[i].get();
   205             const char* prop_pos = strchr(line, ':');
   206             if (prop_pos != nullptr) {
   207                 nsCString key(line, prop_pos - line);
   208                 nsCString value(prop_pos + 2);
   209                 if (key.EqualsIgnoreCase("upgrade") &&
   210                     value.EqualsIgnoreCase("websocket")) {
   211                     isWebSocket = true;
   212                 } else if (key.EqualsIgnoreCase("sec-websocket-version")) {
   213                     version = value;
   214                 } else if (key.EqualsIgnoreCase("sec-websocket-key")) {
   215                     wsKey = value;
   216                 } else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
   217                     protocol = value;
   218                 }
   219             }
   220         }
   222         if (!isWebSocket) {
   223             return false;
   224         }
   226         if (!(version.Equals("7") || version.Equals("8") || version.Equals("13"))) {
   227             return false;
   228         }
   230         if (!(protocol.EqualsIgnoreCase("binary"))) {
   231             return false;
   232         }
   234         // Client request is valid. Start to generate and send server response.
   235         nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
   236         nsAutoCString res;
   237         SHA1Sum sha1;
   238         nsCString combined(wsKey + guid);
   239         sha1.update(combined.get(), combined.Length());
   240         uint8_t digest[SHA1Sum::HashSize]; // SHA1 digests are 20 bytes long.
   241         sha1.finish(digest);
   242         nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::HashSize);
   243         Base64Encode(newString, res);
   245         nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
   246         response.Append("Upgrade: websocket\r\n");
   247         response.Append("Connection: Upgrade\r\n");
   248         response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
   249         response.Append("Sec-WebSocket-Protocol: binary\r\n\r\n");
   250         uint32_t written = 0;
   251         uint32_t size = response.Length();
   252         while (written < size) {
   253             uint32_t cnt;
   254             rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
   255                                      size - written, &cnt);
   256             if (NS_FAILED(rv))
   257                 return false;
   259             written += cnt;
   260         }
   261         mOutputStream->Flush();
   263         return true;
   264     }
   266     nsCOMPtr<nsIOutputStream> mOutputStream;
   267     nsCOMPtr<nsIAsyncInputStream> mInputStream;
   268     nsCOMPtr<nsISocketTransport> mTransport;
   269     SocketStateType mState;
   270 };
   272 NS_IMPL_ISUPPORTS(LayerScopeWebSocketHandler, nsIInputStreamCallback);
   274 class LayerScopeWebSocketManager {
   275 public:
   276     LayerScopeWebSocketManager();
   277     ~LayerScopeWebSocketManager();
   279     void AddConnection(nsISocketTransport *aTransport)
   280     {
   281         MOZ_ASSERT(aTransport);
   282         nsRefPtr<LayerScopeWebSocketHandler> temp = new LayerScopeWebSocketHandler();
   283         temp->OpenStream(aTransport);
   284         mHandlers.AppendElement(temp.get());
   285     }
   287     void RemoveConnection(uint32_t aIndex)
   288     {
   289         MOZ_ASSERT(aIndex < mHandlers.Length());
   290         mHandlers.RemoveElementAt(aIndex);
   291     }
   293     void RemoveAllConnections()
   294     {
   295         mHandlers.Clear();
   296     }
   298     bool WriteAll(void *ptr, uint32_t size)
   299     {
   300         for (int32_t i = mHandlers.Length() - 1; i >= 0; --i) {
   301             if (!mHandlers[i]->WriteToStream(ptr, size)) {
   302                 // Send failed, remove this handler
   303                 RemoveConnection(i);
   304             }
   305         }
   307         return true;
   308     }
   310     bool IsConnected()
   311     {
   312         return (mHandlers.Length() != 0) ? true : false;
   313     }
   315     void AppendDebugData(DebugGLData *aDebugData);
   316     void DispatchDebugData();
   317 private:
   318     nsTArray<nsRefPtr<LayerScopeWebSocketHandler> > mHandlers;
   319     nsCOMPtr<nsIThread> mDebugSenderThread;
   320     nsRefPtr<DebugDataSender> mCurrentSender;
   321     nsCOMPtr<nsIServerSocket> mServerSocket;
   322 };
   324 static StaticAutoPtr<LayerScopeWebSocketManager> gLayerScopeWebSocketManager;
   326 class DebugGLData : public LinkedListElement<DebugGLData> {
   327 public:
   328     typedef enum {
   329         FrameStart,
   330         FrameEnd,
   331         TextureData,
   332         ColorData
   333     } DataType;
   335     virtual ~DebugGLData() { }
   337     DataType GetDataType() const { return mDataType; }
   338     intptr_t GetContextAddress() const { return mContextAddress; }
   339     int64_t GetValue() const { return mValue; }
   341     DebugGLData(DataType dataType)
   342         : mDataType(dataType),
   343           mContextAddress(0),
   344           mValue(0)
   345     { }
   347     DebugGLData(DataType dataType, GLContext* cx)
   348         : mDataType(dataType),
   349           mContextAddress(reinterpret_cast<intptr_t>(cx)),
   350           mValue(0)
   351     { }
   353     DebugGLData(DataType dataType, GLContext* cx, int64_t value)
   354         : mDataType(dataType),
   355           mContextAddress(reinterpret_cast<intptr_t>(cx)),
   356           mValue(value)
   357     { }
   359     virtual bool Write() {
   360         if (mDataType != FrameStart &&
   361             mDataType != FrameEnd)
   362         {
   363             NS_WARNING("Unimplemented data type!");
   364             return false;
   365         }
   367         DebugGLData::BasicPacket packet;
   369         packet.type = mDataType;
   370         packet.ptr = static_cast<uint64_t>(mContextAddress);
   371         packet.value = mValue;
   373         return WriteToStream(&packet, sizeof(packet));
   374     }
   376     static bool WriteToStream(void *ptr, uint32_t size) {
   377         if (!gLayerScopeWebSocketManager)
   378             return true;
   379         return gLayerScopeWebSocketManager->WriteAll(ptr, size);
   380     }
   382 protected:
   383     DataType mDataType;
   384     intptr_t mContextAddress;
   385     int64_t mValue;
   387 public:
   388   // the data packet formats; all packed
   389 #ifdef _MSC_VER
   390 #pragma pack(push, 1)
   391 #endif
   392     typedef struct {
   393         uint32_t type;
   394         uint64_t ptr;
   395         uint64_t value;
   396     } PACKED_STRUCT BasicPacket;
   398     typedef struct {
   399         uint32_t type;
   400         uint64_t ptr;
   401         uint64_t layerref;
   402         uint32_t color;
   403         uint32_t width;
   404         uint32_t height;
   405     } PACKED_STRUCT ColorPacket;
   407     typedef struct {
   408         uint32_t type;
   409         uint64_t ptr;
   410         uint64_t layerref;
   411         uint32_t name;
   412         uint32_t width;
   413         uint32_t height;
   414         uint32_t stride;
   415         uint32_t format;
   416         uint32_t target;
   417         uint32_t dataFormat;
   418         uint32_t dataSize;
   419     } PACKED_STRUCT TexturePacket;
   420 #ifdef _MSC_VER
   421 #pragma pack(pop)
   422 #endif
   423 };
   425 class DebugGLTextureData : public DebugGLData {
   426 public:
   427     DebugGLTextureData(GLContext* cx, void* layerRef, GLuint target, GLenum name, DataSourceSurface* img)
   428         : DebugGLData(DebugGLData::TextureData, cx),
   429           mLayerRef(layerRef),
   430           mTarget(target),
   431           mName(name),
   432           mImage(img)
   433     { }
   435     void *GetLayerRef() const { return mLayerRef; }
   436     GLuint GetName() const { return mName; }
   437     DataSourceSurface* GetImage() const { return mImage; }
   438     GLenum GetTextureTarget() const { return mTarget; }
   440     virtual bool Write() {
   441         DebugGLData::TexturePacket packet;
   442         char* dataptr = nullptr;
   443         uint32_t datasize = 0;
   444         std::auto_ptr<char> compresseddata;
   446         packet.type = mDataType;
   447         packet.ptr = static_cast<uint64_t>(mContextAddress);
   448         packet.layerref = reinterpret_cast<uint64_t>(mLayerRef);
   449         packet.name = mName;
   450         packet.format = 0;
   451         packet.target = mTarget;
   452         packet.dataFormat = LOCAL_GL_RGBA;
   454         if (mImage) {
   455             packet.width = mImage->GetSize().width;
   456             packet.height = mImage->GetSize().height;
   457             packet.stride = mImage->Stride();
   458             packet.dataSize = mImage->GetSize().height * mImage->Stride();
   460             dataptr = (char*) mImage->GetData();
   461             datasize = packet.dataSize;
   463             compresseddata = std::auto_ptr<char>((char*) moz_malloc(LZ4::maxCompressedSize(datasize)));
   464             if (compresseddata.get()) {
   465                 int ndatasize = LZ4::compress(dataptr, datasize, compresseddata.get());
   466                 if (ndatasize > 0) {
   467                     datasize = ndatasize;
   468                     dataptr = compresseddata.get();
   470                     packet.dataFormat = (1 << 16) | packet.dataFormat;
   471                     packet.dataSize = datasize;
   472                 }
   473             }
   474         } else {
   475             packet.width = 0;
   476             packet.height = 0;
   477             packet.stride = 0;
   478             packet.dataSize = 0;
   479         }
   481         // write the packet header data
   482         if (!WriteToStream(&packet, sizeof(packet)))
   483             return false;
   485         // then the image data
   486         if (!WriteToStream(dataptr, datasize))
   487             return false;
   489         // then pad out to 4 bytes
   490         if (datasize % 4 != 0) {
   491             static char buf[] = { 0, 0, 0, 0 };
   492             if (!WriteToStream(buf, 4 - (datasize % 4)))
   493                 return false;
   494         }
   496         return true;
   497     }
   499 protected:
   500     void* mLayerRef;
   501     GLenum mTarget;
   502     GLuint mName;
   503     RefPtr<DataSourceSurface> mImage;
   504 };
   506 class DebugGLColorData : public DebugGLData {
   507 public:
   508     DebugGLColorData(void* layerRef, const gfxRGBA& color, int width, int height)
   509         : DebugGLData(DebugGLData::ColorData),
   510           mColor(color.Packed()),
   511           mSize(width, height)
   512     { }
   514     void *GetLayerRef() const { return mLayerRef; }
   515     uint32_t GetColor() const { return mColor; }
   516     const nsIntSize& GetSize() const { return mSize; }
   518     virtual bool Write() {
   519         DebugGLData::ColorPacket packet;
   521         packet.type = mDataType;
   522         packet.ptr = static_cast<uint64_t>(mContextAddress);
   523         packet.layerref = reinterpret_cast<uintptr_t>(mLayerRef);
   524         packet.color = mColor;
   525         packet.width = mSize.width;
   526         packet.height = mSize.height;
   528         return WriteToStream(&packet, sizeof(packet));
   529     }
   531 protected:
   532     void *mLayerRef;
   533     uint32_t mColor;
   534     nsIntSize mSize;
   535 };
   537 static bool
   538 CheckSender()
   539 {
   540     if (!gLayerScopeWebSocketManager)
   541         return false;
   543     if (!gLayerScopeWebSocketManager->IsConnected())
   544         return false;
   546     return true;
   547 }
   549 class DebugListener : public nsIServerSocketListener
   550 {
   551 public:
   553     NS_DECL_THREADSAFE_ISUPPORTS
   555     DebugListener() { }
   556     virtual ~DebugListener() { }
   558     /* nsIServerSocketListener */
   560     NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
   561                                    nsISocketTransport *aTransport)
   562     {
   563         if (!gLayerScopeWebSocketManager)
   564             return NS_OK;
   566         printf_stderr("*** LayerScope: Accepted connection\n");
   567         gLayerScopeWebSocketManager->AddConnection(aTransport);
   568         return NS_OK;
   569     }
   571     NS_IMETHODIMP OnStopListening(nsIServerSocket *aServ,
   572                                   nsresult aStatus)
   573     {
   574         return NS_OK;
   575     }
   576 };
   578 NS_IMPL_ISUPPORTS(DebugListener, nsIServerSocketListener);
   581 class DebugDataSender : public nsIRunnable
   582 {
   583 public:
   585     NS_DECL_THREADSAFE_ISUPPORTS
   587     DebugDataSender() {
   588         mList = new LinkedList<DebugGLData>();
   589     }
   591     virtual ~DebugDataSender() {
   592         Cleanup();
   593     }
   595     void Append(DebugGLData *d) {
   596         mList->insertBack(d);
   597     }
   599     void Cleanup() {
   600         if (!mList)
   601             return;
   603         DebugGLData *d;
   604         while ((d = mList->popFirst()) != nullptr)
   605             delete d;
   606         delete mList;
   608         mList = nullptr;
   609     }
   611     /* nsIRunnable impl; send the data */
   613     NS_IMETHODIMP Run() {
   614         DebugGLData *d;
   615         nsresult rv = NS_OK;
   617         while ((d = mList->popFirst()) != nullptr) {
   618             std::auto_ptr<DebugGLData> cleaner(d);
   619             if (!d->Write()) {
   620                 rv = NS_ERROR_FAILURE;
   621                 break;
   622             }
   623         }
   625         Cleanup();
   627         if (NS_FAILED(rv)) {
   628             LayerScope::DestroyServerSocket();
   629         }
   631         return NS_OK;
   632     }
   634 protected:
   635     LinkedList<DebugGLData> *mList;
   636 };
   638 NS_IMPL_ISUPPORTS(DebugDataSender, nsIRunnable);
   640 void
   641 LayerScope::CreateServerSocket()
   642 {
   643     if (!gfxPrefs::LayerScopeEnabled()) {
   644         return;
   645     }
   647     if (!gLayerScopeWebSocketManager) {
   648         gLayerScopeWebSocketManager = new LayerScopeWebSocketManager();
   649     }
   650 }
   652 void
   653 LayerScope::DestroyServerSocket()
   654 {
   655     if (gLayerScopeWebSocketManager) {
   656         gLayerScopeWebSocketManager->RemoveAllConnections();
   657     }
   658 }
   660 void
   661 LayerScope::BeginFrame(GLContext* aGLContext, int64_t aFrameStamp)
   662 {
   663     if (!gLayerScopeWebSocketManager)
   664         return;
   666     if (!gLayerScopeWebSocketManager->IsConnected())
   667         return;
   669 #if 0
   670     // if we're sending data in between frames, flush the list down the socket,
   671     // and start a new one
   672     if (gCurrentSender) {
   673         gDebugSenderThread->Dispatch(gCurrentSender, NS_DISPATCH_NORMAL);
   674     }
   675 #endif
   677     gLayerScopeWebSocketManager->AppendDebugData(new DebugGLData(DebugGLData::FrameStart, aGLContext, aFrameStamp));
   678 }
   680 void
   681 LayerScope::EndFrame(GLContext* aGLContext)
   682 {
   683     if (!CheckSender())
   684         return;
   686     gLayerScopeWebSocketManager->AppendDebugData(new DebugGLData(DebugGLData::FrameEnd, aGLContext));
   687     gLayerScopeWebSocketManager->DispatchDebugData();
   688 }
   690 static void
   691 SendColor(void* aLayerRef, const gfxRGBA& aColor, int aWidth, int aHeight)
   692 {
   693     if (!CheckSender())
   694         return;
   696     gLayerScopeWebSocketManager->AppendDebugData(
   697         new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
   698 }
   700 static void
   701 SendTextureSource(GLContext* aGLContext,
   702                   void* aLayerRef,
   703                   TextureSourceOGL* aSource,
   704                   bool aFlipY)
   705 {
   706     GLenum textureTarget = aSource->GetTextureTarget();
   707     ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
   708                                                              aSource->GetFormat());
   709     int shaderConfig = config.mFeatures;
   711     aSource->BindTexture(LOCAL_GL_TEXTURE0, gfx::Filter::LINEAR);
   713     GLuint textureId = 0;
   714     // This is horrid hack. It assumes that aGLContext matches the context
   715     // aSource has bound to.
   716     if (textureTarget == LOCAL_GL_TEXTURE_2D) {
   717         aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &textureId);
   718     } else if (textureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
   719         aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &textureId);
   720     } else if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
   721         aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &textureId);
   722     }
   724     gfx::IntSize size = aSource->GetSize();
   726     // By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
   727     // texture correctly. textureId is used for tracking in DebugGLTextureData.
   728     RefPtr<DataSourceSurface> img =
   729         aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
   730                                                        size,
   731                                                        shaderConfig, aFlipY);
   733     gLayerScopeWebSocketManager->AppendDebugData(
   734         new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
   735                                textureId, img));
   736 }
   738 static void
   739 SendTexturedEffect(GLContext* aGLContext,
   740                    void* aLayerRef,
   741                    const TexturedEffect* aEffect)
   742 {
   743     TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
   744     if (!source)
   745         return;
   747     bool flipY = false;
   748     SendTextureSource(aGLContext, aLayerRef, source, flipY);
   749 }
   751 static void
   752 SendYCbCrEffect(GLContext* aGLContext,
   753                 void* aLayerRef,
   754                 const EffectYCbCr* aEffect)
   755 {
   756     TextureSource* sourceYCbCr = aEffect->mTexture;
   757     if (!sourceYCbCr)
   758         return;
   760     const int Y = 0, Cb = 1, Cr = 2;
   761     TextureSourceOGL* sourceY =  sourceYCbCr->GetSubSource(Y)->AsSourceOGL();
   762     TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
   763     TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
   765     bool flipY = false;
   766     SendTextureSource(aGLContext, aLayerRef, sourceY,  flipY);
   767     SendTextureSource(aGLContext, aLayerRef, sourceCb, flipY);
   768     SendTextureSource(aGLContext, aLayerRef, sourceCr, flipY);
   769 }
   771 void
   772 LayerScope::SendEffectChain(GLContext* aGLContext,
   773                             const EffectChain& aEffectChain,
   774                             int aWidth, int aHeight)
   775 {
   776     if (!CheckSender())
   777         return;
   779     const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
   780     switch (primaryEffect->mType) {
   781     case EFFECT_RGB:
   782     {
   783         const TexturedEffect* texturedEffect =
   784             static_cast<const TexturedEffect*>(primaryEffect);
   785         SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
   786     }
   787     break;
   788     case EFFECT_YCBCR:
   789     {
   790         const EffectYCbCr* yCbCrEffect =
   791             static_cast<const EffectYCbCr*>(primaryEffect);
   792         SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
   793     }
   794     case EFFECT_SOLID_COLOR:
   795     {
   796         const EffectSolidColor* solidColorEffect =
   797             static_cast<const EffectSolidColor*>(primaryEffect);
   798         gfxRGBA color(solidColorEffect->mColor.r,
   799                       solidColorEffect->mColor.g,
   800                       solidColorEffect->mColor.b,
   801                       solidColorEffect->mColor.a);
   802         SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight);
   803     }
   804     break;
   805     case EFFECT_COMPONENT_ALPHA:
   806     case EFFECT_RENDER_TARGET:
   807     default:
   808         break;
   809     }
   811     //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EFFECT_MASK];
   812     // TODO:
   813 }
   815 LayerScopeWebSocketManager::LayerScopeWebSocketManager()
   816 {
   817     NS_NewThread(getter_AddRefs(mDebugSenderThread));
   819     mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
   820     int port = gfxPrefs::LayerScopePort();
   821     mServerSocket->Init(port, false, -1);
   822     mServerSocket->AsyncListen(new DebugListener);
   823 }
   825 LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
   826 {
   827 }
   829 void LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
   830 {
   831     if (!mCurrentSender) {
   832         mCurrentSender = new DebugDataSender();
   833     }
   835     mCurrentSender->Append(aDebugData);
   836 }
   838 void LayerScopeWebSocketManager::DispatchDebugData()
   839 {
   840     mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL);
   841     mCurrentSender = nullptr;
   842 }
   844 } /* layers */
   845 } /* mozilla */

mercurial