Bug 1616395 - Remove FfiVec. r=jrmuizel

Use ThinVec instead, which is compatible with nsTArray, and makes stuff much
harder to misuse.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2020-02-19 18:34:51 +00:00
parent a9e9474027
commit d18caaa054
25 changed files with 110 additions and 188 deletions

1
Cargo.lock generated
View File

@ -4660,6 +4660,7 @@ dependencies = [
"nsstring",
"num_cpus",
"rayon",
"thin-vec",
"thread_profiler",
"uuid 0.8.1",
"webrender",

View File

@ -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) {

View File

@ -2296,7 +2296,7 @@ void CompositorBridgeParent::DidComposite(const VsyncId& aId,
void CompositorBridgeParent::NotifyDidSceneBuild(
const nsTArray<wr::RenderRoot>& aRenderRoots,
RefPtr<wr::WebRenderPipelineInfo> aInfo) {
RefPtr<const wr::WebRenderPipelineInfo> aInfo) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mPaused) {
return;

View File

@ -452,7 +452,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
wr::RendererStats* aStats = nullptr);
void NotifyDidSceneBuild(const nsTArray<wr::RenderRoot>& aRenderRoots,
RefPtr<wr::WebRenderPipelineInfo> aInfo);
RefPtr<const wr::WebRenderPipelineInfo> aInfo);
RefPtr<AsyncImagePipelineManager> GetAsyncImagePipelineManager() const;
PCompositorWidgetParent* AllocPCompositorWidgetParent(

View File

@ -524,7 +524,8 @@ void AsyncImagePipelineManager::HoldExternalImage(
}
void AsyncImagePipelineManager::NotifyPipelinesUpdated(
RefPtr<wr::WebRenderPipelineInfo> aInfo, wr::RenderedFrameId aLatestFrameId,
RefPtr<const wr::WebRenderPipelineInfo> 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);
}
}
}

View File

