зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1689245 - replace CompositorWidget::ClearBeforePaint with GetTransparentRegion. r=mattwoodrow
ClearBeforePaint put the responsibility of clearing the current frame's DrawTarget onto the widget. This doesn't compose well with WR RenderCompositor that may do their own internal clearing. Instead, replace this with a GetTransparentRegion API that can be used by RenderCompositors to limit where they clear so that they are now fully responsible for clearing. Differential Revision: https://phabricator.services.mozilla.com/D103253
This commit is contained in:
Родитель
3d319c55f8
Коммит
b2bd266cde
|
@ -50,7 +50,7 @@ bool RenderCompositorSWGL::BeginFrame() {
|
|||
// Set up a temporary region representing the entire window surface in case a
|
||||
// dirty region is not supplied.
|
||||
ClearMappedBuffer();
|
||||
mRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
|
||||
mDirtyRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
|
||||
wr_swgl_make_current(mContext);
|
||||
return true;
|
||||
}
|
||||
|
@ -60,11 +60,10 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
|
|||
// Request a new draw target to use from the widget...
|
||||
MOZ_ASSERT(!mDT);
|
||||
layers::BufferMode bufferMode = layers::BufferMode::BUFFERED;
|
||||
mDT = mWidget->StartRemoteDrawingInRegion(mRegion, &bufferMode);
|
||||
mDT = mWidget->StartRemoteDrawingInRegion(mDirtyRegion, &bufferMode);
|
||||
if (!mDT) {
|
||||
return false;
|
||||
}
|
||||
mWidget->ClearBeforePaint(mDT, mRegion);
|
||||
// Attempt to lock the underlying buffer directly from the draw target.
|
||||
// Verify that the size at least matches what the widget claims and that
|
||||
// the format is BGRA8 as SWGL requires.
|
||||
|
@ -81,7 +80,7 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
|
|||
mDT->ReleaseBits(data);
|
||||
data = nullptr;
|
||||
}
|
||||
LayoutDeviceIntRect bounds = mRegion.GetBounds();
|
||||
LayoutDeviceIntRect bounds = mDirtyRegion.GetBounds();
|
||||
// If locking succeeded above, just use that.
|
||||
if (data) {
|
||||
mMappedData = data;
|
||||
|
@ -106,7 +105,7 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
|
|||
gfx::DataSourceSurface::MappedSurface map = {nullptr, 0};
|
||||
if (!mSurface || !mSurface->Map(gfx::DataSourceSurface::READ_WRITE, &map)) {
|
||||
// We failed mapping the data surface, so need to cancel the frame.
|
||||
mWidget->EndRemoteDrawingInRegion(mDT, mRegion);
|
||||
mWidget->EndRemoteDrawingInRegion(mDT, mDirtyRegion);
|
||||
ClearMappedBuffer();
|
||||
return false;
|
||||
}
|
||||
|
@ -124,8 +123,9 @@ bool RenderCompositorSWGL::AllocateMappedBuffer(
|
|||
rect.size.width, rect.size.height));
|
||||
}
|
||||
|
||||
LayoutDeviceIntRegion clear;
|
||||
clear.Sub(mRegion, opaque);
|
||||
LayoutDeviceIntRegion clear = mWidget->GetTransparentRegion();
|
||||
clear.AndWith(mDirtyRegion);
|
||||
clear.SubOut(opaque);
|
||||
for (auto iter = clear.RectIter(); !iter.Done(); iter.Next()) {
|
||||
const auto& rect = iter.Get();
|
||||
wr_swgl_clear_color_rect(mContext, 0, rect.x, rect.y, rect.width,
|
||||
|
@ -142,19 +142,19 @@ void RenderCompositorSWGL::StartCompositing(
|
|||
// Cancel any existing buffers that might accidentally be left from updates
|
||||
CommitMappedBuffer(false);
|
||||
// Reset the region to the widget bounds
|
||||
mRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
|
||||
mDirtyRegion = LayoutDeviceIntRect(LayoutDeviceIntPoint(), GetBufferSize());
|
||||
}
|
||||
if (aNumDirtyRects) {
|
||||
// Install the dirty rects into the bounds of the existing region
|
||||
auto bounds = mRegion.GetBounds();
|
||||
mRegion.SetEmpty();
|
||||
auto bounds = mDirtyRegion.GetBounds();
|
||||
mDirtyRegion.SetEmpty();
|
||||
for (size_t i = 0; i < aNumDirtyRects; i++) {
|
||||
const auto& rect = aDirtyRects[i];
|
||||
mRegion.OrWith(LayoutDeviceIntRect(rect.origin.x, rect.origin.y,
|
||||
rect.size.width, rect.size.height));
|
||||
mDirtyRegion.OrWith(LayoutDeviceIntRect(
|
||||
rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
|
||||
}
|
||||
// Ensure the region lies within the widget bounds
|
||||
mRegion.AndWith(bounds);
|
||||
mDirtyRegion.AndWith(bounds);
|
||||
}
|
||||
// Now that the dirty rects have been supplied and the composition region
|
||||
// is known, allocate and install a framebuffer encompassing the composition
|
||||
|
@ -186,12 +186,12 @@ void RenderCompositorSWGL::CommitMappedBuffer(bool aDirty) {
|
|||
// that is offset from the origin to the actual bounds of the dirty
|
||||
// region. The destination DT may also be an offset partial region, but we
|
||||
// must check to see if its size matches the region bounds to verify this.
|
||||
LayoutDeviceIntRect bounds = mRegion.GetBounds();
|
||||
LayoutDeviceIntRect bounds = mDirtyRegion.GetBounds();
|
||||
gfx::IntPoint srcOffset = bounds.TopLeft().ToUnknownPoint();
|
||||
gfx::IntPoint dstOffset = mDT->GetSize() == bounds.Size().ToUnknownSize()
|
||||
? srcOffset
|
||||
: gfx::IntPoint(0, 0);
|
||||
for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = mDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
|
||||
gfx::IntRect dirtyRect = iter.Get().ToUnknownRect();
|
||||
mDT->CopySurface(mSurface, dirtyRect - srcOffset,
|
||||
dirtyRect.TopLeft() - dstOffset);
|
||||
|
@ -202,7 +202,7 @@ void RenderCompositorSWGL::CommitMappedBuffer(bool aDirty) {
|
|||
mDT->ReleaseBits(mMappedData);
|
||||
}
|
||||
// Done with the DT. Hand it back to the widget and clear out any trace of it.
|
||||
mWidget->EndRemoteDrawingInRegion(mDT, mRegion);
|
||||
mWidget->EndRemoteDrawingInRegion(mDT, mDirtyRegion);
|
||||
ClearMappedBuffer();
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class RenderCompositorSWGL : public RenderCompositor {
|
|||
private:
|
||||
void* mContext = nullptr;
|
||||
RefPtr<gfx::DrawTarget> mDT;
|
||||
LayoutDeviceIntRegion mRegion;
|
||||
LayoutDeviceIntRegion mDirtyRegion;
|
||||
RefPtr<gfx::DataSourceSurface> mSurface;
|
||||
uint8_t* mMappedData = nullptr;
|
||||
int32_t mMappedStride = 0;
|
||||
|
|
|
@ -61,5 +61,17 @@ RefPtr<VsyncObserver> CompositorWidget::GetVsyncObserver() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LayoutDeviceIntRegion CompositorWidget::GetTransparentRegion() {
|
||||
// By default, we check the transparency mode to determine if the widget is
|
||||
// transparent, and if so, designate the entire widget drawing area as
|
||||
// transparent. Widgets wanting more complex transparency region determination
|
||||
// should override this method.
|
||||
auto* widget = RealWidget();
|
||||
if (!widget || widget->GetTransparencyMode() != eTransparencyOpaque) {
|
||||
return LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), GetClientSize());
|
||||
}
|
||||
return LayoutDeviceIntRegion();
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -165,10 +165,10 @@ class CompositorWidget {
|
|||
|
||||
/**
|
||||
* Some widgets (namely Gtk) may need clean up underlying surface
|
||||
* before painting to draw transparent objects correctly.
|
||||
* before painting to draw transparent objects correctly. Return
|
||||
* the transparent region where this clearing is required.
|
||||
*/
|
||||
virtual void ClearBeforePaint(RefPtr<gfx::DrawTarget> aTarget,
|
||||
const LayoutDeviceIntRegion& aRegion) {}
|
||||
virtual LayoutDeviceIntRegion GetTransparentRegion();
|
||||
|
||||
/**
|
||||
* Called when shutting down the LayerManager to clean-up any cached
|
||||
|
|
|
@ -125,22 +125,16 @@ void GtkCompositorWidget::SetEGLNativeWindowSize(
|
|||
}
|
||||
#endif
|
||||
|
||||
void GtkCompositorWidget::ClearBeforePaint(
|
||||
RefPtr<gfx::DrawTarget> aTarget, const LayoutDeviceIntRegion& aRegion) {
|
||||
LayoutDeviceIntRegion GtkCompositorWidget::GetTransparentRegion() {
|
||||
// We need to clear target buffer alpha values of popup windows as
|
||||
// SW-WR paints with alpha blending (see Bug 1674473).
|
||||
if (mWidget->IsPopup()) {
|
||||
for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
|
||||
aTarget->ClearRect(gfx::Rect(iter.Get().ToUnknownRect()));
|
||||
}
|
||||
return LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), GetClientSize());
|
||||
}
|
||||
|
||||
// Clear background of titlebar area to render titlebar
|
||||
// transparent corners correctly.
|
||||
gfx::Rect rect;
|
||||
if (mWidget->GetTitlebarRect(rect)) {
|
||||
aTarget->ClearRect(rect);
|
||||
}
|
||||
return mWidget->GetTitlebarRect();
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -61,8 +61,7 @@ class GtkCompositorWidget : public CompositorWidget,
|
|||
EGLNativeWindowType GetEGLNativeWindow();
|
||||
int32_t GetDepth();
|
||||
|
||||
void ClearBeforePaint(RefPtr<gfx::DrawTarget> aTarget,
|
||||
const LayoutDeviceIntRegion& aRegion) override;
|
||||
LayoutDeviceIntRegion GetTransparentRegion() override;
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
Display* XDisplay() const { return mXDisplay; }
|
||||
|
|
|
@ -5896,13 +5896,12 @@ nsresult nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsWindow::GetTitlebarRect(mozilla::gfx::Rect& aRect) {
|
||||
LayoutDeviceIntRect nsWindow::GetTitlebarRect() {
|
||||
if (!mGdkWindow || !mDrawInTitlebar) {
|
||||
return false;
|
||||
return LayoutDeviceIntRect();
|
||||
}
|
||||
|
||||
aRect = gfx::Rect(0, 0, mBounds.width, TITLEBAR_SHAPE_MASK_HEIGHT);
|
||||
return true;
|
||||
return LayoutDeviceIntRect(0, 0, mBounds.width, TITLEBAR_SHAPE_MASK_HEIGHT);
|
||||
}
|
||||
|
||||
void nsWindow::UpdateTitlebarTransparencyBitmap() {
|
||||
|
|
|
@ -380,7 +380,7 @@ class nsWindow final : public nsBaseWidget {
|
|||
virtual nsresult SetNonClientMargins(
|
||||
LayoutDeviceIntMargin& aMargins) override;
|
||||
void SetDrawsInTitlebar(bool aState) override;
|
||||
bool GetTitlebarRect(mozilla::gfx::Rect& aRect);
|
||||
LayoutDeviceIntRect GetTitlebarRect();
|
||||
virtual void UpdateWindowDraggingRegion(
|
||||
const LayoutDeviceIntRegion& aRegion) override;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче