Bug 1678892 - Pass dirty and opaque regions to layers compositor. r=sotaro

The backend CompositorD3D11/CompositorOGL layers compositors can already do
partial clear optimizations for us if applicable. The only thing we need to
do is pass in the actual dirty/opaque regions so that it can utilize it.

Like with RenderCompositorSWGL, we move the actual allocation of the framebuffer
into StartCompositing when this information is known, rather than BeginFrame
which is too early in the frame to have this information yet.

Differential Revision: https://phabricator.services.mozilla.com/D109092
This commit is contained in:
Lee Salzman 2021-03-23 06:36:39 +00:00
Родитель 0e1c0ff1cf
Коммит 7d630ccb29
4 изменённых файлов: 57 добавлений и 21 удалений

Просмотреть файл

@ -1044,6 +1044,28 @@ Maybe<IntRect> CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
SetRenderTarget(rt);
mWindowRenderTarget = mCurrentRenderTarget;
for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& r = iter.Get();
mCurrentFrameInvalidRegion.OrWith(
IntRect(r.X(), FlipY(r.YMost()), r.Width(), r.Height()));
}
// Check to see if there is any transparent dirty region that would require
// clearing. If not, just invalidate the framebuffer if supported.
// TODO: Currently we initialize the clear region to the widget bounds as
// SwapBuffers will update the entire framebuffer. On platforms that support
// damage regions, we could initialize this to mCurrentFrameInvalidRegion.
IntRegion regionToClear(rect);
regionToClear.SubOut(aOpaqueRegion);
GLbitfield clearBits = LOCAL_GL_DEPTH_BUFFER_BIT;
if (regionToClear.IsEmpty() &&
mGLContext->IsSupported(GLFeature::invalidate_framebuffer)) {
GLenum attachments[] = {LOCAL_GL_COLOR};
mGLContext->fInvalidateFramebuffer(
LOCAL_GL_FRAMEBUFFER, MOZ_ARRAY_LENGTH(attachments), attachments);
} else {
clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
}
#if defined(MOZ_WIDGET_ANDROID)
if ((mSurfaceOrigin.x > 0) || (mSurfaceOrigin.y > 0)) {
mGLContext->fClearColor(
@ -1059,13 +1081,7 @@ Maybe<IntRect> CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
mGLContext->fClearColor(mClearColor.r, mClearColor.g, mClearColor.b,
mClearColor.a);
#endif // defined(MOZ_WIDGET_ANDROID)
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& r = iter.Get();
mCurrentFrameInvalidRegion.OrWith(
IntRect(r.X(), FlipY(r.YMost()), r.Width(), r.Height()));
}
mGLContext->fClear(clearBits);
return Some(rect);
}

Просмотреть файл

@ -59,33 +59,54 @@ bool RenderCompositorLayersSWGL::MakeCurrent() {
bool RenderCompositorLayersSWGL::BeginFrame() {
MOZ_ASSERT(!mInFrame);
MakeCurrent();
gfx::IntRect rect =
gfx::IntRect(gfx::IntPoint(0, 0), GetBufferSize().ToUnknownSize());
if (!mCompositor->BeginFrameForWindow(nsIntRegion(rect), Nothing(), rect,
nsIntRegion())) {
return false;
}
mInFrame = true;
return true;
}
void RenderCompositorLayersSWGL::CancelFrame() {
MOZ_ASSERT(mInFrame);
mCompositor->CancelFrame();
mInFrame = false;
mCompositingStarted = false;
if (mCompositingStarted) {
mCompositor->CancelFrame();
mCompositingStarted = false;
}
}
void RenderCompositorLayersSWGL::StartCompositing(
const wr::DeviceIntRect* aDirtyRects, size_t aNumDirtyRects,
const wr::DeviceIntRect* aOpaqueRects, size_t aNumOpaqueRects) {
mCompositingStarted = mInFrame;
if (!mInFrame) {
return;
}
gfx::IntRect bounds(gfx::IntPoint(0, 0), GetBufferSize().ToUnknownSize());
nsIntRegion dirty;
if (aNumDirtyRects) {
for (size_t i = 0; i < aNumDirtyRects; i++) {
const auto& rect = aDirtyRects[i];
dirty.OrWith(gfx::IntRect(rect.origin.x, rect.origin.y, rect.size.width,
rect.size.height));
}
dirty.AndWith(bounds);
} else {
dirty = bounds;
}
nsIntRegion opaque(bounds);
opaque.SubOut(mWidget->GetTransparentRegion().ToUnknownRegion());
for (size_t i = 0; i < aNumOpaqueRects; i++) {
const auto& rect = aOpaqueRects[i];
opaque.OrWith(gfx::IntRect(rect.origin.x, rect.origin.y, rect.size.width,
rect.size.height));
}
if (!mCompositor->BeginFrameForWindow(dirty, Nothing(), bounds, opaque)) {
return;
}
mCompositingStarted = true;
}
void RenderCompositorLayersSWGL::CompositorEndFrame() {
nsTArray<FrameSurface> frameSurfaces = std::move(mFrameSurfaces);
if (!mInFrame) {
if (!mCompositingStarted) {
return;
}
@ -133,8 +154,6 @@ RenderedFrameId RenderCompositorLayersSWGL::EndFrame(
if (mCompositingStarted) {
mCompositor->EndFrame();
mCompositingStarted = false;
} else {
mCompositor->CancelFrame();
}
return GetNextRenderFrameId();
}

Просмотреть файл

@ -244,7 +244,7 @@
# On Android, we want an opaque background to be visible under the page,
# so layout should not force a default background.
- name: android.widget_paints_background
type: bool
type: RelaxedAtomicBool
value: true
mirror: always

Просмотреть файл

@ -67,7 +67,8 @@ LayoutDeviceIntRegion CompositorWidget::GetTransparentRegion() {
// transparent. Widgets wanting more complex transparency region determination
// should override this method.
auto* widget = RealWidget();
if (!widget || widget->GetTransparencyMode() != eTransparencyOpaque) {
if (!widget || widget->GetTransparencyMode() != eTransparencyOpaque ||
widget->WidgetPaintsBackground()) {
return LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), GetClientSize());
}
return LayoutDeviceIntRegion();