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