зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
0c611d19d9
Коммит
00f9b4efee
|
@ -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());
|
||||
|
|
Загрузка…
Ссылка в новой задаче