Bug 1585619 - Add option of using PrintWindow() for taking snapshot of DirectComposition r=gw

Differential Revision: https://phabricator.services.mozilla.com/D47894

--HG--
extra : moz-landing-system : lando
This commit is contained in:
sotaro 2019-11-30 03:14:58 +00:00
Родитель 0c611d19d9
Коммит 00f9b4efee
6 изменённых файлов: 96 добавлений и 4 удалений

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

@ -126,6 +126,10 @@ void DCLayerTree::MaybeUpdateDebug() {
}
}
void DCLayerTree::WaitForCommitCompletion() {
mCompositionDevice->WaitForCommitCompletion();
}
bool DCLayerTree::MaybeUpdateDebugCounter() {
bool debugCounter = StaticPrefs::gfx_webrender_debug_dcomp_counter();
if (mDebugCounter == debugCounter) {

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

@ -53,6 +53,7 @@ class DCLayerTree {
void SetDefaultSwapChain(IDXGISwapChain1* aSwapChain);
void MaybeUpdateDebug();
void WaitForCommitCompletion();
// Interface for wr::Compositor
void CompositorBeginFrame();
@ -164,6 +165,7 @@ class DCLayerTree {
}
void SetDefaultSwapChain(IDXGISwapChain1* aSwapChain) {}
void MaybeUpdateDebug() {}
void WaitForCommitCompletion() {}
// Interface for wr::Compositor
void CompositorBeginFrame() {}

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

@ -99,6 +99,14 @@ class RenderCompositor {
// Whether the surface origin is top-left.
virtual bool SurfaceOriginIsTopLeft() { return false; }
// Does readback if wr_renderer_readback() could not get correct WR rendered
// 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) {
return false;
}
protected:
// We default this to 2, so that mLatestRenderFrameId.Prev() is always valid.
RenderedFrameId mLatestRenderFrameId = RenderedFrameId{2};

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

@ -30,6 +30,12 @@
#include <dcomp.h>
#include <dxgi1_2.h>
// Flag for PrintWindow() that is defined in Winuser.h. It is defined since
// Windows 8.1. This allows PrintWindow to capture window content that is
// rendered with DirectComposition.
#undef PW_RENDERFULLCONTENT
#define PW_RENDERFULLCONTENT 0x00000002
namespace mozilla {
namespace wr {
@ -777,5 +783,70 @@ uint32_t RenderCompositorANGLE::GetMaxPartialPresentRects() {
return StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup();
}
bool RenderCompositorANGLE::MaybeReadback(
const gfx::IntSize& aReadbackSize, const wr::ImageFormat& aReadbackFormat,
const Range<uint8_t>& aReadbackBuffer) {
MOZ_ASSERT(aReadbackFormat == wr::ImageFormat::BGRA8);
if (!UseCompositor()) {
return false;
}
HDC nulldc = ::GetDC(NULL);
HDC dc = ::CreateCompatibleDC(nulldc);
::ReleaseDC(nullptr, nulldc);
if (!dc) {
gfxCriticalError() << "CreateCompatibleDC failed";
return false;
}
BITMAPV4HEADER header;
memset(&header, 0, sizeof(BITMAPV4HEADER));
header.bV4Size = sizeof(BITMAPV4HEADER);
header.bV4Width = aReadbackSize.width;
header.bV4Height = -LONG(aReadbackSize.height); // top-to-buttom DIB
header.bV4Planes = 1;
header.bV4BitCount = 32;
header.bV4V4Compression = BI_BITFIELDS;
header.bV4RedMask = 0x00FF0000;
header.bV4GreenMask = 0x0000FF00;
header.bV4BlueMask = 0x000000FF;
header.bV4AlphaMask = 0xFF000000;
void* readbackBits = nullptr;
HBITMAP bitmap =
::CreateDIBSection(dc, reinterpret_cast<BITMAPINFO*>(&header),
DIB_RGB_COLORS, &readbackBits, nullptr, 0);
if (!bitmap) {
::DeleteDC(dc);
gfxCriticalError() << "CreateDIBSection failed";
return false;
}
::SelectObject(dc, bitmap);
UINT flags = PW_CLIENTONLY | PW_RENDERFULLCONTENT;
HWND hwnd = mWidget->AsWindows()->GetHwnd();
mDCLayerTree->WaitForCommitCompletion();
BOOL result = ::PrintWindow(hwnd, dc, flags);
if (!result) {
::DeleteObject(bitmap);
::DeleteDC(dc);
gfxCriticalError() << "PrintWindow failed";
return false;
}
::GdiFlush();
memcpy(&aReadbackBuffer[0], readbackBits, aReadbackBuffer.length());
::DeleteObject(bitmap);
::DeleteDC(dc);
return true;
}
} // namespace wr
} // namespace mozilla

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

@ -83,6 +83,10 @@ class RenderCompositorANGLE : public RenderCompositor {
bool RequestFullRender() override;
uint32_t GetMaxPartialPresentRects() override;
bool MaybeReadback(const gfx::IntSize& aReadbackSize,
const wr::ImageFormat& aReadbackFormat,
const Range<uint8_t>& aReadbackBuffer) override;
protected:
bool UseCompositor();
void InitializeUsePartialPresent();

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

@ -159,10 +159,13 @@ RenderedFrameId RendererOGL::UpdateAndRender(
if (aReadbackBuffer.isSome()) {
MOZ_ASSERT(aReadbackSize.isSome());
MOZ_ASSERT(aReadbackFormat.isSome());
wr_renderer_readback(mRenderer, aReadbackSize.ref().width,
aReadbackSize.ref().height, aReadbackFormat.ref(),
&aReadbackBuffer.ref()[0],
aReadbackBuffer.ref().length());
if (!mCompositor->MaybeReadback(aReadbackSize.ref(), aReadbackFormat.ref(),
aReadbackBuffer.ref())) {
wr_renderer_readback(mRenderer, aReadbackSize.ref().width,
aReadbackSize.ref().height, aReadbackFormat.ref(),
&aReadbackBuffer.ref()[0],
aReadbackBuffer.ref().length());
}
}
mScreenshotGrabber.MaybeGrabScreenshot(mRenderer, size.ToUnknownSize());