@ -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<wr::WebRenderPipelineInfo> aInfo,
void NotifyPipelinesUpdated(RefPtr<const wr::WebRenderPipelineInfo> aInfo,
wr::RenderedFrameId aLatestFrameId,
wr::RenderedFrameId aLastCompletedFrameId);
@ -244,7 +244,8 @@ class AsyncImagePipelineManager final {
nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications;
typedef std::vector<RefPtr<wr::WebRenderPipelineInfo>> PipelineInfoVector;
typedef std::vector<RefPtr<const wr::WebRenderPipelineInfo>>
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.

View File

@ -2508,7 +2508,7 @@ void WebRenderBridgeParent::NotifySceneBuiltForEpoch(
void WebRenderBridgeParent::NotifyDidSceneBuild(
const nsTArray<wr::RenderRoot>& aRenderRoots,
RefPtr<wr::WebRenderPipelineInfo> aInfo) {
RefPtr<const wr::WebRenderPipelineInfo> 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);

View File

@ -254,7 +254,7 @@ class WebRenderBridgeParent final
void ScheduleForcedGenerateFrame();
void NotifyDidSceneBuild(const nsTArray<wr::RenderRoot>& aRenderRoots,
RefPtr<wr::WebRenderPipelineInfo> aInfo);
RefPtr<const wr::WebRenderPipelineInfo> aInfo);
wr::Epoch UpdateWebRender(
CompositorVsyncScheduler* aScheduler,

View File

@ -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;
}

View File

@ -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.
//

View File

@ -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"

View File

@ -42,7 +42,7 @@ class RenderCompositor {
// have been pushed to the queue.
// @return a RenderedFrameId for the frame
virtual RenderedFrameId EndFrame(
const FfiVec<DeviceIntRect>& aDirtyRects) = 0;
const nsTArray<DeviceIntRect>& aDirtyRects) = 0;
// Returns false when waiting gpu tasks is failed.
// It might happen when rendering context is lost.
virtual bool WaitForGPU() { return true; }

View File

@ -446,7 +446,7 @@ bool RenderCompositorANGLE::BeginFrame() {
}
RenderedFrameId RenderCompositorANGLE::EndFrame(
const FfiVec<DeviceIntRect>& aDirtyRects) {
const nsTArray<DeviceIntRect>& 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<RECT, 1> rects(aDirtyRects.length);
for (uintptr_t i = 0; i < aDirtyRects.length; i++) {
const DeviceIntRect& rect = aDirtyRects.data[i];
if (!aDirtyRects.IsEmpty()) {
StackArray<RECT, 1> 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(&params);
params.DirtyRectsCount = aDirtyRects.length;
params.DirtyRectsCount = aDirtyRects.Length();
params.pDirtyRects = rects.data();
HRESULT hr;

View File

@ -40,7 +40,7 @@ class RenderCompositorANGLE : public RenderCompositor {
bool Initialize();
bool BeginFrame() override;
RenderedFrameId EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) final;
RenderedFrameId EndFrame(const nsTArray<DeviceIntRect>& aDirtyRects) final;
bool WaitForGPU() override;
RenderedFrameId GetLastCompletedFrameId() final;
RenderedFrameId UpdateFrameId() final;

View File

@ -90,7 +90,7 @@ bool RenderCompositorEGL::BeginFrame() {
}
RenderedFrameId RenderCompositorEGL::EndFrame(
const FfiVec<DeviceIntRect>& aDirtyRects) {
const nsTArray<DeviceIntRect>& aDirtyRects) {
RenderedFrameId frameId = GetNextRenderFrameId();
if (mEGLSurface != EGL_NO_SURFACE) {
gl()->SwapBuffers();

View File

@ -23,7 +23,7 @@ class RenderCompositorEGL : public RenderCompositor {
virtual ~RenderCompositorEGL();
bool BeginFrame() override;
RenderedFrameId EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) final;
RenderedFrameId EndFrame(const nsTArray<DeviceIntRect>& aDirtyRects) final;
void Pause() override;
bool Resume() override;

View File

@ -117,7 +117,7 @@ bool RenderCompositorOGL::BeginFrame() {
}
RenderedFrameId RenderCompositorOGL::EndFrame(
const FfiVec<DeviceIntRect>& aDirtyRects) {
const nsTArray<DeviceIntRect>& aDirtyRects) {
RenderedFrameId frameId = GetNextRenderFrameId();
InsertFrameDoneSync();

View File

@ -31,7 +31,7 @@ class RenderCompositorOGL : public RenderCompositor {
virtual ~RenderCompositorOGL();
bool BeginFrame() override;
RenderedFrameId EndFrame(const FfiVec<DeviceIntRect>& aDirtyRects) final;
RenderedFrameId EndFrame(const nsTArray<DeviceIntRect>& aDirtyRects) final;
bool WaitForGPU() override;
void Pause() override;
bool Resume() override;

View File

@ -415,7 +415,7 @@ void RenderThread::RunEvent(wr::WindowId aWindowId,
}
static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
RefPtr<WebRenderPipelineInfo> aInfo,
RefPtr<const WebRenderPipelineInfo> 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<WebRenderPipelineInfo> info = renderer->FlushPipelineInfo();
RefPtr<const WebRenderPipelineInfo> 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<layers::CompositorBridgeParent> aBridge,
const nsTArray<wr::RenderRoot>& aRenderRoots,
RefPtr<wr::WebRenderPipelineInfo> aInfo) {
RefPtr<const wr::WebRenderPipelineInfo> 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<mozilla::layers::CompositorBridgeParent> cbp = mozilla::layers::
CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId);
RefPtr<wr::WebRenderPipelineInfo> info = new wr::WebRenderPipelineInfo(aInfo);
RefPtr<wr::WebRenderPipelineInfo> info = new wr::WebRenderPipelineInfo();
info->Raw() = std::move(*aInfo);
if (cbp) {
nsTArray<wr::RenderRoot> renderRoots;
renderRoots.SetLength(aDocumentIdsCount);

View File

@ -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.

View File

@ -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<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) {
@ -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<DeviceIntRect> 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<WebRenderPipelineInfo> RendererOGL::FlushPipelineInfo() {
auto info = wr_renderer_flush_pipeline_info(mRenderer);
return new WebRenderPipelineInfo(info);
RefPtr<WebRenderPipelineInfo> info = new WebRenderPipelineInfo();
wr_renderer_flush_pipeline_info(mRenderer, &info->Raw());
return info;
}
RenderTextureHost* RendererOGL::GetRenderTexture(

View File

@ -40,3 +40,6 @@ bitflags = true
"target_os = windows" = "XP_WIN"
"target_os = macos" = "XP_MACOSX"
"target_os = android" = "ANDROID"
[export.rename]
"ThinVec" = "nsTArray"

View File

@ -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<T> {
// 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<T> FfiVec<T> {
fn from_vec(v: Vec<T>) -> FfiVec<T> {
let ret = FfiVec {
data: v.as_ptr(),
length: v.len(),
capacity: v.capacity(),
};
mem::forget(v);
ret
}
}
impl<T> Drop for FfiVec<T> {
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<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) -> 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<DeviceIntRect>,
) -> 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<WrPipelineEpoch>,
// 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<WrRemovedPipeline>,
/// 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<WrPipelineEpoch>,
/// 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<WrRemovedPipeline>,
}
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<DocumentId>, 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); }
}

View File

@ -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;

View File

@ -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);