Bug 1385003 - Update webrender bindings for API changes in WR cset f6d81d9. r?kvark draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 09 Aug 2017 08:46:24 -0400
changeset 643283 b6eb2f8bc4235705e9c5df417730e93d02596499
parent 643282 c4618866051787ef2974f1769c0539f8a494141c
child 643284 3ded97dc34e9b27da1dcb3935fcf5a1875d57e75
push id73049
push userkgupta@mozilla.com
push dateWed, 09 Aug 2017 14:47:44 +0000
reviewerskvark
bugs1385003
milestone57.0a1
Bug 1385003 - Update webrender bindings for API changes in WR cset f6d81d9. r?kvark In theory the upstream API change should allow us to share the same WR renderer instance across multiple WebRenderAPI instances. For now however I retain the existing behaviour of one WR instance for each WebRenderAPI instance, but keep track of the document id in a new DocumentHandle struct. The C++ side keeps a pointer to this DocumentHandle struct instead of the raw RenderApi. MozReview-Commit-ID: I9pCKOY1OYx
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -18,25 +18,25 @@
 namespace mozilla {
 namespace wr {
 
 using layers::Stringify;
 
 class NewRenderer : public RendererEvent
 {
 public:
-  NewRenderer(wr::RenderApi** aApi, layers::CompositorBridgeParentBase* aBridge,
+  NewRenderer(wr::DocumentHandle** aDocHandle, layers::CompositorBridgeParentBase* aBridge,
               GLint* aMaxTextureSize,
               bool* aUseANGLE,
               RefPtr<widget::CompositorWidget>&& aWidget,
               layers::SynchronousTask* aTask,
               bool aEnableProfiler,
               LayoutDeviceIntSize aSize,
               layers::SyncHandle* aHandle)
-    : mRenderApi(aApi)
+    : mDocHandle(aDocHandle)
     , mMaxTextureSize(aMaxTextureSize)
     , mUseANGLE(aUseANGLE)
     , mBridge(aBridge)
     , mCompositorWidget(Move(aWidget))
     , mTask(aTask)
     , mEnableProfiler(aEnableProfiler)
     , mSize(aSize)
     , mSyncHandle(aHandle)
@@ -70,17 +70,17 @@ public:
     }
 
     gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, mMaxTextureSize);
     *mUseANGLE = gl->IsANGLE();
 
     wr::Renderer* wrRenderer = nullptr;
     if (!wr_window_new(aWindowId, mSize.width, mSize.height, gl.get(),
                        aRenderThread.ThreadPool().Raw(),
-                       this->mEnableProfiler, mRenderApi, &wrRenderer)) {
+                       this->mEnableProfiler, mDocHandle, &wrRenderer)) {
       // wr_window_new puts a message into gfxCriticalNote if it returns false
       return;
     }
     MOZ_ASSERT(wrRenderer);
 
     RefPtr<RenderThread> thread = &aRenderThread;
     auto renderer = MakeUnique<RendererOGL>(Move(thread),
                                             Move(gl),
@@ -99,17 +99,17 @@ public:
         *mSyncHandle = syncObj->GetSyncHandle();
       }
     }
 
     aRenderThread.AddRenderer(aWindowId, Move(renderer));
   }
 
 private:
-  wr::RenderApi** mRenderApi;
+  wr::DocumentHandle** mDocHandle;
   GLint* mMaxTextureSize;
   bool* mUseANGLE;
   layers::CompositorBridgeParentBase* mBridge;
   RefPtr<widget::CompositorWidget> mCompositorWidget;
   layers::SynchronousTask* mTask;
   bool mEnableProfiler;
   LayoutDeviceIntSize mSize;
   layers::SyncHandle* mSyncHandle;
