diff --git a/webrender/res/ps_image_rect.fs.glsl b/webrender/res/ps_image_rect.fs.glsl new file mode 100644 index 0000000000..b5ba2b7fec --- /dev/null +++ b/webrender/res/ps_image_rect.fs.glsl @@ -0,0 +1,35 @@ +#line 1 + +/* 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/. */ + +void main(void) { +#ifdef WR_FEATURE_TRANSFORM + float alpha = 0.0; + vec2 pos = init_transform_fs(vLocalPos, vLocalRect, alpha); + + // We clamp the texture coordinate calculation here to the local rectangle boundaries, + // which makes the edge of the texture stretch instead of repeat. + vec2 relative_pos_in_rect = + clamp(pos, vLocalRect.xy, vLocalRect.xy + vLocalRect.zw) - vLocalRect.xy; +#else + float alpha = 1.0; + vec2 relative_pos_in_rect = vLocalPos; +#endif + + alpha = min(alpha, do_clip()); + + // We calculate the particular tile this fragment belongs to, taking into + // account the spacing in between tiles. We only paint if our fragment does + // not fall into that spacing. + vec2 position_in_tile = mod(relative_pos_in_rect, vStretchSize + vTileSpacing); + // We clamp the texture coordinates to the half-pixel offset from the borders + // in order to avoid sampling outside of the texture area. + vec2 st = vTextureOffset + ((position_in_tile / vStretchSize) * vTextureSize); + st = clamp(st, vStRect.xy, vStRect.zw); + + alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize)))); + + oFragColor = vec4(alpha) * texture(sColor0, st); +} diff --git a/webrender/res/ps_image_rect.glsl b/webrender/res/ps_image_rect.glsl new file mode 100644 index 0000000000..18a01d863a --- /dev/null +++ b/webrender/res/ps_image_rect.glsl @@ -0,0 +1,17 @@ +/* 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/. */ + +flat varying vec2 vTextureOffset; // Offset of this image into the texture atlas. +flat varying vec2 vTextureSize; // Size of the image in the texture atlas. +flat varying vec2 vTileSpacing; // Amount of space between tiled instances of this image. +flat varying vec4 vStRect; // Rectangle of valid texture rect, in st-space. + +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; +flat varying vec4 vLocalRect; +flat varying vec2 vStretchSize; +#else +varying vec2 vLocalPos; +flat varying vec2 vStretchSize; +#endif diff --git a/webrender/res/ps_image_rect.vs.glsl b/webrender/res/ps_image_rect.vs.glsl new file mode 100644 index 0000000000..5eb78b01e7 --- /dev/null +++ b/webrender/res/ps_image_rect.vs.glsl @@ -0,0 +1,39 @@ +#line 1 +/* 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/. */ + +void main(void) { + Primitive prim = load_primitive(); + Image image = fetch_image(prim.prim_index); + ResourceRect res = fetch_resource_rect(prim.user_data.x); + +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.task); + vLocalRect = vi.clipped_local_rect; + vLocalPos = vi.local_pos; +#else + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.task); + vLocalPos = vi.local_pos - vi.local_rect.p0; +#endif + + write_clip(vi.screen_pos, prim.clip_area); + + vec2 st0 = res.uv_rect.xy; + vec2 st1 = res.uv_rect.zw; + + vTextureSize = st1 - st0; + vTextureOffset = st0; + vTileSpacing = image.stretch_size_and_tile_spacing.zw; + vStretchSize = image.stretch_size_and_tile_spacing.xy; + + vStRect = vec4(min(st0, st1), max(st0, st1)); +} diff --git a/webrender/res/shared.glsl b/webrender/res/shared.glsl index f250a709c6..3922f74986 100644 --- a/webrender/res/shared.glsl +++ b/webrender/res/shared.glsl @@ -33,9 +33,15 @@ //====================================================================================== // Shared shader uniforms //====================================================================================== +#ifndef WR_FEATURE_TEXTURE_RECT uniform sampler2D sColor0; uniform sampler2D sColor1; uniform sampler2D sColor2; +#else +uniform sampler2DRect sColor0; +uniform sampler2DRect sColor1; +uniform sampler2DRect sColor2; +#endif uniform sampler2D sMask; //====================================================================================== diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index c2af4f49d2..40ed7b7148 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -64,6 +64,7 @@ const GPU_TAG_INIT: GpuProfileTag = GpuProfileTag { label: "Init", color: debug_ const GPU_TAG_SETUP_TARGET: GpuProfileTag = GpuProfileTag { label: "Target", color: debug_colors::SLATEGREY }; const GPU_TAG_PRIM_RECT: GpuProfileTag = GpuProfileTag { label: "Rect", color: debug_colors::RED }; const GPU_TAG_PRIM_IMAGE: GpuProfileTag = GpuProfileTag { label: "Image", color: debug_colors::GREEN }; +const GPU_TAG_PRIM_IMAGE_RECT: GpuProfileTag = GpuProfileTag { label: "ImageRect", color: debug_colors::GREENYELLOW }; const GPU_TAG_PRIM_YUV_IMAGE: GpuProfileTag = GpuProfileTag { label: "YuvImage", color: debug_colors::DARKGREEN }; const GPU_TAG_PRIM_BLEND: GpuProfileTag = GpuProfileTag { label: "Blend", color: debug_colors::LIGHTBLUE }; const GPU_TAG_PRIM_HW_COMPOSITE: GpuProfileTag = GpuProfileTag { label: "HwComposite", color: debug_colors::DODGERBLUE }; @@ -215,6 +216,7 @@ pub type GradientDataStore = GpuStore; const TRANSFORM_FEATURE: &'static str = "TRANSFORM"; const SUBPIXEL_AA_FEATURE: &'static str = "SUBPIXEL_AA"; const CLIP_FEATURE: &'static str = "CLIP"; +const TEXTURE_RECT_FEATURE: &'static str = "TEXTURE_RECT"; enum ShaderKind { Primitive, @@ -457,6 +459,7 @@ pub struct Renderer { ps_text_run: PrimitiveShader, ps_text_run_subpixel: PrimitiveShader, ps_image: PrimitiveShader, + ps_image_rect: PrimitiveShader, ps_yuv_image: PrimitiveShader, ps_border: PrimitiveShader, ps_gradient: PrimitiveShader, @@ -659,6 +662,13 @@ impl Renderer { options.precache_shaders) }; + let ps_image_rect = try!{ + PrimitiveShader::new("ps_image_rect", + &mut device, + &[ TEXTURE_RECT_FEATURE ], + options.precache_shaders) + }; + let ps_yuv_image = try!{ PrimitiveShader::new("ps_yuv_image", &mut device, @@ -880,6 +890,7 @@ impl Renderer { ps_text_run: ps_text_run, ps_text_run_subpixel: ps_text_run_subpixel, ps_image: ps_image, + ps_image_rect: ps_image_rect, ps_yuv_image: ps_yuv_image, ps_border: ps_border, ps_box_shadow: ps_box_shadow, @@ -1309,6 +1320,10 @@ impl Renderer { let shader = self.ps_image.get(&mut self.device, transform_kind); (GPU_TAG_PRIM_IMAGE, shader) } + AlphaBatchKind::ImageRect => { + let shader = self.ps_image_rect.get(&mut self.device, transform_kind); + (GPU_TAG_PRIM_IMAGE_RECT, shader) + } AlphaBatchKind::YuvImage => { let shader = self.ps_yuv_image.get(&mut self.device, transform_kind); (GPU_TAG_PRIM_YUV_IMAGE, shader) diff --git a/webrender/src/tiling.rs b/webrender/src/tiling.rs index 0ac82dfc6b..7f5c5a65a2 100644 --- a/webrender/src/tiling.rs +++ b/webrender/src/tiling.rs @@ -26,6 +26,7 @@ use webrender_traits::{AuxiliaryLists, ColorF, DeviceIntPoint, DeviceIntRect, De use webrender_traits::{DeviceUintSize, FontRenderMode, ImageRendering, LayerPoint, LayerRect}; use webrender_traits::{LayerToWorldTransform, MixBlendMode, PipelineId, ScrollLayerId}; use webrender_traits::{WorldPoint4D, WorldToLayerTransform}; +use webrender_traits::{ExternalImageType}; // Special sentinel value recognized by the shader. It is considered to be // a dummy task that doesn't mask out anything. @@ -68,7 +69,24 @@ impl AlphaBatchHelpers for PrimitiveStore { let batch_kind = match metadata.prim_kind { PrimitiveKind::Border => AlphaBatchKind::Border, PrimitiveKind::BoxShadow => AlphaBatchKind::BoxShadow, - PrimitiveKind::Image => AlphaBatchKind::Image, + PrimitiveKind::Image => { + let image_cpu = &self.cpu_images[metadata.cpu_prim_index.0]; + + match image_cpu.color_texture_id { + SourceTexture::External(ext_image) => { + match ext_image.image_type { + ExternalImageType::Texture2DHandle => AlphaBatchKind::Image, + ExternalImageType::TextureRectHandle => AlphaBatchKind::ImageRect, + _ => { + panic!("Non-texture handle type should be handled in other way."); + } + } + } + _ => { + AlphaBatchKind::Image + } + } + } PrimitiveKind::YuvImage => AlphaBatchKind::YuvImage, PrimitiveKind::Rectangle => AlphaBatchKind::Rectangle, PrimitiveKind::AlignedGradient => AlphaBatchKind::AlignedGradient, @@ -269,7 +287,8 @@ impl AlphaBatchHelpers for PrimitiveStore { }); } } - AlphaBatchKind::Image => { + AlphaBatchKind::Image | + AlphaBatchKind::ImageRect => { let image_cpu = &self.cpu_images[metadata.cpu_prim_index.0]; data.push(PrimitiveInstance { @@ -1129,6 +1148,7 @@ pub enum AlphaBatchKind { Rectangle, TextRun, Image, + ImageRect, YuvImage, Border, AlignedGradient, @@ -1259,6 +1279,7 @@ impl PrimitiveBatch { AlphaBatchKind::Rectangle | AlphaBatchKind::TextRun | AlphaBatchKind::Image | + AlphaBatchKind::ImageRect | AlphaBatchKind::YuvImage | AlphaBatchKind::Border | AlphaBatchKind::AlignedGradient |