diff options
Diffstat (limited to 'gfx/wr/examples/yuv.rs')
-rw-r--r-- | gfx/wr/examples/yuv.rs | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/gfx/wr/examples/yuv.rs b/gfx/wr/examples/yuv.rs new file mode 100644 index 0000000000..eacd97daa9 --- /dev/null +++ b/gfx/wr/examples/yuv.rs @@ -0,0 +1,225 @@ +/* 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/. */ + +extern crate gleam; +extern crate glutin; +extern crate webrender; +extern crate winit; + +#[path = "common/boilerplate.rs"] +mod boilerplate; + +use crate::boilerplate::Example; +use gleam::gl; +use webrender::api::*; +use webrender::render_api::*; +use webrender::api::units::*; + + +fn init_gl_texture( + id: gl::GLuint, + internal: gl::GLenum, + external: gl::GLenum, + bytes: &[u8], + gl: &dyn gl::Gl, +) { + gl.bind_texture(gl::TEXTURE_2D, id); + gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as gl::GLint); + gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as gl::GLint); + gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as gl::GLint); + gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as gl::GLint); + gl.tex_image_2d( + gl::TEXTURE_2D, + 0, + internal as gl::GLint, + 100, + 100, + 0, + external, + gl::UNSIGNED_BYTE, + Some(bytes), + ); + gl.bind_texture(gl::TEXTURE_2D, 0); +} + +struct YuvImageProvider { + texture_ids: Vec<gl::GLuint>, +} + +impl YuvImageProvider { + fn new(gl: &dyn gl::Gl) -> Self { + let texture_ids = gl.gen_textures(4); + + init_gl_texture(texture_ids[0], gl::RED, gl::RED, &[127; 100 * 100], gl); + init_gl_texture(texture_ids[1], gl::RG8, gl::RG, &[0; 100 * 100 * 2], gl); + init_gl_texture(texture_ids[2], gl::RED, gl::RED, &[127; 100 * 100], gl); + init_gl_texture(texture_ids[3], gl::RED, gl::RED, &[127; 100 * 100], gl); + + YuvImageProvider { + texture_ids + } + } +} + +impl ExternalImageHandler for YuvImageProvider { + fn lock( + &mut self, + key: ExternalImageId, + _channel_index: u8, + _rendering: ImageRendering + ) -> ExternalImage { + let id = self.texture_ids[key.0 as usize]; + ExternalImage { + uv: TexelRect::new(0.0, 0.0, 1.0, 1.0), + source: ExternalImageSource::NativeTexture(id), + } + } + fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) { + } +} + +struct App { + texture_id: gl::GLuint, + current_value: u8, +} + +impl Example for App { + fn render( + &mut self, + api: &mut RenderApi, + builder: &mut DisplayListBuilder, + txn: &mut Transaction, + _device_size: DeviceIntSize, + pipeline_id: PipelineId, + _document_id: DocumentId, + ) { + let bounds = LayoutRect::new(LayoutPoint::zero(), LayoutSize::new(500.0, 500.0)); + let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id); + + builder.push_simple_stacking_context( + bounds.origin, + space_and_clip.spatial_id, + PrimitiveFlags::IS_BACKFACE_VISIBLE, + ); + + let yuv_chanel1 = api.generate_image_key(); + let yuv_chanel2 = api.generate_image_key(); + let yuv_chanel2_1 = api.generate_image_key(); + let yuv_chanel3 = api.generate_image_key(); + txn.add_image( + yuv_chanel1, + ImageDescriptor::new(100, 100, ImageFormat::R8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::External(ExternalImageData { + id: ExternalImageId(0), + channel_index: 0, + image_type: ExternalImageType::TextureHandle( + ImageBufferKind::Texture2D, + ), + }), + None, + ); + txn.add_image( + yuv_chanel2, + ImageDescriptor::new(100, 100, ImageFormat::RG8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::External(ExternalImageData { + id: ExternalImageId(1), + channel_index: 0, + image_type: ExternalImageType::TextureHandle( + ImageBufferKind::Texture2D, + ), + }), + None, + ); + txn.add_image( + yuv_chanel2_1, + ImageDescriptor::new(100, 100, ImageFormat::R8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::External(ExternalImageData { + id: ExternalImageId(2), + channel_index: 0, + image_type: ExternalImageType::TextureHandle( + ImageBufferKind::Texture2D, + ), + }), + None, + ); + txn.add_image( + yuv_chanel3, + ImageDescriptor::new(100, 100, ImageFormat::R8, ImageDescriptorFlags::IS_OPAQUE), + ImageData::External(ExternalImageData { + id: ExternalImageId(3), + channel_index: 0, + image_type: ExternalImageType::TextureHandle( + ImageBufferKind::Texture2D, + ), + }), + None, + ); + + let info = CommonItemProperties::new( + LayoutRect::new(LayoutPoint::new(100.0, 0.0), LayoutSize::new(100.0, 100.0)), + space_and_clip, + ); + builder.push_yuv_image( + &info, + bounds, + YuvData::NV12(yuv_chanel1, yuv_chanel2), + ColorDepth::Color8, + YuvColorSpace::Rec601, + ColorRange::Limited, + ImageRendering::Auto, + ); + + let info = CommonItemProperties::new( + LayoutRect::new(LayoutPoint::new(300.0, 0.0), LayoutSize::new(100.0, 100.0)), + space_and_clip, + ); + builder.push_yuv_image( + &info, + bounds, + YuvData::PlanarYCbCr(yuv_chanel1, yuv_chanel2_1, yuv_chanel3), + ColorDepth::Color8, + YuvColorSpace::Rec601, + ColorRange::Limited, + ImageRendering::Auto, + ); + + builder.pop_stacking_context(); + } + + fn on_event( + &mut self, + _event: winit::WindowEvent, + _api: &mut RenderApi, + _document_id: DocumentId, + ) -> bool { + false + } + + fn get_image_handler( + &mut self, + gl: &dyn gl::Gl, + ) -> Option<Box<dyn ExternalImageHandler>> { + let provider = YuvImageProvider::new(gl); + self.texture_id = provider.texture_ids[0]; + Some(Box::new(provider)) + } + + fn draw_custom(&mut self, gl: &dyn gl::Gl) { + init_gl_texture(self.texture_id, gl::RED, gl::RED, &[self.current_value; 100 * 100], gl); + self.current_value = self.current_value.wrapping_add(1); + } +} + +fn main() { + let mut app = App { + texture_id: 0, + current_value: 0, + }; + + let opts = webrender::RendererOptions { + ..Default::default() + }; + + boilerplate::main_wrapper(&mut app, Some(opts)); +} |