|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
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/. */ |
|
5 |
|
6 #include "mozilla/layers/Compositor.h" |
|
7 #include "base/message_loop.h" // for MessageLoop |
|
8 #include "mozilla/layers/CompositorParent.h" // for CompositorParent |
|
9 #include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc |
|
10 #include "mozilla/mozalloc.h" // for operator delete, etc |
|
11 #include "gfx2DGlue.h" |
|
12 |
|
13 namespace mozilla { |
|
14 namespace gfx { |
|
15 class Matrix4x4; |
|
16 } |
|
17 |
|
18 namespace layers { |
|
19 |
|
20 /* static */ LayersBackend Compositor::sBackend = LayersBackend::LAYERS_NONE; |
|
21 /* static */ LayersBackend |
|
22 Compositor::GetBackend() |
|
23 { |
|
24 AssertOnCompositorThread(); |
|
25 return sBackend; |
|
26 } |
|
27 |
|
28 /* static */ void |
|
29 Compositor::SetBackend(LayersBackend backend) |
|
30 { |
|
31 if (sBackend != LayersBackend::LAYERS_NONE && sBackend != backend) { |
|
32 // Assert this once we figure out bug 972891. |
|
33 //MOZ_CRASH("Trying to use more than one OMTC compositor."); |
|
34 |
|
35 #ifdef XP_MACOSX |
|
36 printf("ERROR: Changing compositor from %u to %u.\n", |
|
37 unsigned(sBackend), unsigned(backend)); |
|
38 #endif |
|
39 } |
|
40 sBackend = backend; |
|
41 } |
|
42 |
|
43 /* static */ void |
|
44 Compositor::AssertOnCompositorThread() |
|
45 { |
|
46 MOZ_ASSERT(CompositorParent::CompositorLoop() == |
|
47 MessageLoop::current(), |
|
48 "Can only call this from the compositor thread!"); |
|
49 } |
|
50 |
|
51 bool |
|
52 Compositor::ShouldDrawDiagnostics(DiagnosticFlags aFlags) |
|
53 { |
|
54 if ((aFlags & DIAGNOSTIC_TILE) && !(mDiagnosticTypes & DIAGNOSTIC_TILE_BORDERS)) { |
|
55 return false; |
|
56 } |
|
57 if ((aFlags & DIAGNOSTIC_BIGIMAGE) && |
|
58 !(mDiagnosticTypes & DIAGNOSTIC_BIGIMAGE_BORDERS)) { |
|
59 return false; |
|
60 } |
|
61 if (!mDiagnosticTypes) { |
|
62 return false; |
|
63 } |
|
64 return true; |
|
65 } |
|
66 |
|
67 void |
|
68 Compositor::DrawDiagnostics(DiagnosticFlags aFlags, |
|
69 const nsIntRegion& aVisibleRegion, |
|
70 const gfx::Rect& aClipRect, |
|
71 const gfx::Matrix4x4& aTransform, |
|
72 uint32_t aFlashCounter) |
|
73 { |
|
74 if (!ShouldDrawDiagnostics(aFlags)) { |
|
75 return; |
|
76 } |
|
77 |
|
78 if (aVisibleRegion.GetNumRects() > 1) { |
|
79 nsIntRegionRectIterator screenIter(aVisibleRegion); |
|
80 |
|
81 while (const nsIntRect* rect = screenIter.Next()) |
|
82 { |
|
83 DrawDiagnostics(aFlags | DIAGNOSTIC_REGION_RECT, |
|
84 ToRect(*rect), aClipRect, aTransform, aFlashCounter); |
|
85 } |
|
86 } |
|
87 |
|
88 DrawDiagnostics(aFlags, ToRect(aVisibleRegion.GetBounds()), |
|
89 aClipRect, aTransform, aFlashCounter); |
|
90 } |
|
91 |
|
92 void |
|
93 Compositor::DrawDiagnostics(DiagnosticFlags aFlags, |
|
94 const gfx::Rect& aVisibleRect, |
|
95 const gfx::Rect& aClipRect, |
|
96 const gfx::Matrix4x4& aTransform, |
|
97 uint32_t aFlashCounter) |
|
98 { |
|
99 if (!ShouldDrawDiagnostics(aFlags)) { |
|
100 return; |
|
101 } |
|
102 |
|
103 DrawDiagnosticsInternal(aFlags, aVisibleRect, aClipRect, aTransform, |
|
104 aFlashCounter); |
|
105 } |
|
106 |
|
107 gfx::Rect |
|
108 Compositor::ClipRectInLayersCoordinates(gfx::Rect aClip) const { |
|
109 gfx::Rect result; |
|
110 aClip = aClip + GetCurrentRenderTarget()->GetOrigin(); |
|
111 gfx::IntSize destSize = GetWidgetSize(); |
|
112 |
|
113 switch (mScreenRotation) { |
|
114 case ROTATION_0: |
|
115 result = aClip; |
|
116 break; |
|
117 case ROTATION_90: |
|
118 result = gfx::Rect(aClip.y, |
|
119 destSize.width - aClip.x - aClip.width, |
|
120 aClip.height, aClip.width); |
|
121 break; |
|
122 case ROTATION_270: |
|
123 result = gfx::Rect(destSize.height - aClip.y - aClip.height, |
|
124 aClip.x, |
|
125 aClip.height, aClip.width); |
|
126 break; |
|
127 case ROTATION_180: |
|
128 result = gfx::Rect(destSize.width - aClip.x - aClip.width, |
|
129 destSize.height - aClip.y - aClip.height, |
|
130 aClip.width, aClip.height); |
|
131 break; |
|
132 // ScreenRotation has a sentinel value, need to catch it in the switch |
|
133 // statement otherwise the build fails (-WError) |
|
134 default: {} |
|
135 } |
|
136 return result; |
|
137 } |
|
138 |
|
139 void |
|
140 Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags, |
|
141 const gfx::Rect& aVisibleRect, |
|
142 const gfx::Rect& aClipRect, |
|
143 const gfx::Matrix4x4& aTransform, |
|
144 uint32_t aFlashCounter) |
|
145 { |
|
146 #ifdef MOZ_B2G |
|
147 int lWidth = 4; |
|
148 #elif defined(ANDROID) |
|
149 int lWidth = 10; |
|
150 #else |
|
151 int lWidth = 2; |
|
152 #endif |
|
153 float opacity = 0.7f; |
|
154 |
|
155 gfx::Color color; |
|
156 if (aFlags & DIAGNOSTIC_CONTENT) { |
|
157 color = gfx::Color(0.0f, 1.0f, 0.0f, 1.0f); // green |
|
158 if (aFlags & DIAGNOSTIC_COMPONENT_ALPHA) { |
|
159 color = gfx::Color(0.0f, 1.0f, 1.0f, 1.0f); // greenish blue |
|
160 } |
|
161 } else if (aFlags & DIAGNOSTIC_IMAGE) { |
|
162 color = gfx::Color(1.0f, 0.0f, 0.0f, 1.0f); // red |
|
163 } else if (aFlags & DIAGNOSTIC_COLOR) { |
|
164 color = gfx::Color(0.0f, 0.0f, 1.0f, 1.0f); // blue |
|
165 } else if (aFlags & DIAGNOSTIC_CONTAINER) { |
|
166 color = gfx::Color(0.8f, 0.0f, 0.8f, 1.0f); // purple |
|
167 } |
|
168 |
|
169 // make tile borders a bit more transparent to keep layer borders readable. |
|
170 if (aFlags & DIAGNOSTIC_TILE || |
|
171 aFlags & DIAGNOSTIC_BIGIMAGE || |
|
172 aFlags & DIAGNOSTIC_REGION_RECT) { |
|
173 lWidth = 1; |
|
174 opacity = 0.5f; |
|
175 color.r *= 0.7f; |
|
176 color.g *= 0.7f; |
|
177 color.b *= 0.7f; |
|
178 } |
|
179 |
|
180 if (mDiagnosticTypes & DIAGNOSTIC_FLASH_BORDERS) { |
|
181 float flash = (float)aFlashCounter / (float)DIAGNOSTIC_FLASH_COUNTER_MAX; |
|
182 color.r *= flash; |
|
183 color.g *= flash; |
|
184 color.b *= flash; |
|
185 } |
|
186 |
|
187 EffectChain effects; |
|
188 |
|
189 effects.mPrimaryEffect = new EffectSolidColor(color); |
|
190 // left |
|
191 this->DrawQuad(gfx::Rect(aVisibleRect.x, aVisibleRect.y, |
|
192 lWidth, aVisibleRect.height), |
|
193 aClipRect, effects, opacity, |
|
194 aTransform); |
|
195 // top |
|
196 this->DrawQuad(gfx::Rect(aVisibleRect.x + lWidth, aVisibleRect.y, |
|
197 aVisibleRect.width - 2 * lWidth, lWidth), |
|
198 aClipRect, effects, opacity, |
|
199 aTransform); |
|
200 // right |
|
201 this->DrawQuad(gfx::Rect(aVisibleRect.x + aVisibleRect.width - lWidth, aVisibleRect.y, |
|
202 lWidth, aVisibleRect.height), |
|
203 aClipRect, effects, opacity, |
|
204 aTransform); |
|
205 // bottom |
|
206 this->DrawQuad(gfx::Rect(aVisibleRect.x + lWidth, aVisibleRect.y + aVisibleRect.height-lWidth, |
|
207 aVisibleRect.width - 2 * lWidth, lWidth), |
|
208 aClipRect, effects, opacity, |
|
209 aTransform); |
|
210 } |
|
211 |
|
212 } // namespace |
|
213 } // namespace |