Backed out 4 changesets (bug 1520678) for build bustages complaining no field `resources` CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Fri, 18 Jan 2019 04:05:26 +0200
changeset 511485 a15dd0f8abd30f7d78faaa9596533f2cd950788e
parent 511484 508f0c568b834e49fd9b7d2ecbfe44a1fa061da6
child 511486 f34a165f5aff3b051da1b06fd768fcb74200988a
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1520678
milestone66.0a1
backs outad7c9c863c2e6cb1711c4e8c0fc1057489dfe1e1
64717bf7f849d4a1f42f3e4a1b7a3fc3814a2ae7
5fa2f414676e818c36c92276ce9dc20341b877d2
1d2ae392021c5fabbd8a19290e965cafc7c09dec
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1520678) for build bustages complaining no field `resources` CLOSED TREE Backed out changeset ad7c9c863c2e (bug 1520678) Backed out changeset 64717bf7f849 (bug 1520678) Backed out changeset 5fa2f414676e (bug 1520678) Backed out changeset 1d2ae392021c (bug 1520678)
gfx/thebes/gfxPlatform.cpp
gfx/webrender_bindings/webrender_ffi.h
gfx/wr/webrender/src/batch.rs
gfx/wr/webrender/src/clip.rs
gfx/wr/webrender/src/display_list_flattener.rs
gfx/wr/webrender/src/frame_builder.rs
gfx/wr/webrender/src/intern_types.rs
gfx/wr/webrender/src/lib.rs
gfx/wr/webrender/src/picture.rs
gfx/wr/webrender/src/prim_store/borders.rs
gfx/wr/webrender/src/prim_store/gradient.rs
gfx/wr/webrender/src/prim_store/image.rs
gfx/wr/webrender/src/prim_store/line_dec.rs
gfx/wr/webrender/src/prim_store/mod.rs
gfx/wr/webrender/src/prim_store/picture.rs
gfx/wr/webrender/src/prim_store/text_run.rs
gfx/wr/webrender/src/profiler.rs
gfx/wr/webrender/src/render_backend.rs
gfx/wr/webrender/src/scene_builder.rs
gfx/wr/webrender/src/tiling.rs
gfx/wr/webrender_api/src/api.rs
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -680,22 +680,22 @@ static void FinishAsyncMemoryReport() {
   if (imgr) {
     imgr->EndReport();
   }
 }
 
 // clang-format off
 // (For some reason, clang-format gets the second macro right, but totally mangles the first).
 #define REPORT_INTERNER(id)                      \
