Bug 1498650. Update webrender to commit 5adc86c19cbef6697975ea078fa0d10635e5d660
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Sat, 13 Oct 2018 21:17:50 -0400
changeset 496882 08f77e821f0919fa33c0ef47f7dd3ff9e8f1a57d
parent 496881 5c8a070fcfe8691f7c6344bd7091b5a6a41a0739
child 496883 7cbf19248394a63dbbdb707d31e8b265c8a5aca3
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1498650
milestone64.0a1
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
Bug 1498650. Update webrender to commit 5adc86c19cbef6697975ea078fa0d10635e5d660
gfx/webrender/Cargo.toml
gfx/webrender/src/debug_render.rs
gfx/webrender/src/device/gl.rs
gfx/webrender/src/gpu_glyph_renderer.rs
gfx/webrender/src/renderer.rs
gfx/webrender_bindings/Cargo.toml
gfx/webrender_bindings/revision.txt
--- a/gfx/webrender/Cargo.toml
+++ b/gfx/webrender/Cargo.toml
@@ -22,17 +22,17 @@ serialize_program = ["serde"]
 app_units = "0.7"
 base64 = { optional = true, version = "0.6" }
 bincode = "1.0"
 bitflags = "1.0"
 byteorder = "1.0"
 cfg-if = "0.1.2"
 euclid = "0.19"
 fxhash = "0.2.1"
-gleam = "0.6.2"
+gleam = "0.6.3"
 image = { optional = true, version = "0.19" }
 lazy_static = "1"
 log = "0.4"
 num-traits = "0.2"
 plane-split = "0.13.2"
 png = { optional = true, version = "0.12" }
 rayon = "1"
 ron = { optional = true, version = "0.1.7" }
--- a/gfx/webrender/src/debug_render.rs
+++ b/gfx/webrender/src/debug_render.rs
@@ -118,25 +118,28 @@ impl DebugRenderer {
             "",
             &DESC_COLOR,
         )?;
 
         let font_vao = device.create_vao(&DESC_FONT);
         let line_vao = device.create_vao(&DESC_COLOR);
         let tri_vao = device.create_vao(&DESC_COLOR);
 
