Skip to content

Commit

Permalink
Auto merge of #997 - JerryShih:gl-texture-rect-support, r=kvark
Browse files Browse the repository at this point in the history
GL_TEXTURE_RECTANGLE texture target support

@glennw @kvark @nical @sotaroikeda
The hardware video decoder in mac platform is usually decoding the video content into MacIOSurface. The MacIOSurface could just map to  an GL_TEXTURE_RECTANGLE gl texture without any uploading. That's good for video playing.
These patches try to add a new type of external gl rect image and its corresponding shader.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/997)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Mar 30, 2017
2 parents 1b9b265 + bbfefcc commit 9800670
Show file tree
Hide file tree
Showing 14 changed files with 305 additions and 157 deletions.
7 changes: 5 additions & 2 deletions webrender/res/ps_image.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ void main(void) {
// 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))));

#ifdef WR_FEATURE_TEXTURE_RECT
// textureLod doesn't support sampler2DRect. Use texture() instead.
oFragColor = vec4(alpha) * texture(sColor0, st);
#else
oFragColor = vec4(alpha) * textureLod(sColor0, st, 0.0);
#endif
}
5 changes: 4 additions & 1 deletion webrender/res/ps_image.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
* 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/. */

// If this is in WR_FEATURE_TEXTURE_RECT mode, the rect and size use non-normalized
// texture coordinates. Otherwise, it uses normalized texture coordinates. Please
// check GL_TEXTURE_RECTANGLE.
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.
flat varying vec4 vStRect; // Rectangle of valid texture rect.

#ifdef WR_FEATURE_TRANSFORM
varying vec3 vLocalPos;
Expand Down
20 changes: 16 additions & 4 deletions webrender/res/ps_image.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,28 @@ void main(void) {

write_clip(vi.screen_pos, prim.clip_area);

vTileSpacing = image.stretch_size_and_tile_spacing.zw;
vStretchSize = image.stretch_size_and_tile_spacing.xy;

// If this is in WR_FEATURE_TEXTURE_RECT mode, the rect and size use
// non-normalized texture coordinates.
#ifdef WR_FEATURE_TEXTURE_RECT
vec2 texture_size_normalization_factor = vec2(1, 1);
#else
vec2 texture_size_normalization_factor = vec2(textureSize(sColor0, 0));
#endif

// vUv will contain how many times this image has wrapped around the image size.
vec2 texture_size = vec2(textureSize(sColor0, 0));
vec2 st0 = res.uv_rect.xy / texture_size;
vec2 st1 = res.uv_rect.zw / texture_size;
vec2 st0 = res.uv_rect.xy / texture_size_normalization_factor;
vec2 st1 = res.uv_rect.zw / texture_size_normalization_factor;

vTextureSize = st1 - st0;
vTextureOffset = st0;
vTileSpacing = image.stretch_size_and_tile_spacing.zw;
vStretchSize = image.stretch_size_and_tile_spacing.xy;

vec2 half_texel = vec2(0.5) / texture_size;
// We clamp the texture coordinates to the half-pixel offset from the borders
// in order to avoid sampling outside of the texture area.
vec2 half_texel = vec2(0.5) / texture_size_normalization_factor;
vStRect = vec4(min(st0, st1) + half_texel, max(st0, st1) - half_texel);
}
6 changes: 6 additions & 0 deletions webrender/res/shared.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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 sDither;
uniform sampler2D sMask;

Expand Down
22 changes: 14 additions & 8 deletions webrender/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ pub enum DepthFunction {
pub enum TextureTarget {
Default,
Array,
Rect,
}

impl TextureTarget {
pub fn to_gl_target(&self) -> gl::GLuint {
match *self {
TextureTarget::Default => gl::TEXTURE_2D,
TextureTarget::Array => gl::TEXTURE_2D_ARRAY,
TextureTarget::Rect => gl::TEXTURE_RECTANGLE,
}
}
}

#[derive(Copy, Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -304,10 +315,10 @@ impl TextureId {
gl.bind_texture(self.target, self.name);
}

