Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=99: */
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 : #include "PaintThread.h"
8 :
9 : #include "base/task.h"
10 : #include "gfxPrefs.h"
11 : #include "mozilla/layers/CompositorBridgeChild.h"
12 : #include "mozilla/gfx/2D.h"
13 : #include "mozilla/Preferences.h"
14 : #include "mozilla/SyncRunnable.h"
15 :
16 : namespace mozilla {
17 : namespace layers {
18 :
19 : using namespace gfx;
20 :
21 3 : StaticAutoPtr<PaintThread> PaintThread::sSingleton;
22 3 : StaticRefPtr<nsIThread> PaintThread::sThread;
23 : PlatformThreadId PaintThread::sThreadId;
24 :
25 : void
26 0 : PaintThread::Release()
27 : {
28 0 : }
29 :
30 : void
31 0 : PaintThread::AddRef()
32 : {
33 0 : }
34 :
35 : void
36 0 : PaintThread::InitOnPaintThread()
37 : {
38 0 : MOZ_ASSERT(!NS_IsMainThread());
39 0 : sThreadId = PlatformThread::CurrentId();
40 0 : }
41 :
42 : bool
43 0 : PaintThread::Init()
44 : {
45 0 : MOZ_ASSERT(NS_IsMainThread());
46 :
47 0 : RefPtr<nsIThread> thread;
48 0 : nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(thread));
49 0 : if (NS_FAILED(rv)) {
50 0 : return false;
51 : }
52 0 : sThread = thread;
53 :
54 : nsCOMPtr<nsIRunnable> paintInitTask =
55 0 : NewRunnableMethod("PaintThread::InitOnPaintThread",
56 0 : this, &PaintThread::InitOnPaintThread);
57 0 : SyncRunnable::DispatchToThread(sThread, paintInitTask);
58 0 : return true;
59 : }
60 :
61 : /* static */ void
62 0 : PaintThread::Start()
63 : {
64 0 : PaintThread::sSingleton = new PaintThread();
65 :
66 0 : if (!PaintThread::sSingleton->Init()) {
67 0 : gfxCriticalNote << "Unable to start paint thread";
68 0 : PaintThread::sSingleton = nullptr;
69 : }
70 0 : }
71 :
72 : /* static */ PaintThread*
73 77 : PaintThread::Get()
74 : {
75 77 : MOZ_ASSERT(NS_IsMainThread());
76 77 : return PaintThread::sSingleton.get();
77 : }
78 :
79 : void
80 0 : DestroyPaintThread(UniquePtr<PaintThread>&& pt)
81 : {
82 0 : MOZ_ASSERT(PaintThread::IsOnPaintThread());
83 0 : pt->ShutdownOnPaintThread();
84 0 : }
85 :
86 : /* static */ void
87 0 : PaintThread::Shutdown()
88 : {
89 0 : MOZ_ASSERT(NS_IsMainThread());
90 :
91 0 : UniquePtr<PaintThread> pt(sSingleton.forget());
92 0 : if (!pt) {
93 0 : return;
94 : }
95 :
96 0 : sThread->Dispatch(NewRunnableFunction(DestroyPaintThread, Move(pt)));
97 0 : sThread->Shutdown();
98 0 : sThread = nullptr;
99 : }
100 :
101 : void
102 0 : PaintThread::ShutdownOnPaintThread()
103 : {
104 0 : MOZ_ASSERT(IsOnPaintThread());
105 0 : }
106 :
107 : /* static */ bool
108 0 : PaintThread::IsOnPaintThread()
109 : {
110 0 : return sThreadId == PlatformThread::CurrentId();
111 : }
112 :
113 : void
114 0 : PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
115 : gfx::DrawTargetCapture* aCapture,
116 : gfx::DrawTarget* aTarget)
117 : {
118 0 : MOZ_ASSERT(IsOnPaintThread());
119 :
120 : // Draw all the things into the actual dest target.
121 0 : aTarget->DrawCapturedDT(aCapture, Matrix());
122 :
123 0 : if (aBridge) {
124 0 : aBridge->NotifyFinishedAsyncPaint();
125 : }
126 0 : }
127 :
128 : void
129 0 : PaintThread::PaintContents(DrawTargetCapture* aCapture,
130 : DrawTarget* aTarget)
131 : {
132 0 : MOZ_ASSERT(NS_IsMainThread());
133 :
134 : // If painting asynchronously, we need to acquire the compositor bridge which
135 : // owns the underlying MessageChannel. Otherwise we leave it null and use
136 : // synchronous dispatch.
137 0 : RefPtr<CompositorBridgeChild> cbc;
138 0 : if (!gfxPrefs::LayersOMTPForceSync()) {
139 0 : cbc = CompositorBridgeChild::Get();
140 0 : cbc->NotifyBeginAsyncPaint();
141 : }
142 0 : RefPtr<DrawTargetCapture> capture(aCapture);
143 0 : RefPtr<DrawTarget> target(aTarget);
144 :
145 0 : RefPtr<PaintThread> self = this;
146 0 : RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
147 0 : [self, cbc, capture, target]() -> void
148 : {
149 0 : self->PaintContentsAsync(cbc, capture, target);
150 0 : });
151 :
152 0 : if (cbc) {
153 0 : sThread->Dispatch(task.forget());
154 : } else {
155 0 : SyncRunnable::DispatchToThread(sThread, task);
156 : }
157 0 : }
158 :
159 : } // namespace layers
160 : } // namespace mozilla
|