/* 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 "RendererScreenshotGrabber.h" #include "RendererOGL.h" #include "mozilla/gfx/2D.h" using mozilla::layers::ProfilerScreenshots; namespace mozilla { namespace wr { RendererScreenshotGrabber::RendererScreenshotGrabber() { mMaxScreenshotSize = ProfilerScreenshots::ScreenshotSize(); } void RendererScreenshotGrabber::MaybeGrabScreenshot( RendererOGL* aRendererOGL, const gfx::IntSize& aWindowSize) { bool isEnabled = ProfilerScreenshots::IsEnabled() && aRendererOGL->EnsureAsyncScreenshot(); if (isEnabled) { if (!mProfilerScreenshots) { mProfilerScreenshots = new ProfilerScreenshots(); } GrabScreenshot(aRendererOGL->GetRenderer(), aWindowSize); } else if (mProfilerScreenshots) { Destroy(aRendererOGL->GetRenderer()); } } void RendererScreenshotGrabber::MaybeProcessQueue(RendererOGL* aRendererOGL) { bool isEnabled = ProfilerScreenshots::IsEnabled() && aRendererOGL->EnsureAsyncScreenshot(); if (isEnabled) { if (!mProfilerScreenshots) { mProfilerScreenshots = new ProfilerScreenshots(); } ProcessQueue(aRendererOGL->GetRenderer()); } else if (mProfilerScreenshots) { Destroy(aRendererOGL->GetRenderer()); } } void RendererScreenshotGrabber::Destroy(Renderer* aRenderer) { mQueue.Clear(); mCurrentFrameQueueItem = Nothing(); mProfilerScreenshots = nullptr; wr_renderer_release_profiler_structures(aRenderer); } void RendererScreenshotGrabber::GrabScreenshot( Renderer* aRenderer, const gfx::IntSize& aWindowSize) { gfx::IntSize screenshotSize; // Some GLES drivers cannot read back BGRA directly (they lack // GL_EXT_read_format_bgra). On those we read RGBA and let ProcessQueue() swap // the channels into the BGRA8 profiler surface. ImageFormat readbackFormat = wr_renderer_supports_bgra_readback(aRenderer) ? ImageFormat::BGRA8 : ImageFormat::RGBA8; AsyncScreenshotHandle handle = wr_renderer_get_screenshot_async( aRenderer, 0, 0, aWindowSize.width, aWindowSize.height, mMaxScreenshotSize.width, mMaxScreenshotSize.height, readbackFormat, &screenshotSize.width, &screenshotSize.height); mCurrentFrameQueueItem = Some(QueueItem{ TimeStamp::Now(), handle, screenshotSize, aWindowSize, }); } void RendererScreenshotGrabber::ProcessQueue(Renderer* aRenderer) { for (const auto& item : mQueue) { mProfilerScreenshots->SubmitScreenshot( item.mWindowSize, item.mScreenshotSize, item.mTimeStamp, [&item, aRenderer](gfx::DataSourceSurface* aTargetSurface) { gfx::DataSourceSurface::ScopedMap map(aTargetSurface, gfx::DataSourceSurface::WRITE); int32_t destStride = map.GetStride(); // The profiler surface is always BGRA8; map_and_recycle_screenshot // swizzles if the data was read back in a different format. bool success = wr_renderer_map_and_recycle_screenshot( aRenderer, item.mHandle, map.GetData(), destStride * aTargetSurface->GetSize().height, destStride, ImageFormat::BGRA8); return success; }); } mQueue.Clear(); if (mCurrentFrameQueueItem) { mQueue.AppendElement(*mCurrentFrameQueueItem); mCurrentFrameQueueItem = Nothing(); } } } // namespace wr } // namespace mozilla