@@ -148,73 +148,73 @@ WebRenderAPI::Create(bool aEnableProfile
                      LayoutDeviceIntSize aSize)
 {
   MOZ_ASSERT(aBridge);
   MOZ_ASSERT(aWidget);
 
   static uint64_t sNextId = 1;
   auto id = NewWindowId(sNextId++);
 
-  wr::RenderApi* renderApi = nullptr;
+  wr::DocumentHandle* docHandle = nullptr;
   GLint maxTextureSize = 0;
   bool useANGLE = false;
   layers::SyncHandle syncHandle = 0;
 
-  // Dispatch a synchronous task because the RenderApi object needs to be created
+  // Dispatch a synchronous task because the DocumentHandle object needs to be created
   // on the render thread. If need be we could delay waiting on this task until
-  // the next time we need to access the RenderApi object.
+  // the next time we need to access the DocumentHandle object.
   layers::SynchronousTask task("Create Renderer");
-  auto event = MakeUnique<NewRenderer>(&renderApi, aBridge, &maxTextureSize, &useANGLE,
+  auto event = MakeUnique<NewRenderer>(&docHandle, aBridge, &maxTextureSize, &useANGLE,
                                        Move(aWidget), &task, aEnableProfiler, aSize,
                                        &syncHandle);
   RenderThread::Get()->RunEvent(id, Move(event));
 
   task.Wait();
 
-  if (!renderApi) {
+  if (!docHandle) {
     return nullptr;
   }
 
-  return RefPtr<WebRenderAPI>(new WebRenderAPI(renderApi, id, maxTextureSize, useANGLE, syncHandle)).forget();
+  return RefPtr<WebRenderAPI>(new WebRenderAPI(docHandle, id, maxTextureSize, useANGLE, syncHandle)).forget();
 }
 
 wr::WrIdNamespace
 WebRenderAPI::GetNamespace() {
-  return wr_api_get_namespace(mRenderApi);
+  return wr_api_get_namespace(mDocHandle);
 }
 
 WebRenderAPI::~WebRenderAPI()
 {
   layers::SynchronousTask task("Destroy WebRenderAPI");
   auto event = MakeUnique<RemoveRenderer>(&task);
   RunOnRenderThread(Move(event));
   task.Wait();
 
-  wr_api_delete(mRenderApi);
+  wr_api_delete(mDocHandle);
 }
 
 void
 WebRenderAPI::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
                                    const layers::FrameMetrics::ViewID& aScrollId,
                                    const wr::LayoutPoint& aScrollPosition)
 {
-  wr_scroll_layer_with_id(mRenderApi, aPipelineId, aScrollId, aScrollPosition);
+  wr_scroll_layer_with_id(mDocHandle, aPipelineId, aScrollId, aScrollPosition);
 }
 
 void
 WebRenderAPI::GenerateFrame()
 {
-  wr_api_generate_frame(mRenderApi);
+  wr_api_generate_frame(mDocHandle);
 }
 
 void
 WebRenderAPI::GenerateFrame(const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                             const nsTArray<wr::WrTransformProperty>& aTransformArray)
 {
-  wr_api_generate_frame_with_properties(mRenderApi,
+  wr_api_generate_frame_with_properties(mDocHandle,
                                         aOpacityArray.IsEmpty() ?
                                           nullptr : aOpacityArray.Elements(),
                                         aOpacityArray.Length(),
                                         aTransformArray.IsEmpty() ?
                                           nullptr : aTransformArray.Elements(),
                                         aTransformArray.Length());
 }
 
@@ -223,38 +223,38 @@ WebRenderAPI::SetRootDisplayList(gfx::Co
                                  Epoch aEpoch,
                                  mozilla::LayerSize aViewportSize,
                                  wr::WrPipelineId pipeline_id,
                                  const LayoutSize& content_size,
                                  wr::BuiltDisplayListDescriptor dl_descriptor,
                                  uint8_t *dl_data,
                                  size_t dl_size)
 {
-    wr_api_set_root_display_list(mRenderApi,
+    wr_api_set_root_display_list(mDocHandle,
                                  ToColorF(aBgColor),
                                  aEpoch,
                                  aViewportSize.width, aViewportSize.height,
                                  pipeline_id,
                                  content_size,
                                  dl_descriptor,
                                  dl_data,
                                  dl_size);
 }
 
 void
 WebRenderAPI::ClearRootDisplayList(Epoch aEpoch,
                                    wr::WrPipelineId pipeline_id)
 {
-  wr_api_clear_root_display_list(mRenderApi, aEpoch, pipeline_id);
+  wr_api_clear_root_display_list(mDocHandle, aEpoch, pipeline_id);
 }
 
 void
 WebRenderAPI::SetWindowParameters(LayoutDeviceIntSize size)
 {
-  wr_api_set_window_parameters(mRenderApi, size.width, size.height);
+  wr_api_set_window_parameters(mDocHandle, size.width, size.height);
 }
 
 void
 WebRenderAPI::Readback(gfx::IntSize size,
                        uint8_t *buffer,
                        uint32_t buffer_size)
 {
     class Readback : public RendererEvent
@@ -406,47 +406,47 @@ WebRenderAPI::WaitFlushed()
     RunOnRenderThread(Move(event));
 
     task.Wait();
 }
 
 void
 WebRenderAPI::SetRootPipeline(PipelineId aPipeline)
 {
-  wr_api_set_root_pipeline(mRenderApi, aPipeline);
+  wr_api_set_root_pipeline(mDocHandle, aPipeline);
 }
 
 void
 WebRenderAPI::AddImage(ImageKey key, const ImageDescriptor& aDescriptor,
                        Range<uint8_t> aBytes)
 {
-  wr_api_add_image(mRenderApi,
+  wr_api_add_image(mDocHandle,
                    key,
                    &aDescriptor,
                    RangeToByteSlice(aBytes));
 }
 
 void
 WebRenderAPI::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor,
                            Range<uint8_t> aBytes)
 {
-  wr_api_add_blob_image(mRenderApi,
+  wr_api_add_blob_image(mDocHandle,
                         key,
                         &aDescriptor,
                         RangeToByteSlice(aBytes));
 }
 
 void
 WebRenderAPI::AddExternalImage(ImageKey key,
                                const ImageDescriptor& aDescriptor,
                                ExternalImageId aExtID,
                                wr::WrExternalImageBufferType aBufferType,
                                uint8_t aChannelIndex)
 {
-  wr_api_add_external_image(mRenderApi,
+  wr_api_add_external_image(mDocHandle,
                             key,
                             &aDescriptor,
                             aExtID,
                             aBufferType,
                             aChannelIndex);
 }
 
 void
@@ -460,64 +460,64 @@ WebRenderAPI::AddExternalImageBuffer(Ima
                    channelIndex);
 }
 
 void
 WebRenderAPI::UpdateImageBuffer(ImageKey aKey,
                                 const ImageDescriptor& aDescriptor,
                                 Range<uint8_t> aBytes)
 {
-  wr_api_update_image(mRenderApi,
+  wr_api_update_image(mDocHandle,
                       aKey,
                       &aDescriptor,
                       RangeToByteSlice(aBytes));
 }
 
 void
 WebRenderAPI::UpdateBlobImage(ImageKey aKey,
                               const ImageDescriptor& aDescriptor,
                               Range<uint8_t> aBytes)
 {
-  wr_api_update_blob_image(mRenderApi,
+  wr_api_update_blob_image(mDocHandle,
                            aKey,
                            &aDescriptor,
                            RangeToByteSlice(aBytes));
 }
 
 void
 WebRenderAPI::UpdateExternalImage(ImageKey aKey,
                                   const ImageDescriptor& aDescriptor,
                                   ExternalImageId aExtID,
                                   wr::WrExternalImageBufferType aBufferType,
                                   uint8_t aChannelIndex)
 {
-  wr_api_update_external_image(mRenderApi,
+  wr_api_update_external_image(mDocHandle,
                                aKey,
                                &aDescriptor,
                                aExtID,
                                aBufferType,
                                aChannelIndex);
 }
 
 void
 WebRenderAPI::DeleteImage(ImageKey aKey)
 {
-  wr_api_delete_image(mRenderApi, aKey);
+  wr_api_delete_image(mDocHandle, aKey);
 }
 
 void
 WebRenderAPI::AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex)
 {
-  wr_api_add_raw_font(mRenderApi, aKey, &aBytes[0], aBytes.length(), aIndex);
+  wr_api_add_raw_font(mDocHandle, aKey, &aBytes[0], aBytes.length(), aIndex);
 }
 
 void
 WebRenderAPI::DeleteFont(wr::FontKey aKey)
 {
-  wr_api_delete_font(mRenderApi, aKey);
+  wr_api_delete_font(mDocHandle, aKey);
 }
 
 class EnableProfiler : public RendererEvent
 {
 public:
   explicit EnableProfiler(bool aEnabled)
     : mEnabled(aEnabled)
   {
@@ -580,17 +580,17 @@ WebRenderAPI::SetFrameStartTime(const Ti
   auto event = MakeUnique<FrameStartTime>(aTime);
   RunOnRenderThread(Move(event));
 }
 
 void
 WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent)
 {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
-  wr_api_send_external_event(mRenderApi, event);
+  wr_api_send_external_event(mDocHandle, event);
 }
 
 DisplayListBuilder::DisplayListBuilder(PipelineId aId,
                                        const wr::LayoutSize& aContentSize)
 {
   MOZ_COUNT_CTOR(DisplayListBuilder);
   mWrState = wr_state_new(aId, aContentSize);
 }
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -121,29 +121,29 @@ public:
   bool Resume();
 
   wr::WrIdNamespace GetNamespace();
   GLint GetMaxTextureSize() const { return mMaxTextureSize; }
   bool GetUseANGLE() const { return mUseANGLE; }
   layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
 
 protected:
-  WebRenderAPI(wr::RenderApi* aRawApi, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE, layers::SyncHandle aSyncHandle)
-    : mRenderApi(aRawApi)
+  WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE, layers::SyncHandle aSyncHandle)
+    : mDocHandle(aHandle)
     , mId(aId)
     , mMaxTextureSize(aMaxTextureSize)
     , mUseANGLE(aUseANGLE)
     , mSyncHandle(aSyncHandle)
   {}
 
   ~WebRenderAPI();
   // Should be used only for shutdown handling
   void WaitFlushed();
 
-  wr::RenderApi* mRenderApi;
+  wr::DocumentHandle* mDocHandle;
   wr::WindowId mId;
   GLint mMaxTextureSize;
   bool mUseANGLE;
   layers::SyncHandle mSyncHandle;
 
   friend class DisplayListBuilder;
   friend class layers::WebRenderBridgeParent;
 };
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -51,16 +51,31 @@ fn make_slice<'a, T>(ptr: *const T, len:
 fn make_slice_mut<'a, T>(ptr: *mut T, len: usize) -> &'a mut [T] {
     if ptr.is_null() {
         &mut []
     } else {
         unsafe { slice::from_raw_parts_mut(ptr, len) }
     }
 }
 
+pub struct DocumentHandle {
+    api: RenderApi,
+    document_id: DocumentId,
+}
+
+impl DocumentHandle {
+    pub fn new(api: RenderApi, size: DeviceUintSize) -> DocumentHandle {
+        let doc = api.add_document(size);
+        DocumentHandle {
+            api: api,
+            document_id: doc
+        }
+    }
+}
+
 #[repr(C)]
 pub struct WrVecU8 {
     data: *mut u8,
     length: usize,
     capacity: usize,
 }
 
 impl WrVecU8 {
@@ -526,17 +541,17 @@ pub unsafe extern "C" fn wr_thread_pool_
 // Call MakeCurrent before this.
 #[no_mangle]
 pub extern "C" fn wr_window_new(window_id: WrWindowId,
                                 window_width: u32,
                                 window_height: u32,
                                 gl_context: *mut c_void,
                                 thread_pool: *mut WrThreadPool,
                                 enable_profiler: bool,
-                                out_api: &mut *mut RenderApi,
+                                out_handle: &mut *mut DocumentHandle,
                                 out_renderer: &mut *mut Renderer)
                                 -> bool {
     assert!(unsafe { is_in_render_thread() });
 
     let recorder: Option<Box<ApiRecordingReceiver>> = if unsafe { gfx_use_wrench() } {
         let name = format!("wr-record-{}.bin", window_id.0);
         Some(Box::new(BinaryRecorder::new(&PathBuf::from(name))))
     } else {
@@ -566,161 +581,165 @@ pub extern "C" fn wr_window_new(window_i
         recorder: recorder,
         blob_image_renderer: Some(Box::new(Moz2dImageRenderer::new(workers.clone()))),
         workers: Some(workers.clone()),
         cache_expiry_frames: 60, // see https://github.com/servo/webrender/pull/1294#issuecomment-304318800
         enable_render_on_scroll: false,
         ..Default::default()
     };
 
-    let window_size = DeviceUintSize::new(window_width, window_height);
-    let (renderer, sender) = match Renderer::new(gl, opts, window_size) {
+    let (renderer, sender) = match Renderer::new(gl, opts) {
         Ok((renderer, sender)) => (renderer, sender),
         Err(e) => {
             println!(" Failed to create a Renderer: {:?}", e);
             let msg = CString::new(format!("wr_window_new: {:?}", e)).unwrap();
             unsafe {
                 gfx_critical_note(msg.as_ptr());
             }
             return false;
         },
     };
 
     renderer.set_render_notifier(Box::new(CppNotifier {
                                               window_id: window_id,
                                           }));
 
-    *out_api = Box::into_raw(Box::new(sender.create_api()));
+    let window_size = DeviceUintSize::new(window_width, window_height);
+    *out_handle = Box::into_raw(Box::new(
+            DocumentHandle::new(sender.create_api(), window_size)));
     *out_renderer = Box::into_raw(Box::new(renderer));
 
     return true;
 }
 
 /// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
-pub unsafe extern "C" fn wr_api_delete(api: *mut RenderApi) {
-    let api = Box::from_raw(api);
-    api.shut_down();
+pub unsafe extern "C" fn wr_api_delete(dh: *mut DocumentHandle) {
+    let handle = Box::from_raw(dh);
+    handle.api.delete_document(handle.document_id);
+    handle.api.shut_down();
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_image(api: &mut RenderApi,
+pub extern "C" fn wr_api_add_image(dh: &mut DocumentHandle,
                                    image_key: WrImageKey,
                                    descriptor: &WrImageDescriptor,
                                    bytes: ByteSlice) {
     assert!(unsafe { is_in_compositor_thread() });
     let copied_bytes = bytes.as_slice().to_owned();
-    api.add_image(image_key,
-                  descriptor.into(),
-                  ImageData::new(copied_bytes),
-                  None);
+    dh.api.add_image(image_key,
+                     descriptor.into(),
+                     ImageData::new(copied_bytes),
+                     None);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_blob_image(api: &mut RenderApi,
+pub extern "C" fn wr_api_add_blob_image(dh: &mut DocumentHandle,
                                         image_key: WrImageKey,
                                         descriptor: &WrImageDescriptor,
                                         bytes: ByteSlice) {
     assert!(unsafe { is_in_compositor_thread() });
     let copied_bytes = bytes.as_slice().to_owned();
-    api.add_image(image_key,
-                  descriptor.into(),
-                  ImageData::new_blob_image(copied_bytes),
-                  None);
+    dh.api.add_image(image_key,
+                     descriptor.into(),
+                     ImageData::new_blob_image(copied_bytes),
+                     None);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_external_image(api: &mut RenderApi,
+pub extern "C" fn wr_api_add_external_image(dh: &mut DocumentHandle,
                                             image_key: WrImageKey,
                                             descriptor: &WrImageDescriptor,
                                             external_image_id: WrExternalImageId,
                                             buffer_type: WrExternalImageBufferType,
                                             channel_index: u8) {
     assert!(unsafe { is_in_compositor_thread() });
-    api.add_image(image_key,
-                  descriptor.into(),
-                  ImageData::External(ExternalImageData {
-                                          id: external_image_id.into(),
-                                          channel_index: channel_index,
-                                          image_type: buffer_type,
-                                      }),
-                  None);
+    dh.api.add_image(image_key,
+                     descriptor.into(),
+                     ImageData::External(ExternalImageData {
+                                             id: external_image_id.into(),
+                                             channel_index: channel_index,
+                                             image_type: buffer_type,
+                                         }),
+                     None);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_update_image(api: &mut RenderApi,
+pub extern "C" fn wr_api_update_image(dh: &mut DocumentHandle,
                                       key: WrImageKey,
                                       descriptor: &WrImageDescriptor,
                                       bytes: ByteSlice) {
     assert!(unsafe { is_in_compositor_thread() });
     let copied_bytes = bytes.as_slice().to_owned();
 
-    api.update_image(key, descriptor.into(), ImageData::new(copied_bytes), None);
+    dh.api.update_image(key, descriptor.into(), ImageData::new(copied_bytes), None);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_update_external_image(
-    api: &mut RenderApi,
+    dh: &mut DocumentHandle,
     key: WrImageKey,
     descriptor: &WrImageDescriptor,
     external_image_id: WrExternalImageId,
     image_type: WrExternalImageBufferType,
     channel_index: u8
 ) {
     assert!(unsafe { is_in_compositor_thread() });
 
     let data = ImageData::External(
         ExternalImageData {
             id: external_image_id.into(),
             channel_index,
             image_type,
         }
     );
 
-    api.update_image(key, descriptor.into(), data, None);
+    dh.api.update_image(key, descriptor.into(), data, None);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_update_blob_image(api: &mut RenderApi,
+pub extern "C" fn wr_api_update_blob_image(dh: &mut DocumentHandle,
                                            image_key: WrImageKey,
                                            descriptor: &WrImageDescriptor,
                                            bytes: ByteSlice) {
     assert!(unsafe { is_in_compositor_thread() });
     let copied_bytes = bytes.as_slice().to_owned();
-    api.update_image(
-        image_key,
-        descriptor.into(),
-        ImageData::new_blob_image(copied_bytes),
-        None
+    dh.api.update_image(
+           image_key,
+           descriptor.into(),
+           ImageData::new_blob_image(copied_bytes),
+           None
     );
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_delete_image(api: &mut RenderApi,
+pub extern "C" fn wr_api_delete_image(dh: &mut DocumentHandle,
                                       key: WrImageKey) {
     assert!(unsafe { is_in_compositor_thread() });
-    api.delete_image(key)
+    dh.api.delete_image(key)
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_set_root_pipeline(api: &mut RenderApi,
+pub extern "C" fn wr_api_set_root_pipeline(dh: &mut DocumentHandle,
                                            pipeline_id: WrPipelineId) {
-    api.set_root_pipeline(pipeline_id);
+    dh.api.set_root_pipeline(dh.document_id, pipeline_id);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_set_window_parameters(api: &mut RenderApi,
+pub extern "C" fn wr_api_set_window_parameters(dh: &mut DocumentHandle,
                                                width: i32,
                                                height: i32) {
     let size = DeviceUintSize::new(width as u32, height as u32);
-    api.set_window_parameters(size, DeviceUintRect::new(DeviceUintPoint::new(0, 0), size));
+    dh.api.set_window_parameters(dh.document_id,
+                                 size,
+                                 DeviceUintRect::new(DeviceUintPoint::new(0, 0), size));
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn wr_api_set_root_display_list(api: &mut RenderApi,
+pub unsafe extern "C" fn wr_api_set_root_display_list(dh: &mut DocumentHandle,
                                                       color: ColorF,
                                                       epoch: WrEpoch,
                                                       viewport_width: f32,
                                                       viewport_height: f32,
                                                       pipeline_id: WrPipelineId,
                                                       content_size: LayoutSize,
                                                       dl_descriptor: BuiltDisplayListDescriptor,
                                                       dl_data: *mut u8,
@@ -736,44 +755,46 @@ pub unsafe extern "C" fn wr_api_set_root
     let preserve_frame_state = true;
 
     let dl_slice = make_slice(dl_data, dl_size);
     let mut dl_vec = Vec::new();
     // XXX: see if we can get rid of the copy here
     dl_vec.extend_from_slice(dl_slice);
     let dl = BuiltDisplayList::from_data(dl_vec, dl_descriptor);
 
-    api.set_display_list(color,
-                         epoch,
-                         LayoutSize::new(viewport_width, viewport_height),
-                         (pipeline_id, content_size.into(), dl),
-                         preserve_frame_state);
+    dh.api.set_display_list(dh.document_id,
+                            epoch,
+                            color,
+                            LayoutSize::new(viewport_width, viewport_height),
+                            (pipeline_id, content_size.into(), dl),
+                            preserve_frame_state);
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn wr_api_clear_root_display_list(api: &mut RenderApi,
+pub unsafe extern "C" fn wr_api_clear_root_display_list(dh: &mut DocumentHandle,
                                                         epoch: WrEpoch,
                                                         pipeline_id: WrPipelineId) {
     let preserve_frame_state = true;
     let frame_builder = WebRenderFrameBuilder::new(pipeline_id, LayoutSize::zero());
 
-    api.set_display_list(None,
-                         epoch,
-                         LayoutSize::new(0.0, 0.0),
-                         frame_builder.dl_builder.finalize(),
-                         preserve_frame_state);
+    dh.api.set_display_list(dh.document_id,
+                            epoch,
+                            None,
+                            LayoutSize::new(0.0, 0.0),
+                            frame_builder.dl_builder.finalize(),
+                            preserve_frame_state);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_generate_frame(api: &mut RenderApi) {
-    api.generate_frame(None);
+pub extern "C" fn wr_api_generate_frame(dh: &mut DocumentHandle) {
+    dh.api.generate_frame(dh.document_id, None);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_generate_frame_with_properties(api: &mut RenderApi,
+pub extern "C" fn wr_api_generate_frame_with_properties(dh: &mut DocumentHandle,
                                                         opacity_array: *const WrOpacityProperty,
                                                         opacity_count: usize,
                                                         transform_array: *const WrTransformProperty,
                                                         transform_count: usize) {
     let mut properties = DynamicProperties {
         transforms: Vec::new(),
         floats: Vec::new(),
     };
@@ -798,53 +819,53 @@ pub extern "C" fn wr_api_generate_frame_
             let prop = PropertyValue {
                 key: PropertyBindingKey::new(element.id),
                 value: element.opacity,
             };
             properties.floats.push(prop);
         }
     }
 
-    api.generate_frame(Some(properties));
+    dh.api.generate_frame(dh.document_id, Some(properties));
 }
 
 /// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
-pub extern "C" fn wr_api_send_external_event(api: &mut RenderApi,
+pub extern "C" fn wr_api_send_external_event(dh: &mut DocumentHandle,
                                              evt: usize) {
     assert!(unsafe { !is_in_render_thread() });
 
-    api.send_external_event(ExternalEvent::from_raw(evt));
+    dh.api.send_external_event(ExternalEvent::from_raw(evt));
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_add_raw_font(api: &mut RenderApi,
+pub extern "C" fn wr_api_add_raw_font(dh: &mut DocumentHandle,
                                       key: WrFontKey,
                                       font_buffer: *mut u8,
                                       buffer_size: usize,
                                       index: u32) {
     assert!(unsafe { is_in_compositor_thread() });
 
     let font_slice = make_slice(font_buffer, buffer_size);
     let mut font_vector = Vec::new();
     font_vector.extend_from_slice(font_slice);
 
-    api.add_raw_font(key, font_vector, index);
+    dh.api.add_raw_font(key, font_vector, index);
 }
 
 #[no_mangle]
-pub extern "C" fn wr_api_delete_font(api: &mut RenderApi,
+pub extern "C" fn wr_api_delete_font(dh: &mut DocumentHandle,
                                      key: WrFontKey) {
     assert!(unsafe { is_in_compositor_thread() });
-    api.delete_font(key);
+    dh.api.delete_font(key);
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn wr_api_get_namespace(api: &mut RenderApi) -> WrIdNamespace {
-    api.id_namespace
+pub unsafe extern "C" fn wr_api_get_namespace(dh: &mut DocumentHandle) -> WrIdNamespace {
+    dh.document_id.0
 }
 
 // RenderThread WIP notes:
 // In order to separate the compositor thread (or ipc receiver) and the render
 // thread, some of the logic below needs to be rewritten. In particular
 // the WrWindowState and Notifier implementations aren't designed to work with
 // a separate render thread.
 // As part of that I am moving the bindings closer to WebRender's API boundary,
@@ -1045,23 +1066,23 @@ pub extern "C" fn wr_dp_push_scroll_laye
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_scroll_layer(state: &mut WrState) {
     assert!(unsafe { is_in_main_thread() });
     state.frame_builder.dl_builder.pop_clip_id();
 }
 
 #[no_mangle]
-pub extern "C" fn wr_scroll_layer_with_id(api: &mut RenderApi,
+pub extern "C" fn wr_scroll_layer_with_id(dh: &mut DocumentHandle,
                                           pipeline_id: WrPipelineId,
                                           scroll_id: u64,
                                           new_scroll_origin: LayoutPoint) {
     assert!(unsafe { is_in_compositor_thread() });
     let clip_id = ClipId::new(scroll_id, pipeline_id);
-    api.scroll_node_with_id(new_scroll_origin.into(), clip_id, ScrollClamping::NoClamping);
+    dh.api.scroll_node_with_id(dh.document_id, new_scroll_origin.into(), clip_id, ScrollClamping::NoClamping);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_clip_and_scroll_info(state: &mut WrState,
                                                   scroll_id: u64,
                                                   clip_id: *const u64) {
     assert!(unsafe { is_in_main_thread() });
     let scroll_id = ClipId::new(scroll_id, state.pipeline_id);