-        let font_texture = device.create_texture::<u8>(
+        let font_texture = device.create_texture(
             TextureTarget::Array,
             ImageFormat::R8,
             debug_font_data::BMP_WIDTH,
             debug_font_data::BMP_HEIGHT,
             TextureFilter::Linear,
             None,
             1,
-            Some(&debug_font_data::FONT_BITMAP),
+        );
+        device.upload_texture_immediate(
+            &font_texture,
+            &debug_font_data::FONT_BITMAP
         );
 
         Ok(DebugRenderer {
             font_vertices: Vec::new(),
             font_indices: Vec::new(),
             line_vertices: Vec::new(),
             tri_vao,
             tri_vertices: Vec::new(),
--- a/gfx/webrender/src/device/gl.rs
+++ b/gfx/webrender/src/device/gl.rs
@@ -9,16 +9,17 @@ use api::TextureTarget;
 #[cfg(any(feature = "debug_renderer", feature="capture"))]
 use api::ImageDescriptor;
 use euclid::Transform3D;
 use gleam::gl;
 use internal_types::{FastHashMap, RenderTargetInfo};
 use log::Level;
 use smallvec::SmallVec;
 use std::cell::RefCell;
+use std::cmp;
 use std::fs::File;
 use std::io::Read;
 use std::marker::PhantomData;
 use std::mem;
 use std::ops::Add;
 use std::path::PathBuf;
 use std::ptr;
 use std::rc::Rc;
@@ -40,22 +41,16 @@ impl FrameId {
 impl Add<usize> for FrameId {
     type Output = FrameId;
 
     fn add(self, other: usize) -> FrameId {
         FrameId(self.0 + other)
     }
 }
 
-const GL_FORMAT_RGBA: gl::GLuint = gl::RGBA;
-
-const GL_FORMAT_BGRA_GL: gl::GLuint = gl::BGRA;
-
-const GL_FORMAT_BGRA_GLES: gl::GLuint = gl::BGRA_EXT;
-
 const SHADER_VERSION_GL: &str = "#version 150\n";
 const SHADER_VERSION_GLES: &str = "#version 300 es\n";
 
 const SHADER_KIND_VERTEX: &str = "#define WR_VERTEX_SHADER\n";
 const SHADER_KIND_FRAGMENT: &str = "#define WR_FRAGMENT_SHADER\n";
 const SHADER_IMPORT: &str = "#include ";
 
 pub struct TextureSlot(pub usize);
@@ -732,32 +727,39 @@ pub struct Device {
 
     device_pixel_ratio: f32,
     upload_method: UploadMethod,
 
     // HW or API capabilities
     #[cfg(feature = "debug_renderer")]
     capabilities: Capabilities,
 
-    bgra_format: gl::GLuint,
+    bgra_format_internal: gl::GLuint,
+    bgra_format_external: gl::GLuint,
 
     // debug
     inside_frame: bool,
 
     // resources
     resource_override_path: Option<PathBuf>,
 
     max_texture_size: u32,
     renderer_name: String,
     cached_programs: Option<Rc<ProgramCache>>,
 
     // Frame counter. This is used to map between CPU
     // frames and GPU frames.
     frame_id: FrameId,
 
+    /// Whether glTexStorage* is supported. We prefer this over glTexImage*
+    /// because it guarantees that mipmaps won't be generated (which they
+    /// otherwise are on some drivers, particularly ANGLE), If it's not
+    /// supported, we fall back to glTexImage*.
+    supports_texture_storage: bool,
+
     // GL extensions
     extensions: Vec<String>,
 }
 
 impl Device {
     pub fn new(
         gl: Rc<gl::Gl>,
         resource_override_path: Option<PathBuf>,
@@ -776,56 +778,77 @@ impl Device {
             gl.get_integer_v(gl::NUM_EXTENSIONS, &mut extension_count);
         }
         let extension_count = extension_count[0] as gl::GLuint;
         let mut extensions = Vec::new();
         for i in 0 .. extension_count {
             extensions.push(gl.get_string_i(gl::EXTENSIONS, i));
         }
 
+        // Our common-case image data in Firefox is BGRA, so we make an effort
+        // to use BGRA as the internal texture storage format to avoid the need
+        // to swizzle during upload. Currently we only do this on GLES (and thus
+        // for Windows, via ANGLE).
+        //
+        // On Mac, Apple docs [1] claim that BGRA is a more efficient internal
+        // format, so we may want to consider doing that at some point, since it
+        // would give us both a more efficient internal format and avoid the
+        // swizzling in the common case.
+        //
+        // We also need our internal format types to be sized, since glTexStorage*
+        // will reject non-sized internal format types.
+        //
+        // [1] https://developer.apple.com/library/archive/documentation/
+        //     GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/
+        //     opengl_texturedata.html#//apple_ref/doc/uid/TP40001987-CH407-SW22
         let supports_bgra = supports_extension(&extensions, "GL_EXT_texture_format_BGRA8888");
-        let bgra_format = match gl.get_type() {
-            gl::GlType::Gl => GL_FORMAT_BGRA_GL,
-            gl::GlType::Gles => if supports_bgra {
-                GL_FORMAT_BGRA_GLES
-            } else {
-                GL_FORMAT_RGBA
-            }
+        let (bgra_format_internal, bgra_format_external) = if supports_bgra {
+            assert_eq!(gl.get_type(), gl::GlType::Gles, "gleam only detects bgra on gles");
+            (gl::BGRA8_EXT, gl::BGRA_EXT)
+        } else {
+            (gl::RGBA8, gl::BGRA)
+        };
+
+        let supports_texture_storage = match gl.get_type() {
+            gl::GlType::Gl => supports_extension(&extensions, "GL_ARB_texture_storage"),
+            gl::GlType::Gles => true,
         };
 
         Device {
             gl,
             resource_override_path,
             // This is initialized to 1 by default, but it is reset
             // at the beginning of each frame in `Renderer::bind_frame_data`.
             device_pixel_ratio: 1.0,
             upload_method,
             inside_frame: false,
 
             #[cfg(feature = "debug_renderer")]
             capabilities: Capabilities {
                 supports_multisampling: false, //TODO
             },
 
-            bgra_format,
+            bgra_format_internal,
+            bgra_format_external,
 
             bound_textures: [0; 16],
             bound_program: 0,
             bound_vao: 0,
             bound_read_fbo: FBOId(0),
             bound_draw_fbo: FBOId(0),
             program_mode_id: UniformLocation::INVALID,
             default_read_fbo: 0,
             default_draw_fbo: 0,
 
             max_texture_size,
             renderer_name,
             cached_programs,
             frame_id: FrameId(0),
             extensions,
+            supports_texture_storage,
         }
     }
 
     pub fn gl(&self) -> &gl::Gl {
         &*self.gl
     }
 
     pub fn rc_gl(&self) -> &Rc<gl::Gl> {
@@ -1177,26 +1200,25 @@ impl Device {
 
         if self.bound_program != program.id {
             self.gl.use_program(program.id);
             self.bound_program = program.id;
             self.program_mode_id = UniformLocation(program.u_mode);
         }
     }
 
-    pub fn create_texture<T: Texel>(
+    pub fn create_texture(
         &mut self,
         target: TextureTarget,
         format: ImageFormat,
         mut width: u32,
         mut height: u32,
         filter: TextureFilter,
         render_target: Option<RenderTargetInfo>,
         layer_count: i32,
-        pixels: Option<&[T]>,
     ) -> Texture {
         debug_assert!(self.inside_frame);
 
         if width > self.max_texture_size || height > self.max_texture_size {
             error!("Attempting to allocate a texture of size {}x{} above the limit, trimming", width, height);
             width = width.min(self.max_texture_size);
             height = height.min(self.max_texture_size);
         }
@@ -1215,46 +1237,79 @@ impl Device {
             depth_rb: None,
             last_frame_used: self.frame_id,
         };
         self.bind_texture(DEFAULT_TEXTURE, &texture);
         self.set_texture_parameters(texture.target, filter);
 
         // Allocate storage.
         let desc = self.gl_describe_format(texture.format);
-        match texture.target {
-            gl::TEXTURE_2D_ARRAY => {
+        let is_array = match texture.target {
+            gl::TEXTURE_2D_ARRAY => true,
+            gl::TEXTURE_2D | gl::TEXTURE_RECTANGLE | gl::TEXTURE_EXTERNAL_OES => false,
+            _ => panic!("BUG: Unexpected texture target!"),
+        };
+        assert!(is_array || texture.layer_count == 1);
+
+        // Firefox doesn't use mipmaps, but Servo uses them for standalone image
+        // textures images larger than 512 pixels. This is the only case where
+        // we set the filter to trilinear.
+        let mipmap_levels =  if texture.filter == TextureFilter::Trilinear {
+            let max_dimension = cmp::max(width, height);
+            ((max_dimension) as f64).log2() as gl::GLint + 1
+        } else {
+            1
+        };
+
+        // Use glTexStorage where available, since it avoids allocating
+        // unnecessary mipmap storage and generally improves performance with
+        // stronger invariants.
+        match (self.supports_texture_storage, is_array) {
+            (true, true) =>
+                self.gl.tex_storage_3d(
+                    gl::TEXTURE_2D_ARRAY,
+                    mipmap_levels,
+                    desc.internal,
+                    texture.width as gl::GLint,
+                    texture.height as gl::GLint,
+                    texture.layer_count,
+                ),
+            (true, false) =>
+                self.gl.tex_storage_2d(
+                    texture.target,
+                    mipmap_levels,
+                    desc.internal,
+                    texture.width as gl::GLint,
+                    texture.height as gl::GLint,
+                ),
+            (false, true) =>
                 self.gl.tex_image_3d(
                     gl::TEXTURE_2D_ARRAY,
                     0,
-                    desc.internal,
-                    texture.width as _,
-                    texture.height as _,
+                    desc.internal as gl::GLint,
+                    texture.width as gl::GLint,
+                    texture.height as gl::GLint,
                     texture.layer_count,
                     0,
                     desc.external,
                     desc.pixel_type,
-                    pixels.map(texels_to_u8_slice),
-                )
-            }
-            gl::TEXTURE_2D | gl::TEXTURE_RECTANGLE | gl::TEXTURE_EXTERNAL_OES => {
-                assert_eq!(texture.layer_count, 1);
+                    None,
+                ),
+            (false, false) =>
                 self.gl.tex_image_2d(
                     texture.target,
                     0,
-                    desc.internal,
-                    texture.width as _,
-                    texture.height as _,
+                    desc.internal as gl::GLint,
+                    texture.width as gl::GLint,
+                    texture.height as gl::GLint,
                     0,
                     desc.external,
                     desc.pixel_type,
-                    pixels.map(texels_to_u8_slice),
-                )
-            },
-            _ => panic!("BUG: Unexpected texture target!"),
+                    None,
+                ),
         }
 
         // Set up FBOs, if required.
         if let Some(rt_info) = render_target {
             self.init_fbos(&mut texture, rt_info);
         }
 
         texture
@@ -1297,16 +1352,36 @@ impl Device {
         for (read_fbo, draw_fbo) in src.fbo_ids.iter().zip(&dst.fbo_ids) {
             self.bind_read_target_impl(*read_fbo);
             self.bind_draw_target_impl(*draw_fbo);
             self.blit_render_target(rect, rect);
         }
         self.bind_read_target(None);
     }
 
+    /// Notifies the device that the contents of a render target are no longer
+    /// needed.
+    pub fn invalidate_render_target(&mut self, texture: &Texture) {
+        let attachments: &[gl::GLenum] = if texture.has_depth() {
+            &[gl::COLOR_ATTACHMENT0, gl::DEPTH_ATTACHMENT]
+        } else {
+            &[gl::COLOR_ATTACHMENT0]
+        };
+
+        let original_bound_fbo = self.bound_draw_fbo;
+        for fbo_id in texture.fbo_ids.iter() {
+            // Note: The invalidate extension may not be supported, in which
+            // case this is a no-op. That's ok though, because it's just a
+            // hint.
+            self.bind_external_draw_target(*fbo_id);
+            self.gl.invalidate_framebuffer(gl::FRAMEBUFFER, attachments);
+        }
+        self.bind_external_draw_target(original_bound_fbo);
+    }
+
     /// Notifies the device that a render target is about to be reused.
     ///
     /// This method adds or removes a depth target as necessary.
     pub fn reuse_render_target<T: Texel>(
         &mut self,
         texture: &mut Texture,
         rt_info: RenderTargetInfo,
     ) {
@@ -1574,24 +1649,63 @@ impl Device {
                 }
                 Some(PixelBuffer::new(hint.to_gl(), upload_size))
             },
         };
 
         TextureUploader {
             target: UploadTarget {
                 gl: &*self.gl,
-                bgra_format: self.bgra_format,
+                bgra_format: self.bgra_format_external,
                 texture,
             },
             buffer,
             marker: PhantomData,
         }
     }
 
+    /// Performs an immediate (non-PBO) texture upload.
+    pub fn upload_texture_immediate<T: Texel>(
+        &mut self,
+        texture: &Texture,
+        pixels: &[T]
+    ) {
+        self.bind_texture(DEFAULT_TEXTURE, texture);
+        let desc = self.gl_describe_format(texture.format);
+        match texture.target {
+            gl::TEXTURE_2D | gl::TEXTURE_RECTANGLE | gl::TEXTURE_EXTERNAL_OES =>
+                self.gl.tex_sub_image_2d(
+                    texture.target,
+                    0,
+                    0,
+                    0,
+                    texture.width as gl::GLint,
+                    texture.height as gl::GLint,
+                    desc.external,
+                    desc.pixel_type,
+                    texels_to_u8_slice(pixels),
+                ),
+            gl::TEXTURE_2D_ARRAY =>
+                self.gl.tex_sub_image_3d(
+                    texture.target,
+                    0,
+                    0,
+                    0,
+                    0,
+                    texture.width as gl::GLint,
+                    texture.height as gl::GLint,
+                    texture.layer_count as gl::GLint,
+                    desc.external,
+                    desc.pixel_type,
+                    texels_to_u8_slice(pixels),
+                ),
+            _ => panic!("BUG: Unexpected texture target!"),
+        }
+    }
+
     #[cfg(any(feature = "debug_renderer", feature = "capture"))]
     pub fn read_pixels(&mut self, img_desc: &ImageDescriptor) -> Vec<u8> {
         let desc = self.gl_describe_format(img_desc.format);
         self.gl.read_pixels(
             0, 0,
             img_desc.size.width as i32,
             img_desc.size.height as i32,
             desc.external,
@@ -1608,17 +1722,17 @@ impl Device {
     ) {
         let (bytes_per_pixel, desc) = match format {
             ReadPixelsFormat::Standard(imf) => {
                 (imf.bytes_per_pixel(), self.gl_describe_format(imf))
             }
             ReadPixelsFormat::Rgba8 => {
                 (4, FormatDesc {
                     external: gl::RGBA,
-                    internal: gl::RGBA8 as _,
+                    internal: gl::RGBA8,
                     pixel_type: gl::UNSIGNED_BYTE,
                 })
             }
         };
         let size_in_bytes = (bytes_per_pixel * rect.size.width * rect.size.height) as usize;
         assert_eq!(output.len(), size_in_bytes);
 
         self.gl.flush();
@@ -2165,57 +2279,53 @@ impl Device {
             };
             log!(level, "({}) {}", ty, msg.message);
         }
     }
 
     fn gl_describe_format(&self, format: ImageFormat) -> FormatDesc {
         match format {
             ImageFormat::R8 => FormatDesc {
-                internal: gl::R8 as _,
+                internal: gl::R8,
                 external: gl::RED,
                 pixel_type: gl::UNSIGNED_BYTE,
             },
             ImageFormat::R16 => FormatDesc {
-                internal: gl::R16 as _,
+                internal: gl::R16,
                 external: gl::RED,
                 pixel_type: gl::UNSIGNED_SHORT,
             },
             ImageFormat::BGRA8 => {
-                let external = self.bgra_format;
                 FormatDesc {
-                    internal: match self.gl.get_type() {
-                        gl::GlType::Gl => gl::RGBA as _,
-                        gl::GlType::Gles => external as _,
-                    },
-                    external,
+                    internal: self.bgra_format_internal,
+                    external: self.bgra_format_external,
                     pixel_type: gl::UNSIGNED_BYTE,
                 }
             },
             ImageFormat::RGBAF32 => FormatDesc {
-                internal: gl::RGBA32F as _,
+                internal: gl::RGBA32F,
                 external: gl::RGBA,
                 pixel_type: gl::FLOAT,
             },
             ImageFormat::RGBAI32 => FormatDesc {
-                internal: gl::RGBA32I as _,
+                internal: gl::RGBA32I,
                 external: gl::RGBA_INTEGER,
                 pixel_type: gl::INT,
             },
             ImageFormat::RG8 => FormatDesc {
-                internal: gl::RG8 as _,
+                internal: gl::RG8,
                 external: gl::RG,
                 pixel_type: gl::UNSIGNED_BYTE,
             },
         }
     }
 }
 
 struct FormatDesc {
-    internal: gl::GLint,
+    internal: gl::GLenum,
     external: gl::GLuint,
     pixel_type: gl::GLuint,
 }
 
 struct UploadChunk {
     rect: DeviceUintRect,
     layer_index: i32,
     stride: Option<u32>,
--- a/gfx/webrender/src/gpu_glyph_renderer.rs
+++ b/gfx/webrender/src/gpu_glyph_renderer.rs
@@ -57,18 +57,18 @@ impl GpuGlyphRenderer {
         let area_lut_texture = device.create_texture(
             TextureTarget::Default,
             ImageFormat::R8,
             area_lut_width,
             area_lut_height,
             TextureFilter::Linear,
             None,
             1,
-            Some(area_lut_pixels)
         );
+        device.upload_texture_immediate(&area_lut_texture, area_lut_pixels);
 
         let vector_stencil_vao =
             device.create_vao_with_new_instances(&renderer::desc::VECTOR_STENCIL, prim_vao);
         let vector_cover_vao = device.create_vao_with_new_instances(&renderer::desc::VECTOR_COVER,
                                                                     prim_vao);
 
         // Load Pathfinder vector graphics shaders.
         let vector_stencil = try!{
@@ -105,27 +105,26 @@ impl Renderer {
                           stats: &mut RendererStats)
                           -> Option<StenciledGlyphPage> {
         if glyphs.is_empty() {
             return None
         }
 
         let _timer = self.gpu_profile.start_timer(GPU_TAG_GLYPH_STENCIL);
 
-        let texture = self.device.create_texture::<f32>(
+        let texture = self.device.create_texture(
             TextureTarget::Default,
             ImageFormat::RGBAF32,
             target_size.width,
             target_size.height,
             TextureFilter::Nearest,
             Some(RenderTargetInfo {
                 has_depth: false,
             }),
             1,
-            None
         );
 
         // Initialize temporary framebuffer.
         // FIXME(pcwalton): Cache this!
         // FIXME(pcwalton): Use RF32, not RGBAF32!
         let mut current_page = StenciledGlyphPage {
             texture,
             glyphs: vec![],
@@ -183,18 +182,18 @@ impl Renderer {
         let path_info_texture = self.device.create_texture(
             TextureTarget::Default,
             ImageFormat::RGBAF32,
             3,
             glyphs.len() as u32,
             TextureFilter::Nearest,
             None,
             1,
-            Some(&path_info_texels)
         );
+        self.device.upload_texture_immediate(&path_info_texture, &path_info_texels);
 
         self.gpu_glyph_renderer.vector_stencil.bind(&mut self.device,
                                                     projection,
                                                     &mut self.renderer_errors);
 
         self.device.bind_draw_target(Some((&current_page.texture, 0)), Some(*target_size));
         self.device.clear_target(Some([0.0, 0.0, 0.0, 0.0]), None, None);
 
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -808,25 +808,24 @@ struct TextureResolver {
     /// See the comments in `allocate_target_texture` for more insight on why
     /// reuse is a win.
     render_target_pool: Vec<Texture>,
 }
 
 impl TextureResolver {
     fn new(device: &mut Device) -> TextureResolver {
         let dummy_cache_texture = device
-            .create_texture::<u8>(
+            .create_texture(
                 TextureTarget::Array,
                 ImageFormat::BGRA8,
                 1,
                 1,
                 TextureFilter::Linear,
                 None,
                 1,
-                None,
             );
 
         TextureResolver {
             texture_cache_map: FastHashMap::default(),
             external_images: FastHashMap::default(),
             dummy_cache_texture,
             prev_pass_alpha: None,
             prev_pass_color: None,
@@ -850,69 +849,78 @@ impl TextureResolver {
     fn begin_frame(&mut self) {
         assert!(self.prev_pass_color.is_none());
         assert!(self.prev_pass_alpha.is_none());
         assert!(self.saved_targets.is_empty());
     }
 
     fn end_frame(&mut self, device: &mut Device, frame_id: FrameId) {
         // return the cached targets to the pool
-        self.end_pass(None, None);
+        self.end_pass(device, None, None);
         // return the saved targets as well
-        self.render_target_pool.extend(self.saved_targets.drain(..));
+        while let Some(target) = self.saved_targets.pop() {
+            self.return_to_pool(device, target);
+        }
 
         // GC the render target pool.
         //
         // We use a simple scheme whereby we drop any texture that hasn't been used
         // in the last 30 frames. This should generally prevent any sustained build-
         // up of unused textures, unless we don't generate frames for a long period.
         // This can happen when the window is minimized, and we probably want to
         // flush all the WebRender caches in that case [1].
         //
         // [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1494099
         self.retain_targets(device, |texture| texture.used_recently(frame_id, 30));
     }
 
+    /// Transfers ownership of a render target back to the pool.
+    fn return_to_pool(&mut self, device: &mut Device, target: Texture) {
+        device.invalidate_render_target(&target);
+        self.render_target_pool.push(target);
+    }
+
     /// Drops all targets from the render target pool that do not satisfy the predicate.
     pub fn retain_targets<F: Fn(&Texture) -> bool>(&mut self, device: &mut Device, f: F) {
         // We can't just use retain() because `Texture` requires manual cleanup.
         let mut tmp = SmallVec::<[Texture; 8]>::new();
         for target in self.render_target_pool.drain(..) {
             if f(&target) {
                 tmp.push(target);
             } else {
                 device.delete_texture(target);
             }
         }
         self.render_target_pool.extend(tmp);
     }
 
     fn end_pass(
         &mut self,
+        device: &mut Device,
         a8_texture: Option<ActiveTexture>,
         rgba8_texture: Option<ActiveTexture>,
     ) {
         // If we have cache textures from previous pass, return them to the pool.
         // Also assign the pool index of those cache textures to last pass's index because this is
         // the result of last pass.
         // Note: the order here is important, needs to match the logic in `RenderPass::build()`.
         if let Some(at) = self.prev_pass_color.take() {
             if let Some(index) = at.saved_index {
                 assert_eq!(self.saved_targets.len(), index.0);
                 self.saved_targets.push(at.texture);
             } else {
-                self.render_target_pool.push(at.texture);
+                self.return_to_pool(device, at.texture);
             }
         }
         if let Some(at) = self.prev_pass_alpha.take() {
             if let Some(index) = at.saved_index {
                 assert_eq!(self.saved_targets.len(), index.0);
                 self.saved_targets.push(at.texture);
             } else {
-                self.render_target_pool.push(at.texture);
+                self.return_to_pool(device, at.texture);
             }
         }
 
         // We have another pass to process, make these textures available
         // as inputs to the next pass.
         self.prev_pass_color = rgba8_texture;
         self.prev_pass_alpha = a8_texture;
     }
@@ -1098,25 +1106,24 @@ impl GpuCacheTexture {
             if rt_info.is_some() {
                 blit_source = Some(t);
             } else {
                 device.delete_texture(t);
             }
         }
 
         // Create the new texture.
-        let mut texture = device.create_texture::<u8>(
+        let mut texture = device.create_texture(
             TextureTarget::Default,
             ImageFormat::RGBAF32,
             new_size.width,
             new_size.height,
             TextureFilter::Nearest,
             rt_info,
             1,
-            None,
         );
 
         // Blit the contents of the previous texture, if applicable.
         if let Some(blit_source) = blit_source {
             device.blit_renderable_texture(&mut texture, &blit_source);
             device.delete_texture(blit_source);
         }
 
@@ -1395,25 +1402,24 @@ impl VertexDataTexture {
         // Create a new texture if needed.
         if needed_height > existing_height {
             // Drop the existing texture, if any.
             if let Some(t) = self.texture.take() {
                 device.delete_texture(t);
             }
             let new_height = (needed_height + 127) & !127;
 
-            let texture = device.create_texture::<u8>(
+            let texture = device.create_texture(
                 TextureTarget::Default,
                 self.format,
                 width,
                 new_height,
                 TextureFilter::Nearest,
                 None,
                 1,
-                None,
             );
             self.texture = Some(texture);
         }
 
         let rect = DeviceUintRect::new(
             DeviceUintPoint::zero(),
             DeviceUintSize::new(width, needed_height),
         );
@@ -1751,26 +1757,26 @@ impl Renderer {
                 38,
                 22,
                 41,
                 25,
                 37,
                 21,
             ];
 
-            let mut texture = device.create_texture::<u8>(
+            let mut texture = device.create_texture(
                 TextureTarget::Default,
                 ImageFormat::R8,
                 8,
                 8,
                 TextureFilter::Nearest,
                 None,
                 1,
-                Some(&dither_matrix),
             );
+            device.upload_texture_immediate(&texture, &dither_matrix);
 
             Some(texture)
         } else {
             None
         };
 
         let x0 = 0.0;
         let y0 = 0.0;
@@ -2769,25 +2775,24 @@ impl Renderer {
                         format,
                         filter,
                         render_target,
                     } => {
                         // Create a new native texture, as requested by the texture cache.
                         //
                         // Ensure no PBO is bound when creating the texture storage,
                         // or GL will attempt to read data from there.
-                        let texture = self.device.create_texture::<u8>(
+                        let texture = self.device.create_texture(
                             TextureTarget::Array,
                             format,
                             width,
                             height,
                             filter,
                             render_target,
                             layer_count,
-                            None,
                         );
                         self.texture_resolver.texture_cache_map.insert(update.id, texture);
                     }
                     TextureUpdateOp::Update {
                         rect,
                         source,
                         stride,
                         layer_index,
@@ -3810,27 +3815,25 @@ impl Renderer {
 
         let rt_info = RenderTargetInfo { has_depth: list.needs_depth() };
         let texture = if let Some(idx) = index {
             let mut t = self.texture_resolver.render_target_pool.swap_remove(idx);
             self.device.reuse_render_target::<u8>(&mut t, rt_info);
             t
         } else {
             counters.targets_created.inc();
-            let mut t = self.device.create_texture::<u8>(
+            self.device.create_texture(
                 TextureTarget::Array,
                 list.format,
                 list.max_size.width,
                 list.max_size.height,
                 TextureFilter::Linear,
                 Some(rt_info),
                 list.targets.len() as _,
-                None,
-            );
-            t
+            )
         };
 
         list.check_ready(&texture);
         Some(ActiveTexture {
             texture,
             saved_index: list.saved_index.clone(),
         })
     }
@@ -4011,16 +4014,17 @@ impl Renderer {
                         );
                     }
 
                     (alpha_tex, color_tex)
                 }
             };
 
             self.texture_resolver.end_pass(
+                &mut self.device,
                 cur_alpha,
                 cur_color,
             );
         }
 
         self.texture_resolver.end_frame(&mut self.device, frame_id);
 
         #[cfg(feature = "debug_renderer")]
@@ -4758,18 +4762,18 @@ impl Renderer {
         let texture = device.create_texture(
             target,
             plain.format,
             plain.size.0,
             plain.size.1,
             plain.filter,
             plain.render_target,
             plain.size.2,
-            Some(texels.as_slice()),
         );
+        device.upload_texture_immediate(&texture, &texels);
 
         (texture, texels)
     }
 
     #[cfg(feature = "capture")]
     fn save_capture(
         &mut self,
         config: CaptureConfig,
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -4,17 +4,17 @@ version = "0.1.0"
 authors = ["The Mozilla Project Developers"]
 license = "MPL-2.0"
 
 [dependencies]
 rayon = "1"
 thread_profiler = "0.1.1"
 euclid = { version = "0.19", features = ["serde"] }
 app_units = "0.7"
-gleam = "0.6.2"
+gleam = "0.6.3"
 log = "0.4"
 nsstring = { path = "../../servo/support/gecko/nsstring" }
 bincode = "1.0"
 uuid = { version = "0.5", features = ["v4"] }
 fxhash = "0.2.1"
 
 [dependencies.webrender]
 path = "../webrender"
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-7aa1d42ad41097b68e8026e3384127242601c95b
+5adc86c19cbef6697975ea078fa0d10635e5d660