Line data Source code
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/CompositorBridgeParent.h" // for CompositorBridgeParent
9 : #include "mozilla/layers/Diagnostics.h"
10 : #include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
11 : #include "mozilla/layers/TextureClient.h"
12 : #include "mozilla/layers/TextureHost.h"
13 : #include "mozilla/layers/CompositorThread.h"
14 : #include "mozilla/mozalloc.h" // for operator delete, etc
15 : #include "gfx2DGlue.h"
16 : #include "nsAppRunner.h"
17 : #include "LayersHelpers.h"
18 :
19 : namespace mozilla {
20 :
21 : namespace layers {
22 :
23 1 : Compositor::Compositor(widget::CompositorWidget* aWidget,
24 1 : CompositorBridgeParent* aParent)
25 : : mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
26 : , mParent(aParent)
27 : , mPixelsPerFrame(0)
28 : , mPixelsFilled(0)
29 : , mScreenRotation(ROTATION_0)
30 : , mWidget(aWidget)
31 : , mIsDestroyed(false)
32 : #if defined(MOZ_WIDGET_ANDROID)
33 : // If the default color isn't white for Fennec, there is a black
34 : // flash before the first page of a tab is loaded.
35 : , mClearColor(1.0, 1.0, 1.0, 1.0)
36 : , mDefaultClearColor(1.0, 1.0, 1.0, 1.0)
37 : #else
38 : , mClearColor(0.0, 0.0, 0.0, 0.0)
39 1 : , mDefaultClearColor(0.0, 0.0, 0.0, 0.0)
40 : #endif
41 : {
42 1 : }
43 :
44 0 : Compositor::~Compositor()
45 : {
46 0 : ReadUnlockTextures();
47 0 : }
48 :
49 : void
50 0 : Compositor::Destroy()
51 : {
52 0 : TextureSourceProvider::Destroy();
53 0 : mIsDestroyed = true;
54 0 : }
55 :
56 : void
57 27 : Compositor::EndFrame()
58 : {
59 27 : ReadUnlockTextures();
60 27 : mLastCompositionEndTime = TimeStamp::Now();
61 27 : }
62 :
63 : /* static */ void
64 316 : Compositor::AssertOnCompositorThread()
65 : {
66 316 : MOZ_ASSERT(!CompositorThreadHolder::Loop() ||
67 : CompositorThreadHolder::Loop() == MessageLoop::current(),
68 : "Can only call this from the compositor thread!");
69 316 : }
70 :
71 : bool
72 86 : Compositor::ShouldDrawDiagnostics(DiagnosticFlags aFlags)
73 : {
74 86 : if ((aFlags & DiagnosticFlags::TILE) && !(mDiagnosticTypes & DiagnosticTypes::TILE_BORDERS)) {
75 0 : return false;
76 : }
77 258 : if ((aFlags & DiagnosticFlags::BIGIMAGE) &&
78 172 : !(mDiagnosticTypes & DiagnosticTypes::BIGIMAGE_BORDERS)) {
79 0 : return false;
80 : }
81 86 : if (mDiagnosticTypes == DiagnosticTypes::NO_DIAGNOSTIC) {
82 86 : return false;
83 : }
84 0 : return true;
85 : }
86 :
87 : void
88 56 : Compositor::DrawDiagnostics(DiagnosticFlags aFlags,
89 : const nsIntRegion& aVisibleRegion,
90 : const gfx::IntRect& aClipRect,
91 : const gfx::Matrix4x4& aTransform,
92 : uint32_t aFlashCounter)
93 : {
94 56 : if (!ShouldDrawDiagnostics(aFlags)) {
95 56 : return;
96 : }
97 :
98 0 : if (aVisibleRegion.GetNumRects() > 1) {
99 0 : for (auto iter = aVisibleRegion.RectIter(); !iter.Done(); iter.Next()) {
100 0 : DrawDiagnostics(aFlags | DiagnosticFlags::REGION_RECT,
101 0 : IntRectToRect(iter.Get()), aClipRect, aTransform,
102 0 : aFlashCounter);
103 : }
104 : }
105 :
106 0 : DrawDiagnostics(aFlags, IntRectToRect(aVisibleRegion.GetBounds()),
107 0 : aClipRect, aTransform, aFlashCounter);
108 : }
109 :
110 : void
111 30 : Compositor::DrawDiagnostics(DiagnosticFlags aFlags,
112 : const gfx::Rect& aVisibleRect,
113 : const gfx::IntRect& aClipRect,
114 : const gfx::Matrix4x4& aTransform,
115 : uint32_t aFlashCounter)
116 : {
117 30 : if (!ShouldDrawDiagnostics(aFlags)) {
118 30 : return;
119 : }
120 :
121 : DrawDiagnosticsInternal(aFlags, aVisibleRect, aClipRect, aTransform,
122 0 : aFlashCounter);
123 : }
124 :
125 : void
126 0 : Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
127 : const gfx::Rect& aVisibleRect,
128 : const gfx::IntRect& aClipRect,
129 : const gfx::Matrix4x4& aTransform,
130 : uint32_t aFlashCounter)
131 : {
132 : #ifdef ANDROID
133 : int lWidth = 10;
134 : #else
135 0 : int lWidth = 2;
136 : #endif
137 :
138 0 : gfx::Color color;
139 0 : if (aFlags & DiagnosticFlags::CONTENT) {
140 0 : color = gfx::Color(0.0f, 1.0f, 0.0f, 1.0f); // green
141 0 : if (aFlags & DiagnosticFlags::COMPONENT_ALPHA) {
142 0 : color = gfx::Color(0.0f, 1.0f, 1.0f, 1.0f); // greenish blue
143 : }
144 0 : } else if (aFlags & DiagnosticFlags::IMAGE) {
145 0 : if (aFlags & DiagnosticFlags::NV12) {
146 0 : color = gfx::Color(1.0f, 1.0f, 0.0f, 1.0f); // yellow
147 0 : } else if (aFlags & DiagnosticFlags::YCBCR) {
148 0 : color = gfx::Color(1.0f, 0.55f, 0.0f, 1.0f); // orange
149 : } else {
150 0 : color = gfx::Color(1.0f, 0.0f, 0.0f, 1.0f); // red
151 : }
152 0 : } else if (aFlags & DiagnosticFlags::COLOR) {
153 0 : color = gfx::Color(0.0f, 0.0f, 1.0f, 1.0f); // blue
154 0 : } else if (aFlags & DiagnosticFlags::CONTAINER) {
155 0 : color = gfx::Color(0.8f, 0.0f, 0.8f, 1.0f); // purple
156 : }
157 :
158 : // make tile borders a bit more transparent to keep layer borders readable.
159 0 : if (aFlags & DiagnosticFlags::TILE ||
160 0 : aFlags & DiagnosticFlags::BIGIMAGE ||
161 0 : aFlags & DiagnosticFlags::REGION_RECT) {
162 0 : lWidth = 1;
163 0 : color.r *= 0.7f;
164 0 : color.g *= 0.7f;
165 0 : color.b *= 0.7f;
166 0 : color.a = color.a * 0.5f;
167 : } else {
168 0 : color.a = color.a * 0.7f;
169 : }
170 :
171 :
172 0 : if (mDiagnosticTypes & DiagnosticTypes::FLASH_BORDERS) {
173 0 : float flash = (float)aFlashCounter / (float)DIAGNOSTIC_FLASH_COUNTER_MAX;
174 0 : color.r *= flash;
175 0 : color.g *= flash;
176 0 : color.b *= flash;
177 : }
178 :
179 0 : SlowDrawRect(aVisibleRect, color, aClipRect, aTransform, lWidth);
180 0 : }
181 :
182 : static void
183 0 : UpdateTextureCoordinates(gfx::TexturedTriangle& aTriangle,
184 : const gfx::Rect& aRect,
185 : const gfx::Rect& aIntersection,
186 : const gfx::Rect& aTextureCoords)
187 : {
188 : // Calculate the relative offset of the intersection within the layer.
189 0 : float dx = (aIntersection.x - aRect.x) / aRect.width;
190 0 : float dy = (aIntersection.y - aRect.y) / aRect.height;
191 :
192 : // Update the texture offset.
193 0 : float x = aTextureCoords.x + dx * aTextureCoords.width;
194 0 : float y = aTextureCoords.y + dy * aTextureCoords.height;
195 :
196 : // Scale the texture width and height.
197 0 : float w = aTextureCoords.width * aIntersection.width / aRect.width;
198 0 : float h = aTextureCoords.height * aIntersection.height / aRect.height;
199 :
200 0 : static const auto Clamp = [](float& f)
201 : {
202 0 : if (f >= 1.0f) f = 1.0f;
203 0 : if (f <= 0.0f) f = 0.0f;
204 0 : };
205 :
206 0 : auto UpdatePoint = [&](const gfx::Point& p, gfx::Point& t)
207 : {
208 0 : t.x = x + (p.x - aIntersection.x) / aIntersection.width * w;
209 0 : t.y = y + (p.y - aIntersection.y) / aIntersection.height * h;
210 :
211 0 : Clamp(t.x);
212 0 : Clamp(t.y);
213 0 : };
214 :
215 0 : UpdatePoint(aTriangle.p1, aTriangle.textureCoords.p1);
216 0 : UpdatePoint(aTriangle.p2, aTriangle.textureCoords.p2);
217 0 : UpdatePoint(aTriangle.p3, aTriangle.textureCoords.p3);
218 0 : }
219 :
220 : void
221 80 : Compositor::DrawGeometry(const gfx::Rect& aRect,
222 : const gfx::IntRect& aClipRect,
223 : const EffectChain& aEffectChain,
224 : gfx::Float aOpacity,
225 : const gfx::Matrix4x4& aTransform,
226 : const gfx::Rect& aVisibleRect,
227 : const Maybe<gfx::Polygon>& aGeometry)
228 : {
229 80 : if (aRect.IsEmpty()) {
230 99 : return;
231 : }
232 :
233 61 : if (!aGeometry || !SupportsLayerGeometry()) {
234 : DrawQuad(aRect, aClipRect, aEffectChain,
235 61 : aOpacity, aTransform, aVisibleRect);
236 61 : return;
237 : }
238 :
239 : // Cull completely invisible polygons.
240 0 : if (aRect.Intersect(aGeometry->BoundingBox()).IsEmpty()) {
241 0 : return;
242 : }
243 :
244 0 : const gfx::Polygon clipped = aGeometry->ClipPolygon(aRect);
245 :
246 : // Cull polygons with no area.
247 0 : if (clipped.IsEmpty()) {
248 0 : return;
249 : }
250 :
251 : DrawPolygon(clipped, aRect, aClipRect, aEffectChain,
252 0 : aOpacity, aTransform, aVisibleRect);
253 : }
254 :
255 : void
256 0 : Compositor::DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles,
257 : const gfx::Rect& aRect,
258 : const gfx::IntRect& aClipRect,
259 : const EffectChain& aEffectChain,
260 : gfx::Float aOpacity,
261 : const gfx::Matrix4x4& aTransform,
262 : const gfx::Rect& aVisibleRect)
263 : {
264 0 : for (const gfx::TexturedTriangle& triangle : aTriangles) {
265 : DrawTriangle(triangle, aClipRect, aEffectChain,
266 0 : aOpacity, aTransform, aVisibleRect);
267 : }
268 0 : }
269 :
270 : nsTArray<gfx::TexturedTriangle>
271 0 : GenerateTexturedTriangles(const gfx::Polygon& aPolygon,
272 : const gfx::Rect& aRect,
273 : const gfx::Rect& aTexRect)
274 : {
275 0 : nsTArray<gfx::TexturedTriangle> texturedTriangles;
276 :
277 0 : gfx::Rect layerRects[4];
278 0 : gfx::Rect textureRects[4];
279 : size_t rects = DecomposeIntoNoRepeatRects(aRect, aTexRect,
280 0 : &layerRects, &textureRects);
281 0 : for (size_t i = 0; i < rects; ++i) {
282 0 : const gfx::Rect& rect = layerRects[i];
283 0 : const gfx::Rect& texRect = textureRects[i];
284 0 : const gfx::Polygon clipped = aPolygon.ClipPolygon(rect);
285 :
286 0 : if (clipped.IsEmpty()) {
287 0 : continue;
288 : }
289 :
290 0 : for (const gfx::Triangle& triangle : clipped.ToTriangles()) {
291 0 : const gfx::Rect intersection = rect.Intersect(triangle.BoundingBox());
292 :
293 : // Cull completely invisible triangles.
294 0 : if (intersection.IsEmpty()) {
295 0 : continue;
296 : }
297 :
298 0 : MOZ_ASSERT(rect.width > 0.0f && rect.height > 0.0f);
299 0 : MOZ_ASSERT(intersection.width > 0.0f && intersection.height > 0.0f);
300 :
301 : // Since the texture was created for non-split geometry, we need to
302 : // update the texture coordinates to account for the split.
303 0 : gfx::TexturedTriangle t(triangle);
304 0 : UpdateTextureCoordinates(t, rect, intersection, texRect);
305 0 : texturedTriangles.AppendElement(Move(t));
306 : }
307 : }
308 :
309 0 : return texturedTriangles;
310 : }
311 :
312 : nsTArray<TexturedVertex>
313 0 : TexturedTrianglesToVertexArray(const nsTArray<gfx::TexturedTriangle>& aTriangles)
314 : {
315 0 : const auto VertexFromPoints = [](const gfx::Point& p, const gfx::Point& t) {
316 0 : return TexturedVertex { { p.x, p.y }, { t.x, t.y } };
317 0 : };
318 :
319 0 : nsTArray<TexturedVertex> vertices;
320 :
321 0 : for (const gfx::TexturedTriangle& t : aTriangles) {
322 0 : vertices.AppendElement(VertexFromPoints(t.p1, t.textureCoords.p1));
323 0 : vertices.AppendElement(VertexFromPoints(t.p2, t.textureCoords.p2));
324 0 : vertices.AppendElement(VertexFromPoints(t.p3, t.textureCoords.p3));
325 : }
326 :
327 0 : return vertices;
328 : }
329 :
330 : void
331 0 : Compositor::DrawPolygon(const gfx::Polygon& aPolygon,
332 : const gfx::Rect& aRect,
333 : const gfx::IntRect& aClipRect,
334 : const EffectChain& aEffectChain,
335 : gfx::Float aOpacity,
336 : const gfx::Matrix4x4& aTransform,
337 : const gfx::Rect& aVisibleRect)
338 : {
339 0 : nsTArray<gfx::TexturedTriangle> texturedTriangles;
340 :
341 : TexturedEffect* texturedEffect =
342 0 : aEffectChain.mPrimaryEffect->AsTexturedEffect();
343 :
344 0 : if (texturedEffect) {
345 : texturedTriangles =
346 0 : GenerateTexturedTriangles(aPolygon, aRect, texturedEffect->mTextureCoords);
347 : } else {
348 0 : for (const gfx::Triangle& triangle : aPolygon.ToTriangles()) {
349 0 : texturedTriangles.AppendElement(gfx::TexturedTriangle(triangle));
350 : }
351 : }
352 :
353 0 : if (texturedTriangles.IsEmpty()) {
354 : // Nothing to render.
355 0 : return;
356 : }
357 :
358 : DrawTriangles(texturedTriangles, aRect, aClipRect, aEffectChain,
359 0 : aOpacity, aTransform, aVisibleRect);
360 : }
361 :
362 : void
363 0 : Compositor::SlowDrawRect(const gfx::Rect& aRect, const gfx::Color& aColor,
364 : const gfx::IntRect& aClipRect,
365 : const gfx::Matrix4x4& aTransform, int aStrokeWidth)
366 : {
367 : // TODO This should draw a rect using a single draw call but since
368 : // this is only used for debugging overlays it's not worth optimizing ATM.
369 0 : float opacity = 1.0f;
370 0 : EffectChain effects;
371 :
372 0 : effects.mPrimaryEffect = new EffectSolidColor(aColor);
373 : // left
374 0 : this->DrawQuad(gfx::Rect(aRect.x, aRect.y,
375 0 : aStrokeWidth, aRect.height),
376 : aClipRect, effects, opacity,
377 0 : aTransform);
378 : // top
379 0 : this->DrawQuad(gfx::Rect(aRect.x + aStrokeWidth, aRect.y,
380 0 : aRect.width - 2 * aStrokeWidth, aStrokeWidth),
381 : aClipRect, effects, opacity,
382 0 : aTransform);
383 : // right
384 0 : this->DrawQuad(gfx::Rect(aRect.x + aRect.width - aStrokeWidth, aRect.y,
385 0 : aStrokeWidth, aRect.height),
386 : aClipRect, effects, opacity,
387 0 : aTransform);
388 : // bottom
389 0 : this->DrawQuad(gfx::Rect(aRect.x + aStrokeWidth, aRect.y + aRect.height - aStrokeWidth,
390 0 : aRect.width - 2 * aStrokeWidth, aStrokeWidth),
391 : aClipRect, effects, opacity,
392 0 : aTransform);
393 0 : }
394 :
395 : void
396 0 : Compositor::FillRect(const gfx::Rect& aRect, const gfx::Color& aColor,
397 : const gfx::IntRect& aClipRect,
398 : const gfx::Matrix4x4& aTransform)
399 : {
400 0 : float opacity = 1.0f;
401 0 : EffectChain effects;
402 :
403 0 : effects.mPrimaryEffect = new EffectSolidColor(aColor);
404 : this->DrawQuad(aRect,
405 : aClipRect, effects, opacity,
406 0 : aTransform);
407 0 : }
408 :
409 :
410 : static float
411 0 : WrapTexCoord(float v)
412 : {
413 : // This should return values in range [0, 1.0)
414 0 : return v - floorf(v);
415 : }
416 :
417 : static void
418 0 : SetRects(size_t n,
419 : decomposedRectArrayT* aLayerRects,
420 : decomposedRectArrayT* aTextureRects,
421 : float x0, float y0, float x1, float y1,
422 : float tx0, float ty0, float tx1, float ty1,
423 : bool flip_y)
424 : {
425 0 : if (flip_y) {
426 0 : std::swap(ty0, ty1);
427 : }
428 0 : (*aLayerRects)[n] = gfx::Rect(x0, y0, x1 - x0, y1 - y0);
429 0 : (*aTextureRects)[n] = gfx::Rect(tx0, ty0, tx1 - tx0, ty1 - ty0);
430 0 : }
431 :
432 : #ifdef DEBUG
433 : static inline bool
434 0 : FuzzyEqual(float a, float b)
435 : {
436 0 : return fabs(a - b) < 0.0001f;
437 : }
438 : static inline bool
439 0 : FuzzyLTE(float a, float b)
440 : {
441 0 : return a <= b + 0.0001f;
442 : }
443 : #endif
444 :
445 : size_t
446 0 : DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
447 : const gfx::Rect& aTexCoordRect,
448 : decomposedRectArrayT* aLayerRects,
449 : decomposedRectArrayT* aTextureRects)
450 : {
451 0 : gfx::Rect texCoordRect = aTexCoordRect;
452 :
453 : // If the texture should be flipped, it will have negative height. Detect that
454 : // here and compensate for it. We will flip each rect as we emit it.
455 0 : bool flipped = false;
456 0 : if (texCoordRect.height < 0) {
457 0 : flipped = true;
458 0 : texCoordRect.y += texCoordRect.height;
459 0 : texCoordRect.height = -texCoordRect.height;
460 : }
461 :
462 : // Wrap the texture coordinates so they are within [0,1] and cap width/height
463 : // at 1. We rely on this below.
464 0 : texCoordRect = gfx::Rect(gfx::Point(WrapTexCoord(texCoordRect.x),
465 : WrapTexCoord(texCoordRect.y)),
466 0 : gfx::Size(std::min(texCoordRect.width, 1.0f),
467 0 : std::min(texCoordRect.height, 1.0f)));
468 :
469 0 : NS_ASSERTION(texCoordRect.x >= 0.0f && texCoordRect.x <= 1.0f &&
470 : texCoordRect.y >= 0.0f && texCoordRect.y <= 1.0f &&
471 : texCoordRect.width >= 0.0f && texCoordRect.width <= 1.0f &&
472 : texCoordRect.height >= 0.0f && texCoordRect.height <= 1.0f &&
473 : texCoordRect.XMost() >= 0.0f && texCoordRect.XMost() <= 2.0f &&
474 : texCoordRect.YMost() >= 0.0f && texCoordRect.YMost() <= 2.0f,
475 : "We just wrapped the texture coordinates, didn't we?");
476 :
477 : // Get the top left and bottom right points of the rectangle. Note that
478 : // tl.x/tl.y are within [0,1] but br.x/br.y are within [0,2].
479 0 : gfx::Point tl = texCoordRect.TopLeft();
480 0 : gfx::Point br = texCoordRect.BottomRight();
481 :
482 0 : NS_ASSERTION(tl.x >= 0.0f && tl.x <= 1.0f &&
483 : tl.y >= 0.0f && tl.y <= 1.0f &&
484 : br.x >= tl.x && br.x <= 2.0f &&
485 : br.y >= tl.y && br.y <= 2.0f &&
486 : FuzzyLTE(br.x - tl.x, 1.0f) &&
487 : FuzzyLTE(br.y - tl.y, 1.0f),
488 : "Somehow generated invalid texture coordinates");
489 :
490 : // Then check if we wrap in either the x or y axis.
491 0 : bool xwrap = br.x > 1.0f;
492 0 : bool ywrap = br.y > 1.0f;
493 :
494 : // If xwrap is false, the texture will be sampled from tl.x .. br.x.
495 : // If xwrap is true, then it will be split into tl.x .. 1.0, and
496 : // 0.0 .. WrapTexCoord(br.x). Same for the Y axis. The destination
497 : // rectangle is also split appropriately, according to the calculated
498 : // xmid/ymid values.
499 0 : if (!xwrap && !ywrap) {
500 0 : SetRects(0, aLayerRects, aTextureRects,
501 0 : aRect.x, aRect.y, aRect.XMost(), aRect.YMost(),
502 : tl.x, tl.y, br.x, br.y,
503 0 : flipped);
504 0 : return 1;
505 : }
506 :
507 : // If we are dealing with wrapping br.x and br.y are greater than 1.0 so
508 : // wrap them here as well.
509 0 : br = gfx::Point(xwrap ? WrapTexCoord(br.x) : br.x,
510 0 : ywrap ? WrapTexCoord(br.y) : br.y);
511 :
512 : // If we wrap around along the x axis, we will draw first from
513 : // tl.x .. 1.0 and then from 0.0 .. br.x (which we just wrapped above).
514 : // The same applies for the Y axis. The midpoints we calculate here are
515 : // only valid if we actually wrap around.
516 0 : GLfloat xmid = aRect.x + (1.0f - tl.x) / texCoordRect.width * aRect.width;
517 0 : GLfloat ymid = aRect.y + (1.0f - tl.y) / texCoordRect.height * aRect.height;
518 :
519 : // Due to floating-point inaccuracy, we have to use XMost()-x and YMost()-y
520 : // to calculate width and height, respectively, to ensure that size will
521 : // remain consistent going from absolute to relative and back again.
522 0 : NS_ASSERTION(!xwrap ||
523 : (xmid >= aRect.x &&
524 : xmid <= aRect.XMost() &&
525 : FuzzyEqual((xmid - aRect.x) + (aRect.XMost() - xmid), aRect.XMost() - aRect.x)),
526 : "xmid should be within [x,XMost()] and the wrapped rect should have the same width");
527 0 : NS_ASSERTION(!ywrap ||
528 : (ymid >= aRect.y &&
529 : ymid <= aRect.YMost() &&
530 : FuzzyEqual((ymid - aRect.y) + (aRect.YMost() - ymid), aRect.YMost() - aRect.y)),
531 : "ymid should be within [y,YMost()] and the wrapped rect should have the same height");
532 :
533 0 : if (!xwrap && ywrap) {
534 0 : SetRects(0, aLayerRects, aTextureRects,
535 0 : aRect.x, aRect.y, aRect.XMost(), ymid,
536 : tl.x, tl.y, br.x, 1.0f,
537 0 : flipped);
538 0 : SetRects(1, aLayerRects, aTextureRects,
539 0 : aRect.x, ymid, aRect.XMost(), aRect.YMost(),
540 : tl.x, 0.0f, br.x, br.y,
541 0 : flipped);
542 0 : return 2;
543 : }
544 :
545 0 : if (xwrap && !ywrap) {
546 0 : SetRects(0, aLayerRects, aTextureRects,
547 0 : aRect.x, aRect.y, xmid, aRect.YMost(),
548 : tl.x, tl.y, 1.0f, br.y,
549 0 : flipped);
550 0 : SetRects(1, aLayerRects, aTextureRects,
551 0 : xmid, aRect.y, aRect.XMost(), aRect.YMost(),
552 : 0.0f, tl.y, br.x, br.y,
553 0 : flipped);
554 0 : return 2;
555 : }
556 :
557 0 : SetRects(0, aLayerRects, aTextureRects,
558 0 : aRect.x, aRect.y, xmid, ymid,
559 : tl.x, tl.y, 1.0f, 1.0f,
560 0 : flipped);
561 0 : SetRects(1, aLayerRects, aTextureRects,
562 0 : xmid, aRect.y, aRect.XMost(), ymid,
563 : 0.0f, tl.y, br.x, 1.0f,
564 0 : flipped);
565 0 : SetRects(2, aLayerRects, aTextureRects,
566 0 : aRect.x, ymid, xmid, aRect.YMost(),
567 : tl.x, 0.0f, 1.0f, br.y,
568 0 : flipped);
569 0 : SetRects(3, aLayerRects, aTextureRects,
570 : xmid, ymid, aRect.XMost(), aRect.YMost(),
571 : 0.0f, 0.0f, br.x, br.y,
572 0 : flipped);
573 0 : return 4;
574 : }
575 :
576 : gfx::IntRect
577 0 : Compositor::ComputeBackdropCopyRect(const gfx::Rect& aRect,
578 : const gfx::IntRect& aClipRect,
579 : const gfx::Matrix4x4& aTransform,
580 : gfx::Matrix4x4* aOutTransform,
581 : gfx::Rect* aOutLayerQuad)
582 : {
583 : // Compute the clip.
584 0 : gfx::IntPoint rtOffset = GetCurrentRenderTarget()->GetOrigin();
585 0 : gfx::IntSize rtSize = GetCurrentRenderTarget()->GetSize();
586 :
587 : return layers::ComputeBackdropCopyRect(
588 : aRect,
589 : aClipRect,
590 : aTransform,
591 0 : gfx::IntRect(rtOffset, rtSize),
592 : aOutTransform,
593 0 : aOutLayerQuad);
594 : }
595 :
596 : gfx::IntRect
597 0 : Compositor::ComputeBackdropCopyRect(const gfx::Triangle& aTriangle,
598 : const gfx::IntRect& aClipRect,
599 : const gfx::Matrix4x4& aTransform,
600 : gfx::Matrix4x4* aOutTransform,
601 : gfx::Rect* aOutLayerQuad)
602 : {
603 0 : gfx::Rect boundingBox = aTriangle.BoundingBox();
604 : return ComputeBackdropCopyRect(boundingBox, aClipRect, aTransform,
605 0 : aOutTransform, aOutLayerQuad);
606 : }
607 :
608 : void
609 0 : Compositor::SetInvalid()
610 : {
611 0 : mParent = nullptr;
612 0 : }
613 :
614 : bool
615 66 : Compositor::IsValid() const
616 : {
617 66 : return !!mParent;
618 : }
619 :
620 : void
621 27 : Compositor::SetDispAcquireFence(Layer* aLayer)
622 : {
623 27 : }
624 :
625 : bool
626 0 : Compositor::NotifyNotUsedAfterComposition(TextureHost* aTextureHost)
627 : {
628 0 : if (IsDestroyed() || AsBasicCompositor()) {
629 0 : return false;
630 : }
631 0 : return TextureSourceProvider::NotifyNotUsedAfterComposition(aTextureHost);
632 : }
633 :
634 : void
635 0 : Compositor::GetFrameStats(GPUStats* aStats)
636 : {
637 0 : aStats->mInvalidPixels = mPixelsPerFrame;
638 0 : aStats->mPixelsFilled = mPixelsFilled;
639 0 : }
640 :
641 : } // namespace layers
642 : } // namespace mozilla
|