pub fn new(name: gl::GLuint) -> TextureId {
pub fn new(name: gl::GLuint, texture_target: TextureTarget) -> TextureId {
TextureId {
name: name,
target: gl::TEXTURE_2D,
target: texture_target.to_gl_target(),
}
}

Expand Down Expand Up @@ -1090,15 +1101,10 @@ impl Device {
let id_list = self.gl.gen_textures(count);
let mut texture_ids = Vec::new();

let target = match target {
TextureTarget::Default => gl::TEXTURE_2D,
TextureTarget::Array => gl::TEXTURE_2D_ARRAY,
};

for id in id_list {
let texture_id = TextureId {
name: id,
target: target,
target: target.to_gl_target(),
};

let texture = Texture {
Expand Down
4 changes: 2 additions & 2 deletions webrender/src/internal_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use tiling;
use renderer::BlendMode;
use webrender_traits::{Epoch, ColorF, PipelineId};
use webrender_traits::{ImageFormat, NativeFontHandle};
use webrender_traits::{ExternalImageId, ScrollLayerId};
use webrender_traits::{ExternalImageData, ExternalImageId, ScrollLayerId};
use webrender_traits::{ImageData};
use webrender_traits::{DeviceUintRect};

Expand All @@ -43,7 +43,7 @@ pub struct CacheTextureId(pub usize);
pub enum SourceTexture {
Invalid,
TextureCache(CacheTextureId),
External(ExternalImageId),
External(ExternalImageData),
#[cfg_attr(not(feature = "webgl"), allow(dead_code))]
/// This is actually a gl::GLuint, with the shared texture id between the
/// main context and the WebGL context.
Expand Down
6 changes: 3 additions & 3 deletions webrender/src/prim_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,8 @@ impl PrimitiveStore {

// Check if an external image that needs to be resolved
// by the render thread.
match image_properties.external_id {
Some(external_id) => {
match image_properties.external_image {
Some(external_image) => {
// This is an external texture - we will add it to
// the deferred resolves list to be patched by
// the render thread...
Expand All @@ -878,7 +878,7 @@ impl PrimitiveStore {
resource_address: image_uv_address,
});

(SourceTexture::External(external_id), None)
(SourceTexture::External(external_image), None)
}
None => {
let cache_item = resource_cache.get_cached_image(image_key, image_rendering, tile_offset);
Expand Down
82 changes: 56 additions & 26 deletions webrender/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use thread_profiler::{register_thread_with_profiler, write_profile};
use util::TransformedRectKind;
use webgl_types::GLContextHandleWrapper;
use webrender_traits::{ColorF, Epoch, PipelineId, RenderNotifier, RenderDispatcher};
use webrender_traits::{ExternalImageId, ImageData, ImageFormat, RenderApiSender};
use webrender_traits::{ExternalImageId, ExternalImageType, ImageData, ImageFormat, RenderApiSender};
use webrender_traits::{DeviceIntRect, DevicePoint, DeviceIntPoint, DeviceIntSize, DeviceUintSize};
use webrender_traits::{ImageDescriptor, BlobImageRenderer};
use webrender_traits::channel;
Expand All @@ -65,6 +65,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 };
Expand Down Expand Up @@ -223,6 +224,7 @@ pub type GradientDataStore = GpuStore<GradientData, GradientDataTextureLayout>;
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,
Expand Down Expand Up @@ -465,6 +467,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,
Expand Down Expand Up @@ -670,6 +673,13 @@ impl Renderer {
options.precache_shaders)
};

let ps_image_rect = try!{
PrimitiveShader::new("ps_image",
&mut device,
&[ TEXTURE_RECT_FEATURE ],
options.precache_shaders)
};

let ps_yuv_image = try!{
PrimitiveShader::new("ps_yuv_image",
&mut device,
Expand Down Expand Up @@ -912,6 +922,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,
Expand Down Expand Up @@ -1039,10 +1050,10 @@ impl Renderer {
fn resolve_source_texture(&mut self, texture_id: &SourceTexture) -> TextureId {
match *texture_id {
SourceTexture::Invalid => TextureId::invalid(),
SourceTexture::WebGL(id) => TextureId::new(id),
SourceTexture::External(ref key) => {
SourceTexture::WebGL(id) => TextureId::new(id, TextureTarget::Default),
SourceTexture::External(external_image) => {
*self.external_images
.get(key)
.get(&external_image.id)
.expect("BUG: External image should be resolved by now!")
}
SourceTexture::TextureCache(index) => {
Expand Down Expand Up @@ -1193,24 +1204,31 @@ impl Renderer {
mode,
Some(raw.as_slice()));
}
ImageData::ExternalBuffer(id) => {
let handler = self.external_image_handler
.as_mut()
.expect("Found external image, but no handler set!");

match handler.lock(id).source {
ExternalImageSource::RawData(raw) => {
self.device.init_texture(texture_id,
width,
height,
format,
filter,
mode,
Some(raw));
ImageData::External(ext_image) => {
match ext_image.image_type {
ExternalImageType::ExternalBuffer => {
let handler = self.external_image_handler
.as_mut()
.expect("Found external image, but no handler set!");

match handler.lock(ext_image.id).source {
ExternalImageSource::RawData(raw) => {
self.device.init_texture(texture_id,
width,
height,
format,
filter,
mode,
Some(raw));
}
_ => panic!("No external buffer found"),
};
handler.unlock(ext_image.id);
}
_ => panic!("No external buffer found"),
};
handler.unlock(id);
_ => {
panic!("External texture handle should not use TextureUpdateOp::Create.");
}
}
}
_ => {
panic!("No suitable image buffer for TextureUpdateOp::Create.");
Expand Down Expand Up @@ -1339,6 +1357,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)
Expand Down Expand Up @@ -1665,16 +1687,24 @@ impl Renderer {
for deferred_resolve in &frame.deferred_resolves {
GpuMarker::fire(self.device.gl(), "deferred resolve");
let props = &deferred_resolve.image_properties;
let external_id = props.external_id
.expect("BUG: Deferred resolves must be external images!");
let image = handler.lock(external_id);
let ext_image = props.external_image
.expect("BUG: Deferred resolves must be external images!");
let image = handler.lock(ext_image.id);
let texture_target = match ext_image.image_type {
ExternalImageType::Texture2DHandle => TextureTarget::Default,
ExternalImageType::TextureRectHandle => TextureTarget::Rect,
_ => {
panic!("{:?} is not a suitable image type in update_deferred_resolves().",
ext_image.image_type);
}
};

let texture_id = match image.source {
ExternalImageSource::NativeTexture(texture_id) => TextureId::new(texture_id),
ExternalImageSource::NativeTexture(texture_id) => TextureId::new(texture_id, texture_target),
_ => panic!("No native texture found."),
};

self.external_images.insert(external_id, texture_id);
self.external_images.insert(ext_image.id, texture_id);
let resource_rect_index = deferred_resolve.resource_address.0 as usize;
let resource_rect = &mut frame.gpu_resource_rects[resource_rect_index];
resource_rect.uv0 = DevicePoint::new(image.u0, image.v0);
Expand Down
Loading

0 comments on commit 9800670

Please sign in to comment.