Skip to content

Commit 3e36377

Browse files
author
bors-servo
authored
Auto merge of #636 - JerryShih:handle-external-image-life-time, r=glennw
Handle external image life time in api.delete_image() call Currently, the delete_image() call just removes the image_key in the hash_map. If the key is associate to an external image, we should release that image using the ExternalImageHandler callbacks. Since the ExternalImageHandler callbacks are only used in renderer, a pending releasing array is used. Then, pass this array to the renderer for ExternalImageHandler::release() call. @nical @glennw <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/636) <!-- Reviewable:end -->
2 parents 41a481d + ba33b43 commit 3e36377

File tree

4 files changed

+71
-21
lines changed

4 files changed

+71
-21
lines changed

webrender/src/internal_types.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ pub enum TextureUpdateOp {
347347
Grow(u32, u32, ImageFormat, TextureFilter, RenderTargetMode),
348348
}
349349

350+
pub type ExternalImageUpdateList = Vec<ExternalImageId>;
351+
350352
pub struct TextureUpdate {
351353
pub id: CacheTextureId,
352354
pub op: TextureUpdateOp,
@@ -395,9 +397,8 @@ impl RendererFrame {
395397
}
396398

397399
pub enum ResultMsg {
398-
UpdateTextureCache(TextureUpdateList),
399400
RefreshShader(PathBuf),
400-
NewFrame(RendererFrame, BackendProfileCounters),
401+
NewFrame(RendererFrame, TextureUpdateList, ExternalImageUpdateList, BackendProfileCounters),
401402
}
402403

403404
#[repr(u32)]

webrender/src/render_backend.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -431,18 +431,15 @@ impl RenderBackend {
431431
&self.scene.pipeline_auxiliary_lists,
432432
self.device_pixel_ratio);
433433

434-
let pending_update = self.resource_cache.pending_updates();
435-
if !pending_update.updates.is_empty() {
436-
self.result_tx.send(ResultMsg::UpdateTextureCache(pending_update)).unwrap();
437-
}
438-
439434
frame
440435
}
441436

442437
fn publish_frame(&mut self,
443438
frame: RendererFrame,
444439
profile_counters: &mut BackendProfileCounters) {
445-
let msg = ResultMsg::NewFrame(frame, profile_counters.clone());
440+
let pending_update = self.resource_cache.pending_updates();
441+
let pending_external_image_update = self.resource_cache.pending_external_image_updates();
442+
let msg = ResultMsg::NewFrame(frame, pending_update, pending_external_image_update, profile_counters.clone());
446443
self.result_tx.send(msg).unwrap();
447444
profile_counters.reset();
448445
}

