Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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 */