summaryrefslogtreecommitdiffstats
path: root/gfx/wr/examples/yuv.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/wr/examples/yuv.rs225
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..ecbf6f428a
--- /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,
+ ) -> 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::from_size(LayoutSize::new(500.0, 500.0));
+ let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
+
+ builder.push_simple_stacking_context(
+ bounds.min,
+ 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::from_origin_and_size(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::from_origin_and_size(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::event::WindowEvent,
+ _window: &winit::window::Window,
+ _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::WebRenderOptions {
+ ..Default::default()
+ };
+
+ boilerplate::main_wrapper(&mut app, Some(opts));
+}