Files
palemoon27/gfx/layers/Compositor.cpp
T
roytam1 f553544f33 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1144012 - Part 1: Create HwcDevice wrapper. r=sotaro (dcb5bca6c)
- Bug 1143522 - Convert cliprect coordinate in gonk code. r=botond (4b5bfe61b)
- Bug 1144012 - Part 2: Use wrapper in HwcComposer2D. r=sotaro (783cbca1a)
- Bug 1169093 - Do not use HWC when a region of layer is too small r=mattwoodrow (bf77e1a55)
- Bug 1155797 - P1: extract format BPP util function. r=mwu (06f3b96f5)
- Bug 1155797 - P2: show a black solid color frame if we don't have the bootAnim. r=mwu (2e6dda6d2)
- Bug 1153395 - Disable Hardware Vsync on Non Kit-Kat devices. r=mwu (e7ec09cee)
- Bug 1151489. Enable software vsync on all b2g versions. r=kats (597cdc85f)
- Bug 1155797 - P3: turn on vsync for kk, l and up. r=mwu (3e8187e50)
- Bug 1144012 - Part 3: Wrap vsync code. r=sotaro (4eb4af3d8)
- Bug 1144012 - Part 4: Remove the usage of mHwc from GonkDisplayICS. r=sotaro (ad5e257f0)
- Bug 1187048 - Code clean up around nsScreenGonk's EGLSurface handling r=mwu (eecdaf1ef)
- Bug 1188877 - Fix LayerComposite::SetClearRect() calling r=mwu (d748f2c50)
- Bug 1180657 - Use hwc directly on GonkDisplayICS. r=sotaro (55d2699aa)
- Bug 1163905 - b2g.neterror.url should use a relative URL. r=fabrice (abefb3d0b)
- Bug 1186000 - Support screen mirroring to HDMI display on gonk r=mwu,mattwoodrow (3df30f9dd)
- Bug 1186031 - Fix SetDispAcquireFence() calling r=nical (d561ef18c)
- Bug 1191457 - Revert SetDispAcquireFence() calling change r=nical (46bc14d4c)
- Bug 1192352 - Fix fence handling of display mirroring r=nical (fb686f922)
- Bug 1170966 - Check quad's effective region before drawing. r=nical, a=me (d85277b8e)
- Bug 1186236 - Fix drawQuad culling bug. r=nical (4fd64fb71)
- Bug 1192192 - fix quad culling method. r=nical (03c59a942)
- Bug 1179933, add Layer::ReplaceEffectiveTransform for temporary transform changes; r=mstange (c9e0c919a)
- Bug 1151937; [webvr] change deviceId/hardwareId to simple values; r=jrmuizel CLOSED TREE (f4f2332ab)
- Bug 1151904; fix Linux OVR library typo to use lowercase lib; r=me (7580c527b)
- Bug 1179944, [webvr] support Oculus 0.6.0 runtime and rendering; r=mstange (954bbb49c)
- Bug 633097 - Fix jittering animated text by disallowing flattening into a container layer that has animated text. r=mwoodrow (7eada20c4)
- Bug 914457 - Part 1: Use an empty clip rect for layers with an empty visible region (7b2462a5f)
- Bug 914457 - Part 2: Implement Crashtest (f6f6fcfaa)
- Bug 1149923 - Let 2D mask effect can check whether to use IntermediateSurface or not in its own logic. r=roc (f90c6f19c)
- Bug 1177018 - When finding a painted layer for a display item, include event regions in a layer's visible region. r=tn (ccedfcc38)
- Bug 1200158 - Define PaintedLayerData::AccumulateEventRegions() out of line. r=mstange (8fcfe35fd)
- Bug 1200158 - Avoid expensive computations involving the maybe-hit region in hot code paths. r=mstange (871c0944c)
- Bug 1201548 - When testing whether the visible rect intersects event regions in FindPaintedLayerFor(), only use the bounds of the event regions. r=mstange (976798e33)
- Bug 1180295 - Rip out call to setContentDocumentFixedPositionMargins. r=rbarker (c24ed7a7f)
- Bug 1166301 - Use the correct format flags for printing fixed position data in the layers dump. r=kats (a51d7b42a)
- Bug 1166301 - Store a flag on Layer to tell fixed background layers apart from fixed position layers. r=mattwoodrow (c9d1c1c63)
- Bug 1166301 - Annotate fixed background layers with scroll metadata for the animated geometry root of the frame they're the background of. r=mattwoodrow (0f3f8a715)
- Bug 1097464 - Part 6: Handle preserves-3d by compositor. r=roc (b231219b9)
- Hoist scroll info items above inactive blur containers. (bug 1193557 part 1, r=mstange) (d6212d65c)
- Ensure scroll info layers have a dispatch-to-content region. (bug 1193557 part 2, r=kats) (97fe0e4d7)
- Bug 1145143 - Check if buffer size is correct before calling the update. r=nical (fc4019b45)
- Bug 1145143 - When we fail to UpdateRenderTarget, report the size as well. r=bas (885668a28)
- Bug 1161670, cache D3D11 ShaderResourceView on TextureSourceD3D11; r=bas,jrmuizel (5fbd7d741)
- Bug 1188700, [webvr] Fix VR distortion compositing in d3d11/gl to take into account rendertarget size and transform; r=kip (47a73c37a)
- Allow wheel tests finer control over the refresh driver. (bug 1140293, r=mstange) (c47d17d0a)
- Bug 1164274 - Disable the wheel-scroll test on Mulet for intermittent failures. r=mstange (24ba31ab6)
- Bug 1172648 - Full-stack APZ mochitest for bug 1151667. r=kats (19b3fbd74)
- Bug 1173580 - Full-stack APZ layerization mochitest. r=kats (df7d6efc1)
- Bug 1175585 - Full-stack mochitest for wheel transactions. r=kats (b2e00b916)
- Bug 961289 - Add an initial mochitest (for bug 982141) that exercises the APZ testing framework. r=ehsan,kats,BenWa,ted (9e0eea39f)
- Bug 1151663 - Extract some helper functions for writing APZ mochitests into a separate file. r=kats (e0a565ca4)
- remaining  Bug 1151663 - Fix reconstruction of APZC tree structure in APZ mochitests. r=kats (f9836eb45)
- part of Bug 1139155 - Add a basic sanity test to exercise touch-based scrolling on B2G. r=botond (0b1673810)
- part of Add a test case for bug 1193557, r=kats. (157e5d8d0)
- Bug 1166649 - Fix GrallocTextureClient.cpp unified build bustage. r=nical (42d01ef5e)
- namespace (0096c7a24)
- Bug 1181085 - Don't accumulate ImageCompositeNotifications when we're compositing to a DrawTarget. r=nical (e7ad9e485)
- Bug 1186159 - Add an APZ minimap. r=kats (576b74a94)
- Bug 1167215 - Composite on every vsync until the scheduled one. r=roc (6ff8f84ca)
2022-01-04 09:29:39 +08:00

