yuv.rs (7027B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 extern crate gleam; 6 extern crate glutin; 7 extern crate webrender; 8 extern crate winit; 9 10 #[path = "common/boilerplate.rs"] 11 mod boilerplate; 12 13 use crate::boilerplate::Example; 14 use gleam::gl; 15 use webrender::api::*; 16 use webrender::render_api::*; 17 use webrender::api::units::*; 18 19 20 fn init_gl_texture( 21 id: gl::GLuint, 22 internal: gl::GLenum, 23 external: gl::GLenum, 24 bytes: &[u8], 25 gl: &dyn gl::Gl, 26 ) { 27 gl.bind_texture(gl::TEXTURE_2D, id); 28 gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as gl::GLint); 29 gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as gl::GLint); 30 gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as gl::GLint); 31 gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as gl::GLint); 32 gl.tex_image_2d( 33 gl::TEXTURE_2D, 34 0, 35 internal as gl::GLint, 36 100, 37 100, 38 0, 39 external, 40 gl::UNSIGNED_BYTE, 41 Some(bytes), 42 ); 43 gl.bind_texture(gl::TEXTURE_2D, 0); 44 } 45 46 struct YuvImageProvider { 47 texture_ids: Vec<gl::GLuint>, 48 } 49 50 impl YuvImageProvider { 51 fn new(gl: &dyn gl::Gl) -> Self { 52 let texture_ids = gl.gen_textures(4); 53 54 init_gl_texture(texture_ids[0], gl::RED, gl::RED, &[127; 100 * 100], gl); 55 init_gl_texture(texture_ids[1], gl::RG8, gl::RG, &[0; 100 * 100 * 2], gl); 56 init_gl_texture(texture_ids[2], gl::RED, gl::RED, &[127; 100 * 100], gl); 57 init_gl_texture(texture_ids[3], gl::RED, gl::RED, &[127; 100 * 100], gl); 58 59 YuvImageProvider { 60 texture_ids 61 } 62 } 63 } 64 65 impl ExternalImageHandler for YuvImageProvider { 66 fn lock( 67 &mut self, 68 key: ExternalImageId, 69 _channel_index: u8, 70 _is_composited: bool, 71 ) -> ExternalImage<'_> { 72 let id = self.texture_ids[key.0 as usize]; 73 ExternalImage { 74 uv: TexelRect::new(0.0, 0.0, 1.0, 1.0), 75 source: ExternalImageSource::NativeTexture(id), 76 } 77 } 78 fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) { 79 } 80 } 81 82 struct App { 83 texture_id: gl::GLuint, 84 current_value: u8, 85 } 86 87 impl Example for App { 88 fn render( 89 &mut self, 90 api: &mut RenderApi, 91 builder: &mut DisplayListBuilder, 92 txn: &mut Transaction, 93 _device_size: DeviceIntSize, 94 pipeline_id: PipelineId, 95 _document_id: DocumentId, 96 ) { 97 let bounds = LayoutRect::from_size(LayoutSize::new(500.0, 500.0)); 98 let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id); 99 100 builder.push_simple_stacking_context( 101 bounds.min, 102 space_and_clip.spatial_id, 103 PrimitiveFlags::IS_BACKFACE_VISIBLE, 104 ); 105 106 let yuv_chanel1 = api.generate_image_key(); 107 let yuv_chanel2 = api.generate_image_key(); 108 let yuv_chanel2_1 = api.generate_image_key(); 109 let yuv_chanel3 = api.generate_image_key(); 110 txn.add_image( 111 yuv_chanel1, 112 ImageDescriptor::new(100, 100, ImageFormat::R8, ImageDescriptorFlags::IS_OPAQUE), 113 ImageData::External(ExternalImageData { 114 id: ExternalImageId(0), 115 channel_index: 0, 116 image_type: ExternalImageType::TextureHandle( 117 ImageBufferKind::Texture2D, 118 ), 119 normalized_uvs: false, 120 }), 121 None, 122 ); 123 txn.add_image( 124 yuv_chanel2, 125 ImageDescriptor::new(100, 100, ImageFormat::RG8, ImageDescriptorFlags::IS_OPAQUE), 126 ImageData::External(ExternalImageData { 127 id: ExternalImageId(1), 128 channel_index: 0, 129 image_type: ExternalImageType::TextureHandle( 130 ImageBufferKind::Texture2D, 131 ), 132 normalized_uvs: false, 133 }), 134 None, 135 ); 136 txn.add_image( 137 yuv_chanel2_1, 138 ImageDescriptor::new(100, 100, ImageFormat::R8, ImageDescriptorFlags::IS_OPAQUE), 139 ImageData::External(ExternalImageData { 140 id: ExternalImageId(2), 141 channel_index: 0, 142 image_type: ExternalImageType::TextureHandle( 143 ImageBufferKind::Texture2D, 144 ), 145 normalized_uvs: false, 146 }), 147 None, 148 ); 149 txn.add_image( 150 yuv_chanel3, 151 ImageDescriptor::new(100, 100, ImageFormat::R8, ImageDescriptorFlags::IS_OPAQUE), 152 ImageData::External(ExternalImageData { 153 id: ExternalImageId(3), 154 channel_index: 0, 155 image_type: ExternalImageType::TextureHandle( 156 ImageBufferKind::Texture2D, 157 ), 158 normalized_uvs: false, 159 }), 160 None, 161 ); 162 163 let info = CommonItemProperties::new( 164 LayoutRect::from_origin_and_size(LayoutPoint::new(100.0, 0.0), LayoutSize::new(100.0, 100.0)), 165 space_and_clip, 166 ); 167 builder.push_yuv_image( 168 &info, 169 bounds, 170 YuvData::NV12(yuv_chanel1, yuv_chanel2), 171 ColorDepth::Color8, 172 YuvColorSpace::Rec601, 173 ColorRange::Limited, 174 ImageRendering::Auto, 175 ); 176 177 let info = CommonItemProperties::new( 178 LayoutRect::from_origin_and_size(LayoutPoint::new(300.0, 0.0), LayoutSize::new(100.0, 100.0)), 179 space_and_clip, 180 ); 181 builder.push_yuv_image( 182 &info, 183 bounds, 184 YuvData::PlanarYCbCr(yuv_chanel1, yuv_chanel2_1, yuv_chanel3), 185 ColorDepth::Color8, 186 YuvColorSpace::Rec601, 187 ColorRange::Limited, 188 ImageRendering::Auto, 189 ); 190 191 builder.pop_stacking_context(); 192 } 193 194 fn on_event( 195 &mut self, 196 _event: winit::event::WindowEvent, 197 _window: &winit::window::Window, 198 _api: &mut RenderApi, 199 _document_id: DocumentId, 200 ) -> bool { 201 false 202 } 203 204 fn get_image_handler( 205 &mut self, 206 gl: &dyn gl::Gl, 207 ) -> Option<Box<dyn ExternalImageHandler>> { 208 let provider = YuvImageProvider::new(gl); 209 self.texture_id = provider.texture_ids[0]; 210 Some(Box::new(provider)) 211 } 212 213 fn draw_custom(&mut self, gl: &dyn gl::Gl) { 214 init_gl_texture(self.texture_id, gl::RED, gl::RED, &[self.current_value; 100 * 100], gl); 215 self.current_value = self.current_value.wrapping_add(1); 216 } 217 } 218 219 fn main() { 220 let mut app = App { 221 texture_id: 0, 222 current_value: 0, 223 }; 224 225 let opts = webrender::WebRenderOptions { 226 ..Default::default() 227 }; 228 229 boilerplate::main_wrapper(&mut app, Some(opts)); 230 }