mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1656818 - Move decision to flip WebRender readback closer to the source, and make it correct for SWGL. r=lsalzman,geckoview-reviewers,snorp
Differential Revision: https://phabricator.services.mozilla.com/D86892
This commit is contained in:
parent
02b6ed52b4
commit
a250b4d7a3
@ -1450,7 +1450,7 @@ void LayerManagerComposite::HandlePixelsTarget() {
|
||||
gl->fReadPixels(0, 0, bufferWidth, bufferHeight, LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE, mem.get<uint8_t>());
|
||||
Unused << mScreenPixelsTarget->SendScreenPixels(
|
||||
std::move(mem), ScreenIntSize(bufferWidth, bufferHeight));
|
||||
std::move(mem), ScreenIntSize(bufferWidth, bufferHeight), true);
|
||||
mScreenPixelsTarget = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
@ -39,7 +39,7 @@ parent:
|
||||
child:
|
||||
async ToolbarAnimatorMessageFromCompositor(int32_t aMessage);
|
||||
async RootFrameMetrics(ScreenPoint aScrollOffset, CSSToScreenScale aZoom);
|
||||
async ScreenPixels(Shmem aMem, ScreenIntSize aSize);
|
||||
async ScreenPixels(Shmem aMem, ScreenIntSize aSize, bool aNeedsYFlip);
|
||||
};
|
||||
|
||||
} // layers
|
||||
|
@ -64,7 +64,7 @@ parent:
|
||||
async UpdateResources(OpUpdateResource[] aResourceUpdates,
|
||||
RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
|
||||
async ParentCommands(WebRenderParentCommand[] commands);
|
||||
sync GetSnapshot(PTexture texture);
|
||||
sync GetSnapshot(PTexture texture) returns (bool aNeedsYFlip);
|
||||
async SetLayersObserverEpoch(LayersObserverEpoch childEpoch);
|
||||
async ClearCachedResources();
|
||||
// Invalidate rendered frame
|
||||
|
@ -240,10 +240,10 @@ mozilla::ipc::IPCResult UiCompositorControllerChild::RecvRootFrameMetrics(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult UiCompositorControllerChild::RecvScreenPixels(
|
||||
ipc::Shmem&& aMem, const ScreenIntSize& aSize) {
|
||||
ipc::Shmem&& aMem, const ScreenIntSize& aSize, bool aNeedsYFlip) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
if (mWidget) {
|
||||
mWidget->RecvScreenPixels(std::move(aMem), aSize);
|
||||
mWidget->RecvScreenPixels(std::move(aMem), aSize, aNeedsYFlip);
|
||||
}
|
||||
#endif // defined(MOZ_WIDGET_ANDROID)
|
||||
|
||||
|
@ -60,7 +60,8 @@ class UiCompositorControllerChild final
|
||||
mozilla::ipc::IPCResult RecvRootFrameMetrics(const ScreenPoint& aScrollOffset,
|
||||
const CSSToScreenScale& aZoom);
|
||||
mozilla::ipc::IPCResult RecvScreenPixels(Shmem&& aMem,
|
||||
const ScreenIntSize& aSize);
|
||||
const ScreenIntSize& aSize,
|
||||
bool aNeedsYFlip);
|
||||
|
||||
private:
|
||||
explicit UiCompositorControllerChild(const uint64_t& aProcessToken);
|
||||
|
@ -1528,18 +1528,21 @@ void WebRenderBridgeParent::MaybeCaptureScreenPixels() {
|
||||
|
||||
IntSize size(client_size.width, client_size.height);
|
||||
|
||||
bool needsYFlip = false;
|
||||
mApi->Readback(TimeStamp::Now(), size, format,
|
||||
Range<uint8_t>(mem.get<uint8_t>(), buffer_size));
|
||||
Range<uint8_t>(mem.get<uint8_t>(), buffer_size), &needsYFlip);
|
||||
|
||||
Unused << mScreenPixelsTarget->SendScreenPixels(
|
||||
std::move(mem), ScreenIntSize(client_size.width, client_size.height));
|
||||
std::move(mem), ScreenIntSize(client_size.width, client_size.height),
|
||||
needsYFlip);
|
||||
|
||||
mScreenPixelsTarget = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetSnapshot(
|
||||
PTextureParent* aTexture) {
|
||||
PTextureParent* aTexture, bool* aNeedsYFlip) {
|
||||
*aNeedsYFlip = false;
|
||||
if (mDestroyed) {
|
||||
return IPC_OK();
|
||||
}
|
||||
@ -1591,7 +1594,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetSnapshot(
|
||||
FlushSceneBuilds();
|
||||
FlushFrameGeneration();
|
||||
mApi->Readback(start, size, bufferTexture->GetFormat(),
|
||||
Range<uint8_t>(buffer, buffer_size));
|
||||
Range<uint8_t>(buffer, buffer_size), aNeedsYFlip);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -170,7 +170,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||
const FocusTarget& aFocusTarget) override;
|
||||
mozilla::ipc::IPCResult RecvParentCommands(
|
||||
nsTArray<WebRenderParentCommand>&& commands) override;
|
||||
mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
|
||||
mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture,
|
||||
bool* aNeedsYFlip) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetLayersObserverEpoch(
|
||||
const LayersObserverEpoch& aChildEpoch) override;
|
||||
|
@ -471,7 +471,8 @@ void WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize) {
|
||||
}
|
||||
|
||||
IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
|
||||
if (!WrBridge()->SendGetSnapshot(texture->GetIPDLActor())) {
|
||||
bool needsYFlip = false;
|
||||
if (!WrBridge()->SendGetSnapshot(texture->GetIPDLActor(), &needsYFlip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -495,14 +496,6 @@ void WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize) {
|
||||
Rect dst(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height());
|
||||
Rect src(0, 0, bounds.Width(), bounds.Height());
|
||||
|
||||
// The data we get from webrender is upside down. So flip and translate up so
|
||||
// the image is rightside up. Webrender always does a full screen readback.
|
||||
#ifdef XP_WIN
|
||||
// ANGLE with WR does not need y flip
|
||||
const bool needsYFlip = !WrBridge()->GetCompositorUseANGLE();
|
||||
#else
|
||||
const bool needsYFlip = true;
|
||||
#endif
|
||||
Matrix m;
|
||||
if (needsYFlip) {
|
||||
m = Matrix::Scaling(1.0, -1.0).PostTranslate(0.0, aSize.height);
|
||||
|
@ -132,7 +132,8 @@ class RenderCompositor {
|
||||
// result. It could happen when WebRender renders to multiple overlay layers.
|
||||
virtual bool MaybeReadback(const gfx::IntSize& aReadbackSize,
|
||||
const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer) {
|
||||
const Range<uint8_t>& aReadbackBuffer,
|
||||
bool* aNeedsYFlip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -940,7 +940,7 @@ uint32_t RenderCompositorANGLE::GetMaxPartialPresentRects() {
|
||||
|
||||
bool RenderCompositorANGLE::MaybeReadback(
|
||||
const gfx::IntSize& aReadbackSize, const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer) {
|
||||
const Range<uint8_t>& aReadbackBuffer, bool* aNeedsYFlip) {
|
||||
MOZ_ASSERT(aReadbackFormat == wr::ImageFormat::BGRA8);
|
||||
|
||||
if (!UseCompositor()) {
|
||||
@ -1007,6 +1007,10 @@ bool RenderCompositorANGLE::MaybeReadback(
|
||||
gfxCriticalNote << "Readback took too long: " << latencyMs << " ms";
|
||||
}
|
||||
|
||||
if (aNeedsYFlip) {
|
||||
*aNeedsYFlip = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,8 @@ class RenderCompositorANGLE : public RenderCompositor {
|
||||
|
||||
bool MaybeReadback(const gfx::IntSize& aReadbackSize,
|
||||
const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer) override;
|
||||
const Range<uint8_t>& aReadbackBuffer,
|
||||
bool* aNeedsYFlip) override;
|
||||
|
||||
protected:
|
||||
bool UseCompositor();
|
||||
|
@ -98,7 +98,7 @@ bool RenderCompositorNative::ShouldUseNativeCompositor() {
|
||||
|
||||
bool RenderCompositorNative::MaybeReadback(
|
||||
const gfx::IntSize& aReadbackSize, const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer) {
|
||||
const Range<uint8_t>& aReadbackBuffer, bool* aNeedsYFlip) {
|
||||
if (!ShouldUseNativeCompositor()) {
|
||||
return false;
|
||||
}
|
||||
@ -114,6 +114,10 @@ bool RenderCompositorNative::MaybeReadback(
|
||||
// current again.
|
||||
MakeCurrent();
|
||||
|
||||
if (aNeedsYFlip) {
|
||||
*aNeedsYFlip = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,8 @@ class RenderCompositorNative : public RenderCompositor {
|
||||
// Does the readback for the ShouldUseNativeCompositor() case.
|
||||
bool MaybeReadback(const gfx::IntSize& aReadbackSize,
|
||||
const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer) override;
|
||||
const Range<uint8_t>& aReadbackBuffer,
|
||||
bool* aNeedsYFlip) override;
|
||||
|
||||
// Interface for wr::Compositor
|
||||
void CompositorBeginFrame() override;
|
||||
|
@ -457,7 +457,7 @@ void RenderThread::UpdateAndRender(
|
||||
const TimeStamp& aStartTime, bool aRender,
|
||||
const Maybe<gfx::IntSize>& aReadbackSize,
|
||||
const Maybe<wr::ImageFormat>& aReadbackFormat,
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer) {
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer, bool* aNeedsYFlip) {
|
||||
AUTO_PROFILER_TRACING_MARKER("Paint", "Composite", GRAPHICS);
|
||||
MOZ_ASSERT(IsInRenderThread());
|
||||
MOZ_ASSERT(aRender || aReadbackBuffer.isNothing());
|
||||
@ -479,8 +479,8 @@ void RenderThread::UpdateAndRender(
|
||||
wr::RenderedFrameId latestFrameId;
|
||||
RendererStats stats = {0};
|
||||
if (aRender) {
|
||||
latestFrameId = renderer->UpdateAndRender(aReadbackSize, aReadbackFormat,
|
||||
aReadbackBuffer, &stats);
|
||||
latestFrameId = renderer->UpdateAndRender(
|
||||
aReadbackSize, aReadbackFormat, aReadbackBuffer, aNeedsYFlip, &stats);
|
||||
} else {
|
||||
renderer->Update();
|
||||
}
|
||||
|
@ -188,7 +188,8 @@ class RenderThread final {
|
||||
const TimeStamp& aStartTime, bool aRender,
|
||||
const Maybe<gfx::IntSize>& aReadbackSize,
|
||||
const Maybe<wr::ImageFormat>& aReadbackFormat,
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer);
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer,
|
||||
bool* aNeedsYFlip = nullptr);
|
||||
|
||||
void Pause(wr::WindowId aWindowId);
|
||||
bool Resume(wr::WindowId aWindowId);
|
||||
|
@ -114,7 +114,8 @@ static void DoWebRenderDisableNativeCompositor(
|
||||
RenderedFrameId RendererOGL::UpdateAndRender(
|
||||
const Maybe<gfx::IntSize>& aReadbackSize,
|
||||
const Maybe<wr::ImageFormat>& aReadbackFormat,
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer, RendererStats* aOutStats) {
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer, bool* aNeedsYFlip,
|
||||
RendererStats* aOutStats) {
|
||||
mozilla::widget::WidgetRenderingContext widgetContext;
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
@ -164,11 +165,18 @@ RenderedFrameId RendererOGL::UpdateAndRender(
|
||||
MOZ_ASSERT(aReadbackSize.isSome());
|
||||
MOZ_ASSERT(aReadbackFormat.isSome());
|
||||
if (!mCompositor->MaybeReadback(aReadbackSize.ref(), aReadbackFormat.ref(),
|
||||
aReadbackBuffer.ref())) {
|
||||
aReadbackBuffer.ref(), aNeedsYFlip)) {
|
||||
wr_renderer_readback(mRenderer, aReadbackSize.ref().width,
|
||||
aReadbackSize.ref().height, aReadbackFormat.ref(),
|
||||
&aReadbackBuffer.ref()[0],
|
||||
aReadbackBuffer.ref().length());
|
||||
|
||||
// SWGL and ANGLE both draw the right way up, otherwise we will need a
|
||||
// flip.
|
||||
if (aNeedsYFlip) {
|
||||
*aNeedsYFlip =
|
||||
!gfx::gfxVars::UseSoftwareWebRender() && !mCompositor->UseANGLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ class RendererOGL {
|
||||
RenderedFrameId UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize,
|
||||
const Maybe<wr::ImageFormat>& aReadbackFormat,
|
||||
const Maybe<Range<uint8_t>>& aReadbackBuffer,
|
||||
RendererStats* aOutStats);
|
||||
bool* aNeedsYFlip, RendererStats* aOutStats);
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
void WaitForGPU();
|
||||
|
@ -441,17 +441,18 @@ std::vector<WrHitResult> WebRenderAPI::HitTest(const wr::WorldPoint& aPoint) {
|
||||
|
||||
void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
|
||||
const gfx::SurfaceFormat& aFormat,
|
||||
const Range<uint8_t>& buffer) {
|
||||
const Range<uint8_t>& buffer, bool* aNeedsYFlip) {
|
||||
class Readback : public RendererEvent {
|
||||
public:
|
||||
explicit Readback(layers::SynchronousTask* aTask, TimeStamp aStartTime,
|
||||
gfx::IntSize aSize, const gfx::SurfaceFormat& aFormat,
|
||||
const Range<uint8_t>& aBuffer)
|
||||
const Range<uint8_t>& aBuffer, bool* aNeedsYFlip)
|
||||
: mTask(aTask),
|
||||
mStartTime(aStartTime),
|
||||
mSize(aSize),
|
||||
mFormat(aFormat),
|
||||
mBuffer(aBuffer) {
|
||||
mBuffer(aBuffer),
|
||||
mNeedsYFlip(aNeedsYFlip) {
|
||||
MOZ_COUNT_CTOR(Readback);
|
||||
}
|
||||
|
||||
@ -461,7 +462,7 @@ void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
|
||||
aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime,
|
||||
/* aRender */ true, Some(mSize),
|
||||
wr::SurfaceFormatToImageFormat(mFormat),
|
||||
Some(mBuffer));
|
||||
Some(mBuffer), mNeedsYFlip);
|
||||
layers::AutoCompleteTask complete(mTask);
|
||||
}
|
||||
|
||||
@ -470,13 +471,15 @@ void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
|
||||
gfx::IntSize mSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
const Range<uint8_t>& mBuffer;
|
||||
bool* mNeedsYFlip;
|
||||
};
|
||||
|
||||
// Disable debug flags during readback. See bug 1436020.
|
||||
UpdateDebugFlags(0);
|
||||
|
||||
layers::SynchronousTask task("Readback");
|
||||
auto event = MakeUnique<Readback>(&task, aStartTime, size, aFormat, buffer);
|
||||
auto event = MakeUnique<Readback>(&task, aStartTime, size, aFormat, buffer,
|
||||
aNeedsYFlip);
|
||||
// This event will be passed from wr_backend thread to renderer thread. That
|
||||
// implies that all frame data have been processed when the renderer runs this
|
||||
// read-back event. Then, we could make sure this read-back event gets the
|
||||
@ -862,8 +865,7 @@ void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) {
|
||||
wr_api_send_external_event(mDocHandle, event);
|
||||
}
|
||||
|
||||
DisplayListBuilder::DisplayListBuilder(PipelineId aId,
|
||||
size_t aCapacity,
|
||||
DisplayListBuilder::DisplayListBuilder(PipelineId aId, size_t aCapacity,
|
||||
layers::DisplayItemCache* aCache)
|
||||
: mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
|
||||
mActiveFixedPosTracker(nullptr),
|
||||
|
@ -249,7 +249,7 @@ class WebRenderAPI final {
|
||||
|
||||
void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize,
|
||||
const gfx::SurfaceFormat& aFormat,
|
||||
const Range<uint8_t>& aBuffer);
|
||||
const Range<uint8_t>& aBuffer, bool* aNeedsYFlip);
|
||||
|
||||
void ClearAllCaches();
|
||||
void EnableNativeCompositor(bool aEnable);
|
||||
|
@ -1226,7 +1226,8 @@ class nsWindow::LayerViewSupport final
|
||||
}
|
||||
}
|
||||
|
||||
void RecvScreenPixels(Shmem&& aMem, const ScreenIntSize& aSize) {
|
||||
void RecvScreenPixels(Shmem&& aMem, const ScreenIntSize& aSize,
|
||||
bool aNeedsYFlip) {
|
||||
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
|
||||
CaptureRequest request;
|
||||
java::GeckoResult::LocalRef result = nullptr;
|
||||
@ -1244,8 +1245,16 @@ class nsWindow::LayerViewSupport final
|
||||
|
||||
if (result) {
|
||||
if (bitmap) {
|
||||
RefPtr<DataSourceSurface> surf =
|
||||
FlipScreenPixels(aMem, aSize, request.mSource, request.mOutputSize);
|
||||
RefPtr<DataSourceSurface> surf;
|
||||
if (aNeedsYFlip) {
|
||||
surf = FlipScreenPixels(aMem, aSize, request.mSource,
|
||||
request.mOutputSize);
|
||||
} else {
|
||||
surf = gfx::Factory::CreateWrappingDataSourceSurface(
|
||||
aMem.get<uint8_t>(),
|
||||
StrideForFormatAndWidth(SurfaceFormat::B8G8R8A8, aSize.width),
|
||||
IntSize(aSize.width, aSize.height), SurfaceFormat::B8G8R8A8);
|
||||
}
|
||||
if (surf) {
|
||||
DataSourceSurface::ScopedMap smap(surf, DataSourceSurface::READ);
|
||||
auto pixels = mozilla::jni::ByteBuffer::New(
|
||||
@ -2405,10 +2414,11 @@ void nsWindow::UpdateRootFrameMetrics(const ScreenPoint& aScrollOffset,
|
||||
}
|
||||
}
|
||||
|
||||
void nsWindow::RecvScreenPixels(Shmem&& aMem, const ScreenIntSize& aSize) {
|
||||
void nsWindow::RecvScreenPixels(Shmem&& aMem, const ScreenIntSize& aSize,
|
||||
bool aNeedsYFlip) {
|
||||
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
|
||||
if (NativePtr<LayerViewSupport>::Locked lvs{mLayerViewSupport}) {
|
||||
lvs->RecvScreenPixels(std::move(aMem), aSize);
|
||||
lvs->RecvScreenPixels(std::move(aMem), aSize, aNeedsYFlip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,8 +325,8 @@ class nsWindow final : public nsBaseWidget {
|
||||
void RecvToolbarAnimatorMessageFromCompositor(int32_t aMessage) override;
|
||||
void UpdateRootFrameMetrics(const ScreenPoint& aScrollOffset,
|
||||
const CSSToScreenScale& aZoom) override;
|
||||
void RecvScreenPixels(mozilla::ipc::Shmem&& aMem,
|
||||
const ScreenIntSize& aSize) override;
|
||||
void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize,
|
||||
bool aNeedsYFlip) override;
|
||||
void UpdateDynamicToolbarMaxHeight(mozilla::ScreenIntCoord aHeight) override;
|
||||
mozilla::ScreenIntCoord GetDynamicToolbarMaxHeight() const override {
|
||||
return mDynamicToolbarMaxHeight;
|
||||
|
@ -433,8 +433,8 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
||||
void RecvToolbarAnimatorMessageFromCompositor(int32_t) override{};
|
||||
void UpdateRootFrameMetrics(const ScreenPoint& aScrollOffset,
|
||||
const CSSToScreenScale& aZoom) override{};
|
||||
void RecvScreenPixels(mozilla::ipc::Shmem&& aMem,
|
||||
const ScreenIntSize& aSize) override{};
|
||||
void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize,
|
||||
bool aNeedsYFlip) override{};
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
@ -2127,7 +2127,8 @@ class nsIWidget : public nsISupports {
|
||||
* @param aSize size of the buffer in screen pixels.
|
||||
*/
|
||||
virtual void RecvScreenPixels(mozilla::ipc::Shmem&& aMem,
|
||||
const ScreenIntSize& aSize) = 0;
|
||||
const ScreenIntSize& aSize,
|
||||
bool aNeedsYFlip) = 0;
|
||||
|
||||
virtual void UpdateDynamicToolbarMaxHeight(mozilla::ScreenIntCoord aHeight) {}
|
||||
virtual mozilla::ScreenIntCoord GetDynamicToolbarMaxHeight() const {
|
||||
|
Loading…
Reference in New Issue
Block a user