Skip to content

Commit 307553d

Browse files
committed
Add an API for providing external images.
This allows applications to provide images without supplying the image bytes up front. This can be useful if the application doesn't have the bytes available immediately (e.g. video decoding) or wants to manage the buffer allocation and reduce memory copies.
1 parent 916f46e commit 307553d

16 files changed

+474
-144
lines changed

sample/src/main.rs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use euclid::{Size2D, Point2D, Rect, Matrix4D};
88
use gleam::gl;
99
use std::path::PathBuf;
1010
use std::ffi::CStr;
11-
use webrender_traits::{AuxiliaryListsBuilder, ColorF, Epoch, GlyphInstance};
12-
use webrender_traits::{ImageFormat, PipelineId, RendererKind};
11+
use webrender::{ExternalImage, ExternalImageHandler};
12+
use webrender_traits::{AuxiliaryListsBuilder, ColorF, Epoch, GlyphInstance, ExternalImageId};
13+
use webrender_traits::{ImageData, ImageFormat, PipelineId, RendererKind, ImageRendering};
1314
use std::fs::File;
1415
use std::io::Read;
1516
use std::env;
@@ -53,6 +54,49 @@ impl webrender_traits::RenderNotifier for Notifier {
5354
}
5455
}
5556

57+
struct ImageHandler {
58+
data: Vec<u8>,
59+
frame: u64,
60+
}
61+
62+
impl ImageHandler {
63+
fn new() -> ImageHandler {
64+
ImageHandler {
65+
frame: 0,
66+
data: vec![ 0xff, 0x00, 0x00, 0xff,
67+
0x00, 0xff, 0x00, 0xff,
68+
0x00, 0x00, 0xff, 0xff,
69+
0x00, 0xff, 0xff, 0xff ],
70+
}
71+
}
72+
}
73+
74+
impl ExternalImageHandler for ImageHandler {
75+
fn lock_image(&mut self, _: ExternalImageId) -> ExternalImage {
76+
self.frame += 1;
77+
78+
if self.frame == 10 {
79+
self.data = vec![ 0x00, 0x00, 0x00, 0xff,
80+
0xff, 0xff, 0xff, 0xff,
81+
0xff, 0xff, 0xff, 0xff,
82+
0x00, 0x00, 0x00, 0xff ];
83+
}
84+
85+
ExternalImage {
86+
timestamp: self.frame,
87+
u0: 0.0,
88+
v0: 0.0,
89+
u1: 2.0,
90+
v1: 2.0,
91+
data: self.data.as_ptr(),
92+
len: self.data.len(),
93+
}
94+
}
95+
96+
fn unlock_image(&mut self, _: ExternalImageId) {
97+
}
98+
}
99+
56100
fn main() {
57101
let args: Vec<String> = env::args().collect();
58102
if args.len() != 2 {
@@ -106,6 +150,7 @@ fn main() {
106150

107151
let notifier = Box::new(Notifier::new(window.create_window_proxy()));
108152
renderer.set_render_notifier(notifier);
153+
renderer.set_external_image_handler(Box::new(ImageHandler::new()));
109154

110155
let pipeline_id = PipelineId(0, 0);
111156
let epoch = Epoch(0);
@@ -135,7 +180,7 @@ fn main() {
135180
let clip_region = {
136181
let rect = Rect::new(Point2D::new(100.0, 100.0), Size2D::new(100.0, 100.0));
137182
let mask = webrender_traits::ImageMask {
138-
image: api.add_image(2, 2, None, ImageFormat::A8, vec![0,80, 180, 255]),
183+
image: api.add_image(2, 2, None, ImageFormat::A8, ImageData::Raw(vec![0,80, 180, 255])),
139184
rect: rect,
140185
repeat: false,
141186
};
@@ -154,6 +199,22 @@ fn main() {
154199

155200
let _text_bounds = Rect::new(Point2D::new(100.0, 200.0), Size2D::new(700.0, 300.0));
156201

202+
let ext_id = ExternalImageId(0);
203+
let image_key = api.add_image(2, 2, None, ImageFormat::RGBA8, ImageData::External(ext_id));
204+
205+
let ext_image_rect = Rect::new(Point2D::new(300.0, 100.0), Size2D::new(100.0, 100.0));
206+
let ext_image_clip_region = webrender_traits::ClipRegion::new(&ext_image_rect,
207+
vec![],
208+
None,
209+
&mut auxiliary_lists_builder);
210+
211+
builder.push_image(ext_image_rect,
212+
ext_image_clip_region,
213+
Size2D::new(100.0, 100.0),
214+
Size2D::zero(),
215+
ImageRendering::Auto,
216+
image_key);
217+
157218
let _glyphs = vec![
158219
GlyphInstance {
159220
index: 48,

webrender/res/cs_text_run.vs.glsl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ void main(void) {
1313
TextRun text = fetch_text_run(cpi.specific_prim_index);
1414
Glyph glyph = fetch_glyph(cpi.sub_index);
1515
PrimitiveGeometry pg = fetch_prim_geometry(cpi.global_prim_index);
16+
ResourceRect res = fetch_resource_rect(cpi.user_data.x);
1617

1718
// Glyphs size is already in device-pixels.
1819
// The render task origin is in device-pixels. Offset that by
1920
// the glyph offset, relative to its primitive bounding rect.
20-
vec2 size = glyph.uv_rect.zw - glyph.uv_rect.xy;
21+
vec2 size = res.uv_rect.zw - res.uv_rect.xy;
2122
vec2 origin = task.data0.xy + uDevicePixelRatio * (glyph.offset.xy - pg.local_rect.xy);
2223
vec4 local_rect = vec4(origin, size);
2324

2425
vec2 texture_size = vec2(textureSize(sColor0, 0));
25-
vec2 st0 = glyph.uv_rect.xy / texture_size;
26-
vec2 st1 = glyph.uv_rect.zw / texture_size;
26+
vec2 st0 = res.uv_rect.xy / texture_size;
27+
vec2 st1 = res.uv_rect.zw / texture_size;
2728

2829
vec2 pos = mix(local_rect.xy,
2930
local_rect.xy + local_rect.zw,

webrender/res/prim_shared.glsl

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ uniform sampler2D sData16;
5555
uniform sampler2D sData32;
5656
uniform sampler2D sData64;
5757
uniform sampler2D sData128;
58+
uniform sampler2D sResourceRects;
5859

5960
ivec2 get_fetch_uv(int index, int vecs_per_item) {
6061
int items_per_row = WR_MAX_VERTEX_TEXTURE_WIDTH / vecs_per_item;
@@ -186,16 +187,14 @@ GradientStop fetch_gradient_stop(int index) {
186187

187188
struct Glyph {
188189
vec4 offset;
189-
vec4 uv_rect;
190190
};
191191

192192
Glyph fetch_glyph(int index) {
193193
Glyph glyph;
194194

195-
ivec2 uv = get_fetch_uv_2(index);
195+
ivec2 uv = get_fetch_uv_1(index);
196196

197-
glyph.offset = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
198-
glyph.uv_rect = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));
197+
glyph.offset = texelFetchOffset(sData16, uv, 0, ivec2(0, 0));
199198

200199
return glyph;
201200
}
@@ -302,19 +301,22 @@ struct CachePrimitiveInstance {
302301
int specific_prim_index;
303302
int render_task_index;
304303
int sub_index;
304+
ivec4 user_data;
305305
};
306306

307307
CachePrimitiveInstance fetch_cache_instance(int index) {
308308
CachePrimitiveInstance cpi;
309309

310-
int offset = index * 1;
310+
int offset = index * 2;
311311

312312
ivec4 data0 = int_data[offset + 0];
313+
ivec4 data1 = int_data[offset + 1];
313314

314315
cpi.global_prim_index = data0.x;
315316
cpi.specific_prim_index = data0.y;
316317
cpi.render_task_index = data0.z;
317318
cpi.sub_index = data0.w;
319+
cpi.user_data = data1;
318320

319321
return cpi;
320322
}
@@ -584,6 +586,20 @@ TransformVertexInfo write_transform_vertex(vec4 instance_rect,
584586

585587
#endif //WR_FEATURE_TRANSFORM
586588

589+
struct ResourceRect {
590+
vec4 uv_rect;
591+
};
592+
593+
ResourceRect fetch_resource_rect(int index) {
594+
ResourceRect rect;
595+
596+
ivec2 uv = get_fetch_uv_1(index);
597+
598+
rect.uv_rect = texelFetchOffset(sResourceRects, uv, 0, ivec2(0, 0));
599+
600+
return rect;
601+
}
602+
587603
struct Rectangle {
588604
vec4 color;
589605
};
@@ -613,18 +629,16 @@ TextRun fetch_text_run(int index) {
613629
}
614630

615631
struct Image {
616-
vec4 st_rect; // Location of the image texture in the texture atlas.
617632
vec4 stretch_size_and_tile_spacing; // Size of the actual image and amount of space between
618633
// tiled instances of this image.
619634
};
620635

621636
Image fetch_image(int index) {
622637
Image image;
623638

624-
ivec2 uv = get_fetch_uv_2(index);
639+
ivec2 uv = get_fetch_uv_1(index);
625640

626-
image.st_rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
627-
image.stretch_size_and_tile_spacing = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));
641+
image.stretch_size_and_tile_spacing = texelFetchOffset(sData16, uv, 0, ivec2(0, 0));
628642

629643
return image;
630644
}

webrender/res/ps_image.vs.glsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
void main(void) {
77
Primitive prim = load_primitive(gl_InstanceID);
88
Image image = fetch_image(prim.prim_index);
9+
ResourceRect res = fetch_resource_rect(prim.user_data.x);
910

1011
#ifdef WR_FEATURE_TRANSFORM
1112
TransformVertexInfo vi = write_transform_vertex(prim.local_rect,
@@ -24,8 +25,8 @@ void main(void) {
2425

2526
// vUv will contain how many times this image has wrapped around the image size.
2627
vec2 texture_size = vec2(textureSize(sColor0, 0));
27-
vec2 st0 = image.st_rect.xy / texture_size;
28-
vec2 st1 = image.st_rect.zw / texture_size;
28+
vec2 st0 = res.uv_rect.xy / texture_size;
29+
vec2 st1 = res.uv_rect.zw / texture_size;
2930

3031
vTextureSize = st1 - st0;
3132
vTextureOffset = st0;

webrender/res/ps_image_clip.vs.glsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
void main(void) {
77
Primitive prim = load_primitive(gl_InstanceID);
88
Image image = fetch_image(prim.prim_index);
9+
ResourceRect res = fetch_resource_rect(prim.user_data.x);
910

1011
#ifdef WR_FEATURE_TRANSFORM
1112
TransformVertexInfo vi = write_transform_vertex(prim.local_rect,
@@ -28,8 +29,8 @@ void main(void) {
2829

2930
// vUv will contain how many times this image has wrapped around the image size.
3031
vec2 texture_size = vec2(textureSize(sColor0, 0));
31-
vec2 st0 = image.st_rect.xy / texture_size;
32-
vec2 st1 = image.st_rect.zw / texture_size;
32+
vec2 st0 = res.uv_rect.xy / texture_size;
33+
vec2 st1 = res.uv_rect.zw / texture_size;
3334

3435
vTextureSize = st1 - st0;
3536
vTextureOffset = st0;

webrender/res/ps_text_run.vs.glsl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ void main(void) {
77
Primitive prim = load_primitive(gl_InstanceID);
88
TextRun text = fetch_text_run(prim.prim_index);
99
Glyph glyph = fetch_glyph(prim.sub_index);
10-
vec4 local_rect = vec4(glyph.offset.xy, (glyph.uv_rect.zw - glyph.uv_rect.xy) / uDevicePixelRatio);
10+
ResourceRect res = fetch_resource_rect(prim.user_data.x);
11+
12+
vec4 local_rect = vec4(glyph.offset.xy, (res.uv_rect.zw - res.uv_rect.xy) / uDevicePixelRatio);
1113

1214
#ifdef WR_FEATURE_TRANSFORM
1315
TransformVertexInfo vi = write_transform_vertex(local_rect,
@@ -26,8 +28,8 @@ void main(void) {
2628
#endif
2729

2830
vec2 texture_size = vec2(textureSize(sColor0, 0));
29-
vec2 st0 = glyph.uv_rect.xy / texture_size;
30-
vec2 st1 = glyph.uv_rect.zw / texture_size;
31+
vec2 st0 = res.uv_rect.xy / texture_size;
32+
vec2 st1 = res.uv_rect.zw / texture_size;
3133

3234
vColor = text.color;
3335
vUv = mix(st0, st1, f);

webrender/src/device.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,11 @@ impl Device {
13661366
if u_data128 != -1 {
13671367
gl::uniform_1i(u_data128, TextureSampler::Data128 as i32);
13681368
}
1369+
1370+
let u_resource_rects = gl::get_uniform_location(program.id, "sResourceRects");
1371+
if u_resource_rects != -1 {
1372+
gl::uniform_1i(u_resource_rects, TextureSampler::ResourceRects as i32);
1373+
}
13691374
}
13701375
}
13711376
}

webrender/src/internal_types.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::sync::Arc;
2020
use tiling;
2121
use webrender_traits::{Epoch, ColorF, PipelineId};
2222
use webrender_traits::{ImageFormat, MixBlendMode, NativeFontHandle};
23-
use webrender_traits::{ScrollLayerId, WebGLCommand};
23+
use webrender_traits::{ExternalImageId, ScrollLayerId, WebGLCommand};
2424

2525
// An ID for a texture that is owned by the
2626
// texture cache module. This can include atlases
@@ -45,9 +45,7 @@ pub enum SourceTexture {
4545
Invalid,
4646
TextureCache(CacheTextureId),
4747
WebGL(u32), // Is actually a gl::GLuint
48-
49-
// TODO(gw): Implement external image support via callback
50-
//External(i32),
48+
External(ExternalImageId),
5149
}
5250

5351
pub enum GLContextHandleWrapper {
@@ -203,6 +201,7 @@ pub enum TextureSampler {
203201
Layers,
204202
RenderTasks,
205203
Geometry,
204+
ResourceRects,
206205
}
207206

208207
impl TextureSampler {

webrender/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,5 @@ extern crate offscreen_gl_context;
120120
extern crate byteorder;
121121
extern crate rayon;
122122

123+
pub use renderer::{ExternalImage, ExternalImageHandler};
123124
pub use renderer::{Renderer, RendererOptions};

0 commit comments

Comments
 (0)