webrender/src/renderer.rs

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use device::{TextureFilter, VAOId, VertexUsageHint, FileWatcherHandler, TextureT
1616
use euclid::Matrix4D;
1717
use fnv::FnvHasher;
1818
use internal_types::{CacheTextureId, RendererFrame, ResultMsg, TextureUpdateOp};
19-
use internal_types::{TextureUpdateList, PackedVertex, RenderTargetMode};
19+
use internal_types::{ExternalImageUpdateList, TextureUpdateList, PackedVertex, RenderTargetMode};
2020
use internal_types::{ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE, SourceTexture};
2121
use internal_types::{BatchTextures, TextureSampler, GLContextHandleWrapper};
2222
use profiler::{Profiler, BackendProfileCounters};
@@ -710,10 +710,12 @@ impl Renderer {
710710
// Pull any pending results and return the most recent.
711711
while let Ok(msg) = self.result_rx.try_recv() {
712712
match msg {
713-
ResultMsg::UpdateTextureCache(update_list) => {
714-
self.pending_texture_updates.push(update_list);
715-
}
716-
ResultMsg::NewFrame(frame, profile_counters) => {
713+
ResultMsg::NewFrame(frame, texture_update_list, external_image_update_list, profile_counters) => {
714+
self.pending_texture_updates.push(texture_update_list);
715+
716+
// When a new frame is ready, we could start to update all pending external image requests here.
717+
self.release_external_images(external_image_update_list);
718+
717719
self.backend_profile_counters = profile_counters;
718720

719721
// Update the list of available epochs for use during reftests.
@@ -1262,7 +1264,7 @@ impl Renderer {
12621264
let props = &deferred_resolve.image_properties;
12631265
let external_id = props.external_id
12641266
.expect("BUG: Deferred resolves must be external images!");
1265-
let image = handler.get(external_id);
1267+
let image = handler.lock(external_id);
12661268

12671269
let texture_id = match image.source {
12681270
ExternalImageSource::NativeTexture(texture_id) => TextureId::new(texture_id),
@@ -1277,13 +1279,25 @@ impl Renderer {
12771279
}
12781280
}
12791281

1280-
fn release_external_textures(&mut self) {
1282+
fn unlock_external_images(&mut self) {
12811283
if !self.external_images.is_empty() {
12821284
let handler = self.external_image_handler
12831285
.as_mut()
12841286
.expect("Found external image, but no handler set!");
12851287

12861288
for (external_id, _) in self.external_images.drain() {
1289+
handler.unlock(external_id);
1290+
}
1291+
}
1292+
}
1293+
1294+
fn release_external_images(&mut self, mut pending_external_image_updates: ExternalImageUpdateList) {
1295+
if !pending_external_image_updates.is_empty() {
1296+
let handler = self.external_image_handler
1297+
.as_mut()
1298+
.expect("found external image updates, but no handler set!");
1299+
1300+
for external_id in pending_external_image_updates.drain(..) {
12871301
handler.release(external_id);
12881302
}
12891303
}
@@ -1388,7 +1402,7 @@ impl Renderer {
13881402
}
13891403
}
13901404

1391-
self.release_external_textures();
1405+
self.unlock_external_images();
13921406
}
13931407

13941408
pub fn debug_renderer<'a>(&'a mut self) -> &'a mut DebugRenderer {
@@ -1427,10 +1441,19 @@ pub struct ExternalImage {
14271441
pub source: ExternalImageSource,
14281442
}
14291443

1430-
/// Interface that an application can implement
1431-
/// to support providing external image buffers.
1444+
/// The interfaces that an application can implement to support providing
1445+
/// external image buffers.
1446+
/// When the the application passes an external image to WR, it should kepp that
1447+
/// external image life time untile the release() call.
14321448
pub trait ExternalImageHandler {
1433-
fn get(&mut self, key: ExternalImageId) -> ExternalImage;
1449+
/// Lock the external image. Then, WR could start to read the image content.
1450+
/// The WR client should not change the image content until the unlock()
1451+
/// call.
1452+
fn lock(&mut self, key: ExternalImageId) -> ExternalImage;
1453+
/// Unlock the external image. The WR should not read the image content
1454+
/// after this call.
1455+
fn unlock(&mut self, key: ExternalImageId);
1456+
/// Tell the WR client that it could start to release this external image.
14341457
fn release(&mut self, key: ExternalImageId);
14351458
}
14361459

webrender/src/resource_cache.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ use app_units::Au;
66
use device::TextureFilter;
77
use fnv::FnvHasher;
88
use frame::FrameId;
9-
use internal_types::{FontTemplate, SourceTexture, TextureUpdateList};
9+
use internal_types::{ExternalImageUpdateList, FontTemplate, SourceTexture, TextureUpdateList};
1010
use platform::font::{FontContext, RasterizedGlyph};
1111
use std::cell::RefCell;
1212
use std::collections::{HashMap, HashSet};
1313
use std::collections::hash_map::Entry::{self, Occupied, Vacant};
1414
use std::fmt::Debug;
1515
use std::hash::BuildHasherDefault;
1616
use std::hash::Hash;
17+
use std::mem;
1718
use std::sync::{Arc, Barrier};
1819
use std::sync::mpsc::{channel, Receiver, Sender};
1920
use std::thread;
@@ -207,6 +208,7 @@ pub struct ResourceCache {
207208
pending_image_requests: Vec<ImageRequest>,
208209
glyph_cache_tx: Sender<GlyphCacheMsg>,
209210
glyph_cache_result_queue: Receiver<GlyphCacheResultMsg>,
211+
pending_external_image_update_list: ExternalImageUpdateList,
210212
}
211213

212214
impl ResourceCache {
@@ -228,6 +230,7 @@ impl ResourceCache {
228230
pending_image_requests: Vec::new(),
229231
glyph_cache_tx: glyph_cache_tx,
230232
glyph_cache_result_queue: glyph_cache_result_queue,
233+
pending_external_image_update_list: ExternalImageUpdateList::new(),
231234
}
232235
}
233236

@@ -272,6 +275,14 @@ impl ResourceCache {
272275
bytes: Vec<u8>) {
273276
let next_epoch = match self.image_templates.get(&image_key) {
274277
Some(image) => {
278+
// This image should not be an external image.
279+
match image.data {
280+
ImageData::External(id) => {
281+
panic!("Update an external image with buffer, id={} image_key={:?}", id.0, image_key);
282+
},
283+
_ => {},
284+
}
285+
275286
let Epoch(current_epoch) = image.epoch;
276287
Epoch(current_epoch + 1)
277288
}
@@ -294,7 +305,21 @@ impl ResourceCache {
294305
}
295306

296307
pub fn delete_image_template(&mut self, image_key: ImageKey) {
297-
self.image_templates.remove(&image_key);
308+
let value = self.image_templates.remove(&image_key);
309+
310+
// If the key is associated to an external image, pass the external id to renderer for cleanup.
311+
if let Some(image) = value {
312+
match image.data {
313+
ImageData::External(id) => {
314+
self.pending_external_image_update_list.push(id);
315+
},
316+
_ => {},
317+
}
318+
319+
return;
320+
}
321+
322+
println!("Delete the non-exist key:{:?}", image_key);
298323
}
299324

300325
pub fn add_webgl_texture(&mut self, id: WebGLContextId, texture_id: SourceTexture, size: DeviceIntSize) {
@@ -343,6 +368,10 @@ impl ResourceCache {
343368
self.texture_cache.pending_updates()
344369
}
345370

371+
pub fn pending_external_image_updates(&mut self) -> ExternalImageUpdateList {
372+
mem::replace(&mut self.pending_external_image_update_list, ExternalImageUpdateList::new())
373+
}
374+
346375
pub fn get_glyphs<F>(&self,
347376
font_key: FontKey,
348377
size: Au,

0 commit comments

Comments
 (0)