Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GL_TEXTURE_RECTANGLE texture target support #997

Merged
merged 4 commits into from
Mar 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

macIOSurface should use sampler2DRect

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!{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add a new shader for textureRect. We could also merge this back to the original image shader. I don't like too much "#ifdef" in the code.

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