Bumping manifests a=b2g-bump
[gecko.git] / gfx / layers / LayerScope.cpp
blob649dbbdf702ed9fb941111cb7caa6c41f03cd9ac
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/CompositorOGL.h"
16 #include "mozilla/layers/LayerManagerComposite.h"
17 #include "mozilla/layers/TextureHostOGL.h"
19 #include "gfxColor.h"
20 #include "gfxContext.h"
21 #include "gfxUtils.h"
22 #include "gfxPrefs.h"
23 #include "nsIWidget.h"
25 #include "GLContext.h"
26 #include "GLContextProvider.h"
27 #include "GLReadTexImageHelper.h"
29 #include "nsIServiceManager.h"
30 #include "nsIConsoleService.h"
32 #include <memory>
33 #include "mozilla/LinkedList.h"
34 #include "mozilla/Base64.h"
35 #include "mozilla/SHA1.h"
36 #include "mozilla/StaticPtr.h"
37 #include "nsThreadUtils.h"
38 #include "nsISocketTransport.h"
39 #include "nsIServerSocket.h"
40 #include "nsReadLine.h"
41 #include "nsNetCID.h"
42 #include "nsIOutputStream.h"
43 #include "nsIAsyncInputStream.h"
44 #include "nsIEventTarget.h"
45 #include "nsProxyRelease.h"
47 // Undo the damage done by mozzconf.h
48 #undef compress
49 #include "mozilla/Compression.h"
51 // Protocol buffer (generated automatically)
52 #include "protobuf/LayerScopePacket.pb.h"
54 namespace mozilla {
55 namespace layers {
57 using namespace mozilla::Compression;
58 using namespace mozilla::gfx;
59 using namespace mozilla::gl;
60 using namespace mozilla;
61 using namespace layerscope;
63 class DebugDataSender;
64 class DebugGLData;
66 /* This class handle websocket protocol which included
67 * handshake and data frame's header
69 class LayerScopeWebSocketHandler : public nsIInputStreamCallback {
70 public:
71 NS_DECL_THREADSAFE_ISUPPORTS
73 enum SocketStateType {
74 NoHandshake,
75 HandshakeSuccess,
76 HandshakeFailed
79 LayerScopeWebSocketHandler()
80 : mState(NoHandshake)
81 { }
83 private:
84 virtual ~LayerScopeWebSocketHandler()
86 if (mTransport) {
87 mTransport->Close(NS_OK);
91 public:
92 void OpenStream(nsISocketTransport* aTransport) {
93 MOZ_ASSERT(aTransport);
95 mTransport = aTransport;
96 mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
99 getter_AddRefs(mOutputStream));
101 nsCOMPtr<nsIInputStream> debugInputStream;
102 mTransport->OpenInputStream(0,
105 getter_AddRefs(debugInputStream));
106 mInputStream = do_QueryInterface(debugInputStream);
107 mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
110 bool WriteToStream(void *ptr, uint32_t size) {
111 if (mState == NoHandshake) {
112 // Not yet handshake, just return true in case of
113 // LayerScope remove this handle
114 return true;
115 } else if (mState == HandshakeFailed) {
116 return false;
119 // Generate WebSocket header
120 uint8_t wsHeader[10];
121 int wsHeaderSize = 0;
122 const uint8_t opcode = 0x2;
123 wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
124 if (size <= 125) {
125 wsHeaderSize = 2;
126 wsHeader[1] = size;
127 } else if (size < 65536) {
128 wsHeaderSize = 4;
129 wsHeader[1] = 0x7E;
130 NetworkEndian::writeUint16(wsHeader + 2, size);
131 } else {
132 wsHeaderSize = 10;
133 wsHeader[1] = 0x7F;
134 NetworkEndian::writeUint64(wsHeader + 2, size);
137 // Send WebSocket header
138 nsresult rv;
139 uint32_t cnt;
140 rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
141 wsHeaderSize, &cnt);
142 if (NS_FAILED(rv))
143 return false;
145 uint32_t written = 0;
146 while (written < size) {
147 uint32_t cnt;
148 rv = mOutputStream->Write(reinterpret_cast<char*>(ptr) + written,
149 size - written, &cnt);
150 if (NS_FAILED(rv))
151 return false;
153 written += cnt;
156 return true;
159 // nsIInputStreamCallback
160 NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *stream) MOZ_OVERRIDE
162 nsTArray<nsCString> protocolString;
163 ReadInputStreamData(protocolString);
165 if (WebSocketHandshake(protocolString)) {
166 mState = HandshakeSuccess;
167 } else {
168 mState = HandshakeFailed;
170 return NS_OK;
172 private:
173 void ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
175 nsLineBuffer<char> lineBuffer;
176 nsCString line;
177 bool more = true;
178 do {
179 NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
181 if (line.Length() > 0) {
182 aProtocolString.AppendElement(line);
184 } while (more && line.Length() > 0);
187 bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
189 nsresult rv;
190 bool isWebSocket = false;
191 nsCString version;
192 nsCString wsKey;
193 nsCString protocol;
195 // Validate WebSocket client request.
196 if (aProtocolString.Length() == 0)
197 return false;
199 // Check that the HTTP method is GET
200 const char* HTTP_METHOD = "GET ";
201 if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
202 return false;
205 for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
206 const char* line = aProtocolString[i].get();
207 const char* prop_pos = strchr(line, ':');
208 if (prop_pos != nullptr) {
209 nsCString key(line, prop_pos - line);
210 nsCString value(prop_pos + 2);
211 if (key.EqualsIgnoreCase("upgrade") &&
212 value.EqualsIgnoreCase("websocket")) {
213 isWebSocket = true;
214 } else if (key.EqualsIgnoreCase("sec-websocket-version")) {
215 version = value;
216 } else if (key.EqualsIgnoreCase("sec-websocket-key")) {
217 wsKey = value;
218 } else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
219 protocol = value;
224 if (!isWebSocket) {
225 return false;
228 if (!(version.EqualsLiteral("7") ||
229 version.EqualsLiteral("8") ||
230 version.EqualsLiteral("13"))) {
231 return false;
234 if (!(protocol.EqualsIgnoreCase("binary"))) {
235 return false;
238 // Client request is valid. Start to generate and send server response.
239 nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
240 nsAutoCString res;
241 SHA1Sum sha1;
242 nsCString combined(wsKey + guid);
243 sha1.update(combined.get(), combined.Length());
244 uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
245 sha1.finish(digest);
246 nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
247 Base64Encode(newString, res);
249 nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
250 response.AppendLiteral("Upgrade: websocket\r\n");
251 response.AppendLiteral("Connection: Upgrade\r\n");
252 response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
253 response.AppendLiteral("Sec-WebSocket-Protocol: binary\r\n\r\n");
254 uint32_t written = 0;
255 uint32_t size = response.Length();
256 while (written < size) {
257 uint32_t cnt;
258 rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
259 size - written, &cnt);
260 if (NS_FAILED(rv))
261 return false;
263 written += cnt;
265 mOutputStream->Flush();
267 return true;
270 nsCOMPtr<nsIOutputStream> mOutputStream;
271 nsCOMPtr<nsIAsyncInputStream> mInputStream;
272 nsCOMPtr<nsISocketTransport> mTransport;
273 SocketStateType mState;
276 NS_IMPL_ISUPPORTS(LayerScopeWebSocketHandler, nsIInputStreamCallback);
278 class LayerScopeWebSocketManager {
279 public:
280 LayerScopeWebSocketManager();
281 ~LayerScopeWebSocketManager();
283 void AddConnection(nsISocketTransport *aTransport)
285 MOZ_ASSERT(aTransport);
286 nsRefPtr<LayerScopeWebSocketHandler> temp = new LayerScopeWebSocketHandler();
287 temp->OpenStream(aTransport);
288 mHandlers.AppendElement(temp.get());
291 void RemoveConnection(uint32_t aIndex)
293 MOZ_ASSERT(aIndex < mHandlers.Length());
294 mHandlers.RemoveElementAt(aIndex);
297 void RemoveAllConnections()
299 mHandlers.Clear();
302 bool WriteAll(void *ptr, uint32_t size)
304 for (int32_t i = mHandlers.Length() - 1; i >= 0; --i) {
305 if (!mHandlers[i]->WriteToStream(ptr, size)) {
306 // Send failed, remove this handler
307 RemoveConnection(i);
311 return true;
314 bool IsConnected()
316 return (mHandlers.Length() != 0) ? true : false;
319 void AppendDebugData(DebugGLData *aDebugData);
320 void CleanDebugData();
321 void DispatchDebugData();
322 private:
323 nsTArray<nsRefPtr<LayerScopeWebSocketHandler> > mHandlers;
324 nsCOMPtr<nsIThread> mDebugSenderThread;
325 nsRefPtr<DebugDataSender> mCurrentSender;
326 nsCOMPtr<nsIServerSocket> mServerSocket;
329 // Static class to create and destory LayerScopeWebSocketManager object
330 class WebSocketHelper
332 public:
333 static void CreateServerSocket()
335 // Create Web Server Socket (which has to be on the main thread)
336 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
337 if (!sWebSocketManager) {
338 sWebSocketManager = new LayerScopeWebSocketManager();
342 static void DestroyServerSocket()
344 // Destroy Web Server Socket
345 if (sWebSocketManager) {
346 sWebSocketManager->RemoveAllConnections();
350 static LayerScopeWebSocketManager* GetSocketManager()
352 return sWebSocketManager;
355 private:
356 static StaticAutoPtr<LayerScopeWebSocketManager> sWebSocketManager;
359 StaticAutoPtr<LayerScopeWebSocketManager> WebSocketHelper::sWebSocketManager;
362 * DebugGLData is the base class of
363 * 1. DebugGLFrameStatusData (Frame start/end packet)
364 * 2. DebugGLColorData (Color data packet)
365 * 3. DebugGLTextureData (Texture data packet)
367 class DebugGLData: public LinkedListElement<DebugGLData> {
368 public:
369 explicit DebugGLData(Packet::DataType aDataType)
370 : mDataType(aDataType)
373 virtual ~DebugGLData() { }
375 Packet::DataType GetDataType() const { return mDataType; }
377 virtual bool Write() = 0;
379 static bool WriteToStream(Packet& aPacket) {
380 if (!WebSocketHelper::GetSocketManager())
381 return true;
383 uint32_t size = aPacket.ByteSize();
384 auto data = MakeUnique<uint8_t[]>(size);
385 aPacket.SerializeToArray(data.get(), size);
386 return WebSocketHelper::GetSocketManager()->WriteAll(data.get(), size);
389 protected:
390 Packet::DataType mDataType;
393 class DebugGLFrameStatusData : public DebugGLData
395 public:
396 DebugGLFrameStatusData(Packet::DataType aDataType,
397 int64_t aValue)
398 : DebugGLData(aDataType),
399 mFrameStamp(aValue)
402 explicit DebugGLFrameStatusData(Packet::DataType aDataType)
403 : DebugGLData(aDataType),
404 mFrameStamp(0)
407 int64_t GetFrameStamp() const { return mFrameStamp; }
409 virtual bool Write() MOZ_OVERRIDE {
410 Packet packet;
411 packet.set_type(mDataType);
413 FramePacket* fp = packet.mutable_frame();
414 fp->set_value(static_cast<uint64_t>(mFrameStamp));
416 if (!WriteToStream(packet))
417 return false;
418 return true;
421 protected:
422 int64_t mFrameStamp;
425 class DebugGLTextureData : public DebugGLData {
426 public:
427 DebugGLTextureData(GLContext* cx,
428 void* layerRef,
429 GLenum target,
430 GLuint name,
431 DataSourceSurface* img)
432 : DebugGLData(Packet::TEXTURE),
433 mLayerRef(layerRef),
434 mTarget(target),
435 mName(name),
436 mContextAddress(reinterpret_cast<intptr_t>(cx)),
437 mDatasize(0)
439 // pre-packing
440 // DataSourceSurface may have locked buffer,
441 // so we should compress now, and then it could
442 // be unlocked outside.
443 pack(img);
446 const void* GetLayerRef() const { return mLayerRef; }
447 GLuint GetName() const { return mName; }
448 GLenum GetTextureTarget() const { return mTarget; }
449 intptr_t GetContextAddress() const { return mContextAddress; }
450 uint32_t GetDataSize() const { return mDatasize; }
452 virtual bool Write() MOZ_OVERRIDE {
453 if (!WriteToStream(mPacket))
454 return false;
455 return true;
458 private:
459 void pack(DataSourceSurface* aImage) {
460 mPacket.set_type(mDataType);
462 TexturePacket* tp = mPacket.mutable_texture();
463 tp->set_layerref(reinterpret_cast<uint64_t>(mLayerRef));
464 tp->set_name(mName);
465 tp->set_target(mTarget);
466 tp->set_dataformat(LOCAL_GL_RGBA);
467 tp->set_glcontext(static_cast<uint64_t>(mContextAddress));
469 if (aImage) {
470 tp->set_width(aImage->GetSize().width);
471 tp->set_height(aImage->GetSize().height);
472 tp->set_stride(aImage->Stride());
474 mDatasize = aImage->GetSize().height * aImage->Stride();
476 auto compresseddata = MakeUnique<char[]>(LZ4::maxCompressedSize(mDatasize));
477 if (compresseddata) {
478 int ndatasize = LZ4::compress((char*)aImage->GetData(),
479 mDatasize,
480 compresseddata.get());
481 if (ndatasize > 0) {
482 mDatasize = ndatasize;
483 tp->set_dataformat((1 << 16 | tp->dataformat()));
484 tp->set_data(compresseddata.get(), mDatasize);
485 } else {
486 NS_WARNING("Compress data failed");
487 tp->set_data(aImage->GetData(), mDatasize);
489 } else {
490 NS_WARNING("Couldn't new compressed data.");
491 tp->set_data(aImage->GetData(), mDatasize);
493 } else {
494 tp->set_width(0);
495 tp->set_height(0);
496 tp->set_stride(0);
500 protected:
501 void* mLayerRef;
502 GLenum mTarget;
503 GLuint mName;
504 intptr_t mContextAddress;
505 uint32_t mDatasize;
507 // Packet data
508 Packet mPacket;
511 class DebugGLColorData : public DebugGLData {
512 public:
513 DebugGLColorData(void* layerRef,
514 const gfxRGBA& color,
515 int width,
516 int height)
517 : DebugGLData(Packet::COLOR),
518 mLayerRef(layerRef),
519 mColor(color.Packed()),
520 mSize(width, height)
523 const void* GetLayerRef() const { return mLayerRef; }
524 uint32_t GetColor() const { return mColor; }
525 const nsIntSize& GetSize() const { return mSize; }
527 virtual bool Write() MOZ_OVERRIDE {
528 Packet packet;
529 packet.set_type(mDataType);
531 ColorPacket* cp = packet.mutable_color();
532 cp->set_layerref(reinterpret_cast<uint64_t>(mLayerRef));
533 cp->set_color(mColor);
534 cp->set_width(mSize.width);
535 cp->set_height(mSize.height);
537 if (!WriteToStream(packet))
538 return false;
539 return true;
542 protected:
543 void* mLayerRef;
544 uint32_t mColor;
545 nsIntSize mSize;
548 class DebugGLLayersData : public DebugGLData {
549 public:
550 explicit DebugGLLayersData(UniquePtr<Packet> aPacket)
551 : DebugGLData(Packet::LAYERS),
552 mPacket(Move(aPacket))
555 virtual bool Write() MOZ_OVERRIDE {
556 mPacket->set_type(mDataType);
558 if (!WriteToStream(*mPacket))
559 return false;
560 return true;
563 protected:
564 UniquePtr<Packet> mPacket;
567 class DebugListener : public nsIServerSocketListener
569 virtual ~DebugListener() { }
571 public:
573 NS_DECL_THREADSAFE_ISUPPORTS
575 DebugListener() { }
577 /* nsIServerSocketListener */
579 NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
580 nsISocketTransport *aTransport)
582 if (!WebSocketHelper::GetSocketManager())
583 return NS_OK;
585 printf_stderr("*** LayerScope: Accepted connection\n");
586 WebSocketHelper::GetSocketManager()->AddConnection(aTransport);
587 return NS_OK;
590 NS_IMETHODIMP OnStopListening(nsIServerSocket *aServ,
591 nsresult aStatus)
593 return NS_OK;
597 NS_IMPL_ISUPPORTS(DebugListener, nsIServerSocketListener);
600 class DebugDataSender : public nsIRunnable
602 virtual ~DebugDataSender() {
603 Cleanup();
606 public:
608 NS_DECL_THREADSAFE_ISUPPORTS
610 DebugDataSender() { }
612 void Append(DebugGLData *d) {
613 mList.insertBack(d);
616 void Cleanup() {
617 if (mList.isEmpty())
618 return;
620 DebugGLData *d;
621 while ((d = mList.popFirst()) != nullptr)
622 delete d;
625 /* nsIRunnable impl; send the data */
627 NS_IMETHODIMP Run() {
628 DebugGLData *d;
629 nsresult rv = NS_OK;
631 while ((d = mList.popFirst()) != nullptr) {
632 UniquePtr<DebugGLData> cleaner(d);
633 if (!d->Write()) {
634 rv = NS_ERROR_FAILURE;
635 break;
639 Cleanup();
641 if (NS_FAILED(rv)) {
642 WebSocketHelper::DestroyServerSocket();
645 return NS_OK;
648 protected:
649 LinkedList<DebugGLData> mList;
652 NS_IMPL_ISUPPORTS(DebugDataSender, nsIRunnable);
655 * LayerScope SendXXX Structure
656 * 1. SendLayer
657 * 2. SendEffectChain
658 * 1. SendTexturedEffect
659 * -> SendTextureSource
660 * 2. SendYCbCrEffect
661 * -> SendTextureSource
662 * 3. SendColor
664 class SenderHelper
666 // Sender public APIs
667 public:
668 static void SendLayer(LayerComposite* aLayer,
669 int aWidth,
670 int aHeight);
672 static void SendEffectChain(gl::GLContext* aGLContext,
673 const EffectChain& aEffectChain,
674 int aWidth = 0,
675 int aHeight = 0);
677 // Sender private functions
678 private:
679 static void SendColor(void* aLayerRef,
680 const gfxRGBA& aColor,
681 int aWidth,
682 int aHeight);
683 static void SendTextureSource(GLContext* aGLContext,
684 void* aLayerRef,
685 TextureSourceOGL* aSource,
686 bool aFlipY);
687 static void SendTexturedEffect(GLContext* aGLContext,
688 void* aLayerRef,
689 const TexturedEffect* aEffect);
690 static void SendYCbCrEffect(GLContext* aGLContext,
691 void* aLayerRef,
692 const EffectYCbCr* aEffect);
696 // ----------------------------------------------
697 // SenderHelper implementation
698 // ----------------------------------------------
699 void
700 SenderHelper::SendLayer(LayerComposite* aLayer,
701 int aWidth,
702 int aHeight)
704 MOZ_ASSERT(aLayer && aLayer->GetLayer());
705 if (!aLayer || !aLayer->GetLayer()) {
706 return;
709 switch (aLayer->GetLayer()->GetType()) {
710 case Layer::TYPE_COLOR: {
711 EffectChain effect;
712 aLayer->GenEffectChain(effect);
713 SenderHelper::SendEffectChain(nullptr, effect, aWidth, aHeight);
714 break;
716 case Layer::TYPE_IMAGE:
717 case Layer::TYPE_CANVAS:
718 case Layer::TYPE_THEBES: {
719 // Get CompositableHost and Compositor
720 CompositableHost* compHost = aLayer->GetCompositableHost();
721 Compositor* comp = compHost->GetCompositor();
722 // Send EffectChain only for CompositorOGL
723 if (LayersBackend::LAYERS_OPENGL == comp->GetBackendType()) {
724 CompositorOGL* compOGL = static_cast<CompositorOGL*>(comp);
725 EffectChain effect;
726 // Generate primary effect (lock and gen)
727 AutoLockCompositableHost lock(compHost);
728 aLayer->GenEffectChain(effect);
729 SenderHelper::SendEffectChain(compOGL->gl(), effect);
731 break;
733 case Layer::TYPE_CONTAINER:
734 default:
735 break;
739 void
740 SenderHelper::SendColor(void* aLayerRef,
741 const gfxRGBA& aColor,
742 int aWidth,
743 int aHeight)
745 WebSocketHelper::GetSocketManager()->AppendDebugData(
746 new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
749 void
750 SenderHelper::SendTextureSource(GLContext* aGLContext,
751 void* aLayerRef,
752 TextureSourceOGL* aSource,
753 bool aFlipY)
755 MOZ_ASSERT(aGLContext);
756 if (!aGLContext) {
757 return;
760 GLenum textureTarget = aSource->GetTextureTarget();
761 ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
762 aSource->GetFormat());
763 int shaderConfig = config.mFeatures;
765 aSource->BindTexture(LOCAL_GL_TEXTURE0, gfx::Filter::LINEAR);
767 GLuint textureId = 0;
768 // This is horrid hack. It assumes that aGLContext matches the context
769 // aSource has bound to.
770 if (textureTarget == LOCAL_GL_TEXTURE_2D) {
771 aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &textureId);
772 } else if (textureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
773 aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &textureId);
774 } else if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
775 aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &textureId);
778 gfx::IntSize size = aSource->GetSize();
780 // By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
781 // texture correctly. textureId is used for tracking in DebugGLTextureData.
782 RefPtr<DataSourceSurface> img =
783 aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
784 size,
785 shaderConfig, aFlipY);
787 WebSocketHelper::GetSocketManager()->AppendDebugData(
788 new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
789 textureId, img));
792 void
793 SenderHelper::SendTexturedEffect(GLContext* aGLContext,
794 void* aLayerRef,
795 const TexturedEffect* aEffect)
797 TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
798 if (!source)
799 return;
801 bool flipY = false;
802 SendTextureSource(aGLContext, aLayerRef, source, flipY);
805 void
806 SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
807 void* aLayerRef,
808 const EffectYCbCr* aEffect)
810 TextureSource* sourceYCbCr = aEffect->mTexture;
811 if (!sourceYCbCr)
812 return;
814 const int Y = 0, Cb = 1, Cr = 2;
815 TextureSourceOGL* sourceY = sourceYCbCr->GetSubSource(Y)->AsSourceOGL();
816 TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
817 TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
819 bool flipY = false;
820 SendTextureSource(aGLContext, aLayerRef, sourceY, flipY);
821 SendTextureSource(aGLContext, aLayerRef, sourceCb, flipY);
822 SendTextureSource(aGLContext, aLayerRef, sourceCr, flipY);
825 void
826 SenderHelper::SendEffectChain(GLContext* aGLContext,
827 const EffectChain& aEffectChain,
828 int aWidth,
829 int aHeight)
831 const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
832 switch (primaryEffect->mType) {
833 case EffectTypes::RGB: {
834 const TexturedEffect* texturedEffect =
835 static_cast<const TexturedEffect*>(primaryEffect);
836 SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
837 break;
839 case EffectTypes::YCBCR: {
840 const EffectYCbCr* yCbCrEffect =
841 static_cast<const EffectYCbCr*>(primaryEffect);
842 SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
843 break;
845 case EffectTypes::SOLID_COLOR: {
846 const EffectSolidColor* solidColorEffect =
847 static_cast<const EffectSolidColor*>(primaryEffect);
848 gfxRGBA color(solidColorEffect->mColor.r,
849 solidColorEffect->mColor.g,
850 solidColorEffect->mColor.b,
851 solidColorEffect->mColor.a);
852 SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight);
853 break;
855 case EffectTypes::COMPONENT_ALPHA:
856 case EffectTypes::RENDER_TARGET:
857 default:
858 break;
861 //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK];
862 // TODO:
865 // ----------------------------------------------
866 // LayerScopeWebSocketManager implementation
867 // ----------------------------------------------
868 LayerScopeWebSocketManager::LayerScopeWebSocketManager()
870 NS_NewThread(getter_AddRefs(mDebugSenderThread));
872 mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
873 int port = gfxPrefs::LayerScopePort();
874 mServerSocket->Init(port, false, -1);
875 mServerSocket->AsyncListen(new DebugListener);
878 LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
882 void
883 LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
885 if (!mCurrentSender) {
886 mCurrentSender = new DebugDataSender();
889 mCurrentSender->Append(aDebugData);
892 void
893 LayerScopeWebSocketManager::CleanDebugData()
895 if (mCurrentSender) {
896 mCurrentSender->Cleanup();
900 void
901 LayerScopeWebSocketManager::DispatchDebugData()
903 mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL);
904 mCurrentSender = nullptr;
908 // ----------------------------------------------
909 // LayerScope implementation
910 // ----------------------------------------------
911 void
912 LayerScope::Init()
914 if (!gfxPrefs::LayerScopeEnabled()) {
915 return;
918 // Note: The server socket has to be created on the main thread
919 WebSocketHelper::CreateServerSocket();
922 void
923 LayerScope::DeInit()
925 // Destroy Web Server Socket
926 WebSocketHelper::DestroyServerSocket();
929 void
930 LayerScope::SendEffectChain(gl::GLContext* aGLContext,
931 const EffectChain& aEffectChain,
932 int aWidth,
933 int aHeight)
935 // Protect this public function
936 if (!CheckSendable()) {
937 return;
939 SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight);
942 void
943 LayerScope::SendLayer(LayerComposite* aLayer,
944 int aWidth,
945 int aHeight)
947 // Protect this public function
948 if (!CheckSendable()) {
949 return;
951 SenderHelper::SendLayer(aLayer, aWidth, aHeight);
954 void
955 LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
957 // Protect this public function
958 if (!CheckSendable()) {
959 return;
961 WebSocketHelper::GetSocketManager()->AppendDebugData(
962 new DebugGLLayersData(Move(aPacket)));
965 bool
966 LayerScope::CheckSendable()
968 if (!WebSocketHelper::GetSocketManager()) {
969 return false;
971 if (!WebSocketHelper::GetSocketManager()->IsConnected()) {
972 return false;
974 return true;
977 void
978 LayerScope::CleanLayer()
980 if (CheckSendable()) {
981 WebSocketHelper::GetSocketManager()->CleanDebugData();
985 // ----------------------------------------------
986 // LayerScopeAutoFrame implementation
987 // ----------------------------------------------
988 LayerScopeAutoFrame::LayerScopeAutoFrame(int64_t aFrameStamp)
990 // Do Begin Frame
991 BeginFrame(aFrameStamp);
994 LayerScopeAutoFrame::~LayerScopeAutoFrame()
996 // Do End Frame
997 EndFrame();
1000 void
1001 LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
1003 if (!LayerScope::CheckSendable()) {
1004 return;
1007 WebSocketHelper::GetSocketManager()->AppendDebugData(
1008 new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));
1011 void
1012 LayerScopeAutoFrame::EndFrame()
1014 if (!LayerScope::CheckSendable()) {
1015 return;
1018 WebSocketHelper::GetSocketManager()->AppendDebugData(
1019 new DebugGLFrameStatusData(Packet::FRAMEEND));
1020 WebSocketHelper::GetSocketManager()->DispatchDebugData();
1023 } /* layers */
1024 } /* mozilla */