diff --git a/Cargo.lock b/Cargo.lock index f2bc9402eb8d..5b3f1c79c3dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4660,6 +4660,7 @@ dependencies = [ "nsstring", "num_cpus", "rayon", + "thin-vec", "thread_profiler", "uuid 0.8.1", "webrender", diff --git a/gfx/layers/apz/src/APZUpdater.cpp b/gfx/layers/apz/src/APZUpdater.cpp index 4afbef8e3941..8c71f0b02567 100644 --- a/gfx/layers/apz/src/APZUpdater.cpp +++ b/gfx/layers/apz/src/APZUpdater.cpp @@ -89,9 +89,9 @@ void APZUpdater::CompleteSceneSwap(const wr::WrWindowId& aWindowId, return; } - for (uintptr_t i = 0; i < aInfo.removed_pipelines.length; i++) { - WRRootId layersId = WRRootId(aInfo.removed_pipelines.data[i].pipeline_id, - aInfo.removed_pipelines.data[i].document_id); + for (const auto& removedPipeline : aInfo.removed_pipelines) { + WRRootId layersId = + WRRootId(removedPipeline.pipeline_id, removedPipeline.document_id); updater->mEpochData.erase(layersId); } // Reset the built info for all pipelines, then put it back for the ones @@ -99,10 +99,9 @@ void APZUpdater::CompleteSceneSwap(const wr::WrWindowId& aWindowId, for (auto& i : updater->mEpochData) { i.second.mBuilt = Nothing(); } - for (uintptr_t i = 0; i < aInfo.epochs.length; i++) { - WRRootId layersId = WRRootId(aInfo.epochs.data[i].pipeline_id, - aInfo.epochs.data[i].document_id); - updater->mEpochData[layersId].mBuilt = Some(aInfo.epochs.data[i].epoch); + for (const auto& epoch : aInfo.epochs) { + WRRootId layersId = WRRootId(epoch.pipeline_id, epoch.document_id); + updater->mEpochData[layersId].mBuilt = Some(epoch.epoch); } // Run any tasks that got unblocked, then unlock the tree. The order is @@ -597,9 +596,8 @@ void apz_pre_scene_swap(mozilla::wr::WrWindowId aWindowId) { } void apz_post_scene_swap(mozilla::wr::WrWindowId aWindowId, - mozilla::wr::WrPipelineInfo aInfo) { - mozilla::layers::APZUpdater::CompleteSceneSwap(aWindowId, aInfo); - wr_pipeline_info_delete(aInfo); + const mozilla::wr::WrPipelineInfo* aInfo) { + mozilla::layers::APZUpdater::CompleteSceneSwap(aWindowId, *aInfo); } void apz_run_updater(mozilla::wr::WrWindowId aWindowId) { diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 63c7479775dc..d5bd9baa308a 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -2296,7 +2296,7 @@ void CompositorBridgeParent::DidComposite(const VsyncId& aId, void CompositorBridgeParent::NotifyDidSceneBuild( const nsTArray& aRenderRoots, - RefPtr aInfo) { + RefPtr aInfo) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); if (mPaused) { return; diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h index 8a454f329450..671e4173ce15 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -452,7 +452,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase, TimeStamp& aRenderStart, TimeStamp& aCompositeEnd, wr::RendererStats* aStats = nullptr); void NotifyDidSceneBuild(const nsTArray& aRenderRoots, - RefPtr aInfo); + RefPtr aInfo); RefPtr GetAsyncImagePipelineManager() const; PCompositorWidgetParent* AllocPCompositorWidgetParent( diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index 9e99c738e192..6bc6cfe69cfa 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -524,7 +524,8 @@ void AsyncImagePipelineManager::HoldExternalImage( } void AsyncImagePipelineManager::NotifyPipelinesUpdated( - RefPtr aInfo, wr::RenderedFrameId aLatestFrameId, + RefPtr aInfo, + wr::RenderedFrameId aLatestFrameId, wr::RenderedFrameId aLastCompletedFrameId) { MOZ_ASSERT(wr::RenderThread::IsInRenderThread()); MOZ_ASSERT(mLastCompletedFrameId <= aLastCompletedFrameId.mId); @@ -532,7 +533,7 @@ void AsyncImagePipelineManager::NotifyPipelinesUpdated( // This is called on the render thread, so we just stash the data into // mPendingUpdates and process it later on the compositor thread. - mPendingUpdates.push_back(aInfo); + mPendingUpdates.push_back(std::move(aInfo)); mLastCompletedFrameId = aLastCompletedFrameId.mId; { @@ -575,12 +576,11 @@ void AsyncImagePipelineManager::ProcessPipelineUpdates() { for (auto pipelineInfo : update.second) { auto& info = pipelineInfo->Raw(); - for (uintptr_t i = 0; i < info.epochs.length; i++) { - ProcessPipelineRendered(info.epochs.data[i].pipeline_id, - info.epochs.data[i].epoch, update.first); + for (auto& epoch : info.epochs) { + ProcessPipelineRendered(epoch.pipeline_id, epoch.epoch, update.first); } - for (uintptr_t i = 0; i < info.removed_pipelines.length; i++) { - ProcessPipelineRemoved(info.removed_pipelines.data[i], update.first); + for (auto& removedPipeline : info.removed_pipelines) { + ProcessPipelineRemoved(removedPipeline, update.first); } } } diff --git a/gfx/layers/wr/AsyncImagePipelineManager.h b/gfx/layers/wr/AsyncImagePipelineManager.h index 54dea7958bd1..9bd7ecb6a1ee 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.h +++ b/gfx/layers/wr/AsyncImagePipelineManager.h @@ -65,7 +65,7 @@ class AsyncImagePipelineManager final { // @param aLatestFrameId RenderedFrameId if a frame has been submitted for // rendering, invalid if not // @param aLastCompletedFrameId RenderedFrameId for the last completed frame - void NotifyPipelinesUpdated(RefPtr aInfo, + void NotifyPipelinesUpdated(RefPtr aInfo, wr::RenderedFrameId aLatestFrameId, wr::RenderedFrameId aLastCompletedFrameId); @@ -244,7 +244,8 @@ class AsyncImagePipelineManager final { nsTArray mImageCompositeNotifications; - typedef std::vector> PipelineInfoVector; + typedef std::vector> + PipelineInfoVector; // PipelineInfo updates to be processed once a render has been submitted. // This is only accessed on the render thread, so does not need a lock. diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index ecc726f4acc1..405ad1b68c04 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -2508,7 +2508,7 @@ void WebRenderBridgeParent::NotifySceneBuiltForEpoch( void WebRenderBridgeParent::NotifyDidSceneBuild( const nsTArray& aRenderRoots, - RefPtr aInfo) { + RefPtr aInfo) { MOZ_ASSERT(IsRootWebRenderBridgeParent()); if (!mCompositorScheduler) { return; @@ -2533,10 +2533,8 @@ void WebRenderBridgeParent::NotifyDidSceneBuild( // Look through all the pipelines contained within the built scene // and check which vsync they initiated from. - auto info = aInfo->Raw(); - for (uintptr_t i = 0; i < info.epochs.length; i++) { - auto epoch = info.epochs.data[i]; - + const auto& info = aInfo->Raw(); + for (const auto& epoch : info.epochs) { WebRenderBridgeParent* wrBridge = this; if (!(epoch.pipeline_id == PipelineId())) { wrBridge = mAsyncImageManager->GetWrBridge(epoch.pipeline_id); diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index b742af97841e..64e57cc6d754 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -254,7 +254,7 @@ class WebRenderBridgeParent final void ScheduleForcedGenerateFrame(); void NotifyDidSceneBuild(const nsTArray& aRenderRoots, - RefPtr aInfo); + RefPtr aInfo); wr::Epoch UpdateWebRender( CompositorVsyncScheduler* aScheduler, diff --git a/gfx/layers/wr/WebRenderCompositionRecorder.cpp b/gfx/layers/wr/WebRenderCompositionRecorder.cpp index de48163cb4b4..7150717889db 100644 --- a/gfx/layers/wr/WebRenderCompositionRecorder.cpp +++ b/gfx/layers/wr/WebRenderCompositionRecorder.cpp @@ -46,7 +46,7 @@ class RendererRecordedFrame final : public layers::RecordedFrame { }; void WebRenderCompositionRecorder::MaybeRecordFrame( - wr::Renderer* aRenderer, wr::WebRenderPipelineInfo* aFrameEpochs) { + wr::Renderer* aRenderer, const wr::WebRenderPipelineInfo* aFrameEpochs) { MOZ_ASSERT(wr::RenderThread::IsInRenderThread()); if (!aRenderer || !aFrameEpochs || !DidPaintContent(aFrameEpochs)) { @@ -66,30 +66,28 @@ void WebRenderCompositionRecorder::MaybeRecordFrame( } bool WebRenderCompositionRecorder::DidPaintContent( - wr::WebRenderPipelineInfo* aFrameEpochs) { + const wr::WebRenderPipelineInfo* aFrameEpochs) { const wr::WrPipelineInfo& info = aFrameEpochs->Raw(); bool didPaintContent = false; - for (wr::usize i = 0; i < info.epochs.length; i++) { - const wr::PipelineId pipelineId = info.epochs.data[i].pipeline_id; + for (const auto& epoch : info.epochs) { + const wr::PipelineId pipelineId = epoch.pipeline_id; if (pipelineId == mRootPipelineId) { continue; } const auto it = mContentPipelines.find(AsUint64(pipelineId)); - if (it == mContentPipelines.end() || - it->second != info.epochs.data[i].epoch) { + if (it == mContentPipelines.end() || it->second != epoch.epoch) { // This content pipeline has updated list last render or has newly // rendered. didPaintContent = true; - mContentPipelines[AsUint64(pipelineId)] = info.epochs.data[i].epoch; + mContentPipelines[AsUint64(pipelineId)] = epoch.epoch; } } - for (wr::usize i = 0; i < info.removed_pipelines.length; i++) { - const wr::PipelineId pipelineId = - info.removed_pipelines.data[i].pipeline_id; + for (const auto& removedPipeline : info.removed_pipelines) { + const wr::PipelineId pipelineId = removedPipeline.pipeline_id; if (pipelineId == mRootPipelineId) { continue; } diff --git a/gfx/layers/wr/WebRenderCompositionRecorder.h b/gfx/layers/wr/WebRenderCompositionRecorder.h index 82068769cf6d..65cea8cdeef9 100644 --- a/gfx/layers/wr/WebRenderCompositionRecorder.h +++ b/gfx/layers/wr/WebRenderCompositionRecorder.h @@ -60,13 +60,13 @@ class WebRenderCompositionRecorder final : public CompositionRecorder { * recorder structures. */ void MaybeRecordFrame(wr::Renderer* aRenderer, - wr::WebRenderPipelineInfo* aFrameEpochs); + const wr::WebRenderPipelineInfo* aFrameEpochs); private: /** * Determine if any content pipelines updated. */ - bool DidPaintContent(wr::WebRenderPipelineInfo* aFrameEpochs); + bool DidPaintContent(const wr::WebRenderPipelineInfo* aFrameEpochs); // The id of the root WebRender pipeline. // diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index 097334af1b5b..113e0c64fee0 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -19,6 +19,7 @@ nsstring = { path = "../../xpcom/rust/nsstring" } bincode = "1.0" uuid = { version = "0.8", features = ["v4"] } fxhash = "0.2.1" +thin-vec = { version = "0.1.0", features = ["gecko-ffi"] } [dependencies.webrender] path = "../wr/webrender" diff --git a/gfx/webrender_bindings/RenderCompositor.h b/gfx/webrender_bindings/RenderCompositor.h index d3bef5a839d8..7791056a8847 100644 --- a/gfx/webrender_bindings/RenderCompositor.h +++ b/gfx/webrender_bindings/RenderCompositor.h @@ -42,7 +42,7 @@ class RenderCompositor { // have been pushed to the queue. // @return a RenderedFrameId for the frame virtual RenderedFrameId EndFrame( - const FfiVec& aDirtyRects) = 0; + const nsTArray& aDirtyRects) = 0; // Returns false when waiting gpu tasks is failed. // It might happen when rendering context is lost. virtual bool WaitForGPU() { return true; } diff --git a/gfx/webrender_bindings/RenderCompositorANGLE.cpp b/gfx/webrender_bindings/RenderCompositorANGLE.cpp index 5187ca4ab48e..0b2512550f33 100644 --- a/gfx/webrender_bindings/RenderCompositorANGLE.cpp +++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp @@ -446,7 +446,7 @@ bool RenderCompositorANGLE::BeginFrame() { } RenderedFrameId RenderCompositorANGLE::EndFrame( - const FfiVec& aDirtyRects) { + const nsTArray& aDirtyRects) { RenderedFrameId frameId = GetNextRenderFrameId(); InsertGraphicsCommandsFinishedWaitQuery(frameId); @@ -474,10 +474,9 @@ RenderedFrameId RenderCompositorANGLE::EndFrame( // Clear full render flag. mFullRender = false; // If there is no diry rect, we skip SwapChain present. - if (aDirtyRects.length > 0) { - StackArray rects(aDirtyRects.length); - for (uintptr_t i = 0; i < aDirtyRects.length; i++) { - const DeviceIntRect& rect = aDirtyRects.data[i]; + if (!aDirtyRects.IsEmpty()) { + StackArray rects(aDirtyRects.Length()); + for (const auto& rect : aDirtyRects) { // Clip rect to bufferSize rects[i].left = std::max(0, std::min(rect.origin.x, bufferSize.width)); @@ -491,7 +490,7 @@ RenderedFrameId RenderCompositorANGLE::EndFrame( DXGI_PRESENT_PARAMETERS params; PodZero(¶ms); - params.DirtyRectsCount = aDirtyRects.length; + params.DirtyRectsCount = aDirtyRects.Length(); params.pDirtyRects = rects.data(); HRESULT hr; diff --git a/gfx/webrender_bindings/RenderCompositorANGLE.h b/gfx/webrender_bindings/RenderCompositorANGLE.h index 6dabed0e9f99..c18b27699c20 100644 --- a/gfx/webrender_bindings/RenderCompositorANGLE.h +++ b/gfx/webrender_bindings/RenderCompositorANGLE.h @@ -40,7 +40,7 @@ class RenderCompositorANGLE : public RenderCompositor { bool Initialize(); bool BeginFrame() override; - RenderedFrameId EndFrame(const FfiVec& aDirtyRects) final; + RenderedFrameId EndFrame(const nsTArray& aDirtyRects) final; bool WaitForGPU() override; RenderedFrameId GetLastCompletedFrameId() final; RenderedFrameId UpdateFrameId() final; diff --git a/gfx/webrender_bindings/RenderCompositorEGL.cpp b/gfx/webrender_bindings/RenderCompositorEGL.cpp index 8ee25cb67d14..351d7c60c57b 100644 --- a/gfx/webrender_bindings/RenderCompositorEGL.cpp +++ b/gfx/webrender_bindings/RenderCompositorEGL.cpp @@ -90,7 +90,7 @@ bool RenderCompositorEGL::BeginFrame() { } RenderedFrameId RenderCompositorEGL::EndFrame( - const FfiVec& aDirtyRects) { + const nsTArray& aDirtyRects) { RenderedFrameId frameId = GetNextRenderFrameId(); if (mEGLSurface != EGL_NO_SURFACE) { gl()->SwapBuffers(); diff --git a/gfx/webrender_bindings/RenderCompositorEGL.h b/gfx/webrender_bindings/RenderCompositorEGL.h index 5aade763f4f3..d18cc34c858b 100644 --- a/gfx/webrender_bindings/RenderCompositorEGL.h +++ b/gfx/webrender_bindings/RenderCompositorEGL.h @@ -23,7 +23,7 @@ class RenderCompositorEGL : public RenderCompositor { virtual ~RenderCompositorEGL(); bool BeginFrame() override; - RenderedFrameId EndFrame(const FfiVec& aDirtyRects) final; + RenderedFrameId EndFrame(const nsTArray& aDirtyRects) final; void Pause() override; bool Resume() override; diff --git a/gfx/webrender_bindings/RenderCompositorOGL.cpp b/gfx/webrender_bindings/RenderCompositorOGL.cpp index 5cb0b4cbdc63..d23d62f30d86 100644 --- a/gfx/webrender_bindings/RenderCompositorOGL.cpp +++ b/gfx/webrender_bindings/RenderCompositorOGL.cpp @@ -117,7 +117,7 @@ bool RenderCompositorOGL::BeginFrame() { } RenderedFrameId RenderCompositorOGL::EndFrame( - const FfiVec& aDirtyRects) { + const nsTArray& aDirtyRects) { RenderedFrameId frameId = GetNextRenderFrameId(); InsertFrameDoneSync(); diff --git a/gfx/webrender_bindings/RenderCompositorOGL.h b/gfx/webrender_bindings/RenderCompositorOGL.h index f4d90acdeb08..36c675291944 100644 --- a/gfx/webrender_bindings/RenderCompositorOGL.h +++ b/gfx/webrender_bindings/RenderCompositorOGL.h @@ -31,7 +31,7 @@ class RenderCompositorOGL : public RenderCompositor { virtual ~RenderCompositorOGL(); bool BeginFrame() override; - RenderedFrameId EndFrame(const FfiVec& aDirtyRects) final; + RenderedFrameId EndFrame(const nsTArray& aDirtyRects) final; bool WaitForGPU() override; void Pause() override; bool Resume() override; diff --git a/gfx/webrender_bindings/RenderThread.cpp b/gfx/webrender_bindings/RenderThread.cpp index 7b8fc646e4d9..b165bc92faa6 100644 --- a/gfx/webrender_bindings/RenderThread.cpp +++ b/gfx/webrender_bindings/RenderThread.cpp @@ -415,7 +415,7 @@ void RenderThread::RunEvent(wr::WindowId aWindowId, } static void NotifyDidRender(layers::CompositorBridgeParent* aBridge, - RefPtr aInfo, + RefPtr aInfo, VsyncId aCompositeStartId, TimeStamp aCompositeStart, TimeStamp aRenderStart, TimeStamp aEnd, bool aRender, @@ -429,10 +429,10 @@ static void NotifyDidRender(layers::CompositorBridgeParent* aBridge, auto info = aInfo->Raw(); - for (uintptr_t i = 0; i < info.epochs.length; i++) { - aBridge->NotifyPipelineRendered( - info.epochs.data[i].pipeline_id, info.epochs.data[i].epoch, - aCompositeStartId, aCompositeStart, aRenderStart, aEnd, &aStats); + for (const auto& epoch : info.epochs) { + aBridge->NotifyPipelineRendered(epoch.pipeline_id, epoch.epoch, + aCompositeStartId, aCompositeStart, + aRenderStart, aEnd, &aStats); } if (aBridge->GetWrBridge()) { @@ -484,7 +484,7 @@ void RenderThread::UpdateAndRender( renderer->CheckGraphicsResetStatus(); TimeStamp end = TimeStamp::Now(); - RefPtr info = renderer->FlushPipelineInfo(); + RefPtr info = renderer->FlushPipelineInfo(); layers::CompositorThreadHolder::Loop()->PostTask( NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender, @@ -881,13 +881,6 @@ WebRenderShaders::~WebRenderShaders() { wr_shaders_delete(mShaders, mGL.get()); } -WebRenderPipelineInfo::WebRenderPipelineInfo(wr::WrPipelineInfo aPipelineInfo) - : mPipelineInfo(aPipelineInfo) {} - -WebRenderPipelineInfo::~WebRenderPipelineInfo() { - wr_pipeline_info_delete(mPipelineInfo); -} - WebRenderThreadPool::WebRenderThreadPool(bool low_priority) { mThreadPool = wr_thread_pool_new(low_priority); } @@ -1054,17 +1047,18 @@ void wr_schedule_render(mozilla::wr::WrWindowId aWindowId, static void NotifyDidSceneBuild(RefPtr aBridge, const nsTArray& aRenderRoots, - RefPtr aInfo) { + RefPtr aInfo) { aBridge->NotifyDidSceneBuild(aRenderRoots, aInfo); } void wr_finished_scene_build(mozilla::wr::WrWindowId aWindowId, const mozilla::wr::WrDocumentId* aDocumentIds, size_t aDocumentIdsCount, - mozilla::wr::WrPipelineInfo aInfo) { + mozilla::wr::WrPipelineInfo* aInfo) { RefPtr cbp = mozilla::layers:: CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId); - RefPtr info = new wr::WebRenderPipelineInfo(aInfo); + RefPtr info = new wr::WebRenderPipelineInfo(); + info->Raw() = std::move(*aInfo); if (cbp) { nsTArray renderRoots; renderRoots.SetLength(aDocumentIdsCount); diff --git a/gfx/webrender_bindings/RenderThread.h b/gfx/webrender_bindings/RenderThread.h index 539782532c76..2c9a9bfdc902 100644 --- a/gfx/webrender_bindings/RenderThread.h +++ b/gfx/webrender_bindings/RenderThread.h @@ -93,15 +93,12 @@ class WebRenderShaders final { class WebRenderPipelineInfo final { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderPipelineInfo); - public: - explicit WebRenderPipelineInfo(wr::WrPipelineInfo aPipelineInfo); - - const wr::WrPipelineInfo& Raw() { return mPipelineInfo; } + const wr::WrPipelineInfo& Raw() const { return mPipelineInfo; } + wr::WrPipelineInfo& Raw() { return mPipelineInfo; } protected: - ~WebRenderPipelineInfo(); - - const wr::WrPipelineInfo mPipelineInfo; + ~WebRenderPipelineInfo() = default; + wr::WrPipelineInfo mPipelineInfo; }; /// Base class for an event that can be scheduled to run on the render thread. diff --git a/gfx/webrender_bindings/RendererOGL.cpp b/gfx/webrender_bindings/RendererOGL.cpp index 040a74c3ecea..1bb4df685b56 100644 --- a/gfx/webrender_bindings/RendererOGL.cpp +++ b/gfx/webrender_bindings/RendererOGL.cpp @@ -20,23 +20,6 @@ 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 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) { @@ -154,9 +137,9 @@ RenderedFrameId RendererOGL::UpdateAndRender( auto size = mCompositor->GetBufferSize(); - AutoWrRenderResult result(wr_renderer_render( - mRenderer, size.width, size.height, aHadSlowFrame, aOutStats)); - if (!result.Result()) { + nsTArray dirtyRects; + if (!wr_renderer_render(mRenderer, size.width, size.height, aHadSlowFrame, + aOutStats, &dirtyRects)) { RenderThread::Get()->HandleWebRenderError(WebRenderError::RENDER); mCompositor->GetWidget()->PostRender(&widgetContext); return RenderedFrameId(); @@ -176,7 +159,7 @@ RenderedFrameId RendererOGL::UpdateAndRender( mScreenshotGrabber.MaybeGrabScreenshot(this, size.ToUnknownSize()); - RenderedFrameId frameId = mCompositor->EndFrame(result.DirtyRects()); + RenderedFrameId frameId = mCompositor->EndFrame(dirtyRects); mCompositor->GetWidget()->PostRender(&widgetContext); @@ -265,8 +248,9 @@ void RendererOGL::SetFrameStartTime(const TimeStamp& aTime) { } RefPtr RendererOGL::FlushPipelineInfo() { - auto info = wr_renderer_flush_pipeline_info(mRenderer); - return new WebRenderPipelineInfo(info); + RefPtr info = new WebRenderPipelineInfo(); + wr_renderer_flush_pipeline_info(mRenderer, &info->Raw()); + return info; } RenderTextureHost* RendererOGL::GetRenderTexture( diff --git a/gfx/webrender_bindings/cbindgen.toml b/gfx/webrender_bindings/cbindgen.toml index 826c4448466d..2bba87f62e40 100644 --- a/gfx/webrender_bindings/cbindgen.toml +++ b/gfx/webrender_bindings/cbindgen.toml @@ -40,3 +40,6 @@ bitflags = true "target_os = windows" = "XP_WIN" "target_os = macos" = "XP_MACOSX" "target_os = android" = "ANDROID" + +[export.rename] +"ThinVec" = "nsTArray" diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index bf164252059a..6b63c0656d37 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -23,6 +23,7 @@ use std::os::raw::{c_void, c_char, c_float}; use std::os::raw::{c_int}; use std::time::Duration; use gleam::gl; +use thin_vec::ThinVec; use webrender::{ api::*, api::units::*, ApiRecordingReceiver, AsyncPropertySampler, AsyncScreenshotHandle, @@ -256,40 +257,6 @@ impl WrVecU8 { } } -#[repr(C)] -pub struct FfiVec { - // We use a *const instead of a *mut because we don't want the C++ side - // to be mutating this. It is strictly read-only from C++ - data: *const T, - length: usize, - capacity: usize, -} - -impl FfiVec { - fn from_vec(v: Vec) -> FfiVec { - let ret = FfiVec { - data: v.as_ptr(), - length: v.len(), - capacity: v.capacity(), - }; - mem::forget(v); - ret - } -} - -impl Drop for FfiVec { - fn drop(&mut self) { - // turn the stuff back into a Vec and let it be freed normally - let _ = unsafe { - Vec::from_raw_parts( - self.data as *mut T, - self.length, - self.capacity - ) - }; - } -} - #[no_mangle] pub extern "C" fn wr_vec_u8_push_bytes(v: &mut WrVecU8, bytes: ByteSlice) { v.push_bytes(bytes.as_slice()); @@ -564,10 +531,11 @@ extern "C" { fn wr_schedule_render(window_id: WrWindowId, document_id_array: *const WrDocumentId, document_id_count: usize); + // NOTE: This moves away from pipeline_info. fn wr_finished_scene_build(window_id: WrWindowId, document_id_array: *const WrDocumentId, document_id_count: usize, - pipeline_info: WrPipelineInfo); + pipeline_info: &mut WrPipelineInfo); fn wr_transaction_notification_notified(handler: usize, when: Checkpoint); } @@ -621,34 +589,23 @@ pub extern "C" fn wr_renderer_update(renderer: &mut Renderer) { renderer.update(); } -#[repr(C)] -pub struct WrRenderResult { - result: bool, - dirty_rects: FfiVec, -} - #[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) -> WrRenderResult { +pub extern "C" fn wr_renderer_render( + renderer: &mut Renderer, + width: i32, + height: i32, + had_slow_frame: bool, + out_stats: &mut RendererStats, + out_dirty_rects: &mut ThinVec, +) -> bool { if had_slow_frame { renderer.notify_slow_frame(); } match renderer.render(DeviceIntSize::new(width, height)) { Ok(results) => { *out_stats = results.stats; - WrRenderResult { - result: true, - dirty_rects: FfiVec::from_vec(results.dirty_rects), - } + out_dirty_rects.extend(results.dirty_rects); + true } Err(errors) => { for e in errors { @@ -658,10 +615,7 @@ pub extern "C" fn wr_renderer_render(renderer: &mut Renderer, gfx_critical_note(msg.as_ptr()); } } - WrRenderResult { - result: false, - dirty_rects: FfiVec::from_vec(vec![]), - } + false }, } } @@ -829,40 +783,36 @@ impl<'a> From<&'a (WrPipelineId, WrDocumentId)> for WrRemovedPipeline { #[repr(C)] pub struct WrPipelineInfo { - // This contains an entry for each pipeline that was rendered, along with - // the epoch at which it was rendered. Rendered pipelines include the root - // pipeline and any other pipelines that were reachable via IFrame display - // items from the root pipeline. - epochs: FfiVec, - // This contains an entry for each pipeline that was removed during the - // last transaction. These pipelines would have been explicitly removed by - // calling remove_pipeline on the transaction object; the pipeline showing - // up in this array means that the data structures have been torn down on - // the webrender side, and so any remaining data structures on the caller - // side can now be torn down also. - removed_pipelines: FfiVec, + /// This contains an entry for each pipeline that was rendered, along with + /// the epoch at which it was rendered. Rendered pipelines include the root + /// pipeline and any other pipelines that were reachable via IFrame display + /// items from the root pipeline. + epochs: ThinVec, + /// This contains an entry for each pipeline that was removed during the + /// last transaction. These pipelines would have been explicitly removed by + /// calling remove_pipeline on the transaction object; the pipeline showing + /// up in this array means that the data structures have been torn down on + /// the webrender side, and so any remaining data structures on the caller + /// side can now be torn down also. + removed_pipelines: ThinVec, } impl WrPipelineInfo { fn new(info: &PipelineInfo) -> Self { WrPipelineInfo { - epochs: FfiVec::from_vec(info.epochs.iter().map(WrPipelineEpoch::from).collect()), - removed_pipelines: FfiVec::from_vec(info.removed_pipelines.iter() - .map(WrRemovedPipeline::from).collect()), + epochs: info.epochs.iter().map(WrPipelineEpoch::from).collect(), + removed_pipelines: info.removed_pipelines.iter().map(WrRemovedPipeline::from).collect(), } } } #[no_mangle] -pub unsafe extern "C" fn wr_renderer_flush_pipeline_info(renderer: &mut Renderer) -> WrPipelineInfo { +pub unsafe extern "C" fn wr_renderer_flush_pipeline_info( + renderer: &mut Renderer, + out: &mut WrPipelineInfo, +) { let info = renderer.flush_pipeline_info(); - WrPipelineInfo::new(&info) -} - -#[no_mangle] -pub unsafe extern "C" fn wr_pipeline_info_delete(_info: WrPipelineInfo) { - // _info will be dropped here, and the drop impl on FfiVec will free - // the underlying vec memory + *out = WrPipelineInfo::new(&info); } extern "C" { @@ -912,9 +862,7 @@ extern "C" { // updater thread) fn apz_register_updater(window_id: WrWindowId); fn apz_pre_scene_swap(window_id: WrWindowId); - // This function takes ownership of the pipeline_info and is responsible for - // freeing it via wr_pipeline_info_delete. - fn apz_post_scene_swap(window_id: WrWindowId, pipeline_info: WrPipelineInfo); + fn apz_post_scene_swap(window_id: WrWindowId, pipeline_info: &WrPipelineInfo); fn apz_run_updater(window_id: WrWindowId); fn apz_deregister_updater(window_id: WrWindowId); @@ -955,17 +903,16 @@ impl SceneBuilderHooks for APZCallbacks { } fn post_scene_swap(&self, document_ids: &Vec, info: PipelineInfo, sceneswap_time: u64) { + let mut info = WrPipelineInfo::new(&info); unsafe { - let info = WrPipelineInfo::new(&info); record_telemetry_time(TelemetryProbe::SceneSwapTime, sceneswap_time); - apz_post_scene_swap(self.window_id, info); + apz_post_scene_swap(self.window_id, &info); } - let info = WrPipelineInfo::new(&info); // After a scene swap we should schedule a render for the next vsync, // otherwise there's no guarantee that the new scene will get rendered // anytime soon - unsafe { wr_finished_scene_build(self.window_id, document_ids.as_ptr(), document_ids.len(), info) } + unsafe { wr_finished_scene_build(self.window_id, document_ids.as_ptr(), document_ids.len(), &mut info) } unsafe { gecko_profiler_end_marker(b"SceneBuilding\0".as_ptr() as *const c_char); } } diff --git a/gfx/webrender_bindings/src/lib.rs b/gfx/webrender_bindings/src/lib.rs index 933c00076d85..2630e516b406 100644 --- a/gfx/webrender_bindings/src/lib.rs +++ b/gfx/webrender_bindings/src/lib.rs @@ -12,6 +12,7 @@ extern crate nsstring; extern crate rayon; extern crate num_cpus; extern crate thread_profiler; +extern crate thin_vec; extern crate bincode; extern crate uuid; extern crate fxhash; diff --git a/gfx/webrender_bindings/webrender_ffi.h b/gfx/webrender_bindings/webrender_ffi.h index cae04eda4be4..7dd9020bcacc 100644 --- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -81,7 +81,7 @@ const uint64_t ROOT_CLIP_CHAIN = ~0; void apz_register_updater(mozilla::wr::WrWindowId aWindowId); void apz_pre_scene_swap(mozilla::wr::WrWindowId aWindowId); void apz_post_scene_swap(mozilla::wr::WrWindowId aWindowId, - mozilla::wr::WrPipelineInfo aInfo); + const mozilla::wr::WrPipelineInfo* aInfo); void apz_run_updater(mozilla::wr::WrWindowId aWindowId); void apz_deregister_updater(mozilla::wr::WrWindowId aWindowId);