383 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/Compositor.h"
#include "base/message_loop.h" // for MessageLoop
#include "mozilla/layers/CompositorParent.h" // for CompositorParent
#include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "gfx2DGlue.h"
#include "nsAppRunner.h"
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
namespace layers {
/* static */ LayersBackend Compositor::sBackend = LayersBackend::LAYERS_NONE;
/* static */ LayersBackend
Compositor::GetBackend()
{
if (sBackend != LayersBackend::LAYERS_NONE) {
AssertOnCompositorThread();
}
return sBackend;
}
/* static */ void
Compositor::SetBackend(LayersBackend backend)
{
if (!gIsGtest && sBackend != backend &&
sBackend != LayersBackend::LAYERS_NONE &&
backend != LayersBackend::LAYERS_NONE) {
// Assert this once we figure out bug 972891.
#ifdef XP_MACOSX
gfxWarning() << "Changing compositor from " << unsigned(sBackend) << " to " << unsigned(backend);
#endif
}
sBackend = backend;
}
/* static */ void
Compositor::AssertOnCompositorThread()
{
MOZ_ASSERT(!CompositorParent::CompositorLoop() ||
CompositorParent::CompositorLoop() == MessageLoop::current(),
"Can only call this from the compositor thread!");
}
bool
Compositor::ShouldDrawDiagnostics(DiagnosticFlags aFlags)
{
if ((aFlags & DiagnosticFlags::TILE) && !(mDiagnosticTypes & DiagnosticTypes::TILE_BORDERS)) {
return false;
}
if ((aFlags & DiagnosticFlags::BIGIMAGE) &&
!(mDiagnosticTypes & DiagnosticTypes::BIGIMAGE_BORDERS)) {
return false;
}
if (mDiagnosticTypes == DiagnosticTypes::NO_DIAGNOSTIC) {
return false;
}
return true;
}
void
Compositor::DrawDiagnostics(DiagnosticFlags aFlags,
const nsIntRegion& aVisibleRegion,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform,
uint32_t aFlashCounter)
{
if (!ShouldDrawDiagnostics(aFlags)) {
return;
}
if (aVisibleRegion.GetNumRects() > 1) {
nsIntRegionRectIterator screenIter(aVisibleRegion);
while (const gfx::IntRect* rect = screenIter.Next())
{
DrawDiagnostics(aFlags | DiagnosticFlags::REGION_RECT,
ToRect(*rect), aClipRect, aTransform, aFlashCounter);
}
}
DrawDiagnostics(aFlags, ToRect(aVisibleRegion.GetBounds()),
aClipRect, aTransform, aFlashCounter);
}
void
Compositor::DrawDiagnostics(DiagnosticFlags aFlags,
const gfx::Rect& aVisibleRect,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform,
uint32_t aFlashCounter)
{
if (!ShouldDrawDiagnostics(aFlags)) {
return;
}
DrawDiagnosticsInternal(aFlags, aVisibleRect, aClipRect, aTransform,
aFlashCounter);
}
void
Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
const gfx::Rect& aVisibleRect,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform,
uint32_t aFlashCounter)
{
#ifdef MOZ_B2G
int lWidth = 4;
#elif defined(ANDROID)
int lWidth = 10;
#else
int lWidth = 2;
#endif
gfx::Color color;
if (aFlags & DiagnosticFlags::CONTENT) {
color = gfx::Color(0.0f, 1.0f, 0.0f, 1.0f); // green
if (aFlags & DiagnosticFlags::COMPONENT_ALPHA) {
color = gfx::Color(0.0f, 1.0f, 1.0f, 1.0f); // greenish blue
}
} else if (aFlags & DiagnosticFlags::IMAGE) {
color = gfx::Color(1.0f, 0.0f, 0.0f, 1.0f); // red
} else if (aFlags & DiagnosticFlags::COLOR) {
color = gfx::Color(0.0f, 0.0f, 1.0f, 1.0f); // blue
} else if (aFlags & DiagnosticFlags::CONTAINER) {
color = gfx::Color(0.8f, 0.0f, 0.8f, 1.0f); // purple
}
// make tile borders a bit more transparent to keep layer borders readable.
if (aFlags & DiagnosticFlags::TILE ||
aFlags & DiagnosticFlags::BIGIMAGE ||
aFlags & DiagnosticFlags::REGION_RECT) {
lWidth = 1;
color.r *= 0.7f;
color.g *= 0.7f;
color.b *= 0.7f;
color.a = color.a * 0.5f;
} else {
color.a = color.a * 0.7f;
}
if (mDiagnosticTypes & DiagnosticTypes::FLASH_BORDERS) {
float flash = (float)aFlashCounter / (float)DIAGNOSTIC_FLASH_COUNTER_MAX;
color.r *= flash;
color.g *= flash;
color.b *= flash;
}
SlowDrawRect(aVisibleRect, color, aClipRect, aTransform, lWidth);
}
void
Compositor::SlowDrawRect(const gfx::Rect& aRect, const gfx::Color& aColor,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform, int aStrokeWidth)
{
// TODO This should draw a rect using a single draw call but since
// this is only used for debugging overlays it's not worth optimizing ATM.
float opacity = 1.0f;
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(aColor);
// left
this->DrawQuad(gfx::Rect(aRect.x, aRect.y,
aStrokeWidth, aRect.height),
aClipRect, effects, opacity,
aTransform);
// top
this->DrawQuad(gfx::Rect(aRect.x + aStrokeWidth, aRect.y,
aRect.width - 2 * aStrokeWidth, aStrokeWidth),
aClipRect, effects, opacity,
aTransform);
// right
this->DrawQuad(gfx::Rect(aRect.x + aRect.width - aStrokeWidth, aRect.y,
aStrokeWidth, aRect.height),
aClipRect, effects, opacity,
aTransform);
// bottom
this->DrawQuad(gfx::Rect(aRect.x + aStrokeWidth, aRect.y + aRect.height - aStrokeWidth,
aRect.width - 2 * aStrokeWidth, aStrokeWidth),
aClipRect, effects, opacity,
aTransform);
}
void
Compositor::FillRect(const gfx::Rect& aRect, const gfx::Color& aColor,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform)
{
float opacity = 1.0f;
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(aColor);
this->DrawQuad(aRect,
aClipRect, effects, opacity,
aTransform);
}
static float
WrapTexCoord(float v)
{
// fmodf gives negative results for negative numbers;
// that is, fmodf(0.75, 1.0) == 0.75, but
// fmodf(-0.75, 1.0) == -0.75. For the negative case,
// the result we need is 0.25, so we add 1.0f.
if (v < 0.0f) {
return 1.0f + fmodf(v, 1.0f);
}
return fmodf(v, 1.0f);
}
static void
SetRects(size_t n,
decomposedRectArrayT* aLayerRects,
decomposedRectArrayT* aTextureRects,
float x0, float y0, float x1, float y1,
float tx0, float ty0, float tx1, float ty1,
bool flip_y)
{
if (flip_y) {
std::swap(ty0, ty1);
}
(*aLayerRects)[n] = gfx::Rect(x0, y0, x1 - x0, y1 - y0);
(*aTextureRects)[n] = gfx::Rect(tx0, ty0, tx1 - tx0, ty1 - ty0);
}
#ifdef DEBUG
static inline bool
FuzzyEqual(float a, float b)
{
return fabs(a - b) < 0.0001f;
}
static inline bool
FuzzyLTE(float a, float b)
{
return a <= b + 0.0001f;
}
#endif
size_t
DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
const gfx::Rect& aTexCoordRect,
decomposedRectArrayT* aLayerRects,
decomposedRectArrayT* aTextureRects)
{
gfx::Rect texCoordRect = aTexCoordRect;
// If the texture should be flipped, it will have negative height. Detect that
// here and compensate for it. We will flip each rect as we emit it.
bool flipped = false;
if (texCoordRect.height < 0) {
flipped = true;
texCoordRect.y += texCoordRect.height;
texCoordRect.height = -texCoordRect.height;
}
// Wrap the texture coordinates so they are within [0,1] and cap width/height
// at 1. We rely on this below.
texCoordRect = gfx::Rect(gfx::Point(WrapTexCoord(texCoordRect.x),
WrapTexCoord(texCoordRect.y)),
gfx::Size(std::min(texCoordRect.width, 1.0f),
std::min(texCoordRect.height, 1.0f)));
NS_ASSERTION(texCoordRect.x >= 0.0f && texCoordRect.x <= 1.0f &&
texCoordRect.y >= 0.0f && texCoordRect.y <= 1.0f &&
texCoordRect.width >= 0.0f && texCoordRect.width <= 1.0f &&
texCoordRect.height >= 0.0f && texCoordRect.height <= 1.0f &&
texCoordRect.XMost() >= 0.0f && texCoordRect.XMost() <= 2.0f &&
texCoordRect.YMost() >= 0.0f && texCoordRect.YMost() <= 2.0f,
"We just wrapped the texture coordinates, didn't we?");
// Get the top left and bottom right points of the rectangle. Note that
// tl.x/tl.y are within [0,1] but br.x/br.y are within [0,2].
gfx::Point tl = texCoordRect.TopLeft();
gfx::Point br = texCoordRect.BottomRight();
NS_ASSERTION(tl.x >= 0.0f && tl.x <= 1.0f &&
tl.y >= 0.0f && tl.y <= 1.0f &&
br.x >= tl.x && br.x <= 2.0f &&
br.y >= tl.y && br.y <= 2.0f &&
FuzzyLTE(br.x - tl.x, 1.0f) &&
FuzzyLTE(br.y - tl.y, 1.0f),
"Somehow generated invalid texture coordinates");
// Then check if we wrap in either the x or y axis.
bool xwrap = br.x > 1.0f;
bool ywrap = br.y > 1.0f;
// If xwrap is false, the texture will be sampled from tl.x .. br.x.
// If xwrap is true, then it will be split into tl.x .. 1.0, and
// 0.0 .. WrapTexCoord(br.x). Same for the Y axis. The destination
// rectangle is also split appropriately, according to the calculated
// xmid/ymid values.
if (!xwrap && !ywrap) {
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, aRect.XMost(), aRect.YMost(),
tl.x, tl.y, br.x, br.y,
flipped);
return 1;
}
// If we are dealing with wrapping br.x and br.y are greater than 1.0 so
// wrap them here as well.
br = gfx::Point(xwrap ? WrapTexCoord(br.x) : br.x,
ywrap ? WrapTexCoord(br.y) : br.y);
// If we wrap around along the x axis, we will draw first from
// tl.x .. 1.0 and then from 0.0 .. br.x (which we just wrapped above).
// The same applies for the Y axis. The midpoints we calculate here are
// only valid if we actually wrap around.
GLfloat xmid = aRect.x + (1.0f - tl.x) / texCoordRect.width * aRect.width;
GLfloat ymid = aRect.y + (1.0f - tl.y) / texCoordRect.height * aRect.height;
NS_ASSERTION(!xwrap ||
(xmid > aRect.x &&
xmid < aRect.XMost() &&
FuzzyEqual((xmid - aRect.x) + (aRect.XMost() - xmid), aRect.width)),
"xmid should be within [x,XMost()] and the wrapped rect should have the same width");
NS_ASSERTION(!ywrap ||
(ymid > aRect.y &&
ymid < aRect.YMost() &&
FuzzyEqual((ymid - aRect.y) + (aRect.YMost() - ymid), aRect.height)),
"ymid should be within [y,YMost()] and the wrapped rect should have the same height");
if (!xwrap && ywrap) {
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, aRect.XMost(), ymid,
tl.x, tl.y, br.x, 1.0f,
flipped);
SetRects(1, aLayerRects, aTextureRects,
aRect.x, ymid, aRect.XMost(), aRect.YMost(),
tl.x, 0.0f, br.x, br.y,
flipped);
return 2;
}
if (xwrap && !ywrap) {
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, xmid, aRect.YMost(),
tl.x, tl.y, 1.0f, br.y,
flipped);
SetRects(1, aLayerRects, aTextureRects,
xmid, aRect.y, aRect.XMost(), aRect.YMost(),
0.0f, tl.y, br.x, br.y,
flipped);
return 2;
}
SetRects(0, aLayerRects, aTextureRects,
aRect.x, aRect.y, xmid, ymid,
tl.x, tl.y, 1.0f, 1.0f,
flipped);
SetRects(1, aLayerRects, aTextureRects,
xmid, aRect.y, aRect.XMost(), ymid,
0.0f, tl.y, br.x, 1.0f,
flipped);
SetRects(2, aLayerRects, aTextureRects,
aRect.x, ymid, xmid, aRect.YMost(),
tl.x, 0.0f, 1.0f, br.y,
flipped);
SetRects(3, aLayerRects, aTextureRects,
xmid, ymid, aRect.XMost(), aRect.YMost(),
0.0f, 0.0f, br.x, br.y,
flipped);
return 4;
}
} // namespace layers
} // namespace mozilla