зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1575159 - Implement partial invalidation on Windows r=gw
Partial present for WR is off by default. Differential Revision: https://phabricator.services.mozilla.com/D51358 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
8ad1e883c8
Коммит
34a65d16bb
|
@ -37,7 +37,7 @@ class RenderCompositor {
|
|||
virtual ~RenderCompositor();
|
||||
|
||||
virtual bool BeginFrame() = 0;
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) = 0;
|
||||
// Returns false when waiting gpu tasks is failed.
|
||||
// It might happen when rendering context is lost.
|
||||
virtual bool WaitForGPU() { return true; }
|
||||
|
@ -78,6 +78,10 @@ class RenderCompositor {
|
|||
virtual void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
wr::DeviceIntRect aClipRect) {}
|
||||
|
||||
// Interface for partial present
|
||||
virtual bool RequestFullRender() { return false; }
|
||||
virtual uint32_t GetMaxPartialPresentRects() { return 0; }
|
||||
|
||||
// Whether the surface contents are flipped vertically
|
||||
virtual bool SurfaceIsYFlipped() { return false; }
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/StackArray.h"
|
||||
#include "mozilla/layers/HelpersD3D11.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
#include "mozilla/StaticPrefs_gfx.h"
|
||||
|
@ -55,7 +56,9 @@ RenderCompositorANGLE::RenderCompositorANGLE(
|
|||
mEGLConfig(nullptr),
|
||||
mEGLSurface(nullptr),
|
||||
mUseTripleBuffering(false),
|
||||
mUseAlpha(false) {}
|
||||
mUseAlpha(false),
|
||||
mUsePartialPresent(false),
|
||||
mFullRender(false) {}
|
||||
|
||||
RenderCompositorANGLE::~RenderCompositorANGLE() {
|
||||
DestroyEGLSurface();
|
||||
|
@ -207,6 +210,7 @@ bool RenderCompositorANGLE::Initialize() {
|
|||
DXGI_RGBA color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
swapChain1->SetBackgroundColor(&color);
|
||||
mSwapChain = swapChain1;
|
||||
mSwapChain1 = swapChain1;
|
||||
mUseTripleBuffering = useTripleBuffering;
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +240,13 @@ bool RenderCompositorANGLE::Initialize() {
|
|||
gfxCriticalNote << "Could not create swap chain: " << gfx::hexa(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGISwapChain1> swapChain1;
|
||||
hr = mSwapChain->QueryInterface(
|
||||
(IDXGISwapChain1**)getter_AddRefs(swapChain1));
|
||||
if (SUCCEEDED(hr)) {
|
||||
mSwapChain1 = swapChain1;
|
||||
}
|
||||
}
|
||||
|
||||
// We need this because we don't want DXGI to respond to Alt+Enter.
|
||||
|
@ -254,6 +265,8 @@ bool RenderCompositorANGLE::Initialize() {
|
|||
}
|
||||
}
|
||||
|
||||
InitializeUsePartialPresent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -285,6 +298,7 @@ void RenderCompositorANGLE::CreateSwapChainForDCompIfPossible(
|
|||
CreateSwapChainForDComp(useTripleBuffering, useAlpha);
|
||||
if (swapChain1) {
|
||||
mSwapChain = swapChain1;
|
||||
mSwapChain1 = swapChain1;
|
||||
mUseTripleBuffering = useTripleBuffering;
|
||||
mUseAlpha = useAlpha;
|
||||
mDCLayerTree->SetDefaultSwapChain(swapChain1);
|
||||
|
@ -401,7 +415,7 @@ bool RenderCompositorANGLE::BeginFrame() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void RenderCompositorANGLE::EndFrame() {
|
||||
void RenderCompositorANGLE::EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) {
|
||||
InsertPresentWaitQuery();
|
||||
|
||||
if (!UseCompositor()) {
|
||||
|
@ -414,7 +428,43 @@ void RenderCompositorANGLE::EndFrame() {
|
|||
fxrHandler->UpdateOutput(mCtx);
|
||||
}
|
||||
}
|
||||
mSwapChain->Present(0, 0);
|
||||
|
||||
const LayoutDeviceIntSize& bufferSize = mBufferSize.ref();
|
||||
|
||||
if (mUsePartialPresent) {
|
||||
// Clear full render flag.
|
||||
mFullRender = false;
|
||||
// If there is no diry rect, we skip SwapChain present.
|
||||
if (aDirtyRects.length > 0) {
|
||||
StackArray<RECT, 1> rects(aDirtyRects.length);
|
||||
for (uintptr_t i = 0; i < aDirtyRects.length; i++) {
|
||||
const DeviceIntRect& rect = aDirtyRects.data[i];
|
||||
// Clip rect to bufferSize
|
||||
rects[i].left =
|
||||
std::max(0, std::min(rect.origin.x, bufferSize.width));
|
||||
rects[i].top =
|
||||
std::max(0, std::min(rect.origin.y, bufferSize.height));
|
||||
rects[i].right = std::max(
|
||||
0, std::min(rect.origin.x + rect.size.width, bufferSize.width));
|
||||
rects[i].bottom = std::max(
|
||||
0, std::min(rect.origin.y + rect.size.height, bufferSize.height));
|
||||
}
|
||||
|
||||
DXGI_PRESENT_PARAMETERS params;
|
||||
PodZero(¶ms);
|
||||
params.DirtyRectsCount = aDirtyRects.length;
|
||||
params.pDirtyRects = rects.data();
|
||||
|
||||
HRESULT hr;
|
||||
hr = mSwapChain1->Present1(0, 0, ¶ms);
|
||||
if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) {
|
||||
gfxCriticalNote << "Present1 failed: " << gfx::hexa(hr);
|
||||
mFullRender = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mSwapChain->Present(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDCLayerTree) {
|
||||
|
@ -464,6 +514,9 @@ bool RenderCompositorANGLE::ResizeBufferIfNeeded() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mUsePartialPresent) {
|
||||
mFullRender = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -675,5 +728,24 @@ void RenderCompositorANGLE::AddSurface(wr::NativeSurfaceId aId,
|
|||
mDCLayerTree->AddSurface(aId, aPosition, aClipRect);
|
||||
}
|
||||
|
||||
void RenderCompositorANGLE::InitializeUsePartialPresent() {
|
||||
if (UseCompositor() || !mSwapChain1 ||
|
||||
mWidget->AsWindows()->HasFxrOutputHandler() ||
|
||||
StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup() <= 0) {
|
||||
mUsePartialPresent = false;
|
||||
} else {
|
||||
mUsePartialPresent = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderCompositorANGLE::RequestFullRender() { return mFullRender; }
|
||||
|
||||
uint32_t RenderCompositorANGLE::GetMaxPartialPresentRects() {
|
||||
if (!mUsePartialPresent) {
|
||||
return 0;
|
||||
}
|
||||
return StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup();
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -40,7 +40,7 @@ class RenderCompositorANGLE : public RenderCompositor {
|
|||
bool Initialize();
|
||||
|
||||
bool BeginFrame() override;
|
||||
void EndFrame() override;
|
||||
void EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) override;
|
||||
bool WaitForGPU() override;
|
||||
void Pause() override;
|
||||
bool Resume() override;
|
||||
|
@ -76,8 +76,13 @@ class RenderCompositorANGLE : public RenderCompositor {
|
|||
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
wr::DeviceIntRect aClipRect) override;
|
||||
|
||||
// Interface for partial present
|
||||
bool RequestFullRender() override;
|
||||
uint32_t GetMaxPartialPresentRects() override;
|
||||
|
||||
protected:
|
||||
bool UseCompositor();
|
||||
void InitializeUsePartialPresent();
|
||||
void InsertPresentWaitQuery();
|
||||
bool WaitForPreviousPresentQuery();
|
||||
bool ResizeBufferIfNeeded();
|
||||
|
@ -99,6 +104,7 @@ class RenderCompositorANGLE : public RenderCompositor {
|
|||
RefPtr<ID3D11Device> mDevice;
|
||||
RefPtr<ID3D11DeviceContext> mCtx;
|
||||
RefPtr<IDXGISwapChain> mSwapChain;
|
||||
RefPtr<IDXGISwapChain1> mSwapChain1;
|
||||
|
||||
UniquePtr<DCLayerTree> mDCLayerTree;
|
||||
|
||||
|
@ -106,6 +112,8 @@ class RenderCompositorANGLE : public RenderCompositor {
|
|||
RefPtr<ID3D11Query> mRecycledQuery;
|
||||
|
||||
Maybe<LayoutDeviceIntSize> mBufferSize;
|
||||
bool mUsePartialPresent;
|
||||
bool mFullRender;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
|
|
@ -111,7 +111,7 @@ bool RenderCompositorEGL::BeginFrame() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void RenderCompositorEGL::EndFrame() {
|
||||
void RenderCompositorEGL::EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) {
|
||||
if (mEGLSurface != EGL_NO_SURFACE) {
|
||||
gl()->SwapBuffers();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class RenderCompositorEGL : public RenderCompositor {
|
|||
virtual ~RenderCompositorEGL();
|
||||
|
||||
bool BeginFrame() override;
|
||||
void EndFrame() override;
|
||||
void EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) override;
|
||||
void Pause() override;
|
||||
bool Resume() override;
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ bool RenderCompositorOGL::BeginFrame() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void RenderCompositorOGL::EndFrame() {
|
||||
void RenderCompositorOGL::EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) {
|
||||
InsertFrameDoneSync();
|
||||
mGL->SwapBuffers();
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class RenderCompositorOGL : public RenderCompositor {
|
|||
virtual ~RenderCompositorOGL();
|
||||
|
||||
bool BeginFrame() override;
|
||||
void EndFrame() override;
|
||||
void EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) override;
|
||||
bool WaitForGPU() override;
|
||||
void Pause() override;
|
||||
bool Resume() override;
|
||||
|
|
|
@ -19,6 +19,23 @@
|
|||
namespace mozilla {
|
||||
namespace wr {
|
||||
|
||||
class MOZ_STACK_CLASS AutoWrRenderResult {
|
||||
public:
|
||||
explicit AutoWrRenderResult(WrRenderResult&& aResult) : mResult(aResult) {}
|
||||
|
||||
~AutoWrRenderResult() { wr_render_result_delete(mResult); }
|
||||
|
||||
bool Result() const { return mResult.result; }
|
||||
|
||||
FfiVec<DeviceIntRect> DirtyRects() const { return mResult.dirty_rects; }
|
||||
|
||||
private:
|
||||
const WrRenderResult mResult;
|
||||
|
||||
AutoWrRenderResult(const AutoWrRenderResult&) = delete;
|
||||
AutoWrRenderResult& operator=(const AutoWrRenderResult&) = delete;
|
||||
};
|
||||
|
||||
wr::WrExternalImage wr_renderer_lock_external_image(
|
||||
void* aObj, wr::ExternalImageId aId, uint8_t aChannelIndex,
|
||||
wr::ImageRendering aRendering) {
|
||||
|
@ -120,10 +137,15 @@ bool RendererOGL::UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize,
|
|||
|
||||
wr_renderer_update(mRenderer);
|
||||
|
||||
if (mCompositor->RequestFullRender()) {
|
||||
wr_renderer_force_redraw(mRenderer);
|
||||
}
|
||||
|
||||
auto size = mCompositor->GetBufferSize();
|
||||
|
||||
if (!wr_renderer_render(mRenderer, size.width, size.height, aHadSlowFrame,
|
||||
aOutStats)) {
|
||||
AutoWrRenderResult result(wr_renderer_render(
|
||||
mRenderer, size.width, size.height, aHadSlowFrame, aOutStats));
|
||||
if (!result.Result()) {
|
||||
RenderThread::Get()->HandleWebRenderError(WebRenderError::RENDER);
|
||||
mCompositor->GetWidget()->PostRender(&widgetContext);
|
||||
return false;
|
||||
|
@ -140,7 +162,7 @@ bool RendererOGL::UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize,
|
|||
|
||||
mScreenshotGrabber.MaybeGrabScreenshot(mRenderer, size.ToUnknownSize());
|
||||
|
||||
mCompositor->EndFrame();
|
||||
mCompositor->EndFrame(result.DirtyRects());
|
||||
|
||||
mCompositor->GetWidget()->PostRender(&widgetContext);
|
||||
|
||||
|
|
|
@ -96,7 +96,8 @@ class NewRenderer : public RendererEvent {
|
|||
&WebRenderMallocEnclosingSizeOf, (uint32_t)wr::RenderRoot::Default,
|
||||
compositor->ShouldUseNativeCompositor() ? compositor.get()
|
||||
: nullptr,
|
||||
mDocHandle, &wrRenderer, mMaxTextureSize)) {
|
||||
compositor->GetMaxPartialPresentRects(), mDocHandle, &wrRenderer,
|
||||
mMaxTextureSize)) {
|
||||
// wr_window_new puts a message into gfxCriticalNote if it returns false
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -611,19 +611,34 @@ pub extern "C" fn wr_renderer_update(renderer: &mut Renderer) {
|
|||
renderer.update();
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct WrRenderResult {
|
||||
result: bool,
|
||||
dirty_rects: FfiVec<DeviceIntRect>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wr_render_result_delete(_result: WrRenderResult) {
|
||||
// _result will be dropped here, and the drop impl on FfiVec will free
|
||||
// the underlying vec memory
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_renderer_render(renderer: &mut Renderer,
|
||||
width: i32,
|
||||
height: i32,
|
||||
had_slow_frame: bool,
|
||||
out_stats: &mut RendererStats) -> bool {
|
||||
out_stats: &mut RendererStats) -> WrRenderResult {
|
||||
if had_slow_frame {
|
||||
renderer.notify_slow_frame();
|
||||
}
|
||||
match renderer.render(DeviceIntSize::new(width, height)) {
|
||||
Ok(results) => {
|
||||
*out_stats = results.stats;
|
||||
true
|
||||
WrRenderResult {
|
||||
result: true,
|
||||
dirty_rects: FfiVec::from_vec(results.dirty_rects),
|
||||
}
|
||||
}
|
||||
Err(errors) => {
|
||||
for e in errors {
|
||||
|
@ -633,11 +648,19 @@ pub extern "C" fn wr_renderer_render(renderer: &mut Renderer,
|
|||
gfx_critical_note(msg.as_ptr());
|
||||
}
|
||||
}
|
||||
false
|
||||
WrRenderResult {
|
||||
result: false,
|
||||
dirty_rects: FfiVec::from_vec(vec![]),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_renderer_force_redraw(renderer: &mut Renderer) {
|
||||
renderer.force_redraw();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_renderer_record_frame(
|
||||
renderer: &mut Renderer,
|
||||
|
@ -1280,6 +1303,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
|||
enclosing_size_of_op: VoidPtrToSizeFn,
|
||||
document_id: u32,
|
||||
compositor: *mut c_void,
|
||||
max_partial_present_rects: usize,
|
||||
out_handle: &mut *mut DocumentHandle,
|
||||
out_renderer: &mut *mut Renderer,
|
||||
out_max_texture_size: *mut i32)
|
||||
|
@ -1339,7 +1363,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
|||
}
|
||||
} else {
|
||||
CompositorConfig::Draw {
|
||||
max_partial_present_rects: 0,
|
||||
max_partial_present_rects,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3607,6 +3607,11 @@
|
|||
value: false
|
||||
mirror: once
|
||||
|
||||
- name: gfx.webrender.max-partial-present-rects
|
||||
type: uint32_t
|
||||
value: 0
|
||||
mirror: once
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
# Keep this pref hidden on non-nightly builds to avoid people accidentally
|
||||
# turning it on.
|
||||
|
|
Загрузка…
Ссылка в новой задаче