-  helper.Report(aReport.interning.interners.id, \
+  helper.Report(aReport.interning.id##_interner, \
                 "interning/" #id "/interners");
 // clang-format on
 
 #define REPORT_DATA_STORE(id)                      \
-  helper.Report(aReport.interning.data_stores.id, \
+  helper.Report(aReport.interning.id##_data_store, \
                 "interning/" #id "/data-stores");
 
 NS_IMPL_ISUPPORTS(WebRenderMemoryReporter, nsIMemoryReporter)
 
 NS_IMETHODIMP
 WebRenderMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
                                         nsISupports* aData, bool aAnonymize) {
   MOZ_ASSERT(XRE_IsParentProcess());
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -49,23 +49,25 @@ void gecko_profiler_end_marker(const cha
   macro(picture);                          \
   macro(text_run);
 
 // Prelude of types necessary before including webrender_ffi_generated.h
 namespace mozilla {
 namespace wr {
 
 // Because this struct is macro-generated on the Rust side, cbindgen can't see
-// it. Work around that by re-declaring it here.
-#define DECLARE_MEMBER(id) uintptr_t id;
-struct InternerSubReport {
-  WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBER)
+// it for some reason. Work around that by re-declaring it here.
+#define DECLARE_MEMBERS(id) \
+  uintptr_t id##_interner;  \
+  uintptr_t id##_data_store;
+struct InterningMemoryReport {
+  WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBERS)
 };
 
-#undef DECLARE_MEMBER
+#undef DECLARE_MEMBERS
 
 struct FontInstanceFlags {
   uint32_t bits;
 
   bool operator==(const FontInstanceFlags& aOther) const {
     return bits == aOther.bits;
   }
 
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -14,17 +14,17 @@ use gpu_types::{ClipMaskInstance, SplitC
 use gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
 use gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
 use internal_types::{FastHashMap, SavedTargetIndex, TextureSource};
 use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureSurface};
 use prim_store::{DeferredResolve, EdgeAaSegmentMask, PrimitiveInstanceKind, PrimitiveVisibilityIndex};
 use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
 use prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex};
 use prim_store::image::ImageSource;
-use render_backend::DataStores;
+use render_backend::FrameResources;
 use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree, TileBlit};
 use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
 use renderer::BLOCKS_PER_UV_RECT;
 use resource_cache::{CacheItem, GlyphFetchResult, ImageRequest, ResourceCache, ImageProperties};
 use scene::FilterOpHelpers;
 use smallvec::SmallVec;
 use std::{f32, i32, usize};
 use tiling::{RenderTargetContext};
@@ -609,25 +609,25 @@ impl AlphaBatchBuilder {
         // Get the clip task address for the global primitive, if one was set.
         let clip_task_address = get_clip_task_address(
             &ctx.scratch.clip_mask_instances,
             prim_info.clip_task_index,
             0,
             render_tasks,
         ).unwrap_or(OPAQUE_TASK_ADDRESS);
 
-        let prim_common_data = &ctx.data_stores.as_common_data(&prim_instance);
+        let prim_common_data = &ctx.resources.as_common_data(&prim_instance);
         let prim_rect = LayoutRect::new(
             prim_instance.prim_origin,
             prim_common_data.prim_size,
         );
 
         match prim_instance.kind {
             PrimitiveInstanceKind::Clear { data_handle } => {
-                let prim_data = &ctx.data_stores.prim[data_handle];
+                let prim_data = &ctx.resources.prim_data_store[data_handle];
                 let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
 
                 // TODO(gw): We can abstract some of the common code below into
                 //           helper methods, as we port more primitives to make
                 //           use of interning.
 
                 let prim_header = PrimitiveHeader {
                     local_rect: prim_rect,
@@ -662,17 +662,17 @@ impl AlphaBatchBuilder {
                 self.current_batch_list().push_single_instance(
                     batch_key,
                     bounding_rect,
                     z_id,
                     PrimitiveInstanceData::from(instance),
                 );
             }
             PrimitiveInstanceKind::NormalBorder { data_handle, ref cache_handles, .. } => {
-                let prim_data = &ctx.data_stores.normal_border[data_handle];
+                let prim_data = &ctx.resources.normal_border_data_store[data_handle];
                 let common_data = &prim_data.common;
                 let prim_cache_address = gpu_cache.get_address(&common_data.gpu_cache_handle);
                 let cache_handles = &ctx.scratch.border_cache_handles[*cache_handles];
                 let specified_blend_mode = BlendMode::PremultipliedAlpha;
                 let mut segment_data: SmallVec<[SegmentInstanceData; 8]> = SmallVec::new();
 
                 // Collect the segment instance data from each render
                 // task for each valid edge / corner of the border.
@@ -742,17 +742,17 @@ impl AlphaBatchBuilder {
                 );
             }
             PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
                 let run = &ctx.prim_store.text_runs[run_index];
                 let subpx_dir = run.used_font.get_subpx_dir();
 
                 // The GPU cache data is stored in the template and reused across
                 // frames and display lists.
-                let prim_data = &ctx.data_stores.text_run[data_handle];
+                let prim_data = &ctx.resources.text_run_data_store[data_handle];
                 let glyph_fetch_buffer = &mut self.glyph_fetch_buffer;
                 let alpha_batch_list = &mut self.batch_lists.last_mut().unwrap().alpha_batch_list;
                 let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
 
                 let prim_header = PrimitiveHeader {
                     local_rect: prim_rect,
                     local_clip_rect: prim_info.combined_local_clip_rect,
                     task_address,
@@ -849,17 +849,17 @@ impl AlphaBatchBuilder {
                             ));
                         }
                     },
                 );
             }
             PrimitiveInstanceKind::LineDecoration { data_handle, ref cache_handle, .. } => {
                 // The GPU cache data is stored in the template and reused across
                 // frames and display lists.
-                let common_data = &ctx.data_stores.line_decoration[data_handle].common;
+                let common_data = &ctx.resources.line_decoration_data_store[data_handle].common;
                 let prim_cache_address = gpu_cache.get_address(&common_data.gpu_cache_handle);
 
                 let (batch_kind, textures, prim_user_data, segment_user_data) = match cache_handle {
                     Some(cache_handle) => {
                         let rt_cache_entry = ctx
                             .resource_cache
                             .get_cached_render_task(cache_handle);
                         let cache_item = ctx
@@ -1483,17 +1483,17 @@ impl AlphaBatchBuilder {
                             transforms,
                             root_spatial_node_index,
                             z_generator,
                         );
                     }
                 }
             }
             PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
-                let prim_data = &ctx.data_stores.image_border[data_handle];
+                let prim_data = &ctx.resources.image_border_data_store[data_handle];
                 let common_data = &prim_data.common;
                 let border_data = &prim_data.kind;
 
                 let cache_item = resolve_image(
                     border_data.request,
                     ctx.resource_cache,
                     gpu_cache,
                     deferred_resolves,
@@ -1552,17 +1552,17 @@ impl AlphaBatchBuilder {
                     transform_kind,
                     render_tasks,
                     z_id,
                     prim_info.clip_task_index,
                     ctx,
                 );
             }
             PrimitiveInstanceKind::Rectangle { data_handle, segment_instance_index, opacity_binding_index, .. } => {
-                let prim_data = &ctx.data_stores.prim[data_handle];
+                let prim_data = &ctx.resources.prim_data_store[data_handle];
                 let specified_blend_mode = BlendMode::PremultipliedAlpha;
                 let opacity_binding = ctx.prim_store.get_opacity_binding(opacity_binding_index);
 
                 let opacity = PrimitiveOpacity::from_alpha(opacity_binding);
                 let opacity = opacity.combine(prim_data.opacity);
 
                 let non_segmented_blend_mode = if !opacity.is_opaque ||
                     prim_info.clip_task_index != ClipTaskIndex::INVALID ||
@@ -1615,17 +1615,17 @@ impl AlphaBatchBuilder {
                     transform_kind,
                     render_tasks,
                     z_id,
                     prim_info.clip_task_index,
                     ctx,
                 );
             }
             PrimitiveInstanceKind::YuvImage { data_handle, segment_instance_index, .. } => {
-                let yuv_image_data = &ctx.data_stores.yuv_image[data_handle].kind;
+                let yuv_image_data = &ctx.resources.yuv_image_data_store[data_handle].kind;
                 let mut textures = BatchTextures::no_texture();
                 let mut uv_rect_addresses = [0; 3];
 
                 //yuv channel
                 let channel_count = yuv_image_data.format.get_plane_num();
                 debug_assert!(channel_count <= 3);
                 for channel in 0 .. channel_count {
                     let image_key = yuv_image_data.yuv_key[channel];
@@ -1723,18 +1723,18 @@ impl AlphaBatchBuilder {
                     transform_kind,
                     render_tasks,
                     z_id,
                     prim_info.clip_task_index,
                     ctx,
                 );
             }
             PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
-                let image_data = &ctx.data_stores.image[data_handle].kind;
-                let common_data = &ctx.data_stores.image[data_handle].common;
+                let image_data = &ctx.resources.image_data_store[data_handle].kind;
+                let common_data = &ctx.resources.image_data_store[data_handle].common;
                 let image_instance = &ctx.prim_store.images[image_instance_index];
                 let opacity_binding = ctx.prim_store.get_opacity_binding(image_instance.opacity_binding_index);
                 let specified_blend_mode = match image_data.alpha_type {
                     AlphaType::PremultipliedAlpha => BlendMode::PremultipliedAlpha,
                     AlphaType::Alpha => BlendMode::Alpha,
                 };
                 let request = ImageRequest {
                     key: image_data.key,
@@ -1862,17 +1862,17 @@ impl AlphaBatchBuilder {
                                 uv_rect_address,
                                 z_id,
                             );
                         }
                     }
                 }
             }
             PrimitiveInstanceKind::LinearGradient { data_handle, ref visible_tiles_range, .. } => {
-                let prim_data = &ctx.data_stores.linear_grad[data_handle];
+                let prim_data = &ctx.resources.linear_grad_data_store[data_handle];
                 let specified_blend_mode = BlendMode::PremultipliedAlpha;
 
                 let mut prim_header = PrimitiveHeader {
                     local_rect: prim_rect,
                     local_clip_rect: prim_info.combined_local_clip_rect,
                     task_address,
                     specific_prim_address: GpuCacheAddress::invalid(),
                     clip_task_address,
@@ -1943,17 +1943,17 @@ impl AlphaBatchBuilder {
                         self.current_batch_list(),
                         &prim_header,
                         prim_headers,
                         z_id,
                     );
                 }
             }
             PrimitiveInstanceKind::RadialGradient { data_handle, ref visible_tiles_range, .. } => {
-                let prim_data = &ctx.data_stores.radial_grad[data_handle];
+                let prim_data = &ctx.resources.radial_grad_data_store[data_handle];
                 let specified_blend_mode = BlendMode::PremultipliedAlpha;
 
                 let mut prim_header = PrimitiveHeader {
                     local_rect: prim_rect,
                     local_clip_rect: prim_info.combined_local_clip_rect,
                     task_address,
                     specific_prim_address: GpuCacheAddress::invalid(),
                     clip_task_address,
@@ -2354,27 +2354,27 @@ impl BrushBatchParameters {
             ),
         }
     }
 }
 
 impl PrimitiveInstance {
     pub fn is_cacheable(
         &self,
-        data_stores: &DataStores,
+        resources: &FrameResources,
         resource_cache: &ResourceCache,
     ) -> bool {
         let image_key = match self.kind {
             PrimitiveInstanceKind::Image { data_handle, .. } => {
-                let image_data = &data_stores.image[data_handle].kind;
+                let image_data = &resources.image_data_store[data_handle].kind;
                 image_data.key
             }
             PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
                 let yuv_image_data =
-                    &data_stores.yuv_image[data_handle].kind;
+                    &resources.yuv_image_data_store[data_handle].kind;
                 yuv_image_data.yuv_key[0]
             }
             PrimitiveInstanceKind::Picture { .. } |
             PrimitiveInstanceKind::TextRun { .. } |
             PrimitiveInstanceKind::LineDecoration { .. } |
             PrimitiveInstanceKind::NormalBorder { .. } |
             PrimitiveInstanceKind::ImageBorder { .. } |
             PrimitiveInstanceKind::Rectangle { .. } |
--- a/gfx/wr/webrender/src/clip.rs
+++ b/gfx/wr/webrender/src/clip.rs
@@ -99,19 +99,25 @@ use util::{extract_inner_rect_safe, proj
     +------------------+------------------+------------------+------------------+------------------+
     | flags            | flags            | flags            | flags            | flags            |
     | ...              | ...              | ...              | ...              | ...              |
     +------------------+------------------+------------------+------------------+------------------+
 
  */
 
 // Type definitions for interning clip nodes.
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+pub struct ClipDataMarker;
 
-pub use intern_types::clip::Store as ClipDataStore;
-use intern_types::clip::Handle as ClipDataHandle;
+pub type ClipDataStore = intern::DataStore<ClipItemKey, ClipNode, ClipDataMarker>;
+pub type ClipDataHandle = intern::Handle<ClipDataMarker>;
+pub type ClipDataUpdateList = intern::UpdateList<ClipItemKey>;
+pub type ClipDataInterner = intern::Interner<ClipItemKey, (), ClipDataMarker>;
 
 // Result of comparing a clip node instance against a local rect.
 #[derive(Debug)]
 enum ClipResult {
     // The clip does not affect the region at all.
     Accept,
     // The clip prevents the region from being drawn.
     Reject,
--- a/gfx/wr/webrender/src/display_list_flattener.rs
+++ b/gfx/wr/webrender/src/display_list_flattener.rs
@@ -30,17 +30,17 @@ use prim_store::borders::{ImageBorder, N
 use prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
 use prim_store::image::{Image, YuvImage};
 use prim_store::line_dec::{LineDecoration, LineDecorationCacheKey};
 use prim_store::picture::{Picture, PictureCompositeKey, PictureKey};
 use prim_store::text_run::TextRun;
 use render_backend::{DocumentView};
 use resource_cache::{FontInstanceMap, ImageRequest};
 use scene::{Scene, ScenePipeline, StackingContextHelpers};
-use scene_builder::{InternerMut, Interners};
+use scene_builder::{DocumentResources, InternerMut};
 use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
 use std::{f32, mem, usize};
 use std::collections::vec_deque::VecDeque;
 use std::sync::Arc;
 use tiling::{CompositeOps};
 use util::{MaxRect, VecHelper};
 
 #[derive(Debug, Copy, Clone)]
@@ -134,34 +134,35 @@ pub struct DisplayListFlattener<'a> {
 
     /// The store which holds all complex clipping information.
     pub clip_store: ClipStore,
 
     /// The configuration to use for the FrameBuilder. We consult this in
     /// order to determine the default font.
     pub config: FrameBuilderConfig,
 
-    /// Reference to the set of data that is interned across display lists.
-    interners: &'a mut Interners,
+    /// Reference to the document resources, which contains
+    /// shared (interned) data between display lists.
+    resources: &'a mut DocumentResources,
 
     /// The root picture index for this flattener. This is the picture
     /// to start the culling phase from.
     pub root_pic_index: PictureIndex,
 }
 
 impl<'a> DisplayListFlattener<'a> {
     pub fn create_frame_builder(
         scene: &Scene,
         clip_scroll_tree: &mut ClipScrollTree,
         font_instances: FontInstanceMap,
         view: &DocumentView,
         output_pipelines: &FastHashSet<PipelineId>,
         frame_builder_config: &FrameBuilderConfig,
         new_scene: &mut Scene,
-        interners: &mut Interners,
+        resources: &mut DocumentResources,
         prim_store_stats: &PrimitiveStoreStats,
     ) -> FrameBuilder {
         // We checked that the root pipeline is available on the render backend.
         let root_pipeline_id = scene.root_pipeline_id.unwrap();
         let root_pipeline = scene.pipelines.get(&root_pipeline_id).unwrap();
 
         let background_color = root_pipeline
             .background_color
@@ -175,17 +176,17 @@ impl<'a> DisplayListFlattener<'a> {
             output_pipelines,
             id_to_index_mapper: NodeIdToIndexMapper::default(),
             hit_testing_runs: Vec::new(),
             pending_shadow_items: VecDeque::new(),
             sc_stack: Vec::new(),
             pipeline_clip_chain_stack: vec![ClipChainId::NONE],
             prim_store: PrimitiveStore::new(&prim_store_stats),
             clip_store: ClipStore::new(),
-            interners,
+            resources,
             root_pic_index: PictureIndex(0),
         };
 
         flattener.push_root(
             root_pipeline_id,
             &root_pipeline.viewport_size,
             &root_pipeline.content_size,
         );
@@ -320,31 +321,31 @@ impl<'a> DisplayListFlattener<'a> {
                 preceding_prims = Vec::new();
                 remaining_prims = old_prim_list;
                 trailing_prims = Vec::new();
             }
         }
 
         let prim_list = PrimitiveList::new(
             remaining_prims,
-            &self.interners,
+            &self.resources,
         );
 
         // Now, create a picture with tile caching enabled that will hold all
         // of the primitives selected as belonging to the main scroll root.
         let pic_key = PictureKey::new(
             true,
             LayoutSize::zero(),
             Picture {
                 composite_mode_key: PictureCompositeKey::Identity,
             },
         );
 
-        let pic_data_handle = self.interners
-            .picture
+        let pic_data_handle = self.resources
+            .picture_interner
             .intern(&pic_key, || {
                 PrimitiveSceneData {
                     prim_size: LayoutSize::zero(),
                     is_backface_visible: true,
                 }
             }
         );
 
@@ -1022,18 +1023,18 @@ impl<'a> DisplayListFlattener<'a> {
         if clip_items.is_empty() {
             parent_clip_chain_id
         } else {
             let mut clip_chain_id = parent_clip_chain_id;
 
             for (local_pos, item) in clip_items {
                 // Intern this clip item, and store the handle
                 // in the clip chain node.
-                let handle = self.interners
-                    .clip
+                let handle = self.resources
+                    .clip_interner
                     .intern(&item, || ());
 
                 clip_chain_id = self.clip_store.add_clip_chain_node(
                     handle,
                     local_pos,
                     spatial_node_index,
                     clip_chain_id,
                 );
@@ -1053,22 +1054,22 @@ impl<'a> DisplayListFlattener<'a> {
         info: &LayoutPrimitiveInfo,
         clip_chain_id: ClipChainId,
         spatial_node_index: SpatialNodeIndex,
         prim: P,
     ) -> PrimitiveInstance
     where
         P: Internable<InternData=PrimitiveSceneData>,
         P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
-        Interners: InternerMut<P>,
+        DocumentResources: InternerMut<P>,
     {
         // Build a primitive key.
         let prim_key = prim.build_key(info);
 
-        let interner = self.interners.interner_mut();
+        let interner = self.resources.interner_mut();
         let prim_data_handle =
             interner
             .intern(&prim_key, || {
                 PrimitiveSceneData {
                     prim_size: info.rect.size,
                     is_backface_visible: info.is_backface_visible,
                 }
             });
@@ -1128,17 +1129,17 @@ impl<'a> DisplayListFlattener<'a> {
         clip_and_scroll: ScrollNodeAndClipChain,
         info: &LayoutPrimitiveInfo,
         clip_items: Vec<(LayoutPoint, ClipItemKey)>,
         prim: P,
     )
     where
         P: Internable<InternData = PrimitiveSceneData> + IsVisible,
         P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
-        Interners: InternerMut<P>,
+        DocumentResources: InternerMut<P>,
     {
         if prim.is_visible() {
             let clip_chain_id = self.build_clip_chain(
                 clip_items,
                 clip_and_scroll.spatial_node_index,
                 clip_and_scroll.clip_chain_id,
             );
             self.add_prim_to_draw_list(
@@ -1155,17 +1156,17 @@ impl<'a> DisplayListFlattener<'a> {
         clip_and_scroll: ScrollNodeAndClipChain,
         info: &LayoutPrimitiveInfo,
         clip_items: Vec<(LayoutPoint, ClipItemKey)>,
         prim: P,
     )
     where
         P: Internable<InternData = PrimitiveSceneData> + IsVisible,
         P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
-        Interners: InternerMut<P>,
+        DocumentResources: InternerMut<P>,
         ShadowItem: From<PendingPrimitive<P>>
     {
         // If a shadow context is not active, then add the primitive
         // directly to the parent picture.
         if self.pending_shadow_items.is_empty() {
             self.add_nonshadowable_primitive(clip_and_scroll, info, clip_items, prim);
         } else {
             debug_assert!(clip_items.is_empty(), "No per-prim clips expected for shadowed primitives");
@@ -1185,17 +1186,17 @@ impl<'a> DisplayListFlattener<'a> {
         info: &LayoutPrimitiveInfo,
         clip_chain_id: ClipChainId,
         clip_and_scroll: ScrollNodeAndClipChain,
         prim: P,
     )
     where
         P: Internable<InternData = PrimitiveSceneData>,
         P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
-        Interners: InternerMut<P>,
+        DocumentResources: InternerMut<P>,
     {
         let prim_instance = self.create_primitive(
             info,
             clip_chain_id,
             clip_and_scroll.spatial_node_index,
             prim,
         );
         self.register_chase_primitive_by_rect(
@@ -1232,17 +1233,17 @@ impl<'a> DisplayListFlattener<'a> {
         // which determines if we *might* need to draw this on
         // an intermediate surface for plane splitting purposes.
         let (parent_is_3d, extra_3d_instance) = match self.sc_stack.last_mut() {
             Some(sc) => {
                 // Cut the sequence of flat children before starting a child stacking context,
                 // so that the relative order between them and our current SC is preserved.
                 let extra_instance = sc.cut_flat_item_sequence(
                     &mut self.prim_store,
-                    &mut self.interners,
+                    &mut self.resources,
                     &self.clip_store,
                 );
                 (sc.is_3d(), extra_instance)
             },
             None => (false, None),
         };
 
         if let Some(instance) = extra_3d_instance {
@@ -1380,17 +1381,17 @@ impl<'a> DisplayListFlattener<'a> {
                 leaf_composite_mode,
                 leaf_context_3d,
                 stacking_context.pipeline_id,
                 leaf_output_pipeline_id,
                 true,
                 stacking_context.requested_raster_space,
                 PrimitiveList::new(
                     stacking_context.primitives,
-                    &self.interners,
+                    &self.resources,
                 ),
                 stacking_context.spatial_node_index,
                 max_clip,
                 &self.clip_store,
                 None,
             ))
         );
 
@@ -1399,17 +1400,17 @@ impl<'a> DisplayListFlattener<'a> {
 
         let mut current_pic_index = leaf_pic_index;
         let mut cur_instance = create_prim_instance(
             leaf_pic_index,
             leaf_composite_mode.into(),
             stacking_context.is_backface_visible,
             stacking_context.clip_chain_id,
             stacking_context.spatial_node_index,
-            &mut self.interners,
+            &mut self.resources,
         );
 
         if cur_instance.is_chased() {
             println!("\tis a leaf primitive for a stacking context");
         }
 
         // If establishing a 3d context, the `cur_instance` represents
         // a picture with all the *trailing* immediate children elements.
@@ -1427,32 +1428,32 @@ impl<'a> DisplayListFlattener<'a> {
                         ancestor_index,
                     },
                     stacking_context.pipeline_id,
                     stacking_context.frame_output_pipeline_id,
                     true,
                     stacking_context.requested_raster_space,
                     PrimitiveList::new(
                         prims,
-                        &self.interners,
+                        &self.resources,
                     ),
                     stacking_context.spatial_node_index,
                     max_clip,
                     &self.clip_store,
                     None,
                 ))
             );
 
             cur_instance = create_prim_instance(
                 current_pic_index,
                 PictureCompositeKey::Identity,
                 stacking_context.is_backface_visible,
                 stacking_context.clip_chain_id,
                 stacking_context.spatial_node_index,
-                &mut self.interners,
+                &mut self.resources,
             );
         }
 
         // For each filter, create a new image with that composite mode.
         for filter in &stacking_context.composite_ops.filters {
             let filter = filter.sanitize();
             let composite_mode = Some(PictureCompositeMode::Filter(filter));
 
@@ -1462,33 +1463,33 @@ impl<'a> DisplayListFlattener<'a> {
                     composite_mode,
                     Picture3DContext::Out,
                     stacking_context.pipeline_id,
                     None,
                     true,
                     stacking_context.requested_raster_space,
                     PrimitiveList::new(
                         vec![cur_instance.clone()],
-                        &self.interners,
+                        &self.resources,
                     ),
                     stacking_context.spatial_node_index,
                     max_clip,
                     &self.clip_store,
                     None,
                 ))
             );
 
             current_pic_index = filter_pic_index;
             cur_instance = create_prim_instance(
                 current_pic_index,
                 composite_mode.into(),
                 stacking_context.is_backface_visible,
                 stacking_context.clip_chain_id,
                 stacking_context.spatial_node_index,
-                &mut self.interners,
+                &mut self.resources,
             );
 
             if cur_instance.is_chased() {
                 println!("\tis a composite picture for a stacking context with {:?}", filter);
             }
 
             // Run the optimize pass on this picture, to see if we can
             // collapse opacity and avoid drawing to an off-screen surface.
@@ -1505,33 +1506,33 @@ impl<'a> DisplayListFlattener<'a> {
                     composite_mode,
                     Picture3DContext::Out,
                     stacking_context.pipeline_id,
                     None,
                     true,
                     stacking_context.requested_raster_space,
                     PrimitiveList::new(
                         vec![cur_instance.clone()],
-                        &self.interners,
+                        &self.resources,
                     ),
                     stacking_context.spatial_node_index,
                     max_clip,
                     &self.clip_store,
                     None,
                 ))
             );
 
             current_pic_index = blend_pic_index;
             cur_instance = create_prim_instance(
                 blend_pic_index,
                 composite_mode.into(),
                 stacking_context.is_backface_visible,
                 stacking_context.clip_chain_id,
                 stacking_context.spatial_node_index,
-                &mut self.interners,
+                &mut self.resources,
             );
 
             if cur_instance.is_chased() {
                 println!("\tis a mix-blend picture for a stacking context with {:?}", mix_blend_mode);
             }
         }
 
         let has_mix_blend_on_secondary_framebuffer =
@@ -1656,51 +1657,51 @@ impl<'a> DisplayListFlattener<'a> {
 
         // Intern each clip item in this clip node, and add the interned
         // handle to a clip chain node, parented to form a chain.
         // TODO(gw): We could re-structure this to share some of the
         //           interning and chaining code.
 
         // Build the clip sources from the supplied region.
         let handle = self
-            .interners
-            .clip
+            .resources
+            .clip_interner
             .intern(&ClipItemKey::rectangle(clip_region.main.size, ClipMode::Clip), || ());
 
         parent_clip_chain_index = self
             .clip_store
             .add_clip_chain_node(
                 handle,
                 clip_region.main.origin,
                 spatial_node,
                 parent_clip_chain_index,
             );
         clip_count += 1;
 
         if let Some(ref image_mask) = clip_region.image_mask {
             let handle = self
-                .interners
-                .clip
+                .resources
+                .clip_interner
                 .intern(&ClipItemKey::image_mask(image_mask), || ());
 
             parent_clip_chain_index = self
                 .clip_store
                 .add_clip_chain_node(
                     handle,
                     image_mask.rect.origin,
                     spatial_node,
                     parent_clip_chain_index,
                 );
             clip_count += 1;
         }
 
         for region in clip_region.complex_clips {
             let handle = self
-                .interners
-                .clip
+                .resources
+                .clip_interner
                 .intern(&ClipItemKey::rounded_rect(region.rect.size, region.radii, region.mode), || ());
 
             parent_clip_chain_index = self
                 .clip_store
                 .add_clip_chain_node(
                     handle,
                     region.rect.origin,
                     spatial_node,
@@ -1841,33 +1842,33 @@ impl<'a> DisplayListFlattener<'a> {
                                 Some(composite_mode),
                                 Picture3DContext::Out,
                                 pipeline_id,
                                 None,
                                 is_passthrough,
                                 raster_space,
                                 PrimitiveList::new(
                                     prims,
-                                    &self.interners,
+                                    &self.resources,
                                 ),
                                 pending_shadow.clip_and_scroll.spatial_node_index,
                                 max_clip,
                                 &self.clip_store,
                                 None,
                             ))
                         );
 
                         let shadow_pic_key = PictureKey::new(
                             true,
                             LayoutSize::zero(),
                             Picture { composite_mode_key },
                         );
 
-                        let shadow_prim_data_handle = self.interners
-                            .picture
+                        let shadow_prim_data_handle = self.resources
+                            .picture_interner
                             .intern(&shadow_pic_key, || {
                                 PrimitiveSceneData {
                                     prim_size: LayoutSize::zero(),
                                     is_backface_visible: true,
                                 }
                             }
                         );
 
@@ -1913,17 +1914,17 @@ impl<'a> DisplayListFlattener<'a> {
         &mut self,
         pending_shadow: &PendingShadow,
         pending_primitive: &PendingPrimitive<P>,
         prims: &mut Vec<PrimitiveInstance>,
     )
     where
         P: Internable<InternData=PrimitiveSceneData> + CreateShadow,
         P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
-        Interners: InternerMut<P>,
+        DocumentResources: InternerMut<P>,
     {
         // Offset the local rect and clip rect by the shadow offset.
         let mut info = pending_primitive.info.clone();
         info.rect = info.rect.translate(&pending_shadow.shadow.offset);
         info.clip_rect = info.clip_rect.translate(&pending_shadow.shadow.offset);
 
         // Construct and add a primitive for the given shadow.
         let shadow_prim_instance = self.create_primitive(
@@ -1938,17 +1939,17 @@ impl<'a> DisplayListFlattener<'a> {
         // Add the new primitive to the shadow picture.
         prims.push(shadow_prim_instance);
     }
 
     fn add_shadow_prim_to_draw_list<P>(&mut self, pending_primitive: PendingPrimitive<P>)
     where
         P: Internable<InternData = PrimitiveSceneData> + IsVisible,
         P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
-        Interners: InternerMut<P>,
+        DocumentResources: InternerMut<P>,
     {
         // For a normal primitive, if it has alpha > 0, then we add this
         // as a normal primitive to the parent picture.
         if pending_primitive.prim.is_visible() {
             self.add_prim_to_draw_list(
                 &pending_primitive.info,
                 pending_primitive.clip_and_scroll.clip_chain_id,
                 pending_primitive.clip_and_scroll,
@@ -2588,17 +2589,17 @@ impl FlattenedStackingContext {
         true
     }
 
     /// For a Preserve3D context, cut the sequence of the immediate flat children
     /// recorded so far and generate a picture from them.
     pub fn cut_flat_item_sequence(
         &mut self,
         prim_store: &mut PrimitiveStore,
-        interners: &mut Interners,
+        resources: &mut DocumentResources,
         clip_store: &ClipStore,
     ) -> Option<PrimitiveInstance> {
         if !self.is_3d() || self.primitives.is_empty() {
             return None
         }
         let flat_items_context_3d = match self.context_3d {
             Picture3DContext::In { ancestor_index, .. } => Picture3DContext::In {
                 root_data: None,
@@ -2613,32 +2614,32 @@ impl FlattenedStackingContext {
                 Some(PictureCompositeMode::Blit),
                 flat_items_context_3d,
                 self.pipeline_id,
                 None,
                 true,
                 self.requested_raster_space,
                 PrimitiveList::new(
                     mem::replace(&mut self.primitives, Vec::new()),
-                    interners,
+                    resources,
                 ),
                 self.spatial_node_index,
                 LayoutRect::max_rect(),
                 clip_store,
                 None,
             ))
         );
 
         let prim_instance = create_prim_instance(
             pic_index,
             PictureCompositeKey::Identity,
             self.is_backface_visible,
             self.clip_chain_id,
             self.spatial_node_index,
-            interners,
+            resources,
         );
 
         Some(prim_instance)
     }
 }
 
 /// A primitive that is added while a shadow context is
 /// active is stored as a pending primitive and only
@@ -2696,26 +2697,26 @@ impl From<PendingPrimitive<TextRun>> for
 }
 
 fn create_prim_instance(
     pic_index: PictureIndex,
     composite_mode_key: PictureCompositeKey,
     is_backface_visible: bool,
     clip_chain_id: ClipChainId,
     spatial_node_index: SpatialNodeIndex,
-    interners: &mut Interners,
+    resources: &mut DocumentResources,
 ) -> PrimitiveInstance {
     let pic_key = PictureKey::new(
         is_backface_visible,
         LayoutSize::zero(),
         Picture { composite_mode_key },
     );
 
-    let data_handle = interners
-        .picture
+    let data_handle = resources
+        .picture_interner
         .intern(&pic_key, || {
             PrimitiveSceneData {
                 prim_size: LayoutSize::zero(),
                 is_backface_visible,
             }
         }
     );
 
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -13,17 +13,17 @@ use gpu_types::{PrimitiveHeaders, Transf
 use hit_test::{HitTester, HitTestingRun};
 use internal_types::{FastHashMap, PlaneSplitter};
 use picture::{PictureSurface, PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
 use picture::{RetainedTiles, TileCache};
 use prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer};
 #[cfg(feature = "replay")]
 use prim_store::{PrimitiveStoreStats};
 use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
-use render_backend::{DataStores, FrameStamp};
+use render_backend::{FrameResources, FrameStamp};
 use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
 use resource_cache::{ResourceCache};
 use scene::{ScenePipeline, SceneProperties};
 use segment::SegmentBuilder;
 use spatial_node::SpatialNode;
 use std::{f32, mem};
 use std::sync::Arc;
 use tiling::{Frame, RenderPass, RenderPassKind, RenderTargetContext, RenderTarget};
@@ -81,17 +81,17 @@ pub struct FrameVisibilityContext<'a> {
 
 pub struct FrameVisibilityState<'a> {
     pub clip_store: &'a mut ClipStore,
     pub resource_cache: &'a mut ResourceCache,
     pub gpu_cache: &'a mut GpuCache,
     pub scratch: &'a mut PrimitiveScratchBuffer,
     pub tile_cache: Option<TileCache>,
     pub retained_tiles: &'a mut RetainedTiles,
-    pub data_stores: &'a mut DataStores,
+    pub resources: &'a mut FrameResources,
 }
 
 pub struct FrameBuildingContext<'a> {
     pub device_pixel_scale: DevicePixelScale,
     pub scene_properties: &'a SceneProperties,
     pub pipelines: &'a FastHashMap<PipelineId, Arc<ScenePipeline>>,
     pub screen_world_rect: WorldRect,
     pub clip_scroll_tree: &'a ClipScrollTree,
@@ -239,17 +239,17 @@ impl FrameBuilder {
         pipelines: &FastHashMap<PipelineId, Arc<ScenePipeline>>,
         resource_cache: &mut ResourceCache,
         gpu_cache: &mut GpuCache,
         render_tasks: &mut RenderTaskTree,
         profile_counters: &mut FrameProfileCounters,
         device_pixel_scale: DevicePixelScale,
         scene_properties: &SceneProperties,
         transform_palette: &mut TransformPalette,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         surfaces: &mut Vec<SurfaceInfo>,
         scratch: &mut PrimitiveScratchBuffer,
         debug_flags: DebugFlags,
     ) -> Option<RenderTaskId> {
         profile_scope!("cull");
 
         if self.prim_store.pictures.is_empty() {
             return None
@@ -300,17 +300,17 @@ impl FrameBuilder {
         // set up render tasks, determine scaling of surfaces, and detect
         // which surfaces have valid cached surfaces that don't need to
         // be rendered this frame.
         self.prim_store.update_picture(
             self.root_pic_index,
             &mut pic_update_state,
             &frame_context,
             gpu_cache,
-            data_stores,
+            resources,
             &self.clip_store,
         );
 
         {
             let visibility_context = FrameVisibilityContext {
                 device_pixel_scale,
                 clip_scroll_tree,
                 screen_world_rect,
@@ -321,17 +321,17 @@ impl FrameBuilder {
 
             let mut visibility_state = FrameVisibilityState {
                 resource_cache,
                 gpu_cache,
                 clip_store: &mut self.clip_store,
                 scratch,
                 tile_cache: None,
                 retained_tiles: &mut retained_tiles,
-                data_stores,
+                resources,
             };
 
             self.prim_store.update_visibility(
                 self.root_pic_index,
                 ROOT_SURFACE_INDEX,
                 &visibility_context,
                 &mut visibility_state,
             );
@@ -364,17 +364,17 @@ impl FrameBuilder {
             .unwrap();
 
         self.prim_store.prepare_primitives(
             &mut prim_list,
             &pic_context,
             &mut pic_state,
             &frame_context,
             &mut frame_state,
-            data_stores,
+            resources,
             scratch,
         );
 
         let pic = &mut self.prim_store.pictures[self.root_pic_index.0];
         pic.restore_context(
             prim_list,
             pic_context,
             pic_state,
@@ -412,17 +412,17 @@ impl FrameBuilder {
         clip_scroll_tree: &mut ClipScrollTree,
         pipelines: &FastHashMap<PipelineId, Arc<ScenePipeline>>,
         device_pixel_scale: DevicePixelScale,
         layer: DocumentLayer,
         pan: WorldPoint,
         texture_cache_profile: &mut TextureCacheProfileCounters,
         gpu_cache_profile: &mut GpuCacheProfileCounters,
         scene_properties: &SceneProperties,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         scratch: &mut PrimitiveScratchBuffer,
         debug_flags: DebugFlags,
     ) -> Frame {
         profile_scope!("build");
         debug_assert!(
             DeviceIntRect::new(DeviceIntPoint::zero(), self.window_size)
                 .contains_rect(&self.screen_rect)
         );
@@ -453,17 +453,17 @@ impl FrameBuilder {
             pipelines,
             resource_cache,
             gpu_cache,
             &mut render_tasks,
             &mut profile_counters,
             device_pixel_scale,
             scene_properties,
             &mut transform_palette,
-            data_stores,
+            resources,
             &mut surfaces,
             scratch,
             debug_flags,
         );
 
         resource_cache.block_until_all_resources_added(gpu_cache,
                                                        &mut render_tasks,
                                                        texture_cache_profile);
@@ -507,17 +507,17 @@ impl FrameBuilder {
 
         for pass in &mut passes {
             let mut ctx = RenderTargetContext {
                 device_pixel_scale,
                 prim_store: &self.prim_store,
                 resource_cache,
                 use_dual_source_blending,
                 clip_scroll_tree,
-                data_stores,
+                resources,
                 surfaces: &surfaces,
                 scratch,
             };
 
             pass.build(
                 &mut ctx,
                 gpu_cache,
                 &mut render_tasks,
deleted file mode 100644
--- a/gfx/wr/webrender/src/intern_types.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-macro_rules! common {
-    () => (
-        use ::intern;
-        #[allow(unused_imports)]
-        use ::prim_store::PrimitiveSceneData;
-        #[cfg_attr(feature = "capture", derive(Serialize))]
-        #[cfg_attr(feature = "replay", derive(Deserialize))]
-        #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
-        pub struct Marker;
-        pub type Handle = intern::Handle<Marker>;
-    )
-}
-
-pub mod clip {
-common!();
-use ::clip::{ClipItemKey, ClipNode};
-pub type Store = intern::DataStore<ClipItemKey, ClipNode, Marker>;
-pub type UpdateList = intern::UpdateList<ClipItemKey>;
-pub type Interner = intern::Interner<ClipItemKey, (), Marker>;
-}
-
-pub mod prim {
-common!();
-use ::prim_store::{PrimitiveKey, PrimitiveTemplate};
-pub type Store = intern::DataStore<PrimitiveKey, PrimitiveTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<PrimitiveKey>;
-pub type Interner = intern::Interner<PrimitiveKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod normal_border {
-common!();
-use ::prim_store::borders::{NormalBorderKey, NormalBorderTemplate};
-pub type Store = intern::DataStore<NormalBorderKey, NormalBorderTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<NormalBorderKey>;
-pub type Interner = intern::Interner<NormalBorderKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod image_border {
-common!();
-use ::prim_store::borders::{ImageBorderKey, ImageBorderTemplate};
-pub type Store = intern::DataStore<ImageBorderKey, ImageBorderTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<ImageBorderKey>;
-pub type Interner = intern::Interner<ImageBorderKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod image {
-common!();
-use ::prim_store::image::{ImageKey, ImageTemplate};
-pub type Store = intern::DataStore<ImageKey, ImageTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<ImageKey>;
-pub type Interner = intern::Interner<ImageKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod yuv_image {
-common!();
-use ::prim_store::image::{YuvImageKey, YuvImageTemplate};
-pub type Store = intern::DataStore<YuvImageKey, YuvImageTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<YuvImageKey>;
-pub type Interner = intern::Interner<YuvImageKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod line_decoration {
-use ::prim_store::line_dec::{LineDecorationKey, LineDecorationTemplate};
-common!();
-pub type Store = intern::DataStore<LineDecorationKey, LineDecorationTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<LineDecorationKey>;
-pub type Interner = intern::Interner<LineDecorationKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod linear_grad {
-common!();
-use ::prim_store::gradient::{LinearGradientKey, LinearGradientTemplate};
-pub type Store = intern::DataStore<LinearGradientKey, LinearGradientTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<LinearGradientKey>;
-pub type Interner = intern::Interner<LinearGradientKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod radial_grad {
-common!();
-use ::prim_store::gradient::{RadialGradientKey, RadialGradientTemplate};
-pub type Store = intern::DataStore<RadialGradientKey, RadialGradientTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<RadialGradientKey>;
-pub type Interner = intern::Interner<RadialGradientKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod picture {
-common!();
-use ::prim_store::picture::{PictureKey, PictureTemplate};
-pub type Store = intern::DataStore<PictureKey, PictureTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<PictureKey>;
-pub type Interner = intern::Interner<PictureKey, PrimitiveSceneData, Marker>;
-}
-
-pub mod text_run {
-common!();
-use ::prim_store::text_run::{TextRunKey, TextRunTemplate};
-pub type Store = intern::DataStore<TextRunKey, TextRunTemplate, Marker>;
-pub type UpdateList = intern::UpdateList<TextRunKey>;
-pub type Interner = intern::Interner<TextRunKey, PrimitiveSceneData, Marker>;
-}
-
-
-
--- a/gfx/wr/webrender/src/lib.rs
+++ b/gfx/wr/webrender/src/lib.rs
@@ -95,17 +95,16 @@ mod glyph_cache;
 mod glyph_rasterizer;
 mod gpu_cache;
 #[cfg(feature = "pathfinder")]
 mod gpu_glyph_renderer;
 mod gpu_types;
 mod hit_test;
 mod image;
 mod intern;
-mod intern_types;
 mod internal_types;
 mod picture;
 mod prim_store;
 mod print_tree;
 mod profiler;
 mod record;
 mod render_backend;
 mod render_task;
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -22,22 +22,22 @@ use internal_types::{FastHashMap, FastHa
 use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext};
 use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
 use gpu_types::{TransformPalette, TransformPaletteId, UvRectKind};
 use plane_split::{Clipper, Polygon, Splitter};
 use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, VisibleFace, PrimitiveInstanceKind};
 use prim_store::{get_raster_rects, PrimitiveScratchBuffer, VectorKey, PointKey};
 use prim_store::{OpacityBindingStorage, ImageInstanceStorage, OpacityBindingIndex, RectangleKey};
 use print_tree::PrintTreePrinter;
-use render_backend::DataStores;
+use render_backend::FrameResources;
 use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
 use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
 use resource_cache::ResourceCache;
 use scene::{FilterOpHelpers, SceneProperties};
-use scene_builder::Interners;
+use scene_builder::DocumentResources;
 use smallvec::SmallVec;
 use surface::{SurfaceDescriptor};
 use std::{mem, u16};
 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 use texture_cache::{Eviction, TextureCacheHandle};
 use tiling::RenderTargetKind;
 use util::{ComparableVec, TransformedRectKind, MatrixHelpers, MaxRect};
 
@@ -810,33 +810,33 @@ impl TileCache {
         }
     }
 
     /// Update the dependencies for each tile for a given primitive instance.
     pub fn update_prim_dependencies(
         &mut self,
         prim_instance: &PrimitiveInstance,
         clip_scroll_tree: &ClipScrollTree,
-        data_stores: &DataStores,
+        resources: &FrameResources,
         clip_chain_nodes: &[ClipChainNode],
         pictures: &[PicturePrimitive],
         resource_cache: &ResourceCache,
         opacity_binding_store: &OpacityBindingStorage,
         image_instances: &ImageInstanceStorage,
     ) {
         if !self.needs_update {
             return;
         }
 
         self.map_local_to_world.set_target_spatial_node(
             prim_instance.spatial_node_index,
             clip_scroll_tree,
         );
 
-        let prim_data = &data_stores.as_common_data(&prim_instance);
+        let prim_data = &resources.as_common_data(&prim_instance);
 
         let prim_rect = match prim_instance.kind {
             PrimitiveInstanceKind::Picture { pic_index, .. } => {
                 let pic = &pictures[pic_index.0];
                 pic.local_rect
             }
             _ => {
                 LayoutRect::new(
@@ -872,17 +872,17 @@ impl TileCache {
 
         // TODO(gw): We only care about world clip rects that don't have the main
         //           scroll root as an ancestor. It may be a worthwhile optimization
         //           to check for these and skip them.
         let mut world_clips: SmallVec<[(RectangleKey, SpatialNodeIndex); 4]> = SmallVec::default();
 
         // Some primitives can not be cached (e.g. external video images)
         let is_cacheable = prim_instance.is_cacheable(
-            &data_stores,
+            &resources,
             resource_cache,
         );
 
         // For pictures, we don't (yet) know the valid clip rect, so we can't correctly
         // use it to calculate the local bounding rect for the tiles. If we include them
         // then we may calculate a bounding rect that is too large, since it won't include
         // the clip bounds of the picture. Excluding them from the bounding rect here
         // fixes any correctness issues (the clips themselves are considered when we
@@ -908,32 +908,32 @@ impl TileCache {
                     for binding in &opacity_binding.bindings {
                         opacity_bindings.push(OpacityBinding::from(*binding));
                     }
                 }
 
                 true
             }
             PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
-                let image_data = &data_stores.image[data_handle].kind;
+                let image_data = &resources.image_data_store[data_handle].kind;
                 let image_instance = &image_instances[image_instance_index];
                 let opacity_binding_index = image_instance.opacity_binding_index;
 
                 if opacity_binding_index != OpacityBindingIndex::INVALID {
                     let opacity_binding = &opacity_binding_store[opacity_binding_index];
                     for binding in &opacity_binding.bindings {
                         opacity_bindings.push(OpacityBinding::from(*binding));
                     }
                 }
 
                 image_keys.push(image_data.key);
                 true
             }
             PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
-                let yuv_image_data = &data_stores.yuv_image[data_handle].kind;
+                let yuv_image_data = &resources.yuv_image_data_store[data_handle].kind;
                 image_keys.extend_from_slice(&yuv_image_data.yuv_key);
                 true
             }
             PrimitiveInstanceKind::TextRun { .. } |
             PrimitiveInstanceKind::LineDecoration { .. } |
             PrimitiveInstanceKind::Clear { .. } |
             PrimitiveInstanceKind::NormalBorder { .. } |
             PrimitiveInstanceKind::LinearGradient { .. } |
@@ -949,17 +949,17 @@ impl TileCache {
         let mut world_clip_rect = world_rect;
         let mut culling_rect = prim_rect
             .intersection(&prim_instance.local_clip_rect)
             .unwrap_or(LayoutRect::zero());
 
         let mut current_clip_chain_id = prim_instance.clip_chain_id;
         while current_clip_chain_id != ClipChainId::NONE {
             let clip_chain_node = &clip_chain_nodes[current_clip_chain_id.0 as usize];
-            let clip_node = &data_stores.clip[clip_chain_node.handle];
+            let clip_node = &resources.clip_data_store[clip_chain_node.handle];
 
             // We can skip the root clip node - it will be taken care of by the
             // world bounding rect calculated for the cache.
             if current_clip_chain_id == self.root_clip_chain_id {
                 current_clip_chain_id = clip_chain_node.parent_clip_chain_id;
                 continue;
             }
 
@@ -1629,17 +1629,17 @@ impl PrimitiveList {
     }
 
     /// Construct a new prim list from a list of instances
     /// in render order. This does some work during scene
     /// building which makes the frame building traversals
     /// significantly faster.
     pub fn new(
         mut prim_instances: Vec<PrimitiveInstance>,
-        interners: &Interners
+        resources: &DocumentResources
     ) -> Self {
         let mut pictures = SmallVec::new();
         let mut clusters_map = FastHashMap::default();
         let mut clusters: SmallVec<[PrimitiveCluster; 4]> = SmallVec::new();
 
         // Walk the list of primitive instances and extract any that
         // are pictures.
         for prim_instance in &mut prim_instances {
@@ -1653,44 +1653,44 @@ impl PrimitiveList {
                 _ => {
                     false
                 }
             };
 
             let prim_data = match prim_instance.kind {
                 PrimitiveInstanceKind::Rectangle { data_handle, .. } |
                 PrimitiveInstanceKind::Clear { data_handle, .. } => {
-                    &interners.prim[data_handle]
+                    &resources.prim_interner[data_handle]
                 }
                 PrimitiveInstanceKind::Image { data_handle, .. } => {
-                    &interners.image[data_handle]
+                    &resources.image_interner[data_handle]
                 }
                 PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
-                    &interners.image_border[data_handle]
+                    &resources.image_border_interner[data_handle]
                 }
                 PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
-                    &interners.line_decoration[data_handle]
+                    &resources.line_decoration_interner[data_handle]
                 }
                 PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
-                    &interners.linear_grad[data_handle]
+                    &resources.linear_grad_interner[data_handle]
                 }
                 PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
-                    &interners.normal_border[data_handle]
+                    &resources.normal_border_interner[data_handle]
                 }
                 PrimitiveInstanceKind::Picture { data_handle, .. } => {
-                    &interners.picture[data_handle]
+                    &resources.picture_interner[data_handle]
                 }
                 PrimitiveInstanceKind::RadialGradient { data_handle, ..} => {
-                    &interners.radial_grad[data_handle]
+                    &resources.radial_grad_interner[data_handle]
                 }
                 PrimitiveInstanceKind::TextRun { data_handle, .. } => {
-                    &interners.text_run[data_handle]
+                    &resources.text_run_interner[data_handle]
                 }
                 PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
-                    &interners.yuv_image[data_handle]
+                    &resources.yuv_image_interner[data_handle]
                 }
             };
 
             // Get the key for the cluster that this primitive should
             // belong to.
             let key = PrimitiveClusterKey {
                 spatial_node_index: prim_instance.spatial_node_index,
                 is_backface_visible: prim_data.is_backface_visible,
--- a/gfx/wr/webrender/src/prim_store/borders.rs
+++ b/gfx/wr/webrender/src/prim_store/borders.rs
@@ -8,17 +8,16 @@ use api::{
     Shadow
 };
 use border::create_border_segments;
 use border::NormalBorderAu;
 use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
 use frame_builder::{FrameBuildingState};
 use gpu_cache::GpuDataRequest;
 use intern;
-use intern_types;
 use prim_store::{
     BorderSegmentInfo, BrushSegment, NinePatchDescriptor, PrimKey,
     PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
     PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData,
     PrimitiveStore
 };
 use resource_cache::ImageRequest;
 use storage;
@@ -154,20 +153,28 @@ impl From<NormalBorderKey> for NormalBor
                 border_segments,
                 border,
                 widths,
             }
         }
     }
 }
 
-pub use intern_types::normal_border::Handle as NormalBorderDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct NormalBorderDataMarker;
+
+pub type NormalBorderDataStore = intern::DataStore<NormalBorderKey, NormalBorderTemplate, NormalBorderDataMarker>;
+pub type NormalBorderDataHandle = intern::Handle<NormalBorderDataMarker>;
+pub type NormalBorderDataUpdateList = intern::UpdateList<NormalBorderKey>;
+pub type NormalBorderDataInterner = intern::Interner<NormalBorderKey, PrimitiveSceneData, NormalBorderDataMarker>;
 
 impl intern::Internable for NormalBorderPrim {
-    type Marker = intern_types::normal_border::Marker;
+    type Marker = NormalBorderDataMarker;
     type Source = NormalBorderKey;
     type StoreData = NormalBorderTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
@@ -323,20 +330,28 @@ impl From<ImageBorderKey> for ImageBorde
             kind: ImageBorderData {
                 request: key.kind.request,
                 brush_segments,
             }
         }
     }
 }
 
-pub use intern_types::image_border::Handle as ImageBorderDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct ImageBorderDataMarker;
+
+pub type ImageBorderDataStore = intern::DataStore<ImageBorderKey, ImageBorderTemplate, ImageBorderDataMarker>;
+pub type ImageBorderDataHandle = intern::Handle<ImageBorderDataMarker>;
+pub type ImageBorderDataUpdateList = intern::UpdateList<ImageBorderKey>;
+pub type ImageBorderDataInterner = intern::Interner<ImageBorderKey, PrimitiveSceneData, ImageBorderDataMarker>;
 
 impl intern::Internable for ImageBorder {
-    type Marker = intern_types::image_border::Marker;
+    type Marker = ImageBorderDataMarker;
     type Source = ImageBorderKey;
     type StoreData = ImageBorderTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
--- a/gfx/wr/webrender/src/prim_store/gradient.rs
+++ b/gfx/wr/webrender/src/prim_store/gradient.rs
@@ -4,18 +4,17 @@
 
 use api::{
     ColorF, ColorU,ExtendMode, GradientStop, LayoutPoint, LayoutSize,
     LayoutPrimitiveInfo, PremultipliedColorF
 };
 use display_list_flattener::{AsInstanceKind, IsVisible};
 use frame_builder::FrameBuildingState;
 use gpu_cache::{GpuCacheHandle, GpuDataRequest};
-use intern::{Internable, InternDebug};
-use intern_types;
+use intern::{DataStore, Handle, Internable, InternDebug, Interner, UpdateList};
 use prim_store::{BrushSegment, GradientTileRange};
 use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
 use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
 use prim_store::{NinePatchDescriptor, PointKey, SizeKey};
 use std::{hash, ops::{Deref, DerefMut}, mem};
 use util::pack_as_float;
 
 /// A hashable gradient stop that can be used in primitive keys.
@@ -221,31 +220,39 @@ impl LinearGradientTemplate {
                 self.stops_opacity
             } else {
                PrimitiveOpacity::translucent()
             }
         }
     }
 }
 
-pub type LinearGradientDataHandle = intern_types::linear_grad::Handle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct LinearGradientDataMarker;
+
+pub type LinearGradientDataStore = DataStore<LinearGradientKey, LinearGradientTemplate, LinearGradientDataMarker>;
+pub type LinearGradientDataHandle = Handle<LinearGradientDataMarker>;
+pub type LinearGradientDataUpdateList = UpdateList<LinearGradientKey>;
+pub type LinearGradientDataInterner = Interner<LinearGradientKey, PrimitiveSceneData, LinearGradientDataMarker>;
 
 pub struct LinearGradient {
     pub extend_mode: ExtendMode,
     pub start_point: PointKey,
     pub end_point: PointKey,
     pub stretch_size: SizeKey,
     pub tile_spacing: SizeKey,
     pub stops: Vec<GradientStopKey>,
     pub reverse_stops: bool,
     pub nine_patch: Option<Box<NinePatchDescriptor>>,
 }
 
 impl Internable for LinearGradient {
-    type Marker = intern_types::linear_grad::Marker;
+    type Marker = LinearGradientDataMarker;
     type Source = LinearGradientKey;
     type StoreData = LinearGradientTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
@@ -440,30 +447,38 @@ impl RadialGradientTemplate {
                 &self.stops,
             );
         }
 
         self.opacity = PrimitiveOpacity::translucent();
     }
 }
 
-pub type RadialGradientDataHandle = intern_types::radial_grad::Handle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct RadialGradientDataMarker;
+
+pub type RadialGradientDataStore = DataStore<RadialGradientKey, RadialGradientTemplate, RadialGradientDataMarker>;
+pub type RadialGradientDataHandle = Handle<RadialGradientDataMarker>;
+pub type RadialGradientDataUpdateList = UpdateList<RadialGradientKey>;
+pub type RadialGradientDataInterner = Interner<RadialGradientKey, PrimitiveSceneData, RadialGradientDataMarker>;
 
 pub struct RadialGradient {
     pub extend_mode: ExtendMode,
     pub center: PointKey,
     pub params: RadialGradientParams,
     pub stretch_size: SizeKey,
     pub stops: Vec<GradientStopKey>,
     pub tile_spacing: SizeKey,
     pub nine_patch: Option<Box<NinePatchDescriptor>>,
 }
 
 impl Internable for RadialGradient {
-    type Marker = intern_types::radial_grad::Marker;
+    type Marker = RadialGradientDataMarker;
     type Source = RadialGradientKey;
     type StoreData = RadialGradientTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
--- a/gfx/wr/webrender/src/prim_store/image.rs
+++ b/gfx/wr/webrender/src/prim_store/image.rs
@@ -6,18 +6,17 @@ use api::{
     AlphaType, ColorDepth, ColorF, ColorU, DeviceIntRect, DeviceIntSideOffsets,
     DeviceIntSize, ImageRendering, LayoutRect, LayoutSize, LayoutPrimitiveInfo,
     PremultipliedColorF, Shadow, TileOffset, YuvColorSpace, YuvFormat
 };
 use api::ImageKey as ApiImageKey;
 use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
 use frame_builder::FrameBuildingState;
 use gpu_cache::{GpuCacheHandle, GpuDataRequest};
-use intern::{Internable, InternDebug};
-use intern_types;
+use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
 use prim_store::{
     EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
     PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
     PrimTemplate, PrimTemplateCommonData, PrimitiveStore, SegmentInstanceIndex,
     SizeKey
 };
 use render_task::{
     BlitSource, RenderTask, RenderTaskCacheEntryHandle, RenderTaskCacheKey,
@@ -329,20 +328,28 @@ impl From<ImageKey> for ImageTemplate {
 
         ImageTemplate {
             common,
             kind: image.kind.into(),
         }
     }
 }
 
-pub use intern_types::image::Handle as ImageDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct ImageDataMarker;
+
+pub type ImageDataStore = DataStore<ImageKey, ImageTemplate, ImageDataMarker>;
+pub type ImageDataHandle = Handle<ImageDataMarker>;
+pub type ImageDataUpdateList = UpdateList<ImageKey>;
+pub type ImageDataInterner = Interner<ImageKey, PrimitiveSceneData, ImageDataMarker>;
 
 impl Internable for Image {
-    type Marker = intern_types::image::Marker;
+    type Marker = ImageDataMarker;
     type Source = ImageKey;
     type StoreData = ImageTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
@@ -495,20 +502,28 @@ impl From<YuvImageKey> for YuvImageTempl
 
         YuvImageTemplate {
             common,
             kind: image.kind.into(),
         }
     }
 }
 
-pub use intern_types::yuv_image::Handle as YuvImageDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct YuvImageDataMarker;
+
+pub type YuvImageDataStore = DataStore<YuvImageKey, YuvImageTemplate, YuvImageDataMarker>;
+pub type YuvImageDataHandle = Handle<YuvImageDataMarker>;
+pub type YuvImageDataUpdateList = UpdateList<YuvImageKey>;
+pub type YuvImageDataInterner = Interner<YuvImageKey, PrimitiveSceneData, YuvImageDataMarker>;
 
 impl Internable for YuvImage {
-    type Marker = intern_types::yuv_image::Marker;
+    type Marker = YuvImageDataMarker;
     type Source = YuvImageKey;
     type StoreData = YuvImageTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
--- a/gfx/wr/webrender/src/prim_store/line_dec.rs
+++ b/gfx/wr/webrender/src/prim_store/line_dec.rs
@@ -6,17 +6,16 @@ use api::{
     ColorF, ColorU, LayoutPrimitiveInfo, LayoutSizeAu,
     LineOrientation, LineStyle, PremultipliedColorF, Shadow,
 };
 use app_units::Au;
 use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
 use frame_builder::{FrameBuildingState};
 use gpu_cache::GpuDataRequest;
 use intern;
-use intern_types;
 use prim_store::{
     PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
     PrimitiveSceneData, PrimitiveStore,
 };
 use prim_store::PrimitiveInstanceKind;
 
 #[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
@@ -129,20 +128,28 @@ impl From<LineDecorationKey> for LineDec
             kind: LineDecorationData {
                 cache_key: line_dec.kind.cache_key,
                 color: line_dec.kind.color.into(),
             }
         }
     }
 }
 
-pub use intern_types::line_decoration::Handle as LineDecorationDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct LineDecorationDataMarker;
+
+pub type LineDecorationDataStore = intern::DataStore<LineDecorationKey, LineDecorationTemplate, LineDecorationDataMarker>;
+pub type LineDecorationDataHandle = intern::Handle<LineDecorationDataMarker>;
+pub type LineDecorationDataUpdateList = intern::UpdateList<LineDecorationKey>;
+pub type LineDecorationDataInterner = intern::Interner<LineDecorationKey, PrimitiveSceneData, LineDecorationDataMarker>;
 
 impl intern::Internable for LineDecoration {
-    type Marker = intern_types::line_decoration::Marker;
+    type Marker = LineDecorationDataMarker;
     type Source = LineDecorationKey;
     type StoreData = LineDecorationTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -36,17 +36,17 @@ use picture::{ClusterIndex, PrimitiveLis
 use prim_store::borders::{ImageBorderDataHandle, NormalBorderDataHandle};
 use prim_store::gradient::{LinearGradientDataHandle, RadialGradientDataHandle};
 use prim_store::image::{ImageDataHandle, ImageInstance, VisibleImageTile, YuvImageDataHandle};
 use prim_store::line_dec::LineDecorationDataHandle;
 use prim_store::picture::PictureDataHandle;
 use prim_store::text_run::{TextRunDataHandle, TextRunPrimitive};
 #[cfg(debug_assertions)]
 use render_backend::{FrameId};
-use render_backend::DataStores;
+use render_backend::FrameResources;
 use render_task::{RenderTask, RenderTaskCacheKey, to_cache_size};
 use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskCacheEntryHandle};
 use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
 use resource_cache::{ImageProperties, ImageRequest};
 use scene::SceneProperties;
 use segment::SegmentBuilder;
 use std::{cmp, fmt, hash, ops, u32, usize, mem};
 #[cfg(debug_assertions)]
@@ -816,35 +816,44 @@ impl PrimitiveTemplate {
             }
             PrimitiveTemplateKind::Rectangle { ref color, .. } => {
                 PrimitiveOpacity::from_alpha(color.a)
             }
         };
     }
 }
 
+// Type definitions for interning primitives.
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct PrimitiveDataMarker;
+
 impl intern::Internable for PrimitiveKeyKind {
-    type Marker = ::intern_types::prim::Marker;
+    type Marker = PrimitiveDataMarker;
     type Source = PrimitiveKey;
     type StoreData = PrimitiveTemplate;
     type InternData = PrimitiveSceneData;
 
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
     ) -> PrimitiveKey {
         PrimitiveKey::new(
             info.is_backface_visible,
             info.rect.size,
             self,
         )
     }
 }
 
-use intern_types::prim::Handle as PrimitiveDataHandle;
+pub type PrimitiveDataStore = intern::DataStore<PrimitiveKey, PrimitiveTemplate, PrimitiveDataMarker>;
+pub type PrimitiveDataHandle = intern::Handle<PrimitiveDataMarker>;
+pub type PrimitiveDataUpdateList = intern::UpdateList<PrimitiveKey>;
+pub type PrimitiveDataInterner = intern::Interner<PrimitiveKey, PrimitiveSceneData, PrimitiveDataMarker>;
 
 // Maintains a list of opacity bindings that have been collapsed into
 // the color of a single primitive. This is an important optimization
 // that avoids allocating an intermediate surface for most common
 // uses of opacity filters.
 #[derive(Debug)]
 pub struct OpacityBinding {
     pub bindings: Vec<PropertyBinding<f32>>,
@@ -1723,30 +1732,30 @@ impl PrimitiveStore {
     /// rasterization roots, and (in future) whether there
     /// are cached surfaces that can be used by this picture.
     pub fn update_picture(
         &mut self,
         pic_index: PictureIndex,
         state: &mut PictureUpdateState,
         frame_context: &FrameBuildingContext,
         gpu_cache: &mut GpuCache,
-        data_stores: &DataStores,
+        resources: &FrameResources,
         clip_store: &ClipStore,
     ) {
         if let Some(children) = self.pictures[pic_index.0].pre_update(
             state,
             frame_context,
         ) {
             for child_pic_index in &children {
                 self.update_picture(
                     *child_pic_index,
                     state,
                     frame_context,
                     gpu_cache,
-                    data_stores,
+                    resources,
                     clip_store,
                 );
             }
 
             self.pictures[pic_index.0].post_update(
                 children,
                 state,
                 frame_context,
@@ -1863,17 +1872,17 @@ impl PrimitiveStore {
                         } else {
                             None
                         }
                     });
 
                     (pic.raster_config.is_none(), pic.local_rect, clip_node_collector)
                 }
                 _ => {
-                    let prim_data = &frame_state.data_stores.as_common_data(&prim_instance);
+                    let prim_data = &frame_state.resources.as_common_data(&prim_instance);
 
                     let prim_rect = LayoutRect::new(
                         prim_instance.prim_origin,
                         prim_data.prim_size,
                     );
 
                     (false, prim_rect, None)
                 }
@@ -1929,24 +1938,24 @@ impl PrimitiveStore {
                         &map_local_to_surface,
                         &map_surface_to_world,
                         &frame_context.clip_scroll_tree,
                         frame_state.gpu_cache,
                         frame_state.resource_cache,
                         frame_context.device_pixel_scale,
                         &frame_context.screen_world_rect,
                         clip_node_collector.as_ref(),
-                        &mut frame_state.data_stores.clip,
+                        &mut frame_state.resources.clip_data_store,
                     );
 
                 if let Some(ref mut tile_cache) = frame_state.tile_cache {
                     tile_cache.update_prim_dependencies(
                         prim_instance,
                         frame_context.clip_scroll_tree,
-                        frame_state.data_stores,
+                        frame_state.resources,
                         &frame_state.clip_store.clip_chain_nodes,
                         &self.pictures,
                         frame_state.resource_cache,
                         &self.opacity_bindings,
                         &self.images,
                     );
                 }
 
@@ -2177,17 +2186,17 @@ impl PrimitiveStore {
         &mut self,
         prim_instance: &mut PrimitiveInstance,
         prim_context: &PrimitiveContext,
         pic_context: &PictureContext,
         pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         plane_split_anchor: usize,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         scratch: &mut PrimitiveScratchBuffer,
     ) -> bool {
         // If we have dependencies, we need to prepare them first, in order
         // to know the actual rect of this primitive.
         // For example, scrolling may affect the location of an item in
         // local space, which may force us to render this item on a larger
         // picture target, if being composited.
         let pic_info = {
@@ -2236,17 +2245,17 @@ impl PrimitiveStore {
                 let is_passthrough = pic_context_for_children.is_passthrough;
 
                 self.prepare_primitives(
                     &mut prim_list,
                     &pic_context_for_children,
                     &mut pic_state_for_children,
                     frame_context,
                     frame_state,
-                    data_stores,
+                    resources,
                     scratch,
                 );
 
                 if !pic_state_for_children.is_cacheable {
                     pic_state.is_cacheable = false;
                 }
 
                 // Restore the dependencies (borrow check dance)
@@ -2268,32 +2277,32 @@ impl PrimitiveStore {
             prim_instance.update_clip_task(
                 prim_context,
                 pic_context.raster_spatial_node_index,
                 pic_context,
                 pic_state,
                 frame_context,
                 frame_state,
                 self,
-                data_stores,
+                resources,
                 scratch,
             );
 
             if prim_instance.is_chased() {
                 println!("\tconsidered visible and ready with local pos {:?}", prim_instance.prim_origin);
             }
         }
 
         #[cfg(debug_assertions)]
         {
             prim_instance.prepared_frame_id = frame_state.render_tasks.frame_id();
         }
 
         pic_state.is_cacheable &= prim_instance.is_cacheable(
-            &data_stores,
+            &resources,
             frame_state.resource_cache,
         );
 
         match prim_instance.kind {
             PrimitiveInstanceKind::Picture { pic_index, .. } => {
                 let pic = &mut self.pictures[pic_index.0];
                 let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
                 if pic.prepare_for_render(
@@ -2341,33 +2350,33 @@ impl PrimitiveStore {
             PrimitiveInstanceKind::RadialGradient { .. } |
             PrimitiveInstanceKind::LineDecoration { .. } => {
                 self.prepare_interned_prim_for_render(
                     prim_instance,
                     prim_context,
                     pic_context,
                     frame_context,
                     frame_state,
-                    data_stores,
+                    resources,
                     scratch,
                 );
             }
         }
 
         true
     }
 
     pub fn prepare_primitives(
         &mut self,
         prim_list: &mut PrimitiveList,
         pic_context: &PictureContext,
         pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         scratch: &mut PrimitiveScratchBuffer,
     ) {
         for (plane_split_anchor, prim_instance) in prim_list.prim_instances.iter_mut().enumerate() {
             if prim_instance.visibility_info == PrimitiveVisibilityIndex::INVALID {
                 continue;
             }
 
             // The original clipped world rect was calculated during the initial visibility pass.
@@ -2409,17 +2418,17 @@ impl PrimitiveStore {
             if self.prepare_prim_for_render(
                 prim_instance,
                 &prim_context,
                 pic_context,
                 pic_state,
                 frame_context,
                 frame_state,
                 plane_split_anchor,
-                data_stores,
+                resources,
                 scratch,
             ) {
                 frame_state.profile_counters.visible_primitives.inc();
             }
         }
     }
 
     /// Prepare an interned primitive for rendering, by requesting
@@ -2427,24 +2436,24 @@ impl PrimitiveStore {
     /// prepare_prim_for_render_inner call for old style primitives.
     fn prepare_interned_prim_for_render(
         &mut self,
         prim_instance: &mut PrimitiveInstance,
         prim_context: &PrimitiveContext,
         pic_context: &PictureContext,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         scratch: &mut PrimitiveScratchBuffer,
     ) {
         let is_chased = prim_instance.is_chased();
 
         match &mut prim_instance.kind {
             PrimitiveInstanceKind::LineDecoration { data_handle, ref mut cache_handle, .. } => {
-                let prim_data = &mut data_stores.line_decoration[*data_handle];
+                let prim_data = &mut resources.line_decoration_data_store[*data_handle];
                 let common_data = &mut prim_data.common;
                 let line_dec_data = &mut prim_data.kind;
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 line_dec_data.update(common_data, frame_state);
 
                 // Work out the device pixel size to be used to cache this line decoration.
@@ -2483,17 +2492,17 @@ impl PrimitiveStore {
                                 LayoutSize::from_au(cache_key.size),
                             );
                             render_tasks.add(task)
                         }
                     ));
                 }
             }
             PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
-                let prim_data = &mut data_stores.text_run[*data_handle];
+                let prim_data = &mut resources.text_run_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 prim_data.update(frame_state);
 
                 // The transform only makes sense for screen space rasterization
                 let transform = prim_context.spatial_node.world_content_transform.to_transform();
                 let prim_offset = prim_instance.prim_origin.to_vector() - prim_data.offset;
@@ -2512,24 +2521,24 @@ impl PrimitiveStore {
                     pic_context,
                     frame_state.resource_cache,
                     frame_state.gpu_cache,
                     frame_state.render_tasks,
                     scratch,
                 );
             }
             PrimitiveInstanceKind::Clear { data_handle, .. } => {
-                let prim_data = &mut data_stores.prim[*data_handle];
+                let prim_data = &mut resources.prim_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 prim_data.update(frame_state);
             }
             PrimitiveInstanceKind::NormalBorder { data_handle, ref mut cache_handles, .. } => {
-                let prim_data = &mut data_stores.normal_border[*data_handle];
+                let prim_data = &mut resources.normal_border_data_store[*data_handle];
                 let common_data = &mut prim_data.common;
                 let border_data = &mut prim_data.kind;
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 border_data.update(common_data, frame_state);
 
                 // TODO(gw): When drawing in screen raster mode, we should also incorporate a
@@ -2576,24 +2585,24 @@ impl PrimitiveStore {
                     ));
                 }
 
                 *cache_handles = scratch
                     .border_cache_handles
                     .extend(handles);
             }
             PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
-                let prim_data = &mut data_stores.image_border[*data_handle];
+                let prim_data = &mut resources.image_border_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 prim_data.kind.update(&mut prim_data.common, frame_state);
             }
             PrimitiveInstanceKind::Rectangle { data_handle, segment_instance_index, opacity_binding_index, .. } => {
-                let prim_data = &mut data_stores.prim[*data_handle];
+                let prim_data = &mut resources.prim_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 prim_data.update(frame_state);
 
                 update_opacity_binding(
                     &mut self.opacity_bindings,
                     *opacity_binding_index,
@@ -2602,28 +2611,28 @@ impl PrimitiveStore {
 
                 write_segment(*segment_instance_index, frame_state, scratch, |request| {
                     prim_data.kind.write_prim_gpu_blocks(
                         request,
                     );
                 });
             }
             PrimitiveInstanceKind::YuvImage { data_handle, segment_instance_index, .. } => {
-                let yuv_image_data = &mut data_stores.yuv_image[*data_handle];
+                let yuv_image_data = &mut resources.yuv_image_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 yuv_image_data.kind.update(&mut yuv_image_data.common, frame_state);
 
                 write_segment(*segment_instance_index, frame_state, scratch, |request| {
                     yuv_image_data.kind.write_prim_gpu_blocks(request);
                 });
             }
             PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
-                let prim_data = &mut data_stores.image[*data_handle];
+                let prim_data = &mut resources.image_data_store[*data_handle];
                 let common_data = &mut prim_data.common;
                 let image_data = &mut prim_data.kind;
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 image_data.update(common_data, frame_state);
 
                 let image_instance = &mut self.images[*image_instance_index];
@@ -2727,17 +2736,17 @@ impl PrimitiveStore {
                     }
                 }
 
                 write_segment(image_instance.segment_instance_index, frame_state, scratch, |request| {
                     image_data.write_prim_gpu_blocks(request);
                 });
             }
             PrimitiveInstanceKind::LinearGradient { data_handle, ref mut visible_tiles_range, .. } => {
-                let prim_data = &mut data_stores.linear_grad[*data_handle];
+                let prim_data = &mut resources.linear_grad_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 prim_data.update(frame_state);
 
                 if prim_data.tile_spacing != LayoutSize::zero() {
                     let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
                     let prim_rect = LayoutRect::new(
@@ -2774,17 +2783,17 @@ impl PrimitiveStore {
                         prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
                     }
                 }
 
                 // TODO(gw): Consider whether it's worth doing segment building
                 //           for gradient primitives.
             }
             PrimitiveInstanceKind::RadialGradient { data_handle, ref mut visible_tiles_range, .. } => {
-                let prim_data = &mut data_stores.radial_grad[*data_handle];
+                let prim_data = &mut resources.radial_grad_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
                 prim_data.update(frame_state);
 
                 if prim_data.tile_spacing != LayoutSize::zero() {
                     let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
                     let prim_rect = LayoutRect::new(
@@ -2957,17 +2966,17 @@ impl<'a> GpuDataRequest<'a> {
 }
 
     fn write_brush_segment_description(
         prim_local_rect: LayoutRect,
         prim_local_clip_rect: LayoutRect,
         clip_chain: &ClipChainInstance,
         segment_builder: &mut SegmentBuilder,
         clip_store: &ClipStore,
-        data_stores: &DataStores,
+        resources: &FrameResources,
     ) -> bool {
         // If the brush is small, we generally want to skip building segments
         // and just draw it as a single primitive with clip mask. However,
         // if the clips are purely rectangles that have no per-fragment
         // clip masks, we will segment anyway. This allows us to completely
         // skip allocating a clip mask in these cases.
         let is_large = prim_local_rect.size.area() > MIN_BRUSH_SPLIT_AREA;
 
@@ -2982,17 +2991,17 @@ impl<'a> GpuDataRequest<'a> {
             prim_local_clip_rect
         );
 
         // Segment the primitive on all the local-space clip sources that we can.
         let mut local_clip_count = 0;
         for i in 0 .. clip_chain.clips_range.count {
             let clip_instance = clip_store
                 .get_instance_from_range(&clip_chain.clips_range, i);
-            let clip_node = &data_stores.clip[clip_instance.handle];
+            let clip_node = &resources.clip_data_store[clip_instance.handle];
 
             // If this clip item is positioned by another positioning node, its relative position
             // could change during scrolling. This means that we would need to resegment. Instead
             // of doing that, only segment with clips that have the same positioning node.
             // TODO(mrobinson, #2858): It may make sense to include these nodes, resegmenting only
             // when necessary while scrolling.
             if !clip_instance.flags.contains(ClipNodeFlags::SAME_SPATIAL_NODE) {
                 continue;
@@ -3087,33 +3096,33 @@ impl<'a> GpuDataRequest<'a> {
     }
 
 impl PrimitiveInstance {
     fn build_segments_if_needed(
         &mut self,
         prim_clip_chain: &ClipChainInstance,
         frame_state: &mut FrameBuildingState,
         prim_store: &mut PrimitiveStore,
-        data_stores: &DataStores,
+        resources: &FrameResources,
         segments_store: &mut SegmentStorage,
         segment_instances_store: &mut SegmentInstanceStorage,
     ) {
-        let prim_data = &data_stores.as_common_data(self);
+        let prim_data = &resources.as_common_data(self);
         let prim_local_rect = LayoutRect::new(
             self.prim_origin,
             prim_data.prim_size,
         );
 
         let segment_instance_index = match self.kind {
             PrimitiveInstanceKind::Rectangle { ref mut segment_instance_index, .. } |
             PrimitiveInstanceKind::YuvImage { ref mut segment_instance_index, .. } => {
                 segment_instance_index
             }
             PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
-                let image_data = &data_stores.image[data_handle].kind;
+                let image_data = &resources.image_data_store[data_handle].kind;
                 let image_instance = &mut prim_store.images[image_instance_index];
                 // tiled images don't support segmentation
                 if frame_state
                     .resource_cache
                     .get_image_properties(image_data.key)
                     .and_then(|properties| properties.tiling)
                     .is_some() {
                         image_instance.segment_instance_index = SegmentInstanceIndex::UNUSED;
@@ -3138,17 +3147,17 @@ impl PrimitiveInstance {
             let mut segments: SmallVec<[BrushSegment; 8]> = SmallVec::new();
 
             if write_brush_segment_description(
                 prim_local_rect,
                 self.local_clip_rect,
                 prim_clip_chain,
                 &mut frame_state.segment_builder,
                 frame_state.clip_store,
-                data_stores,
+                resources,
             ) {
                 frame_state.segment_builder.build(|segment| {
                     segments.push(
                         BrushSegment::new(
                             segment.rect.translate(&LayoutVector2D::new(-prim_local_rect.origin.x, -prim_local_rect.origin.y)),
                             segment.has_mask,
                             segment.edge_flags,
                             [0.0; 4],
@@ -3178,17 +3187,17 @@ impl PrimitiveInstance {
         prim_info: &mut PrimitiveVisibility,
         root_spatial_node_index: SpatialNodeIndex,
         prim_context: &PrimitiveContext,
         pic_context: &PictureContext,
         pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         prim_store: &PrimitiveStore,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         segments_store: &mut SegmentStorage,
         segment_instances_store: &mut SegmentInstanceStorage,
         clip_mask_instances: &mut Vec<ClipMaskKind>,
     ) -> bool {
         let segments = match self.kind {
             PrimitiveInstanceKind::Picture { .. } |
             PrimitiveInstanceKind::TextRun { .. } |
             PrimitiveInstanceKind::Clear { .. } |
@@ -3216,42 +3225,42 @@ impl PrimitiveInstance {
                     return false;
                 }
 
                 let segment_instance = &segment_instances_store[segment_instance_index];
 
                 &segments_store[segment_instance.segments_range]
             }
             PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
-                let border_data = &data_stores.image_border[data_handle].kind;
+                let border_data = &resources.image_border_data_store[data_handle].kind;
 
                 // TODO: This is quite messy - once we remove legacy primitives we
                 //       can change this to be a tuple match on (instance, template)
                 border_data.brush_segments.as_slice()
             }
             PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
-                let border_data = &data_stores.normal_border[data_handle].kind;
+                let border_data = &resources.normal_border_data_store[data_handle].kind;
 
                 // TODO: This is quite messy - once we remove legacy primitives we
                 //       can change this to be a tuple match on (instance, template)
                 border_data.brush_segments.as_slice()
             }
             PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
-                let prim_data = &data_stores.linear_grad[data_handle];
+                let prim_data = &resources.linear_grad_data_store[data_handle];
 
                 // TODO: This is quite messy - once we remove legacy primitives we
                 //       can change this to be a tuple match on (instance, template)
                 if prim_data.brush_segments.is_empty() {
                     return false;
                 }
 
                 prim_data.brush_segments.as_slice()
             }
             PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
-                let prim_data = &data_stores.radial_grad[data_handle];
+                let prim_data = &resources.radial_grad_data_store[data_handle];
 
                 // TODO: This is quite messy - once we remove legacy primitives we
                 //       can change this to be a tuple match on (instance, template)
                 if prim_data.brush_segments.is_empty() {
                     return false;
                 }
 
                 prim_data.brush_segments.as_slice()
@@ -3277,17 +3286,17 @@ impl PrimitiveInstance {
             let clip_mask_kind = segments[0].update_clip_task(
                 Some(&prim_info.clip_chain),
                 prim_info.clipped_world_rect,
                 root_spatial_node_index,
                 pic_context.surface_index,
                 pic_state,
                 frame_context,
                 frame_state,
-                &mut data_stores.clip,
+                &mut resources.clip_data_store,
             );
             clip_mask_instances.push(clip_mask_kind);
         } else {
             for segment in segments {
                 // Build a clip chain for the smaller segment rect. This will
                 // often manage to eliminate most/all clips, and sometimes
                 // clip the segment completely.
                 let segment_clip_chain = frame_state
@@ -3303,28 +3312,28 @@ impl PrimitiveInstance {
                         &pic_state.map_local_to_pic,
                         &pic_state.map_pic_to_world,
                         &frame_context.clip_scroll_tree,
                         frame_state.gpu_cache,
                         frame_state.resource_cache,
                         frame_context.device_pixel_scale,
                         &pic_context.dirty_world_rect,
                         None,
-                        &mut data_stores.clip,
+                        &mut resources.clip_data_store,
                     );
 
                 let clip_mask_kind = segment.update_clip_task(
                     segment_clip_chain.as_ref(),
                     prim_info.clipped_world_rect,
                     root_spatial_node_index,
                     pic_context.surface_index,
                     pic_state,
                     frame_context,
                     frame_state,
-                    &mut data_stores.clip,
+                    &mut resources.clip_data_store,
                 );
                 clip_mask_instances.push(clip_mask_kind);
             }
         }
 
         true
     }
 
@@ -3332,45 +3341,45 @@ impl PrimitiveInstance {
         &mut self,
         prim_context: &PrimitiveContext,
         root_spatial_node_index: SpatialNodeIndex,
         pic_context: &PictureContext,
         pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         prim_store: &mut PrimitiveStore,
-        data_stores: &mut DataStores,
+        resources: &mut FrameResources,
         scratch: &mut PrimitiveScratchBuffer,
     ) {
         let prim_info = &mut scratch.prim_info[self.visibility_info.0 as usize];
 
         if self.is_chased() {
             println!("\tupdating clip task with pic rect {:?}", prim_info.clip_chain.pic_clip_rect);
         }
 
         self.build_segments_if_needed(
             &prim_info.clip_chain,
             frame_state,
             prim_store,
-            data_stores,
+            resources,
             &mut scratch.segments,
             &mut scratch.segment_instances,
         );
 
         // First try to  render this primitive's mask using optimized brush rendering.
         if self.update_clip_task_for_brush(
             prim_info,
             root_spatial_node_index,
             prim_context,
             pic_context,
             pic_state,
             frame_context,
             frame_state,
             prim_store,
-            data_stores,
+            resources,
             &mut scratch.segments,
             &mut scratch.segment_instances,
             &mut scratch.clip_mask_instances,
         ) {
             if self.is_chased() {
                 println!("\tsegment tasks have been created for clipping");
             }
             return;
@@ -3387,17 +3396,17 @@ impl PrimitiveInstance {
                 let clip_task = RenderTask::new_mask(
                     device_rect,
                     prim_info.clip_chain.clips_range,
                     root_spatial_node_index,
                     frame_state.clip_store,
                     frame_state.gpu_cache,
                     frame_state.resource_cache,
                     frame_state.render_tasks,
-                    &mut data_stores.clip,
+                    &mut resources.clip_data_store,
                 );
 
                 let clip_task_id = frame_state.render_tasks.add(clip_task);
                 if self.is_chased() {
                     println!("\tcreated task {:?} with device rect {:?}",
                         clip_task_id, device_rect);
                 }
                 // Set the global clip mask instance for this primitive.
--- a/gfx/wr/webrender/src/prim_store/picture.rs
+++ b/gfx/wr/webrender/src/prim_store/picture.rs
@@ -3,18 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{
     ColorU, FilterOp, LayoutSize, LayoutPrimitiveInfo, MixBlendMode,
     PropertyBinding, PropertyBindingId,
 };
 use app_units::Au;
 use display_list_flattener::{AsInstanceKind, IsVisible};
-use intern::{Internable, InternDebug};
-use intern_types;
+use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
 use picture::PictureCompositeMode;
 use prim_store::{
     PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
     PrimitiveInstanceKind, PrimitiveSceneData, PrimitiveStore, VectorKey,
 };
 
 /// Represents a hashable description of how a picture primitive
 /// will be composited into its parent.
@@ -181,20 +180,28 @@ impl From<PictureKey> for PictureTemplat
 
         PictureTemplate {
             common,
             kind: PictureData,
         }
     }
 }
 
-pub use intern_types::picture::Handle as PictureDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct PictureDataMarker;
+
+pub type PictureDataStore = DataStore<PictureKey, PictureTemplate, PictureDataMarker>;
+pub type PictureDataHandle = Handle<PictureDataMarker>;
+pub type PictureDataUpdateList = UpdateList<PictureKey>;
+pub type PictureDataInterner = Interner<PictureKey, PrimitiveSceneData, PictureDataMarker>;
 
 impl Internable for Picture {
-    type Marker = intern_types::picture::Marker;
+    type Marker = PictureDataMarker;
     type Source = PictureKey;
     type StoreData = PictureTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
--- a/gfx/wr/webrender/src/prim_store/text_run.rs
+++ b/gfx/wr/webrender/src/prim_store/text_run.rs
@@ -5,17 +5,16 @@
 use api::{ColorF, DevicePixelScale, GlyphInstance, LayoutPrimitiveInfo};
 use api::{LayoutToWorldTransform, RasterSpace};
 use api::{LayoutVector2D, Shadow};
 use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
 use frame_builder::{FrameBuildingState, PictureContext};
 use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
 use gpu_cache::GpuCache;
 use intern;
-use intern_types;
 use prim_store::{PrimitiveOpacity, PrimitiveSceneData,  PrimitiveScratchBuffer};
 use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData, VectorKey};
 use render_task::{RenderTaskTree};
 use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
 use resource_cache::{ResourceCache};
 use util::{MatrixHelpers};
 use prim_store::PrimitiveInstanceKind;
 use std::ops;
@@ -157,27 +156,35 @@ impl TextRunTemplate {
                 request.push(gpu_block);
             }
 
             assert!(request.current_used_block_num() <= MAX_VERTEX_TEXTURE_WIDTH);
         }
     }
 }
 
-pub use intern_types::text_run::Handle as TextRunDataHandle;
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+pub struct TextRunDataMarker;
+
+pub type TextRunDataStore = intern::DataStore<TextRunKey, TextRunTemplate, TextRunDataMarker>;
+pub type TextRunDataHandle = intern::Handle<TextRunDataMarker>;
+pub type TextRunDataUpdateList = intern::UpdateList<TextRunKey>;
+pub type TextRunDataInterner = intern::Interner<TextRunKey, PrimitiveSceneData, TextRunDataMarker>;
 
 pub struct TextRun {
     pub font: FontInstance,
     pub offset: LayoutVector2D,
     pub glyphs: Arc<Vec<GlyphInstance>>,
     pub shadow: bool,
 }
 
 impl intern::Internable for TextRun {
-    type Marker = intern_types::text_run::Marker;
+    type Marker = TextRunDataMarker;
     type Source = TextRunKey;
     type StoreData = TextRunTemplate;
     type InternData = PrimitiveSceneData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
--- a/gfx/wr/webrender/src/profiler.rs
+++ b/gfx/wr/webrender/src/profiler.rs
@@ -396,49 +396,31 @@ pub struct ResourceProfileCounters {
 pub struct IpcProfileCounters {
     pub build_time: TimeProfileCounter,
     pub consume_time: TimeProfileCounter,
     pub send_time: TimeProfileCounter,
     pub total_time: TimeProfileCounter,
     pub display_lists: ResourceProfileCounter,
 }
 
-macro_rules! declare_intern_profile_counters {
-    ( $( $name: ident, )+ ) => {
-        #[derive(Clone)]
-        pub struct InternProfileCounters {
-            $(
-                pub $name: ResourceProfileCounter,
-            )+
-        }
-
-        impl InternProfileCounters {
-            #[cfg(feature = "debug_renderer")]
-            fn draw(
-                &self,
-                debug_renderer: &mut DebugRenderer,
-                draw_state: &mut DrawState,
-            ) {
-                Profiler::draw_counters(
-                    &[
-                        $(
-                            &self.$name,
-                        )+
-                    ],
-                    debug_renderer,
-                    true,
-                    draw_state,
-                );
-            }
-        }
-    }
+#[derive(Clone)]
+pub struct InternProfileCounters {
+    pub prims: ResourceProfileCounter,
+    pub images: ResourceProfileCounter,
+    pub image_borders: ResourceProfileCounter,
+    pub line_decs: ResourceProfileCounter,
+    pub linear_gradients: ResourceProfileCounter,
+    pub normal_borders: ResourceProfileCounter,
+    pub pictures: ResourceProfileCounter,
+    pub radial_gradients: ResourceProfileCounter,
+    pub text_runs: ResourceProfileCounter,
+    pub yuv_images: ResourceProfileCounter,
+    pub clips: ResourceProfileCounter,
 }
 
-enumerate_interners!(declare_intern_profile_counters);
-
 impl IpcProfileCounters {
     pub fn set(
         &mut self,
         build_start: u64,
         build_end: u64,
         send_start: u64,
         consume_start: u64,
         consume_end: u64,
@@ -468,27 +450,27 @@ impl BackendProfileCounters {
             ipc: IpcProfileCounters {
                 build_time: TimeProfileCounter::new("Display List Build Time", false),
                 consume_time: TimeProfileCounter::new("Display List Consume Time", false),
                 send_time: TimeProfileCounter::new("Display List Send Time", false),
                 total_time: TimeProfileCounter::new("Total Display List Time", false),
                 display_lists: ResourceProfileCounter::new("Display Lists Sent"),
             },
             intern: InternProfileCounters {
-                prim: ResourceProfileCounter::new("Interned primitives"),
-                image: ResourceProfileCounter::new("Interned images"),
-                image_border: ResourceProfileCounter::new("Interned image borders"),
-                line_decoration: ResourceProfileCounter::new("Interned line decorations"),
-                linear_grad: ResourceProfileCounter::new("Interned linear gradients"),
-                normal_border: ResourceProfileCounter::new("Interned normal borders"),
-                picture: ResourceProfileCounter::new("Interned pictures"),
-                radial_grad: ResourceProfileCounter::new("Interned radial gradients"),
-                text_run: ResourceProfileCounter::new("Interned text runs"),
-                yuv_image: ResourceProfileCounter::new("Interned YUV images"),
-                clip: ResourceProfileCounter::new("Interned clips"),
+                prims: ResourceProfileCounter::new("Interned primitives"),
+                images: ResourceProfileCounter::new("Interned images"),
+                image_borders: ResourceProfileCounter::new("Interned image borders"),
+                line_decs: ResourceProfileCounter::new("Interned line decorations"),
+                linear_gradients: ResourceProfileCounter::new("Interned linear gradients"),
+                normal_borders: ResourceProfileCounter::new("Interned normal borders"),
+                pictures: ResourceProfileCounter::new("Interned pictures"),
+                radial_gradients: ResourceProfileCounter::new("Interned radial gradients"),
+                text_runs: ResourceProfileCounter::new("Interned text runs"),
+                yuv_images: ResourceProfileCounter::new("Interned YUV images"),
+                clips: ResourceProfileCounter::new("Interned clips"),
             },
         }
     }
 
     pub fn reset(&mut self) {
         self.total_time.reset();
         self.ipc.total_time.reset();
         self.ipc.build_time.reset();
@@ -1124,17 +1106,34 @@ impl Profiler {
                 &backend_profile.resources.font_templates,
                 &backend_profile.resources.image_templates,
             ],
             debug_renderer,
             true,
             &mut self.draw_state
         );
 
-        backend_profile.intern.draw(debug_renderer, &mut self.draw_state);
+        Profiler::draw_counters(
+            &[
+                &backend_profile.intern.clips,
+                &backend_profile.intern.prims,
+                &backend_profile.intern.images,
+                &backend_profile.intern.image_borders,
+                &backend_profile.intern.line_decs,
+                &backend_profile.intern.linear_gradients,
+                &backend_profile.intern.normal_borders,
+                &backend_profile.intern.pictures,
+                &backend_profile.intern.radial_gradients,
+                &backend_profile.intern.text_runs,
+                &backend_profile.intern.yuv_images,
+            ],
+            debug_renderer,
+            true,
+            &mut self.draw_state
+        );
 
         Profiler::draw_counters(
             &[
                 &backend_profile.resources.texture_cache.pages_a8_linear,
                 &backend_profile.resources.texture_cache.pages_rgba8_linear,
                 &backend_profile.resources.texture_cache.pages_rgba8_nearest,
                 &backend_profile.ipc.display_lists,
             ],
--- a/gfx/wr/webrender/src/render_backend.rs
+++ b/gfx/wr/webrender/src/render_backend.rs
@@ -17,28 +17,34 @@ use api::{IdNamespace, LayoutPoint, Pipe
 use api::{MemoryReport};
 use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, BlobImageKey};
 use api::{NotificationRequest, Checkpoint};
 use api::channel::{MsgReceiver, MsgSender, Payload};
 #[cfg(feature = "capture")]
 use api::CaptureBits;
 #[cfg(feature = "replay")]
 use api::CapturedDocument;
+use clip::ClipDataStore;
 use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
 #[cfg(feature = "debugger")]
 use debug_server;
 use frame_builder::{FrameBuilder, FrameBuilderConfig};
 use gpu_cache::GpuCache;
 use hit_test::{HitTest, HitTester};
-use intern_types;
 use internal_types::{DebugOutput, FastHashMap, FastHashSet, RenderedDocument, ResultMsg};
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use picture::RetainedTiles;
-use prim_store::{PrimitiveScratchBuffer, PrimitiveInstance};
+use prim_store::{PrimitiveDataStore, PrimitiveScratchBuffer, PrimitiveInstance};
 use prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData};
+use prim_store::borders::{ImageBorderDataStore, NormalBorderDataStore};
+use prim_store::gradient::{LinearGradientDataStore, RadialGradientDataStore};
+use prim_store::image::{ImageDataStore, YuvImageDataStore};
+use prim_store::line_dec::LineDecorationDataStore;
+use prim_store::picture::PictureDataStore;
+use prim_store::text_run::TextRunDataStore;
 use profiler::{BackendProfileCounters, IpcProfileCounters, ResourceProfileCounters};
 use record::ApiRecordingReceiver;
 use renderer::{AsyncPropertySampler, PipelineInfo};
 use resource_cache::ResourceCache;
 #[cfg(feature = "replay")]
 use resource_cache::PlainCacheOwn;
 #[cfg(any(feature = "capture", feature = "replay"))]
 use resource_cache::PlainResources;
@@ -203,100 +209,87 @@ impl FrameStamp {
     /// An invalid sentinel FrameStamp.
     pub const INVALID: FrameStamp = FrameStamp {
         id: FrameId(0),
         time: UNIX_EPOCH,
         document_id: DocumentId::INVALID,
     };
 }
 
-macro_rules! declare_data_stores {
-    ( $( $name: ident, )+ ) => {
+macro_rules! declare_frame_resources {
+    ( $( { $x: ident, $y: ty, $datastore_ident: ident, $datastore_type: ty } )+ ) => {
         /// A collection of resources that are shared by clips, primitives
         /// between display lists.
         #[cfg_attr(feature = "capture", derive(Serialize))]
         #[cfg_attr(feature = "replay", derive(Deserialize))]
         #[derive(Default)]
-        pub struct DataStores {
+        pub struct FrameResources {
             $(
-                pub $name: intern_types::$name::Store,
+                pub $datastore_ident: $datastore_type,
             )+
         }
 
-        impl DataStores {
+        impl FrameResources {
             /// Reports CPU heap usage.
             fn report_memory(&self, ops: &mut MallocSizeOfOps, r: &mut MemoryReport) {
                 $(
-                    r.interning.data_stores.$name += self.$name.size_of(ops);
-                )+
-            }
-
-            fn apply_updates(
-                &mut self,
-                updates: InternerUpdates,
-                profile_counters: &mut BackendProfileCounters,
-            ) {
-                $(
-                    self.$name.apply_updates(
-                        updates.$name,
-                        &mut profile_counters.intern.$name,
-                    );
+                    r.interning.$datastore_ident += self.$datastore_ident.size_of(ops);
                 )+
             }
         }
     }
 }
 
-enumerate_interners!(declare_data_stores);
+enumerate_interners!(declare_frame_resources);
 
-impl DataStores {
+impl FrameResources {
     pub fn as_common_data(
         &self,
         prim_inst: &PrimitiveInstance
     ) -> &PrimTemplateCommonData {
         match prim_inst.kind {
             PrimitiveInstanceKind::Rectangle { data_handle, .. } |
             PrimitiveInstanceKind::Clear { data_handle, .. } => {
-                let prim_data = &self.prim[data_handle];
+                let prim_data = &self.prim_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::Image { data_handle, .. } => {
-                let prim_data = &self.image[data_handle];
+                let prim_data = &self.image_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
-                let prim_data = &self.image_border[data_handle];
+                let prim_data = &self.image_border_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
-                let prim_data = &self.line_decoration[data_handle];
+                let prim_data = &self.line_decoration_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
-                let prim_data = &self.linear_grad[data_handle];
+                let prim_data = &self.linear_grad_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
-                let prim_data = &self.normal_border[data_handle];
+                let prim_data = &self.normal_border_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::Picture { data_handle, .. } => {
-                let prim_data = &self.picture[data_handle];
+                let prim_data = &self.picture_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
-                let prim_data = &self.radial_grad[data_handle];
+                let prim_data = &self.radial_grad_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::TextRun { data_handle, .. }  => {
-                let prim_data = &self.text_run[data_handle];
+                let prim_data = &self.text_run_data_store[data_handle];
                 &prim_data.common
             }
             PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
-                let prim_data = &self.yuv_image[data_handle];
+                let prim_data = &self.yuv_image_data_store[data_handle];
                 &prim_data.common
             }
         }
     }
 }
 
 struct Document {
     // The latest built scene, usable to build frames.
@@ -335,17 +328,17 @@ struct Document {
     /// before rendering again.
     frame_is_valid: bool,
     hit_tester_is_valid: bool,
     rendered_frame_is_valid: bool,
     // We track this information to be able to display debugging information from the
     // renderer.
     has_built_scene: bool,
 
-    data_stores: DataStores,
+    resources: FrameResources,
 
     /// Contains various vecs of data that is used only during frame building,
     /// where we want to recycle the memory each new display list, to avoid constantly
     /// re-allocating and moving memory around.
     scratch: PrimitiveScratchBuffer,
 }
 
 impl Document {
@@ -372,17 +365,17 @@ impl Document {
             frame_builder: None,
             output_pipelines: FastHashSet::default(),
             hit_tester: None,
             dynamic_properties: SceneProperties::new(),
             frame_is_valid: false,
             hit_tester_is_valid: false,
             rendered_frame_is_valid: false,
             has_built_scene: false,
-            data_stores: DataStores::default(),
+            resources: FrameResources::default(),
             scratch: PrimitiveScratchBuffer::new(),
         }
     }
 
     fn can_render(&self) -> bool {
         self.frame_builder.is_some() && self.scene.has_root_pipeline()
     }
 
@@ -514,23 +507,23 @@ impl Document {
                 &mut self.clip_scroll_tree,
                 &self.scene.pipelines,
                 accumulated_scale_factor,
                 self.view.layer,
                 pan,
                 &mut resource_profile.texture_cache,
                 &mut resource_profile.gpu_cache,
                 &self.dynamic_properties,
-                &mut self.data_stores,
+                &mut self.resources,
                 &mut self.scratch,
                 debug_flags,
             );
             self.hit_tester = Some(frame_builder.create_hit_tester(
                 &self.clip_scroll_tree,
-                &self.data_stores.clip,
+                &self.resources.clip_data_store,
             ));
             frame
         };
 
         self.frame_is_valid = true;
         self.hit_tester_is_valid = true;
 
         let is_new_scene = self.has_built_scene;
@@ -550,17 +543,17 @@ impl Document {
             self.clip_scroll_tree.update_tree(
                 pan,
                 &self.dynamic_properties,
                 None,
             );
 
             self.hit_tester = Some(frame_builder.create_hit_tester(
                 &self.clip_scroll_tree,
-                &self.data_stores.clip,
+                &self.resources.clip_data_store,
             ));
             self.hit_tester_is_valid = true;
         }
     }
 
     pub fn updated_pipeline_info(&mut self) -> PipelineInfo {
         let removed_pipelines = replace(&mut self.removed_pipelines, Vec::new());
         PipelineInfo {
@@ -888,17 +881,17 @@ impl RenderBackend {
                         );
                         if let Some((rasterizer, info)) = txn.blob_rasterizer.take() {
                             self.resource_cache.set_blob_rasterizer(rasterizer, info);
                         }
 
                         self.update_document(
                             txn.document_id,
                             replace(&mut txn.resource_updates, Vec::new()),
-                            txn.interner_updates.take(),
+                            txn.doc_resource_updates.take(),
                             replace(&mut txn.frame_ops, Vec::new()),
                             replace(&mut txn.notifications, Vec::new()),
                             txn.render_frame,
                             txn.invalidate_rendered_frame,
                             &mut frame_counter,
                             &mut profile_counters,
                             has_built_scene,
                         );
@@ -1272,17 +1265,17 @@ impl RenderBackend {
 
         tx.send(SceneBuilderRequest::Transaction(txn)).unwrap();
     }
 
     fn update_document(
         &mut self,
         document_id: DocumentId,
         resource_updates: Vec<ResourceUpdate>,
-        interner_updates: Option<InternerUpdates>,
+        doc_resource_updates: Option<DocumentResourceUpdates>,
         mut frame_ops: Vec<FrameMsg>,
         mut notifications: Vec<NotificationRequest>,
         mut render_frame: bool,
         invalidate_rendered_frame: bool,
         frame_counter: &mut u32,
         profile_counters: &mut BackendProfileCounters,
         has_built_scene: bool,
     ) {
@@ -1299,18 +1292,61 @@ impl RenderBackend {
             }
         }
 
         let doc = self.documents.get_mut(&document_id).unwrap();
         doc.has_built_scene |= has_built_scene;
 
         // If there are any additions or removals of clip modes
         // during the scene build, apply them to the data store now.
-        if let Some(updates) = interner_updates {
-            doc.data_stores.apply_updates(updates, profile_counters);
+        if let Some(updates) = doc_resource_updates {
+            doc.resources.clip_data_store.apply_updates(
+                updates.clip_updates,
+                &mut profile_counters.intern.clips,
+            );
+            doc.resources.prim_data_store.apply_updates(
+                updates.prim_updates,
+                &mut profile_counters.intern.prims,
+            );
+            doc.resources.image_data_store.apply_updates(
+                updates.image_updates,
+                &mut profile_counters.intern.images,
+            );
+            doc.resources.image_border_data_store.apply_updates(
+                updates.image_border_updates,
+                &mut profile_counters.intern.image_borders,
+            );
+            doc.resources.line_decoration_data_store.apply_updates(
+                updates.line_decoration_updates,
+                &mut profile_counters.intern.line_decs,
+            );
+            doc.resources.linear_grad_data_store.apply_updates(
+                updates.linear_grad_updates,
+                &mut profile_counters.intern.linear_gradients,
+            );
+            doc.resources.normal_border_data_store.apply_updates(
+                updates.normal_border_updates,
+                &mut profile_counters.intern.normal_borders,
+            );
+            doc.resources.picture_data_store.apply_updates(
+                updates.picture_updates,
+                &mut profile_counters.intern.pictures,
+            );
+            doc.resources.radial_grad_data_store.apply_updates(
+                updates.radial_grad_updates,
+                &mut profile_counters.intern.radial_gradients,
+            );
+            doc.resources.text_run_data_store.apply_updates(
+                updates.text_run_updates,
+                &mut profile_counters.intern.text_runs,
+            );
+            doc.resources.yuv_image_data_store.apply_updates(
+                updates.yuv_image_updates,
+                &mut profile_counters.intern.yuv_images,
+            );
         }
 
         // TODO: this scroll variable doesn't necessarily mean we scrolled. It is only used
         // for something wrench specific and we should remove it.
         let mut scroll = false;
         for frame_msg in frame_ops {
             let _timer = profile_counters.total_time.timer();
             let op = doc.process_frame_msg(frame_msg);
@@ -1523,17 +1559,17 @@ impl RenderBackend {
         let op = ops.size_of_op;
         report.gpu_cache_metadata = self.gpu_cache.size_of(ops);
         for (_id, doc) in &self.documents {
             if let Some(ref fb) = doc.frame_builder {
                 report.clip_stores += fb.clip_store.size_of(ops);
             }
             report.hit_testers += doc.hit_tester.size_of(ops);
 
-            doc.data_stores.report_memory(ops, &mut report)
+            doc.resources.report_memory(ops, &mut report)
         }
 
         report += self.resource_cache.report_memory(op);
 
         // Send a message to report memory on the scene-builder thread, which
         // will add its report to this one and send the result back to the original
         // thread waiting on the request.
         self.scene_tx.send(SceneBuilderRequest::ReportMemory(report, tx)).unwrap();
@@ -1632,18 +1668,18 @@ impl RenderBackend {
                 // it has `pipeline_epoch_map`,
                 // which may capture necessary details for some cases.
                 let file_name = format!("frame-{}-{}", (id.0).0, id.1);
                 config.serialize(&rendered_document.frame, file_name);
                 let file_name = format!("clip-scroll-{}-{}", (id.0).0, id.1);
                 config.serialize_tree(&doc.clip_scroll_tree, file_name);
             }
 
-            let data_stores_name = format!("data-stores-{}-{}", (id.0).0, id.1);
-            config.serialize(&doc.data_stores, data_stores_name);
+            let frame_resources_name = format!("frame-resources-{}-{}", (id.0).0, id.1);
+            config.serialize(&doc.resources, frame_resources_name);
         }
 
         debug!("\tscene builder");
         self.scene_tx.send(SceneBuilderRequest::SaveScene(config.clone())).unwrap();
 
         debug!("\tresource cache");
         let (resources, deferred) = self.resource_cache.save_capture(&config.root);
 
@@ -1717,39 +1753,39 @@ impl RenderBackend {
         let mut scenes_to_build = Vec::new();
 
         for (id, view) in backend.documents {
             debug!("\tdocument {:?}", id);
             let scene_name = format!("scene-{}-{}", (id.0).0, id.1);
             let scene = CaptureConfig::deserialize::<Scene, _>(root, &scene_name)
                 .expect(&format!("Unable to open {}.ron", scene_name));
 
-            let interners_name = format!("interners-{}-{}", (id.0).0, id.1);
-            let interners = CaptureConfig::deserialize::<Interners, _>(root, &interners_name)
-                .expect(&format!("Unable to open {}.ron", interners_name));
+            let doc_resources_name = format!("doc-resources-{}-{}", (id.0).0, id.1);
+            let doc_resources = CaptureConfig::deserialize::<DocumentResources, _>(root, &doc_resources_name)
+                .expect(&format!("Unable to open {}.ron", doc_resources_name));
 
-            let data_stores_name = format!("data-stores-{}-{}", (id.0).0, id.1);
-            let data_stores = CaptureConfig::deserialize::<DataStores, _>(root, &data_stores_name)
-                .expect(&format!("Unable to open {}.ron", data_stores_name));
+            let frame_resources_name = format!("frame-resources-{}-{}", (id.0).0, id.1);
+            let frame_resources = CaptureConfig::deserialize::<FrameResources, _>(root, &frame_resources_name)
+                .expect(&format!("Unable to open {}.ron", frame_resources_name));
 
             let mut doc = Document {
                 scene: scene.clone(),
                 removed_pipelines: Vec::new(),
                 view: view.clone(),
                 clip_scroll_tree: ClipScrollTree::new(),
                 stamp: FrameStamp::first(id),
                 frame_builder: Some(FrameBuilder::empty()),
                 output_pipelines: FastHashSet::default(),
                 dynamic_properties: SceneProperties::new(),
                 hit_tester: None,
                 frame_is_valid: false,
                 hit_tester_is_valid: false,
                 rendered_frame_is_valid: false,
                 has_built_scene: false,
-                data_stores,
+                resources: frame_resources,
                 scratch: PrimitiveScratchBuffer::new(),
             };
 
             let frame_name = format!("frame-{}-{}", (id.0).0, id.1);
             let frame = CaptureConfig::deserialize::<Frame, _>(root, frame_name);
             let build_frame = match frame {
                 Some(frame) => {
                     info!("\tloaded a built frame with {} passes", frame.passes.len());
@@ -1778,17 +1814,17 @@ impl RenderBackend {
             scenes_to_build.push(LoadScene {
                 document_id: id,
                 scene: doc.scene.clone(),
                 view: view.clone(),
                 config: self.frame_config.clone(),
                 output_pipelines: doc.output_pipelines.clone(),
                 font_instances: self.resource_cache.get_font_instances(),
                 build_frame,
-                interners,
+                doc_resources,
             });
 
             self.documents.insert(id, doc);
         }
 
         if !scenes_to_build.is_empty() {
             self.low_priority_scene_tx.send(
                 SceneBuilderRequest::LoadScenes(scenes_to_build)
--- a/gfx/wr/webrender/src/scene_builder.rs
+++ b/gfx/wr/webrender/src/scene_builder.rs
@@ -5,41 +5,66 @@
 use api::{AsyncBlobImageRasterizer, BlobImageRequest, BlobImageParams, BlobImageResult};
 use api::{DocumentId, PipelineId, ApiMsg, FrameMsg, ResourceUpdate, ExternalEvent, Epoch};
 use api::{BuiltDisplayList, ColorF, LayoutSize, NotificationRequest, Checkpoint, IdNamespace};
 use api::{MemoryReport};
 use api::channel::MsgSender;
 #[cfg(feature = "capture")]
 use capture::CaptureConfig;
 use frame_builder::{FrameBuilderConfig, FrameBuilder};
+use clip::{ClipDataInterner, ClipDataUpdateList};
 use clip_scroll_tree::ClipScrollTree;
 use display_list_flattener::DisplayListFlattener;
 use intern::{Internable, Interner};
-use intern_types;
 use internal_types::{FastHashMap, FastHashSet};
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-use prim_store::{PrimitiveKeyKind};
+use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind};
 use prim_store::PrimitiveStoreStats;
-use prim_store::borders::{ImageBorder, NormalBorderPrim};
-use prim_store::gradient::{LinearGradient, RadialGradient};
-use prim_store::image::{Image, YuvImage};
-use prim_store::line_dec::LineDecoration;
-use prim_store::picture::Picture;
-use prim_store::text_run::TextRun;
+use prim_store::borders::{
+    ImageBorder, ImageBorderDataInterner, ImageBorderDataUpdateList,
+    NormalBorderPrim, NormalBorderDataInterner, NormalBorderDataUpdateList
+};
+use prim_store::gradient::{
+    LinearGradient, LinearGradientDataInterner, LinearGradientDataUpdateList,
+    RadialGradient, RadialGradientDataInterner, RadialGradientDataUpdateList
+};
+use prim_store::image::{
+    Image, ImageDataInterner, ImageDataUpdateList,
+    YuvImage, YuvImageDataInterner, YuvImageDataUpdateList,
+};
+use prim_store::line_dec::{
+    LineDecoration, LineDecorationDataInterner, LineDecorationDataUpdateList
+};
+use prim_store::picture::{PictureDataInterner, Picture, PictureDataUpdateList};
+use prim_store::text_run::{TextRunDataInterner, TextRun, TextRunDataUpdateList};
 use resource_cache::{AsyncBlobImageInfo, FontInstanceMap};
 use render_backend::DocumentView;
 use renderer::{PipelineInfo, SceneBuilderHooks};
 use scene::Scene;
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::mem::replace;
 use time::precise_time_ns;
 use util::drain_filter;
 use std::thread;
 use std::time::Duration;
 
+pub struct DocumentResourceUpdates {
+    pub clip_updates: ClipDataUpdateList,
+    pub prim_updates: PrimitiveDataUpdateList,
+    pub image_updates: ImageDataUpdateList,
+    pub image_border_updates: ImageBorderDataUpdateList,
+    pub line_decoration_updates: LineDecorationDataUpdateList,
+    pub linear_grad_updates: LinearGradientDataUpdateList,
+    pub normal_border_updates: NormalBorderDataUpdateList,
+    pub picture_updates: PictureDataUpdateList,
+    pub radial_grad_updates: RadialGradientDataUpdateList,
+    pub text_run_updates: TextRunDataUpdateList,
+    pub yuv_image_updates: YuvImageDataUpdateList,
+}
+
 /// Represents the work associated to a transaction before scene building.
 pub struct Transaction {
     pub document_id: DocumentId,
     pub display_list_updates: Vec<DisplayListUpdate>,
     pub removed_pipelines: Vec<PipelineId>,
     pub epoch_updates: Vec<(PipelineId, Epoch)>,
     pub request_scene_build: Option<SceneRequest>,
     pub blob_requests: Vec<BlobImageParams>,
@@ -87,17 +112,17 @@ pub struct BuiltTransaction {
     pub document_id: DocumentId,
     pub built_scene: Option<BuiltScene>,
     pub resource_updates: Vec<ResourceUpdate>,
     pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>,
     pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, AsyncBlobImageInfo)>,
     pub frame_ops: Vec<FrameMsg>,
     pub removed_pipelines: Vec<PipelineId>,
     pub notifications: Vec<NotificationRequest>,
-    pub interner_updates: Option<InternerUpdates>,
+    pub doc_resource_updates: Option<DocumentResourceUpdates>,
     pub scene_build_start_time: u64,
     pub scene_build_end_time: u64,
     pub render_frame: bool,
     pub invalidate_rendered_frame: bool,
 }
 
 pub struct DisplayListUpdate {
     pub pipeline_id: PipelineId,
@@ -119,17 +144,17 @@ pub struct SceneRequest {
 pub struct LoadScene {
     pub document_id: DocumentId,
     pub scene: Scene,
     pub output_pipelines: FastHashSet<PipelineId>,
     pub font_instances: FontInstanceMap,
     pub view: DocumentView,
     pub config: FrameBuilderConfig,
     pub build_frame: bool,
-    pub interners: Interners,
+    pub doc_resources: DocumentResources,
 }
 
 pub struct BuiltScene {
     pub scene: Scene,
     pub frame_builder: FrameBuilder,
     pub clip_scroll_tree: ClipScrollTree,
 }
 
@@ -164,112 +189,98 @@ pub enum SceneBuilderResult {
 // Message from render backend to scene builder to indicate the
 // scene swap was completed. We need a separate channel for this
 // so that they don't get mixed with SceneBuilderRequest messages.
 pub enum SceneSwapResult {
     Complete(Sender<()>),
     Aborted,
 }
 
-macro_rules! declare_interners {
-    ( $( $name: ident, )+ ) => {
+macro_rules! declare_document_resources {
+    ( $( { $interner_ident: ident, $interner_type: ty, $x: ident, $y: ty } )+ ) => {
         /// This struct contains all items that can be shared between
         /// display lists. We want to intern and share the same clips,
         /// primitives and other things between display lists so that:
         /// - GPU cache handles remain valid, reducing GPU cache updates.
         /// - Comparison of primitives and pictures between two
         ///   display lists is (a) fast (b) done during scene building.
         #[cfg_attr(feature = "capture", derive(Serialize))]
         #[cfg_attr(feature = "replay", derive(Deserialize))]
         #[derive(Default)]
-        pub struct Interners {
+        pub struct DocumentResources {
             $(
-                pub $name: intern_types::$name::Interner,
+                pub $interner_ident: $interner_type,
             )+
         }
 
-        pub struct InternerUpdates {
-            $(
-                pub $name: intern_types::$name::UpdateList,
-            )+
-        }
-
-        impl Interners {
+        impl DocumentResources {
             /// Reports CPU heap memory used by the interners.
             fn report_memory(
                 &self,
                 ops: &mut MallocSizeOfOps,
                 r: &mut MemoryReport,
             ) {
                 $(
-                    r.interning.interners.$name += self.$name.size_of(ops);
+                    r.interning.$interner_ident += self.$interner_ident.size_of(ops);
                 )+
             }
-
-            fn end_frame_and_get_pending_updates(&mut self) -> InternerUpdates {
-                InternerUpdates {
-                    $(
-                        $name: self.$name.end_frame_and_get_pending_updates(),
-                    )+
-                }
-            }
         }
     }
 }
 
-enumerate_interners!(declare_interners);
+enumerate_interners!(declare_document_resources);
 
-// Access to `Interners` interners by `Internable`
+// Access to `DocumentResources` interners by `Internable`
 pub trait InternerMut<I: Internable>
 {
     fn interner_mut(&mut self) -> &mut Interner<I::Source, I::InternData, I::Marker>;
 }
 
-macro_rules! impl_interner_mut {
+macro_rules! impl_internet_mut {
     ($($ty:ident: $mem:ident,)*) => {
-        $(impl InternerMut<$ty> for Interners {
+        $(impl InternerMut<$ty> for DocumentResources {
             fn interner_mut(&mut self) -> &mut Interner<
                 <$ty as Internable>::Source,
                 <$ty as Internable>::InternData,
                 <$ty as Internable>::Marker
             > {
                 &mut self.$mem
             }
         })*
     }
 }
 
-impl_interner_mut! {
-    Image: image,
-    ImageBorder: image_border,
-    LineDecoration: line_decoration,
-    LinearGradient: linear_grad,
-    NormalBorderPrim: normal_border,
-    Picture: picture,
-    PrimitiveKeyKind: prim,
-    RadialGradient: radial_grad,
-    TextRun: text_run,
-    YuvImage: yuv_image,
+impl_internet_mut! {
+    Image: image_interner,
+    ImageBorder: image_border_interner,
+    LineDecoration: line_decoration_interner,
+    LinearGradient: linear_grad_interner,
+    NormalBorderPrim: normal_border_interner,
+    Picture: picture_interner,
+    PrimitiveKeyKind: prim_interner,
+    RadialGradient: radial_grad_interner,
+    TextRun: text_run_interner,
+    YuvImage: yuv_image_interner,
 }
 
 // A document in the scene builder contains the current scene,
 // as well as a persistent clip interner. This allows clips
 // to be de-duplicated, and persisted in the GPU cache between
 // display lists.
 struct Document {
     scene: Scene,
-    interners: Interners,
+    resources: DocumentResources,
     prim_store_stats: PrimitiveStoreStats,
 }
 
 impl Document {
     fn new(scene: Scene) -> Self {
         Document {
             scene,
-            interners: Interners::default(),
+            resources: DocumentResources::default(),
             prim_store_stats: PrimitiveStoreStats::empty(),
         }
     }
 }
 
 pub struct SceneBuilder {
     documents: FastHashMap<DocumentId, Document>,
     rx: Receiver<SceneBuilderRequest>,
@@ -379,63 +390,132 @@ impl SceneBuilder {
         if let Some(ref hooks) = self.hooks {
             hooks.deregister();
         }
     }
 
     #[cfg(feature = "capture")]
     fn save_scene(&mut self, config: CaptureConfig) {
         for (id, doc) in &self.documents {
-            let interners_name = format!("interners-{}-{}", (id.0).0, id.1);
-            config.serialize(&doc.interners, interners_name);
+            let doc_resources_name = format!("doc-resources-{}-{}", (id.0).0, id.1);
+            config.serialize(&doc.resources, doc_resources_name);
         }
     }
 
     #[cfg(feature = "replay")]
     fn load_scenes(&mut self, scenes: Vec<LoadScene>) {
         for mut item in scenes {
             self.config = item.config;
 
             let scene_build_start_time = precise_time_ns();
 
             let mut built_scene = None;
-            let mut interner_updates = None;
+            let mut doc_resource_updates = None;
 
             if item.scene.has_root_pipeline() {
                 let mut clip_scroll_tree = ClipScrollTree::new();
                 let mut new_scene = Scene::new();
 
                 let frame_builder = DisplayListFlattener::create_frame_builder(
                     &item.scene,
                     &mut clip_scroll_tree,
                     item.font_instances,
                     &item.view,
                     &item.output_pipelines,
                     &self.config,
                     &mut new_scene,
-                    &mut item.interners,
+                    &mut item.doc_resources,
                     &PrimitiveStoreStats::empty(),
                 );
 
-                interner_updates = Some(
-                    item.interners.end_frame_and_get_pending_updates()
+                // TODO(djg): Can we do better than this?  Use a #[derive] to
+                // write the code for us, or unify updates into one enum/list?
+                let clip_updates = item
+                    .doc_resources
+                    .clip_interner
+                    .end_frame_and_get_pending_updates();
+
+                let prim_updates = item
+                    .doc_resources
+                    .prim_interner
+                    .end_frame_and_get_pending_updates();
+
+                let image_updates = item
+                    .doc_resources
+                    .image_interner
+                    .end_frame_and_get_pending_updates();
+
+                let image_border_updates = item
+                    .doc_resources
+                    .image_border_interner
+                    .end_frame_and_get_pending_updates();
+
+                let line_decoration_updates = item
+                    .doc_resources
+                    .line_decoration_interner
+                    .end_frame_and_get_pending_updates();
+
+                let linear_grad_updates = item
+                    .doc_resources
+                    .linear_grad_interner
+                    .end_frame_and_get_pending_updates();
+
+                let normal_border_updates = item
+                    .doc_resources
+                    .normal_border_interner
+                    .end_frame_and_get_pending_updates();
+
+                let picture_updates = item
+                    .doc_resources
+                    .picture_interner
+                    .end_frame_and_get_pending_updates();
+
+                let radial_grad_updates = item
+                    .doc_resources
+                    .radial_grad_interner
+                    .end_frame_and_get_pending_updates();
+
+                let text_run_updates = item
+                    .doc_resources
+                    .text_run_interner
+                    .end_frame_and_get_pending_updates();
+
+                let yuv_image_updates = item
+                    .doc_resources
+                    .yuv_image_interner
+                    .end_frame_and_get_pending_updates();
+
+                doc_resource_updates = Some(
+                    DocumentResourceUpdates {
+                        clip_updates,
+                        prim_updates,
+                        image_updates,
+                        image_border_updates,
+                        line_decoration_updates,
+                        linear_grad_updates,
+                        normal_border_updates,
+                        picture_updates,
+                        radial_grad_updates,
+                        text_run_updates,
+                        yuv_image_updates,
+                    }
                 );
 
                 built_scene = Some(BuiltScene {
                     scene: new_scene,
                     frame_builder,
                     clip_scroll_tree,
                 });
             }
 
             self.documents.insert(
                 item.document_id,
                 Document {
                     scene: item.scene,
-                    interners: item.interners,
+                    resources: item.doc_resources,
                     prim_store_stats: PrimitiveStoreStats::empty(),
                 },
             );
 
             let txn = Box::new(BuiltTransaction {
                 document_id: item.document_id,
                 render_frame: item.build_frame,
                 invalidate_rendered_frame: false,
@@ -443,17 +523,17 @@ impl SceneBuilder {
                 resource_updates: Vec::new(),
                 rasterized_blobs: Vec::new(),
                 blob_rasterizer: None,
                 frame_ops: Vec::new(),
                 removed_pipelines: Vec::new(),
                 notifications: Vec::new(),
                 scene_build_start_time,
                 scene_build_end_time: precise_time_ns(),
-                interner_updates,
+                doc_resource_updates,
             });
 
             self.forward_built_transaction(txn);
         }
     }
 
     /// Do the bulk of the work of the scene builder thread.
     fn process_transaction(&mut self, txn: &mut Transaction) -> Box<BuiltTransaction> {
@@ -487,40 +567,107 @@ impl SceneBuilder {
             scene.set_root_pipeline_id(id);
         }
 
         for pipeline_id in &txn.removed_pipelines {
             scene.remove_pipeline(*pipeline_id)
         }
 
         let mut built_scene = None;
-        let mut interner_updates = None;
+        let mut doc_resource_updates = None;
         if scene.has_root_pipeline() {
             if let Some(request) = txn.request_scene_build.take() {
                 let mut clip_scroll_tree = ClipScrollTree::new();
                 let mut new_scene = Scene::new();
 
                 let frame_builder = DisplayListFlattener::create_frame_builder(
                     &scene,
                     &mut clip_scroll_tree,
                     request.font_instances,
                     &request.view,
                     &request.output_pipelines,
                     &self.config,
                     &mut new_scene,
-                    &mut doc.interners,
+                    &mut doc.resources,
                     &doc.prim_store_stats,
                 );
 
                 // Update the allocation stats for next scene
                 doc.prim_store_stats = frame_builder.prim_store.get_stats();
 
                 // Retrieve the list of updates from the clip interner.
-                interner_updates = Some(
-                    doc.interners.end_frame_and_get_pending_updates()
+                let clip_updates = doc
+                    .resources
+                    .clip_interner
+                    .end_frame_and_get_pending_updates();
+
+                let prim_updates = doc
+                    .resources
+                    .prim_interner
+                    .end_frame_and_get_pending_updates();
+
+                let image_updates = doc
+                    .resources
+                    .image_interner
+                    .end_frame_and_get_pending_updates();
+
+                let image_border_updates = doc
+                    .resources
+                    .image_border_interner
+                    .end_frame_and_get_pending_updates();
+
+                let line_decoration_updates = doc
+                    .resources
+                    .line_decoration_interner
+                    .end_frame_and_get_pending_updates();
+
+                let linear_grad_updates = doc
+                    .resources
+                    .linear_grad_interner
+                    .end_frame_and_get_pending_updates();
+
+                let normal_border_updates = doc
+                    .resources
+                    .normal_border_interner
+                    .end_frame_and_get_pending_updates();
+
+                let picture_updates = doc
+                    .resources
+                    .picture_interner
+                    .end_frame_and_get_pending_updates();
+
+                let radial_grad_updates = doc
+                    .resources
+                    .radial_grad_interner
+                    .end_frame_and_get_pending_updates();
+
+                let text_run_updates = doc
+                    .resources
+                    .text_run_interner
+                    .end_frame_and_get_pending_updates();
+
+                let yuv_image_updates = doc
+                    .resources
+                    .yuv_image_interner
+                    .end_frame_and_get_pending_updates();
+
+                doc_resource_updates = Some(
+                    DocumentResourceUpdates {
+                        clip_updates,
+                        prim_updates,
+                        image_updates,
+                        image_border_updates,
+                        line_decoration_updates,
+                        linear_grad_updates,
+                        normal_border_updates,
+                        picture_updates,
+                        radial_grad_updates,
+                        text_run_updates,
+                        yuv_image_updates,
+                    }
                 );
 
                 built_scene = Some(BuiltScene {
                     scene: new_scene,
                     frame_builder,
                     clip_scroll_tree,
                 });
             }
@@ -545,17 +692,17 @@ impl SceneBuilder {
             invalidate_rendered_frame: txn.invalidate_rendered_frame,
             built_scene,
             rasterized_blobs: replace(&mut txn.rasterized_blobs, Vec::new()),
             resource_updates: replace(&mut txn.resource_updates, Vec::new()),
             blob_rasterizer: replace(&mut txn.blob_rasterizer, None),
             frame_ops: replace(&mut txn.frame_ops, Vec::new()),
             removed_pipelines: replace(&mut txn.removed_pipelines, Vec::new()),
             notifications: replace(&mut txn.notifications, Vec::new()),
-            interner_updates,
+            doc_resource_updates,
             scene_build_start_time,
             scene_build_end_time: precise_time_ns(),
         })
     }
 
     /// Send the result of process_transaction back to the render backend.
     fn forward_built_transaction(&mut self, txn: Box<BuiltTransaction>) {
         // We only need the pipeline info and the result channel if we
@@ -608,17 +755,17 @@ impl SceneBuilder {
         }
     }
 
     /// Reports CPU heap memory used by the SceneBuilder.
     fn report_memory(&mut self) -> MemoryReport {
         let ops = self.size_of_ops.as_mut().unwrap();
         let mut report = MemoryReport::default();
         for doc in self.documents.values() {
-            doc.interners.report_memory(ops, &mut report);
+            doc.resources.report_memory(ops, &mut report);
         }
 
         report
     }
 }
 
 /// A scene builder thread which executes expensive operations such as blob rasterization
 /// with a lower priority than the normal scene builder thread.
--- a/gfx/wr/webrender/src/tiling.rs
+++ b/gfx/wr/webrender/src/tiling.rs
@@ -17,17 +17,17 @@ use gpu_cache::{GpuCache};
 use gpu_types::{BorderInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
 use gpu_types::{TransformData, TransformPalette, ZBufferIdGenerator};
 use internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex, TextureSource};
 #[cfg(feature = "pathfinder")]
 use pathfinder_partitioner::mesh::Mesh;
 use picture::SurfaceInfo;
 use prim_store::{PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
 use profiler::FrameProfileCounters;
-use render_backend::{DataStores, FrameId};
+use render_backend::{FrameId, FrameResources};
 use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
 use render_task::{BlurTask, ClearMode, GlyphTask, RenderTaskLocation, RenderTaskTree, ScalingTask};
 use resource_cache::ResourceCache;
 use std::{cmp, usize, f32, i32, mem};
 use texture_allocator::{ArrayAllocationTracker, FreeRectSlice};
 #[cfg(feature = "pathfinder")]
 use webrender_api::{DevicePixel, FontRenderMode};
 
@@ -50,17 +50,17 @@ const TEXTURE_DIMENSION_MASK: i32 = 0xFF
 pub struct RenderTargetIndex(pub usize);
 
 pub struct RenderTargetContext<'a, 'rc> {
     pub device_pixel_scale: DevicePixelScale,
     pub prim_store: &'a PrimitiveStore,
     pub resource_cache: &'rc mut ResourceCache,
     pub use_dual_source_blending: bool,
     pub clip_scroll_tree: &'a ClipScrollTree,
-    pub data_stores: &'a DataStores,
+    pub resources: &'a FrameResources,
     pub surfaces: &'a [SurfaceInfo],
     pub scratch: &'a PrimitiveScratchBuffer,
 }
 
 /// Represents a number of rendering operations on a surface.
 ///
 /// In graphics parlance, a "render target" usually means "a surface (texture or
 /// framebuffer) bound to the output of a shader". This trait has a slightly
@@ -653,17 +653,17 @@ impl RenderTarget for AlphaRenderTarget 
                     task_address,
                     task_info.clip_node_range,
                     task_info.root_spatial_node_index,
                     ctx.resource_cache,
                     gpu_cache,
                     clip_store,
                     ctx.clip_scroll_tree,
                     transforms,
-                    &ctx.data_stores.clip,
+                    &ctx.resources.clip_data_store,
                 );
             }
             RenderTaskKind::ClipRegion(ref task) => {
                 let task_address = render_tasks.get_task_address(task_id);
                 self.clip_batcher.add_clip_region(
                     task_address,
                     task.clip_data_address,
                     task.local_pos,
--- a/gfx/wr/webrender_api/src/api.rs
+++ b/gfx/wr/webrender_api/src/api.rs
@@ -820,69 +820,56 @@ impl PipelineId {
 /// IMPORTANT: Keep this synchronized with the list in mozilla-central located at
 /// gfx/webrender_bindings/webrender_ffi.h
 ///
 /// Note that this could be a lot less verbose if concat_idents! were stable. :-(
 #[macro_export]
 macro_rules! enumerate_interners {
     ($macro_name: ident) => {
         $macro_name! {
-            clip,
-            prim,
-            normal_border,
-            image_border,
-            image,
-            yuv_image,
-            line_decoration,
-            linear_grad,
-            radial_grad,
-            picture,
-            text_run,
+            { clip_interner, ClipDataInterner, clip_data_store, ClipDataStore }
+            { prim_interner, PrimitiveDataInterner, prim_data_store, PrimitiveDataStore }
+            { normal_border_interner, NormalBorderDataInterner, normal_border_data_store, NormalBorderDataStore }
+            { image_border_interner, ImageBorderDataInterner, image_border_data_store, ImageBorderDataStore }
+            { image_interner, ImageDataInterner, image_data_store, ImageDataStore }
+            { yuv_image_interner, YuvImageDataInterner, yuv_image_data_store, YuvImageDataStore }
+            { line_decoration_interner, LineDecorationDataInterner,
+              line_decoration_data_store, LineDecorationDataStore }
+            { linear_grad_interner, LinearGradientDataInterner, linear_grad_data_store, LinearGradientDataStore }
+            { radial_grad_interner, RadialGradientDataInterner, radial_grad_data_store, RadialGradientDataStore }
+            { picture_interner, PictureDataInterner, picture_data_store, PictureDataStore }
+            { text_run_interner, TextRunDataInterner, text_run_data_store, TextRunDataStore }
         }
     }
 }
 
 macro_rules! declare_interning_memory_report {
-    ( $( $name: ident, )+ ) => {
+    ( $( { $interner_ident: ident, $x: ty, $datastore_ident: ident, $y: ty } )+ ) => {
         #[repr(C)]
         #[derive(Clone, Debug, Default, Deserialize, Serialize)]
-        pub struct InternerSubReport {
+        pub struct InterningMemoryReport {
             $(
-                pub $name: usize,
+                pub $interner_ident: usize,
+                pub $datastore_ident: usize,
             )+
         }
 
-        impl ::std::ops::AddAssign for InternerSubReport {
-            fn add_assign(&mut self, other: InternerSubReport) {
+        impl ::std::ops::AddAssign for InterningMemoryReport {
+            fn add_assign(&mut self, other: InterningMemoryReport) {
                 $(
-                    self.$name += other.$name;
+                    self.$interner_ident += other.$interner_ident;
+                    self.$datastore_ident += other.$datastore_ident;
                 )+
             }
         }
     }
 }
 
 enumerate_interners!(declare_interning_memory_report);
 
-/// Memory report for interning-related data structures.
-/// cbindgen:derive-eq=false
-#[repr(C)]
-#[derive(Clone, Debug, Default, Deserialize, Serialize)]
-pub struct InterningMemoryReport {
-    pub interners: InternerSubReport,
-    pub data_stores: InternerSubReport,
-}
-
-impl ::std::ops::AddAssign for InterningMemoryReport {
-    fn add_assign(&mut self, other: InterningMemoryReport) {
-        self.interners += other.interners;
-        self.data_stores += other.data_stores;
-    }
-}
-
 /// Collection of heap sizes, in bytes.
 /// cbindgen:derive-eq=false
 #[repr(C)]
 #[derive(Clone, Debug, Default, Deserialize, Serialize)]
 pub struct MemoryReport {
     //
     // CPU Memory.
     //