Bug 1498650. Update webrender to commit 5adc86c19cbef6697975ea078fa0d10635e5d660
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Sat, 13 Oct 2018 21:17:50 -0400
changeset 489477 08f77e821f0919fa33c0ef47f7dd3ff9e8f1a57d
parent 489476 5c8a070fcfe8691f7c6344bd7091b5a6a41a0739
child 489478 7cbf19248394a63dbbdb707d31e8b265c8a5aca3
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
bugs1498650
milestone64.0a1
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